A little bit extended mover

Discussions about Coding and Scripting

A little bit extended mover

Postby Haxer557 » Sun Sep 25, 2011 11:57 am

Hello,

I map a level for a team game (Thievery UT), and I wish to create a boat, that would carry players of one team, but only if they are inside. To achieve it, I have coded a Trigger that I will call from now a controller. The controller checks every tick id there is a player of this particular team in boat, and how many of them, if boat is not interpolating it checks its keys, and modifies KeyPos and KeyRot values, as well as MoveSpeed - the more players are in boat, the faster it moves - then it triggers it. The boat is also coded, for by default KeyPos and KeyRot values do not replicate to client.
Code: Select all
var vector DesiredLocation;
var rotator DesiredRotationAdv;
var float NewMoveTime;
var int DesiredKeyNum;
var() name AttachTag;

replication
{
   reliable if(Role==Role_Authority)
      DesiredLocation, DesiredRotationAdv, DesiredKeyNum, NewMoveTime;
}


A simulated Tick overrides KeyPos, KeyRot, and MoveTime variables, just like that:
Code: Select all
simulated function Tick(float DeltaTime)
{
   Super.Tick(DeltaTime);
   if(KeyPos[DesiredKeyNum]!=DesiredLocation)
      KeyPos[DesiredKeyNum]=DesiredLocation;
   if(KeyRot[DesiredKeyNum]!=DesiredRotationAdv)
   {
      KeyRot[DesiredKeyNum]=DesiredRotationAdv;
   }
   if(MoveTime!=NewMoveTime)
      MoveTime=NewMoveTime;
}


If I try to play it solo, everything works as I desired, however if I try it online, the moment boat turns left - and mover starts to rotate - mover starts shaking very fast, and player on the boat starts to spin around. Perhaps there is something more I should replicate to the client?

edit: in case it was helpful, here are source codes:

The controller:
Code: Select all
//=============================================================================
// ThHaxersBoatController.
//=============================================================================
class ThHaxersBoatController expands Triggers;

var vector       HaxersKeyPos[128];
var rotator      HaxersKeyRot[128];
var int        HaxersActualKeyNum;
var ThHaxersAdvancedBoat Boat;
var rotator SavedRotatorTest;

var() float Speedmps;
var float MoveTime;
var bool bInitialized;

function InitializeBoat()
{
   local int i;

   log("Boat is initializing");
   HaxersKeyPos[0].X=0;
   HaxersKeyPos[0].Y=0;
   HaxersKeyPos[0].Z=0;
   HaxersKeyRot[0]=Rotation-Rotation;

   for(i=1; i<28; i++)//first 28 keys boat moves straight forward
   {
   HaxersKeyPos[i].X=HaxersKeyPos[i-1].X;
   HaxersKeyPos[i].Y=HaxersKeyPos[i-1].Y+64;
   HaxersKeyPos[i].Z=HaxersKeyPos[i-1].Z;
   HaxersKeyRot[i]=Rotation-Rotation;
   }
   for(i=28; i<63; i++)//then it moves diagonally
   {
   HaxersKeyPos[i].X=HaxersKeyPos[i-1].X+46;
   HaxersKeyPos[i].Y=HaxersKeyPos[i-1].Y+46;
   HaxersKeyPos[i].Z=HaxersKeyPos[i-1].Z;
   HaxersKeyRot[i]=Rotation-Rotation;
   HaxersKeyRot[i].Yaw=HaxersKeyRot[i-1].Yaw - 468.114;
   }
   for(i=63; i<122; i++)//the last part of boats movement is almost perpendicular to the first part
   {
   HaxersKeyPos[i].X=HaxersKeyPos[i-1].X+64;
   HaxersKeyPos[i].Y=HaxersKeyPos[i-1].Y+4;
   HaxersKeyPos[i].Z=HaxersKeyPos[i-1].Z;
   HaxersKeyRot[i]=HaxersKeyRot[i-1];
   }

   foreach AllActors(class'ThHaxersAdvancedBoat', Boat, Event)
   {
      break;
   }

   MoveTime = 1/Speedmps;

   bInitialized=true;
}

function SetKeys()
{
   HaxersActualKeyNum++;
   if(Boat.KeyNum==0)
   {
      Boat.DesiredKeyNum=1;
   }
   if(Boat.KeyNum==1)
   {
      Boat.DesiredKeyNum=0;
   }
   Boat.DesiredLocation=HaxersKeyPos[HaxersActualKeyNum];
   Boat.DesiredRotationAdv=HaxersKeyRot[HaxersActualKeyNum];
}

function Tick(float DeltaTime)
{
   local int ThievesStanding;
   local Actor A;
   local Pawn P;
   local Pawn SavedPawn;

   //count thieves standing on a boat
   Super.Tick(DeltaTime);

   if(!bInitialized)
      return;

   if(HaxersActualKeyNum==120)
   {
   log("Boat Reached!");
      if(!binterpolating)
      {
         foreach AllActors(class 'Actor', A, 'BoatReached') {
            A.Trigger(None, None);}
         bInitialized=false;
      }
   return;
   }
   for (P=Level.PawnList; P!=None; P=P.nextPawn)
      {
      if(ThieveryPPawn(P)!=None&&ThieveryPPawn(P).PlayerReplicationInfo!=None&&ThieveryPPawn(P).PlayerReplicationInfo.Team==0)
      {
         if(VSize(ThieveryPPawn(P).Location - Boat.Location)<140&&ThieveryPPawn(P).Location.Z>Boat.Location.Z)
         {
            SavedPawn=P;
            ThievesStanding++;
         }
      }
   }

   if(ThievesStanding>0)
   {
      // some taffer is sitting in a boat - let's set sail
      if(!Boat.bInterpolating)
      {
         SetKeys();
         Boat.NewMoveTime=MoveTime+(ThievesStanding-1)*MoveTime*0.5;
         Boat.Trigger(SavedPawn, SavedPawn);
      }
   }
}



And the boat:
Code: Select all
//=============================================================================
// ThHaxersAdvancedBoat.
//=============================================================================
class ThHaxersAdvancedBoat expands Mover;

var vector DesiredLocation;
var rotator DesiredRotationAdv;
var float NewMoveTime;
var int DesiredKeyNum;
var() name AttachTag;

replication
{
   reliable if(Role==Role_Authority)
      DesiredLocation, DesiredRotationAdv, DesiredKeyNum, NewMoveTime;
}

function PostBeginPlay()
{
   local Actor Act;
   local Mover Mov;

   Super.PostBeginPlay();

   // Initialize all slaves.
   if ( AttachTag != '' )
      foreach AllActors( class 'Actor', Act, AttachTag )
      {
         Mov = Mover(Act);
         if (Mov == None) {

            Act.SetBase( Self );
         }
         else if (Mov.bSlave) {
         
            Mov.GotoState('');
            Mov.SetBase( Self );
         }
      }
}

simulated function Tick(float DeltaTime)
{
   local Actor A;
   Super.Tick(DeltaTime);
   if(KeyPos[DesiredKeyNum]!=DesiredLocation)
      KeyPos[DesiredKeyNum]=DesiredLocation;
   if(KeyRot[DesiredKeyNum]!=DesiredRotationAdv)
   {
      KeyRot[DesiredKeyNum]=DesiredRotationAdv;
   }
   if(MoveTime!=NewMoveTime)
      MoveTime=NewMoveTime;
}


edit2:

To make it more clear, I recorded a video:
http://www.youtube.com/watch?v=hW4urDPoJj8
Haxer557
Novice
 
Posts: 8
Joined: Mon Jun 06, 2011 9:51 am
Personal rank: Thievery UT Player

Re: A little bit extended mover

Postby Feralidragon » Tue Sep 27, 2011 12:38 pm

Could you post your default properties as well.

Movers are a quite messed up part of the UEngine relative online play (they never worked right, take their rotating mover of example which doesn't even rotate at all online).
However in your case I think this may be fixed, but the default properties are important since they define certain things like the NetPriority, Roles, etc.
User avatar
Feralidragon
Site Staff
 
Posts: 3712
Joined: Wed Feb 27, 2008 6:24 pm
Location: Portugal - Lisbon
Personal rank: The Unreal Boy

Re: A little bit extended mover

Postby Haxer557 » Fri Sep 30, 2011 4:52 pm

Most of the properties are just mover's defaults I guess. Sorry for the inconvenience, but since I use my mobile phone to access the Internet atm, I am unable to post a Sshot. Instead, I will write down some properties:
NetPriority - 2.7
NetUpdateFrequency - 100.0
RemoteRole - ROLE_SimulatedProxy
Haxer557
Novice
 
Posts: 8
Joined: Mon Jun 06, 2011 9:51 am
Personal rank: Thievery UT Player

Re: A little bit extended mover

Postby Feralidragon » Fri Sep 30, 2011 5:41 pm

Well, I will be honest with you: I never coded a mover in my life, therefore my "solution" may or may not work, but give it a try nonethless:
- It happens that to me that "shake" is simply 2 different rotation values "conflicting" with eachother, meaning that when the client updates to a value, the server sends its own value and is updated again, and the server value is different from the client.
I checked up your code and the Mover class code to see how it handled movement, and everything sugests that you're worrying about something you don't have to, therefore try this:
- Remove that replication block from the mover, it will be useless from this moment on;
- Turn that simulated tick into a non-simulated (remove the "simulated" word)

From that moment on, the keys will be only updated in the server, and the mover super class replication code should handle the rest.
Again, no guarantees it will work, and in case it really doesn't, at least we can observe perhaps another kind of behaviour to create a pattern and check how that can be fixed.

EDIT: Btw, remove those Rotation-Rotation parts of your code (replace them by rot(0,0,0) instead).
User avatar
Feralidragon
Site Staff
 
Posts: 3712
Joined: Wed Feb 27, 2008 6:24 pm
Location: Portugal - Lisbon
Personal rank: The Unreal Boy

Re: A little bit extended mover

Postby Haxer557 » Fri Sep 30, 2011 10:59 pm

By the time you posted it, I had tried setting role to dumbproxy, and it works pretty fine. Still you helped me a lot by pointing to Networking properties.
Your solution is something similar to what I have once tried, but the parent class doesn't replicate KeyPos arrays, what would lead to a desynch in online game.
The very first parts of the code I wrote when I was just starting with Unreal Script, thats why there is Rotation-Rotation :P shame on me.
Thank you once again, for I wouldn't have touched those Networking properties if it wasn't you who mentioned it. If I create any readable item with credits, I will mention it, as well as the forums. :)
Haxer557
Novice
 
Posts: 8
Joined: Mon Jun 06, 2011 9:51 am
Personal rank: Thievery UT Player

Re: A little bit extended mover

Postby Feralidragon » Sat Oct 01, 2011 10:54 am

No problem. However:
Haxer557 wrote:Your solution is something similar to what I have once tried, but the parent class doesn't replicate KeyPos arrays, what would lead to a desynch in online game.

The first thing you must understand about the Mover class (from what I checked in its code) is that you don't even need to replicate those values (the same happens to actors like the guided redeemer). Most of the values of the mover are server-side only, and the only values you replicate are stuff like "RealLocation" and "RealRotation" and so on, values that were updated in the server, and that must be updated in the client, exactly to avoid the sync problem between both ends.

But well, that "solution" is not perfect, but if it works well for you, that's ok (considering that replication of Movers and guided redeemers isn't exactly simple stuff) :thuup:
User avatar
Feralidragon
Site Staff
 
Posts: 3712
Joined: Wed Feb 27, 2008 6:24 pm
Location: Portugal - Lisbon
Personal rank: The Unreal Boy


Return to Coding, Scripting

Who is online

Users browsing this forum: No registered users and 0 guests