# HG changeset patch # User Adam Kaminski # Date 1626998938 14400 # Thu Jul 22 20:08:58 2021 -0400 # Node ID 07e3fba9b812e8d27a3acff5339984ac2d8b4c6c # Parent 5a044ece3c8868a2cf51755f358ab6ad2ae07359 Fixed dead spectators not spawning where they died if sv_samespawnspot is enabled. diff -r 5a044ece3c88 -r 07e3fba9b812 docs/zandronum-history.txt --- a/docs/zandronum-history.txt Thu Jul 22 19:54:24 2021 -0400 +++ b/docs/zandronum-history.txt Thu Jul 22 20:08:58 2021 -0400 @@ -90,6 +90,7 @@ - - Fixed "####" and "----" in PlayerPawns. [Zandrewnum] - - Fixed dormant sounds from still playing upon resetting the map. [Kaminsky] - - Fixed a player's old body from being frozen and not finishing their animation when they become a dead spectator. [Kaminsky] +- - Fixed dead spectators not spawning where they died if sv_samespawnspot is enabled. [Kaminsky] ! - sv_forcegldefaults renamed to sv_forcevideodefaults. The old name still exists for compatibility. [Dusk] ! - r_3dfloors is now forced to be true when sv_forcevideodefaults is true. [Dusk] ! - When the wad authentication fails for a connecting client, the client only reports the missing and incompatible PWADS instead of all of them. [Pol Marcet] diff -r 5a044ece3c88 -r 07e3fba9b812 src/cl_main.cpp --- a/src/cl_main.cpp Thu Jul 22 19:54:24 2021 -0400 +++ b/src/cl_main.cpp Thu Jul 22 20:08:58 2021 -0400 @@ -3088,10 +3088,7 @@ pPlayer->ulPing = 0; pPlayer->ulPingAverages = 0; pPlayer->bReadyToGoOn = 0; - pPlayer->bSpawnOkay = 0; - pPlayer->SpawnX = 0; - pPlayer->SpawnY = 0; - pPlayer->SpawnAngle = 0; + pPlayer->pCorpse = NULL; pPlayer->OldPendingWeapon = 0; pPlayer->bLagging = 0; pPlayer->bSpawnTelefragged = 0; diff -r 5a044ece3c88 -r 07e3fba9b812 src/d_player.h --- a/src/d_player.h Thu Jul 22 19:54:24 2021 -0400 +++ b/src/d_player.h Thu Jul 22 20:08:58 2021 -0400 @@ -692,13 +692,8 @@ // Is this player ready for the next map? (intermission) bool bReadyToGoOn; - // Is it alright to respawn in the same spot we died? (same spawn spot dmflag) - bool bSpawnOkay; - - // Position/angle we died at. This is for the same spawn spot dmflag. - fixed_t SpawnX; - fixed_t SpawnY; - angle_t SpawnAngle; + // [AK] Pointer to our corpse in case we became a dead spectator. This is in case DF2_SAME_SPAWN_SPOT is enabled. + AActor *pCorpse; // Save the old pending weapon. If the current one differs, update some clients. AWeapon *OldPendingWeapon; diff -r 5a044ece3c88 -r 07e3fba9b812 src/p_interaction.cpp --- a/src/p_interaction.cpp Thu Jul 22 19:54:24 2021 -0400 +++ b/src/p_interaction.cpp Thu Jul 22 20:08:58 2021 -0400 @@ -741,12 +741,6 @@ player->pSkullBot->PostEvent( BOTEVENT_KILLED_BYENVIORNMENT ); } - // [BC] Keep track of where we died for the "same spot respawn" dmflags. - player->SpawnX = x; - player->SpawnY = y; - player->SpawnAngle = angle; - player->bSpawnOkay = true; - // Death script execution, care of Skull Tag FBehavior::StaticStartTypedScripts (SCRIPT_Death, this, true); @@ -775,10 +769,6 @@ if (!source) { PLAYER_SetFragcount( player, player->fragcount - (( bPossessedTerminatorArtifact ) ? 10 : 1 ), true, true ); // [RH] Cumulative frag count - - // Spawning in nukage or getting crushed is NOT - // somewhere where you would want to be at when you respawn again - player->bSpawnOkay = false; } // [BC] Increment team deathcount. @@ -2614,9 +2604,11 @@ pOldBody = pPlayer->mo; // [BB] This also transfers the inventory from the old to the new body. players[pPlayer - players].playerstate = ( zadmflags & ZADF_DEAD_PLAYERS_CAN_KEEP_INVENTORY ) ? PST_REBORN : PST_REBORNNOINVENTORY; - const bool bSpawnOkay = pPlayer->bSpawnOkay; // [EP] Save the same-spot spawn information, since it'll be lost when GAMEMODE_SpawnPlayer is called. GAMEMODE_SpawnPlayer( pPlayer - players ); - pPlayer->bSpawnOkay = bSpawnOkay; // [EP] + + // [AK] Remember our old body when we become a dead spectator. This is so we can respawn back + // at our corpse in case DF2_SAME_SPAWN_SPOT is enabled. + pPlayer->pCorpse = pOldBody; // Set the player's new body to the position of his or her old body. if (( pPlayer->mo ) && @@ -3254,6 +3246,9 @@ // [BB] Clear the players medals and the medal related counters. The former is something also clients need to do. memset( players[ulPlayer].ulMedalCount, 0, sizeof( ULONG ) * NUM_MEDALS ); PLAYER_ResetSpecialCounters ( &players[ulPlayer] ); + + // [AK] We have no more use for our corpse since we left the game. + players[ulPlayer].pCorpse = NULL; } //***************************************************************************** @@ -3330,11 +3325,13 @@ // bool PLAYER_CanRespawnWhereDied( player_t *pPlayer ) { + AActor *mo = pPlayer->pCorpse ? pPlayer->pCorpse : pPlayer->mo; + // [AK] The player shouldn't respawn in any sectors that have damaging floors. - if (( pPlayer->mo->Sector->damage > 0 ) || ( Terrains[P_GetThingFloorType( pPlayer->mo )].DamageAmount > 0 )) + if (( mo->Sector->damage > 0 ) || ( Terrains[P_GetThingFloorType( mo )].DamageAmount > 0 )) return false; - switch ( pPlayer->mo->Sector->special ) + switch ( mo->Sector->special ) { case dLight_Strobe_Hurt: case dDamage_Hellslime: @@ -3352,11 +3349,11 @@ } // [AK] Don't respawn the player in an instant death sector. Taken directly from P_PlayerSpawn. - if (( pPlayer->mo->Sector->Flags & SECF_NORESPAWN ) || (( pPlayer->mo->Sector->special & 255 ) == Damage_InstantDeath )) + if (( mo->Sector->Flags & SECF_NORESPAWN ) || (( mo->Sector->special & 255 ) == Damage_InstantDeath )) return false; // [AK] Make sure they're not going to be blocked by anything upon respawning where they died. - AActor *temp = Spawn( pPlayer->cls->TypeName.GetChars( ), pPlayer->mo->x, pPlayer->mo->y, pPlayer->mo->z, NO_REPLACE ); + AActor *temp = Spawn( pPlayer->cls->TypeName.GetChars( ), mo->x, mo->y, mo->z, NO_REPLACE ); bool bCanSpawn = P_TestMobjLocation( temp ); temp->Destroy( ); @@ -3370,7 +3367,7 @@ // through all ceilings crushers and see if one is connected to the sector the player's body is in. while (( pCeiling = CeilingIterator.Next( )) != NULL ) { - if (( pCeiling->GetSector( ) == pPlayer->mo->Sector ) && ( pCeiling->GetCrush( ) > -1 )) + if (( pCeiling->GetSector( ) == mo->Sector ) && ( pCeiling->GetCrush( ) > -1 )) return false; } @@ -3380,7 +3377,7 @@ // [AK] Next, check all the floor crushers. while (( pFloor = FloorIterator.Next( )) != NULL ) { - if (( pFloor->GetSector( ) == pPlayer->mo->Sector ) && ( pFloor->GetCrush( ) > -1 )) + if (( pFloor->GetSector( ) == mo->Sector ) && ( pFloor->GetCrush( ) > -1 )) return false; } diff -r 5a044ece3c88 -r 07e3fba9b812 src/p_mobj.cpp --- a/src/p_mobj.cpp Thu Jul 22 19:54:24 2021 -0400 +++ b/src/p_mobj.cpp Thu Jul 22 20:08:58 2021 -0400 @@ -5419,18 +5419,22 @@ p->cls = PlayerClasses[p->CurrentPlayerClass].Type; } + // [AK] Make sure we can still respawn at our corpse if we're a dead spectator. This isn't always + // the same body that we're still using! + AActor *mo = p->pCorpse ? p->pCorpse : p->mo; + if (( dmflags2 & DF2_SAME_SPAWN_SPOT ) && (( p->playerstate == PST_REBORN ) || ( p->playerstate == PST_REBORNNOINVENTORY )) && ( deathmatch == false ) && ( teamgame == false ) && ( gameaction != ga_worlddone ) && - ( p->mo != NULL ) && + ( mo != NULL ) && // [AK] Moved the SECF_NORESPAWN and Damage_InstantDeath checks into PLAYER_CanRespawnWhereDied. ( PLAYER_CanRespawnWhereDied( p ))) { - spawn_x = p->mo->x; - spawn_y = p->mo->y; - spawn_angle = p->mo->angle; + spawn_x = mo->x; + spawn_y = mo->y; + spawn_angle = mo->angle; } else { @@ -5843,6 +5847,9 @@ if (( p->bSpectating ) && ( oldactor != NULL ) && ( oldactor->player == p )) oldactor->player = NULL; + // [AK] We've spawned now, so we don't need to remember our corpse anymore. + p->pCorpse = NULL; + return mobj; } diff -r 5a044ece3c88 -r 07e3fba9b812 src/p_user.cpp --- a/src/p_user.cpp Thu Jul 22 19:54:24 2021 -0400 +++ b/src/p_user.cpp Thu Jul 22 20:08:58 2021 -0400 @@ -349,10 +349,7 @@ ulPing( 0 ), ulPingAverages( 0 ), bReadyToGoOn( 0 ), - bSpawnOkay( 0 ), - SpawnX( 0 ), - SpawnY( 0 ), - SpawnAngle( 0 ), + pCorpse( 0 ), OldPendingWeapon( 0 ), bLagging( 0 ), bSpawnTelefragged( 0 ), @@ -517,10 +514,7 @@ ulPing = p.ulPing; ulPingAverages = p.ulPingAverages; bReadyToGoOn = p.bReadyToGoOn; - bSpawnOkay = p.bSpawnOkay; - SpawnX = p.SpawnX; - SpawnY = p.SpawnY; - SpawnAngle = p.SpawnAngle; + pCorpse = p.pCorpse; OldPendingWeapon = p.OldPendingWeapon; StartingWeaponName = p.StartingWeaponName; bClientSelectedWeapon = p.bClientSelectedWeapon;