- 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
Printf ("%s joined the game\n", players[bnum].userinfo.GetName());
G_DoReborn (bnum, true);
level.DoReborn (bnum, true);
return true;
}

View File

@ -667,6 +667,6 @@ CCMD(fpuke)
}
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)
{
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
// almost everything is cleared and initialized
//
void G_PlayerReborn (int player)
void FLevelLocals::PlayerReborn (int player)
{
player_t* p;
int frags[MAXPLAYERS];
@ -1325,7 +1325,7 @@ void G_PlayerReborn (int player)
// because something is occupying it
//
bool G_CheckSpot (int playernum, FPlayerStart *mthing)
bool FLevelLocals::CheckSpot (int playernum, FPlayerStart *mthing)
{
DVector3 spot;
double oldz;
@ -1335,7 +1335,7 @@ bool G_CheckSpot (int playernum, FPlayerStart *mthing)
spot = mthing->pos;
if (!(level.flags & LEVEL_USEPLAYERSTARTZ))
if (!(flags & LEVEL_USEPLAYERSTARTZ))
{
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
static double PlayersRangeFromSpot (FPlayerStart *spot)
double FLevelLocals::PlayersRangeFromSpot (FPlayerStart *spot)
{
double closest = INT_MAX;
double distance;
@ -1398,7 +1398,7 @@ static double PlayersRangeFromSpot (FPlayerStart *spot)
}
// [RH] Select the deathmatch spawn spot farthest from everyone.
static FPlayerStart *SelectFarthestDeathmatchSpot (size_t selections)
FPlayerStart *FLevelLocals::SelectFarthestDeathmatchSpot (size_t selections)
{
double bestdistance = 0;
FPlayerStart *bestspot = NULL;
@ -1406,7 +1406,7 @@ static FPlayerStart *SelectFarthestDeathmatchSpot (size_t selections)
for (i = 0; i < selections; i++)
{
double distance = PlayersRangeFromSpot (&level.deathmatchstarts[i]);
double distance = PlayersRangeFromSpot (&deathmatchstarts[i]);
if (distance > bestdistance)
{
@ -1419,27 +1419,27 @@ static FPlayerStart *SelectFarthestDeathmatchSpot (size_t selections)
}
// [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;
for (j = 0; j < 20; j++)
{
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
return &level.deathmatchstarts[i];
return &deathmatchstarts[i];
}
DEFINE_ACTION_FUNCTION(DObject, G_PickDeathmatchStart)
DEFINE_ACTION_FUNCTION(FLevelLocals, PickDeathmatchStart)
{
PARAM_PROLOGUE;
unsigned int selections = level.deathmatchstarts.Size();
PARAM_SELF_STRUCT_PROLOGUE(FLevelLocals);
unsigned int selections = self->deathmatchstarts.Size();
DVector3 pos;
int angle;
if (selections == 0)
@ -1450,8 +1450,8 @@ DEFINE_ACTION_FUNCTION(DObject, G_PickDeathmatchStart)
else
{
unsigned int i = pr_dmspawn() % selections;
angle = level.deathmatchstarts[i].angle;
pos = level.deathmatchstarts[i].pos;
angle = self->deathmatchstarts[i].angle;
pos = self->deathmatchstarts[i].pos;
}
if (numret > 1)
@ -1466,12 +1466,12 @@ DEFINE_ACTION_FUNCTION(DObject, G_PickDeathmatchStart)
return numret;
}
void G_DeathMatchSpawnPlayer (int playernum)
void FLevelLocals::DeathMatchSpawnPlayer (int playernum)
{
unsigned int selections;
FPlayerStart *spot;
selections = level.deathmatchstarts.Size ();
selections = deathmatchstarts.Size ();
// [RH] We can get by with just 1 deathmatch start
if (selections < 1)
I_Error ("No deathmatch starts");
@ -1488,17 +1488,17 @@ void G_DeathMatchSpawnPlayer (int playernum)
{ // No good spot, so the player will probably get stuck.
// We were probably using select farthest above, and all
// the spots were taken.
spot = G_PickPlayerStart(playernum, PPS_FORCERANDOM);
if (!G_CheckSpot(playernum, spot))
spot = PickPlayerStart(playernum, PPS_FORCERANDOM);
if (!CheckSpot(playernum, spot))
{ // This map doesn't have enough coop spots for this player
// to use one.
spot = SelectRandomDeathmatchSpot(playernum, selections);
if (spot == NULL)
{ // We have a player 1 start, right?
spot = &level.playerstarts[0];
spot = &playerstarts[0];
if (spot->type == 0)
{ // Fine, whatever.
spot = &level.deathmatchstarts[0];
spot = &deathmatchstarts[0];
}
}
}
@ -1511,15 +1511,15 @@ void G_DeathMatchSpawnPlayer (int playernum)
//
// 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;
}
if ((level.flags2 & LEVEL2_RANDOMPLAYERSTARTS) || (flags & PPS_FORCERANDOM) ||
level.playerstarts[playernum].type == 0)
if ((flags2 & LEVEL2_RANDOMPLAYERSTARTS) || (flags & PPS_FORCERANDOM) ||
playerstarts[playernum].type == 0)
{
if (!(flags & PPS_NOBLOCKINGCHECK))
{
@ -1529,9 +1529,9 @@ FPlayerStart *G_PickPlayerStart(int playernum, int flags)
// Find all unblocked player starts.
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)
@ -1540,17 +1540,17 @@ FPlayerStart *G_PickPlayerStart(int playernum, int flags)
}
}
// 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(flags);
auto ps = G_PickPlayerStart(playernum, flags);
auto ps = self->PickPlayerStart(playernum, flags);
if (numret > 1)
{
ret[1].SetInt(ps? ps->angle : 0);
@ -1566,23 +1566,24 @@ DEFINE_ACTION_FUNCTION(DObject, G_PickPlayerStart)
//
// G_QueueBody
//
static void G_QueueBody (AActor *body)
void FLevelLocals::QueueBody (AActor *body)
{
// flush an old corpse if needed
int modslot = level.bodyqueslot%level.BODYQUESIZE;
level.bodyqueslot = modslot + 1;
int modslot = bodyqueslot%level.BODYQUESIZE;
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
// their current body will change and not all their old corpses.
if (GetTranslationType(body->Translation) == TRANSLATION_Players ||
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);
body->Translation = TRANSLATION(TRANSLATION_PlayerCorpses,modslot);
translationtables[TRANSLATION_PlayerCorpses][modslot]->UpdateNative();
@ -1606,9 +1607,9 @@ static void G_QueueBody (AActor *body)
// G_DoReborn
//
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))
{
if (BackupSaveName.Len() > 0 && FileExists (BackupSaveName.GetChars()))
@ -1633,27 +1634,27 @@ void G_DoReborn (int playernum, bool freshbot)
// first disassociate the corpse
if (players[playernum].mo)
{
G_QueueBody (players[playernum].mo);
QueueBody (players[playernum].mo);
players[playernum].mo->player = NULL;
}
// 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;
}
if (!(level.flags2 & LEVEL2_RANDOMPLAYERSTARTS) &&
level.playerstarts[playernum].type != 0 &&
G_CheckSpot (playernum, &level.playerstarts[playernum]))
if (!(flags2 & LEVEL2_RANDOMPLAYERSTARTS) &&
playerstarts[playernum].type != 0 &&
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);
}
else
{ // 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);
if (mo != NULL) P_PlayerStartStomp(mo, true);
}

View File

@ -38,9 +38,6 @@ class AActor;
//
// GAME
//
void G_DeathMatchSpawnPlayer (int playernum);
struct FPlayerStart *G_PickPlayerStart (int playernum, int flags = 0);
enum
{
PPS_FORCERANDOM = 1,
@ -89,7 +86,6 @@ enum EFinishLevelType
void G_PlayerFinishLevel (int player, EFinishLevelType mode, int flags);
void G_DoReborn (int playernum, bool freshbot);
void G_DoPlayerPop(int playernum);
// 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;
}
// ]]
G_DoReborn(i, false);
level.DoReborn(i, false);
}
}
}
@ -1360,7 +1360,7 @@ int G_FinishTravel ()
pawndup = pawn->player->mo;
assert (pawn != pawndup);
start = G_PickPlayerStart(pnum, 0);
start = level.PickPlayerStart(pnum, 0);
if (start == NULL)
{
if (pawndup != nullptr)

View File

@ -262,6 +262,17 @@ public:
void SpawnExtraPlayers();
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:
// Work data for CollectConnectedGroups.

View File

@ -109,8 +109,6 @@
// EXTERNAL FUNCTION PROTOTYPES --------------------------------------------
void G_PlayerReborn (int player);
// PRIVATE FUNCTION PROTOTYPES ---------------------------------------------
static void PlayerLandedOnThing (AActor *mo, AActor *onmobj);
@ -4999,7 +4997,7 @@ AActor *FLevelLocals::SpawnPlayer (FPlayerStart *mthing, int playernum, int flag
state = p->playerstate;
if (state == PST_REBORN || state == PST_ENTER)
{
G_PlayerReborn (playernum);
PlayerReborn (playernum);
}
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])
{
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])
{
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);
}
}
@ -474,7 +474,7 @@ void P_SetupLevel(FLevelLocals *Level, int position, bool newGame)
if (!(players[i].mo->flags & MF_FRIENDLY))
{
AActor * oldSpawn = players[i].mo;
G_DeathMatchSpawnPlayer(i);
Level->DeathMatchSpawnPlayer(i);
oldSpawn->Destroy();
}
}

View File

@ -400,8 +400,14 @@ class Object native
native static String G_SkillName();
native static int G_SkillPropertyInt(int p);
native static double G_SkillPropertyFloat(int p);
native static vector3, int G_PickDeathmatchStart();
native static vector3, int G_PickPlayerStart(int pnum, int flags = 0);
deprecated("3.8") static vector3, int G_PickDeathmatchStart()
{
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_PauseSound (bool notmusic, 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 uint GetSkyboxPortal(Actor actor);
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);

View File

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

View File

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