diff --git a/src/d_clisrv.c b/src/d_clisrv.c index d5023265f..fc365a85b 100644 --- a/src/d_clisrv.c +++ b/src/d_clisrv.c @@ -2775,20 +2775,36 @@ void CL_ClearPlayer(INT32 playernum) K_RemoveFollower(&players[playernum]); } - if (players[playernum].mo) - { - P_RemoveMobj(players[playernum].mo); - P_SetTarget(&players[playernum].mo, NULL); +#define PlayerPointerRemove(field) \ + if (field) \ + { \ + P_RemoveMobj(field); \ + P_SetTarget(&field, NULL); \ } + // These are mostly subservient to the player, and may not clean themselves up. + PlayerPointerRemove(players[playernum].mo); + PlayerPointerRemove(players[playernum].followmobj); + PlayerPointerRemove(players[playernum].stumbleIndicator); + PlayerPointerRemove(players[playernum].sliptideZipIndicator); + +#undef PlayerPointerRemove + + // These have thinkers of their own. + P_SetTarget(&players[playernum].whip, NULL); + P_SetTarget(&players[playernum].hand, NULL); + P_SetTarget(&players[playernum].hoverhyudoro, NULL); + P_SetTarget(&players[playernum].ringShooter, NULL); + + // TODO: Any better handling in store? + P_SetTarget(&players[playernum].flickyAttacker, NULL); + P_SetTarget(&players[playernum].powerup.flickyController, NULL); + + // These are camera items and possibly belong to multiple players. P_SetTarget(&players[playernum].skybox.viewpoint, NULL); P_SetTarget(&players[playernum].skybox.centerpoint, NULL); P_SetTarget(&players[playernum].awayview.mobj, NULL); - P_SetTarget(&players[playernum].followmobj, NULL); - P_SetTarget(&players[playernum].hoverhyudoro, NULL); - P_SetTarget(&players[playernum].stumbleIndicator, NULL); - P_SetTarget(&players[playernum].sliptideZipIndicator, NULL); - P_SetTarget(&players[playernum].ringShooter, NULL); + } // Handle parties. diff --git a/src/g_game.c b/src/g_game.c index 1280a8319..708479fbc 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -2455,10 +2455,8 @@ void G_PlayerReborn(INT32 player, boolean betweenmaps) INT32 followerskin; UINT16 followercolor; - mobj_t *follower; // old follower, will probably be removed by the time we're dead but you never know. - mobj_t *hoverhyudoro; - mobj_t *skyboxviewpoint; - mobj_t *skyboxcenterpoint; + mobj_t *ringShooter, *hoverhyudoro; + mobj_t *skyboxviewpoint, *skyboxcenterpoint; INT32 charflags; UINT32 followitem; @@ -2677,22 +2675,40 @@ void G_PlayerReborn(INT32 player, boolean betweenmaps) if (!betweenmaps) { - follower = players[player].follower; - P_SetTarget(&players[player].follower, NULL); - P_SetTarget(&players[player].awayview.mobj, NULL); - P_SetTarget(&players[player].stumbleIndicator, NULL); + K_RemoveFollower(&players[player]); + +#define PlayerPointerRemove(field) \ + if (field) \ + { \ + P_RemoveMobj(field); \ + P_SetTarget(&field, NULL); \ + } + + // These are mostly subservient to the player, and may not clean themselves up. + PlayerPointerRemove(players[player].followmobj); + PlayerPointerRemove(players[player].stumbleIndicator); + PlayerPointerRemove(players[player].sliptideZipIndicator); + +#undef PlayerPointerRemove + + // These will erase themselves. P_SetTarget(&players[player].whip, NULL); P_SetTarget(&players[player].hand, NULL); - P_SetTarget(&players[player].ringShooter, NULL); - P_SetTarget(&players[player].followmobj, NULL); + // TODO: Any better handling in store? + P_SetTarget(&players[player].awayview.mobj, NULL); + P_SetTarget(&players[player].flickyAttacker, NULL); + P_SetTarget(&players[player].powerup.flickyController, NULL); + + // The following pointers are safe to set directly, because the end goal should be refcount consistency before and after remanifestation. + ringShooter = players[player].ringShooter; hoverhyudoro = players[player].hoverhyudoro; skyboxviewpoint = players[player].skybox.viewpoint; skyboxcenterpoint = players[player].skybox.centerpoint; } else { - follower = hoverhyudoro = NULL; + ringShooter = hoverhyudoro = NULL; skyboxviewpoint = skyboxcenterpoint = NULL; } @@ -2769,9 +2785,8 @@ void G_PlayerReborn(INT32 player, boolean betweenmaps) if (saveroundconditions) memcpy(&p->roundconditions, &roundconditions, sizeof (p->roundconditions)); - if (follower) - P_RemoveMobj(follower); - + // See above comment about refcount consistency. + p->ringShooter = ringShooter; p->hoverhyudoro = hoverhyudoro; p->skybox.viewpoint = skyboxviewpoint; p->skybox.centerpoint = skyboxcenterpoint; diff --git a/src/k_kart.c b/src/k_kart.c index c1f793399..4f570f3b5 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -8065,9 +8065,6 @@ void K_KartPlayerThink(player_t *player, ticcmd_t *cmd) if (player->guardCooldown) player->guardCooldown--; - - if (player->whip && P_MobjWasRemoved(player->whip)) - P_SetTarget(&player->whip, NULL); if (player->startboost > 0 && onground == true) { @@ -8326,15 +8323,6 @@ void K_KartPlayerThink(player_t *player, ticcmd_t *cmd) player->tripwireState = TRIPSTATE_NONE; } - if (player->hand && P_MobjWasRemoved(player->hand)) - P_SetTarget(&player->hand, NULL); - - if (player->flickyAttacker && P_MobjWasRemoved(player->flickyAttacker)) - P_SetTarget(&player->flickyAttacker, NULL); - - if (player->powerup.flickyController && P_MobjWasRemoved(player->powerup.flickyController)) - P_SetTarget(&player->powerup.flickyController, NULL); - if (player->spectator == false) { K_KartEbrakeVisuals(player); diff --git a/src/p_user.c b/src/p_user.c index 74b5d6231..692eabdb0 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -4249,6 +4249,25 @@ void P_PlayerThink(player_t *player) player->playerstate = PST_DEAD; } + // Erasing invalid player pointers + { +#define PlayerPointerErase(field) \ + if (field && P_MobjWasRemoved(field)) \ + P_SetTarget(&field, NULL); \ + + PlayerPointerErase(player->followmobj); + PlayerPointerErase(player->stumbleIndicator); + PlayerPointerErase(player->sliptideZipIndicator); + PlayerPointerErase(player->whip); + PlayerPointerErase(player->hand); + PlayerPointerErase(player->ringShooter); + PlayerPointerErase(player->hoverhyudoro); + PlayerPointerErase(player->flickyAttacker); + PlayerPointerErase(player->powerup.flickyController); + +#undef PlayerPointerErase + } + player->old_drawangle = player->drawangle; P_TickAltView(&player->awayview);