mirror of
https://git.do.srb2.org/STJr/SRB2.git
synced 2024-12-18 17:01:20 +00:00
Add PlayerRespawn hook
This commit is contained in:
parent
fac87627a4
commit
8728ed1ec0
8 changed files with 244 additions and 84 deletions
|
@ -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,
|
||||
|
|
42
src/g_game.c
42
src/g_game.c
|
@ -2836,10 +2836,21 @@ void G_SpawnPlayer(INT32 playernum)
|
|||
|
||||
void G_MovePlayerToSpawnOrStarpost(INT32 playernum)
|
||||
{
|
||||
spawnpoint_t *spawnpoint = LUA_HookPlayerRespawn(&players[playernum]);
|
||||
|
||||
if (spawnpoint == NULL)
|
||||
{
|
||||
if (players[playernum].starposttime)
|
||||
P_MovePlayerToStarpost(playernum);
|
||||
else
|
||||
P_MovePlayerToSpawn(playernum, G_FindMapStart(playernum));
|
||||
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)
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
85
src/p_mobj.c
85
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<<FRACBITS);
|
||||
x = spawnpoint->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<<FRACBITS);
|
||||
|
||||
// Setting the spawnpoint's args[0] will make the player start on the ceiling
|
||||
// Objectflip inverts
|
||||
spawnpoint->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);
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
Loading…
Reference in a new issue