Projectile speed replication

Discussions about Coding and Scripting
Post Reply
User avatar
Barbie
Godlike
Posts: 1727
Joined: Fri Sep 25, 2015 9:01 pm
Location: moved without proper hashing

Projectile speed replication

Post by Barbie » Sat Mar 23, 2019 9:34 pm

Short description: a given value in server's INI file should be transferred to clients.

Long description: For some reasons I want to change the speed of a projectile by an INI file located at the server. For example for the RocketLauncher: I subclassed the default projectile ("SBRocketMk2"), added a new variable "ProjectileSpeed" that should be replicated and assign the value of "ProjectileSpeed" to the variable "Speed" in PostBeginPlay():

Code: Select all

class SBRocketMk2 expands RocketMk2 config(SBRocketMk2);

var config float ProjectileSpeed;

replication {
	reliable if (Role == ROLE_Authority)
		ProjectileSpeed;
}

simulated function logger(string msg) {
	Log(msg);
	broadcastmessage(msg);
}


simulated function PostNetBeginPlay() {
	Logger(self $ ".PostNetBeginPlay: Speed=" $ Speed);
	super.PostNetBeginPlay();
}


simulated function PostBeginPlay() {
	Logger(self $ ".PostBeginPlay starting with SmokeRate=" $ SmokeRate $ ", ProjectileSpeed=" $ ProjectileSpeed  $ ", Speed=" $ Speed);
	Speed = ProjectileSpeed;
	Super.PostBeginPlay();
	logger(self $ ".PostBeginPlay finished with SmokeRate=" $ SmokeRate $ ", ProjectileSpeed=" $ ProjectileSpeed  $ ", Speed=" $ Speed);
}


defaultproperties {
	ProjectileSpeed=20
}
Because the new projectile has to be used, I subclassed the weapon also ("SBEightball") and set the ProjectileClass there. (Unfortunately the default ProjectileClass ("Class'RocketMk2'") is also used in the code, so I have to substitute it there.)
SBEightball
Show

Code: Select all

class SBEightball expands UT_Eightball;


state FireRockets {

	function BeginState() // complete copy of parent except line 87 where class'rocketmk2' is spawned
	{
		local vector FireLocation, StartLoc, X,Y,Z;
		local rotator FireRot, RandRot;
		local rocketmk2 r;
		local UT_SeekingRocket s;
		local ut_grenade g;
		local float Angle, RocketRad;
		local pawn BestTarget, PawnOwner;
		local PlayerPawn PlayerOwner;
		local int DupRockets;
		local bool bMultiRockets;

		PawnOwner = Pawn(Owner);
		if ( PawnOwner == None )
			return;
		PawnOwner.PlayRecoil(FiringSpeed);
		PlayerOwner = PlayerPawn(Owner);
		Angle = 0;
		DupRockets = RocketsLoaded - 1;
		if (DupRockets < 0) DupRockets = 0;
		if ( PlayerOwner == None )
			bTightWad = ( FRand() * 4 < PawnOwner.skill );

		GetAxes(PawnOwner.ViewRotation,X,Y,Z);
		StartLoc = Owner.Location + CalcDrawOffset() + FireOffset.X * X + FireOffset.Y * Y + FireOffset.Z * Z;

		if ( bFireLoad )
			AdjustedAim = PawnOwner.AdjustAim(ProjectileSpeed, StartLoc, AimError, True, bWarnTarget);
		else
			AdjustedAim = PawnOwner.AdjustToss(AltProjectileSpeed, StartLoc, AimError, True, bAltWarnTarget);

		if ( PlayerOwner != None )
			AdjustedAim = PawnOwner.ViewRotation;

		PlayRFiring(RocketsLoaded-1);
		Owner.MakeNoise(PawnOwner.SoundDampening);
		if ( !bFireLoad )
		{
			LockedTarget = None;
			bLockedOn = false;
		}
		else if ( LockedTarget != None )
		{
			BestTarget = Pawn(CheckTarget());
			if ( (LockedTarget!=None) && (LockedTarget != BestTarget) )
			{
				LockedTarget = None;
				bLockedOn=False;
			}
		}
		else
			BestTarget = None;
		bPendingLock = false;
		bPointing = true;
		FireRot = AdjustedAim;
		RocketRad = 4;
		if (bTightWad || !bFireLoad) RocketRad=7;
		bMultiRockets = ( RocketsLoaded > 1 );
		While ( RocketsLoaded > 0 )
		{
			if ( bMultiRockets )
				Firelocation = StartLoc - (Sin(Angle)*RocketRad - 7.5)*Y + (Cos(Angle)*RocketRad - 7)*Z - X * 4 * FRand();
			else
				FireLocation = StartLoc;
			if (bFireLoad)
			{
				if ( Angle > 0 )
				{
					if ( Angle < 3 && !bTightWad)
						FireRot.Yaw = AdjustedAim.Yaw - Angle * 600;
					else if ( Angle > 3.5 && !bTightWad)
						FireRot.Yaw = AdjustedAim.Yaw + (Angle - 3)  * 600;
					else
						FireRot.Yaw = AdjustedAim.Yaw;
				}
				if ( LockedTarget != None )
				{
					s = Spawn( class 'ut_SeekingRocket',, '', FireLocation,FireRot);
					s.Seeking = LockedTarget;
					s.NumExtraRockets = DupRockets;
					if ( Angle > 0 )
						s.Velocity *= (0.9 + 0.2 * FRand());
				}
				else
				{
					//r = Spawn( class'rocketmk2',, '', FireLocation,FireRot);
					r = RocketMK2(Spawn(ProjectileClass,, '', FireLocation,FireRot));

					r.NumExtraRockets = DupRockets;
					if (RocketsLoaded>4 && bTightWad) r.bRing=True;
					if ( Angle > 0 )
						r.Velocity *= (0.9 + 0.2 * FRand());
				}
			}
			else
			{
				g = Spawn( class 'ut_Grenade',, '', FireLocation,AdjustedAim);
				g.NumExtraGrenades = DupRockets;
				if ( DupRockets > 0 )
				{
					RandRot.Pitch = FRand() * 1500 - 750;
					RandRot.Yaw = FRand() * 1500 - 750;
					RandRot.Roll = FRand() * 1500 - 750;
					g.Velocity = g.Velocity >> RandRot;
				}
			}

			Angle += 1.0484; //2*3.1415/6;
			RocketsLoaded--;
		}
		bTightWad=False;
		bRotated = false;
	}

	function AnimEnd()
	{
		if ( !bRotated && (AmmoType.AmmoAmount > 0) )
		{
			PlayLoading(1.5,0);
			RocketsLoaded = 1;
			bRotated = true;
			return;
		}
		LockedTarget = None;
		Finish();
	}


}


defaultproperties {
	ItemName="Enhanced Rocket Launcher"
	PickupMessage="You got the Enhanced Rocket Launcher."
	ProjectileClass=class'SBRocketMk2'
}
For testing I set the ProjectileSpeed quite high:
SBRocketMk2.ini wrote:[SBEightballV1.SBRocketMk2]
ProjectileSpeed=5000.000000
Running the testmap locally all things work, but playing with client/server and INI file on server only, the client logs
UnrealTournament.ini wrote:ScriptLog: TestProjectileSpeed.SBRocketMk0.PostBeginPlay starting with SmokeRate=0.000000, ProjectileSpeed=20.000000, Speed=900.000000
ScriptLog: TestProjectileSpeed.SBRocketMk0.PostBeginPlay finished with SmokeRate=10.000000, ProjectileSpeed=20.000000, Speed=20.000000
ScriptLog: TestProjectileSpeed.SBRocketMk0.PostNetBeginPlay: Speed=20.000000
Warning: New actor channel received non-open packet: 0/1/1
So "ProjectileSpeed" is not replicated?
Attachments
SBEightball.7z
Project files of "SBEightball"
(6.7 KiB) Downloaded 18 times
"Multiple exclamation marks," he went on, shaking his head, "are a sure sign of a diseased mind." --Terry Pratchett

User avatar
sektor2111
Godlike
Posts: 4171
Joined: Sun May 09, 2010 6:15 pm
Location: On the roof.

Re: Projectile speed replication

Post by sektor2111 » Sat Mar 23, 2019 10:38 pm

You lost me here. If this projectile has a "defaultproperty" with your desired value, client should know a "defaultproperty" of a certain class if package is being sent to client as it knows other stock things. If that property is changed/changeable via INI... umm... nwm, I'm not going to roam client again - ACE won't love what I do...

User avatar
Feralidragon
Godlike
Posts: 5121
Joined: Wed Feb 27, 2008 6:24 pm
Personal rank: Work In Progress
Location: Liandri

Re: Projectile speed replication

Post by Feralidragon » Sun Mar 24, 2019 11:23 am

It's been a looooong while since I looked at anything concerning projectiles, but I am pretty sure that by the time you call PostBeginPlay, you still don't have any initial values replicated/processed from the server, and that's why you have PostNetBeginPlay, which is only called after the first batch of replicated properties, and that's where you should set the speed in order for it to work online.

In later engine iterations, namely UE3, Epic realized how stupid it was to have 2 different events like this, so they just moved PostBeginPlay to be called later, at PostNetBeginPlay time, and removed the latter.

User avatar
TheDane
Masterful
Posts: 618
Joined: Tue Feb 12, 2008 2:47 pm
Personal rank: Happy fool :-)

Re: Projectile speed replication

Post by TheDane » Sun Mar 24, 2019 1:14 pm

You can set it dynamicly through the game with a mutator doing a:

Code: Select all

var config float ConfigurableVariable;

function bool AlwaysKeep(Actor Other)
{
	if (Other.IsA('SBRocketMk2'))
        {
		SBRocketMk2(Other).ProjectileSpeed = ConfigurableVariable;
		return true;
		}
	
	if ( NextMutator != None )
		return ( NextMutator.AlwaysKeep(Other) );
	return false;
}
You can build the above script into any mutator you have running, or ofcause make it as stand-alone. If you use it as stand-alone be sure not to break the chain in the functions (call super and such).
Retired.

Higor
Godlike
Posts: 1781
Joined: Sun Mar 04, 2012 6:47 pm

Re: Projectile speed replication

Post by Higor » Sun Mar 24, 2019 4:22 pm

PostBeginPlay your replicated vars haven't been set.

PostNetBeginPlay projectile physics has already been initialized by PostBeginPlay.

Solution?
Reinitialize projectile physics in PostNetBeginPlay.
ImageImage
Image unreal://23.111.157.138:7777
Image unreal://46.228.199.205:7788

Post Reply