diff --git a/src/doomstat.h b/src/doomstat.h index f0bf5d6a9..7111806fa 100644 --- a/src/doomstat.h +++ b/src/doomstat.h @@ -637,6 +637,14 @@ extern tic_t gametic; #define localgametic leveltime +typedef struct +{ + fixed_t x, y, z; + angle_t angle; + boolean spawn_on_ceiling; + boolean spawn_flipped; +} spawnpoint_t; + enum { PLAYER_START_TYPE_COOP, diff --git a/src/g_game.c b/src/g_game.c index 5b06381ff..8eed82129 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -2836,10 +2836,21 @@ void G_SpawnPlayer(INT32 playernum) void G_MovePlayerToSpawnOrStarpost(INT32 playernum) { - if (players[playernum].starposttime) - P_MovePlayerToStarpost(playernum); - else - P_MovePlayerToSpawn(playernum, G_FindMapStart(playernum)); + spawnpoint_t *spawnpoint = LUA_HookPlayerRespawn(&players[playernum]); + + if (spawnpoint == NULL) + { + if (players[playernum].starposttime) + P_MovePlayerToStarpost(playernum); + else + spawnpoint = G_FindSpawnPoint(playernum); + } + + if (spawnpoint) + { + P_MovePlayerToSpawn(playernum, spawnpoint); + Z_Free(spawnpoint); + } R_ResetMobjInterpolationState(players[playernum].mo); @@ -3174,13 +3185,13 @@ static mapthing_t *G_GetTeamStartForSpawning(INT32 playernum) return spawnpoint; } -mapthing_t *G_FindMapStart(INT32 playernum) +spawnpoint_t *G_FindSpawnPoint(INT32 playernum) { if (!playeringame[playernum]) return NULL; player_t *player = &players[playernum]; - mapthing_t *spawnpoint = NULL; + mapthing_t *mthing = NULL; // -- Spectators -- // Order in platform gametypes: Coop->DM->Team @@ -3190,9 +3201,9 @@ mapthing_t *G_FindMapStart(INT32 playernum) // In platform gametypes, spawn in Co-op starts first // Overriden by GTR_DEATHMATCHSTARTS. if (G_PlatformGametype() && !(gametyperules & GTR_DEATHMATCHSTARTS)) - spawnpoint = G_GetCoopStartForSpawning(playernum); + mthing = G_GetCoopStartForSpawning(playernum); else - spawnpoint = G_GetMatchStartForSpawning(playernum); + mthing = G_GetMatchStartForSpawning(playernum); } // -- CTF -- @@ -3200,9 +3211,9 @@ mapthing_t *G_FindMapStart(INT32 playernum) else if (gametyperules & GTR_TEAMFLAGS && G_GametypeHasTeams()) { if (player->ctfteam > TEAM_NONE && player->ctfteam < numteams) - spawnpoint = G_GetTeamStartForSpawning(playernum); + mthing = G_GetTeamStartForSpawning(playernum); else - spawnpoint = G_GetMatchStartForSpawning(playernum); + mthing = G_GetMatchStartForSpawning(playernum); } // -- DM/Tag/etc -- @@ -3213,42 +3224,43 @@ mapthing_t *G_FindMapStart(INT32 playernum) // If the player is not in a team, then this just gets a match start. if (G_GametypeHasTeams() && player->ctfteam > TEAM_NONE && player->ctfteam < numteams) { - spawnpoint = G_FindTeamStart(playernum); + mthing = G_FindTeamStart(playernum); // If no spawn point was returned, but team starts are available, this means there is no good location // for the player to spawn at. In that situation, we display a message telling the player so. - if (spawnpoint == NULL && G_AreTeamStartsAvailable(player->ctfteam) && P_IsLocalPlayer(player)) + if (mthing == NULL && G_AreTeamStartsAvailable(player->ctfteam) && P_IsLocalPlayer(player)) CONS_Alert(CONS_WARNING, M_GetText("Could not spawn at any %s starts!\n"), G_GetTeamName(player->ctfteam)); } // If that failed, no warning is shown. Instead, this will look for a match start, which may // then display a warning if no suitable map start was found. - if (spawnpoint == NULL) - spawnpoint = G_GetMatchStartForSpawning(playernum); + if (mthing == NULL) + mthing = G_GetMatchStartForSpawning(playernum); } // -- Other game modes -- // Order: Coop->DM->Team else - spawnpoint = G_GetCoopStartForSpawning(playernum); + mthing = G_GetCoopStartForSpawning(playernum); //No spawns found. ANYWHERE. - if (!spawnpoint) + if (!mthing) { if (nummapthings) { if (P_IsLocalPlayer(player)) CONS_Alert(CONS_ERROR, M_GetText("No player spawns found, spawning at the first mapthing!\n")); - spawnpoint = &mapthings[0]; + mthing = &mapthings[0]; } else { if (P_IsLocalPlayer(player)) CONS_Alert(CONS_ERROR, M_GetText("No player spawns found, spawning at the origin!\n")); + return NULL; } } - return spawnpoint; + return P_MakeSpawnPointFromMapthing(mthing); } mapthing_t *G_FindBestPlayerStart(INT32 playernum) diff --git a/src/g_game.h b/src/g_game.h index bb427d341..19b9b8fd9 100644 --- a/src/g_game.h +++ b/src/g_game.h @@ -179,11 +179,13 @@ 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); mapthing_t *G_FindMatchStart(INT32 playernum); mapthing_t *G_FindTeamStart(INT32 playernum); + +spawnpoint_t *G_FindSpawnPoint(INT32 playernum); + void G_MovePlayerToSpawnOrStarpost(INT32 playernum); void G_SpawnPlayer(INT32 playernum); diff --git a/src/lua_hook.h b/src/lua_hook.h index cb0e30d87..b78a9bbe5 100644 --- a/src/lua_hook.h +++ b/src/lua_hook.h @@ -72,6 +72,7 @@ automatically. X (MusicChange),\ X (PlayerHeight),/* override player height */\ X (PlayerCanEnterSpinGaps),\ + X (PlayerRespawn),\ X (KeyDown),\ X (KeyUp),\ @@ -148,4 +149,5 @@ int LUA_HookShouldJingleContinue(player_t *, const char *musname); int LUA_HookPlayerCmd(player_t *, ticcmd_t *); int LUA_HookMusicChange(const char *oldname, struct MusicChange *); fixed_t LUA_HookPlayerHeight(player_t *player); +spawnpoint_t *LUA_HookPlayerRespawn(player_t *player); int LUA_HookPlayerCanEnterSpinGaps(player_t *player); diff --git a/src/lua_hooklib.c b/src/lua_hooklib.c index 039a9677f..174c90139 100644 --- a/src/lua_hooklib.c +++ b/src/lua_hooklib.c @@ -264,7 +264,12 @@ typedef struct Hook_State Hook_State; typedef void (*Hook_Callback)(Hook_State *); struct Hook_State { - INT32 status;/* return status to calling function */ + union { + int type_int; + fixed_t type_fixed; + boolean type_bool; + void * type_void_pointer; + } status;/* return status to calling function */ void * userdata; int hook_type; mobjtype_t mobj_type;/* >0 if mobj hook */ @@ -313,7 +318,7 @@ static boolean init_hook_type const char * string, int nonzero ){ - hook->status = status; + hook->status.type_int = status; if (nonzero) { @@ -531,13 +536,13 @@ static int call_hooks static void res_true(Hook_State *hook) { if (lua_toboolean(gL, -1)) - hook->status = true; + hook->status.type_bool = true; } static void res_false(Hook_State *hook) { if (!lua_isnil(gL, -1) && !lua_toboolean(gL, -1)) - hook->status = false; + hook->status.type_bool = false; } static void res_force(Hook_State *hook) @@ -545,9 +550,9 @@ static void res_force(Hook_State *hook) if (!lua_isnil(gL, -1)) { if (lua_toboolean(gL, -1)) - hook->status = 1; // Force yes + hook->status.type_int = 1; // Force yes else - hook->status = 2; // Force no + hook->status.type_int = 2; // Force no } } @@ -563,7 +568,7 @@ int LUA_HookMobj(mobj_t *mobj, int hook_type) LUA_PushUserdata(gL, mobj, META_MOBJ); call_hooks(&hook, 1, res_true); } - return hook.status; + return hook.status.type_int; } int LUA_Hook2Mobj(mobj_t *t1, mobj_t *t2, int hook_type) @@ -575,7 +580,7 @@ int LUA_Hook2Mobj(mobj_t *t1, mobj_t *t2, int hook_type) LUA_PushUserdata(gL, t2, META_MOBJ); call_hooks(&hook, 1, res_force); } - return hook.status; + return hook.status.type_int; } void LUA_HookVoid(int type) @@ -613,7 +618,7 @@ int LUA_HookPlayer(player_t *player, int hook_type) LUA_PushUserdata(gL, player, META_PLAYER); call_hooks(&hook, 1, res_true); } - return hook.status; + return hook.status.type_int; } int LUA_HookTiccmd(player_t *player, ticcmd_t *cmd, int hook_type) @@ -632,7 +637,7 @@ int LUA_HookTiccmd(player_t *player, ticcmd_t *cmd, int hook_type) if (hook_type == HOOK(PlayerCmd)) hook_cmd_running = false; } - return hook.status; + return hook.status.type_int; } int LUA_HookKey(event_t *event, int hook_type) @@ -643,7 +648,7 @@ int LUA_HookKey(event_t *event, int hook_type) LUA_PushUserdata(gL, event, META_KEYEVENT); call_hooks(&hook, 1, res_true); } - return hook.status; + return hook.status.type_int; } void LUA_HookHUD(int hook_type, huddrawlist_h list) @@ -723,7 +728,7 @@ int LUA_HookMobjLineCollide(mobj_t *mobj, line_t *line) LUA_PushUserdata(gL, line, META_LINE); call_hooks(&hook, 1, res_force); } - return hook.status; + return hook.status.type_int; } int LUA_HookTouchSpecial(mobj_t *special, mobj_t *toucher) @@ -735,7 +740,7 @@ int LUA_HookTouchSpecial(mobj_t *special, mobj_t *toucher) LUA_PushUserdata(gL, toucher, META_MOBJ); call_hooks(&hook, 1, res_true); } - return hook.status; + return hook.status.type_int; } static int damage_hook @@ -759,7 +764,7 @@ static int damage_hook lua_pushinteger(gL, damagetype); call_hooks(&hook, 1, results_handler); } - return hook.status; + return hook.status.type_int; } int LUA_HookShouldDamage(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 damage, UINT8 damagetype) @@ -790,7 +795,7 @@ int LUA_HookMobjMoveBlocked(mobj_t *t1, mobj_t *t2, line_t *line) LUA_PushUserdata(gL, line, META_LINE); call_hooks(&hook, 1, res_true); } - return hook.status; + return hook.status.type_int; } typedef struct { @@ -843,7 +848,7 @@ static void res_botai(Hook_State *hook) B_KeysToTiccmd(botai->tails, botai->cmd, k[0],k[1],k[2],k[3],k[4],k[5],k[6],k[7]); - hook->status = true; + hook->status.type_bool = true; } int LUA_HookBotAI(mobj_t *sonic, mobj_t *tails, ticcmd_t *cmd) @@ -866,7 +871,7 @@ int LUA_HookBotAI(mobj_t *sonic, mobj_t *tails, ticcmd_t *cmd) call_hooks(&hook, 8, res_botai); } - return hook.status; + return hook.status.type_int; } void LUA_HookLinedefExecute(line_t *line, mobj_t *mo, sector_t *sector) @@ -904,7 +909,7 @@ int LUA_HookPlayerMsg(int source, int target, int flags, char *msg) lua_pushstring(gL, msg); // msg call_hooks(&hook, 1, res_true); } - return hook.status; + return hook.status.type_int; } int LUA_HookHurtMsg(player_t *player, mobj_t *inflictor, mobj_t *source, UINT8 damagetype) @@ -918,7 +923,7 @@ int LUA_HookHurtMsg(player_t *player, mobj_t *inflictor, mobj_t *source, UINT8 d lua_pushinteger(gL, damagetype); call_hooks(&hook, 1, res_true); } - return hook.status; + return hook.status.type_int; } void LUA_HookNetArchive(lua_CFunction archFunc) @@ -960,7 +965,7 @@ int LUA_HookMapThingSpawn(mobj_t *mobj, mapthing_t *mthing) LUA_PushUserdata(gL, mthing, META_MAPTHING); call_hooks(&hook, 1, res_true); } - return hook.status; + return hook.status.type_int; } int LUA_HookFollowMobj(player_t *player, mobj_t *mobj) @@ -972,7 +977,7 @@ int LUA_HookFollowMobj(player_t *player, mobj_t *mobj) LUA_PushUserdata(gL, mobj, META_MOBJ); call_hooks(&hook, 1, res_true); } - return hook.status; + return hook.status.type_int; } int LUA_HookPlayerCanDamage(player_t *player, mobj_t *mobj) @@ -984,7 +989,7 @@ int LUA_HookPlayerCanDamage(player_t *player, mobj_t *mobj) LUA_PushUserdata(gL, mobj, META_MOBJ); call_hooks(&hook, 1, res_force); } - return hook.status; + return hook.status.type_int; } void LUA_HookPlayerQuit(player_t *plr, kickreason_t reason) @@ -1010,7 +1015,7 @@ int LUA_HookTeamSwitch(player_t *player, int newteam, boolean fromspectators, bo lua_pushboolean(gL, tryingscramble); call_hooks(&hook, 1, res_false); } - return hook.status; + return hook.status.type_int; } int LUA_HookViewpointSwitch(player_t *player, player_t *newdisplayplayer, boolean forced) @@ -1026,7 +1031,7 @@ int LUA_HookViewpointSwitch(player_t *player, player_t *newdisplayplayer, boolea call_hooks(&hook, 1, res_force); hud_running = false; } - return hook.status; + return hook.status.type_int; } int LUA_HookSeenPlayer(player_t *player, player_t *seenfriend) @@ -1041,7 +1046,7 @@ int LUA_HookSeenPlayer(player_t *player, player_t *seenfriend) call_hooks(&hook, 1, res_false); hud_running = false; } - return hook.status; + return hook.status.type_int; } int LUA_HookShouldJingleContinue(player_t *player, const char *musname) @@ -1057,7 +1062,7 @@ int LUA_HookShouldJingleContinue(player_t *player, const char *musname) call_hooks(&hook, 1, res_true); hud_running = false; } - return hook.status; + return hook.status.type_int; } boolean hook_cmd_running = false; @@ -1090,7 +1095,7 @@ static void res_musicchange(Hook_State *hook) if (lua_isstring(gL, -6)) update_music_name(musicchange); else if (lua_isboolean(gL, -6) && lua_toboolean(gL, -6)) - hook->status = true; + hook->status.type_bool = true; // output 2: mflags override if (lua_isnumber(gL, -5)) @@ -1145,7 +1150,7 @@ int LUA_HookMusicChange(const char *oldname, struct MusicChange *param) lua_settop(gL, 0); } - return hook.status; + return hook.status.type_int; } static void res_playerheight(Hook_State *hook) @@ -1157,7 +1162,7 @@ static void res_playerheight(Hook_State *hook) // when an object's height is set to a negative number directly with lua, it's forced to 0 instead. // here, I think it's better to ignore negatives so that they don't replace any results of previous hooks! if (returnedheight >= 0) - hook->status = returnedheight; + hook->status.type_fixed = returnedheight; } } @@ -1169,7 +1174,105 @@ fixed_t LUA_HookPlayerHeight(player_t *player) LUA_PushUserdata(gL, player, META_PLAYER); call_hooks(&hook, 1, res_playerheight); } - return hook.status; + return hook.status.type_fixed; +} + +static void res_playerrespawn(Hook_State *hook) +{ + hook->status.type_void_pointer = NULL; + + if (!lua_isnil(gL, -1)) + { + if (!lua_istable(gL, -1)) + { + CONS_Alert(CONS_WARNING, "table expected in \"PlayerRespawn\" hook, got %s\n", luaL_typename(gL, -1)); + return; + } + + fixed_t height_offset = 0; + boolean has_z = false; + spawnpoint_t spawnpoint; + memset(&spawnpoint, 0, sizeof(spawnpoint)); + + lua_pushnil(gL); + while (lua_next(gL, -2)) + { + lua_pushvalue(gL, -2); + + const char *key = NULL; + if (lua_isstring(gL, -1)) + key = lua_tostring(gL, -1); + +#define TYPEERROR(f, t) \ + CONS_Alert(CONS_WARNING, \ + "bad value for \"%s\" in table returned by \"PlayerRespawn\" hook (%s expected, got %s)\n", \ + f, lua_typename(gL, t), luaL_typename(gL, -2)) + +#define GETNUMBER(r,f) \ + if (!strcmp(key, f)) \ + { \ + if (!lua_isnumber(gL, -2)) \ + TYPEERROR(f, LUA_TNUMBER); \ + else \ + r = lua_tonumber(gL, -2); \ + } +#define GETNUMBEROPT(r,f,opt) \ + if (!strcmp(key, f)) \ + { \ + if (!lua_isnumber(gL, -2)) \ + TYPEERROR(f, LUA_TNUMBER); \ + else \ + r = lua_tonumber(gL, -2); \ + opt = true; \ + } +#define GETBOOLEAN(r,f) \ + if (!strcmp(key, f)) \ + { \ + if (!lua_isboolean(gL, -2)) \ + TYPEERROR(f, LUA_TBOOLEAN); \ + else \ + r = lua_toboolean(gL, -2); \ + } + + if (key) + { + GETNUMBER(spawnpoint.x, "x"); + GETNUMBER(spawnpoint.y, "y"); + GETNUMBEROPT(spawnpoint.z, "z", has_z); + GETNUMBER(height_offset, "height"); + GETNUMBER(spawnpoint.angle, "angle"); + GETBOOLEAN(spawnpoint.spawn_on_ceiling, "spawn_on_ceiling"); + GETBOOLEAN(spawnpoint.spawn_flipped, "spawn_flipped"); + } + +#undef GETNUMBER +#undef GETNUMBEROPT +#undef GETBOOLEAN +#undef TYPEERROR + + lua_pop(gL, 2); + } + + if (!has_z) + P_SetAbsoluteSpawnPointHeight(&spawnpoint, height_offset); + else + spawnpoint.z += height_offset; + + spawnpoint_t *result = Z_Calloc(sizeof(spawnpoint_t), PU_STATIC, NULL); + memcpy(result, &spawnpoint, sizeof(spawnpoint_t)); + hook->status.type_void_pointer = result; + } +} + +spawnpoint_t *LUA_HookPlayerRespawn(player_t *player) +{ + Hook_State hook; + if (prepare_hook(&hook, -1, HOOK(PlayerRespawn))) + { + LUA_PushUserdata(gL, player, META_PLAYER); + call_hooks(&hook, 1, res_playerrespawn); + } + return (spawnpoint_t *)hook.status.type_void_pointer; } int LUA_HookPlayerCanEnterSpinGaps(player_t *player) @@ -1180,5 +1283,5 @@ int LUA_HookPlayerCanEnterSpinGaps(player_t *player) LUA_PushUserdata(gL, player, META_PLAYER); call_hooks(&hook, 1, res_force); } - return hook.status; + return hook.status.type_int; } diff --git a/src/p_local.h b/src/p_local.h index f0b0a86e2..a114d43c6 100644 --- a/src/p_local.h +++ b/src/p_local.h @@ -15,6 +15,7 @@ #define __P_LOCAL__ #include "command.h" +#include "doomstat.h" #include "d_player.h" #include "d_think.h" #include "m_fixed.h" @@ -126,6 +127,15 @@ void CV_UpdateCam2Dist(void); extern fixed_t t_cam_dist, t_cam_height, t_cam_rotate; extern fixed_t t_cam2_dist, t_cam2_height, t_cam2_rotate; +// Player spawn points +void P_SpawnPlayer(INT32 playernum); +void P_MovePlayerToSpawn(INT32 playernum, spawnpoint_t *mthing); +void P_MovePlayerToStarpost(INT32 playernum); +void P_AfterPlayerSpawn(INT32 playernum); + +spawnpoint_t *P_MakeSpawnPointFromMapthing(mapthing_t *mthing); +void P_SetAbsoluteSpawnPointHeight(spawnpoint_t *spawnpoint, fixed_t offset); + INT32 P_GetPlayerControlDirection(player_t *player); void P_AddPlayerScore(player_t *player, UINT32 amount); void P_StealPlayerScore(player_t *player, UINT32 amount); diff --git a/src/p_mobj.c b/src/p_mobj.c index 942edff65..0928725c7 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -11726,51 +11726,46 @@ void P_AfterPlayerSpawn(INT32 playernum) } // spawn it at a playerspawn mapthing -void P_MovePlayerToSpawn(INT32 playernum, mapthing_t *mthing) +void P_MovePlayerToSpawn(INT32 playernum, spawnpoint_t *spawnpoint) { - fixed_t x = 0, y = 0; - angle_t angle = 0; - - fixed_t z; - sector_t *sector; - fixed_t floor, ceiling, ceilingspawn; + fixed_t x, y, z; + angle_t angle; player_t *p = &players[playernum]; mobj_t *mobj = p->mo; I_Assert(mobj != NULL); - if (mthing) + if (spawnpoint) { - x = mthing->x << FRACBITS; - y = mthing->y << FRACBITS; - angle = FixedAngle(mthing->angle<x; + y = spawnpoint->y; + angle = spawnpoint->angle; + } + else + { + // Spawn at the origin as a desperation move if there is no spawnpoint + x = 0; + y = 0; + angle = 0; } - //spawn at the origin as a desperation move if there is no mapthing // set Z height - sector = R_PointInSubsector(x, y)->sector; + sector_t *sector = R_PointInSubsector(x, y)->sector; + fixed_t floor = P_GetSectorFloorZAt(sector, x, y); + fixed_t ceiling = P_GetSectorCeilingZAt(sector, x, y); + fixed_t ceilingspawn = ceiling - mobjinfo[MT_PLAYER].height; - floor = P_GetSectorFloorZAt (sector, x, y); - ceiling = P_GetSectorCeilingZAt(sector, x, y); - ceilingspawn = ceiling - mobjinfo[MT_PLAYER].height; - - if (mthing) + if (spawnpoint) { - fixed_t offset = mthing->z << FRACBITS; + z = spawnpoint->z; - // Setting the spawnpoint's args[0] will make the player start on the ceiling - // Objectflip inverts - if (!!(mthing->args[0]) ^ !!(mthing->options & MTF_OBJECTFLIP)) - z = ceilingspawn - offset; - else - z = floor + offset; - - if (mthing->options & MTF_OBJECTFLIP) // flip the player! + if (spawnpoint->spawn_flipped) // flip the player! { mobj->eflags |= MFE_VERTICALFLIP; mobj->flags2 |= MF2_OBJECTFLIP; } - if (mthing->args[0]) + + if (spawnpoint->spawn_on_ceiling) P_SetPlayerMobjState(mobj, S_PLAY_FALL); else if (metalrecording) P_SetPlayerMobjState(mobj, S_PLAY_WAIT); @@ -11857,6 +11852,40 @@ void P_MovePlayerToStarpost(INT32 playernum) leveltime = p->starposttime; } +spawnpoint_t *P_MakeSpawnPointFromMapthing(mapthing_t *mthing) +{ + spawnpoint_t *spawnpoint = Z_Malloc(sizeof(spawnpoint_t), PU_STATIC, NULL); + spawnpoint->x = mthing->x << FRACBITS; + spawnpoint->y = mthing->y << FRACBITS; + spawnpoint->angle = FixedAngle(mthing->angle<spawn_on_ceiling = mthing->args[0]; + spawnpoint->spawn_flipped = mthing->options & MTF_OBJECTFLIP; + + P_SetAbsoluteSpawnPointHeight(spawnpoint, mthing->z << FRACBITS); + + return spawnpoint; +} + +void P_SetAbsoluteSpawnPointHeight(spawnpoint_t *spawnpoint, fixed_t offset) +{ + sector_t *sector = R_PointInSubsector(spawnpoint->x, spawnpoint->y)->sector; + fixed_t floor = P_GetSectorFloorZAt(sector, spawnpoint->x, spawnpoint->y); + fixed_t ceilingspawn = P_GetSectorCeilingZAt(sector, spawnpoint->x, spawnpoint->y) - mobjinfo[MT_PLAYER].height; + + if (!!(spawnpoint->spawn_on_ceiling) ^ !!(spawnpoint->spawn_flipped)) + spawnpoint->z = ceilingspawn - offset; + else + spawnpoint->z = floor + offset; + + if (spawnpoint->z < floor) + spawnpoint->z = floor; + else if (spawnpoint->z > ceilingspawn) + spawnpoint->z = ceilingspawn; +} + fixed_t P_GetMobjSpawnHeight(const mobjtype_t mobjtype, const fixed_t x, const fixed_t y, const fixed_t dz, const fixed_t offset, const boolean flip, const fixed_t scale) { const subsector_t *ss = R_PointInSubsector(x, y); diff --git a/src/p_mobj.h b/src/p_mobj.h index fd959588d..54a160cb1 100644 --- a/src/p_mobj.h +++ b/src/p_mobj.h @@ -486,12 +486,6 @@ void P_AddCachedAction(mobj_t *mobj, INT32 statenum); // check mobj against water content, before movement code void P_MobjCheckWater(mobj_t *mobj); -// Player spawn points -void P_SpawnPlayer(INT32 playernum); -void P_MovePlayerToSpawn(INT32 playernum, mapthing_t *mthing); -void P_MovePlayerToStarpost(INT32 playernum); -void P_AfterPlayerSpawn(INT32 playernum); - fixed_t P_GetMobjSpawnHeight(const mobjtype_t mobjtype, const fixed_t x, const fixed_t y, const fixed_t dz, const fixed_t offset, const boolean flip, const fixed_t scale); fixed_t P_GetMapThingSpawnHeight(const mobjtype_t mobjtype, const mapthing_t* mthing, const fixed_t x, const fixed_t y);