- made most of the player spawn spot handliing functions members of FLevelLocals.

This commit is contained in:
Christoph Oelckers 2019-01-28 02:44:05 +01:00
parent 0ef0698d24
commit 66695ac6a0
11 changed files with 84 additions and 70 deletions

View file

@ -417,7 +417,7 @@ bool FCajunMaster::DoAddBot (uint8_t *info, botskill_t skill)
else else
Printf ("%s joined the game\n", players[bnum].userinfo.GetName()); Printf ("%s joined the game\n", players[bnum].userinfo.GetName());
G_DoReborn (bnum, true); level.DoReborn (bnum, true);
return true; return true;
} }

View file

@ -667,6 +667,6 @@ CCMD(fpuke)
} }
else else
{ {
T_RunScript(currentUILevel, atoi(argv[1]), players[consoleplayer].mo); T_RunScript(players[consoleplayer].mo->Level, atoi(argv[1]), players[consoleplayer].mo);
} }
} }

View file

@ -1014,7 +1014,7 @@ void G_Ticker ()
} }
if (players[i].playerstate == PST_REBORN || players[i].playerstate == PST_ENTER) if (players[i].playerstate == PST_REBORN || players[i].playerstate == PST_ENTER)
{ {
G_DoReborn(i, false); level.DoReborn(i, false);
} }
} }
} }
@ -1241,7 +1241,7 @@ void G_PlayerFinishLevel (int player, EFinishLevelType mode, int flags)
// Called after a player dies // Called after a player dies
// almost everything is cleared and initialized // almost everything is cleared and initialized
// //
void G_PlayerReborn (int player) void FLevelLocals::PlayerReborn (int player)
{ {
player_t* p; player_t* p;
int frags[MAXPLAYERS]; int frags[MAXPLAYERS];
@ -1325,7 +1325,7 @@ void G_PlayerReborn (int player)
// because something is occupying it // because something is occupying it
// //
bool G_CheckSpot (int playernum, FPlayerStart *mthing) bool FLevelLocals::CheckSpot (int playernum, FPlayerStart *mthing)
{ {
DVector3 spot; DVector3 spot;
double oldz; double oldz;
@ -1335,7 +1335,7 @@ bool G_CheckSpot (int playernum, FPlayerStart *mthing)
spot = mthing->pos; spot = mthing->pos;
if (!(level.flags & LEVEL_USEPLAYERSTARTZ)) if (!(flags & LEVEL_USEPLAYERSTARTZ))
{ {
spot.Z = 0; spot.Z = 0;
} }
@ -1377,7 +1377,7 @@ bool G_CheckSpot (int playernum, FPlayerStart *mthing)
// //
// [RH] Returns the distance of the closest player to the given mapthing // [RH] Returns the distance of the closest player to the given mapthing
static double PlayersRangeFromSpot (FPlayerStart *spot) double FLevelLocals::PlayersRangeFromSpot (FPlayerStart *spot)
{ {
double closest = INT_MAX; double closest = INT_MAX;
double distance; double distance;
@ -1398,7 +1398,7 @@ static double PlayersRangeFromSpot (FPlayerStart *spot)
} }
// [RH] Select the deathmatch spawn spot farthest from everyone. // [RH] Select the deathmatch spawn spot farthest from everyone.
static FPlayerStart *SelectFarthestDeathmatchSpot (size_t selections) FPlayerStart *FLevelLocals::SelectFarthestDeathmatchSpot (size_t selections)
{ {
double bestdistance = 0; double bestdistance = 0;
FPlayerStart *bestspot = NULL; FPlayerStart *bestspot = NULL;
@ -1406,7 +1406,7 @@ static FPlayerStart *SelectFarthestDeathmatchSpot (size_t selections)
for (i = 0; i < selections; i++) for (i = 0; i < selections; i++)
{ {
double distance = PlayersRangeFromSpot (&level.deathmatchstarts[i]); double distance = PlayersRangeFromSpot (&deathmatchstarts[i]);
if (distance > bestdistance) if (distance > bestdistance)
{ {
@ -1419,27 +1419,27 @@ static FPlayerStart *SelectFarthestDeathmatchSpot (size_t selections)
} }
// [RH] Select a deathmatch spawn spot at random (original mechanism) // [RH] Select a deathmatch spawn spot at random (original mechanism)
static FPlayerStart *SelectRandomDeathmatchSpot (int playernum, unsigned int selections) FPlayerStart *FLevelLocals::SelectRandomDeathmatchSpot (int playernum, unsigned int selections)
{ {
unsigned int i, j; unsigned int i, j;
for (j = 0; j < 20; j++) for (j = 0; j < 20; j++)
{ {
i = pr_dmspawn() % selections; i = pr_dmspawn() % selections;
if (G_CheckSpot (playernum, &level.deathmatchstarts[i]) ) if (CheckSpot (playernum, &level.deathmatchstarts[i]) )
{ {
return &level.deathmatchstarts[i]; return &deathmatchstarts[i];
} }
} }
// [RH] return a spot anyway, since we allow telefragging when a player spawns // [RH] return a spot anyway, since we allow telefragging when a player spawns
return &level.deathmatchstarts[i]; return &deathmatchstarts[i];
} }
DEFINE_ACTION_FUNCTION(DObject, G_PickDeathmatchStart) DEFINE_ACTION_FUNCTION(FLevelLocals, PickDeathmatchStart)
{ {
PARAM_PROLOGUE; PARAM_SELF_STRUCT_PROLOGUE(FLevelLocals);
unsigned int selections = level.deathmatchstarts.Size(); unsigned int selections = self->deathmatchstarts.Size();
DVector3 pos; DVector3 pos;
int angle; int angle;
if (selections == 0) if (selections == 0)
@ -1450,8 +1450,8 @@ DEFINE_ACTION_FUNCTION(DObject, G_PickDeathmatchStart)
else else
{ {
unsigned int i = pr_dmspawn() % selections; unsigned int i = pr_dmspawn() % selections;
angle = level.deathmatchstarts[i].angle; angle = self->deathmatchstarts[i].angle;
pos = level.deathmatchstarts[i].pos; pos = self->deathmatchstarts[i].pos;
} }
if (numret > 1) if (numret > 1)
@ -1466,12 +1466,12 @@ DEFINE_ACTION_FUNCTION(DObject, G_PickDeathmatchStart)
return numret; return numret;
} }
void G_DeathMatchSpawnPlayer (int playernum) void FLevelLocals::DeathMatchSpawnPlayer (int playernum)
{ {
unsigned int selections; unsigned int selections;
FPlayerStart *spot; FPlayerStart *spot;
selections = level.deathmatchstarts.Size (); selections = deathmatchstarts.Size ();
// [RH] We can get by with just 1 deathmatch start // [RH] We can get by with just 1 deathmatch start
if (selections < 1) if (selections < 1)
I_Error ("No deathmatch starts"); I_Error ("No deathmatch starts");
@ -1488,17 +1488,17 @@ void G_DeathMatchSpawnPlayer (int playernum)
{ // No good spot, so the player will probably get stuck. { // No good spot, so the player will probably get stuck.
// We were probably using select farthest above, and all // We were probably using select farthest above, and all
// the spots were taken. // the spots were taken.
spot = G_PickPlayerStart(playernum, PPS_FORCERANDOM); spot = PickPlayerStart(playernum, PPS_FORCERANDOM);
if (!G_CheckSpot(playernum, spot)) if (!CheckSpot(playernum, spot))
{ // This map doesn't have enough coop spots for this player { // This map doesn't have enough coop spots for this player
// to use one. // to use one.
spot = SelectRandomDeathmatchSpot(playernum, selections); spot = SelectRandomDeathmatchSpot(playernum, selections);
if (spot == NULL) if (spot == NULL)
{ // We have a player 1 start, right? { // We have a player 1 start, right?
spot = &level.playerstarts[0]; spot = &playerstarts[0];
if (spot->type == 0) if (spot->type == 0)
{ // Fine, whatever. { // Fine, whatever.
spot = &level.deathmatchstarts[0]; spot = &deathmatchstarts[0];
} }
} }
} }
@ -1511,15 +1511,15 @@ void G_DeathMatchSpawnPlayer (int playernum)
// //
// G_PickPlayerStart // G_PickPlayerStart
// //
FPlayerStart *G_PickPlayerStart(int playernum, int flags) FPlayerStart *FLevelLocals::PickPlayerStart(int playernum, int flags)
{ {
if (level.AllPlayerStarts.Size() == 0) // No starts to pick if (AllPlayerStarts.Size() == 0) // No starts to pick
{ {
return NULL; return NULL;
} }
if ((level.flags2 & LEVEL2_RANDOMPLAYERSTARTS) || (flags & PPS_FORCERANDOM) || if ((flags2 & LEVEL2_RANDOMPLAYERSTARTS) || (flags & PPS_FORCERANDOM) ||
level.playerstarts[playernum].type == 0) playerstarts[playernum].type == 0)
{ {
if (!(flags & PPS_NOBLOCKINGCHECK)) if (!(flags & PPS_NOBLOCKINGCHECK))
{ {
@ -1529,9 +1529,9 @@ FPlayerStart *G_PickPlayerStart(int playernum, int flags)
// Find all unblocked player starts. // Find all unblocked player starts.
for (i = 0; i < level.AllPlayerStarts.Size(); ++i) for (i = 0; i < level.AllPlayerStarts.Size(); ++i)
{ {
if (G_CheckSpot(playernum, &level.AllPlayerStarts[i])) if (CheckSpot(playernum, &AllPlayerStarts[i]))
{ {
good_starts.Push(&level.AllPlayerStarts[i]); good_starts.Push(&AllPlayerStarts[i]);
} }
} }
if (good_starts.Size() > 0) if (good_starts.Size() > 0)
@ -1540,17 +1540,17 @@ FPlayerStart *G_PickPlayerStart(int playernum, int flags)
} }
} }
// Pick a spot at random, whether it's open or not. // Pick a spot at random, whether it's open or not.
return &level.AllPlayerStarts[pr_pspawn(level.AllPlayerStarts.Size())]; return &level.AllPlayerStarts[pr_pspawn(AllPlayerStarts.Size())];
} }
return &level.playerstarts[playernum]; return &playerstarts[playernum];
} }
DEFINE_ACTION_FUNCTION(DObject, G_PickPlayerStart) DEFINE_ACTION_FUNCTION(FLevelLocals, PickPlayerStart)
{ {
PARAM_PROLOGUE; PARAM_SELF_STRUCT_PROLOGUE(FLevelLocals);
PARAM_INT(playernum); PARAM_INT(playernum);
PARAM_INT(flags); PARAM_INT(flags);
auto ps = G_PickPlayerStart(playernum, flags); auto ps = self->PickPlayerStart(playernum, flags);
if (numret > 1) if (numret > 1)
{ {
ret[1].SetInt(ps? ps->angle : 0); ret[1].SetInt(ps? ps->angle : 0);
@ -1566,23 +1566,24 @@ DEFINE_ACTION_FUNCTION(DObject, G_PickPlayerStart)
// //
// G_QueueBody // G_QueueBody
// //
static void G_QueueBody (AActor *body) void FLevelLocals::QueueBody (AActor *body)
{ {
// flush an old corpse if needed // flush an old corpse if needed
int modslot = level.bodyqueslot%level.BODYQUESIZE; int modslot = bodyqueslot%level.BODYQUESIZE;
level.bodyqueslot = modslot + 1; bodyqueslot = modslot + 1;
if (level.bodyqueslot >= level.BODYQUESIZE && level.bodyque[modslot] != NULL) if (bodyqueslot >= BODYQUESIZE && bodyque[modslot] != NULL)
{ {
level.bodyque[modslot]->Destroy (); bodyque[modslot]->Destroy ();
} }
level.bodyque[modslot] = body; bodyque[modslot] = body;
// Copy the player's translation, so that if they change their color later, only // Copy the player's translation, so that if they change their color later, only
// their current body will change and not all their old corpses. // their current body will change and not all their old corpses.
if (GetTranslationType(body->Translation) == TRANSLATION_Players || if (GetTranslationType(body->Translation) == TRANSLATION_Players ||
GetTranslationType(body->Translation) == TRANSLATION_PlayersExtra) GetTranslationType(body->Translation) == TRANSLATION_PlayersExtra)
{ {
// This needs to be able to handle multiple levels, in case a level with dead players is used as a secondary one later.
*translationtables[TRANSLATION_PlayerCorpses][modslot] = *TranslationToTable(body->Translation); *translationtables[TRANSLATION_PlayerCorpses][modslot] = *TranslationToTable(body->Translation);
body->Translation = TRANSLATION(TRANSLATION_PlayerCorpses,modslot); body->Translation = TRANSLATION(TRANSLATION_PlayerCorpses,modslot);
translationtables[TRANSLATION_PlayerCorpses][modslot]->UpdateNative(); translationtables[TRANSLATION_PlayerCorpses][modslot]->UpdateNative();
@ -1606,9 +1607,9 @@ static void G_QueueBody (AActor *body)
// G_DoReborn // G_DoReborn
// //
EXTERN_CVAR(Bool, sv_singleplayerrespawn) EXTERN_CVAR(Bool, sv_singleplayerrespawn)
void G_DoReborn (int playernum, bool freshbot) void FLevelLocals::DoReborn (int playernum, bool freshbot)
{ {
if (!multiplayer && !(level.flags2 & LEVEL2_ALLOWRESPAWN) && !sv_singleplayerrespawn && if (!multiplayer && !(flags2 & LEVEL2_ALLOWRESPAWN) && !sv_singleplayerrespawn &&
!G_SkillProperty(SKILLP_PlayerRespawn)) !G_SkillProperty(SKILLP_PlayerRespawn))
{ {
if (BackupSaveName.Len() > 0 && FileExists (BackupSaveName.GetChars())) if (BackupSaveName.Len() > 0 && FileExists (BackupSaveName.GetChars()))
@ -1633,27 +1634,27 @@ void G_DoReborn (int playernum, bool freshbot)
// first disassociate the corpse // first disassociate the corpse
if (players[playernum].mo) if (players[playernum].mo)
{ {
G_QueueBody (players[playernum].mo); QueueBody (players[playernum].mo);
players[playernum].mo->player = NULL; players[playernum].mo->player = NULL;
} }
// spawn at random spot if in deathmatch // spawn at random spot if in deathmatch
if ((deathmatch || isUnfriendly) && (level.deathmatchstarts.Size () > 0)) if ((deathmatch || isUnfriendly) && (deathmatchstarts.Size () > 0))
{ {
G_DeathMatchSpawnPlayer (playernum); DeathMatchSpawnPlayer (playernum);
return; return;
} }
if (!(level.flags2 & LEVEL2_RANDOMPLAYERSTARTS) && if (!(flags2 & LEVEL2_RANDOMPLAYERSTARTS) &&
level.playerstarts[playernum].type != 0 && playerstarts[playernum].type != 0 &&
G_CheckSpot (playernum, &level.playerstarts[playernum])) CheckSpot (playernum, &playerstarts[playernum]))
{ {
AActor *mo = P_SpawnPlayer(&level.playerstarts[playernum], playernum); AActor *mo = P_SpawnPlayer(&playerstarts[playernum], playernum);
if (mo != NULL) P_PlayerStartStomp(mo, true); if (mo != NULL) P_PlayerStartStomp(mo, true);
} }
else else
{ // try to spawn at any random player's spot { // try to spawn at any random player's spot
FPlayerStart *start = G_PickPlayerStart(playernum, PPS_FORCERANDOM); FPlayerStart *start = PickPlayerStart(playernum, PPS_FORCERANDOM);
AActor *mo = P_SpawnPlayer(start, playernum); AActor *mo = P_SpawnPlayer(start, playernum);
if (mo != NULL) P_PlayerStartStomp(mo, true); if (mo != NULL) P_PlayerStartStomp(mo, true);
} }

View file

@ -38,9 +38,6 @@ class AActor;
// //
// GAME // GAME
// //
void G_DeathMatchSpawnPlayer (int playernum);
struct FPlayerStart *G_PickPlayerStart (int playernum, int flags = 0);
enum enum
{ {
PPS_FORCERANDOM = 1, PPS_FORCERANDOM = 1,
@ -89,7 +86,6 @@ enum EFinishLevelType
void G_PlayerFinishLevel (int player, EFinishLevelType mode, int flags); void G_PlayerFinishLevel (int player, EFinishLevelType mode, int flags);
void G_DoReborn (int playernum, bool freshbot);
void G_DoPlayerPop(int playernum); void G_DoPlayerPop(int playernum);
// Adds pitch to consoleplayer's viewpitch and clamps it // Adds pitch to consoleplayer's viewpitch and clamps it

View file

@ -693,7 +693,7 @@ void G_ChangeLevel(const char *levelname, int position, int flags, int nextSkill
player->mo->special1 = 0; player->mo->special1 = 0;
} }
// ]] // ]]
G_DoReborn(i, false); level.DoReborn(i, false);
} }
} }
} }
@ -1360,7 +1360,7 @@ int G_FinishTravel ()
pawndup = pawn->player->mo; pawndup = pawn->player->mo;
assert (pawn != pawndup); assert (pawn != pawndup);
start = G_PickPlayerStart(pnum, 0); start = level.PickPlayerStart(pnum, 0);
if (start == NULL) if (start == NULL)
{ {
if (pawndup != nullptr) if (pawndup != nullptr)

View file

@ -262,6 +262,17 @@ public:
void SpawnExtraPlayers(); void SpawnExtraPlayers();
void Serialize(FSerializer &arc, bool hubload); void Serialize(FSerializer &arc, bool hubload);
// g_Game
void PlayerReborn (int player);
bool CheckSpot (int playernum, FPlayerStart *mthing);
void DoReborn (int playernum, bool freshbot);
void QueueBody (AActor *body);
double PlayersRangeFromSpot (FPlayerStart *spot);
FPlayerStart *SelectFarthestDeathmatchSpot (size_t selections);
FPlayerStart *SelectRandomDeathmatchSpot (int playernum, unsigned int selections);
void DeathMatchSpawnPlayer (int playernum);
FPlayerStart *PickPlayerStart(int playernum, int flags = 0);
private: private:
// Work data for CollectConnectedGroups. // Work data for CollectConnectedGroups.

View file

@ -109,8 +109,6 @@
// EXTERNAL FUNCTION PROTOTYPES -------------------------------------------- // EXTERNAL FUNCTION PROTOTYPES --------------------------------------------
void G_PlayerReborn (int player);
// PRIVATE FUNCTION PROTOTYPES --------------------------------------------- // PRIVATE FUNCTION PROTOTYPES ---------------------------------------------
static void PlayerLandedOnThing (AActor *mo, AActor *onmobj); static void PlayerLandedOnThing (AActor *mo, AActor *onmobj);
@ -4999,7 +4997,7 @@ AActor *FLevelLocals::SpawnPlayer (FPlayerStart *mthing, int playernum, int flag
state = p->playerstate; state = p->playerstate;
if (state == PST_REBORN || state == PST_ENTER) if (state == PST_REBORN || state == PST_ENTER)
{ {
G_PlayerReborn (playernum); PlayerReborn (playernum);
} }
else if (oldactor != NULL && oldactor->player == p && !(flags & SPF_TEMPPLAYER)) else if (oldactor != NULL && oldactor->player == p && !(flags & SPF_TEMPPLAYER))
{ {

View file

@ -445,7 +445,7 @@ void P_SetupLevel(FLevelLocals *Level, int position, bool newGame)
if (playeringame[i]) if (playeringame[i])
{ {
players[i].mo = nullptr; players[i].mo = nullptr;
G_DeathMatchSpawnPlayer(i); Level->DeathMatchSpawnPlayer(i);
} }
} }
} }
@ -457,7 +457,7 @@ void P_SetupLevel(FLevelLocals *Level, int position, bool newGame)
if (playeringame[i]) if (playeringame[i])
{ {
players[i].mo = nullptr; players[i].mo = nullptr;
FPlayerStart *mthing = G_PickPlayerStart(i); FPlayerStart *mthing = Level->PickPlayerStart(i);
P_SpawnPlayer(mthing, i, (Level->flags2 & LEVEL2_PRERAISEWEAPON) ? SPF_WEAPONFULLYUP : 0); P_SpawnPlayer(mthing, i, (Level->flags2 & LEVEL2_PRERAISEWEAPON) ? SPF_WEAPONFULLYUP : 0);
} }
} }
@ -474,7 +474,7 @@ void P_SetupLevel(FLevelLocals *Level, int position, bool newGame)
if (!(players[i].mo->flags & MF_FRIENDLY)) if (!(players[i].mo->flags & MF_FRIENDLY))
{ {
AActor * oldSpawn = players[i].mo; AActor * oldSpawn = players[i].mo;
G_DeathMatchSpawnPlayer(i); Level->DeathMatchSpawnPlayer(i);
oldSpawn->Destroy(); oldSpawn->Destroy();
} }
} }

View file

@ -400,8 +400,14 @@ class Object native
native static String G_SkillName(); native static String G_SkillName();
native static int G_SkillPropertyInt(int p); native static int G_SkillPropertyInt(int p);
native static double G_SkillPropertyFloat(int p); native static double G_SkillPropertyFloat(int p);
native static vector3, int G_PickDeathmatchStart(); deprecated("3.8") static vector3, int G_PickDeathmatchStart()
native static vector3, int G_PickPlayerStart(int pnum, int flags = 0); {
return level.PickDeathmatchStart();
}
deprecated("3.8") static vector3, int G_PickPlayerStart(int pnum, int flags = 0)
{
return level.PickPlayerStart(pnum, flags);
}
native static void S_Sound (Sound sound_id, int channel, float volume = 1, float attenuation = ATTN_NORM); native static void S_Sound (Sound sound_id, int channel, float volume = 1, float attenuation = ATTN_NORM);
native static void S_PauseSound (bool notmusic, bool notsfx); native static void S_PauseSound (bool notmusic, bool notsfx);
native static void S_ResumeSound (bool notsfx); native static void S_ResumeSound (bool notsfx);
@ -703,6 +709,8 @@ struct LevelLocals native
native int FindUniqueTid(int start = 0, int limit = 0); native int FindUniqueTid(int start = 0, int limit = 0);
native uint GetSkyboxPortal(Actor actor); native uint GetSkyboxPortal(Actor actor);
native void ReplaceTextures(String from, String to, int flags); native void ReplaceTextures(String from, String to, int flags);
native vector3, int PickDeathmatchStart();
native vector3, int PickPlayerStart(int pnum, int flags = 0);
native static clearscope bool IsPointInMap(vector3 p); native static clearscope bool IsPointInMap(vector3 p);

View file

@ -157,12 +157,12 @@ class TelOtherFX1 : Actor
// //
//=========================================================================== //===========================================================================
private static void P_TeleportToPlayerStarts (Actor victim) private void P_TeleportToPlayerStarts (Actor victim)
{ {
Vector3 dest; Vector3 dest;
double destAngle; double destAngle;
[dest, destAngle] = G_PickPlayerStart(0, PPS_FORCERANDOM | PPS_NOBLOCKINGCHECK); [dest, destAngle] = level.PickPlayerStart(0, PPS_FORCERANDOM | PPS_NOBLOCKINGCHECK);
dest.Z = ONFLOORZ; dest.Z = ONFLOORZ;
victim.Teleport ((dest.xy, ONFLOORZ), destangle, TELF_SOURCEFOG | TELF_DESTFOG); victim.Teleport ((dest.xy, ONFLOORZ), destangle, TELF_SOURCEFOG | TELF_DESTFOG);
} }
@ -178,7 +178,7 @@ class TelOtherFX1 : Actor
Vector3 dest; Vector3 dest;
double destAngle; double destAngle;
[dest, destAngle] = G_PickDeathmatchStart(); [dest, destAngle] = level.PickDeathmatchStart();
if (destAngle < 65536) victim.Teleport((dest.xy, ONFLOORZ), destangle, TELF_SOURCEFOG | TELF_DESTFOG); if (destAngle < 65536) victim.Teleport((dest.xy, ONFLOORZ), destangle, TELF_SOURCEFOG | TELF_DESTFOG);
else P_TeleportToPlayerStarts(victim); else P_TeleportToPlayerStarts(victim);
} }

View file

@ -30,11 +30,11 @@ class ArtiTeleport : Inventory
if (deathmatch) if (deathmatch)
{ {
[dest, destAngle] = G_PickDeathmatchStart(); [dest, destAngle] = level.PickDeathmatchStart();
} }
else else
{ {
[dest, destAngle] = G_PickPlayerStart(Owner.PlayerNumber()); [dest, destAngle] = level.PickPlayerStart(Owner.PlayerNumber());
} }
dest.Z = ONFLOORZ; dest.Z = ONFLOORZ;
Owner.Teleport (dest, destAngle, TELF_SOURCEFOG | TELF_DESTFOG); Owner.Teleport (dest, destAngle, TELF_SOURCEFOG | TELF_DESTFOG);