mirror of
https://git.do.srb2.org/STJr/SRB2.git
synced 2024-12-18 17:01:20 +00:00
Add playerstarts, matchstarts, teamstarts to Lua
Refactor player starts
This commit is contained in:
parent
f493e4aae0
commit
82f5c42e94
14 changed files with 410 additions and 122 deletions
|
@ -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];
|
||||
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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;
|
||||
|
|
168
src/g_game.c
168
src/g_game.c
|
@ -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;
|
||||
|
|
15
src/g_game.h
15
src/g_game.h
|
@ -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);
|
||||
|
|
|
@ -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"},
|
||||
|
|
|
@ -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");
|
||||
|
|
|
@ -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*"
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
43
src/p_mobj.c
43
src/p_mobj.c
|
@ -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)
|
||||
|
|
100
src/p_saveg.c
100
src/p_saveg.c
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
Loading…
Reference in a new issue