Commits

Torr_Samaho committed 0f852a7

[TIHan]:
Fixed: Poly object doors were not handled properly online.
Fixed: Newly connected clients were not properly informed of poly objects.

Comments (0)

Files changed (5)

docs/Skulltag Version History.txt

 -	- Fixed: Under certain circumstances after a monster was resurrected, it did not get reset when the map reset. [TIHan]
 -	- Fixed: Spectators were blocked by SOLID things on steps. [Torr Samaho]
 -	- Fixed: The remains of crushed actors were not removed on the clients online by a map reset. [Torr Samaho]
+-	- Fixed: Poly object doors were not handled properly online. [TIHan]
+-	- Fixed: Newly connected clients were not properly informed of poly objects. [TIHan]
 !	- Changed F12 to allow spectators full spying, with the exception of during LMS if it's disabled. [Eruanna]
 !	- Changed F12 to allow full demo spying. [Eruanna]
 !	- Players aren't forced to spectate after a "changemap" map change on a server with a join password anymore. [Torr Samaho]
 	void	SetDist( LONG lDist );
 
 	LONG	GetPolyObj( void );
+
+	virtual void UpdateToClient( ULONG ulClient ); // [WS] We need this here.
 protected:
 	DPolyAction ();
 	int m_PolyObj;
 	DMovePoly (int polyNum);
 	void Serialize (FArchive &arc);
 	void Tick ();
-	void UpdateToClient( ULONG ulClient );
+	virtual void UpdateToClient( ULONG ulClient ); // [WS] This needs to be virtual.
 
 	LONG	GetAngle( void );
 	void	SetAngle( LONG lAngle );
 	return ( m_PolyObj );
 }
 
+// [WS] This should never be called.
+void DPolyAction::UpdateToClient( ULONG ulClient )
+{
+	Printf("WARNING: DPolyAction::UpdateToClient was called. This should never happen! Please report this at the Skulltag bug tracker!\n");
+}
+
 DRotatePoly::DRotatePoly ()
 {
 }
 
 void DPolyDoor::UpdateToClient( ULONG ulClient )
 {
-	SERVERCOMMANDS_DoPolyDoor( m_Type, m_xSpeed, m_ySpeed, m_Speed, m_PolyObj, ulClient, SVCF_ONLYTHISCLIENT );
+	// [WS] Is our door paused?
+	if (m_Tics != 0)
+		SERVERCOMMANDS_DoPolyDoor( m_Type, 0, 0, 0, m_PolyObj, ulClient, SVCF_ONLYTHISCLIENT );
+	else // [WS] Door is in motion, inform the client.
+	{
+		// [WS] Play the sound.
+		SERVERCOMMANDS_PlayPolyobjSound( m_PolyObj, POLYSOUND_SEQ_DOOR );
+		SERVERCOMMANDS_DoPolyDoor( m_Type, m_xSpeed, m_ySpeed, m_Speed, m_PolyObj, ulClient, SVCF_ONLYTHISCLIENT );
+	}
 }
 
 LONG DPolyDoor::GetDirection ()
 void DRotatePoly::Tick ()
 {
 	// [BC] For clients, just tick them and get out.
-	if (( NETWORK_GetState( ) == NETSTATE_CLIENT ) ||
-		( CLIENTDEMO_IsPlaying( )))
+	if ( NETWORK_InClientMode( ) )
 	{
 		PO_RotatePolyobj( m_PolyObj, m_Speed );
 		return;
 			m_Speed = m_Dist * (m_Speed < 0 ? -1 : 1);
 		}
 	}
+	else if ( NETWORK_GetState( ) == NETSTATE_SERVER )
+		// [WS] The poly object is blocked, tell clients the rotation!
+	{
+		FPolyObj *poly = GetPolyobj (m_PolyObj);
+		SERVERCOMMANDS_SetPolyobjRotation( m_PolyObj, poly->angle );
+	}
 }
 
 //==========================================================================
 	FPolyObj *poly;
 
 	// [BC] For clients, just tick them and get out.
-	if (( NETWORK_GetState( ) == NETSTATE_CLIENT ) ||
-		( CLIENTDEMO_IsPlaying( )))
+	if ( NETWORK_InClientMode( ) )
 	{
 		PO_MovePolyobj( m_PolyObj, m_xSpeed, m_ySpeed );
 		return;
 			m_ySpeed = FixedMul (m_Speed, finesine[m_Angle]);
 		}
 	}
+	else if ( NETWORK_GetState ( ) == NETSTATE_SERVER )
+		// [WS] The poly object is blocked, tell clients the position!
+	{
+		poly = GetPolyobj (m_PolyObj);
+		SERVERCOMMANDS_SetPolyobjPosition( m_PolyObj, poly->startSpot[0], poly->startSpot[1] );
+	}
 }
 
 //==========================================================================
 {
 	int absSpeed;
 	FPolyObj *poly;
-	bool	bBlocked;
 
 	// [BC] For clients, just tick them and get out.
-	if (( NETWORK_GetState( ) == NETSTATE_CLIENT ) ||
-		( CLIENTDEMO_IsPlaying( )))
+	if ( NETWORK_InClientMode( ) )
 	{
 		switch ( m_Type )
 		{
 
 		return;
 	}
-
-	// The door is currently paused after opening all the way.
+	poly = GetPolyobj (m_PolyObj); // [WS] Need to use this in the rest of the function.
 	if (m_Tics)
 	{
-		// Pause time is over! Time to set the door back in motion.
 		if (!--m_Tics)
 		{
-			poly = GetPolyobj (m_PolyObj);
-
-			// [BC] Tell clients to start the sound sequence, and to set the polyobject
-			// back in motion
-			if ( NETWORK_GetState( ) == NETSTATE_SERVER )
-			{
-				SERVERCOMMANDS_PlayPolyobjSound( m_PolyObj, POLYSOUND_SEQ_DOOR );
-				if ( m_Type == PODOOR_SLIDE )
-				{
-					SERVERCOMMANDS_SetPolyDoorSpeedPosition( m_PolyObj,
-																m_xSpeed,
-																m_ySpeed,
-																poly->startSpot[0],
-																poly->startSpot[1] );
-				}
-			}
-
+			//poly = GetPolyobj (m_PolyObj); // [WS] We are handling this elsewhere.
 			SN_StartSequence (poly, poly->seqType, SEQ_DOOR, m_Close);
 		}
 		return;
 	switch (m_Type)
 	{
 	case PODOOR_SLIDE:
-
-		poly = GetPolyobj( m_PolyObj );
-		bBlocked = ( PO_MovePolyobj (m_PolyObj, m_xSpeed, m_ySpeed) == false );
-
-		// [BC] If the polyobject had NOT been blocked last frame, but is now, tell clients
-		// to set stop the polyobject.
-		if (( NETWORK_GetState( ) == NETSTATE_SERVER ) && ( bBlocked ) && ( poly->bBlocked == false ))
+		if (m_Dist <= 0 || PO_MovePolyobj (m_PolyObj, m_xSpeed, m_ySpeed))
 		{
-			poly->bBlocked = true;
-			SERVERCOMMANDS_SetPolyDoorSpeedPosition( m_PolyObj,
-														m_xSpeed,
-														m_ySpeed,
-														poly->startSpot[0],
-														poly->startSpot[1] );
-		}
-
-		if (m_Dist <= 0 || ( bBlocked == false ))
-		{
-			// [BC] If the polyobject had been blocked last frame, but isn't now, tell clients
-			// to set the polyobject back in motion.
-			if (( NETWORK_GetState( ) == NETSTATE_SERVER ) && ( poly->bBlocked ))
-			{
-				poly->bBlocked = false;
+			// [WS] Inform clients that the door is closing.
+			if ( NETWORK_GetState( ) == NETSTATE_SERVER && m_TotalDist == m_Dist && m_Close )
 				SERVERCOMMANDS_SetPolyDoorSpeedPosition( m_PolyObj,
 															m_xSpeed,
 															m_ySpeed,
 															poly->startSpot[0],
 															poly->startSpot[1] );
-			}
 
 			absSpeed = abs (m_Speed);
 			m_Dist -= absSpeed;
 					m_xSpeed = -m_xSpeed;
 					m_ySpeed = -m_ySpeed;					
 
-					// [BC] Tell clients that the door is now paused.
+					// [WS] Inform clients the door has stopped.
 					if ( NETWORK_GetState( ) == NETSTATE_SERVER )
-					{
-						SERVERCOMMANDS_SetPolyDoorSpeedPosition( m_PolyObj,
-																	0,
-																	0,
-																	poly->startSpot[0],
-																	poly->startSpot[1] );
-					}
+						SERVERCOMMANDS_SetPolyDoorSpeedPosition( m_PolyObj, 0, 0, poly->startSpot[0], poly->startSpot[1] );
 				}
 				else
 				{
 
 					// [BC] If we're the server, tell clients to destroy the poly door.
 					if ( NETWORK_GetState( ) == NETSTATE_SERVER )
+					{
 						SERVERCOMMANDS_DestroyPolyDoor( m_PolyObj );
+						SERVERCOMMANDS_SetPolyobjPosition( m_PolyObj );
+					}
 
 					Destroy ();
 				}
 				SN_StartSequence (poly, poly->seqType, SEQ_DOOR, 0);
 
 				// [BC] Tell clients to play the sound sequence.
+				// [WS] Tell clients to update the speed and position.
 				if ( NETWORK_GetState( ) == NETSTATE_SERVER )
+				{
 					SERVERCOMMANDS_PlayPolyobjSound( m_PolyObj, POLYSOUND_SEQ_DOOR );
+					SERVERCOMMANDS_SetPolyDoorSpeedPosition( m_PolyObj, m_xSpeed, m_ySpeed,
+														poly->startSpot[0],
+														poly->startSpot[1] );
+				}
 			}
 		}
 		break;
 	case PODOOR_SWING:
 		if (PO_RotatePolyobj (m_PolyObj, m_Speed))
 		{
+
+			// [WS] Inform clients that the door is closing.
+			if ( NETWORK_GetState( ) == NETSTATE_SERVER && m_TotalDist == m_Dist && m_Close )
+				SERVERCOMMANDS_SetPolyDoorSpeedRotation( m_PolyObj, m_Speed, poly->angle );
+
 			absSpeed = abs (m_Speed);
 			if (m_Dist == -1)
 			{ // perpetual polyobj
 					m_Close = true;
 					m_Tics = m_WaitTics;
 					m_Speed = -m_Speed;
+
+					// [WS] Inform clients the door has stopped.
+					if ( NETWORK_GetState( ) == NETSTATE_SERVER )
+						SERVERCOMMANDS_SetPolyDoorSpeedRotation( m_PolyObj, 0, poly->angle );
 				}
 				else
 				{
 
 					// [BC] Tell clients to destroy the poly door.
 					if ( NETWORK_GetState( ) == NETSTATE_SERVER )
+					{
 						SERVERCOMMANDS_DestroyPolyDoor( m_PolyObj );
+						SERVERCOMMANDS_SetPolyobjRotation( m_PolyObj );
+					}
 
 					Destroy ();
 				}
 				SN_StartSequence (poly, poly->seqType, SEQ_DOOR, 0);
 
 				// [BC] Tell clients to play the sound sequence.
+				// [WS] Tell clients to update the speed and rotation.
 				if ( NETWORK_GetState( ) == NETSTATE_SERVER )
+				{
 					SERVERCOMMANDS_PlayPolyobjSound( m_PolyObj, POLYSOUND_SEQ_DOOR );
+					SERVERCOMMANDS_SetPolyDoorSpeedRotation( m_PolyObj, m_Speed, poly->angle );
+				}
 			}
 		}			
 		break;
 	thrustY = FixedMul (force, finesine[thrustAngle]);
 	actor->momx += thrustX;
 	actor->momy += thrustY;
-	if (po->crush &&
-		( NETWORK_GetState( ) != NETSTATE_CLIENT ) &&
-		( CLIENTDEMO_IsPlaying( ) == false ))
+	if (po->crush && !NETWORK_InClientMode( ))
 	{
 		if (po->bHurtOnTouch || !P_CheckMove (actor, actor->x + thrustX, actor->y + thrustY))
 		{
 		seg_t **segList = po->segs;
 		bool blocked = false;
 
-		// Don't check if the polyobject was blocked by something in client mode. The server will
-		// tell us if something is blocking its path.
-		if (( NETWORK_GetState( ) != NETSTATE_CLIENT ) &&
-			( CLIENTDEMO_IsPlaying( ) == false ))
+		for (int count = po->numsegs; count; count--, segList++)
 		{
-			for (int count = po->numsegs; count; count--, segList++)
+			if (CheckMobjBlocking(*segList, po))
 			{
-				if (CheckMobjBlocking(*segList, po))
-				{
-					blocked = true;
-					break;
-				}
+				blocked = true;
+				break;
 			}
 		}
-
 		if (blocked)
 		{
 			DoMovePolyobj (po, -x, -y);
 	line_t *ld;
 	bool blocked;
 
-	if (( NETWORK_GetState( ) == NETSTATE_CLIENT ) ||
-		( CLIENTDEMO_IsPlaying( )))
-	{
-		return ( false );
-	}
+	// [WS] The client doesn't check if anything is blocking
+	if ( NETWORK_InClientMode( ) )
+		return false;
 
 	ld = seg->linedef;
 
 			polyobjs[index].bHurtOnTouch = (type == PO_SPAWNHURT_TYPE);
 			polyobjs[index].bMoved = false;
 			polyobjs[index].bRotated = false;
-			polyobjs[index].bBlocked = false;
 			polyobjs[index].tag = tag;
 			polyobjs[index].seqType = segs[i].linedef->args[2];
 			if (polyobjs[index].seqType < 0 || polyobjs[index].seqType > 63)
 			polyobjs[index].bHurtOnTouch = (type == PO_SPAWNHURT_TYPE);
 			polyobjs[index].bMoved = false;
 			polyobjs[index].bRotated = false;
-			polyobjs[index].bBlocked = false;
 			polyobjs[index].tag = tag;
 			polyobjs[index].segs = new seg_t *[polyobjs[index].numsegs];
 			for (i = 0; i < polyobjs[index].numsegs; i++)
 
 	// Has this polyobject rotated at all? If so, we need to tell connecting clients of its new position.
 	bool		bRotated;
-
-	// Was the polyobject blocked the last time it tried to move?
-	bool		bBlocked;
 };
 extern FPolyObj *polyobjs;		// list of all poly-objects on the level
 
 	// [BB] Tell the client of things derived from DMover and similar classes.
 	SERVER_UpdateMovers( g_lCurrentClient );
 
-	// Tell the client about any active rotate polyobjects.
-	{
-		DRotatePoly	*pRotatePoly;
-		TThinkerIterator<DRotatePoly>	Iterator;
-
-		while (( pRotatePoly = Iterator.Next( )))
-			pRotatePoly->UpdateToClient( g_lCurrentClient );
-	}
-
-	// Tell the client about any move polyobjects.
-	{
-		DMovePoly	*pMovePoly;
-		TThinkerIterator<DMovePoly>		Iterator;
-
-		while (( pMovePoly = Iterator.Next( )))
-			pMovePoly->UpdateToClient( g_lCurrentClient );
-	}
-
-	// Tell the client about any active door polyobjects.
-	{
-		DPolyDoor	*pPolyDoor;
-		TThinkerIterator<DPolyDoor>		Iterator;
-
-		while (( pPolyDoor = Iterator.Next( )))
-			pPolyDoor->UpdateToClient( g_lCurrentClient );
-	}
-
 	// Send a snapshot of the level.
 	SERVER_SendFullUpdate( g_lCurrentClient );
 
 	ULONG							ulIdx;
 	sector_t						*pSector;
 	FPolyObj						*pPoly;
+	TThinkerIterator<DPolyAction>	PolyActionIterator;
+	DPolyAction						*pPolyAction;
 	TThinkerIterator<DFireFlicker>	FireFlickerIterator;
 	DFireFlicker					*pFireFlicker;
 	TThinkerIterator<DFlicker>		FlickerIterator;
 			SERVERCOMMANDS_SetPolyobjRotation( pPoly->tag, ulClient, SVCF_ONLYTHISCLIENT );
 	}
 
+	// [WS] Because poly objects can potentially have more than one thinker,
+	// we need to iterate through every thinker and tell the client about it.
+	while (( pPolyAction = PolyActionIterator.Next( )) != NULL )
+		pPolyAction->UpdateToClient( ulClient );
+
 	// Check for various sector light effects. If we find any, tell the client about them.
 	while (( pFireFlicker = FireFlickerIterator.Next( )) != NULL )
 		pFireFlicker->UpdateToClient( ulClient );