Projectile speed replication

Discussions about Coding and Scripting

Projectile speed replication

Postby 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
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 13 times
"Multiple exclamation marks," he went on, shaking his head, "are a sure sign of a diseased mind." --Terry Pratchett
User avatar
Barbie
Godlike
 
Posts: 1685
Joined: Fri Sep 25, 2015 9:01 pm
Location: moved without proper hashing

Re: Projectile speed replication

Postby 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
sektor2111
Godlike
 
Posts: 4033
Joined: Sun May 09, 2010 6:15 pm
Location: On the roof.

Re: Projectile speed replication

Postby 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
Feralidragon
Godlike
 
Posts: 5077
Joined: Wed Feb 27, 2008 6:24 pm
Location: Liandri
Personal rank: Work In Progress

Re: Projectile speed replication

Postby 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.
User avatar
TheDane
Masterful
 
Posts: 615
Joined: Tue Feb 12, 2008 2:47 pm
Personal rank: Anti EPIC Games fan

Re: Projectile speed replication

Postby 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.
Higor
Godlike
 
Posts: 1756
Joined: Sun Mar 04, 2012 6:47 pm


Return to Coding, Scripting

Who is online

Users browsing this forum: No registered users and 3 guests