Add playerstarts, matchstarts, teamstarts to Lua

Refactor player starts
This commit is contained in:
Lactozilla 2023-08-13 21:52:37 -03:00
parent f493e4aae0
commit 82f5c42e94
14 changed files with 410 additions and 122 deletions

View file

@ -634,14 +634,33 @@ extern tic_t hidetime;
// WAD, partly set at startup time.
extern tic_t gametic;
#define localgametic leveltime
enum
{
PLAYER_START_TYPE_COOP,
PLAYER_START_TYPE_MATCH,
PLAYER_START_TYPE_TEAM
};
typedef struct
{
size_t count;
size_t capacity;
mapthing_t **list;
} playerstarts_t;
#define MAX_DM_STARTS 64
// Player spawn spots.
extern mapthing_t *playerstarts[MAXPLAYERS]; // Cooperative
extern mapthing_t *teamstarts[MAXTEAMS][MAXPLAYERS]; // CTF
extern playerstarts_t playerstarts;
extern playerstarts_t deathmatchstarts;
extern playerstarts_t teamstarts[MAXTEAMS];
#define WAYPOINTSEQUENCESIZE 256
#define NUMWAYPOINTSEQUENCES 256
extern mobj_t *waypoints[NUMWAYPOINTSEQUENCES][WAYPOINTSEQUENCESIZE];
extern UINT16 numwaypoints[NUMWAYPOINTSEQUENCES];

View file

@ -2441,13 +2441,8 @@ void F_StartTitleScreen(void)
players[displayplayer].playerstate = PST_DEAD; // Don't spawn the player in dummy (I'm still a filthy cheater)
// Set Default Position
if (playerstarts[0])
startpos = playerstarts[0];
else if (deathmatchstarts[0])
startpos = deathmatchstarts[0];
else
startpos = NULL;
// Set initial camera position
startpos = G_GetInitialSpawnPoint();
if (startpos)
{

View file

@ -2564,7 +2564,7 @@ void G_AddGhost(char *defdemoname)
ghosts = gh;
gh->version = ghostversion;
mthing = playerstarts[0];
mthing = G_GetPlayerStart(0);
I_Assert(mthing);
{ // A bit more complex than P_SpawnPlayer because ghosts aren't solid and won't just push themselves out of the ceiling.
fixed_t z,f,c;

View file

@ -153,10 +153,13 @@ INT16 nextmapoverride;
UINT8 skipstats;
INT16 nextgametype = -1;
// Pointers to each CTF flag
mobj_t *flagmobjs[MAXTEAMS];
// Pointers to CTF spawn location
mapthing_t *flagpoints[MAXTEAMS];
// Maintain single and multi player starting spots.
playerstarts_t playerstarts;
playerstarts_t deathmatchstarts;
playerstarts_t teamstarts[MAXTEAMS];
mobj_t *flagmobjs[MAXTEAMS]; // Pointers to each CTF flag
mapthing_t *flagpoints[MAXTEAMS]; // Pointers to CTF flag spawn locations
struct quake quake;
@ -2849,29 +2852,134 @@ void G_MovePlayerToSpawnOrStarpost(INT32 playernum)
P_ResetCamera(&players[playernum], &camera2);
}
enum
{
PLAYER_START_TYPE_COOP,
PLAYER_START_TYPE_MATCH,
PLAYER_START_TYPE_TEAM
};
static boolean G_AreCoopStartsAvailable(void)
{
return numcoopstarts != 0;
return playerstarts.count != 0;
}
static boolean G_AreMatchStartsAvailable(void)
{
return numdmstarts != 0;
return deathmatchstarts.count != 0;
}
static boolean G_AreTeamStartsAvailable(UINT8 team)
{
if (team >= numteams)
if (team == TEAM_NONE || team >= numteams)
return false;
return numteamstarts[team] != 0;
return teamstarts[team].count != 0;
}
mapthing_t *G_GetPlayerStart(INT32 i)
{
if (i < 0 || i >= (signed)playerstarts.count || playerstarts.list == NULL)
return NULL;
return playerstarts.list[i];
}
mapthing_t *G_GetMatchPlayerStart(INT32 i)
{
if (i < 0 || i >= (signed)deathmatchstarts.count || deathmatchstarts.list == NULL)
return NULL;
return deathmatchstarts.list[i];
}
mapthing_t *G_GetTeamPlayerStart(UINT8 team, INT32 i)
{
if (team == TEAM_NONE || team >= numteams)
return NULL;
if (i < 0 || i >= (signed)teamstarts[team].count || teamstarts[team].list == NULL)
return NULL;
return teamstarts[team].list[i];
}
mapthing_t *G_GetInitialSpawnPoint(void)
{
if (gametyperules & GTR_DEATHMATCHSTARTS)
return G_GetMatchPlayerStart(0);
else
return G_GetPlayerStart(0);
}
void G_InitSpawnPointList(playerstarts_t *starts, size_t capacity)
{
Z_Free(starts->list);
starts->list = NULL;
starts->capacity = capacity;
starts->count = 0;
}
void G_AddSpawnPointToList(playerstarts_t *starts, mapthing_t *mthing)
{
if (starts->list == NULL || starts->count == starts->capacity)
{
if (starts->capacity == 0 || starts->list != NULL)
starts->capacity += 16;
if (starts->list != NULL)
starts->list = Z_Realloc(starts->list, sizeof(mapthing_t *) * starts->capacity, PU_STATIC, NULL);
else
starts->list = Z_Calloc(sizeof(mapthing_t *) * starts->capacity, PU_STATIC, NULL);
}
starts->list[starts->count++] = mthing;
}
void G_InitSpawnPoints(void)
{
G_InitSpawnPointList(&playerstarts, MAXPLAYERS);
G_InitSpawnPointList(&deathmatchstarts, MAX_DM_STARTS);
for (UINT8 i = 1; i < MAXTEAMS; i++)
G_InitSpawnPointList(&teamstarts[i], MAXPLAYERS);
}
void G_AddPlayerStart(int index, mapthing_t *mthing)
{
if (playerstarts.list == NULL)
{
if (playerstarts.capacity == 0)
playerstarts.capacity = MAXPLAYERS;
playerstarts.list = Z_Calloc(sizeof(mapthing_t *) * playerstarts.capacity, PU_STATIC, NULL);
}
if (index >= 0 && index < (signed)playerstarts.capacity)
playerstarts.list[index] = mthing;
}
void G_AddMatchPlayerStart(mapthing_t *mthing)
{
G_AddSpawnPointToList(&deathmatchstarts, mthing);
}
void G_AddTeamPlayerStart(UINT8 team, mapthing_t *mthing)
{
if (team == TEAM_NONE || team >= numteams)
return;
G_AddSpawnPointToList(&teamstarts[team], mthing);
}
void G_CountPlayerStarts(void)
{
playerstarts.count = 0;
if (playerstarts.list == NULL)
return;
for (; playerstarts.count < playerstarts.capacity; playerstarts.count++)
if (!playerstarts.list[playerstarts.count])
break;
}
boolean G_IsSpawnPointThingType(UINT16 mthingtype)
{
return mthingtype >= 1 && mthingtype <= 35;
}
static boolean G_AreTeamStartsAvailableForPlayer(INT32 playernum)
@ -2885,13 +2993,14 @@ static boolean G_AreTeamStartsAvailableForPlayer(INT32 playernum)
mapthing_t *G_FindTeamStart(INT32 playernum)
{
UINT8 team = players[playernum].ctfteam;
if (team != TEAM_NONE && G_AreTeamStartsAvailable(team))
{
for (INT32 j = 0; j < MAXPLAYERS; j++)
{
INT32 i = P_RandomKey(numteamstarts[team]);
if (G_CheckSpot(playernum, teamstarts[team][i]))
return teamstarts[team][i];
INT32 i = P_RandomKey(teamstarts[team].count);
if (G_CheckSpot(playernum, teamstarts[team].list[i]))
return teamstarts[team].list[i];
}
}
@ -2900,15 +3009,13 @@ mapthing_t *G_FindTeamStart(INT32 playernum)
mapthing_t *G_FindMatchStart(INT32 playernum)
{
INT32 i, j;
if (G_AreMatchStartsAvailable())
{
for (j = 0; j < 64; j++)
for (INT32 j = 0; j < 64; j++)
{
i = P_RandomKey(numdmstarts);
if (G_CheckSpot(playernum, deathmatchstarts[i]))
return deathmatchstarts[i];
INT32 i = P_RandomKey(deathmatchstarts.count);
if (G_CheckSpot(playernum, deathmatchstarts.list[i]))
return deathmatchstarts.list[i];
}
}
@ -2919,13 +3026,14 @@ mapthing_t *G_FindCoopStart(INT32 playernum)
{
if (G_AreCoopStartsAvailable())
{
//if there's 6 players in a map with 3 player starts, this spawns them 1/2/3/1/2/3.
if (G_CheckSpot(playernum, playerstarts[playernum % numcoopstarts]))
return playerstarts[playernum % numcoopstarts];
// if there's 6 players in a map with 3 player starts, this spawns them 1/2/3/1/2/3.
mapthing_t *spawnpoint = G_GetPlayerStart(playernum % playerstarts.count);
if (G_CheckSpot(playernum, spawnpoint))
return spawnpoint;
//Don't bother checking to see if the player 1 start is open.
//Just spawn there.
return playerstarts[0];
// Don't bother checking to see if the player 1 start is open.
// Just spawn there.
return G_GetPlayerStart(0);
}
return NULL;

View file

@ -164,6 +164,21 @@ void G_FreeMapSearch(mapsearchfreq_t *freq, INT32 freqc);
/* Match map name by search + 2 digit map code or map number. */
INT32 G_FindMapByNameOrCode(const char *query, char **foundmapnamep);
void G_InitSpawnPointList(playerstarts_t *starts, size_t capacity);
void G_AddSpawnPointToList(playerstarts_t *starts, mapthing_t *mthing);
boolean G_IsSpawnPointThingType(UINT16 mthingtype);
mapthing_t *G_GetInitialSpawnPoint(void);
mapthing_t *G_GetPlayerStart(INT32 i);
mapthing_t *G_GetMatchPlayerStart(INT32 i);
mapthing_t *G_GetTeamPlayerStart(UINT8 team, INT32 i);
void G_InitSpawnPoints(void);
void G_AddPlayerStart(int index, mapthing_t *mthing);
void G_AddMatchPlayerStart(mapthing_t *mthing);
void G_AddTeamPlayerStart(UINT8 team, mapthing_t *mthing);
void G_CountPlayerStarts(void);
mapthing_t *G_FindMapStart(INT32 playernum);
mapthing_t *G_FindBestPlayerStart(INT32 playernum);
mapthing_t *G_FindCoopStart(INT32 playernum);

View file

@ -158,6 +158,8 @@ static const struct {
{META_GAMETYPE, "gametype_t"},
{META_TEAM, "team_t"},
{META_TEAMLIST, "teamlist_t"},
{META_TEAMSCORES, "teamscores"},
{META_PLAYERSTARTS, "playerstarts"},
{META_SPRITEINFO, "spriteinfo_t"},
{META_PIVOTLIST, "spriteframepivot_t[]"},
{META_FRAMEPIVOT, "spriteframepivot_t"},

View file

@ -1910,7 +1910,7 @@ static int lib_getGametypes(lua_State *L)
i = luaL_checkinteger(L, 1);
if (i < 0 || i >= gametypecount)
return luaL_error(L, "gametypes[] index %d out of range (0 - %d)", i, gametypecount-1);
return luaL_error(L, "gametypes[] index %d out of range (0 - %d)", i, gametypecount - 1);
LUA_PushUserdata(L, &gametypes[i], META_GAMETYPE);
return 1;
}
@ -2138,7 +2138,7 @@ static int lib_getTeams(lua_State *L)
i = luaL_checkinteger(L, 1);
if (i < 0 || i >= numteams)
return luaL_error(L, "teams[] index %d out of range (0 - %d)", i, numteams-1);
return luaL_error(L, "teams[] index %d out of range (0 - %d)", i, max(0, (int)numteams - 1));
LUA_PushUserdata(L, &teams[i], META_GAMETYPE);
return 1;
}
@ -2255,7 +2255,7 @@ static int lib_setTeams(lua_State *L)
{
teamnum = luaL_checkinteger(L, 1);
if (teamnum >= numteams)
return luaL_error(L, "teams[] index %d out of range (0 - %d)", teamnum, numteams-1);
return luaL_error(L, "teams[] index %d out of range (0 - %d)", teamnum, max(0, (int)numteams - 1));
team = &teams[teamnum];
}
luaL_checktype(L, 2, LUA_TTABLE);
@ -2433,7 +2433,7 @@ static int teamscores_get(lua_State *L)
UINT32 *scoreslist = *((UINT32 **)luaL_checkudata(L, 1, META_TEAMSCORES));
int i = luaL_checkinteger(L, 2);
if (i < 0 || i >= numteams)
return luaL_error(L, "array index %d out of range (0 - %d)", i, numteams - 1);
return luaL_error(L, "array index %d out of range (0 - %d)", i, max(0, (int)numteams - 1));
lua_pushinteger(L, scoreslist[i]);
return 1;
}
@ -2444,7 +2444,7 @@ static int teamscores_set(lua_State *L)
int i = luaL_checkinteger(L, 2);
UINT32 score = (UINT32)luaL_checkinteger(L, 3);
if (i < 0 || i >= numteams)
return luaL_error(L, "array index %d out of range (0 - %d)", i, numteams - 1);
return luaL_error(L, "array index %d out of range (0 - %d)", i, max(0, (int)numteams - 1));
scoreslist[i] = score;
return 0;
}
@ -2455,6 +2455,61 @@ static int teamscores_len(lua_State *L)
return 1;
}
///////////////////
// PLAYER STARTS //
///////////////////
static int playerstarts_get(lua_State *L)
{
playerstarts_t *starts = *((playerstarts_t **)luaL_checkudata(L, 1, META_PLAYERSTARTS));
int i = luaL_checkinteger(L, 2);
if (i < 0 || i >= (signed)starts->count)
return luaL_error(L, "player start index %d out of range (0 - %d)", i, max(0, (int)starts->count - 1));
LUA_PushUserdata(L, starts->list[i], META_MAPTHING);
return 1;
}
static int playerstarts_set(lua_State *L)
{
playerstarts_t *starts = *((playerstarts_t **)luaL_checkudata(L, 1, META_PLAYERSTARTS));
int i = luaL_checkinteger(L, 2);
mapthing_t *mthing = *((mapthing_t **)luaL_checkudata(L, 3, META_MAPTHING));
if (i < 0 || i >= (signed)starts->count)
return luaL_error(L, "player start index %d out of range (0 - %d)", i, max(0, (int)starts->count - 1));
if (!mthing)
return LUA_ErrInvalid(L, "mapthing_t");
starts->list[i] = mthing;
return 0;
}
static int playerstarts_len(lua_State *L)
{
playerstarts_t *starts = *((playerstarts_t **)luaL_checkudata(L, 1, META_PLAYERSTARTS));
lua_pushinteger(L, starts->count);
return 1;
}
static int lib_getTeamstarts(lua_State *L)
{
int i;
lua_remove(L, 1);
i = luaL_checkinteger(L, 1);
if (i <= 0 || i >= numteams)
return luaL_error(L, "team index %d out of range (1 - %d)", i, numteams - 1);
LUA_PushUserdata(L, &teamstarts[i], META_PLAYERSTARTS);
return 1;
}
// #teamstarts -> MAXTEAMS
static int lib_teamstartslen(lua_State *L)
{
lua_pushinteger(L, MAXTEAMS);
return 1;
}
//////////////////////////////
//
// Now push all these functions into the Lua state!
@ -2542,6 +2597,17 @@ int LUA_InfoLib(lua_State *L)
lua_setfield(L, -2, "__len");
lua_pop(L, 1);
luaL_newmetatable(L, META_PLAYERSTARTS);
lua_pushcfunction(L, playerstarts_get);
lua_setfield(L, -2, "__index");
lua_pushcfunction(L, playerstarts_set);
lua_setfield(L, -2, "__newindex");
lua_pushcfunction(L, playerstarts_len);
lua_setfield(L, -2, "__len");
lua_pop(L, 1);
luaL_newmetatable(L, META_SKINCOLOR);
lua_pushcfunction(L, skincolor_get);
lua_setfield(L, -2, "__index");
@ -2731,6 +2797,16 @@ int LUA_InfoLib(lua_State *L)
lua_setmetatable(L, -2);
lua_setglobal(L, "teams");
lua_newuserdata(L, 0);
lua_createtable(L, 0, 2);
lua_pushcfunction(L, lib_getTeamstarts);
lua_setfield(L, -2, "__index");
lua_pushcfunction(L, lib_teamstartslen);
lua_setfield(L, -2, "__len");
lua_setmetatable(L, -2);
lua_setglobal(L, "teamstarts");
luaL_newmetatable(L, META_LUABANKS);
lua_pushcfunction(L, lib_getluabanks);
lua_setfield(L, -2, "__index");

View file

@ -32,6 +32,7 @@ extern boolean mousegrabbedbylua;
#define META_TEAM "TEAM_T*"
#define META_TEAMLIST "TEAMLIST_T*"
#define META_TEAMSCORES "TEAMSCORES"
#define META_PLAYERSTARTS "PLAYERSTARTS"
#define META_PIVOTLIST "SPRITEFRAMEPIVOT_T[]"
#define META_FRAMEPIVOT "SPRITEFRAMEPIVOT_T*"

View file

@ -213,6 +213,12 @@ int LUA_PushGlobals(lua_State *L, const char *word)
} else if (fastcmp(word,"paused")) {
lua_pushboolean(L, paused);
return 1;
} else if (fastcmp(word, "playerstarts")) {
LUA_PushUserdata(L, &playerstarts, META_PLAYERSTARTS);
return 1;
} else if (fastcmp(word, "matchstarts")) {
LUA_PushUserdata(L, &deathmatchstarts, META_PLAYERSTARTS);
return 1;
} else if (fastcmp(word,"bluescore")) {
lua_pushinteger(L, teamscores[G_GetTeam(2)]);
return 1;

View file

@ -513,13 +513,14 @@ void Command_Teleport_f(void)
mapthing_t *mt;
fixed_t offset;
if (starpostpath >= numcoopstarts)
int numstarts = (signed)playerstarts.count;
if (starpostpath >= numstarts)
{
CONS_Alert(CONS_NOTICE, M_GetText("Player %d spawnpoint not found (%d max).\n"), starpostpath+1, numcoopstarts-1);
CONS_Alert(CONS_NOTICE, M_GetText("Player %d spawnpoint not found (%d max).\n"), starpostpath+1, numstarts-1);
return;
}
mt = playerstarts[starpostpath]; // Given above check, should never be NULL.
mt = G_GetPlayerStart(starpostpath); // Given above check, should never be NULL.
intx = mt->x<<FRACBITS;
inty = mt->y<<FRACBITS;
offset = mt->z<<FRACBITS;

View file

@ -44,6 +44,8 @@ actioncache_t actioncachehead;
static mobj_t *overlaycap = NULL;
static mobj_t *P_RespawnMapThing(mapthing_t *mthing);
#define MAXHUNTEMERALDS 64
mapthing_t *huntemeralds[MAXHUNTEMERALDS];
INT32 numhuntemeralds;
@ -11527,7 +11529,7 @@ void P_RespawnSpecials(void)
#endif
if (mthing)
P_SpawnMapThing(mthing);
P_RespawnMapThing(mthing);
// pull it from the que
iquetail = (iquetail+1)&(ITEMQUESIZE-1);
@ -11933,17 +11935,6 @@ fixed_t P_GetMapThingSpawnHeight(const mobjtype_t mobjtype, const mapthing_t* mt
return P_GetMobjSpawnHeight(mobjtype, x, y, dz, offset, flip, mthing->scale);
}
static void P_SetTeamStart(UINT8 team, mapthing_t *mthing)
{
if (team != TEAM_NONE && team < numteams && numteamstarts[team] < MAXPLAYERS)
{
teamstarts[team][numteamstarts[team]] = mthing;
numteamstarts[team]++;
numteamstarts[0]++;
mthing->type = 0;
}
}
static boolean P_SpawnNonMobjMapThing(mapthing_t *mthing)
{
#if MAXPLAYERS > 32
@ -11953,33 +11944,28 @@ static boolean P_SpawnNonMobjMapThing(mapthing_t *mthing)
{
// save spots for respawning in network games
if (!metalrecording)
playerstarts[mthing->type - 1] = mthing;
G_AddPlayerStart(mthing->type - 1, mthing);
return true;
}
else if (mthing->type == 33) // Match starts
{
if (numdmstarts < MAX_DM_STARTS)
{
deathmatchstarts[numdmstarts] = mthing;
mthing->type = 0;
numdmstarts++;
}
G_AddMatchPlayerStart(mthing);
return true;
}
else if (mthing->type == 34) // Red CTF starts
{
P_SetTeamStart(G_GetTeam(TEAM_RED), mthing);
G_AddTeamPlayerStart(G_GetTeam(TEAM_RED), mthing);
return true;
}
else if (mthing->type == 35) // Blue CTF starts
{
P_SetTeamStart(G_GetTeam(TEAM_BLUE), mthing);
G_AddTeamPlayerStart(G_GetTeam(TEAM_BLUE), mthing);
return true;
}
else if (metalrecording && mthing->type == mobjinfo[MT_METALSONIC_RACE].doomednum)
{
// If recording, you ARE Metal Sonic. Do not spawn it, do not save normal spawnpoints.
playerstarts[0] = mthing;
G_AddPlayerStart(0, mthing);
return true;
}
else if (mthing->type == 750 // Slope vertex point (formerly chaos spawn)
@ -13402,11 +13388,6 @@ static mobj_t *P_SpawnMobjFromMapThing(mapthing_t *mthing, fixed_t x, fixed_t y,
return mobj;
}
//
// P_SpawnMapThing
// The fields of the mapthing should
// already be in host byte order.
//
mobj_t *P_SpawnMapThing(mapthing_t *mthing)
{
mobjtype_t i;
@ -13443,6 +13424,14 @@ mobj_t *P_SpawnMapThing(mapthing_t *mthing)
return P_SpawnMobjFromMapThing(mthing, x, y, z, i);
}
static mobj_t *P_RespawnMapThing(mapthing_t *mthing)
{
if (G_IsSpawnPointThingType(mthing->type))
return NULL;
return P_SpawnMapThing(mthing);
}
void P_SpawnHoop(mapthing_t *mthing)
{
if (metalrecording)

View file

@ -4300,6 +4300,101 @@ static inline void P_UnArchiveSPGame(INT16 mapoverride)
playeringame[consoleplayer] = true;
}
static void ArchiveSpawnPoints(void)
{
// Write player starts
WRITEUINT8(save_p, playerstarts.capacity);
for (size_t i = 0; i < playerstarts.capacity; i++)
{
if (playerstarts.list[i] == NULL)
WRITEUINT16(save_p, 0xFFFF);
else
{
size_t mapthingnum = playerstarts.list[i] - mapthings;
WRITEUINT16(save_p, mapthingnum);
}
}
// Write Match starts
WRITEUINT8(save_p, deathmatchstarts.count);
for (size_t i = 0; i < deathmatchstarts.count; i++)
{
size_t mapthingnum = deathmatchstarts.list[i] - mapthings;
WRITEUINT16(save_p, mapthingnum);
}
// Write team starts
for (UINT8 team = 1; team < numteams; team++)
{
WRITEUINT8(save_p, teamstarts[team].count);
for (size_t i = 0; i < teamstarts[team].count; i++)
{
size_t mapthingnum = teamstarts[team].list[i] - mapthings;
WRITEUINT16(save_p, mapthingnum);
}
}
}
static boolean ReadPlayerStarts(playerstarts_t *starts)
{
size_t count = (size_t)READUINT8(save_p);
for (size_t i = 0; i < count; i++)
{
UINT16 mapthingnum = READUINT16(save_p);
if (mapthingnum < nummapthings)
G_AddSpawnPointToList(starts, &mapthings[mapthingnum]);
else
{
CONS_Alert(CONS_ERROR, "Player start %d has invalid map thing number %d\n", (int)i, mapthingnum);
return false;
}
}
return true;
}
static boolean RestoreSpawnPoints(void)
{
// Read player starts
playerstarts.capacity = READUINT8(save_p);
for (size_t i = 0; i < playerstarts.capacity; i++)
{
UINT16 mapthingnum = READUINT16(save_p);
if (mapthingnum == 0xFFFF)
G_AddPlayerStart(i, NULL);
else if (mapthingnum < nummapthings)
G_AddPlayerStart(i, &mapthings[mapthingnum]);
else
{
CONS_Alert(CONS_ERROR, "Player start %d has invalid map thing number %d\n", (int)i, mapthingnum);
return false;
}
}
G_CountPlayerStarts();
// Read Match starts
if (!ReadPlayerStarts(&deathmatchstarts))
{
CONS_Alert(CONS_ERROR, "Failed to read Match player starts\n");
return false;
}
// Read team starts
for (UINT8 team = 1; team < numteams; team++)
{
if (!ReadPlayerStarts(&teamstarts[team]))
{
CONS_Alert(CONS_ERROR, "Failed to read team %d player starts\n", team);
return false;
}
}
return true;
}
static void P_NetArchiveMisc(boolean resending)
{
INT32 i;
@ -4349,6 +4444,8 @@ static void P_NetArchiveMisc(boolean resending)
for (i = 0; i < MAXTEAMS; i++)
WRITEUINT32(save_p, teamscores[i]);
ArchiveSpawnPoints();
WRITEINT32(save_p, modulothing);
WRITEINT16(save_p, autobalance);
@ -4444,6 +4541,9 @@ static inline boolean P_NetUnArchiveMisc(boolean reloading)
for (i = 0; i < MAXTEAMS; i++)
teamscores[i] = READUINT32(save_p);
if (!RestoreSpawnPoints())
I_Error("Savegame corrupted");
modulothing = READINT32(save_p);
autobalance = READINT16(save_p);

View file

@ -143,13 +143,6 @@ mobj_t **blocklinks;
//
UINT8 *rejectmatrix;
// Maintain single and multi player starting spots.
INT32 numdmstarts, numcoopstarts, numteamstarts[MAXTEAMS];
mapthing_t *deathmatchstarts[MAX_DM_STARTS];
mapthing_t *playerstarts[MAXPLAYERS];
mapthing_t *teamstarts[MAXTEAMS][MAXPLAYERS];
// Maintain waypoints
mobj_t *waypoints[NUMWAYPOINTSEQUENCES][WAYPOINTSEQUENCESIZE];
UINT16 numwaypoints[NUMWAYPOINTSEQUENCES];
@ -870,7 +863,7 @@ static void P_SpawnEmeraldHunt(void)
}
}
static void P_SpawnMapThings(boolean spawnemblems)
static void P_SpawnMapThings(boolean respawning, boolean fromnetsave)
{
size_t i;
mapthing_t *mt;
@ -895,22 +888,31 @@ static void P_SpawnMapThings(boolean spawnemblems)
for (i = 0, mt = mapthings; i < nummapthings; i++, mt++)
{
if (mt->type == 1700 // MT_AXIS
|| mt->type == 1701 // MT_AXISTRANSFER
|| mt->type == 1702) // MT_AXISTRANSFERLINE
UINT16 type = mt->type;
if (type == 1700 // MT_AXIS
|| type == 1701 // MT_AXISTRANSFER
|| type == 1702) // MT_AXISTRANSFERLINE
continue; // These were already spawned
if (!spawnemblems && mt->type == mobjinfo[MT_EMBLEM].doomednum)
if (fromnetsave && type == mobjinfo[MT_EMBLEM].doomednum)
continue;
mt->mobj = NULL;
if (mt->type >= 600 && mt->type <= 611) // item patterns
if (type >= 600 && type <= 611) // item patterns
P_SpawnItemPattern(mt, false);
else if (mt->type == 1713) // hoops
else if (type == 1713) // hoops
P_SpawnHoop(mt);
else // Everything else
{
// Don't respawn player starts if the game is either respawning all things,
// or if the game is loading a savegame.
if (G_IsSpawnPointThingType(mt->type) && (respawning || fromnetsave))
continue;
P_SpawnMapThing(mt);
}
}
// random emeralds for hunt
@ -7158,7 +7160,7 @@ void P_RespawnThings(void)
localaiming = 0;
localaiming2 = 0;
P_SpawnMapThings(true);
P_SpawnMapThings(true, false);
// restore skybox viewpoint/centerpoint if necessary, set them to defaults if we can't do that
skyboxmo[0] = skyboxviewpnts[(viewid >= 0) ? viewid : 0];
@ -7231,24 +7233,9 @@ static void P_ForceCharacter(const char *forcecharskin)
static void P_ResetSpawnpoints(void)
{
UINT8 i, j;
UINT8 i;
numdmstarts = 0;
// reset the player starts
for (i = 0; i < MAXPLAYERS; i++)
playerstarts[i] = NULL;
for (i = 0; i < MAX_DM_STARTS; i++)
deathmatchstarts[i] = NULL;
for (i = 0; i < MAXTEAMS; i++)
{
numteamstarts[i] = 0;
for (j = 0; j < MAXPLAYERS; j++)
teamstarts[i][j] = NULL;
}
G_InitSpawnPoints();
for (i = 0; i < 2; i++)
skyboxmo[i] = NULL;
@ -7435,12 +7422,7 @@ static void P_SetupCamera(void)
}
else
{
mapthing_t *thing;
if (gametyperules & GTR_DEATHMATCHSTARTS)
thing = deathmatchstarts[0];
else
thing = playerstarts[0];
mapthing_t *thing = G_GetInitialSpawnPoint();
if (thing)
{
@ -7877,13 +7859,12 @@ boolean P_LoadLevel(boolean fromnetsave, boolean reloadinggamestate)
P_SpawnSlopes(fromnetsave);
P_SpawnMapThings(!fromnetsave);
P_SpawnMapThings(false, fromnetsave);
skyboxmo[0] = skyboxviewpnts[0];
skyboxmo[1] = skyboxcenterpnts[0];
for (numcoopstarts = 0; numcoopstarts < MAXPLAYERS; numcoopstarts++)
if (!playerstarts[numcoopstarts])
break;
if (!fromnetsave)
G_CountPlayerStarts();
// set up world state
P_SpawnSpecials(fromnetsave);

View file

@ -21,11 +21,6 @@
// map md5, sent to players via PT_SERVERINFO
extern unsigned char mapmd5[16];
// Player spawn spots for deathmatch.
#define MAX_DM_STARTS 64
extern mapthing_t *deathmatchstarts[MAX_DM_STARTS];
extern INT32 numdmstarts, numcoopstarts, numteamstarts[MAXTEAMS];
extern boolean levelloading;
extern UINT8 levelfadecol;