logo
Main

Forums

Downloads

Unreal-Netiquette

Donate for Oldunreal:
Donate

borderline

Links to our wiki:
Wiki

Walkthrough

Links

Tutorials

Unreal Reference

Usermaps

borderline

Contact us:
Submit News
Page Index Toggle Pages: 1 Send TopicPrint
Normal Topic Issue #49. Falling inventory may fall out of world and be displayed at wrong location client-side (Read 157 times)
Masterkent
Developer Team
Offline



Posts: 890
Location: Russia
Joined: Apr 5th, 2013
Gender: Male
Issue #49. Falling inventory may fall out of world and be displayed at wrong location client-side
Aug 2nd, 2017 at 7:46pm
Print Post  
When a player takes a copy of a respawnable inventory, the respawnable inventory changes its state from Pickup to Sleeping. Leaving the state Pickup invokes the function Inventory.Pickup.EndState:

Code
Select All
	function EndState()
	{
		bCollideWorld = false;
		bSleepTouch = false;
	} 


This implementation disables collision with the world geometry regardless of whether the inventory is falling or not. If the inventory is falling (e.g. when it's spawned by a destroyed decoration), it may fall out of world and be destroyed by the call to Actor.FellOutOfWorld(). I think, this code should be changed to

Code
Select All
	function EndState()
	{
		if (Physics != PHYS_Falling)
			bCollideWorld = false;
		bSleepTouch = false;
	} 


so touching a respawnable inventory before it reached the ground would not lead to its destruction. This would also affect some UPakHeath actors which are supposed to be respawnable (even in single-player game) but sometimes may fall out of world due to Physics == PHYS_Falling being always true.

When a weapon is dropped by a player, Inventory.DropFrom is called:

Code
Select All
function DropFrom(vector StartLocation)
{
	if ( !SetLocation(StartLocation) )
		return;
	RespawnTime = 0.0; //don't respawn
	SetPhysics(PHYS_Falling);
	RemoteRole = ROLE_DumbProxy;
	BecomePickup();
	NetPriority = 6;
	bCollideWorld = true;
	if ( Pawn(Owner) != None )
		Pawn(Owner).DeleteInventory(self);
	GotoState('PickUp', 'Dropped');
} 


Setting RemoteRole to ROLE_DumbProxy enables replication of Location from server to clients, so the weapon's Location can be properly updated client-side. Then, when Timer() is invoked, it changes RemoteRole from ROLE_DumbProxy to ROLE_SimulatedProxy:

Code
Select All
	function Timer()
	{
		if ( RemoteRole != ROLE_SimulatedProxy )
		{
			NetPriority = 2;
			RemoteRole = ROLE_SimulatedProxy;
			if ( bHeldItem )
				SetTimer(40.0, false);
			return;
		}

		if ( bHeldItem )
			Destroy();
	} 


and then replication of Location does not take place anymore. Normally, for a dropped weapon, the timer should be activated by the call to Landed() when the weapon landed on the ground:

Code
Select All
	function Landed(Vector HitNormal)
	{
		local rotator newRot;
		newRot = Rotation;
		newRot.pitch = 0;
		SetRotation(newRot);
		SetTimer(2.0, false);
	} 


However, some weapons (e.g. Eightball) may activate the timer before they were dropped and for different purposes, then the call to Timer may happen before the weapon reaches the ground, that leads to missing updates of actual Location client-side (the weapon is observed as hanging somewhere in air).

Theoretically, such a situation may also occur when the weapon has bHeldItem == true and it falls during more than 45 seconds. This is how I would fix the current implementation:

Code
Select All
	function Timer()
	{
		if ( RemoteRole != ROLE_SimulatedProxy )
		{
			NetPriority = 2;
			RemoteRole = ROLE_SimulatedProxy;
+			if (Physics == PHYS_Falling)
+				bSimulatedPawnRep = true;
			if ( bHeldItem )
				SetTimer(40.0, false);
			return;
		}

		if ( bHeldItem )
			Destroy();
	}

	function BeginState()
	{
		BecomePickup();
		bCollideWorld = true;
		if ( bHeldItem )
			SetTimer(45, false);
+		else
+			SetTimer(0, false);
	} 


Although adding

Code
Select All
			if (Physics == PHYS_Falling)
				bSimulatedPawnRep = true; 


alone would solve the problem with replication, I think that for a non-held inventory the timer should be stopped anyway. For example, Eightball.Idle.Timer obviously serves a different purpose than controlling RemoteRole or interval before automatic self-destruction, and the current influence of the Eightball-specific use of the timer on such things takes place due to a coincidence that was overlooked.

Engine/Classes/Inventory.uc
« Last Edit: Aug 3rd, 2017 at 6:13am by Masterkent »  
Back to top
 
IP Logged
 
Smirftsch
Forum Administrator
*****
Offline



Posts: 7552
Location: at home
Joined: Apr 30th, 1998
Gender: Male
Re: Issue #49. Falling inventory may fall out of world and be displayed at wrong location client-side
Reply #1 - Aug 3rd, 2017 at 5:46am
Print Post  
implemented as suggested. Thanks Wink
  

Sometimes you have to lose a fight to win the war.
Back to top
WWWICQ  
IP Logged
 
Page Index Toggle Pages: 1
Send TopicPrint
Bookmarks: del.icio.us Digg Facebook Google Google+ Linked in reddit StumbleUpon Twitter Yahoo