From 3b2ab4da1dd42ece14dd24b2aab199efcb3d8020 Mon Sep 17 00:00:00 2001 From: Monster Iestyn Date: Tue, 21 Jun 2016 22:04:58 +0100 Subject: [PATCH 01/27] added linedef type 446, for making FOFs remotely fall down --- src/p_spec.c | 45 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 45 insertions(+) diff --git a/src/p_spec.c b/src/p_spec.c index 36df3de36..d391ac04c 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -3079,6 +3079,51 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec) } break; + case 446: // Make block fall remotely (acts like FF_CRUMBLE) + { + INT16 sectag = (INT16)(sides[line->sidenum[0]].textureoffset>>FRACBITS); + INT16 foftag = (INT16)(sides[line->sidenum[0]].rowoffset>>FRACBITS); + sector_t *sec; // Sector that the FOF is visible in + ffloor_t *rover; // FOF that we are going to make fall down + player_t *player = NULL; // player that caused FOF to fall + boolean respawn = true; // should the fallen FOF respawn? + + if (mo) // NULL check + player = mo->player; + + if (line->flags & ML_NOCLIMB) // don't respawn! + respawn = false; + + for (secnum = -1; (secnum = P_FindSectorFromTag(sectag, secnum)) >= 0 ;) + { + sec = sectors + secnum; + + if (!sec->ffloors) + { + CONS_Debug(DBG_GAMELOGIC, "Line type 446 Executor: Target sector #%d has no FOFs.\n", secnum); + return; + } + + for (rover = sec->ffloors; rover; rover = rover->next) + { + if (rover->master->frontsector->tag == foftag) + break; + } + + if (!rover) + { + CONS_Debug(DBG_GAMELOGIC, "Line type 446 Executor: Can't find a FOF control sector with tag %d\n", foftag); + return; + } + + if (line->flags & ML_BLOCKMONSTERS) // FOF flags determine respawn ability instead? + respawn = !(rover->flags & FF_NORETURN) ^ !!(line->flags & ML_NOCLIMB); // no climb inverts + + EV_StartCrumble(rover->master->frontsector, rover, (rover->flags & FF_FLOATBOB), player, rover->alpha, respawn); + } + } + break; + case 450: // Execute Linedef Executor - for recursion P_LinedefExecute(line->tag, mo, NULL); break; From c775cdc5ebc7a290806661a4e77b21e48f010aec Mon Sep 17 00:00:00 2001 From: Monster Iestyn Date: Fri, 1 Jul 2016 20:27:09 +0100 Subject: [PATCH 02/27] Added EV_StartCrumble to Lua --- src/lua_baselib.c | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/src/lua_baselib.c b/src/lua_baselib.c index 1bacf9102..4aeab7ad4 100644 --- a/src/lua_baselib.c +++ b/src/lua_baselib.c @@ -1533,6 +1533,33 @@ static int lib_evCrumbleChain(lua_State *L) return 0; } +static int lib_evStartCrumble(lua_State *L) +{ + sector_t *sec = *((sector_t **)luaL_checkudata(L, 1, META_SECTOR)); + ffloor_t *rover = *((ffloor_t **)luaL_checkudata(L, 2, META_FFLOOR)); + boolean floating = lua_optboolean(L, 3); + player_t *player = NULL; + fixed_t origalpha; + boolean crumblereturn = lua_optboolean(L, 6); + NOHUD + if (!sec) + return LUA_ErrInvalid(L, "sector_t"); + if (!rover) + return LUA_ErrInvalid(L, "ffloor_t"); + if (!lua_isnone(L, 4) && lua_isuserdata(L, 4)) + { + player = *((player_t **)luaL_checkudata(L, 4, META_PLAYER)); + if (!player) + return LUA_ErrInvalid(L, "player_t"); + } + if (!lua_isnone(L,5)) + origalpha = luaL_checkfixed(L, 5); + else + origalpha = rover->alpha; + lua_pushboolean(L, EV_StartCrumble(sec, rover, floating, player, origalpha, crumblereturn) != 0); + return 0; +} + // R_DEFS //////////// @@ -2096,6 +2123,7 @@ static luaL_Reg lib[] = { {"P_SetSkyboxMobj",lib_pSetSkyboxMobj}, {"P_StartQuake",lib_pStartQuake}, {"EV_CrumbleChain",lib_evCrumbleChain}, + {"EV_StartCrumble",lib_evStartCrumble}, // r_defs {"R_PointToAngle",lib_rPointToAngle}, From 2ac3f684387272133471c6797b60575dd7b0af45 Mon Sep 17 00:00:00 2001 From: Monster Iestyn Date: Wed, 18 Jan 2017 22:02:28 +0000 Subject: [PATCH 03/27] Added in-level checks to a lot of these functions and tables for Lua use This makes it less likely for the game to crash when stuff is used outside a level when they shouldn't be --- src/lua_baselib.c | 124 +++++++++++++++++++++++++++++++++++++++- src/lua_blockmaplib.c | 3 + src/lua_consolelib.c | 6 +- src/lua_maplib.c | 129 ++++++++++++++++++++++++++++++++++++++++++ src/lua_mobjlib.c | 4 ++ src/lua_playerlib.c | 4 ++ src/lua_thinkerlib.c | 5 ++ 7 files changed, 273 insertions(+), 2 deletions(-) diff --git a/src/lua_baselib.c b/src/lua_baselib.c index def0ad1b3..e73a908c9 100644 --- a/src/lua_baselib.c +++ b/src/lua_baselib.c @@ -25,7 +25,10 @@ #include "lua_libs.h" #include "lua_hud.h" // hud_running errors -#define NOHUD if (hud_running) return luaL_error(L, "HUD rendering code should not call this function!"); +#define NOHUD if (hud_running)\ +return luaL_error(L, "HUD rendering code should not call this function!"); +#define INLEVEL if (gamestate != GS_LEVEL)\ +return luaL_error(L, "This function can only be used in a level!"); boolean luaL_checkboolean(lua_State *L, int narg) { luaL_checktype(L, narg, LUA_TBOOLEAN); @@ -246,6 +249,7 @@ static int lib_pCheckMeleeRange(lua_State *L) { mobj_t *actor = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ)); NOHUD + INLEVEL if (!actor) return LUA_ErrInvalid(L, "mobj_t"); lua_pushboolean(L, P_CheckMeleeRange(actor)); @@ -256,6 +260,7 @@ static int lib_pJetbCheckMeleeRange(lua_State *L) { mobj_t *actor = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ)); NOHUD + INLEVEL if (!actor) return LUA_ErrInvalid(L, "mobj_t"); lua_pushboolean(L, P_JetbCheckMeleeRange(actor)); @@ -266,6 +271,7 @@ static int lib_pFaceStabCheckMeleeRange(lua_State *L) { mobj_t *actor = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ)); NOHUD + INLEVEL if (!actor) return LUA_ErrInvalid(L, "mobj_t"); lua_pushboolean(L, P_FaceStabCheckMeleeRange(actor)); @@ -276,6 +282,7 @@ static int lib_pSkimCheckMeleeRange(lua_State *L) { mobj_t *actor = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ)); NOHUD + INLEVEL if (!actor) return LUA_ErrInvalid(L, "mobj_t"); lua_pushboolean(L, P_SkimCheckMeleeRange(actor)); @@ -286,6 +293,7 @@ static int lib_pCheckMissileRange(lua_State *L) { mobj_t *actor = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ)); NOHUD + INLEVEL if (!actor) return LUA_ErrInvalid(L, "mobj_t"); lua_pushboolean(L, P_CheckMissileRange(actor)); @@ -296,6 +304,7 @@ static int lib_pNewChaseDir(lua_State *L) { mobj_t *actor = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ)); NOHUD + INLEVEL if (!actor) return LUA_ErrInvalid(L, "mobj_t"); P_NewChaseDir(actor); @@ -309,6 +318,7 @@ static int lib_pLookForPlayers(lua_State *L) boolean allaround = lua_optboolean(L, 3); boolean tracer = lua_optboolean(L, 4); NOHUD + INLEVEL if (!actor) return LUA_ErrInvalid(L, "mobj_t"); lua_pushboolean(L, P_LookForPlayers(actor, allaround, tracer, dist)); @@ -325,6 +335,7 @@ static int lib_pSpawnMobj(lua_State *L) fixed_t z = luaL_checkfixed(L, 3); mobjtype_t type = luaL_checkinteger(L, 4); NOHUD + INLEVEL if (type >= NUMMOBJTYPES) return luaL_error(L, "mobj type %d out of range (0 - %d)", type, NUMMOBJTYPES-1); LUA_PushUserdata(L, P_SpawnMobj(x, y, z, type), META_MOBJ); @@ -335,6 +346,7 @@ static int lib_pRemoveMobj(lua_State *L) { mobj_t *th = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ)); NOHUD + INLEVEL if (!th) return LUA_ErrInvalid(L, "mobj_t"); if (th->player) @@ -350,6 +362,7 @@ static int lib_pIsValidSprite2(lua_State *L) mobj_t *mobj = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ)); UINT8 spr2 = (UINT8)luaL_checkinteger(L, 2); //HUDSAFE + INLEVEL if (!mobj) return LUA_ErrInvalid(L, "mobj_t"); lua_pushboolean(L, (mobj->skin && (((skin_t *)mobj->skin)->sprites[spr2].numframes > 0))); @@ -362,6 +375,7 @@ static int lib_pSpawnMissile(lua_State *L) mobj_t *dest = *((mobj_t **)luaL_checkudata(L, 2, META_MOBJ)); mobjtype_t type = luaL_checkinteger(L, 3); NOHUD + INLEVEL if (!source || !dest) return LUA_ErrInvalid(L, "mobj_t"); if (type >= NUMMOBJTYPES) @@ -379,6 +393,7 @@ static int lib_pSpawnXYZMissile(lua_State *L) fixed_t y = luaL_checkfixed(L, 5); fixed_t z = luaL_checkfixed(L, 6); NOHUD + INLEVEL if (!source || !dest) return LUA_ErrInvalid(L, "mobj_t"); if (type >= NUMMOBJTYPES) @@ -398,6 +413,7 @@ static int lib_pSpawnPointMissile(lua_State *L) fixed_t y = luaL_checkfixed(L, 7); fixed_t z = luaL_checkfixed(L, 8); NOHUD + INLEVEL if (!source) return LUA_ErrInvalid(L, "mobj_t"); if (type >= NUMMOBJTYPES) @@ -415,6 +431,7 @@ static int lib_pSpawnAlteredDirectionMissile(lua_State *L) fixed_t z = luaL_checkfixed(L, 5); INT32 shiftingAngle = (INT32)luaL_checkinteger(L, 5); NOHUD + INLEVEL if (!source) return LUA_ErrInvalid(L, "mobj_t"); if (type >= NUMMOBJTYPES) @@ -428,6 +445,7 @@ static int lib_pColorTeamMissile(lua_State *L) mobj_t *missile = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ)); player_t *source = *((player_t **)luaL_checkudata(L, 2, META_PLAYER)); NOHUD + INLEVEL if (!missile) return LUA_ErrInvalid(L, "mobj_t"); if (!source) @@ -444,6 +462,7 @@ static int lib_pSPMAngle(lua_State *L) UINT8 allowaim = (UINT8)luaL_optinteger(L, 4, 0); UINT32 flags2 = (UINT32)luaL_optinteger(L, 5, 0); NOHUD + INLEVEL if (!source) return LUA_ErrInvalid(L, "mobj_t"); if (type >= NUMMOBJTYPES) @@ -458,6 +477,7 @@ static int lib_pSpawnPlayerMissile(lua_State *L) mobjtype_t type = luaL_checkinteger(L, 2); UINT32 flags2 = (UINT32)luaL_optinteger(L, 3, 0); NOHUD + INLEVEL if (!source) return LUA_ErrInvalid(L, "mobj_t"); if (type >= NUMMOBJTYPES) @@ -470,6 +490,7 @@ static int lib_pMobjFlip(lua_State *L) { mobj_t *mobj = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ)); //HUDSAFE + INLEVEL if (!mobj) return LUA_ErrInvalid(L, "mobj_t"); lua_pushinteger(L, P_MobjFlip(mobj)); @@ -480,6 +501,7 @@ static int lib_pGetMobjGravity(lua_State *L) { mobj_t *mobj = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ)); //HUDSAFE + INLEVEL if (!mobj) return LUA_ErrInvalid(L, "mobj_t"); lua_pushfixed(L, P_GetMobjGravity(mobj)); @@ -502,6 +524,7 @@ static int lib_pFlashPal(lua_State *L) UINT16 type = (UINT16)luaL_checkinteger(L, 2); UINT16 duration = (UINT16)luaL_checkinteger(L, 3); NOHUD + INLEVEL if (!pl) return LUA_ErrInvalid(L, "player_t"); P_FlashPal(pl, type, duration); @@ -512,6 +535,7 @@ static int lib_pGetClosestAxis(lua_State *L) { mobj_t *source = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ)); //HUDSAFE + INLEVEL if (!source) return LUA_ErrInvalid(L, "mobj_t"); LUA_PushUserdata(L, P_GetClosestAxis(source), META_MOBJ); @@ -530,6 +554,7 @@ static int lib_pSpawnParaloop(lua_State *L) statenum_t nstate = luaL_optinteger(L, 8, S_NULL); boolean spawncenter = lua_optboolean(L, 9); NOHUD + INLEVEL if (type >= NUMMOBJTYPES) return luaL_error(L, "mobj type %d out of range (0 - %d)", type, NUMMOBJTYPES-1); if (nstate >= NUMSTATES) @@ -543,6 +568,7 @@ static int lib_pBossTargetPlayer(lua_State *L) mobj_t *actor = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ)); boolean closest = lua_optboolean(L, 2); NOHUD + INLEVEL if (!actor) return LUA_ErrInvalid(L, "mobj_t"); lua_pushboolean(L, P_BossTargetPlayer(actor, closest)); @@ -553,6 +579,7 @@ static int lib_pSupermanLook4Players(lua_State *L) { mobj_t *actor = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ)); NOHUD + INLEVEL if (!actor) return LUA_ErrInvalid(L, "mobj_t"); lua_pushboolean(L, P_SupermanLook4Players(actor)); @@ -564,6 +591,7 @@ static int lib_pSetScale(lua_State *L) mobj_t *mobj = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ)); fixed_t newscale = luaL_checkfixed(L, 2); NOHUD + INLEVEL if (!mobj) return LUA_ErrInvalid(L, "mobj_t"); if (newscale < FRACUNIT/100) @@ -577,6 +605,7 @@ static int lib_pInsideANonSolidFFloor(lua_State *L) mobj_t *mobj = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ)); ffloor_t *rover = *((ffloor_t **)luaL_checkudata(L, 2, META_FFLOOR)); //HUDSAFE + INLEVEL if (!mobj) return LUA_ErrInvalid(L, "mobj_t"); if (!rover) @@ -589,6 +618,7 @@ static int lib_pCheckDeathPitCollide(lua_State *L) { mobj_t *mo = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ)); //HUDSAFE + INLEVEL if (!mo) return LUA_ErrInvalid(L, "mobj_t"); lua_pushboolean(L, P_CheckDeathPitCollide(mo)); @@ -600,6 +630,7 @@ static int lib_pCheckSolidLava(lua_State *L) mobj_t *mo = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ)); ffloor_t *rover = *((ffloor_t **)luaL_checkudata(L, 2, META_FFLOOR)); //HUDSAFE + INLEVEL if (!mo) return LUA_ErrInvalid(L, "mobj_t"); if (!rover) @@ -613,6 +644,7 @@ static int lib_pCanRunOnWater(lua_State *L) player_t *player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER)); ffloor_t *rover = *((ffloor_t **)luaL_checkudata(L, 2, META_FFLOOR)); //HUDSAFE + INLEVEL if (!player) return LUA_ErrInvalid(L, "player_t"); if (!rover) @@ -628,6 +660,7 @@ static int lib_pGetPlayerHeight(lua_State *L) { player_t *player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER)); //HUDSAFE + INLEVEL if (!player) return LUA_ErrInvalid(L, "player_t"); lua_pushfixed(L, P_GetPlayerHeight(player)); @@ -638,6 +671,7 @@ static int lib_pGetPlayerSpinHeight(lua_State *L) { player_t *player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER)); //HUDSAFE + INLEVEL if (!player) return LUA_ErrInvalid(L, "player_t"); lua_pushfixed(L, P_GetPlayerSpinHeight(player)); @@ -648,6 +682,7 @@ static int lib_pGetPlayerControlDirection(lua_State *L) { player_t *player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER)); //HUDSAFE + INLEVEL if (!player) return LUA_ErrInvalid(L, "player_t"); lua_pushinteger(L, P_GetPlayerControlDirection(player)); @@ -659,6 +694,7 @@ static int lib_pAddPlayerScore(lua_State *L) player_t *player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER)); UINT32 amount = (UINT32)luaL_checkinteger(L, 2); NOHUD + INLEVEL if (!player) return LUA_ErrInvalid(L, "player_t"); P_AddPlayerScore(player, amount); @@ -670,6 +706,7 @@ static int lib_pStealPlayerScore(lua_State *L) player_t *player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER)); UINT32 amount = (UINT32)luaL_checkinteger(L, 2); NOHUD + INLEVEL if (!player) return LUA_ErrInvalid(L, "player_t"); P_StealPlayerScore(player, amount); @@ -680,6 +717,7 @@ static int lib_pPlayerInPain(lua_State *L) { player_t *player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER)); //HUDSAFE + INLEVEL if (!player) return LUA_ErrInvalid(L, "player_t"); lua_pushboolean(L, P_PlayerInPain(player)); @@ -691,6 +729,7 @@ static int lib_pDoPlayerPain(lua_State *L) player_t *player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER)); mobj_t *source = NULL, *inflictor = NULL; NOHUD + INLEVEL if (!player) return LUA_ErrInvalid(L, "player_t"); if (!lua_isnone(L, 2) && lua_isuserdata(L, 2)) @@ -705,6 +744,7 @@ static int lib_pResetPlayer(lua_State *L) { player_t *player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER)); NOHUD + INLEVEL if (!player) return LUA_ErrInvalid(L, "player_t"); P_ResetPlayer(player); @@ -715,6 +755,7 @@ static int lib_pIsObjectInGoop(lua_State *L) { mobj_t *mo = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ)); //HUDSAFE + INLEVEL if (!mo) return LUA_ErrInvalid(L, "mobj_t"); lua_pushboolean(L, P_IsObjectInGoop(mo)); @@ -725,6 +766,7 @@ static int lib_pIsObjectOnGround(lua_State *L) { mobj_t *mo = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ)); //HUDSAFE + INLEVEL if (!mo) return LUA_ErrInvalid(L, "mobj_t"); lua_pushboolean(L, P_IsObjectOnGround(mo)); @@ -735,6 +777,7 @@ static int lib_pInSpaceSector(lua_State *L) { mobj_t *mo = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ)); //HUDSAFE + INLEVEL if (!mo) return LUA_ErrInvalid(L, "mobj_t"); lua_pushboolean(L, P_InSpaceSector(mo)); @@ -745,6 +788,7 @@ static int lib_pInQuicksand(lua_State *L) { mobj_t *mo = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ)); //HUDSAFE + INLEVEL if (!mo) return LUA_ErrInvalid(L, "mobj_t"); lua_pushboolean(L, P_InQuicksand(mo)); @@ -757,6 +801,7 @@ static int lib_pSetObjectMomZ(lua_State *L) fixed_t value = luaL_checkfixed(L, 2); boolean relative = lua_optboolean(L, 3); NOHUD + INLEVEL if (!mo) return LUA_ErrInvalid(L, "mobj_t"); P_SetObjectMomZ(mo, value, relative); @@ -767,6 +812,7 @@ static int lib_pRestoreMusic(lua_State *L) { player_t *player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER)); NOHUD + INLEVEL if (!player) return LUA_ErrInvalid(L, "player_t"); P_RestoreMusic(player); @@ -777,6 +823,7 @@ static int lib_pSpawnShieldOrb(lua_State *L) { player_t *player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER)); NOHUD + INLEVEL if (!player) return LUA_ErrInvalid(L, "player_t"); P_SpawnShieldOrb(player); @@ -787,6 +834,7 @@ static int lib_pSpawnGhostMobj(lua_State *L) { mobj_t *mobj = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ)); NOHUD + INLEVEL if (!mobj) return LUA_ErrInvalid(L, "mobj_t"); LUA_PushUserdata(L, P_SpawnGhostMobj(mobj), META_MOBJ); @@ -798,6 +846,7 @@ static int lib_pGivePlayerRings(lua_State *L) player_t *player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER)); INT32 num_rings = (INT32)luaL_checkinteger(L, 2); NOHUD + INLEVEL if (!player) return LUA_ErrInvalid(L, "player_t"); P_GivePlayerRings(player, num_rings); @@ -809,6 +858,7 @@ static int lib_pGivePlayerLives(lua_State *L) player_t *player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER)); INT32 numlives = (INT32)luaL_checkinteger(L, 2); NOHUD + INLEVEL if (!player) return LUA_ErrInvalid(L, "player_t"); P_GivePlayerLives(player, numlives); @@ -819,6 +869,7 @@ static int lib_pResetScore(lua_State *L) { player_t *player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER)); NOHUD + INLEVEL if (!player) return LUA_ErrInvalid(L, "player_t"); P_ResetScore(player); @@ -829,6 +880,7 @@ static int lib_pDoJumpShield(lua_State *L) { player_t *player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER)); NOHUD + INLEVEL if (!player) return LUA_ErrInvalid(L, "player_t"); P_DoJumpShield(player); @@ -839,6 +891,7 @@ static int lib_pDoBubbleBounce(lua_State *L) { player_t *player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER)); NOHUD + INLEVEL if (!player) return LUA_ErrInvalid(L, "player_t"); P_DoBubbleBounce(player); @@ -849,6 +902,7 @@ static int lib_pBlackOw(lua_State *L) { player_t *player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER)); NOHUD + INLEVEL if (!player) return LUA_ErrInvalid(L, "player_t"); P_BlackOw(player); @@ -860,6 +914,7 @@ static int lib_pElementalFire(lua_State *L) player_t *player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER)); boolean cropcircle = lua_optboolean(L, 2); NOHUD + INLEVEL if (!player) return LUA_ErrInvalid(L, "player_t"); P_ElementalFire(player, cropcircle); @@ -870,6 +925,7 @@ static int lib_pDoPlayerExit(lua_State *L) { player_t *player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER)); NOHUD + INLEVEL if (!player) return LUA_ErrInvalid(L, "player_t"); P_DoPlayerExit(player); @@ -882,6 +938,7 @@ static int lib_pInstaThrust(lua_State *L) angle_t angle = luaL_checkangle(L, 2); fixed_t move = luaL_checkfixed(L, 3); NOHUD + INLEVEL if (!mo) return LUA_ErrInvalid(L, "mobj_t"); P_InstaThrust(mo, angle, move); @@ -919,6 +976,7 @@ static int lib_pLookForEnemies(lua_State *L) player_t *player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER)); boolean nonenemies = lua_opttrueboolean(L, 2); NOHUD + INLEVEL if (!player) return LUA_ErrInvalid(L, "player_t"); lua_pushboolean(L, P_LookForEnemies(player, nonenemies)); @@ -931,6 +989,7 @@ static int lib_pNukeEnemies(lua_State *L) mobj_t *source = *((mobj_t **)luaL_checkudata(L, 2, META_MOBJ)); fixed_t radius = luaL_checkfixed(L, 3); NOHUD + INLEVEL if (!inflictor || !source) return LUA_ErrInvalid(L, "mobj_t"); P_NukeEnemies(inflictor, source, radius); @@ -942,6 +1001,7 @@ static int lib_pHomingAttack(lua_State *L) mobj_t *source = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ)); mobj_t *enemy = *((mobj_t **)luaL_checkudata(L, 2, META_MOBJ)); NOHUD + INLEVEL if (!source || !enemy) return LUA_ErrInvalid(L, "mobj_t"); P_HomingAttack(source, enemy); @@ -952,6 +1012,7 @@ static int lib_pSuperReady(lua_State *L) { player_t *player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER)); //HUDSAFE + INLEVEL if (!player) return LUA_ErrInvalid(L, "player_t"); lua_pushboolean(L, P_SuperReady(player)); @@ -963,6 +1024,7 @@ static int lib_pDoJump(lua_State *L) player_t *player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER)); boolean soundandstate = (boolean)lua_opttrueboolean(L, 2); NOHUD + INLEVEL if (!player) return LUA_ErrInvalid(L, "player_t"); P_DoJump(player, soundandstate); @@ -973,6 +1035,7 @@ static int lib_pSpawnThokMobj(lua_State *L) { player_t *player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER)); NOHUD + INLEVEL if (!player) return LUA_ErrInvalid(L, "player_t"); P_SpawnThokMobj(player); @@ -984,6 +1047,7 @@ static int lib_pSpawnSpinMobj(lua_State *L) player_t *player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER)); mobjtype_t type = luaL_checkinteger(L, 2); NOHUD + INLEVEL if (!player) return LUA_ErrInvalid(L, "player_t"); if (type >= NUMMOBJTYPES) @@ -998,6 +1062,7 @@ static int lib_pTelekinesis(lua_State *L) fixed_t thrust = luaL_checkfixed(L, 2); fixed_t range = luaL_checkfixed(L, 3); NOHUD + INLEVEL if (!player) return LUA_ErrInvalid(L, "player_t"); P_Telekinesis(player, thrust, range); @@ -1014,6 +1079,7 @@ static int lib_pCheckPosition(lua_State *L) fixed_t x = luaL_checkfixed(L, 2); fixed_t y = luaL_checkfixed(L, 3); NOHUD + INLEVEL if (!thing) return LUA_ErrInvalid(L, "mobj_t"); lua_pushboolean(L, P_CheckPosition(thing, x, y)); @@ -1030,6 +1096,7 @@ static int lib_pTryMove(lua_State *L) fixed_t y = luaL_checkfixed(L, 3); boolean allowdropoff = lua_optboolean(L, 4); NOHUD + INLEVEL if (!thing) return LUA_ErrInvalid(L, "mobj_t"); lua_pushboolean(L, P_TryMove(thing, x, y, allowdropoff)); @@ -1044,6 +1111,7 @@ static int lib_pMove(lua_State *L) mobj_t *actor = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ)); fixed_t speed = luaL_checkfixed(L, 2); NOHUD + INLEVEL if (!actor) return LUA_ErrInvalid(L, "mobj_t"); lua_pushboolean(L, P_Move(actor, speed)); @@ -1060,6 +1128,7 @@ static int lib_pTeleportMove(lua_State *L) fixed_t y = luaL_checkfixed(L, 3); fixed_t z = luaL_checkfixed(L, 4); NOHUD + INLEVEL if (!thing) return LUA_ErrInvalid(L, "mobj_t"); lua_pushboolean(L, P_TeleportMove(thing, x, y, z)); @@ -1072,6 +1141,7 @@ static int lib_pSlideMove(lua_State *L) { mobj_t *mo = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ)); NOHUD + INLEVEL if (!mo) return LUA_ErrInvalid(L, "mobj_t"); P_SlideMove(mo); @@ -1082,6 +1152,7 @@ static int lib_pBounceMove(lua_State *L) { mobj_t *mo = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ)); NOHUD + INLEVEL if (!mo) return LUA_ErrInvalid(L, "mobj_t"); P_BounceMove(mo); @@ -1093,6 +1164,7 @@ static int lib_pCheckSight(lua_State *L) mobj_t *t1 = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ)); mobj_t *t2 = *((mobj_t **)luaL_checkudata(L, 2, META_MOBJ)); //HUDSAFE? + INLEVEL if (!t1 || !t2) return LUA_ErrInvalid(L, "mobj_t"); lua_pushboolean(L, P_CheckSight(t1, t2)); @@ -1107,6 +1179,7 @@ static int lib_pCheckHoopPosition(lua_State *L) fixed_t z = luaL_checkfixed(L, 4); fixed_t radius = luaL_checkfixed(L, 5); NOHUD + INLEVEL if (!hoopthing) return LUA_ErrInvalid(L, "mobj_t"); P_CheckHoopPosition(hoopthing, x, y, z, radius); @@ -1119,6 +1192,7 @@ static int lib_pRadiusAttack(lua_State *L) mobj_t *source = *((mobj_t **)luaL_checkudata(L, 2, META_MOBJ)); fixed_t damagedist = luaL_checkfixed(L, 3); NOHUD + INLEVEL if (!spot || !source) return LUA_ErrInvalid(L, "mobj_t"); P_RadiusAttack(spot, source, damagedist); @@ -1132,6 +1206,7 @@ static int lib_pFloorzAtPos(lua_State *L) fixed_t z = luaL_checkfixed(L, 3); fixed_t height = luaL_checkfixed(L, 4); //HUDSAFE + INLEVEL lua_pushfixed(L, P_FloorzAtPos(x, y, z, height)); return 1; } @@ -1141,6 +1216,7 @@ static int lib_pDoSpring(lua_State *L) mobj_t *spring = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ)); mobj_t *object = *((mobj_t **)luaL_checkudata(L, 2, META_MOBJ)); NOHUD + INLEVEL if (!spring || !object) return LUA_ErrInvalid(L, "mobj_t"); lua_pushboolean(L, P_DoSpring(spring, object)); @@ -1154,6 +1230,7 @@ static int lib_pRemoveShield(lua_State *L) { player_t *player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER)); NOHUD + INLEVEL if (!player) return LUA_ErrInvalid(L, "player_t"); P_RemoveShield(player); @@ -1166,6 +1243,7 @@ static int lib_pDamageMobj(lua_State *L) INT32 damage; UINT8 damagetype; NOHUD + INLEVEL if (!target) return LUA_ErrInvalid(L, "mobj_t"); if (!lua_isnone(L, 2) && lua_isuserdata(L, 2)) @@ -1183,6 +1261,7 @@ static int lib_pKillMobj(lua_State *L) mobj_t *target = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ)), *inflictor = NULL, *source = NULL; UINT8 damagetype; NOHUD + INLEVEL if (!target) return LUA_ErrInvalid(L, "mobj_t"); if (!lua_isnone(L, 2) && lua_isuserdata(L, 2)) @@ -1199,6 +1278,7 @@ static int lib_pPlayerRingBurst(lua_State *L) player_t *player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER)); INT32 num_rings = (INT32)luaL_optinteger(L, 2, -1); NOHUD + INLEVEL if (!player) return LUA_ErrInvalid(L, "player_t"); if (num_rings == -1) @@ -1211,6 +1291,7 @@ static int lib_pPlayerWeaponPanelBurst(lua_State *L) { player_t *player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER)); NOHUD + INLEVEL if (!player) return LUA_ErrInvalid(L, "player_t"); P_PlayerWeaponPanelBurst(player); @@ -1221,6 +1302,7 @@ static int lib_pPlayerWeaponAmmoBurst(lua_State *L) { player_t *player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER)); NOHUD + INLEVEL if (!player) return LUA_ErrInvalid(L, "player_t"); P_PlayerWeaponAmmoBurst(player); @@ -1231,6 +1313,7 @@ static int lib_pPlayerWeaponPanelOrAmmoBurst(lua_State *L) { player_t *player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER)); NOHUD + INLEVEL if (!player) return LUA_ErrInvalid(L, "player_t"); P_PlayerWeaponPanelOrAmmoBurst(player); @@ -1242,6 +1325,7 @@ static int lib_pPlayerEmeraldBurst(lua_State *L) player_t *player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER)); boolean toss = lua_optboolean(L, 2); NOHUD + INLEVEL if (!player) return LUA_ErrInvalid(L, "player_t"); P_PlayerEmeraldBurst(player, toss); @@ -1253,6 +1337,7 @@ static int lib_pPlayerFlagBurst(lua_State *L) player_t *player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER)); boolean toss = lua_optboolean(L, 2); NOHUD + INLEVEL if (!player) return LUA_ErrInvalid(L, "player_t"); P_PlayerFlagBurst(player, toss); @@ -1264,6 +1349,7 @@ static int lib_pPlayRinglossSound(lua_State *L) mobj_t *source = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ)); player_t *player = NULL; NOHUD + INLEVEL if (!source) return LUA_ErrInvalid(L, "mobj_t"); if (!lua_isnone(L, 2) && lua_isuserdata(L, 2)) @@ -1282,6 +1368,7 @@ static int lib_pPlayDeathSound(lua_State *L) mobj_t *source = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ)); player_t *player = NULL; NOHUD + INLEVEL if (!source) return LUA_ErrInvalid(L, "mobj_t"); if (!lua_isnone(L, 2) && lua_isuserdata(L, 2)) @@ -1300,6 +1387,7 @@ static int lib_pPlayVictorySound(lua_State *L) mobj_t *source = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ)); player_t *player = NULL; NOHUD + INLEVEL if (!source) return LUA_ErrInvalid(L, "mobj_t"); if (!lua_isnone(L, 2) && lua_isuserdata(L, 2)) @@ -1317,6 +1405,7 @@ static int lib_pPlayLivesJingle(lua_State *L) { player_t *player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER)); NOHUD + INLEVEL if (!player) return LUA_ErrInvalid(L, "player_t"); P_PlayLivesJingle(player); @@ -1328,6 +1417,7 @@ static int lib_pCanPickupItem(lua_State *L) player_t *player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER)); boolean weapon = lua_optboolean(L, 2); //HUDSAFE + INLEVEL if (!player) return LUA_ErrInvalid(L, "player_t"); lua_pushboolean(L, P_CanPickupItem(player, weapon)); @@ -1338,6 +1428,7 @@ static int lib_pDoNightsScore(lua_State *L) { player_t *player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER)); NOHUD + INLEVEL if (!player) return LUA_ErrInvalid(L, "player_t"); P_DoNightsScore(player); @@ -1348,6 +1439,7 @@ static int lib_pDoMatchSuper(lua_State *L) { player_t *player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER)); NOHUD + INLEVEL if (!player) return LUA_ErrInvalid(L, "player_t"); P_DoMatchSuper(player); @@ -1363,6 +1455,7 @@ static int lib_pThrust(lua_State *L) angle_t angle = luaL_checkangle(L, 2); fixed_t move = luaL_checkfixed(L, 3); NOHUD + INLEVEL if (!mo) return LUA_ErrInvalid(L, "mobj_t"); P_Thrust(mo, angle, move); @@ -1374,6 +1467,7 @@ static int lib_pSetMobjStateNF(lua_State *L) mobj_t *mobj = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ)); statenum_t state = luaL_checkinteger(L, 2); NOHUD + INLEVEL if (!mobj) return LUA_ErrInvalid(L, "mobj_t"); if (state >= NUMSTATES) @@ -1389,6 +1483,7 @@ static int lib_pDoSuperTransformation(lua_State *L) player_t *player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER)); boolean giverings = lua_optboolean(L, 2); NOHUD + INLEVEL if (!player) return LUA_ErrInvalid(L, "player_t"); P_DoSuperTransformation(player, giverings); @@ -1399,6 +1494,7 @@ static int lib_pExplodeMissile(lua_State *L) { mobj_t *mo = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ)); NOHUD + INLEVEL if (!mo) return LUA_ErrInvalid(L, "mobj_t"); P_ExplodeMissile(mo); @@ -1411,6 +1507,7 @@ static int lib_pPlayerTouchingSectorSpecial(lua_State *L) INT32 section = (INT32)luaL_checkinteger(L, 2); INT32 number = (INT32)luaL_checkinteger(L, 3); //HUDSAFE + INLEVEL if (!player) return LUA_ErrInvalid(L, "player_t"); LUA_PushUserdata(L, P_PlayerTouchingSectorSpecial(player, section, number), META_SECTOR); @@ -1423,6 +1520,7 @@ static int lib_pFindSpecialLineFromTag(lua_State *L) INT16 line = (INT16)luaL_checkinteger(L, 2); INT32 start = (INT32)luaL_optinteger(L, 3, -1); NOHUD + INLEVEL lua_pushinteger(L, P_FindSpecialLineFromTag(special, line, start)); return 1; } @@ -1432,6 +1530,7 @@ static int lib_pSwitchWeather(lua_State *L) INT32 weathernum = (INT32)luaL_checkinteger(L, 1); player_t *user = NULL; NOHUD + INLEVEL if (!lua_isnone(L, 2) && lua_isuserdata(L, 2)) // if a player, setup weather for only the player, otherwise setup weather for all players user = *((player_t **)luaL_checkudata(L, 2, META_PLAYER)); if (!user) // global @@ -1447,6 +1546,7 @@ static int lib_pLinedefExecute(lua_State *L) mobj_t *actor = NULL; sector_t *caller = NULL; NOHUD + INLEVEL if (!lua_isnone(L, 2) && lua_isuserdata(L, 2)) actor = *((mobj_t **)luaL_checkudata(L, 2, META_MOBJ)); if (!lua_isnone(L, 3) && lua_isuserdata(L, 3)) @@ -1459,6 +1559,7 @@ static int lib_pSpawnLightningFlash(lua_State *L) { sector_t *sector = *((sector_t **)luaL_checkudata(L, 1, META_SECTOR)); NOHUD + INLEVEL if (!sector) return LUA_ErrInvalid(L, "sector_t"); P_SpawnLightningFlash(sector); @@ -1471,6 +1572,7 @@ static int lib_pFadeLight(lua_State *L) INT32 destvalue = (INT32)luaL_checkinteger(L, 2); INT32 speed = (INT32)luaL_checkinteger(L, 3); NOHUD + INLEVEL P_FadeLight(tag, destvalue, speed); return 0; } @@ -1479,6 +1581,7 @@ static int lib_pThingOnSpecial3DFloor(lua_State *L) { mobj_t *mo = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ)); NOHUD + INLEVEL if (!mo) return LUA_ErrInvalid(L, "mobj_t"); LUA_PushUserdata(L, P_ThingOnSpecial3DFloor(mo), META_SECTOR); @@ -1489,6 +1592,7 @@ static int lib_pIsFlagAtBase(lua_State *L) { mobjtype_t flag = luaL_checkinteger(L, 1); NOHUD + INLEVEL if (flag >= NUMMOBJTYPES) return luaL_error(L, "mobj type %d out of range (0 - %d)", flag, NUMMOBJTYPES-1); lua_pushboolean(L, P_IsFlagAtBase(flag)); @@ -1500,6 +1604,7 @@ static int lib_pSetupLevelSky(lua_State *L) INT32 skynum = (INT32)luaL_checkinteger(L, 1); player_t *user = NULL; NOHUD + INLEVEL if (!lua_isnone(L, 2) && lua_isuserdata(L, 2)) // if a player, setup sky for only the player, otherwise setup sky for all players user = *((player_t **)luaL_checkudata(L, 2, META_PLAYER)); if (!user) // global @@ -1518,6 +1623,7 @@ static int lib_pSetSkyboxMobj(lua_State *L) int w = 0; NOHUD + INLEVEL if (!lua_isnil(L,1)) // nil leaves mo as NULL to remove the skybox rendering. { mo = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ)); // otherwise it is a skybox mobj. @@ -1564,6 +1670,7 @@ static int lib_pStartQuake(lua_State *L) static mappoint_t q_epicenter = {0,0,0}; NOHUD + INLEVEL // While technically we don't support epicenter and radius, // we get their values anyway if they exist. @@ -1625,6 +1732,7 @@ static int lib_evCrumbleChain(lua_State *L) sector_t *sec = *((sector_t **)luaL_checkudata(L, 1, META_SECTOR)); ffloor_t *rover = *((ffloor_t **)luaL_checkudata(L, 2, META_FFLOOR)); NOHUD + INLEVEL if (!sec) return LUA_ErrInvalid(L, "sector_t"); if (!rover) @@ -1681,6 +1789,7 @@ static int lib_rPointInSubsector(lua_State *L) fixed_t x = luaL_checkfixed(L, 1); fixed_t y = luaL_checkfixed(L, 2); //HUDSAFE + INLEVEL LUA_PushUserdata(L, R_PointInSubsector(x, y), META_SUBSECTOR); return 1; } @@ -1715,6 +1824,7 @@ static int lib_rSetPlayerSkin(lua_State *L) { player_t *player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER)); NOHUD + INLEVEL if (!player) return LUA_ErrInvalid(L, "player_t"); if (lua_isnoneornil(L, 2)) @@ -1899,6 +2009,7 @@ static int lib_sOriginPlaying(lua_State *L) { void *origin = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ)); NOHUD + INLEVEL if (!origin) return LUA_ErrInvalid(L, "mobj_t"); lua_pushboolean(L, S_OriginPlaying(origin)); @@ -1920,6 +2031,7 @@ static int lib_sSoundPlaying(lua_State *L) void *origin = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ)); sfxenum_t id = luaL_checkinteger(L, 2); NOHUD + INLEVEL if (!origin) return LUA_ErrInvalid(L, "mobj_t"); if (id >= NUMSFX) @@ -1935,6 +2047,7 @@ static int lib_gBuildMapName(lua_State *L) { INT32 map = luaL_optinteger(L, 1, gamemap); //HUDSAFE + INLEVEL lua_pushstring(L, G_BuildMapName(map)); return 1; } @@ -1943,6 +2056,7 @@ static int lib_gDoReborn(lua_State *L) { INT32 playernum = luaL_checkinteger(L, 1); NOHUD + INLEVEL if (playernum >= MAXPLAYERS) return luaL_error(L, "playernum %d out of range (0 - %d)", playernum, MAXPLAYERS-1); G_DoReborn(playernum); @@ -1953,6 +2067,7 @@ static int lib_gExitLevel(lua_State *L) { int n = lua_gettop(L); // Num arguments NOHUD + INLEVEL // LUA EXTENSION: Custom exit like support // Supported: @@ -1979,6 +2094,7 @@ static int lib_gIsSpecialStage(lua_State *L) { INT32 mapnum = luaL_optinteger(L, 1, gamemap); //HUDSAFE + INLEVEL lua_pushboolean(L, G_IsSpecialStage(mapnum)); return 1; } @@ -1986,6 +2102,7 @@ static int lib_gIsSpecialStage(lua_State *L) static int lib_gGametypeUsesLives(lua_State *L) { //HUDSAFE + INLEVEL lua_pushboolean(L, G_GametypeUsesLives()); return 1; } @@ -1993,6 +2110,7 @@ static int lib_gGametypeUsesLives(lua_State *L) static int lib_gGametypeHasTeams(lua_State *L) { //HUDSAFE + INLEVEL lua_pushboolean(L, G_GametypeHasTeams()); return 1; } @@ -2000,6 +2118,7 @@ static int lib_gGametypeHasTeams(lua_State *L) static int lib_gGametypeHasSpectators(lua_State *L) { //HUDSAFE + INLEVEL lua_pushboolean(L, G_GametypeHasSpectators()); return 1; } @@ -2007,6 +2126,7 @@ static int lib_gGametypeHasSpectators(lua_State *L) static int lib_gRingSlingerGametype(lua_State *L) { //HUDSAFE + INLEVEL lua_pushboolean(L, G_RingSlingerGametype()); return 1; } @@ -2014,6 +2134,7 @@ static int lib_gRingSlingerGametype(lua_State *L) static int lib_gPlatformGametype(lua_State *L) { //HUDSAFE + INLEVEL lua_pushboolean(L, G_PlatformGametype()); return 1; } @@ -2021,6 +2142,7 @@ static int lib_gPlatformGametype(lua_State *L) static int lib_gTagGametype(lua_State *L) { //HUDSAFE + INLEVEL lua_pushboolean(L, G_TagGametype()); return 1; } diff --git a/src/lua_blockmaplib.c b/src/lua_blockmaplib.c index 33f350d69..d90ef4d67 100644 --- a/src/lua_blockmaplib.c +++ b/src/lua_blockmaplib.c @@ -186,6 +186,9 @@ static int lib_searchBlockmap(lua_State *L) UINT8 funcret = 0; blockmap_func searchFunc; + if (gamestate != GS_LEVEL) + return luaL_error(L, "This function can only be used in a level!"); + lua_remove(L, 1); // remove searchtype, stack is now function, mobj, [x1, x2, y1, y2] luaL_checktype(L, 1, LUA_TFUNCTION); diff --git a/src/lua_consolelib.c b/src/lua_consolelib.c index 28cc91762..322fecb64 100644 --- a/src/lua_consolelib.c +++ b/src/lua_consolelib.c @@ -22,7 +22,10 @@ #include "lua_libs.h" #include "lua_hud.h" // hud_running errors -#define NOHUD if (hud_running) return luaL_error(L, "HUD rendering code should not call this function!"); +#define NOHUD if (hud_running)\ +return luaL_error(L, "HUD rendering code should not call this function!"); +#define INLEVEL if (gamestate != GS_LEVEL)\ +return luaL_error(L, "This function can only be used in a level!"); static const char *cvname = NULL; @@ -412,6 +415,7 @@ static int lib_consPrintf(lua_State *L) if (n < 2) return luaL_error(L, "CONS_Printf requires at least two arguments: player and text."); //HUDSAFE + INLEVEL plr = *((player_t **)luaL_checkudata(L, 1, META_PLAYER)); if (!plr) return LUA_ErrInvalid(L, "player_t"); diff --git a/src/lua_maplib.c b/src/lua_maplib.c index 9f6d3e7fa..f1bfcb8f1 100644 --- a/src/lua_maplib.c +++ b/src/lua_maplib.c @@ -264,12 +264,19 @@ static const char *const bbox_opt[] = { static const char *const array_opt[] ={"iterate",NULL}; static const char *const valid_opt[] ={"valid",NULL}; +/////////////////////////////////// +// sector list iterate functions // +/////////////////////////////////// + // iterates through a sector's thinglist! static int lib_iterateSectorThinglist(lua_State *L) { mobj_t *state = NULL; mobj_t *thing = NULL; + if (gamestate != GS_LEVEL) + return luaL_error(L, "This function can only be used in a level!"); + if (lua_gettop(L) < 2) return luaL_error(L, "Don't call sector.thinglist() directly, use it as 'for rover in sector.thinglist do end'."); @@ -303,6 +310,9 @@ static int lib_iterateSectorFFloors(lua_State *L) ffloor_t *state = NULL; ffloor_t *ffloor = NULL; + if (gamestate != GS_LEVEL) + return luaL_error(L, "This function can only be used in a level!"); + if (lua_gettop(L) < 2) return luaL_error(L, "Don't call sector.ffloors() directly, use it as 'for rover in sector.ffloors do end'."); @@ -338,6 +348,10 @@ static int sector_iterate(lua_State *L) return 3; } +//////////////////// +// sector.lines[] // +//////////////////// + // sector.lines, i -> sector.lines[i] // sector.lines.valid, for validity checking static int sectorlines_get(lua_State *L) @@ -399,6 +413,10 @@ static int sectorlines_num(lua_State *L) return 1; } +////////////// +// sector_t // +////////////// + static int sector_get(lua_State *L) { sector_t *sector = *((sector_t **)luaL_checkudata(L, 1, META_SECTOR)); @@ -540,6 +558,10 @@ static int sector_num(lua_State *L) return 1; } +///////////////// +// subsector_t // +///////////////// + static int subsector_get(lua_State *L) { subsector_t *subsector = *((subsector_t **)luaL_checkudata(L, 1, META_SUBSECTOR)); @@ -579,6 +601,10 @@ static int subsector_num(lua_State *L) return 1; } +//////////// +// line_t // +//////////// + static int line_get(lua_State *L) { line_t *line = *((line_t **)luaL_checkudata(L, 1, META_LINE)); @@ -676,6 +702,10 @@ static int line_num(lua_State *L) return 1; } +//////////////////// +// line.sidenum[] // +//////////////////// + static int sidenum_get(lua_State *L) { UINT16 *sidenum = *((UINT16 **)luaL_checkudata(L, 1, META_SIDENUM)); @@ -704,6 +734,10 @@ static int sidenum_get(lua_State *L) return 1; } +//////////// +// side_t // +//////////// + static int side_get(lua_State *L) { side_t *side = *((side_t **)luaL_checkudata(L, 1, META_SIDE)); @@ -805,6 +839,10 @@ static int side_num(lua_State *L) return 1; } +////////////// +// vertex_t // +////////////// + static int vertex_get(lua_State *L) { vertex_t *vertex = *((vertex_t **)luaL_checkudata(L, 1, META_VERTEX)); @@ -845,6 +883,11 @@ static int vertex_num(lua_State *L) } #ifdef HAVE_LUA_SEGS + +/////////// +// seg_t // +/////////// + static int seg_get(lua_State *L) { seg_t *seg = *((seg_t **)luaL_checkudata(L, 1, META_SEG)); @@ -902,6 +945,10 @@ static int seg_num(lua_State *L) return 1; } +//////////// +// node_t // +//////////// + static int node_get(lua_State *L) { node_t *node = *((node_t **)luaL_checkudata(L, 1, META_NODE)); @@ -949,6 +996,11 @@ static int node_num(lua_State *L) lua_pushinteger(L, node-nodes); return 1; } + +/////////////// +// node.bbox // +/////////////// + /* // node.bbox[i][j]: i = 0 or 1, j = 0 1 2 or 3 // NOTE: 2D arrays are NOT double pointers, @@ -1028,6 +1080,10 @@ static int nodebbox_call(lua_State *L) return 1; } +///////////////////// +// node.children[] // +///////////////////// + // node.children[i]: i = 0 or 1 static int nodechildren_get(lua_State *L) { @@ -1063,6 +1119,10 @@ static int nodechildren_get(lua_State *L) } #endif +////////// +// bbox // +////////// + // bounding box (aka fixed_t array with four elements) // NOTE: may be useful for polyobjects or other things later static int bbox_get(lua_State *L) @@ -1100,9 +1160,15 @@ static int bbox_get(lua_State *L) return 1; } +/////////////// +// sectors[] // +/////////////// + static int lib_iterateSectors(lua_State *L) { size_t i = 0; + if (gamestate != GS_LEVEL) + return luaL_error(L, "This function can only be used in a level!"); if (lua_gettop(L) < 2) return luaL_error(L, "Don't call sectors.iterate() directly, use it as 'for sector in sectors.iterate do end'."); lua_settop(L, 2); @@ -1120,6 +1186,8 @@ static int lib_iterateSectors(lua_State *L) static int lib_getSector(lua_State *L) { int field; + if (gamestate != GS_LEVEL) + return luaL_error(L, "You cannot access this outside of a level!"); lua_settop(L, 2); lua_remove(L, 1); // dummy userdata table is unused. if (lua_isnumber(L, 1)) @@ -1146,9 +1214,15 @@ static int lib_numsectors(lua_State *L) return 1; } +////////////////// +// subsectors[] // +////////////////// + static int lib_iterateSubsectors(lua_State *L) { size_t i = 0; + if (gamestate != GS_LEVEL) + return luaL_error(L, "This function can only be used in a level!"); if (lua_gettop(L) < 2) return luaL_error(L, "Don't call subsectors.iterate() directly, use it as 'for subsector in subsectors.iterate do end'."); lua_settop(L, 2); @@ -1166,6 +1240,8 @@ static int lib_iterateSubsectors(lua_State *L) static int lib_getSubsector(lua_State *L) { int field; + if (gamestate != GS_LEVEL) + return luaL_error(L, "You cannot access this outside of a level!"); lua_settop(L, 2); lua_remove(L, 1); // dummy userdata table is unused. if (lua_isnumber(L, 1)) @@ -1192,9 +1268,15 @@ static int lib_numsubsectors(lua_State *L) return 1; } +///////////// +// lines[] // +///////////// + static int lib_iterateLines(lua_State *L) { size_t i = 0; + if (gamestate != GS_LEVEL) + return luaL_error(L, "This function can only be used in a level!"); if (lua_gettop(L) < 2) return luaL_error(L, "Don't call lines.iterate() directly, use it as 'for line in lines.iterate do end'."); lua_settop(L, 2); @@ -1212,6 +1294,8 @@ static int lib_iterateLines(lua_State *L) static int lib_getLine(lua_State *L) { int field; + if (gamestate != GS_LEVEL) + return luaL_error(L, "You cannot access this outside of a level!"); lua_settop(L, 2); lua_remove(L, 1); // dummy userdata table is unused. if (lua_isnumber(L, 1)) @@ -1238,9 +1322,15 @@ static int lib_numlines(lua_State *L) return 1; } +///////////// +// sides[] // +///////////// + static int lib_iterateSides(lua_State *L) { size_t i = 0; + if (gamestate != GS_LEVEL) + return luaL_error(L, "This function can only be used in a level!"); if (lua_gettop(L) < 2) return luaL_error(L, "Don't call sides.iterate() directly, use it as 'for side in sides.iterate do end'."); lua_settop(L, 2); @@ -1258,6 +1348,8 @@ static int lib_iterateSides(lua_State *L) static int lib_getSide(lua_State *L) { int field; + if (gamestate != GS_LEVEL) + return luaL_error(L, "You cannot access this outside of a level!"); lua_settop(L, 2); lua_remove(L, 1); // dummy userdata table is unused. if (lua_isnumber(L, 1)) @@ -1284,9 +1376,15 @@ static int lib_numsides(lua_State *L) return 1; } +//////////////// +// vertexes[] // +//////////////// + static int lib_iterateVertexes(lua_State *L) { size_t i = 0; + if (gamestate != GS_LEVEL) + return luaL_error(L, "This function can only be used in a level!"); if (lua_gettop(L) < 2) return luaL_error(L, "Don't call vertexes.iterate() directly, use it as 'for vertex in vertexes.iterate do end'."); lua_settop(L, 2); @@ -1304,6 +1402,8 @@ static int lib_iterateVertexes(lua_State *L) static int lib_getVertex(lua_State *L) { int field; + if (gamestate != GS_LEVEL) + return luaL_error(L, "You cannot access this outside of a level!"); lua_settop(L, 2); lua_remove(L, 1); // dummy userdata table is unused. if (lua_isnumber(L, 1)) @@ -1331,9 +1431,16 @@ static int lib_numvertexes(lua_State *L) } #ifdef HAVE_LUA_SEGS + +//////////// +// segs[] // +//////////// + static int lib_iterateSegs(lua_State *L) { size_t i = 0; + if (gamestate != GS_LEVEL) + return luaL_error(L, "This function can only be used in a level!"); if (lua_gettop(L) < 2) return luaL_error(L, "Don't call segs.iterate() directly, use it as 'for seg in segs.iterate do end'."); lua_settop(L, 2); @@ -1351,6 +1458,8 @@ static int lib_iterateSegs(lua_State *L) static int lib_getSeg(lua_State *L) { int field; + if (gamestate != GS_LEVEL) + return luaL_error(L, "You cannot access this outside of a level!"); lua_settop(L, 2); lua_remove(L, 1); // dummy userdata table is unused. if (lua_isnumber(L, 1)) @@ -1377,9 +1486,15 @@ static int lib_numsegs(lua_State *L) return 1; } +///////////// +// nodes[] // +///////////// + static int lib_iterateNodes(lua_State *L) { size_t i = 0; + if (gamestate != GS_LEVEL) + return luaL_error(L, "This function can only be used in a level!"); if (lua_gettop(L) < 2) return luaL_error(L, "Don't call nodes.iterate() directly, use it as 'for node in nodes.iterate do end'."); lua_settop(L, 2); @@ -1397,6 +1512,8 @@ static int lib_iterateNodes(lua_State *L) static int lib_getNode(lua_State *L) { int field; + if (gamestate != GS_LEVEL) + return luaL_error(L, "You cannot access this outside of a level!"); lua_settop(L, 2); lua_remove(L, 1); // dummy userdata table is unused. if (lua_isnumber(L, 1)) @@ -1424,6 +1541,10 @@ static int lib_numnodes(lua_State *L) } #endif +////////////// +// ffloor_t // +////////////// + static int ffloor_get(lua_State *L) { ffloor_t *ffloor = *((ffloor_t **)luaL_checkudata(L, 1, META_FFLOOR)); @@ -1567,6 +1688,10 @@ static int ffloor_set(lua_State *L) return 0; } +///////////////////// +// mapheaderinfo[] // +///////////////////// + static int lib_getMapheaderinfo(lua_State *L) { // i -> mapheaderinfo[i-1] @@ -1599,6 +1724,10 @@ static int lib_nummapheaders(lua_State *L) return 1; } +///////////////// +// mapheader_t // +///////////////// + static int mapheaderinfo_get(lua_State *L) { mapheader_t *header = *((mapheader_t **)luaL_checkudata(L, 1, META_MAPHEADER)); diff --git a/src/lua_mobjlib.c b/src/lua_mobjlib.c index 9ebc38a61..93febf209 100644 --- a/src/lua_mobjlib.c +++ b/src/lua_mobjlib.c @@ -751,6 +751,8 @@ static int mapthing_set(lua_State *L) static int lib_iterateMapthings(lua_State *L) { size_t i = 0; + if (gamestate != GS_LEVEL) + return luaL_error(L, "This function can only be used in a level!"); if (lua_gettop(L) < 2) return luaL_error(L, "Don't call mapthings.iterate() directly, use it as 'for mapthing in mapthings.iterate do end'."); lua_settop(L, 2); @@ -768,6 +770,8 @@ static int lib_iterateMapthings(lua_State *L) static int lib_getMapthing(lua_State *L) { int field; + if (gamestate != GS_LEVEL) + return luaL_error(L, "You cannot access this outside of a level!"); lua_settop(L, 2); lua_remove(L, 1); // dummy userdata table is unused. if (lua_isnumber(L, 1)) diff --git a/src/lua_playerlib.c b/src/lua_playerlib.c index 29f1c6ff0..0900528ed 100644 --- a/src/lua_playerlib.c +++ b/src/lua_playerlib.c @@ -25,6 +25,8 @@ static int lib_iteratePlayers(lua_State *L) { INT32 i = -1; + if (gamestate != GS_LEVEL) + return luaL_error(L, "This function can only be used in a level!"); if (lua_gettop(L) < 2) { //return luaL_error(L, "Don't call players.iterate() directly, use it as 'for player in players.iterate do end'."); @@ -51,6 +53,8 @@ static int lib_getPlayer(lua_State *L) { const char *field; // i -> players[i] + if (gamestate != GS_LEVEL) + return luaL_error(L, "You cannot access this outside of a level!"); if (lua_type(L, 2) == LUA_TNUMBER) { lua_Integer i = luaL_checkinteger(L, 2); diff --git a/src/lua_thinkerlib.c b/src/lua_thinkerlib.c index d5251425a..b8cf1baec 100644 --- a/src/lua_thinkerlib.c +++ b/src/lua_thinkerlib.c @@ -29,6 +29,9 @@ static int lib_iterateThinkers(lua_State *L) actionf_p1 searchFunc; const char *searchMeta; + if (gamestate != GS_LEVEL) + return luaL_error(L, "This function can only be used in a level!"); + lua_settop(L, 2); lua_remove(L, 1); // remove state now. @@ -84,6 +87,8 @@ static int lib_iterateThinkers(lua_State *L) static int lib_startIterate(lua_State *L) { + if (gamestate != GS_LEVEL) + return luaL_error(L, "This function can only be used in a level!"); luaL_checkoption(L, 1, iter_opt[0], iter_opt); lua_pushcfunction(L, lib_iterateThinkers); lua_pushvalue(L, 1); From 1b542c6501d8dfec42f4357cba9b3542cc36f894 Mon Sep 17 00:00:00 2001 From: Monster Iestyn Date: Thu, 19 Jan 2017 18:30:55 +0000 Subject: [PATCH 04/27] Added userdataType(userdata) function to Lua! This new function returns a string representing the type of userdata the variable given (e.g. mobj_t, player_t), it even works on "minor" userdata types (player_t.powers, skin_t.soundsid, sector_t.lines, etc) --- src/lua_baselib.c | 166 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 166 insertions(+) diff --git a/src/lua_baselib.c b/src/lua_baselib.c index e73a908c9..e0584bd1c 100644 --- a/src/lua_baselib.c +++ b/src/lua_baselib.c @@ -87,6 +87,171 @@ static int lib_print(lua_State *L) return 0; } +enum +{ + UTYPE_NULL=0, + UTYPE_STATE, + UTYPE_MOBJINFO, + UTYPE_SFXINFO, + + UTYPE_MOBJ, + UTYPE_MAPTHING, + + UTYPE_PLAYER, + UTYPE_TICCMD, + UTYPE_SKIN, + UTYPE_POWERS, + UTYPE_SOUNDSID, + + UTYPE_VERTEX, + UTYPE_LINE, + UTYPE_SIDE, + UTYPE_SUBSECTOR, + UTYPE_SECTOR, + UTYPE_FFLOOR, +#ifdef HAVE_LUA_SEGS + UTYPE_SEG, + UTYPE_NODE, +#endif + UTYPE_MAPHEADER, + + UTYPE_CVAR, + + UTYPE_SECTORLINES, + UTYPE_SIDENUM, +#ifdef HAVE_LUA_SEGS + UTYPE_NODEBBOX, + UTYPE_NODECHILDREN, +#endif + + UTYPE_BBOX, + + UTYPE_HUDINFO, + UTYPE_PATCH, + UTYPE_COLORMAP, + UTYPE_CAMERA, +}; + +#define META_UTYPE(name) {META_##name, UTYPE_##name} +static const struct { + const char *meta; + UINT8 utype; +} meta2utype[] = { + META_UTYPE(STATE), + META_UTYPE(MOBJINFO), + META_UTYPE(SFXINFO), + + META_UTYPE(MOBJ), + META_UTYPE(MAPTHING), + + META_UTYPE(PLAYER), + META_UTYPE(TICCMD), + META_UTYPE(SKIN), + META_UTYPE(POWERS), + META_UTYPE(SOUNDSID), + + META_UTYPE(VERTEX), + META_UTYPE(LINE), + META_UTYPE(SIDE), + META_UTYPE(SUBSECTOR), + META_UTYPE(SECTOR), + META_UTYPE(FFLOOR), +#ifdef HAVE_LUA_SEGS + META_UTYPE(SEG), + META_UTYPE(NODE), +#endif + META_UTYPE(MAPHEADER), + + META_UTYPE(CVAR), + + META_UTYPE(SECTORLINES), + META_UTYPE(SIDENUM), +#ifdef HAVE_LUA_SEGS + META_UTYPE(NODEBBOX), + META_UTYPE(NODECHILDREN), +#endif + + META_UTYPE(BBOX), + + META_UTYPE(HUDINFO), + META_UTYPE(PATCH), + META_UTYPE(COLORMAP), + META_UTYPE(CAMERA), + {NULL, UTYPE_NULL} +}; +#undef META_UTYPE + +static UINT8 GetUserdataUType(lua_State *L) +{ + UINT8 i; + lua_getmetatable(L, -1); + + for (i = 0; meta2utype[i].meta; i++) + { + luaL_getmetatable(L, meta2utype[i].meta); + if (lua_rawequal(L, -1, -2)) + { + lua_pop(L, 2); + return meta2utype[i].utype; + } + lua_pop(L, 1); + } + + lua_pop(L, 1); + return UTYPE_NULL; +} + +static int lib_userdataType(lua_State *L) +{ + lua_settop(L, 1); // pop everything except arg 1 (in case somebody decided to add more) + luaL_checktype(L, 1, LUA_TUSERDATA); + switch (GetUserdataUType(L)) + { + case UTYPE_STATE: lua_pushliteral(L, "state_t"); break; + case UTYPE_MOBJINFO: lua_pushliteral(L, "mobjinfo_t"); break; + case UTYPE_SFXINFO: lua_pushliteral(L, "sfxinfo_t"); break; + + case UTYPE_MOBJ: lua_pushliteral(L, "mobj_t"); break; + case UTYPE_MAPTHING: lua_pushliteral(L, "mapthing_t"); break; + + case UTYPE_PLAYER: lua_pushliteral(L, "player_t"); break; + case UTYPE_TICCMD: lua_pushliteral(L, "ticcmd_t"); break; + case UTYPE_SKIN: lua_pushliteral(L, "skin_t"); break; + case UTYPE_POWERS: lua_pushliteral(L, "player_t.powers"); break; + case UTYPE_SOUNDSID: lua_pushliteral(L, "skin_t.soundsid"); break; + + case UTYPE_VERTEX: lua_pushliteral(L, "vertex_t"); break; + case UTYPE_LINE: lua_pushliteral(L, "line_t"); break; + case UTYPE_SIDE: lua_pushliteral(L, "side_t"); break; + case UTYPE_SUBSECTOR: lua_pushliteral(L, "subsector_t"); break; + case UTYPE_SECTOR: lua_pushliteral(L, "sector_t"); break; + case UTYPE_FFLOOR: lua_pushliteral(L, "ffloor_t"); break; +#ifdef HAVE_LUA_SEGS + case UTYPE_SEG: lua_pushliteral(L, "seg_t"); break; + case UTYPE_NODE: lua_pushliteral(L, "node_t"); break; +#endif + case UTYPE_MAPHEADER: lua_pushliteral(L, "mapheader_t"); break; + + case UTYPE_CVAR: lua_pushliteral(L, "cvar_t"); break; + + case UTYPE_SECTORLINES: lua_pushliteral(L, "sector_t.lines"); break; + case UTYPE_SIDENUM: lua_pushliteral(L, "line_t.sidenum"); break; +#ifdef HAVE_LUA_SEGS + case UTYPE_NODEBBOX: lua_pushliteral(L, "node_t.bbox"); break; + case UTYPE_NODECHILDREN: lua_pushliteral(L, "node_t.children"); break; +#endif + + case UTYPE_BBOX: lua_pushliteral(L, "bbox"); break; + + case UTYPE_HUDINFO: lua_pushliteral(L, "hudinfo_t"); break; + case UTYPE_PATCH: lua_pushliteral(L, "patch_t"); break; + case UTYPE_COLORMAP: lua_pushliteral(L, "colormap"); break; + case UTYPE_CAMERA: lua_pushliteral(L, "camera_t"); break; + default: return luaL_error(L, "Unknown userdata type"); + } + return 1; +} + // M_RANDOM ////////////// @@ -2190,6 +2355,7 @@ static int lib_gTicsToMilliseconds(lua_State *L) static luaL_Reg lib[] = { {"print", lib_print}, + {"userdataType", lib_userdataType}, // m_random {"P_RandomFixed",lib_pRandomFixed}, From 930527a3d6cded075d9b585180a92a8b00869347 Mon Sep 17 00:00:00 2001 From: Monster Iestyn Date: Thu, 19 Jan 2017 21:35:53 +0000 Subject: [PATCH 05/27] Reduced code for userdataType significantly UTYPE_* enum wasn't needed, meta2utype is now the meta string and return string for each userdata type --- src/lua_baselib.c | 163 +++++++++++----------------------------------- 1 file changed, 39 insertions(+), 124 deletions(-) diff --git a/src/lua_baselib.c b/src/lua_baselib.c index e0584bd1c..cad5a4ddc 100644 --- a/src/lua_baselib.c +++ b/src/lua_baselib.c @@ -87,101 +87,56 @@ static int lib_print(lua_State *L) return 0; } -enum -{ - UTYPE_NULL=0, - UTYPE_STATE, - UTYPE_MOBJINFO, - UTYPE_SFXINFO, - - UTYPE_MOBJ, - UTYPE_MAPTHING, - - UTYPE_PLAYER, - UTYPE_TICCMD, - UTYPE_SKIN, - UTYPE_POWERS, - UTYPE_SOUNDSID, - - UTYPE_VERTEX, - UTYPE_LINE, - UTYPE_SIDE, - UTYPE_SUBSECTOR, - UTYPE_SECTOR, - UTYPE_FFLOOR, -#ifdef HAVE_LUA_SEGS - UTYPE_SEG, - UTYPE_NODE, -#endif - UTYPE_MAPHEADER, - - UTYPE_CVAR, - - UTYPE_SECTORLINES, - UTYPE_SIDENUM, -#ifdef HAVE_LUA_SEGS - UTYPE_NODEBBOX, - UTYPE_NODECHILDREN, -#endif - - UTYPE_BBOX, - - UTYPE_HUDINFO, - UTYPE_PATCH, - UTYPE_COLORMAP, - UTYPE_CAMERA, -}; - -#define META_UTYPE(name) {META_##name, UTYPE_##name} static const struct { const char *meta; - UINT8 utype; + const char *utype; } meta2utype[] = { - META_UTYPE(STATE), - META_UTYPE(MOBJINFO), - META_UTYPE(SFXINFO), + {META_STATE, "state_t"}, + {META_MOBJINFO, "mobjinfo_t"}, + {META_SFXINFO, "sfxinfo_t"}, - META_UTYPE(MOBJ), - META_UTYPE(MAPTHING), + {META_MOBJ, "mobj_t"}, + {META_MAPTHING, "mapthing_t"}, - META_UTYPE(PLAYER), - META_UTYPE(TICCMD), - META_UTYPE(SKIN), - META_UTYPE(POWERS), - META_UTYPE(SOUNDSID), + {META_PLAYER, "player_t"}, + {META_TICCMD, "ticcmd_t"}, + {META_SKIN, "skin_t"}, + {META_POWERS, "player_t.powers"}, + {META_SOUNDSID, "skin_t.soundsid"}, - META_UTYPE(VERTEX), - META_UTYPE(LINE), - META_UTYPE(SIDE), - META_UTYPE(SUBSECTOR), - META_UTYPE(SECTOR), - META_UTYPE(FFLOOR), + {META_VERTEX, "vertex_t"}, + {META_LINE, "line_t"}, + {META_SIDE, "side_t"}, + {META_SUBSECTOR, "subsector_t"}, + {META_SECTOR, "sector_t"}, + {META_FFLOOR, "ffloor_t"}, #ifdef HAVE_LUA_SEGS - META_UTYPE(SEG), - META_UTYPE(NODE), + {META_SEG, "seg_t"}, + {META_NODE, "node_t"}, #endif - META_UTYPE(MAPHEADER), + {META_MAPHEADER, "mapheader_t"}, - META_UTYPE(CVAR), + {META_CVAR, "consvar_t"}, - META_UTYPE(SECTORLINES), - META_UTYPE(SIDENUM), + {META_SECTORLINES, "sector_t.lines"}, + {META_SIDENUM, "line_t.sidenum"}, #ifdef HAVE_LUA_SEGS - META_UTYPE(NODEBBOX), - META_UTYPE(NODECHILDREN), + {META_NODEBBOX, "node_t.bbox"}, + {META_NODECHILDREN, "node_t.children"}, #endif - META_UTYPE(BBOX), + {META_BBOX, "bbox"}, - META_UTYPE(HUDINFO), - META_UTYPE(PATCH), - META_UTYPE(COLORMAP), - META_UTYPE(CAMERA), - {NULL, UTYPE_NULL} + {META_HUDINFO, "hudinfo_t"}, + {META_PATCH, "patch_t"}, + {META_COLORMAP, "colormap"}, + {META_CAMERA, "camera_t"}, + {NULL, NULL} }; -#undef META_UTYPE -static UINT8 GetUserdataUType(lua_State *L) +// goes through the above list and returns the utype string for the userdata type +// returns "unknown" instead if we couldn't find the right userdata type +static const char *GetUserdataUType(lua_State *L) { UINT8 i; lua_getmetatable(L, -1); @@ -198,57 +153,17 @@ static UINT8 GetUserdataUType(lua_State *L) } lua_pop(L, 1); - return UTYPE_NULL; + return "unknown"; } +// Return a string representing the type of userdata the given var is +// e.g. players[0] -> "player_t" +// or players[0].powers -> "player_t.powers" static int lib_userdataType(lua_State *L) { lua_settop(L, 1); // pop everything except arg 1 (in case somebody decided to add more) luaL_checktype(L, 1, LUA_TUSERDATA); - switch (GetUserdataUType(L)) - { - case UTYPE_STATE: lua_pushliteral(L, "state_t"); break; - case UTYPE_MOBJINFO: lua_pushliteral(L, "mobjinfo_t"); break; - case UTYPE_SFXINFO: lua_pushliteral(L, "sfxinfo_t"); break; - - case UTYPE_MOBJ: lua_pushliteral(L, "mobj_t"); break; - case UTYPE_MAPTHING: lua_pushliteral(L, "mapthing_t"); break; - - case UTYPE_PLAYER: lua_pushliteral(L, "player_t"); break; - case UTYPE_TICCMD: lua_pushliteral(L, "ticcmd_t"); break; - case UTYPE_SKIN: lua_pushliteral(L, "skin_t"); break; - case UTYPE_POWERS: lua_pushliteral(L, "player_t.powers"); break; - case UTYPE_SOUNDSID: lua_pushliteral(L, "skin_t.soundsid"); break; - - case UTYPE_VERTEX: lua_pushliteral(L, "vertex_t"); break; - case UTYPE_LINE: lua_pushliteral(L, "line_t"); break; - case UTYPE_SIDE: lua_pushliteral(L, "side_t"); break; - case UTYPE_SUBSECTOR: lua_pushliteral(L, "subsector_t"); break; - case UTYPE_SECTOR: lua_pushliteral(L, "sector_t"); break; - case UTYPE_FFLOOR: lua_pushliteral(L, "ffloor_t"); break; -#ifdef HAVE_LUA_SEGS - case UTYPE_SEG: lua_pushliteral(L, "seg_t"); break; - case UTYPE_NODE: lua_pushliteral(L, "node_t"); break; -#endif - case UTYPE_MAPHEADER: lua_pushliteral(L, "mapheader_t"); break; - - case UTYPE_CVAR: lua_pushliteral(L, "cvar_t"); break; - - case UTYPE_SECTORLINES: lua_pushliteral(L, "sector_t.lines"); break; - case UTYPE_SIDENUM: lua_pushliteral(L, "line_t.sidenum"); break; -#ifdef HAVE_LUA_SEGS - case UTYPE_NODEBBOX: lua_pushliteral(L, "node_t.bbox"); break; - case UTYPE_NODECHILDREN: lua_pushliteral(L, "node_t.children"); break; -#endif - - case UTYPE_BBOX: lua_pushliteral(L, "bbox"); break; - - case UTYPE_HUDINFO: lua_pushliteral(L, "hudinfo_t"); break; - case UTYPE_PATCH: lua_pushliteral(L, "patch_t"); break; - case UTYPE_COLORMAP: lua_pushliteral(L, "colormap"); break; - case UTYPE_CAMERA: lua_pushliteral(L, "camera_t"); break; - default: return luaL_error(L, "Unknown userdata type"); - } + lua_pushstring(L, GetUserdataUType(L)); return 1; } From e3ded1671c48906152c7ee29769b86880b49b61c Mon Sep 17 00:00:00 2001 From: Monster Iestyn Date: Sat, 21 Jan 2017 23:49:18 +0000 Subject: [PATCH 06/27] Added MobjMoveBlocked Lua hook Also slightly edited P_XYMovement to properly check the mobj still exists before checking its eflags for MFE_SPRUNG, while I was at it --- src/lua_hook.h | 2 ++ src/lua_hooklib.c | 3 +++ src/p_mobj.c | 26 +++++++++++++++++++------- 3 files changed, 24 insertions(+), 7 deletions(-) diff --git a/src/lua_hook.h b/src/lua_hook.h index 7192a2979..88867db2b 100644 --- a/src/lua_hook.h +++ b/src/lua_hook.h @@ -45,6 +45,7 @@ enum hook { hook_PlayerSpawn, hook_ShieldSpawn, hook_ShieldSpecial, + hook_MobjMoveBlocked, hook_MAX // last hook }; @@ -81,5 +82,6 @@ boolean LUAh_HurtMsg(player_t *player, mobj_t *inflictor, mobj_t *source, UINT8 #define LUAh_PlayerSpawn(player) LUAh_PlayerHook(player, hook_PlayerSpawn) // Hook for G_SpawnPlayer #define LUAh_ShieldSpawn(player) LUAh_PlayerHook(player, hook_ShieldSpawn) // Hook for P_SpawnShieldOrb #define LUAh_ShieldSpecial(player) LUAh_PlayerHook(player, hook_ShieldSpecial) // Hook for shield abilities +#define LUAh_MobjMoveBlocked(mo) LUAh_MobjHook(mo, hook_MobjMoveBlocked) // Hook for P_XYMovement (when movement is blocked) #endif diff --git a/src/lua_hooklib.c b/src/lua_hooklib.c index f7ea25224..dadc1861a 100644 --- a/src/lua_hooklib.c +++ b/src/lua_hooklib.c @@ -56,6 +56,7 @@ const char *const hookNames[hook_MAX+1] = { "PlayerSpawn", "ShieldSpawn", "ShieldSpecial", + "MobjMoveBlocked", NULL }; @@ -126,6 +127,7 @@ static int lib_addHook(lua_State *L) case hook_BossDeath: case hook_MobjRemoved: case hook_HurtMsg: + case hook_MobjMoveBlocked: hook.s.mt = MT_NULL; if (lua_isnumber(L, 2)) hook.s.mt = lua_tonumber(L, 2); @@ -184,6 +186,7 @@ static int lib_addHook(lua_State *L) case hook_MobjDeath: case hook_BossDeath: case hook_MobjRemoved: + case hook_MobjMoveBlocked: lastp = &mobjhooks[hook.s.mt]; break; case hook_JumpSpecial: diff --git a/src/p_mobj.c b/src/p_mobj.c index f1dfa94f5..f71dffeae 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -2122,17 +2122,31 @@ void P_XYMovement(mobj_t *mo) if (CheckForBustableBlocks && mo->flags & MF_PUSHABLE) P_PushableCheckBustables(mo); - if (!P_TryMove(mo, mo->x + xmove, mo->y + ymove, true) && !(mo->eflags & MFE_SPRUNG)) - { - // blocked move - moved = false; + moved = P_TryMove(mo, mo->x + xmove, mo->y + ymove, true); // Move! + if (P_MobjWasRemoved(mo)) // mobj was removed during P_TryMove? don't continue + return; + if (mo->eflags & MFE_SPRUNG) // touching a spring counts as moved + moved = true; + + if (!moved) // blocked move + { if (player) { if (player->bot) B_MoveBlocked(player); } - if (mo->flags & MF_BOUNCE) +#ifdef HAVE_BLUA + if (LUAh_MobjMoveBlocked(mo)) + { + if (P_MobjWasRemoved(mo)) + return; + } + else +#endif + if (P_MobjWasRemoved(mo)) + return; + else if (mo->flags & MF_BOUNCE) { P_BounceMove(mo); xmove = ymove = 0; @@ -2232,8 +2246,6 @@ void P_XYMovement(mobj_t *mo) else mo->momx = mo->momy = 0; } - else - moved = true; if (P_MobjWasRemoved(mo)) // MF_SPECIAL touched a player! O_o;; return; From 32562068ba39e026a9eded50e4ed76990c619e59 Mon Sep 17 00:00:00 2001 From: Monster Iestyn Date: Tue, 24 Jan 2017 20:21:50 +0000 Subject: [PATCH 07/27] On second thought, I'll revert the P_TryMove bit to how it was before and just stuff an extra P_MobjWasRemoved check in this way it won't cause as much conflict with the slopetowall transfer branch --- src/p_mobj.c | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/src/p_mobj.c b/src/p_mobj.c index f71dffeae..7649a0c07 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -2122,15 +2122,12 @@ void P_XYMovement(mobj_t *mo) if (CheckForBustableBlocks && mo->flags & MF_PUSHABLE) P_PushableCheckBustables(mo); - moved = P_TryMove(mo, mo->x + xmove, mo->y + ymove, true); // Move! - - if (P_MobjWasRemoved(mo)) // mobj was removed during P_TryMove? don't continue - return; - if (mo->eflags & MFE_SPRUNG) // touching a spring counts as moved - moved = true; - - if (!moved) // blocked move + if (!P_TryMove(mo, mo->x + xmove, mo->y + ymove, true) + && !(P_MobjWasRemoved(mo) || mo->eflags & MFE_SPRUNG)) { + // blocked move + moved = false; + if (player) { if (player->bot) B_MoveBlocked(player); @@ -2246,6 +2243,8 @@ void P_XYMovement(mobj_t *mo) else mo->momx = mo->momy = 0; } + else + moved = true; if (P_MobjWasRemoved(mo)) // MF_SPECIAL touched a player! O_o;; return; From 3212ee0b0fc1fd7734be56a9ccdc2b84ddb6f01d Mon Sep 17 00:00:00 2001 From: Monster Iestyn Date: Mon, 30 Jan 2017 21:08:13 +0000 Subject: [PATCH 08/27] Fix endless loop of R_DrawRepeatMaskedColumn if both sprtopscreen and sprbotscreen are CLAMPMAX (INT32_MAX) This fixes the grid floors in TD's Lava Mountain freezing the game if they go off the bottom of the screen far enough (they have ACWRFL1A as the wall texture, which is a single patch texture with holes) --- src/r_segs.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/r_segs.c b/src/r_segs.c index 8f271bfe3..3059860cf 100644 --- a/src/r_segs.c +++ b/src/r_segs.c @@ -706,10 +706,10 @@ void R_RenderMaskedSegRange(drawseg_t *ds, INT32 x1, INT32 x2) // Loop through R_DrawMaskedColumn calls static void R_DrawRepeatMaskedColumn(column_t *col) { - do { + while (sprtopscreen < sprbotscreen) { R_DrawMaskedColumn(col); sprtopscreen += dc_texheight*spryscale; - } while (sprtopscreen < sprbotscreen); + } } // From 72bd3e28ed2471daad12125b014d90d2bb300a86 Mon Sep 17 00:00:00 2001 From: Monster Iestyn Date: Tue, 31 Jan 2017 22:10:31 +0000 Subject: [PATCH 09/27] Fix sprtopscreen from getting integer overflows once and for all in R_DrawRepeatMaskedColumn Fixes TD's terminal from freezing the game this time, oh boy --- src/r_segs.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/r_segs.c b/src/r_segs.c index 3059860cf..502ff3304 100644 --- a/src/r_segs.c +++ b/src/r_segs.c @@ -708,7 +708,10 @@ static void R_DrawRepeatMaskedColumn(column_t *col) { while (sprtopscreen < sprbotscreen) { R_DrawMaskedColumn(col); - sprtopscreen += dc_texheight*spryscale; + if ((INT64)sprtopscreen + dc_texheight*spryscale > (INT64)INT32_MAX) // prevent overflow + sprtopscreen = INT32_MAX; + else + sprtopscreen += dc_texheight*spryscale; } } From dc249c6cd51fe8186f88588533b1e51bdd56d3ca Mon Sep 17 00:00:00 2001 From: Monster Iestyn Date: Sat, 4 Feb 2017 23:26:37 +0000 Subject: [PATCH 10/27] D_ModifierKeyResponder now checks for ev_console as a "key down" event console window uses ev_keyup too so don't worry about turning off --- src/d_main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/d_main.c b/src/d_main.c index 2caf50087..4080087c1 100644 --- a/src/d_main.c +++ b/src/d_main.c @@ -187,7 +187,7 @@ UINT8 altdown = 0; // 0x1 left, 0x2 right // static inline void D_ModifierKeyResponder(event_t *ev) { - if (ev->type == ev_keydown) switch (ev->data1) + if (ev->type == ev_keydown || ev->type == ev_console) switch (ev->data1) { case KEY_LSHIFT: shiftdown |= 0x1; return; case KEY_RSHIFT: shiftdown |= 0x2; return; From f9b41898a9730f755ce29edf5843d4366a11b0f4 Mon Sep 17 00:00:00 2001 From: Monster Iestyn Date: Sun, 5 Feb 2017 22:04:29 +0000 Subject: [PATCH 11/27] Don't allow skipping stats in record attack/nights attack --- src/g_game.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/g_game.c b/src/g_game.c index 84db90132..7499fe7a0 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -2888,7 +2888,7 @@ static void G_DoCompleted(void) if (nextmap < NUMMAPS && !mapheaderinfo[nextmap]) P_AllocMapHeader(nextmap); - if (skipstats) + if (skipstats && !modeattacking) // Don't skip stats if we're in record attack G_AfterIntermission(); else { From 6dfef794a49a03f024f133ed0b61c805c6e660f0 Mon Sep 17 00:00:00 2001 From: toasterbabe Date: Sun, 12 Feb 2017 01:28:12 +0000 Subject: [PATCH 12/27] Metal Sonic's bounce attack is much nicer. Also, a bunch of other minor tweaks. --- src/info.c | 6 ++--- src/p_mobj.c | 72 ++++++++++++++++++++++++++++++++-------------------- 2 files changed, 48 insertions(+), 30 deletions(-) diff --git a/src/info.c b/src/info.c index fdea617c1..705cb17d8 100644 --- a/src/info.c +++ b/src/info.c @@ -1372,11 +1372,11 @@ state_t states[NUMSTATES] = {SPR_METL, 13, -1, {NULL}, 0, 0, S_NULL}, // S_METALSONIC_BLOCK {SPR_METL, 13, 40, {NULL}, 0, 0, S_METALSONIC_GATHER},// S_METALSONIC_RAISE {SPR_METL, 14, -1, {NULL}, 0, 0, S_NULL}, // S_METALSONIC_GATHER - {SPR_METL, 9, -1, {NULL}, 0, 0, S_METALSONIC_BOUNCE},// S_METALSONIC_DASH + {SPR_METL, 15, -1, {NULL}, 0, 0, S_METALSONIC_BOUNCE},// S_METALSONIC_DASH {SPR_METL, 14, -1, {NULL}, 0, 0, S_NULL}, // S_METALSONIC_BOUNCE {SPR_METL, 13, -1, {NULL}, 0, 0, S_METALSONIC_GATHER},// S_METALSONIC_SHOOT {SPR_METL, 11, 40, {A_Pain}, 0, 0, S_METALSONIC_FLOAT}, // S_METALSONIC_PAIN - {SPR_METL, 0, -1, {A_BossDeath}, 0, 0, S_NULL}, // S_METALSONIC_DEATH + {SPR_METL, 11, -1, {A_BossDeath}, 0, 0, S_NULL}, // S_METALSONIC_DEATH {SPR_METL, 3, 4, {NULL}, 0, 0, S_METALSONIC_FLEE2}, // S_METALSONIC_FLEE1 {SPR_METL, 4, 4, {A_BossScream}, 0, 0, S_METALSONIC_FLEE3}, // S_METALSONIC_FLEE2 {SPR_METL, 5, 4, {NULL}, 0, 0, S_METALSONIC_FLEE4}, // S_METALSONIC_FLEE3 @@ -4961,7 +4961,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = 16*FRACUNIT, // radius 48*FRACUNIT, // height 0, // display offset - sfx_mspogo, // mass + sfx_s3k5a, // mass 3, // damage sfx_mswarp, // activesound MF_NOGRAVITY|MF_BOSS|MF_SLIDEME, // flags diff --git a/src/p_mobj.c b/src/p_mobj.c index 39682a7ef..aaae5efd0 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -5641,6 +5641,15 @@ static void P_Boss7Thinker(mobj_t *mobj) } +#define vectorise mobj->movedir = ANGLE_11hh - FixedAngle(FixedMul(AngleFixed(ANGLE_11hh), FixedDiv((mobj->info->spawnhealth - mobj->health)<info->spawnhealth-1)<movedir = InvAngle(mobj->movedir);\ + mobj->threshold = 6 + (FixedMul(24<info->spawnhealth - mobj->health)<info->spawnhealth-1)<>FRACBITS);\ + if (mobj->info->activesound)\ + S_StartSound(mobj, mobj->info->activesound);\ + if (mobj->info->painchance)\ + P_SetMobjState(mobj, mobj->info->painchance) + // Metal Sonic battle boss // You CAN put multiple Metal Sonics in a single map // because I am a totally competent programmer who can do shit right. @@ -5745,7 +5754,8 @@ static void P_Boss9Thinker(mobj_t *mobj) } if (spawner) { mobj_t *missile = P_SpawnMissile(spawner, mobj, MT_MSGATHER); - missile->momz = FixedDiv(missile->momz, 7*FRACUNIT/4); + if (mobj->health > mobj->info->damage) + missile->momz = FixedDiv(missile->momz, 7*FRACUNIT/5); if (dist == 0) missile->fuse = 0; else @@ -5757,16 +5767,22 @@ static void P_Boss9Thinker(mobj_t *mobj) // Pre-threshold reactiontime stuff for attack phases if (mobj->reactiontime && mobj->movecount == 3) { + mobj->reactiontime--; + if (mobj->movedir == 0 || mobj->movedir == 2) { // Pausing between bounces in the pinball phase if (mobj->target->player->powers[pw_tailsfly]) // Trying to escape, eh? mobj->watertop = mobj->target->z + mobj->target->momz*6; // Readjust your aim. >:3 else mobj->watertop = mobj->target->floorz + 16*FRACUNIT; - if (!(mobj->threshold%4)) + + if (!(mobj->threshold%4)) { mobj->angle = R_PointToAngle2(mobj->x, mobj->y, mobj->target->x + mobj->target->momx*4, mobj->target->y + mobj->target->momy*4); + if (!mobj->reactiontime) + S_StartSound(mobj, sfx_zoom); // zoom! + } } - // Pausing between energy ball shots - mobj->reactiontime--; + // else -- Pausing between energy ball shots + return; } @@ -5838,20 +5854,28 @@ static void P_Boss9Thinker(mobj_t *mobj) P_InstaThrust(mobj, mobj->angle, 30*FRACUNIT); if (!P_TryMove(mobj, mobj->x+mobj->momx, mobj->y+mobj->momy, true)) { // Hit a wall? Find a direction to bounce mobj->threshold--; - if (mobj->threshold) { - P_SetMobjState(mobj, mobj->state->nextstate); - if (mobj->info->mass) - S_StartSound(mobj, mobj->info->mass); - if (!(mobj->threshold%4)) { // We've decided to lock onto the player this bounce. - mobj->angle = R_PointToAngle2(mobj->x, mobj->y, mobj->target->x + mobj->target->momx*4, mobj->target->y + mobj->target->momy*4); - mobj->reactiontime = TICRATE; // targetting time - } else { // No homing, just use P_BounceMove - P_BounceMove(mobj); - mobj->angle = R_PointToAngle2(0,0,mobj->momx,mobj->momy); - mobj->reactiontime = TICRATE/4; // just a pause before you bounce away - } - mobj->momx = mobj->momy = 0; + P_SetMobjState(mobj, mobj->state->nextstate); + if (!mobj->threshold) { // failed bounce! + S_StartSound(mobj, sfx_mspogo); + P_BounceMove(mobj); + mobj->angle = R_PointToAngle2(0,0,mobj->momx, mobj->momy); + P_TryMove(mobj, mobj->x+mobj->momx, mobj->y+mobj->momy, true); + mobj->watertop = mobj->target->floorz + 32*FRACUNIT; + mobj->flags &= ~MF_PAIN; + mobj->fuse = 10*TICRATE; + mobj->movecount = 0; + vectorise; + } else if (!(mobj->threshold%4)) { // We've decided to lock onto the player this bounce. + S_StartSound(mobj, sfx_s3k5a); + mobj->angle = R_PointToAngle2(mobj->x, mobj->y, mobj->target->x + mobj->target->momx*4, mobj->target->y + mobj->target->momy*4); + mobj->reactiontime = TICRATE - 5*(mobj->info->damage - mobj->health); // targetting time + } else { // No homing, just use P_BounceMove + S_StartSound(mobj, sfx_s3kaa); // make the bounces distinct... + P_BounceMove(mobj); + mobj->angle = R_PointToAngle2(0,0,mobj->momx,mobj->momy); + mobj->reactiontime = 1; // TICRATE/4; // just a pause before you bounce away } + mobj->momx = mobj->momy = 0; } return; } @@ -5978,9 +6002,9 @@ static void P_Boss9Thinker(mobj_t *mobj) S_StartSound(mobj, mobj->info->seesound); P_SetMobjState(mobj, mobj->info->seestate); if (mobj->movedir == 2) - mobj->threshold = 16; // bounce 16 times + mobj->threshold = 12; // bounce 12 times else - mobj->threshold = 32; // bounce 32 times + mobj->threshold = 24; // bounce 24 times mobj->watertop = mobj->target->floorz + 16*FRACUNIT; P_LinedefExecute(LE_PINCHPHASE, mobj, NULL); } else { @@ -6063,14 +6087,7 @@ static void P_Boss9Thinker(mobj_t *mobj) if (danger) { // An incoming attack is detected! What should we do?! // Go into vector form! - mobj->movedir = ANGLE_11hh - FixedAngle(FixedMul(AngleFixed(ANGLE_11hh), FixedDiv((mobj->info->spawnhealth - mobj->health)<info->spawnhealth-1)<movedir = InvAngle(mobj->movedir); - mobj->threshold = 6 + (FixedMul(24<info->spawnhealth - mobj->health)<info->spawnhealth-1)<>FRACBITS); - if (mobj->info->activesound) - S_StartSound(mobj, mobj->info->activesound); - if (mobj->info->painchance) - P_SetMobjState(mobj, mobj->info->painchance); + vectorise; return; } @@ -6085,6 +6102,7 @@ static void P_Boss9Thinker(mobj_t *mobj) } } } +#undef vectorise // // P_GetClosestAxis From 5f3cfc67294d006e29a8665a93dc7db7c61b3a60 Mon Sep 17 00:00:00 2001 From: toasterbabe Date: Sun, 12 Feb 2017 14:16:52 +0000 Subject: [PATCH 13/27] Some cleanup. --- src/p_mobj.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/p_mobj.c b/src/p_mobj.c index aaae5efd0..65be4d78d 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -5858,11 +5858,10 @@ static void P_Boss9Thinker(mobj_t *mobj) if (!mobj->threshold) { // failed bounce! S_StartSound(mobj, sfx_mspogo); P_BounceMove(mobj); - mobj->angle = R_PointToAngle2(0,0,mobj->momx, mobj->momy); - P_TryMove(mobj, mobj->x+mobj->momx, mobj->y+mobj->momy, true); + mobj->angle = R_PointToAngle2(mobj->momx, mobj->momy,0,0); mobj->watertop = mobj->target->floorz + 32*FRACUNIT; mobj->flags &= ~MF_PAIN; - mobj->fuse = 10*TICRATE; + mobj->fuse = 0; mobj->movecount = 0; vectorise; } else if (!(mobj->threshold%4)) { // We've decided to lock onto the player this bounce. @@ -5884,8 +5883,9 @@ static void P_Boss9Thinker(mobj_t *mobj) mobj->angle += mobj->movedir; P_InstaThrust(mobj, mobj->angle, -speed); while (!P_TryMove(mobj, mobj->x+mobj->momx, mobj->y+mobj->momy, true) && tries++ < 16) { - mobj->angle += mobj->movedir; - P_InstaThrust(mobj, mobj->angle, -speed); + S_StartSound(mobj, sfx_mspogo); + P_BounceMove(mobj); + mobj->angle = R_PointToAngle2(mobj->momx, mobj->momy,0,0); } mobj->momx = mobj->momy = 0; mobj->threshold--; From 3feac5bc90a1fc9a14c8e91131a4f6138af15098 Mon Sep 17 00:00:00 2001 From: toasterbabe Date: Mon, 13 Feb 2017 18:04:08 +0000 Subject: [PATCH 14/27] bad bounce https://gfycat.com/DeliciousReliableGentoopenguin --- src/dehacked.c | 2 +- src/info.c | 4 ++-- src/info.h | 2 +- src/p_mobj.c | 23 ++++++++++++++++++++--- 4 files changed, 24 insertions(+), 7 deletions(-) diff --git a/src/dehacked.c b/src/dehacked.c index c71c55ac1..748a3dc69 100644 --- a/src/dehacked.c +++ b/src/dehacked.c @@ -4772,11 +4772,11 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit "S_METALSONIC_FLOAT", "S_METALSONIC_VECTOR", "S_METALSONIC_STUN", - "S_METALSONIC_BLOCK", "S_METALSONIC_RAISE", "S_METALSONIC_GATHER", "S_METALSONIC_DASH", "S_METALSONIC_BOUNCE", + "S_METALSONIC_BADBOUNCE", "S_METALSONIC_SHOOT", "S_METALSONIC_PAIN", "S_METALSONIC_DEATH", diff --git a/src/info.c b/src/info.c index 705cb17d8..6b3019781 100644 --- a/src/info.c +++ b/src/info.c @@ -1369,11 +1369,11 @@ state_t states[NUMSTATES] = {SPR_METL, 4, -1, {NULL}, 0, 0, S_NULL}, // S_METALSONIC_FLOAT {SPR_METL, 12, -1, {NULL}, 0, 0, S_METALSONIC_STUN}, // S_METALSONIC_VECTOR {SPR_METL, 0, -1, {NULL}, 0, 0, S_METALSONIC_FLOAT}, // S_METALSONIC_STUN - {SPR_METL, 13, -1, {NULL}, 0, 0, S_NULL}, // S_METALSONIC_BLOCK {SPR_METL, 13, 40, {NULL}, 0, 0, S_METALSONIC_GATHER},// S_METALSONIC_RAISE {SPR_METL, 14, -1, {NULL}, 0, 0, S_NULL}, // S_METALSONIC_GATHER {SPR_METL, 15, -1, {NULL}, 0, 0, S_METALSONIC_BOUNCE},// S_METALSONIC_DASH {SPR_METL, 14, -1, {NULL}, 0, 0, S_NULL}, // S_METALSONIC_BOUNCE + {SPR_METL, 16, -1, {NULL}, 0, 0, S_NULL}, // S_METALSONIC_BADBOUNCE {SPR_METL, 13, -1, {NULL}, 0, 0, S_METALSONIC_GATHER},// S_METALSONIC_SHOOT {SPR_METL, 11, 40, {A_Pain}, 0, 0, S_METALSONIC_FLOAT}, // S_METALSONIC_PAIN {SPR_METL, 11, -1, {A_BossDeath}, 0, 0, S_NULL}, // S_METALSONIC_DEATH @@ -4952,7 +4952,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = S_METALSONIC_PAIN, // painstate S_METALSONIC_VECTOR,// painchance sfx_dmpain, // painsound - S_METALSONIC_BLOCK, // meleestate + S_METALSONIC_BADBOUNCE, // meleestate S_METALSONIC_SHOOT, // missilestate S_METALSONIC_DEATH, // deathstate S_METALSONIC_FLEE1, // xdeathstate diff --git a/src/info.h b/src/info.h index 1a6c14a70..0cca7896e 100644 --- a/src/info.h +++ b/src/info.h @@ -1575,11 +1575,11 @@ typedef enum state S_METALSONIC_FLOAT, S_METALSONIC_VECTOR, S_METALSONIC_STUN, - S_METALSONIC_BLOCK, S_METALSONIC_RAISE, S_METALSONIC_GATHER, S_METALSONIC_DASH, S_METALSONIC_BOUNCE, + S_METALSONIC_BADBOUNCE, S_METALSONIC_SHOOT, S_METALSONIC_PAIN, S_METALSONIC_DEATH, diff --git a/src/p_mobj.c b/src/p_mobj.c index 65be4d78d..fb7ee5a43 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -5694,6 +5694,19 @@ static void P_Boss9Thinker(mobj_t *mobj) if (mobj->health <= 0) return; + if ((statenum_t)(mobj->state-states) == mobj->info->meleestate) + { + P_InstaThrust(mobj, mobj->angle, -4*FRACUNIT); + P_TryMove(mobj, mobj->x+mobj->momx, mobj->y+mobj->momy, true); + mobj->momz -= gravity; + if (mobj->z < mobj->watertop) + { + mobj->watertop = mobj->target->floorz + 32*FRACUNIT; + P_SetMobjState(mobj, mobj->info->spawnstate); + } + return; + } + if ((!mobj->target || !(mobj->target->flags & MF_SHOOTABLE))) { P_BossTargetPlayer(mobj, false); @@ -5711,6 +5724,10 @@ static void P_Boss9Thinker(mobj_t *mobj) } else if (!mobj->fuse) mobj->fuse = 10*TICRATE; + + // reset to flying so everything gets properly re-initialised + mobj->threshold = 0; + mobj->movecount = 0; } // AI goes here. @@ -5859,11 +5876,11 @@ static void P_Boss9Thinker(mobj_t *mobj) S_StartSound(mobj, sfx_mspogo); P_BounceMove(mobj); mobj->angle = R_PointToAngle2(mobj->momx, mobj->momy,0,0); - mobj->watertop = mobj->target->floorz + 32*FRACUNIT; + mobj->momz = 4*FRACUNIT; mobj->flags &= ~MF_PAIN; - mobj->fuse = 0; + mobj->fuse = 10*TICRATE; mobj->movecount = 0; - vectorise; + P_SetMobjState(mobj, mobj->info->meleestate); } else if (!(mobj->threshold%4)) { // We've decided to lock onto the player this bounce. S_StartSound(mobj, sfx_s3k5a); mobj->angle = R_PointToAngle2(mobj->x, mobj->y, mobj->target->x + mobj->target->momx*4, mobj->target->y + mobj->target->momy*4); From a04ae45a93397fcd4d90726159b482ddacd1f4e6 Mon Sep 17 00:00:00 2001 From: toasterbabe Date: Mon, 13 Feb 2017 18:53:16 +0000 Subject: [PATCH 15/27] MORE CUES --- src/p_mobj.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/p_mobj.c b/src/p_mobj.c index fb7ee5a43..33bcf0ce4 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -5880,6 +5880,7 @@ static void P_Boss9Thinker(mobj_t *mobj) mobj->flags &= ~MF_PAIN; mobj->fuse = 10*TICRATE; mobj->movecount = 0; + P_SpawnMobjFromMobj(mobj, 0, 0, 0, MT_CYBRAKDEMON_VILE_EXPLOSION); P_SetMobjState(mobj, mobj->info->meleestate); } else if (!(mobj->threshold%4)) { // We've decided to lock onto the player this bounce. S_StartSound(mobj, sfx_s3k5a); From 758bec6963226d0645da9dc01fc6b48333899e35 Mon Sep 17 00:00:00 2001 From: toasterbabe Date: Tue, 14 Feb 2017 02:07:08 +0000 Subject: [PATCH 16/27] Fixed a bunch of awkwardness where Metal wouldn't reset himself properly when his target died. --- src/p_mobj.c | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/src/p_mobj.c b/src/p_mobj.c index 33bcf0ce4..0edc2c484 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -5709,25 +5709,30 @@ static void P_Boss9Thinker(mobj_t *mobj) if ((!mobj->target || !(mobj->target->flags & MF_SHOOTABLE))) { + if (mobj->tracer) + P_RemoveMobj(mobj->tracer); P_BossTargetPlayer(mobj, false); if (mobj->target && (!P_IsObjectOnGround(mobj->target) || mobj->target->player->pflags & PF_SPINNING)) P_SetTarget(&mobj->target, NULL); // Wait for them to hit the ground first if (!mobj->target) // Still no target, aww. { // Reset the boss. + if (mobj->tracer) + P_RemoveMobj(mobj->tracer); P_SetMobjState(mobj, mobj->info->spawnstate); mobj->fuse = 0; mobj->momx = FixedDiv(mobj->momx, FRACUNIT + (FRACUNIT>>2)); mobj->momy = FixedDiv(mobj->momy, FRACUNIT + (FRACUNIT>>2)); mobj->momz = FixedDiv(mobj->momz, FRACUNIT + (FRACUNIT>>2)); + mobj->watertop = mobj->floorz + 32*FRACUNIT; + mobj->momz = (mobj->watertop - mobj->z)>>3; + mobj->threshold = 0; + mobj->movecount = 0; + mobj->flags = mobj->info->flags; return; } else if (!mobj->fuse) mobj->fuse = 10*TICRATE; - - // reset to flying so everything gets properly re-initialised - mobj->threshold = 0; - mobj->movecount = 0; } // AI goes here. From b0f4bbb44b0020810c88ec2130f47097662bf406 Mon Sep 17 00:00:00 2001 From: Monster Iestyn Date: Thu, 2 Mar 2017 19:37:21 +0000 Subject: [PATCH 17/27] Played TD's Stormy Streets enough to know precipitation sprites didn't get an overflow test of their own (various large invisible blocks used in the level cause rain to make splashes high above the main level, high enough to make ghostly rain splash sprite artifacts appear sometimes in nearby areas) --- src/r_things.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/r_things.c b/src/r_things.c index 927217c5c..331febabd 100644 --- a/src/r_things.c +++ b/src/r_things.c @@ -891,12 +891,18 @@ static void R_DrawPrecipitationVisSprite(vissprite_t *vis) #endif fixed_t frac; patch_t *patch; + INT64 overflow_test; //Fab : R_InitSprites now sets a wad lump number patch = W_CacheLumpNum(vis->patch, PU_CACHE); if (!patch) return; + // Check for overflow + overflow_test = (INT64)centeryfrac - (((INT64)vis->texturemid*vis->scale)>>FRACBITS); + if (overflow_test < 0) overflow_test = -overflow_test; + if ((UINT64)overflow_test&0xFFFFFFFF80000000ULL) return; // fixed point mult would overflow + if (vis->transmap) { colfunc = fuzzcolfunc; From 2823c7bffbbe4f17b5a291a41c285b2b756a46e8 Mon Sep 17 00:00:00 2001 From: Alam Ed Arias Date: Sun, 12 Mar 2017 17:23:56 -0400 Subject: [PATCH 18/27] build: fixup warnings from GCC 6.2.1 --- src/d_net.c | 2 ++ src/hardware/r_opengl/r_opengl.c | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/src/d_net.c b/src/d_net.c index fae1ea311..7f16c302d 100644 --- a/src/d_net.c +++ b/src/d_net.c @@ -991,12 +991,14 @@ void Command_Droprate(void) packetdroprate = droprate; } +#ifndef NONET static boolean ShouldDropPacket(void) { return (packetdropquantity[netbuffer->packettype]) || (packetdroprate != 0 && rand() < (RAND_MAX * (packetdroprate / 100.f))) || packetdroprate == 100; } #endif +#endif // // HSendPacket diff --git a/src/hardware/r_opengl/r_opengl.c b/src/hardware/r_opengl/r_opengl.c index 54dd94854..3a0bf7054 100644 --- a/src/hardware/r_opengl/r_opengl.c +++ b/src/hardware/r_opengl/r_opengl.c @@ -1836,7 +1836,7 @@ EXPORT void HWRAPI(SetSpecialState) (hwdspecialstate_t IdState, INT32 Value) } } -static inline void DrawMD2Ex(INT32 *gl_cmd_buffer, md2_frame_t *frame, UINT32 duration, UINT32 tics, md2_frame_t *nextframe, FTransform *pos, float scale, UINT8 flipped, UINT8 *color) +static void DrawMD2Ex(INT32 *gl_cmd_buffer, md2_frame_t *frame, UINT32 duration, UINT32 tics, md2_frame_t *nextframe, FTransform *pos, float scale, UINT8 flipped, UINT8 *color) { INT32 val, count, pindex; GLfloat s, t; From b22417bcfab06739a4ed692cecc29652905baffe Mon Sep 17 00:00:00 2001 From: Alam Ed Arias Date: Sun, 12 Mar 2017 17:26:37 -0400 Subject: [PATCH 19/27] appveyor: buildbot now using GCC 6.3, not 5.3 --- appveyor.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/appveyor.yml b/appveyor.yml index 25b95d292..b0544a90b 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -47,7 +47,7 @@ before_build: - upx -V - ccache -V - ccache -s -- set SRB2_MFLAGS=-C src MINGW=1 WARNINGMODE=1 GCC53=1 CCACHE=1 +- set SRB2_MFLAGS=-C src MINGW=1 WARNINGMODE=1 GCC63=1 CCACHE=1 build_script: - cmd: mingw32-make.exe %SRB2_MFLAGS% %CONFIGURATION%=1 clean From e0b2a4a7791c846ec13927f0f680e36ebe058d21 Mon Sep 17 00:00:00 2001 From: Alam Ed Arias Date: Sun, 12 Mar 2017 17:45:18 -0400 Subject: [PATCH 20/27] build: add suport for GCC 6.3 --- src/Makefile.cfg | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/src/Makefile.cfg b/src/Makefile.cfg index 72404becc..d5cb112b8 100644 --- a/src/Makefile.cfg +++ b/src/Makefile.cfg @@ -7,6 +7,23 @@ # and other things # + +ifdef GCC63 +GCC62=1 +endif + +ifdef GCC62 +GCC61=1 +endif + +ifdef GCC61 +GCC54=1 +endif + +ifdef GCC54 +GCC53=1 +ENDIF + ifdef GCC53 GCC52=1 endif @@ -176,6 +193,9 @@ endif ifdef GCC46 WFLAGS+=-Wno-error=suggest-attribute=noreturn endif +ifdef GCC62 + WFALGS+=-Wno-tautological-compare +endif WFLAGS+=$(OLDWFLAGS) From b01d5da60ffb20ee1efe4d82262129fd66707be4 Mon Sep 17 00:00:00 2001 From: Alam Ed Arias Date: Sun, 12 Mar 2017 20:23:30 -0400 Subject: [PATCH 21/27] build: fixup GCC54 endif --- src/Makefile.cfg | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Makefile.cfg b/src/Makefile.cfg index d5cb112b8..781076aa2 100644 --- a/src/Makefile.cfg +++ b/src/Makefile.cfg @@ -22,7 +22,7 @@ endif ifdef GCC54 GCC53=1 -ENDIF +endif ifdef GCC53 GCC52=1 From 42ecca817d40f49404359ae402b359b42e98e1a9 Mon Sep 17 00:00:00 2001 From: Alam Ed Arias Date: Sun, 12 Mar 2017 20:43:35 -0400 Subject: [PATCH 22/27] build: disable tautological-compare and logical-op --- src/Makefile.cfg | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/Makefile.cfg b/src/Makefile.cfg index 781076aa2..a891a7551 100644 --- a/src/Makefile.cfg +++ b/src/Makefile.cfg @@ -193,8 +193,11 @@ endif ifdef GCC46 WFLAGS+=-Wno-error=suggest-attribute=noreturn endif -ifdef GCC62 - WFALGS+=-Wno-tautological-compare +ifdef GCC54 + WFALGS+=-Wno-error=logical-op +endif +ifdef GCC61 + WFALGS+=-Wno-error=tautological-compare endif WFLAGS+=$(OLDWFLAGS) From 81fe46213d1b77cc296265a969f74cb26f5d9998 Mon Sep 17 00:00:00 2001 From: Alam Ed Arias Date: Sun, 12 Mar 2017 20:51:45 -0400 Subject: [PATCH 23/27] build: do not overwrite the -Wno-error switchs --- src/Makefile.cfg | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Makefile.cfg b/src/Makefile.cfg index a891a7551..60d96575a 100644 --- a/src/Makefile.cfg +++ b/src/Makefile.cfg @@ -187,6 +187,7 @@ endif ifdef ERRORMODE WFLAGS+=-Werror endif +WFLAGS+=$(OLDWFLAGS) ifdef GCC43 #WFLAGS+=-Wno-error=clobbered endif @@ -199,7 +200,6 @@ endif ifdef GCC61 WFALGS+=-Wno-error=tautological-compare endif -WFLAGS+=$(OLDWFLAGS) #indicate platform and what interface use with From 6bb7a636dc808bc4ca086ff448e7ef4ead510610 Mon Sep 17 00:00:00 2001 From: Alam Ed Arias Date: Sun, 12 Mar 2017 21:02:05 -0400 Subject: [PATCH 24/27] appveyor: output commands passed to GCCwq --- appveyor.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/appveyor.yml b/appveyor.yml index b0544a90b..269b7698d 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -51,7 +51,7 @@ before_build: build_script: - cmd: mingw32-make.exe %SRB2_MFLAGS% %CONFIGURATION%=1 clean -- cmd: mingw32-make.exe %SRB2_MFLAGS% %CONFIGURATION%=1 ERRORMODE=1 -k +- cmd: mingw32-make.exe %SRB2_MFLAGS% %CONFIGURATION%=1 ERRORMODE=1 -k ECHO=1 after_build: - ccache -s From 9cac1e9e6226a26510b5b20c64f5bd353890fdac Mon Sep 17 00:00:00 2001 From: Alam Ed Arias Date: Sun, 12 Mar 2017 21:09:06 -0400 Subject: [PATCH 25/27] build: fixup WFALGS/WFLAGS mistake --- src/Makefile.cfg | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/Makefile.cfg b/src/Makefile.cfg index 60d96575a..e232c4a1b 100644 --- a/src/Makefile.cfg +++ b/src/Makefile.cfg @@ -181,13 +181,17 @@ ifdef GCC45 WFLAGS+=-Wunsuffixed-float-constants endif endif + ifdef NOLDWARNING LDFLAGS+=-Wl,--as-needed endif + ifdef ERRORMODE WFLAGS+=-Werror endif + WFLAGS+=$(OLDWFLAGS) + ifdef GCC43 #WFLAGS+=-Wno-error=clobbered endif @@ -195,10 +199,10 @@ ifdef GCC46 WFLAGS+=-Wno-error=suggest-attribute=noreturn endif ifdef GCC54 - WFALGS+=-Wno-error=logical-op + WFLAGS+=-Wno-error=logical-op endif ifdef GCC61 - WFALGS+=-Wno-error=tautological-compare + WFLAGS+=-Wno-error=tautological-compare endif From 4e8972cd24c291f22d5932415bcafe0d991294af Mon Sep 17 00:00:00 2001 From: Alam Ed Arias Date: Sun, 12 Mar 2017 21:16:37 -0400 Subject: [PATCH 26/27] build: no warning or error about logical-ip or tautological-compare --- src/Makefile.cfg | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Makefile.cfg b/src/Makefile.cfg index e232c4a1b..80d018c4b 100644 --- a/src/Makefile.cfg +++ b/src/Makefile.cfg @@ -199,10 +199,10 @@ ifdef GCC46 WFLAGS+=-Wno-error=suggest-attribute=noreturn endif ifdef GCC54 - WFLAGS+=-Wno-error=logical-op + WFLAGS+=-Wno-logical-op -Wno-error=logical-op endif ifdef GCC61 - WFLAGS+=-Wno-error=tautological-compare + WFLAGS+=-Wno-tautological-compare -Wno-error=tautological-compare endif From 538eac7a471c61e13ffcbae81183de8e32c1d322 Mon Sep 17 00:00:00 2001 From: Alam Ed Arias Date: Sun, 12 Mar 2017 21:17:07 -0400 Subject: [PATCH 27/27] appveyor: disable command output --- appveyor.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/appveyor.yml b/appveyor.yml index 269b7698d..b0544a90b 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -51,7 +51,7 @@ before_build: build_script: - cmd: mingw32-make.exe %SRB2_MFLAGS% %CONFIGURATION%=1 clean -- cmd: mingw32-make.exe %SRB2_MFLAGS% %CONFIGURATION%=1 ERRORMODE=1 -k ECHO=1 +- cmd: mingw32-make.exe %SRB2_MFLAGS% %CONFIGURATION%=1 ERRORMODE=1 -k after_build: - ccache -s