diff --git a/src/d_clisrv.c b/src/d_clisrv.c index 070ab105d..6ce85db27 100644 --- a/src/d_clisrv.c +++ b/src/d_clisrv.c @@ -2550,6 +2550,9 @@ void CL_ClearPlayer(INT32 playernum) memset(&players[playernum], 0, sizeof (player_t)); + players[playernum].followerskin = -1; // don't have a ghost follower + players[playernum].fakeskin = players[playernum].lastfakeskin = MAXSKINS; // don't avoid eggman + RemoveAdminPlayer(playernum); // don't stay admin after you're gone } diff --git a/src/d_player.h b/src/d_player.h index d3b6975ed..50076e3aa 100644 --- a/src/d_player.h +++ b/src/d_player.h @@ -35,8 +35,8 @@ // Extra abilities/settings for skins (combinable stuff) typedef enum { - SF_HIRES = 1, // Draw the sprite at different size? - SF_MACHINE = 1<<1, // Beep boop. Are you a robot? + SF_MACHINE = 1, // Beep boop. Are you a robot? + SF_IRONMAN = 1<<1, // Pick a new skin during POSITION. I main Random! // free up to and including 1<<31 } skinflags_t; @@ -310,6 +310,8 @@ typedef struct botvars_s UINT8 diffincrease; // In GP: bot difficulty will increase this much next round boolean rival; // If true, they're the GP rival + // All entries above persist between rounds and must be recorded in demos + fixed_t rubberband; // Bot rubberband value UINT16 controller; // Special bot controller linedef ID @@ -385,6 +387,9 @@ typedef struct player_s INT32 skin; UINT32 availabilities; + UINT8 fakeskin; // ironman + UINT8 lastfakeskin; + UINT8 kartspeed; // Kart speed stat between 1 and 9 UINT8 kartweight; // Kart weight stat between 1 and 9 diff --git a/src/deh_tables.c b/src/deh_tables.c index aa9dc9310..a36b7af9d 100644 --- a/src/deh_tables.c +++ b/src/deh_tables.c @@ -3282,6 +3282,10 @@ const char *const STATE_LIST[] = { // array length left dynamic for sanity testi //"S_ITEMCAPSULE_BOTTOM", //"S_ITEMCAPSULE_INSIDE", + "S_MAGICIANBOX", + "S_MAGICIANBOXTOP", + "S_MAGICIANBOXBOTTOM", + // Signpost sparkles "S_SIGNSPARK1", "S_SIGNSPARK2", @@ -5284,6 +5288,7 @@ const char *const MOBJTYPE_LIST[] = { // array length left dynamic for sanity t "MT_FLOATINGITEM", "MT_ITEMCAPSULE", "MT_ITEMCAPSULE_PART", + "MT_MAGICIANBOX", "MT_SIGNSPARKLE", @@ -6323,8 +6328,8 @@ struct int_const_s const INT_CONST[] = { {"CR_ZOOMTUBE",CR_ZOOMTUBE}, // Character flags (skinflags_t) - {"SF_HIRES",SF_HIRES}, {"SF_MACHINE",SF_MACHINE}, + {"SF_IRONMAN",SF_IRONMAN}, // Sound flags {"SF_TOTALLYSINGLE",SF_TOTALLYSINGLE}, @@ -6691,6 +6696,7 @@ struct int_const_s const INT_CONST[] = { {"V_OVERLAY",V_OVERLAY}, {"V_ALLOWLOWERCASE",V_ALLOWLOWERCASE}, {"V_FLIP",V_FLIP}, + {"V_VFLIP",V_VFLIP}, {"V_SNAPTOTOP",V_SNAPTOTOP}, {"V_SNAPTOBOTTOM",V_SNAPTOBOTTOM}, {"V_SNAPTOLEFT",V_SNAPTOLEFT}, diff --git a/src/f_finale.c b/src/f_finale.c index a0ae60cf2..ca5b44fb3 100644 --- a/src/f_finale.c +++ b/src/f_finale.c @@ -2729,7 +2729,7 @@ void F_EndTextPrompt(boolean forceexec, boolean noexec) // \todo net safety, maybe loop all player thinkers? if ((promptwasactive || forceexec) && !noexec && promptpostexectag) { - if (tmthing) // edge case where starting an invalid prompt immediately on level load will make P_MapStart fail + if (tm.thing) // edge case where starting an invalid prompt immediately on level load will make P_MapStart fail P_LinedefExecute(promptpostexectag, promptmo, NULL); else { diff --git a/src/g_demo.c b/src/g_demo.c index 7978d0ef6..8566a4c22 100644 --- a/src/g_demo.c +++ b/src/g_demo.c @@ -94,8 +94,13 @@ static struct { // EZT_SCALE fixed_t scale, lastscale; - // EZT_KART - INT32 kartitem, kartamount, kartbumpers; + // EZT_ITEMDATA + SINT8 itemtype; + UINT8 itemamount, bumpers; + + // EZT_STATDATA + UINT8 skinid, kartspeed, kartweight; + UINT32 charflags; UINT8 desyncframes; // Don't try to resync unless we've been off for two frames, to monkeypatch a few trouble spots @@ -133,6 +138,7 @@ demoghost *ghosts = NULL; #define DEMO_SPECTATOR 0x01 #define DEMO_KICKSTART 0x02 #define DEMO_SHRINKME 0x04 +#define DEMO_BOT 0x08 // For demos #define ZT_FWD 0x01 @@ -172,13 +178,14 @@ static ticcmd_t oldcmd[MAXPLAYERS]; #define GZT_EXTRA 0x40 #define GZT_FOLLOW 0x80 // Followmobj -// GZT_EXTRA flags -#define EZT_COLOR 0x001 // Changed color (Super transformation, Mario fireflowers/invulnerability, etc.) -#define EZT_FLIP 0x002 // Reversed gravity -#define EZT_SCALE 0x004 // Changed size -#define EZT_HIT 0x008 // Damaged a mobj -#define EZT_SPRITE 0x010 // Changed sprite set completely out of PLAY (NiGHTS, SOCs, whatever) -#define EZT_KART 0x020 // SRB2Kart: Changed current held item/quantity and bumpers for battle +// GZT_EXTRA flags (currently UINT8) +#define EZT_COLOR 0x01 // Changed color (Super transformation, Mario fireflowers/invulnerability, etc.) +#define EZT_FLIP 0x02 // Reversed gravity +#define EZT_SCALE 0x04 // Changed size +#define EZT_HIT 0x08 // Damaged a mobj +#define EZT_SPRITE 0x10 // Changed sprite set completely out of PLAY (NiGHTS, SOCs, whatever) +#define EZT_ITEMDATA 0x20 // Changed current held item/quantity and bumpers for battle +#define EZT_STATDATA 0x40 // Changed skin/stats // GZT_FOLLOW flags #define FZT_SPAWNED 0x01 // just been spawned @@ -206,14 +213,23 @@ void G_LoadMetal(UINT8 **buffer) } // Finds a skin with the closest stats if the expected skin doesn't exist. -static INT32 GetSkinNumClosestToStats(UINT8 kartspeed, UINT8 kartweight) +static INT32 GetSkinNumClosestToStats(UINT8 kartspeed, UINT8 kartweight, UINT32 flags) { INT32 i, closest_skin = 0; - UINT8 closest_stats = UINT8_MAX, stat_diff; + UINT8 closest_stats, stat_diff; + boolean doflagcheck = true; + UINT32 flagcheck = flags; + +flaglessretry: + closest_stats = UINT8_MAX; for (i = 0; i < numskins; i++) { stat_diff = abs(skins[i].kartspeed - kartspeed) + abs(skins[i].kartweight - kartweight); + if (doflagcheck && (skins[i].flags & flagcheck) != flagcheck) + { + continue; + } if (stat_diff < closest_stats) { closest_stats = stat_diff; @@ -221,17 +237,22 @@ static INT32 GetSkinNumClosestToStats(UINT8 kartspeed, UINT8 kartweight) } } + if (stat_diff && (doflagcheck || closest_stats == UINT8_MAX)) + { + // Just grab *any* SF_IRONMAN if we don't get it on the first pass. + if ((flagcheck & SF_IRONMAN) && (flagcheck != SF_IRONMAN)) + { + flagcheck = SF_IRONMAN; + } + + doflagcheck = false; + + goto flaglessretry; + } + return closest_skin; } -static void FindClosestSkinForStats(UINT32 p, UINT8 kartspeed, UINT8 kartweight) -{ - INT32 closest_skin = GetSkinNumClosestToStats(kartspeed, kartweight); - - //CONS_Printf("Using %s instead...\n", skins[closest_skin].name); - SetPlayerSkinByNum(p, closest_skin); -} - void G_ReadDemoExtraData(void) { INT32 p, extradata, i; @@ -255,6 +276,64 @@ void G_ReadDemoExtraData(void) { extradata = READUINT8(demo_p); + if (extradata & DXD_PLAYSTATE) + { + i = READUINT8(demo_p); + + if (!playeringame[p]) + { + CL_ClearPlayer(p); + playeringame[p] = true; + G_AddPlayer(p); + players[p].spectator = true; + } + + if ((players[p].bot = !!(i & DXD_PST_ISBOT))) + { + players[p].botvars.difficulty = READUINT8(demo_p); + players[p].botvars.diffincrease = READUINT8(demo_p); // needed to avoid having to duplicate logic + players[p].botvars.rival = (boolean)READUINT8(demo_p); + + i &= ~DXD_PST_ISBOT; + } + + switch (i) { + case DXD_PST_PLAYING: + if (players[p].bot) + { + players[p].spectator = false; + } + else + { + players[p].pflags |= PF_WANTSTOJOIN; + } + //CONS_Printf("player %s is despectating on tic %d\n", player_names[p], leveltime); + break; + + case DXD_PST_SPECTATING: + players[p].pflags &= ~PF_WANTSTOJOIN; // double-fuck you + if (players[p].spectator != true) + { + //CONS_Printf("player %s is spectating on tic %d\n", player_names[p], leveltime); + players[p].spectator = true; + if (players[p].mo) + P_DamageMobj(players[p].mo, NULL, NULL, 1, DMG_INSTAKILL); + else + players[p].playerstate = PST_REBORN; + } + break; + + case DXD_PST_LEFT: + CL_RemovePlayer(p, 0); + break; + } + + G_ResetViews(); + + // maybe these are necessary? + K_CheckBumpers(); + P_CheckRacers(); + } if (extradata & DXD_RESPAWN) { if (players[p].mo) @@ -265,21 +344,19 @@ void G_ReadDemoExtraData(void) } if (extradata & DXD_SKIN) { - UINT8 kartspeed, kartweight; + UINT8 skinid; // Skin - M_Memcpy(name, demo_p, 16); - demo_p += 16; - SetPlayerSkin(p, name); - kartspeed = READUINT8(demo_p); - kartweight = READUINT8(demo_p); + skinid = READUINT8(demo_p); + if (skinid >= demo.numskins) + skinid = 0; + SetPlayerSkinByNum(p, demo.skinlist[skinid].mapping); + demo.currentskinid[p] = skinid; - if (stricmp(skins[players[p].skin].name, name) != 0) - FindClosestSkinForStats(p, kartspeed, kartweight); - - players[p].kartspeed = kartspeed; - players[p].kartweight = kartweight; + players[p].kartspeed = ghostext[p].kartspeed = demo.skinlist[skinid].kartspeed; + players[p].kartweight = ghostext[p].kartweight = demo.skinlist[skinid].kartweight; + players[p].charflags = ghostext[p].charflags = demo.skinlist[skinid].flags; } if (extradata & DXD_COLOR) { @@ -320,48 +397,6 @@ void G_ReadDemoExtraData(void) } } } - if (extradata & DXD_PLAYSTATE) - { - i = READUINT8(demo_p); - - switch (i) { - case DXD_PST_PLAYING: - players[p].pflags |= PF_WANTSTOJOIN; // fuck you - //CONS_Printf("player %s is despectating on tic %d\n", player_names[p], leveltime); - break; - - case DXD_PST_SPECTATING: - players[p].pflags &= ~PF_WANTSTOJOIN; // double-fuck you - if (!playeringame[p]) - { - CL_ClearPlayer(p); - playeringame[p] = true; - G_AddPlayer(p); - players[p].spectator = true; - //CONS_Printf("player %s is joining server on tic %d\n", player_names[p], leveltime); - } - else - { - //CONS_Printf("player %s is spectating on tic %d\n", player_names[p], leveltime); - players[p].spectator = true; - if (players[p].mo) - P_DamageMobj(players[p].mo, NULL, NULL, 1, DMG_INSTAKILL); - else - players[p].playerstate = PST_REBORN; - } - break; - - case DXD_PST_LEFT: - CL_RemovePlayer(p, 0); - break; - } - - G_ResetViews(); - - // maybe these are necessary? - K_CheckBumpers(); - P_CheckRacers(); - } if (extradata & DXD_WEAPONPREF) { WeaponPref_Parse(&demo_p, p); @@ -375,6 +410,7 @@ void G_ReadDemoExtraData(void) while (p != DW_END) { UINT32 rng; + boolean storesynced = demosynced; switch (p) { @@ -388,10 +424,11 @@ void G_ReadDemoExtraData(void) P_SetRandSeed(i, rng); if (demosynced) - CONS_Alert(CONS_WARNING, M_GetText("Demo playback has desynced (RNG)!\n")); - demosynced = false; + CONS_Alert(CONS_WARNING, "Demo playback has desynced (RNG class %d)!\n", i); + storesynced = false; } } + demosynced = storesynced; } p = READUINT8(demo_p); @@ -417,18 +454,43 @@ void G_WriteDemoExtraData(void) WRITEUINT8(demo_p, i); WRITEUINT8(demo_p, demo_extradata[i]); + if (demo_extradata[i] & DXD_PLAYSTATE) + { + UINT8 pst = DXD_PST_PLAYING; + + demo_writerng = 1; + + if (!playeringame[i]) + { + pst = DXD_PST_LEFT; + } + else if ( + players[i].spectator && + !(players[i].pflags & PF_WANTSTOJOIN) // <= fuck you specifically + ) + { + pst = DXD_PST_SPECTATING; + } + + if (players[i].bot) + { + pst |= DXD_PST_ISBOT; + } + + WRITEUINT8(demo_p, pst); + + if (pst & DXD_PST_ISBOT) + { + WRITEUINT8(demo_p, players[i].botvars.difficulty); + WRITEUINT8(demo_p, players[i].botvars.diffincrease); // needed to avoid having to duplicate logic + WRITEUINT8(demo_p, (UINT8)players[i].botvars.rival); + } + } //if (demo_extradata[i] & DXD_RESPAWN) has no extra data if (demo_extradata[i] & DXD_SKIN) { // Skin - memset(name, 0, 16); - strncpy(name, skins[players[i].skin].name, 16); - M_Memcpy(demo_p,name,16); - demo_p += 16; - - WRITEUINT8(demo_p, skins[players[i].skin].kartspeed); - WRITEUINT8(demo_p, skins[players[i].skin].kartweight); - + WRITEUINT8(demo_p, players[i].skin); } if (demo_extradata[i] & DXD_COLOR) { @@ -469,19 +531,6 @@ void G_WriteDemoExtraData(void) demo_p += 16; } - if (demo_extradata[i] & DXD_PLAYSTATE) - { - demo_writerng = 1; - if (!playeringame[i]) - WRITEUINT8(demo_p, DXD_PST_LEFT); - else if ( - players[i].spectator && - !(players[i].pflags & PF_WANTSTOJOIN) // <= fuck you specifically - ) - WRITEUINT8(demo_p, DXD_PST_SPECTATING); - else - WRITEUINT8(demo_p, DXD_PST_PLAYING); - } if (demo_extradata[i] & DXD_WEAPONPREF) { WeaponPref_Save(&demo_p, i); @@ -788,15 +837,29 @@ void G_WriteGhostTic(mobj_t *ghost, INT32 playernum) } if (ghost->player && ( - ghostext[playernum].kartitem != ghost->player->itemtype || - ghostext[playernum].kartamount != ghost->player->itemamount || - ghostext[playernum].kartbumpers != ghost->player->bumpers + ghostext[playernum].itemtype != ghost->player->itemtype || + ghostext[playernum].itemamount != ghost->player->itemamount || + ghostext[playernum].bumpers != ghost->player->bumpers )) { - ghostext[playernum].flags |= EZT_KART; - ghostext[playernum].kartitem = ghost->player->itemtype; - ghostext[playernum].kartamount = ghost->player->itemamount; - ghostext[playernum].kartbumpers = ghost->player->bumpers; + ghostext[playernum].flags |= EZT_ITEMDATA; + ghostext[playernum].itemtype = ghost->player->itemtype; + ghostext[playernum].itemamount = ghost->player->itemamount; + ghostext[playernum].bumpers = ghost->player->bumpers; + } + + if (ghost->player && ( + ghostext[playernum].skinid != (UINT8)(((skin_t *)ghost->skin)-skins) || + ghostext[playernum].kartspeed != ghost->player->kartspeed || + ghostext[playernum].kartweight != ghost->player->kartweight || + ghostext[playernum].charflags != ghost->player->charflags + )) + { + ghostext[playernum].flags |= EZT_STATDATA; + ghostext[playernum].skinid = (UINT8)(((skin_t *)ghost->skin)-skins); + ghostext[playernum].kartspeed = ghost->player->kartspeed; + ghostext[playernum].kartweight = ghost->player->kartweight; + ghostext[playernum].charflags = ghost->player->charflags; } if (ghostext[playernum].flags) @@ -840,11 +903,18 @@ void G_WriteGhostTic(mobj_t *ghost, INT32 playernum) } if (ghostext[playernum].flags & EZT_SPRITE) WRITEUINT16(demo_p,oldghost[playernum].sprite); - if (ghostext[playernum].flags & EZT_KART) + if (ghostext[playernum].flags & EZT_ITEMDATA) { - WRITEINT32(demo_p, ghostext[playernum].kartitem); - WRITEINT32(demo_p, ghostext[playernum].kartamount); - WRITEINT32(demo_p, ghostext[playernum].kartbumpers); + WRITESINT8(demo_p, ghostext[playernum].itemtype); + WRITEUINT8(demo_p, ghostext[playernum].itemamount); + WRITEUINT8(demo_p, ghostext[playernum].bumpers); + } + if (ghostext[playernum].flags & EZT_STATDATA) + { + WRITEUINT8(demo_p,ghostext[playernum].skinid); + WRITEUINT8(demo_p,ghostext[playernum].kartspeed); + WRITEUINT8(demo_p,ghostext[playernum].kartweight); + WRITEUINT32(demo_p, ghostext[playernum].charflags); } ghostext[playernum].flags = 0; @@ -1016,11 +1086,20 @@ void G_ConsGhostTic(INT32 playernum) } if (xziptic & EZT_SPRITE) demo_p += sizeof(UINT16); - if (xziptic & EZT_KART) + if (xziptic & EZT_ITEMDATA) { - ghostext[playernum].kartitem = READINT32(demo_p); - ghostext[playernum].kartamount = READINT32(demo_p); - ghostext[playernum].kartbumpers = READINT32(demo_p); + ghostext[playernum].itemtype = READSINT8(demo_p); + ghostext[playernum].itemamount = READUINT8(demo_p); + ghostext[playernum].bumpers = READUINT8(demo_p); + } + if (xziptic & EZT_STATDATA) + { + ghostext[playernum].skinid = READUINT8(demo_p); + if (ghostext[playernum].skinid >= demo.numskins) + ghostext[playernum].skinid = 0; + ghostext[playernum].kartspeed = READUINT8(demo_p); + ghostext[playernum].kartweight = READUINT8(demo_p); + ghostext[playernum].charflags = READUINT32(demo_p); } } @@ -1079,17 +1158,41 @@ void G_ConsGhostTic(INT32 playernum) else ghostext[playernum].desyncframes = 0; - if (players[playernum].itemtype != ghostext[playernum].kartitem - || players[playernum].itemamount != ghostext[playernum].kartamount - || players[playernum].bumpers != ghostext[playernum].kartbumpers) + if (players[playernum].itemtype != ghostext[playernum].itemtype + || players[playernum].itemamount != ghostext[playernum].itemamount + || players[playernum].bumpers != ghostext[playernum].bumpers) { if (demosynced) CONS_Alert(CONS_WARNING, M_GetText("Demo playback has desynced (item/bumpers)!\n")); demosynced = false; - players[playernum].itemtype = ghostext[playernum].kartitem; - players[playernum].itemamount = ghostext[playernum].kartamount; - players[playernum].bumpers = ghostext[playernum].kartbumpers; + players[playernum].itemtype = ghostext[playernum].itemtype; + players[playernum].itemamount = ghostext[playernum].itemamount; + players[playernum].bumpers = ghostext[playernum].bumpers; + } + + if (players[playernum].kartspeed != ghostext[playernum].kartspeed + || players[playernum].kartweight != ghostext[playernum].kartweight + || players[playernum].charflags != ghostext[playernum].charflags || + demo.skinlist[ghostext[playernum].skinid].mapping != (UINT8)(((skin_t *)testmo->skin)-skins)) + { + if (demosynced) + CONS_Alert(CONS_WARNING, M_GetText("Demo playback has desynced (Character/stats)!\n")); + demosynced = false; + + testmo->skin = &skins[demo.skinlist[ghostext[playernum].skinid].mapping]; + players[playernum].kartspeed = ghostext[playernum].kartspeed; + players[playernum].kartweight = ghostext[playernum].kartweight; + players[playernum].charflags = ghostext[playernum].charflags; + + if (demo.skinlist[demo.currentskinid[playernum]].flags & SF_IRONMAN) + { + players[playernum].lastfakeskin = players[playernum].fakeskin; + players[playernum].fakeskin = + (ghostext[playernum].skinid == demo.currentskinid[playernum]) + ? MAXSKINS + : ghostext[playernum].skinid; + } } } @@ -1115,16 +1218,16 @@ void G_GhostTicker(void) if (ziptic == 0) // Only support player 0 info for now { ziptic = READUINT8(g->p); + if (ziptic & DXD_PLAYSTATE && READUINT8(g->p) != DXD_PST_PLAYING) + I_Error("Ghost is not a record attack ghost PLAYSTATE"); //@TODO lmao don't blow up like this if (ziptic & DXD_SKIN) - g->p += 18; // We _could_ read this info, but it shouldn't change anything in record attack... + g->p++; // We _could_ read this info, but it shouldn't change anything in record attack... if (ziptic & DXD_COLOR) g->p += 16; // Same tbh if (ziptic & DXD_NAME) g->p += 16; // yea if (ziptic & DXD_FOLLOWER) g->p += 32; // ok (32 because there's both the skin and the colour) - if (ziptic & DXD_PLAYSTATE && READUINT8(g->p) != DXD_PST_PLAYING) - I_Error("Ghost is not a record attack ghost PLAYSTATE"); //@TODO lmao don't blow up like this if (ziptic & DXD_WEAPONPREF) g->p++; // ditto } @@ -1201,13 +1304,6 @@ void G_GhostTicker(void) g->mo->z = g->oldmo.z; P_SetThingPosition(g->mo); g->mo->angle = g->oldmo.angle; - g->mo->frame = g->oldmo.frame | tr_trans30<fadein) - { - g->mo->frame += (((--g->fadein)/6)<fadein is bad, and it's only set once, so... - g->mo->renderflags &= ~RF_DONTDRAW; - } - g->mo->sprite2 = g->oldmo.sprite2; if (ziptic & GZT_EXTRA) { // But wait, there's more! @@ -1218,9 +1314,6 @@ void G_GhostTicker(void) switch(g->color) { default: - case GHC_RETURNSKIN: - g->mo->skin = g->oldmo.skin; - /* FALLTHRU */ case GHC_NORMAL: // Go back to skin color g->mo->color = g->oldmo.color; break; @@ -1228,9 +1321,6 @@ void G_GhostTicker(void) case GHC_SUPER: case GHC_INVINCIBLE: break; - case GHC_FIREFLOWER: // Fireflower - g->mo->color = SKINCOLOR_WHITE; - break; } } if (xziptic & EZT_FLIP) @@ -1270,8 +1360,25 @@ void G_GhostTicker(void) } if (xziptic & EZT_SPRITE) g->mo->sprite = READUINT16(g->p); - if (xziptic & EZT_KART) - g->p += 12; // kartitem, kartamount, kartbumpers + if (xziptic & EZT_ITEMDATA) + g->p += 3; // itemtype, itemamount, bumpers + if (xziptic & EZT_STATDATA) + { + UINT8 skinid = READUINT8(g->p); + if (skinid >= g->numskins) + skinid = 0; + g->mo->skin = &skins[g->skinlist[skinid].mapping]; + g->p += 6; // kartspeed, kartweight, charflags + } + } + + // todo better defaulting + g->mo->sprite2 = g->oldmo.sprite2; + g->mo->frame = g->oldmo.frame | tr_trans30<fadein) + { + g->mo->frame += (((--g->fadein)/6)<fadein is bad, and it's only set once, so... + g->mo->renderflags &= ~RF_DONTDRAW; } #define follow g->mo->tracer @@ -1381,6 +1488,7 @@ skippedghosttic: p->next = g->next; else ghosts = g->next; + Z_Free(g->skinlist); Z_Free(g); continue; } @@ -1954,291 +2062,24 @@ void G_RecordMetal(void) metalrecording = true; } -void G_BeginRecording(void) +static void G_SaveDemoExtraFiles(UINT8 **pp) { - UINT8 i, j, p; - char name[MAXCOLORNAME+1]; - player_t *player = &players[consoleplayer]; - char *filename; - UINT8 totalfiles; - UINT8 *m; + UINT8 totalfiles = 0, i; + UINT8 *m = (*pp);/* file count */ + (*pp)++; - if (demo_p) - return; - memset(name,0,sizeof(name)); - - demo_p = demobuffer; - demoflags = DF_GHOST|(multiplayer ? DF_MULTIPLAYER : (modeattacking<lumpname, MAXMAPLUMPNAME); - M_Memcpy(demo_p, mapmd5, 16); demo_p += 16; - - WRITEUINT8(demo_p, demoflags); - WRITEUINT8(demo_p, gametype & 0xFF); - WRITEUINT8(demo_p, numlaps); - - // file list - m = demo_p;/* file count */ - demo_p += 1; - - totalfiles = 0; for (i = mainwads; ++i < numwadfiles; ) if (wadfiles[i]->important) { nameonly(( filename = va("%s", wadfiles[i]->filename) )); - WRITESTRINGL(demo_p, filename, MAX_WADPATH); - WRITEMEM(demo_p, wadfiles[i]->md5sum, 16); + WRITESTRINGL((*pp), filename, MAX_WADPATH); + WRITEMEM((*pp), wadfiles[i]->md5sum, 16); totalfiles++; } WRITEUINT8(m, totalfiles); - - switch ((demoflags & DF_ATTACKMASK)>>DF_ATTACKSHIFT) - { - case ATTACKING_NONE: // 0 - break; - case ATTACKING_TIME: // 1 - demotime_p = demo_p; - WRITEUINT32(demo_p,UINT32_MAX); // time - WRITEUINT32(demo_p,UINT32_MAX); // lap - break; - case ATTACKING_CAPSULES: // 2 - demotime_p = demo_p; - WRITEUINT32(demo_p,UINT32_MAX); // time - break; - default: // 3 - break; - } - - for (i = 0; i < PRNUMCLASS; i++) - { - WRITEUINT32(demo_p, P_GetInitSeed(i)); - } - - // Reserved for extrainfo location from start of file - demoinfo_p = demo_p; - WRITEUINT32(demo_p, 0); - - // Save netvar data - CV_SaveDemoVars(&demo_p); - - // Now store some info for each in-game player - - // Lat' 12/05/19: Do note that for the first game you load, everything that gets saved here is total garbage; - // The name will always be Player , the skin sonic, the color None and the follower 0. This is only correct on subsequent games. - // In the case of said first game, the skin and the likes are updated with Got_NameAndColor, which are then saved in extradata for the demo with DXD_SKIN in r_things.c for instance. - - - for (p = 0; p < MAXPLAYERS; p++) { - if (playeringame[p]) { - player = &players[p]; - WRITEUINT8(demo_p, p); - - i = 0; - if (player->spectator) - i |= DEMO_SPECTATOR; - if (player->pflags & PF_KICKSTARTACCEL) - i |= DEMO_KICKSTART; - if (player->pflags & PF_SHRINKME) - i |= DEMO_SHRINKME; - WRITEUINT8(demo_p, i); - - // Name - memset(name, 0, 16); - strncpy(name, player_names[p], 16); - M_Memcpy(demo_p,name,16); - demo_p += 16; - - // Skin - memset(name, 0, 16); - strncpy(name, skins[player->skin].name, 16); - M_Memcpy(demo_p,name,16); - demo_p += 16; - - // Color - memset(name, 0, 16); - strncpy(name, skincolors[player->skincolor].name, 16); - M_Memcpy(demo_p,name,16); - demo_p += 16; - - // Save follower's skin name - // PS: We must check for 'follower' to determine if the followerskin is valid. It's going to be 0 if we don't have a follower, but 0 is also absolutely a valid follower! - // Doesn't really matter if the follower mobj is valid so long as it exists in a way or another. - - memset(name, 0, 16); - if (player->follower) - strncpy(name, followers[player->followerskin].name, 16); - else - strncpy(name, "None", 16); // Say we don't have one, then. - - M_Memcpy(demo_p,name,16); - demo_p += 16; - - // Save follower's colour - memset(name, 0, 16); - for (j = (numskincolors+2)-1; j > 0; j--) - { - if (Followercolor_cons_t[j].value == players[i].followercolor) - break; - } - strncpy(name, Followercolor_cons_t[j].strvalue, 16); // Not KartColor_Names because followercolor has extra values such as "Match" - M_Memcpy(demo_p, name, 16); - demo_p += 16; - - // Score, since Kart uses this to determine where you start on the map - WRITEUINT32(demo_p, player->score); - - // Power Levels - WRITEUINT16(demo_p, clientpowerlevels[p][gametype == GT_BATTLE ? PWRLV_BATTLE : PWRLV_RACE]); - - // Kart speed and weight - WRITEUINT8(demo_p, skins[player->skin].kartspeed); - WRITEUINT8(demo_p, skins[player->skin].kartweight); - - // And mobjtype_t is best with UINT32 too... - WRITEUINT32(demo_p, player->followitem); - } - } - - WRITEUINT8(demo_p, 0xFF); // Denote the end of the player listing - - // player lua vars, always saved even if empty - if (demoflags & DF_LUAVARS) - LUA_Archive(&demo_p); - - memset(&oldcmd,0,sizeof(oldcmd)); - memset(&oldghost,0,sizeof(oldghost)); - memset(&ghostext,0,sizeof(ghostext)); - - for (i = 0; i < MAXPLAYERS; i++) - { - ghostext[i].lastcolor = ghostext[i].color = GHC_NORMAL; - ghostext[i].lastscale = ghostext[i].scale = FRACUNIT; - - if (players[i].mo) - { - oldghost[i].x = players[i].mo->x; - oldghost[i].y = players[i].mo->y; - oldghost[i].z = players[i].mo->z; - oldghost[i].angle = players[i].mo->angle; - - // preticker started us gravity flipped - if (players[i].mo->eflags & MFE_VERTICALFLIP) - ghostext[i].flags |= EZT_FLIP; - } - } -} - -void G_BeginMetal(void) -{ - mobj_t *mo = players[consoleplayer].mo; - -#if 0 - if (demo_p) - return; -#endif - - demo_p = demobuffer; - - // Write header. - M_Memcpy(demo_p, DEMOHEADER, 12); demo_p += 12; - WRITEUINT8(demo_p,VERSION); - WRITEUINT8(demo_p,SUBVERSION); - WRITEUINT16(demo_p,DEMOVERSION); - - // demo checksum - demo_p += 16; - - M_Memcpy(demo_p, "METL", 4); demo_p += 4; - - memset(&ghostext,0,sizeof(ghostext)); - ghostext[0].lastscale = ghostext[0].scale = FRACUNIT; - - // Set up our memory. - memset(&oldmetal,0,sizeof(oldmetal)); - oldmetal.x = mo->x; - oldmetal.y = mo->y; - oldmetal.z = mo->z; - oldmetal.angle = mo->angle>>24; -} - -void G_WriteStanding(UINT8 ranking, char *name, INT32 skinnum, UINT16 color, UINT32 val) -{ - char temp[16]; - - if (demoinfo_p && *(UINT32 *)demoinfo_p == 0) - { - WRITEUINT8(demo_p, DEMOMARKER); // add the demo end marker - *(UINT32 *)demoinfo_p = demo_p - demobuffer; - } - - WRITEUINT8(demo_p, DW_STANDING); - WRITEUINT8(demo_p, ranking); - - // Name - memset(temp, 0, 16); - strncpy(temp, name, 16); - M_Memcpy(demo_p,temp,16); - demo_p += 16; - - // Skin - memset(temp, 0, 16); - strncpy(temp, skins[skinnum].name, 16); - M_Memcpy(demo_p,temp,16); - demo_p += 16; - - // Color - memset(temp, 0, 16); - strncpy(temp, skincolors[color].name, 16); - M_Memcpy(demo_p,temp,16); - demo_p += 16; - - // Score/time/whatever - WRITEUINT32(demo_p, val); -} - -void G_SetDemoTime(UINT32 ptime, UINT32 plap) -{ - if (!demo.recording || !demotime_p) - return; - if (demoflags & DF_TIMEATTACK) - { - WRITEUINT32(demotime_p, ptime); - WRITEUINT32(demotime_p, plap); - demotime_p = NULL; - } - else if (demoflags & DF_BREAKTHECAPSULES) - { - WRITEUINT32(demotime_p, ptime); - (void)plap; - demotime_p = NULL; - } } static void G_LoadDemoExtraFiles(UINT8 **pp) @@ -2403,6 +2244,367 @@ static UINT8 G_CheckDemoExtraFiles(UINT8 **pp, boolean quick) return error; } +static void G_SaveDemoSkins(UINT8 **pp) +{ + char skin[16]; + UINT8 i; + + WRITEUINT8((*pp), numskins); + for (i = 0; i < numskins; i++) + { + // Skinname, for first attempt at identification. + memset(skin, 0, 16); + strncpy(skin, skins[i].name, 16); + WRITEMEM((*pp), skin, 16); + + // Backup information for second pass. + WRITEUINT8((*pp), skins[i].kartspeed); + WRITEUINT8((*pp), skins[i].kartweight); + WRITEUINT32((*pp), skins[i].flags); + } +} + +static democharlist_t *G_LoadDemoSkins(UINT8 **pp, UINT8 *worknumskins, boolean getclosest) +{ + char skin[17]; + UINT8 i; + democharlist_t *skinlist = NULL; + + (*worknumskins) = READUINT8((*pp)); + if (!(*worknumskins)) + return NULL; + + skinlist = Z_Calloc(sizeof(democharlist_t) * (*worknumskins), PU_STATIC, NULL); + if (!skinlist) + { + I_Error("G_LoadDemoSkins: Insufficient memory to allocate list"); + } + + skin[16] = '\0'; + + for (i = 0; i < (*worknumskins); i++) + { + INT32 result = -1; + + READMEM((*pp), skin, 16); + skinlist[i].kartspeed = READUINT8((*pp)); + skinlist[i].kartweight = READUINT8((*pp)); + skinlist[i].flags = READUINT32((*pp)); + + result = R_SkinAvailable(skin); + if (result == -1) + { + if (!getclosest) + { + result = MAXSKINS; + } + else + { + result = GetSkinNumClosestToStats(skinlist[i].kartspeed, skinlist[i].kartweight, skinlist[i].flags); + } + } + + if (result != -1) + { + skinlist[i].mapping = (UINT8)result; + } + } + + return skinlist; +} + +static void G_SkipDemoSkins(UINT8 **pp) +{ + UINT8 demonumskins; + UINT8 i; + + demonumskins = READUINT8((*pp)); + for (i = 0; i < demonumskins; ++i) + { + (*pp) += 16; // name + (*pp)++; // kartspeed + (*pp)++; // kartweight + (*pp) += 4; // flags + } +} + +void G_BeginRecording(void) +{ + UINT8 i, j, p; + char name[MAXCOLORNAME+1]; + player_t *player = &players[consoleplayer]; + + if (demo_p) + return; + memset(name,0,sizeof(name)); + + demo_p = demobuffer; + demoflags = DF_GHOST|(multiplayer ? DF_MULTIPLAYER : (modeattacking<lumpname, MAXMAPLUMPNAME); + M_Memcpy(demo_p, mapmd5, 16); demo_p += 16; + + WRITEUINT8(demo_p, demoflags); + WRITEUINT8(demo_p, gametype & 0xFF); + WRITEUINT8(demo_p, numlaps); + + // file list + G_SaveDemoExtraFiles(&demo_p); + + // character list + G_SaveDemoSkins(&demo_p); + + switch ((demoflags & DF_ATTACKMASK)>>DF_ATTACKSHIFT) + { + case ATTACKING_NONE: // 0 + break; + case ATTACKING_TIME: // 1 + demotime_p = demo_p; + WRITEUINT32(demo_p,UINT32_MAX); // time + WRITEUINT32(demo_p,UINT32_MAX); // lap + break; + case ATTACKING_CAPSULES: // 2 + demotime_p = demo_p; + WRITEUINT32(demo_p,UINT32_MAX); // time + break; + default: // 3 + break; + } + + for (i = 0; i < PRNUMCLASS; i++) + { + WRITEUINT32(demo_p, P_GetInitSeed(i)); + } + + // Reserved for extrainfo location from start of file + demoinfo_p = demo_p; + WRITEUINT32(demo_p, 0); + + // Save netvar data + CV_SaveDemoVars(&demo_p); + + // Now store some info for each in-game player + + // Lat' 12/05/19: Do note that for the first game you load, everything that gets saved here is total garbage; + // The name will always be Player , the skin sonic, the color None and the follower 0. This is only correct on subsequent games. + // In the case of said first game, the skin and the likes are updated with Got_NameAndColor, which are then saved in extradata for the demo with DXD_SKIN in r_things.c for instance. + + + for (p = 0; p < MAXPLAYERS; p++) { + if (playeringame[p]) { + player = &players[p]; + WRITEUINT8(demo_p, p); + + i = 0; + if (player->spectator == true) + i |= DEMO_SPECTATOR; + if (player->pflags & PF_KICKSTARTACCEL) + i |= DEMO_KICKSTART; + if (player->pflags & PF_SHRINKME) + i |= DEMO_SHRINKME; + if (player->bot == true) + i |= DEMO_BOT; + WRITEUINT8(demo_p, i); + + if (i & DEMO_BOT) + { + WRITEUINT8(demo_p, player->botvars.difficulty); + WRITEUINT8(demo_p, player->botvars.diffincrease); // needed to avoid having to duplicate logic + WRITEUINT8(demo_p, (UINT8)player->botvars.rival); + } + + // Name + memset(name, 0, 16); + strncpy(name, player_names[p], 16); + M_Memcpy(demo_p,name,16); + demo_p += 16; + + // Skin (now index into demo.skinlist) + WRITEUINT8(demo_p, player->skin); + WRITEUINT8(demo_p, player->lastfakeskin); + + // Color + memset(name, 0, 16); + strncpy(name, skincolors[player->skincolor].name, 16); + M_Memcpy(demo_p,name,16); + demo_p += 16; + + // Save follower's skin name + // PS: We must check for 'follower' to determine if the followerskin is valid. It's going to be 0 if we don't have a follower, but 0 is also absolutely a valid follower! + // Doesn't really matter if the follower mobj is valid so long as it exists in a way or another. + + memset(name, 0, 16); + if (player->follower) + strncpy(name, followers[player->followerskin].name, 16); + else + strncpy(name, "None", 16); // Say we don't have one, then. + + M_Memcpy(demo_p,name,16); + demo_p += 16; + + // Save follower's colour + memset(name, 0, 16); + for (j = (numskincolors+2)-1; j > 0; j--) + { + if (Followercolor_cons_t[j].value == players[i].followercolor) + break; + } + strncpy(name, Followercolor_cons_t[j].strvalue, 16); // Not KartColor_Names because followercolor has extra values such as "Match" + M_Memcpy(demo_p, name, 16); + demo_p += 16; + + // Score, since Kart uses this to determine where you start on the map + WRITEUINT32(demo_p, player->score); + + // Power Levels + j = gametype == GT_BATTLE ? PWRLV_BATTLE : PWRLV_RACE; + WRITEUINT16(demo_p, clientpowerlevels[p][j]); + + // And mobjtype_t is best with UINT32 too... + WRITEUINT32(demo_p, player->followitem); + } + } + + WRITEUINT8(demo_p, 0xFF); // Denote the end of the player listing + + // player lua vars, always saved even if empty + if (demoflags & DF_LUAVARS) + LUA_Archive(&demo_p); + + memset(&oldcmd,0,sizeof(oldcmd)); + memset(&oldghost,0,sizeof(oldghost)); + memset(&ghostext,0,sizeof(ghostext)); + + for (i = 0; i < MAXPLAYERS; i++) + { + ghostext[i].lastcolor = ghostext[i].color = GHC_NORMAL; + ghostext[i].lastscale = ghostext[i].scale = FRACUNIT; + ghostext[i].skinid = players[i].skin; + ghostext[i].kartspeed = players[i].kartspeed; + ghostext[i].kartweight = players[i].kartweight; + ghostext[i].charflags = players[i].charflags; + + if (players[i].mo) + { + oldghost[i].x = players[i].mo->x; + oldghost[i].y = players[i].mo->y; + oldghost[i].z = players[i].mo->z; + oldghost[i].angle = players[i].mo->angle; + + // preticker started us gravity flipped + if (players[i].mo->eflags & MFE_VERTICALFLIP) + ghostext[i].flags |= EZT_FLIP; + } + } +} + +void G_BeginMetal(void) +{ + mobj_t *mo = players[consoleplayer].mo; + +#if 0 + if (demo_p) + return; +#endif + + demo_p = demobuffer; + + // Write header. + M_Memcpy(demo_p, DEMOHEADER, 12); demo_p += 12; + WRITEUINT8(demo_p,VERSION); + WRITEUINT8(demo_p,SUBVERSION); + WRITEUINT16(demo_p,DEMOVERSION); + + // demo checksum + demo_p += 16; + + M_Memcpy(demo_p, "METL", 4); demo_p += 4; + + memset(&ghostext,0,sizeof(ghostext)); + ghostext[0].lastscale = ghostext[0].scale = FRACUNIT; + + // Set up our memory. + memset(&oldmetal,0,sizeof(oldmetal)); + oldmetal.x = mo->x; + oldmetal.y = mo->y; + oldmetal.z = mo->z; + oldmetal.angle = mo->angle>>24; +} + +void G_WriteStanding(UINT8 ranking, char *name, INT32 skinnum, UINT16 color, UINT32 val) +{ + char temp[16]; + + if (demoinfo_p && *(UINT32 *)demoinfo_p == 0) + { + WRITEUINT8(demo_p, DEMOMARKER); // add the demo end marker + *(UINT32 *)demoinfo_p = demo_p - demobuffer; + } + + WRITEUINT8(demo_p, DW_STANDING); + WRITEUINT8(demo_p, ranking); + + // Name + memset(temp, 0, 16); + strncpy(temp, name, 16); + M_Memcpy(demo_p,temp,16); + demo_p += 16; + + // Skin + WRITEUINT8(demo_p, skinnum); + + // Color + memset(temp, 0, 16); + strncpy(temp, skincolors[color].name, 16); + M_Memcpy(demo_p,temp,16); + demo_p += 16; + + // Score/time/whatever + WRITEUINT32(demo_p, val); +} + +void G_SetDemoTime(UINT32 ptime, UINT32 plap) +{ + if (!demo.recording || !demotime_p) + return; + if (demoflags & DF_TIMEATTACK) + { + WRITEUINT32(demotime_p, ptime); + WRITEUINT32(demotime_p, plap); + demotime_p = NULL; + } + else if (demoflags & DF_BREAKTHECAPSULES) + { + WRITEUINT32(demotime_p, ptime); + (void)plap; + demotime_p = NULL; + } +} + // Returns bitfield: // 1 == new demo has lower time // 2 == new demo has higher score @@ -2445,6 +2647,8 @@ UINT8 G_CmpDemoTime(char *oldname, char *newname) p++; // numlaps G_SkipDemoExtraFiles(&p); + G_SkipDemoSkins(&p); + aflags = flags & (DF_TIMEATTACK|DF_BREAKTHECAPSULES); I_Assert(aflags); @@ -2509,6 +2713,8 @@ UINT8 G_CmpDemoTime(char *oldname, char *newname) return UINT8_MAX; } + G_SkipDemoSkins(&p); + oldtime = READUINT32(p); if (uselaps) oldlap = READUINT32(p); @@ -2540,7 +2746,8 @@ UINT8 G_CmpDemoTime(char *oldname, char *newname) void G_LoadDemoInfo(menudemo_t *pdemo) { UINT8 *infobuffer, *info_p, *extrainfo_p; - UINT8 version, subversion, pdemoflags; + UINT8 version, subversion, pdemoflags, worknumskins, skinid; + democharlist_t *skinlist = NULL; UINT16 pdemoversion, count; char mapname[MAXMAPLUMPNAME]; INT32 i; @@ -2611,6 +2818,13 @@ void G_LoadDemoInfo(menudemo_t *pdemo) pdemo->addonstatus = G_CheckDemoExtraFiles(&info_p, true); + skinlist = G_LoadDemoSkins(&info_p, &worknumskins, false); + if (!skinlist) + { + CONS_Alert(CONS_ERROR, M_GetText("%s has an invalid skin list.\n"), pdemo->filepath); + goto badreplay; + } + for (i = 0; i < PRNUMCLASS; i++) { info_p += 4; // RNG seed @@ -2657,15 +2871,10 @@ void G_LoadDemoInfo(menudemo_t *pdemo) extrainfo_p += 16; // Skin - M_Memcpy(temp,extrainfo_p,16); - extrainfo_p += 16; - pdemo->standings[count].skin = UINT8_MAX; - for (i = 0; i < numskins; i++) - if (stricmp(skins[i].name, temp) == 0) - { - pdemo->standings[count].skin = i; - break; - } + skinid = READUINT8(extrainfo_p); + if (skinid > worknumskins) + skinid = 0; + pdemo->standings[count].skin = skinlist[skinid].mapping; // Color M_Memcpy(temp,extrainfo_p,16); @@ -2687,12 +2896,14 @@ void G_LoadDemoInfo(menudemo_t *pdemo) } // I think that's everything we need? + Z_Free(skinlist); Z_Free(infobuffer); return; badreplay: pdemo->type = MD_INVALID; sprintf(pdemo->title, "INVALID REPLAY"); + Z_Free(skinlist); Z_Free(infobuffer); } @@ -2714,15 +2925,15 @@ void G_DeferedPlayDemo(const char *name) void G_DoPlayDemo(char *defdemoname) { - UINT8 i, p; + UINT8 i, p, numslots = 0; lumpnum_t l; - char skin[17],color[MAXCOLORNAME+1],follower[17],mapname[MAXMAPLUMPNAME],*n,*pdemoname; + char color[MAXCOLORNAME+1],follower[17],mapname[MAXMAPLUMPNAME],*n,*pdemoname; UINT8 version,subversion; UINT32 randseed[PRNUMCLASS]; char msg[1024]; - boolean spectator; - UINT8 slots[MAXPLAYERS], kartspeed[MAXPLAYERS], kartweight[MAXPLAYERS], numslots = 0; + boolean spectator, bot; + UINT8 slots[MAXPLAYERS], lastfakeskin[MAXPLAYERS]; #if defined(SKIPERRORS) && !defined(DEVELOP) boolean skiperrors = false; @@ -2730,7 +2941,6 @@ void G_DoPlayDemo(char *defdemoname) G_InitDemoRewind(); - skin[16] = '\0'; follower[16] = '\0'; color[MAXCOLORNAME] = '\0'; @@ -2902,6 +3112,20 @@ void G_DoPlayDemo(char *defdemoname) } } + // character list + demo.skinlist = G_LoadDemoSkins(&demo_p, &demo.numskins, true); + if (!demo.skinlist) + { + snprintf(msg, 1024, M_GetText("%s has an invalid skin list and cannot be played.\n"), pdemoname); + CONS_Alert(CONS_ERROR, "%s", msg); + M_StartMessage(msg, NULL, MM_NOTHING); + Z_Free(pdemoname); + Z_Free(demobuffer); + demo.playback = false; + demo.title = false; + return; + } + modeattacking = (demoflags & DF_ATTACKMASK)>>DF_ATTACKSHIFT; multiplayer = !!(demoflags & DF_MULTIPLAYER); demo.netgame = (multiplayer && !(demoflags & DF_NONETMP)); @@ -2940,6 +3164,8 @@ void G_DoPlayDemo(char *defdemoname) snprintf(msg, 1024, M_GetText("%s features a course that is not currently loaded.\n"), pdemoname); CONS_Alert(CONS_ERROR, "%s", msg); M_StartMessage(msg, NULL, MM_NOTHING); + Z_Free(demo.skinlist); + demo.skinlist = NULL; Z_Free(pdemoname); Z_Free(demobuffer); demo.playback = false; @@ -2956,6 +3182,8 @@ void G_DoPlayDemo(char *defdemoname) snprintf(msg, 1024, M_GetText("%s contains no data to be played.\n"), pdemoname); CONS_Alert(CONS_ERROR, "%s", msg); M_StartMessage(msg, NULL, MM_NOTHING); + Z_Free(demo.skinlist); + demo.skinlist = NULL; Z_Free(pdemoname); Z_Free(demobuffer); demo.playback = false; @@ -3000,14 +3228,17 @@ void G_DoPlayDemo(char *defdemoname) UINT8 flags = READUINT8(demo_p); spectator = !!(flags & DEMO_SPECTATOR); + bot = !!(flags & DEMO_BOT); - if (spectator == true) + if ((spectator || bot)) { if (modeattacking) { - snprintf(msg, 1024, M_GetText("%s is a Record Attack replay with spectators, and is thus invalid.\n"), pdemoname); + snprintf(msg, 1024, M_GetText("%s is a Record Attack replay with %s, and is thus invalid.\n"), pdemoname, (bot ? "bots" : "spectators")); CONS_Alert(CONS_ERROR, "%s", msg); M_StartMessage(msg, NULL, MM_NOTHING); + Z_Free(demo.skinlist); + demo.skinlist = NULL; Z_Free(pdemoname); Z_Free(demobuffer); demo.playback = false; @@ -3024,6 +3255,8 @@ void G_DoPlayDemo(char *defdemoname) snprintf(msg, 1024, M_GetText("%s is a Record Attack replay with multiple players, and is thus invalid.\n"), pdemoname); CONS_Alert(CONS_ERROR, "%s", msg); M_StartMessage(msg, NULL, MM_NOTHING); + Z_Free(demo.skinlist); + demo.skinlist = NULL; Z_Free(pdemoname); Z_Free(demobuffer); demo.playback = false; @@ -3047,21 +3280,28 @@ void G_DoPlayDemo(char *defdemoname) else players[p].pflags &= ~PF_SHRINKME; + if ((players[p].bot = bot) == true) + { + players[p].botvars.difficulty = READUINT8(demo_p); + players[p].botvars.diffincrease = READUINT8(demo_p); // needed to avoid having to duplicate logic + players[p].botvars.rival = (boolean)READUINT8(demo_p); + } + K_UpdateShrinkCheat(&players[p]); // Name M_Memcpy(player_names[p],demo_p,16); demo_p += 16; - /*if (players[p].spectator) - { - CONS_Printf("player %s is spectator at start\n", player_names[p]); - }*/ - // Skin - M_Memcpy(skin,demo_p,16); - demo_p += 16; - SetPlayerSkin(p, skin); + + i = READUINT8(demo_p); + if (i >= demo.numskins) + i = 0; + SetPlayerSkinByNum(p, demo.skinlist[i].mapping); + demo.currentskinid[p] = ghostext[p].skinid = i; + + lastfakeskin[p] = READUINT8(demo_p); // Color M_Memcpy(color,demo_p,16); @@ -3096,13 +3336,6 @@ void G_DoPlayDemo(char *defdemoname) // Power Levels clientpowerlevels[p][gametype == GT_BATTLE ? PWRLV_BATTLE : PWRLV_RACE] = READUINT16(demo_p); - // Kart stats, temporarily - kartspeed[p] = READUINT8(demo_p); - kartweight[p] = READUINT8(demo_p); - - if (stricmp(skins[players[p].skin].name, skin) != 0) - FindClosestSkinForStats(p, kartspeed[p], kartweight[p]); - // Followitem players[p].followitem = READUINT32(demo_p); @@ -3141,21 +3374,24 @@ void G_DoPlayDemo(char *defdemoname) G_InitNew(demoflags & DF_ENCORE, gamemap, true, true, false); // Doesn't matter whether you reset or not here, given changes to resetplayer. - for (i = 0; i < MAXPLAYERS; i++) + for (i = 0; i < numslots; i++) { - if (players[i].mo) + p = slots[i]; + if (players[p].mo) { - players[i].mo->color = players[i].skincolor; - oldghost[i].x = players[i].mo->x; - oldghost[i].y = players[i].mo->y; - oldghost[i].z = players[i].mo->z; + players[p].mo->color = players[p].skincolor; + oldghost[p].x = players[p].mo->x; + oldghost[p].y = players[p].mo->y; + oldghost[p].z = players[p].mo->z; } // Set saved attribute values // No cheat checking here, because even if they ARE wrong... // it would only break the replay if we clipped them. - players[i].kartspeed = kartspeed[i]; - players[i].kartweight = kartweight[i]; + players[p].kartspeed = ghostext[p].kartspeed = demo.skinlist[demo.currentskinid[p]].kartspeed; + players[p].kartweight = ghostext[p].kartweight = demo.skinlist[demo.currentskinid[p]].kartweight; + players[p].charflags = ghostext[p].charflags = demo.skinlist[demo.currentskinid[p]].flags; + players[p].lastfakeskin = lastfakeskin[p]; } demo.deferstart = true; @@ -3165,17 +3401,17 @@ void G_AddGhost(char *defdemoname) { INT32 i; lumpnum_t l; - char name[17],skin[17],color[MAXCOLORNAME+1],*n,*pdemoname,md5[16]; + char name[17],color[MAXCOLORNAME+1],*n,*pdemoname,md5[16]; demoghost *gh; UINT8 flags; UINT8 *buffer,*p; mapthing_t *mthing; UINT16 count, ghostversion; skin_t *ghskin = &skins[0]; - UINT8 kartspeed = UINT8_MAX, kartweight = UINT8_MAX; + UINT8 worknumskins; + democharlist_t *skinlist = NULL; name[16] = '\0'; - skin[16] = '\0'; color[16] = '\0'; n = defdemoname+strlen(defdemoname); @@ -3278,6 +3514,15 @@ void G_AddGhost(char *defdemoname) p++; // numlaps G_SkipDemoExtraFiles(&p); // Don't wanna modify the file list for ghosts. + skinlist = G_LoadDemoSkins(&p, &worknumskins, true); + if (!skinlist) + { + CONS_Alert(CONS_NOTICE, M_GetText("Ghost %s: Replay data has invalid skin list, cannot continue.\n"), pdemoname); + Z_Free(pdemoname); + Z_Free(buffer); + return; + } + switch ((flags & DF_ATTACKMASK)>>DF_ATTACKSHIFT) { case ATTACKING_NONE: // 0 @@ -3311,6 +3556,7 @@ void G_AddGhost(char *defdemoname) if (*p == DEMOMARKER) { CONS_Alert(CONS_NOTICE, M_GetText("Failed to add ghost %s: Replay is empty.\n"), pdemoname); + Z_Free(skinlist); Z_Free(pdemoname); Z_Free(buffer); return; @@ -3319,9 +3565,10 @@ void G_AddGhost(char *defdemoname) p++; // player number - doesn't really need to be checked, TODO maybe support adding multiple players' ghosts at once // any invalidating flags? - if ((READUINT8(p) & (DEMO_SPECTATOR)) != 0) + if ((READUINT8(p) & (DEMO_SPECTATOR|DEMO_BOT)) != 0) { CONS_Alert(CONS_NOTICE, M_GetText("Failed to add ghost %s: Invalid player slot.\n"), pdemoname); + Z_Free(skinlist); Z_Free(pdemoname); Z_Free(buffer); return; @@ -3332,8 +3579,10 @@ void G_AddGhost(char *defdemoname) p += 16; // Skin - M_Memcpy(skin, p, 16); - p += 16; + i = READUINT8(p); + if (i < worknumskins) + ghskin = &skins[skinlist[i].mapping]; + p++; // lastfakeskin // Color M_Memcpy(color, p, 16); @@ -3345,34 +3594,17 @@ void G_AddGhost(char *defdemoname) p += 4; // score p += 2; // powerlevel - kartspeed = READUINT8(p); - kartweight = READUINT8(p); - p += 4; // followitem (maybe change later) if (READUINT8(p) != 0xFF) { CONS_Alert(CONS_NOTICE, M_GetText("Failed to add ghost %s: Invalid player slot.\n"), pdemoname); + Z_Free(skinlist); Z_Free(pdemoname); Z_Free(buffer); return; } - for (i = 0; i < numskins; i++) - if (!stricmp(skins[i].name,skin)) - { - ghskin = &skins[i]; - break; - } - - if (i == numskins) - { - if (kartspeed != UINT8_MAX && kartweight != UINT8_MAX) - ghskin = &skins[GetSkinNumClosestToStats(kartspeed, kartweight)]; - - CONS_Alert(CONS_NOTICE, M_GetText("Ghost %s: Invalid character. Falling back to %s.\n"), pdemoname, ghskin->name); - } - gh = Z_Calloc(sizeof(demoghost), PU_LEVEL, NULL); gh->next = ghosts; @@ -3380,6 +3612,9 @@ void G_AddGhost(char *defdemoname) M_Memcpy(gh->checksum, md5, 16); gh->p = p; + gh->numskins = worknumskins; + gh->skinlist = skinlist; + ghosts = gh; gh->version = ghostversion; @@ -3442,6 +3677,7 @@ void G_FreeGhosts(void) while (ghosts) { demoghost *next = ghosts->next; + Z_Free(ghosts->skinlist); Z_Free(ghosts); ghosts = next; } @@ -3501,6 +3737,8 @@ void G_UpdateStaffGhostName(lumpnum_t l) p++; // numlaps G_SkipDemoExtraFiles(&p); + G_SkipDemoSkins(&p); + switch ((flags & DF_ATTACKMASK)>>DF_ATTACKSHIFT) { case ATTACKING_NONE: // 0 @@ -3768,6 +4006,9 @@ void G_StopDemo(void) democam.localaiming = 0; democam.keyboardlook = false; + Z_Free(demo.skinlist); + demo.skinlist = NULL; + if (gamestate == GS_INTERMISSION) Y_EndIntermission(); // cleanup diff --git a/src/g_demo.h b/src/g_demo.h index 2dc93eef2..a00756a74 100644 --- a/src/g_demo.h +++ b/src/g_demo.h @@ -28,6 +28,13 @@ extern consvar_t cv_recordmultiplayerdemos, cv_netdemosyncquality; extern tic_t demostarttime; +typedef struct democharlist_s { + UINT8 mapping; // No, this isn't about levels. It maps to loaded character ID. + UINT8 kartspeed; + UINT8 kartweight; + UINT32 flags; +} democharlist_t; + // Publicly-accessible demo vars struct demovars_s { char titlename[65]; @@ -54,6 +61,9 @@ struct demovars_s { boolean freecam; + UINT8 numskins; + democharlist_t *skinlist; + UINT8 currentskinid[MAXPLAYERS]; }; extern struct demovars_s demo; @@ -102,20 +112,18 @@ UINT8 G_CmpDemoTime(char *oldname, char *newname); typedef enum { GHC_NORMAL = 0, - GHC_SUPER, - GHC_FIREFLOWER, GHC_INVINCIBLE, - GHC_RETURNSKIN // not actually a colour + GHC_SUPER } ghostcolor_t; extern UINT8 demo_extradata[MAXPLAYERS]; extern UINT8 demo_writerng; -#define DXD_RESPAWN 0x01 // "respawn" command in console -#define DXD_SKIN 0x02 // skin changed -#define DXD_NAME 0x04 // name changed -#define DXD_COLOR 0x08 // color changed -#define DXD_PLAYSTATE 0x10 // state changed between playing, spectating, or not in-game +#define DXD_PLAYSTATE 0x01 // state changed between playing, spectating, or not in-game +#define DXD_RESPAWN 0x02 // "respawn" command in console +#define DXD_SKIN 0x04 // skin changed +#define DXD_NAME 0x08 // name changed +#define DXD_COLOR 0x10 // color changed #define DXD_FOLLOWER 0x20 // follower was changed #define DXD_WEAPONPREF 0x40 // netsynced playsim settings were changed @@ -123,6 +131,8 @@ extern UINT8 demo_writerng; #define DXD_PST_SPECTATING 0x02 #define DXD_PST_LEFT 0x03 +#define DXD_PST_ISBOT 0x80 // extra flag + // Record/playback tics void G_ReadDemoExtraData(void); void G_WriteDemoExtraData(void); @@ -155,6 +165,8 @@ typedef struct demoghost { UINT8 *buffer, *p, color; UINT8 fadein; UINT16 version; + UINT8 numskins; + democharlist_t *skinlist; mobj_t oldmo, *mo; struct demoghost *next; } demoghost; diff --git a/src/g_game.c b/src/g_game.c index db838ab91..f0f53ca43 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -2239,6 +2239,8 @@ void G_PlayerReborn(INT32 player, boolean betweenmaps) UINT16 skincolor; INT32 skin; UINT32 availabilities; + UINT8 fakeskin; + UINT8 lastfakeskin; tic_t jointime; @@ -2285,9 +2287,21 @@ void G_PlayerReborn(INT32 player, boolean betweenmaps) skincolor = players[player].skincolor; skin = players[player].skin; - // SRB2kart - kartspeed = players[player].kartspeed; - kartweight = players[player].kartweight; + if (betweenmaps) + { + fakeskin = MAXSKINS; + kartspeed = skins[players[player].skin].kartspeed; + kartweight = skins[players[player].skin].kartweight; + charflags = skins[players[player].skin].flags; + } + else + { + fakeskin = players[player].fakeskin; + kartspeed = players[player].kartspeed; + kartweight = players[player].kartweight; + charflags = players[player].charflags; + } + lastfakeskin = players[player].lastfakeskin; followerready = players[player].followerready; followercolor = players[player].followercolor; @@ -2295,8 +2309,6 @@ void G_PlayerReborn(INT32 player, boolean betweenmaps) availabilities = players[player].availabilities; - charflags = players[player].charflags; - followitem = players[player].followitem; bot = players[player].bot; @@ -2413,10 +2425,13 @@ void G_PlayerReborn(INT32 player, boolean betweenmaps) // save player config truth reborn p->skincolor = skincolor; p->skin = skin; + + p->fakeskin = fakeskin; p->kartspeed = kartspeed; p->kartweight = kartweight; - // p->charflags = charflags; + p->lastfakeskin = lastfakeskin; + p->availabilities = availabilities; p->followitem = followitem; @@ -2549,7 +2564,7 @@ static boolean G_CheckSpot(INT32 playernum, mapthing_t *mthing) if (!K_CheckPlayersRespawnColliding(playernum, x, y)) return false; - if (!P_CheckPosition(players[playernum].mo, x, y)) + if (!P_CheckPosition(players[playernum].mo, x, y, NULL)) return false; return true; diff --git a/src/hardware/hw_draw.c b/src/hardware/hw_draw.c index b4917751b..b5268986b 100644 --- a/src/hardware/hw_draw.c +++ b/src/hardware/hw_draw.c @@ -188,7 +188,10 @@ void HWR_DrawStretchyFixedPatch(patch_t *gpatch, fixed_t x, fixed_t y, fixed_t p offsetx = (float)(gpatch->leftoffset) * fscalew; // top offset - offsety = (float)(gpatch->topoffset) * fscaleh; + if (option & V_VFLIP) + offsety = (float)(gpatch->height - gpatch->topoffset) * fscaleh; + else + offsety = (float)(gpatch->topoffset) * fscaleh; cx -= offsetx; cy -= offsety; @@ -249,8 +252,16 @@ void HWR_DrawStretchyFixedPatch(patch_t *gpatch, fixed_t x, fixed_t y, fixed_t p v[2].s = v[1].s = hwrPatch->max_s; } - v[0].t = v[1].t = 0.0f; - v[2].t = v[3].t = hwrPatch->max_t; + if (option & V_VFLIP) + { + v[0].t = v[1].t = hwrPatch->max_t; + v[2].t = v[3].t = 0.0f; + } + else + { + v[0].t = v[1].t = 0.0f; + v[2].t = v[3].t = hwrPatch->max_t; + } flags = PF_NoDepthTest; diff --git a/src/hardware/hw_main.c b/src/hardware/hw_main.c index 74385e7f7..32f46bda3 100644 --- a/src/hardware/hw_main.c +++ b/src/hardware/hw_main.c @@ -5298,7 +5298,7 @@ static void HWR_ProjectSprite(mobj_t *thing) flip ^= (1<skin && ((skin_t *)thing->skin)->flags & SF_HIRES) + if (thing->skin && ((skin_t *)thing->skin)->highresscale != FRACUNIT) this_scale *= FIXED_TO_FLOAT(((skin_t *)thing->skin)->highresscale); spr_width = spritecachedinfo[lumpoff].width; diff --git a/src/info.c b/src/info.c index 44a4d25ae..3824731d1 100644 --- a/src/info.c +++ b/src/info.c @@ -543,6 +543,9 @@ char sprnames[NUMSPRITES + 1][5] = "KINF", // Invincibility flash "INVI", // Invincibility speedlines "ICAP", // Item capsules + "MGBX", // Heavy Magician transform box + "MGBT", // Heavy Magician transform box top + "MGBB", // Heavy Magician transform box bottom "WIPD", // Wipeout dust trail "DRIF", // Drift Sparks @@ -3891,6 +3894,10 @@ state_t states[NUMSTATES] = //{SPR_ICAP, FF_FLOORSPRITE|4, -1, {NULL}, 0, 0, S_NULL}, // S_ITEMCAPSULE_BOTTOM //{SPR_ICAP, FF_FLOORSPRITE|5, -1, {NULL}, 0, 0, S_NULL}, // S_ITEMCAPSULE_INSIDE + {SPR_MGBX, FF_PAPERSPRITE|0, -1, {NULL}, 0, 0, S_NULL}, // S_MAGICIANBOX + {SPR_MGBT, FF_FLOORSPRITE|0, -1, {NULL}, 0, 0, S_NULL}, // S_MAGICIANBOX_TOP + {SPR_MGBB, FF_FLOORSPRITE|0, -1, {NULL}, 0, 0, S_NULL}, // S_MAGICIANBOX_BOTTOM + {SPR_SGNS, FF_ADD|FF_FULLBRIGHT, 1, {NULL}, 0, 0, S_SIGNSPARK2}, // S_SIGNSPARK1 {SPR_SGNS, FF_ADD|FF_FULLBRIGHT|1, 1, {NULL}, 0, 0, S_SIGNSPARK3}, // S_SIGNSPARK2 {SPR_SGNS, FF_ADD|FF_FULLBRIGHT|2, 1, {NULL}, 0, 0, S_SIGNSPARK4}, // S_SIGNSPARK3 @@ -22398,6 +22405,33 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = S_NULL // raisestate }, + { // MT_MAGICIANBOX + -1, // doomednum + S_MAGICIANBOX, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + sfx_None, // seesound + 0, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + 0, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // deathstate + S_NULL, // xdeathstate + sfx_None, // deathsound + 0, // speed + 20*FRACUNIT, // radius + 20*FRACUNIT, // height + 0, // display offset + 100, // mass + 0, // damage + sfx_None, // activesound + MF_NOGRAVITY|MF_NOCLIP|MF_NOCLIPTHING|MF_NOCLIPHEIGHT, // flags + S_NULL // raisestate + }, + { // MT_SIGNSPARKLE -1, // doomednum S_SIGNSPARK1, // spawnstate diff --git a/src/info.h b/src/info.h index 78fc6e2db..7dff6e2de 100644 --- a/src/info.h +++ b/src/info.h @@ -1089,6 +1089,9 @@ typedef enum sprite SPR_KINF, // Invincibility flash SPR_INVI, // Invincibility speedlines SPR_ICAP, // Item capsules + SPR_MGBX, // Heavy Magician transform box + SPR_MGBT, // Heavy Magician transform box top + SPR_MGBB, // Heavy Magician transform box bottom SPR_WIPD, // Wipeout dust trail SPR_DRIF, // Drift Sparks @@ -4295,6 +4298,10 @@ typedef enum state //S_ITEMCAPSULE_BOTTOM, //S_ITEMCAPSULE_INSIDE, + S_MAGICIANBOX, + S_MAGICIANBOX_TOP, + S_MAGICIANBOX_BOTTOM, + // Signpost sparkles S_SIGNSPARK1, S_SIGNSPARK2, @@ -6333,6 +6340,7 @@ typedef enum mobj_type MT_FLOATINGITEM, MT_ITEMCAPSULE, MT_ITEMCAPSULE_PART, + MT_MAGICIANBOX, MT_SIGNSPARKLE, diff --git a/src/k_collide.c b/src/k_collide.c index d3b9bc60c..6a67e5a04 100644 --- a/src/k_collide.c +++ b/src/k_collide.c @@ -655,12 +655,12 @@ boolean K_BubbleShieldCollide(mobj_t *t1, mobj_t *t2) { // Counter desyncs /*mobj_t *oldthing = thing; - mobj_t *oldtmthing = tmthing; + mobj_t *oldtm.thing = tm.thing; - P_Thrust(tmthing, R_PointToAngle2(thing->x, thing->y, tmthing->x, tmthing->y), 4*thing->scale); + P_Thrust(tm.thing, R_PointToAngle2(thing->x, thing->y, tm.thing->x, tm.thing->y), 4*thing->scale); thing = oldthing; - P_SetTarget(&tmthing, oldtmthing);*/ + P_SetTarget(&tm.thing, oldtm.thing);*/ if (P_PlayerInPain(t2->player) || t2->player->flashing || t2->player->hyudorotimer diff --git a/src/k_hud.c b/src/k_hud.c index 4a5644442..d9908c4c6 100644 --- a/src/k_hud.c +++ b/src/k_hud.c @@ -1745,7 +1745,10 @@ static boolean K_drawKartPositionFaces(void) boolean completed[MAXPLAYERS]; INT32 rankplayer[MAXPLAYERS]; INT32 bumperx, emeraldx, numplayersingame = 0; + INT32 xoff, yoff, flipflag = 0; + UINT8 workingskin; UINT8 *colormap; + UINT32 skinflags; ranklines = 0; memset(completed, 0, sizeof (completed)); @@ -1830,15 +1833,36 @@ static boolean K_drawKartPositionFaces(void) bumperx = FACE_X+19; emeraldx = FACE_X+16; + skinflags = (demo.playback) + ? demo.skinlist[demo.currentskinid[rankplayer[i]]].flags + : skins[players[rankplayer[i]].skin].flags; + + // Flip SF_IRONMAN portraits, but only if they're transformed + if (skinflags & SF_IRONMAN + && !(players[rankplayer[i]].charflags & SF_IRONMAN) ) + { + flipflag = V_FLIP|V_VFLIP; // blonic flip + xoff = yoff = 16; + } else + { + flipflag = 0; + xoff = yoff = 0; + } + if (players[rankplayer[i]].mo->color) { - colormap = R_GetTranslationColormap(players[rankplayer[i]].skin, players[rankplayer[i]].mo->color, GTC_CACHE); + if ((skin_t*)players[rankplayer[i]].mo->skin) + workingskin = (skin_t*)players[rankplayer[i]].mo->skin - skins; + else + workingskin = players[rankplayer[i]].skin; + + colormap = R_GetTranslationColormap(workingskin, players[rankplayer[i]].mo->color, GTC_CACHE); if (players[rankplayer[i]].mo->colorized) colormap = R_GetTranslationColormap(TC_RAINBOW, players[rankplayer[i]].mo->color, GTC_CACHE); else - colormap = R_GetTranslationColormap(players[rankplayer[i]].skin, players[rankplayer[i]].mo->color, GTC_CACHE); + colormap = R_GetTranslationColormap(workingskin, players[rankplayer[i]].mo->color, GTC_CACHE); - V_DrawMappedPatch(FACE_X, Y, V_HUDTRANS|V_SLIDEIN|V_SNAPTOLEFT, faceprefix[players[rankplayer[i]].skin][FACE_RANK], colormap); + V_DrawMappedPatch(FACE_X + xoff, Y + yoff, V_HUDTRANS|V_SLIDEIN|V_SNAPTOLEFT|flipflag, faceprefix[workingskin][FACE_RANK], colormap); if (LUA_HudEnabled(hud_battlebumpers)) { diff --git a/src/k_kart.c b/src/k_kart.c index 40d1ff0a2..033f4e3ed 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -2717,6 +2717,47 @@ void K_SpawnBumpEffect(mobj_t *mo) S_StartSound(mo, sfx_s3k49); } +void K_SpawnMagicianParticles(mobj_t *mo, int spread) +{ + INT32 i; + mobj_t *target = mo->target; + + if (P_MobjWasRemoved(target)) + target = mo; + + for (i = 0; i < 16; i++) + { + fixed_t hmomentum = P_RandomRange(PR_DECORATION, spread * -1, spread) * mo->scale; + fixed_t vmomentum = P_RandomRange(PR_DECORATION, spread * -1, spread) * mo->scale; + UINT16 color = P_RandomKey(PR_DECORATION, numskincolors); + + fixed_t ang = FixedAngle(P_RandomRange(PR_DECORATION, 0, 359)*FRACUNIT); + SINT8 flip = 1; + + mobj_t *dust; + + if (i & 1) + ang -= ANGLE_90; + else + ang += ANGLE_90; + + dust = P_SpawnMobjFromMobj(mo, + FixedMul(mo->radius, FINECOSINE(ang >> ANGLETOFINESHIFT)), + FixedMul(mo->radius, FINESINE(ang >> ANGLETOFINESHIFT)), + target->height, (i%3 == 0) ? MT_SIGNSPARKLE : MT_SPINDASHDUST + ); + flip = P_MobjFlip(dust); + + dust->momx = target->momx + FixedMul(hmomentum, FINECOSINE(ang >> ANGLETOFINESHIFT)); + dust->momy = target->momy + FixedMul(hmomentum, FINESINE(ang >> ANGLETOFINESHIFT)); + dust->momz = vmomentum * flip; + dust->scale = dust->scale*4; + dust->frame |= FF_SUBTRACT|FF_TRANS90; + dust->color = color; + dust->colorized = true; + } +} + static SINT8 K_GlanceAtPlayers(player_t *glancePlayer) { const fixed_t maxdistance = FixedMul(1280 * mapobjectscale, K_GetKartGameSpeedScalar(gamespeed)); @@ -3445,6 +3486,8 @@ boolean K_WaterRun(mobj_t *mobj) case MT_PLAYER: { + fixed_t minspeed = 0; + if (mobj->player == NULL) { return false; @@ -3455,11 +3498,18 @@ boolean K_WaterRun(mobj_t *mobj) return K_IsHoldingDownTop(mobj->player) == false; } + minspeed = 2 * K_GetKartSpeed(mobj->player, false, false); // 200% + + if (mobj->player->speed < minspeed / 5) // 40% + { + return false; + } + if (mobj->player->invincibilitytimer || mobj->player->sneakertimer || mobj->player->tiregrease || mobj->player->flamedash - || mobj->player->speed > 2 * K_GetKartSpeed(mobj->player, false, false)) + || mobj->player->speed > minspeed) { return true; } @@ -10362,6 +10412,9 @@ boolean K_FastFallBounce(player_t *player) } } + if (player->mo->eflags & MFE_UNDERWATER) + bounce = (117 * bounce) / 200; + S_StartSound(player->mo, sfx_ffbonc); player->mo->momz = bounce * P_MobjFlip(player->mo); diff --git a/src/k_kart.h b/src/k_kart.h index a5d2b0185..db280afc0 100644 --- a/src/k_kart.h +++ b/src/k_kart.h @@ -110,6 +110,7 @@ void K_SpawnBoostTrail(player_t *player); void K_SpawnSparkleTrail(mobj_t *mo); void K_SpawnWipeoutTrail(mobj_t *mo); void K_SpawnDraftDust(mobj_t *mo); +void K_SpawnMagicianParticles(mobj_t *mo, int spread); void K_DriftDustHandling(mobj_t *spawner); void K_Squish(mobj_t *mo); mobj_t *K_ThrowKartItem(player_t *player, boolean missile, mobjtype_t mapthing, INT32 defaultDir, INT32 altthrow, angle_t angleOffset); diff --git a/src/k_menudraw.c b/src/k_menudraw.c index cfd52a459..8bfec4716 100644 --- a/src/k_menudraw.c +++ b/src/k_menudraw.c @@ -1250,7 +1250,7 @@ static boolean M_DrawCharacterSprite(INT16 x, INT16 y, INT16 skin, boolean charf addflags ^= V_FLIP; // This sprite is left/right flipped! } - if (skins[skin].flags & SF_HIRES) + if (skins[skin].highresscale != FRACUNIT) { V_DrawFixedPatch(x<x, actor->y); - P_SetTarget(&tmthing, ptmthing); + P_CheckPosition(actor, actor->x, actor->y, NULL); + P_RestoreTMStruct(ptm); return 1; } static int lib_pRingZMovement(lua_State *L) { mobj_t *actor = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ)); - mobj_t *ptmthing = tmthing; + tm_t ptm = tm; NOHUD INLEVEL if (!actor) return LUA_ErrInvalid(L, "mobj_t"); P_RingZMovement(actor); - P_CheckPosition(actor, actor->x, actor->y); - P_SetTarget(&tmthing, ptmthing); + P_CheckPosition(actor, actor->x, actor->y, NULL); + P_RestoreTMStruct(ptm); return 0; } static int lib_pSceneryZMovement(lua_State *L) { mobj_t *actor = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ)); - mobj_t *ptmthing = tmthing; + tm_t ptm = tm; NOHUD INLEVEL if (!actor) return LUA_ErrInvalid(L, "mobj_t"); lua_pushboolean(L, P_SceneryZMovement(actor)); - P_CheckPosition(actor, actor->x, actor->y); - P_SetTarget(&tmthing, ptmthing); + P_CheckPosition(actor, actor->x, actor->y, NULL); + P_RestoreTMStruct(ptm); return 1; } static int lib_pPlayerZMovement(lua_State *L) { mobj_t *actor = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ)); - mobj_t *ptmthing = tmthing; + tm_t ptm = tm; NOHUD INLEVEL if (!actor) return LUA_ErrInvalid(L, "mobj_t"); P_PlayerZMovement(actor); - P_CheckPosition(actor, actor->x, actor->y); - P_SetTarget(&tmthing, ptmthing); + P_CheckPosition(actor, actor->x, actor->y, NULL); + P_RestoreTMStruct(ptm); return 0; } @@ -1302,13 +1302,13 @@ static int lib_pGivePlayerLives(lua_State *L) static int lib_pMovePlayer(lua_State *L) { player_t *player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER)); - mobj_t *ptmthing = tmthing; + tm_t ptm = tm; NOHUD INLEVEL if (!player) return LUA_ErrInvalid(L, "player_t"); P_MovePlayer(player); - P_SetTarget(&tmthing, ptmthing); + P_RestoreTMStruct(ptm); return 0; } @@ -1380,7 +1380,7 @@ static int lib_pNukeEnemies(lua_State *L) static int lib_pCheckPosition(lua_State *L) { - mobj_t *ptmthing = tmthing; + tm_t ptm = tm; mobj_t *thing = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ)); fixed_t x = luaL_checkfixed(L, 2); fixed_t y = luaL_checkfixed(L, 3); @@ -1388,15 +1388,15 @@ static int lib_pCheckPosition(lua_State *L) INLEVEL if (!thing) return LUA_ErrInvalid(L, "mobj_t"); - lua_pushboolean(L, P_CheckPosition(thing, x, y)); - LUA_PushUserdata(L, tmthing, META_MOBJ); - P_SetTarget(&tmthing, ptmthing); + lua_pushboolean(L, P_CheckPosition(thing, x, y, NULL)); + LUA_PushUserdata(L, tm.thing, META_MOBJ); + P_RestoreTMStruct(ptm); return 2; } static int lib_pTryMove(lua_State *L) { - mobj_t *ptmthing = tmthing; + tm_t ptm = tm; mobj_t *thing = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ)); fixed_t x = luaL_checkfixed(L, 2); fixed_t y = luaL_checkfixed(L, 3); @@ -1405,15 +1405,15 @@ static int lib_pTryMove(lua_State *L) INLEVEL if (!thing) return LUA_ErrInvalid(L, "mobj_t"); - lua_pushboolean(L, P_TryMove(thing, x, y, allowdropoff)); - LUA_PushUserdata(L, tmthing, META_MOBJ); - P_SetTarget(&tmthing, ptmthing); + lua_pushboolean(L, P_TryMove(thing, x, y, allowdropoff, NULL)); + LUA_PushUserdata(L, tm.thing, META_MOBJ); + P_RestoreTMStruct(ptm); return 2; } static int lib_pMove(lua_State *L) { - mobj_t *ptmthing = tmthing; + tm_t ptm = tm; mobj_t *actor = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ)); fixed_t speed = luaL_checkfixed(L, 2); NOHUD @@ -1421,14 +1421,14 @@ static int lib_pMove(lua_State *L) if (!actor) return LUA_ErrInvalid(L, "mobj_t"); lua_pushboolean(L, P_Move(actor, speed)); - LUA_PushUserdata(L, tmthing, META_MOBJ); - P_SetTarget(&tmthing, ptmthing); + LUA_PushUserdata(L, tm.thing, META_MOBJ); + P_RestoreTMStruct(ptm); return 2; } static int lib_pTeleportMove(lua_State *L) { - mobj_t *ptmthing = tmthing; + tm_t ptm = tm; mobj_t *thing = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ)); fixed_t x = luaL_checkfixed(L, 2); fixed_t y = luaL_checkfixed(L, 3); @@ -1439,14 +1439,14 @@ static int lib_pTeleportMove(lua_State *L) return LUA_ErrInvalid(L, "mobj_t"); LUA_Deprecated(L, "P_TeleportMove", "P_SetOrigin\" or \"P_MoveOrigin"); lua_pushboolean(L, P_MoveOrigin(thing, x, y, z)); - LUA_PushUserdata(L, tmthing, META_MOBJ); - P_SetTarget(&tmthing, ptmthing); + LUA_PushUserdata(L, tm.thing, META_MOBJ); + P_RestoreTMStruct(ptm); return 2; } static int lib_pSetOrigin(lua_State *L) { - mobj_t *ptmthing = tmthing; + tm_t ptm = tm; mobj_t *thing = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ)); fixed_t x = luaL_checkfixed(L, 2); fixed_t y = luaL_checkfixed(L, 3); @@ -1456,14 +1456,14 @@ static int lib_pSetOrigin(lua_State *L) if (!thing) return LUA_ErrInvalid(L, "mobj_t"); lua_pushboolean(L, P_SetOrigin(thing, x, y, z)); - LUA_PushUserdata(L, tmthing, META_MOBJ); - P_SetTarget(&tmthing, ptmthing); + LUA_PushUserdata(L, tm.thing, META_MOBJ); + P_RestoreTMStruct(ptm); return 2; } static int lib_pMoveOrigin(lua_State *L) { - mobj_t *ptmthing = tmthing; + tm_t ptm = tm; mobj_t *thing = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ)); fixed_t x = luaL_checkfixed(L, 2); fixed_t y = luaL_checkfixed(L, 3); @@ -1473,8 +1473,8 @@ static int lib_pMoveOrigin(lua_State *L) if (!thing) return LUA_ErrInvalid(L, "mobj_t"); lua_pushboolean(L, P_MoveOrigin(thing, x, y, z)); - LUA_PushUserdata(L, tmthing, META_MOBJ); - P_SetTarget(&tmthing, ptmthing); + LUA_PushUserdata(L, tm.thing, META_MOBJ); + P_RestoreTMStruct(ptm); return 2; } @@ -1520,23 +1520,31 @@ static int lib_pSetRoll(lua_State *L) 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); + */ + LUA_UsageWarning(L, "FIXME: P_SlideMove needs updated to use result from P_TryMove"); + (void)L; return 0; } 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); + */ + LUA_UsageWarning(L, "FIXME: P_BounceMove needs updated to use result from P_TryMove"); + (void)L; return 0; } diff --git a/src/lua_maplib.c b/src/lua_maplib.c index f89059402..0557456b2 100644 --- a/src/lua_maplib.c +++ b/src/lua_maplib.c @@ -722,7 +722,7 @@ static int sector_set(lua_State *L) return luaL_error(L, "sector_t field " LUA_QS " cannot be set.", sector_opt[field]); case sector_floorheight: { // floorheight boolean flag; - mobj_t *ptmthing = tmthing; + tm_t ptm = tm; fixed_t lastpos = sector->floorheight; sector->floorheight = luaL_checkfixed(L, 3); flag = P_CheckSector(sector, true); @@ -731,12 +731,12 @@ static int sector_set(lua_State *L) sector->floorheight = lastpos; P_CheckSector(sector, true); } - P_SetTarget(&tmthing, ptmthing); + P_RestoreTMStruct(ptm); break; } case sector_ceilingheight: { // ceilingheight boolean flag; - mobj_t *ptmthing = tmthing; + tm_t ptm = tm; fixed_t lastpos = sector->ceilingheight; sector->ceilingheight = luaL_checkfixed(L, 3); flag = P_CheckSector(sector, true); @@ -745,7 +745,7 @@ static int sector_set(lua_State *L) sector->ceilingheight = lastpos; P_CheckSector(sector, true); } - P_SetTarget(&tmthing, ptmthing); + P_RestoreTMStruct(ptm); break; } case sector_floorpic: @@ -2127,7 +2127,7 @@ static int ffloor_set(lua_State *L) case ffloor_topheight: { // topheight boolean flag; fixed_t lastpos = *ffloor->topheight; - mobj_t *ptmthing = tmthing; + tm_t ptm = tm; sector_t *sector = §ors[ffloor->secnum]; sector->ceilingheight = luaL_checkfixed(L, 3); flag = P_CheckSector(sector, true); @@ -2136,7 +2136,7 @@ static int ffloor_set(lua_State *L) *ffloor->topheight = lastpos; P_CheckSector(sector, true); } - P_SetTarget(&tmthing, ptmthing); + P_RestoreTMStruct(ptm); break; } case ffloor_toppic: @@ -2148,7 +2148,7 @@ static int ffloor_set(lua_State *L) case ffloor_bottomheight: { // bottomheight boolean flag; fixed_t lastpos = *ffloor->bottomheight; - mobj_t *ptmthing = tmthing; + tm_t ptm = tm; sector_t *sector = §ors[ffloor->secnum]; sector->floorheight = luaL_checkfixed(L, 3); flag = P_CheckSector(sector, true); @@ -2157,7 +2157,7 @@ static int ffloor_set(lua_State *L) *ffloor->bottomheight = lastpos; P_CheckSector(sector, true); } - P_SetTarget(&tmthing, ptmthing); + P_RestoreTMStruct(ptm); break; } case ffloor_bottompic: diff --git a/src/lua_mobjlib.c b/src/lua_mobjlib.c index ecd87f49f..b87ad7234 100644 --- a/src/lua_mobjlib.c +++ b/src/lua_mobjlib.c @@ -515,14 +515,14 @@ static int mobj_set(lua_State *L) case mobj_z: { // z doesn't cross sector bounds so it's okay. - mobj_t *ptmthing = tmthing; + tm_t ptm = tm; mo->z = luaL_checkfixed(L, 3); - P_CheckPosition(mo, mo->x, mo->y); - mo->floorz = tmfloorz; - mo->ceilingz = tmceilingz; - mo->floorrover = tmfloorrover; - mo->ceilingrover = tmceilingrover; - P_SetTarget(&tmthing, ptmthing); + P_CheckPosition(mo, mo->x, mo->y, NULL); + mo->floorz = tm.floorz; + mo->ceilingz = tm.ceilingz; + mo->floorrover = tm.floorrover; + mo->ceilingrover = tm.ceilingrover; + P_RestoreTMStruct(ptm); break; } case mobj_snext: @@ -583,30 +583,30 @@ static int mobj_set(lua_State *L) return NOSET; case mobj_radius: { - mobj_t *ptmthing = tmthing; + tm_t ptm = tm; mo->radius = luaL_checkfixed(L, 3); if (mo->radius < 0) mo->radius = 0; - P_CheckPosition(mo, mo->x, mo->y); - mo->floorz = tmfloorz; - mo->ceilingz = tmceilingz; - mo->floorrover = tmfloorrover; - mo->ceilingrover = tmceilingrover; - P_SetTarget(&tmthing, ptmthing); + P_CheckPosition(mo, mo->x, mo->y, NULL); + mo->floorz = tm.floorz; + mo->ceilingz = tm.ceilingz; + mo->floorrover = tm.floorrover; + mo->ceilingrover = tm.ceilingrover; + P_RestoreTMStruct(ptm); break; } case mobj_height: { - mobj_t *ptmthing = tmthing; + tm_t ptm = tm; mo->height = luaL_checkfixed(L, 3); if (mo->height < 0) mo->height = 0; - P_CheckPosition(mo, mo->x, mo->y); - mo->floorz = tmfloorz; - mo->ceilingz = tmceilingz; - mo->floorrover = tmfloorrover; - mo->ceilingrover = tmceilingrover; - P_SetTarget(&tmthing, ptmthing); + P_CheckPosition(mo, mo->x, mo->y, NULL); + mo->floorz = tm.floorz; + mo->ceilingz = tm.ceilingz; + mo->floorrover = tm.floorrover; + mo->ceilingrover = tm.ceilingrover; + P_RestoreTMStruct(ptm); break; } case mobj_momx: diff --git a/src/lua_playerlib.c b/src/lua_playerlib.c index c5f5cc4d0..2a3b9e46a 100644 --- a/src/lua_playerlib.c +++ b/src/lua_playerlib.c @@ -410,6 +410,10 @@ static int player_get(lua_State *L) lua_pushinteger(L, plr->skin); else if (fastcmp(field,"availabilities")) lua_pushinteger(L, plr->availabilities); + else if (fastcmp(field,"fakeskin")) + lua_pushinteger(L, plr->fakeskin); + else if (fastcmp(field,"lastfakeskin")) + lua_pushinteger(L, plr->lastfakeskin); else if (fastcmp(field,"score")) lua_pushinteger(L, plr->score); // SRB2kart @@ -575,6 +579,10 @@ static int player_set(lua_State *L) return NOSET; else if (fastcmp(field,"availabilities")) return NOSET; + else if (fastcmp(field,"fakeskin")) + return NOSET; + else if (fastcmp(field,"lastfakeskin")) + return NOSET; else if (fastcmp(field,"score")) plr->score = luaL_checkinteger(L, 3); // SRB2kart diff --git a/src/m_random.h b/src/m_random.h index 5bb5d4435..ec1f643e1 100644 --- a/src/m_random.h +++ b/src/m_random.h @@ -46,6 +46,7 @@ typedef enum PR_PLAYERSTARTS, // Player starts PR_VOICES, // Player voice sounds + PR_RANDOMSKIN, // Random skin select from Heavy Magician(?) PR_RULESCRAMBLE, // Rule scrambing events diff --git a/src/objects/orbinaut.c b/src/objects/orbinaut.c index ee6e72ed5..b4daefb9b 100644 --- a/src/objects/orbinaut.c +++ b/src/objects/orbinaut.c @@ -358,9 +358,9 @@ void Obj_OrbinautJawzMoveHeld(player_t *player) cur->momy = FixedMul(FINESINE(cur->angle >> ANGLETOFINESHIFT), orbinaut_shield_dist(cur)); cur->flags &= ~MF_NOCLIPTHING; - if (!P_TryMove(cur, player->mo->x + cur->momx, player->mo->y + cur->momy, true)) + if (!P_TryMove(cur, player->mo->x + cur->momx, player->mo->y + cur->momy, true, NULL)) { - P_SlideMove(cur); + P_SlideMove(cur, NULL); } if (P_IsObjectOnGround(player->mo)) diff --git a/src/p_enemy.c b/src/p_enemy.c index 439e5c16e..3b8ebb9ce 100644 --- a/src/p_enemy.c +++ b/src/p_enemy.c @@ -541,12 +541,12 @@ boolean P_Move(mobj_t *actor, fixed_t speed) if (actor->type == MT_SKIM && !P_WaterInSector(actor, tryx, tryy)) // bail out if sector lacks water return false; - if (!P_TryMove(actor, tryx, tryy, false)) + if (!P_TryMove(actor, tryx, tryy, false, NULL)) { - if (actor->flags & MF_FLOAT && floatok) + if (actor->flags & MF_FLOAT && tm.floatok) { // must adjust height - if (actor->z < tmfloorz) + if (actor->z < tm.floorz) actor->z += FixedMul(FLOATSPEED, actor->scale); else actor->z -= FixedMul(FLOATSPEED, actor->scale); @@ -1074,7 +1074,7 @@ void A_FaceStabRev(mobj_t *actor) } else { - P_TryMove(actor, actor->x - P_ReturnThrustX(actor, actor->angle, 2<y - P_ReturnThrustY(actor, actor->angle, 2<x - P_ReturnThrustX(actor, actor->angle, 2<y - P_ReturnThrustY(actor, actor->angle, 2<x + P_ReturnThrustX(actor, dirang, actor->extravalue2<y + P_ReturnThrustY(actor, dirang, actor->extravalue2<extravalue2 <= 0 || !P_TryMove(actor, actor->x + P_ReturnThrustX(actor, actor->angle, actor->extravalue2<y + P_ReturnThrustY(actor, actor->angle, actor->extravalue2<extravalue2 = 0; P_SetMobjState(actor, locvar2); @@ -1821,7 +1821,7 @@ void A_CrushstaceanWalk(mobj_t *actor) if (!P_TryMove(actor, actor->x + P_ReturnThrustX(actor, ang, locvar1*actor->scale), actor->y + P_ReturnThrustY(actor, ang, locvar1*actor->scale), - false) + false, NULL) || (actor->reactiontime-- <= 0)) { actor->flags2 ^= MF2_AMBUSH; @@ -2000,7 +2000,7 @@ void A_CrushclawLaunch(mobj_t *actor) if (!P_TryMove(actor, actor->target->x + P_ReturnThrustX(actor, actor->target->angle, actor->extravalue2*actor->scale), actor->target->y + P_ReturnThrustY(actor, actor->target->angle, actor->extravalue2*actor->scale), - true) + true, NULL) && !locvar1) { actor->extravalue1 = 0; @@ -2946,9 +2946,9 @@ void A_Boss1Laser(mobj_t *actor) { fixed_t distx = P_ReturnThrustX(point, point->angle, point->radius); fixed_t disty = P_ReturnThrustY(point, point->angle, point->radius); - if (P_TryMove(point, point->x + distx, point->y + disty, false) // prevents the sprite from clipping into the wall or dangling off ledges - && P_TryMove(point, point->x - 2*distx, point->y - 2*disty, false) - && P_TryMove(point, point->x + distx, point->y + disty, false)) + if (P_TryMove(point, point->x + distx, point->y + disty, false, NULL) // prevents the sprite from clipping into the wall or dangling off ledges + && P_TryMove(point, point->x - 2*distx, point->y - 2*disty, false, NULL) + && P_TryMove(point, point->x + distx, point->y + disty, false, NULL)) { if (point->info->seesound) S_StartSound(point, point->info->seesound); @@ -3012,7 +3012,7 @@ void A_FocusTarget(mobj_t *actor) { actor->momx = 0, actor->momy = 0, actor->momz = 0; actor->z = actor->target->z + (actor->target->height>>1); - P_TryMove(actor, actor->target->x, actor->target->y, true); + P_TryMove(actor, actor->target->x, actor->target->y, true, NULL); } break; default: @@ -3168,7 +3168,7 @@ void A_SkullAttack(mobj_t *actor) if (P_CheckMove(actor,\ P_ReturnThrustX(actor, testang, dist + 2*actor->radius),\ P_ReturnThrustY(actor, testang, dist + 2*actor->radius),\ - true)) break; + true, NULL)) break; if (P_RandomChance(PR_UNDEFINED, FRACUNIT/2)) // port priority 2? { @@ -4483,13 +4483,13 @@ void A_MinusDigging(mobj_t *actor) par = P_SpawnMobj(actor->x, actor->y, mz, MT_MINUSDIRT); if (actor->eflags & MFE_VERTICALFLIP) par->eflags |= MFE_VERTICALFLIP; - P_TryMove(par, x, y, false); + P_TryMove(par, x, y, false, NULL); // If close enough, prepare to attack if (P_AproxDistance(actor->x - actor->target->x, actor->y - actor->target->y) < actor->radius*2) { P_SetMobjState(actor, actor->info->meleestate); - P_TryMove(actor, actor->target->x, actor->target->y, false); + P_TryMove(actor, actor->target->x, actor->target->y, false, NULL); S_StartSound(actor, actor->info->attacksound); // Spawn growing dirt pile. @@ -4532,7 +4532,7 @@ void A_MinusDigging(mobj_t *actor) } else { - if (P_TryMove(actor->tracer, actor->x, actor->y, false)) + if (P_TryMove(actor->tracer, actor->x, actor->y, false, NULL)) actor->tracer->z = mz; else P_SetTarget(&actor->tracer, NULL); @@ -5702,7 +5702,7 @@ void A_MixUp(mobj_t *actor) players[i].mo->floorz = P_GetFloorZ(players[i].mo, players[i].mo->subsector->sector, players[i].mo->x, players[i].mo->y, NULL); players[i].mo->ceilingz = P_GetCeilingZ(players[i].mo, players[i].mo->subsector->sector, players[i].mo->x, players[i].mo->y, NULL); - P_CheckPosition(players[i].mo, players[i].mo->x, players[i].mo->y); + P_CheckPosition(players[i].mo, players[i].mo->x, players[i].mo->y, NULL); } } } @@ -6470,7 +6470,7 @@ void A_GuardChase(mobj_t *actor) && !P_TryMove(actor, actor->x + P_ReturnThrustX(actor, actor->angle, speed), actor->y + P_ReturnThrustY(actor, actor->angle, speed), - false) + false, NULL) && speed > 0) // can't be the same check as previous so that P_TryMove gets to happen. { INT32 direction = actor->spawnpoint ? actor->spawnpoint->args[0] : TMGD_BACK; @@ -9273,7 +9273,7 @@ void A_SpikeRetract(mobj_t *actor) actor->flags &= ~MF_NOCLIPTHING; } if (actor->flags & MF_SOLID) - P_CheckPosition(actor, actor->x, actor->y); + P_CheckPosition(actor, actor->x, actor->y, NULL); } // Function: A_InfoState @@ -10421,13 +10421,13 @@ void A_FlickyCenter(mobj_t *actor) { actor->extravalue2 = 1; P_SetOrigin(actor, actor->target->x, actor->target->y, actor->target->z); - tmthing = NULL; + P_SetTarget(&tm.thing, NULL); } else if(actor->extravalue2) { actor->extravalue2 = 0; P_SetOrigin(actor, originx, originy, originz); - tmthing = NULL; + P_SetTarget(&tm.thing, NULL); } } } @@ -11511,7 +11511,7 @@ void A_DoNPCSkid(mobj_t *actor) locvar2 = FRACUNIT/2; if ((FixedHypot(actor->momx, actor->momy) < locvar2) - || !P_TryMove(actor, actor->x + actor->momx, actor->y + actor->momy, false)) + || !P_TryMove(actor, actor->x + actor->momx, actor->y + actor->momy, false, NULL)) { actor->momx = actor->momy = 0; P_SetMobjState(actor, locvar1); @@ -12286,7 +12286,7 @@ static void P_SnapperLegPlace(mobj_t *mo) INT32 necklen = (32*(mo->info->reactiontime - mo->reactiontime))/mo->info->reactiontime; // Not in FU seg->z = mo->z + ((mo->eflags & MFE_VERTICALFLIP) ? (((mo->height<<1)/3) - seg->height) : mo->height/3); - P_TryMove(seg, mo->x + FixedMul(c, rad) + necklen*c, mo->y + FixedMul(s, rad) + necklen*s, true); + P_TryMove(seg, mo->x + FixedMul(c, rad) + necklen*c, mo->y + FixedMul(s, rad) + necklen*s, true, NULL); seg->angle = a; // Move as many legs as available. @@ -12307,7 +12307,7 @@ static void P_SnapperLegPlace(mobj_t *mo) x = c*o2 + s*o1; y = s*o2 - c*o1; seg->z = mo->z + (((mo->eflags & MFE_VERTICALFLIP) ? (mo->height - seg->height) : 0)); - P_TryMove(seg, mo->x + x, mo->y + y, true); + P_TryMove(seg, mo->x + x, mo->y + y, true, NULL); P_SetMobjState(seg, seg->info->raisestate); } else @@ -12442,7 +12442,7 @@ void A_SnapperThinker(mobj_t *actor) c = FINECOSINE(fa); s = FINESINE(fa); - P_TryMove(actor, actor->x + c*speed, actor->y + s*speed, false); + P_TryMove(actor, actor->x + c*speed, actor->y + s*speed, false, NULL); // The snapper spawns dust if going fast! if (actor->reactiontime < 4) diff --git a/src/p_local.h b/src/p_local.h index f5d613e97..1042f1193 100644 --- a/src/p_local.h +++ b/src/p_local.h @@ -381,25 +381,48 @@ void P_InternalFlickyHop(mobj_t *actor, fixed_t momz, fixed_t momh, angle_t angl // P_MAP // -// If "floatok" true, move would be ok -// if within "tmfloorz - tmceilingz". -extern boolean floatok; -extern fixed_t tmfloorz; -extern fixed_t tmceilingz; -extern ffloor_t *tmfloorrover, *tmceilingrover; -extern mobj_t *tmfloorthing, *tmhitthing, *tmthing; +typedef struct tm_s +{ + mobj_t *thing; + fixed_t x, y; + fixed_t bbox[4]; + INT32 flags; + + precipmobj_t *precipthing; + fixed_t precipbbox[4]; + + // If "floatok" true, move would be ok + // if within "tm.floorz - tm.ceilingz". + boolean floatok; + + fixed_t floorz, ceilingz; + fixed_t dropoffz, drpoffceilz; // drop-off floor/ceiling heights + mobj_t *floorthing; // the thing corresponding to tm.floorz or NULL if tm.floorz is from a sector + mobj_t *hitthing; // the solid thing you bumped into (for collisions) + ffloor_t *floorrover, *ceilingrover; + pslope_t *floorslope, *ceilingslope; + INT32 floorpic, ceilingpic; + fixed_t floorstep, ceilingstep; + + // keep track of the line that lowers the ceiling, + // so missiles don't explode against sky hack walls + line_t *ceilingline; + + // set by PIT_CheckLine() for any line that stopped the PIT_CheckLine() + // that is, for any line which is 'solid' + line_t *blockingline; +} tm_t; + +extern tm_t tm; + +void P_RestoreTMStruct(tm_t tmrestore); + extern camera_t *mapcampointer; -extern fixed_t tmx; -extern fixed_t tmy; -extern pslope_t *tmfloorslope, *tmceilingslope; -extern INT32 tmfloorpic, tmceilingpic; /* cphipps 2004/08/30 */ extern void P_MapStart(void); extern void P_MapEnd(void); -extern line_t *ceilingline; -extern line_t *blockingline; extern msecnode_t *sector_list; extern mprecipsecnode_t *precipsector_list; @@ -408,20 +431,28 @@ void P_UnsetThingPosition(mobj_t *thing); void P_SetThingPosition(mobj_t *thing); void P_SetUnderlayPosition(mobj_t *thing); +typedef struct TryMoveResult_s +{ + boolean success; + line_t *line; + mobj_t *mo; +} TryMoveResult_t; + +boolean P_CheckPosition(mobj_t *thing, fixed_t x, fixed_t y, TryMoveResult_t *result); +boolean P_CheckMove(mobj_t *thing, fixed_t x, fixed_t y, boolean allowdropoff, TryMoveResult_t *result); +boolean P_TryMove(mobj_t *thing, fixed_t x, fixed_t y, boolean allowdropoff, TryMoveResult_t *result); +boolean P_SceneryTryMove(mobj_t *thing, fixed_t x, fixed_t y, TryMoveResult_t *result); + boolean P_IsLineBlocking(const line_t *ld, const mobj_t *thing); boolean P_IsLineTripWire(const line_t *ld); -boolean P_CheckPosition(mobj_t *thing, fixed_t x, fixed_t y); boolean P_CheckCameraPosition(fixed_t x, fixed_t y, camera_t *thiscam); -boolean P_CheckMove(mobj_t *thing, fixed_t x, fixed_t y, boolean allowdropoff); fixed_t P_BaseStepUp(void); fixed_t P_GetThingStepUp(mobj_t *thing, fixed_t destX, fixed_t destY); -boolean P_TryMove(mobj_t *thing, fixed_t x, fixed_t y, boolean allowdropoff); boolean P_Move(mobj_t *actor, fixed_t speed); boolean P_SetOrigin(mobj_t *thing, fixed_t x, fixed_t y, fixed_t z); boolean P_MoveOrigin(mobj_t *thing, fixed_t x, fixed_t y, fixed_t z); -void P_SlideMove(mobj_t *mo); -void P_BouncePlayerMove(mobj_t *mo); -void P_BounceMove(mobj_t *mo); +void P_SlideMove(mobj_t *mo, TryMoveResult_t *result); +void P_BounceMove(mobj_t *mo, TryMoveResult_t *result); boolean P_CheckSight(mobj_t *t1, mobj_t *t2); boolean P_TraceBlockingLines(mobj_t *t1, mobj_t *t2); boolean P_TraceBotTraversal(mobj_t *t1, mobj_t *t2); diff --git a/src/p_map.c b/src/p_map.c index 677954b43..97ea69da7 100644 --- a/src/p_map.c +++ b/src/p_map.c @@ -44,36 +44,46 @@ #include "m_perfstats.h" // ps_checkposition_calls -fixed_t tmbbox[4]; -mobj_t *tmthing; -static INT32 tmflags; -fixed_t tmx; -fixed_t tmy; +tm_t tm = {0}; -static precipmobj_t *tmprecipthing; -static fixed_t preciptmbbox[4]; +void P_RestoreTMStruct(tm_t tmrestore) +{ + // Reference count management + if (tm.thing != tmrestore.thing) + { + P_SetTarget(&tm.thing, NULL); + } -// If "floatok" true, move would be ok -// if within "tmfloorz - tmceilingz". -boolean floatok; + if (tm.floorthing != tmrestore.floorthing) + { + P_SetTarget(&tm.floorthing, NULL); + } -fixed_t tmfloorz, tmceilingz; -static fixed_t tmdropoffz, tmdrpoffceilz; // drop-off floor/ceiling heights -mobj_t *tmfloorthing; // the thing corresponding to tmfloorz or NULL if tmfloorz is from a sector -mobj_t *tmhitthing; // the solid thing you bumped into (for collisions) -ffloor_t *tmfloorrover, *tmceilingrover; -pslope_t *tmfloorslope, *tmceilingslope; -INT32 tmfloorpic, tmceilingpic; -static fixed_t tmfloorstep; -static fixed_t tmceilingstep; + if (tm.hitthing != tmrestore.hitthing) + { + P_SetTarget(&tm.hitthing, NULL); + } -// keep track of the line that lowers the ceiling, -// so missiles don't explode against sky hack walls -line_t *ceilingline; + // Restore state + tm = tmrestore; + + // Validation + if (tm.thing && P_MobjWasRemoved(tm.thing) == true) + { + P_SetTarget(&tm.thing, NULL); + } + + if (tm.floorthing && P_MobjWasRemoved(tm.floorthing) == true) + { + P_SetTarget(&tm.floorthing, NULL); + } + + if (tm.hitthing && P_MobjWasRemoved(tm.hitthing) == true) + { + P_SetTarget(&tm.hitthing, NULL); + } +} -// set by PIT_CheckLine() for any line that stopped the PIT_CheckLine() -// that is, for any line which is 'solid' -line_t *blockingline; // Mostly re-ported from DOOM Legacy // Keep track of special lines as they are hit, process them when the move is valid @@ -121,15 +131,15 @@ static boolean P_TeleportMove(mobj_t *thing, fixed_t x, fixed_t y, fixed_t z) P_SetThingPosition(thing); - P_CheckPosition(thing, thing->x, thing->y); + P_CheckPosition(thing, thing->x, thing->y, NULL); if (P_MobjWasRemoved(thing)) return true; - thing->floorz = tmfloorz; - thing->ceilingz = tmceilingz; - thing->floorrover = tmfloorrover; - thing->ceilingrover = tmceilingrover; + thing->floorz = tm.floorz; + thing->ceilingz = tm.ceilingz; + thing->floorrover = tm.floorrover; + thing->ceilingrover = tm.ceilingrover; return true; } @@ -292,7 +302,7 @@ boolean P_DoSpring(mobj_t *spring, mobj_t *object) if (horizspeed && vertispeed) // Mimic SA { object->momx = object->momy = 0; - P_TryMove(object, spring->x, spring->y, true); + P_TryMove(object, spring->x, spring->y, true, NULL); } #endif @@ -342,7 +352,7 @@ boolean P_DoSpring(mobj_t *spring, mobj_t *object) else if (offx < -(spring->radius + object->radius + 1)) offx = -(spring->radius + object->radius + 1); - P_TryMove(object, spring->x + offx, spring->y + offy, true); + P_TryMove(object, spring->x + offx, spring->y + offy, true, NULL); } if (vertispeed) @@ -529,32 +539,32 @@ static BlockItReturn_t PIT_CheckThing(mobj_t *thing) { fixed_t blockdist; - if (tmthing == NULL || P_MobjWasRemoved(tmthing) == true) - return BMIT_STOP; // func just popped our tmthing, cannot continue. + if (tm.thing == NULL || P_MobjWasRemoved(tm.thing) == true) + return BMIT_STOP; // func just popped our tm.thing, cannot continue. // Ignore... things. if (thing == NULL || P_MobjWasRemoved(thing) == true) return BMIT_CONTINUE; // don't clip against self - if (thing == tmthing) + if (thing == tm.thing) return BMIT_CONTINUE; // Ignore spectators - if ((tmthing->player && tmthing->player->spectator) + if ((tm.thing->player && tm.thing->player->spectator) || (thing->player && thing->player->spectator)) return BMIT_CONTINUE; // Ignore the collision if BOTH things are in hitlag. - if (thing->hitlag > 0 && tmthing->hitlag > 0) + if (thing->hitlag > 0 && tm.thing->hitlag > 0) return BMIT_CONTINUE; if ((thing->flags & MF_NOCLIPTHING) || !(thing->flags & (MF_SOLID|MF_SPECIAL|MF_PAIN|MF_SHOOTABLE|MF_SPRING))) return BMIT_CONTINUE; - blockdist = thing->radius + tmthing->radius; + blockdist = thing->radius + tm.thing->radius; - if (abs(thing->x - tmx) >= blockdist || abs(thing->y - tmy) >= blockdist) + if (abs(thing->x - tm.x) >= blockdist || abs(thing->y - tm.y) >= blockdist) return BMIT_CONTINUE; // didn't hit it if (thing->flags & MF_PAPERCOLLISION) // CAUTION! Very easy to get stuck inside MF_SOLID objects. Giving the player MF_PAPERCOLLISION is a bad idea unless you know what you're doing. @@ -576,47 +586,47 @@ static BlockItReturn_t PIT_CheckThing(mobj_t *thing) junk.dx = 2*cosradius; // v2.x - v1.x; junk.dy = 2*sinradius; // v2.y - v1.y; - if (tmthing->flags & MF_PAPERCOLLISION) // more strenuous checking to prevent clipping issues + if (tm.thing->flags & MF_PAPERCOLLISION) // more strenuous checking to prevent clipping issues { INT32 check1, check2, check3, check4; - fixed_t tmcosradius = FixedMul(tmthing->radius, FINECOSINE(tmthing->angle>>ANGLETOFINESHIFT)); - fixed_t tmsinradius = FixedMul(tmthing->radius, FINESINE(tmthing->angle>>ANGLETOFINESHIFT)); - if (abs(thing->x - tmx) >= (abs(tmcosradius) + abs(cosradius)) || abs(thing->y - tmy) >= (abs(tmsinradius) + abs(sinradius))) + fixed_t tmcosradius = FixedMul(tm.thing->radius, FINECOSINE(tm.thing->angle>>ANGLETOFINESHIFT)); + fixed_t tmsinradius = FixedMul(tm.thing->radius, FINESINE(tm.thing->angle>>ANGLETOFINESHIFT)); + if (abs(thing->x - tm.x) >= (abs(tmcosradius) + abs(cosradius)) || abs(thing->y - tm.y) >= (abs(tmsinradius) + abs(sinradius))) return BMIT_CONTINUE; // didn't hit it - check1 = P_PointOnLineSide(tmx - tmcosradius, tmy - tmsinradius, &junk); - check2 = P_PointOnLineSide(tmx + tmcosradius, tmy + tmsinradius, &junk); - check3 = P_PointOnLineSide(tmx + tmthing->momx - tmcosradius, tmy + tmthing->momy - tmsinradius, &junk); - check4 = P_PointOnLineSide(tmx + tmthing->momx + tmcosradius, tmy + tmthing->momy + tmsinradius, &junk); + check1 = P_PointOnLineSide(tm.x - tmcosradius, tm.y - tmsinradius, &junk); + check2 = P_PointOnLineSide(tm.x + tmcosradius, tm.y + tmsinradius, &junk); + check3 = P_PointOnLineSide(tm.x + tm.thing->momx - tmcosradius, tm.y + tm.thing->momy - tmsinradius, &junk); + check4 = P_PointOnLineSide(tm.x + tm.thing->momx + tmcosradius, tm.y + tm.thing->momy + tmsinradius, &junk); if ((check1 == check2) && (check2 == check3) && (check3 == check4)) return BMIT_CONTINUE; // the line doesn't cross between collider's start or end } else { - if (abs(thing->x - tmx) >= (tmthing->radius + abs(cosradius)) || abs(thing->y - tmy) >= (tmthing->radius + abs(sinradius))) + if (abs(thing->x - tm.x) >= (tm.thing->radius + abs(cosradius)) || abs(thing->y - tm.y) >= (tm.thing->radius + abs(sinradius))) return BMIT_CONTINUE; // didn't hit it - if ((P_PointOnLineSide(tmx - tmthing->radius, tmy - tmthing->radius, &junk) - == P_PointOnLineSide(tmx + tmthing->radius, tmy + tmthing->radius, &junk)) - && (P_PointOnLineSide(tmx + tmthing->radius, tmy - tmthing->radius, &junk) - == P_PointOnLineSide(tmx - tmthing->radius, tmy + tmthing->radius, &junk))) + if ((P_PointOnLineSide(tm.x - tm.thing->radius, tm.y - tm.thing->radius, &junk) + == P_PointOnLineSide(tm.x + tm.thing->radius, tm.y + tm.thing->radius, &junk)) + && (P_PointOnLineSide(tm.x + tm.thing->radius, tm.y - tm.thing->radius, &junk) + == P_PointOnLineSide(tm.x - tm.thing->radius, tm.y + tm.thing->radius, &junk))) return BMIT_CONTINUE; // the line doesn't cross between either pair of opposite corners } } - else if (tmthing->flags & MF_PAPERCOLLISION) + else if (tm.thing->flags & MF_PAPERCOLLISION) { fixed_t tmcosradius, tmsinradius; vertex_t v1, v2; // fake vertexes line_t junk; // fake linedef - tmcosradius = FixedMul(tmthing->radius, FINECOSINE(tmthing->angle>>ANGLETOFINESHIFT)); - tmsinradius = FixedMul(tmthing->radius, FINESINE(tmthing->angle>>ANGLETOFINESHIFT)); + tmcosradius = FixedMul(tm.thing->radius, FINECOSINE(tm.thing->angle>>ANGLETOFINESHIFT)); + tmsinradius = FixedMul(tm.thing->radius, FINESINE(tm.thing->angle>>ANGLETOFINESHIFT)); - if (abs(thing->x - tmx) >= (thing->radius + abs(tmcosradius)) || abs(thing->y - tmy) >= (thing->radius + abs(tmsinradius))) + if (abs(thing->x - tm.x) >= (thing->radius + abs(tmcosradius)) || abs(thing->y - tm.y) >= (thing->radius + abs(tmsinradius))) return BMIT_CONTINUE; // didn't hit it - v1.x = tmx - tmcosradius; - v1.y = tmy - tmsinradius; - v2.x = tmx + tmcosradius; - v2.y = tmy + tmsinradius; + v1.x = tm.x - tmcosradius; + v1.y = tm.y - tmsinradius; + v2.x = tm.x + tmcosradius; + v2.y = tm.y + tmsinradius; junk.v1 = &v1; junk.v2 = &v2; @@ -632,16 +642,16 @@ static BlockItReturn_t PIT_CheckThing(mobj_t *thing) } { - UINT8 shouldCollide = LUA_Hook2Mobj(thing, tmthing, MOBJ_HOOK(MobjCollide)); // checks hook for thing's type - if (P_MobjWasRemoved(tmthing) || P_MobjWasRemoved(thing)) + UINT8 shouldCollide = LUA_Hook2Mobj(thing, tm.thing, MOBJ_HOOK(MobjCollide)); // checks hook for thing's type + if (P_MobjWasRemoved(tm.thing) || P_MobjWasRemoved(thing)) return BMIT_CONTINUE; // one of them was removed??? if (shouldCollide == 1) return BMIT_ABORT; // force collide else if (shouldCollide == 2) return BMIT_CONTINUE; // force no collide - shouldCollide = LUA_Hook2Mobj(tmthing, thing, MOBJ_HOOK(MobjMoveCollide)); // checks hook for tmthing's type - if (P_MobjWasRemoved(tmthing) || P_MobjWasRemoved(thing)) + shouldCollide = LUA_Hook2Mobj(tm.thing, thing, MOBJ_HOOK(MobjMoveCollide)); // checks hook for tm.thing's type + if (P_MobjWasRemoved(tm.thing) || P_MobjWasRemoved(thing)) return BMIT_CONTINUE; // one of them was removed??? if (shouldCollide == 1) return BMIT_ABORT; // force collide @@ -650,66 +660,66 @@ static BlockItReturn_t PIT_CheckThing(mobj_t *thing) } // When solid spikes move, assume they just popped up and teleport things on top of them to hurt. - if (tmthing->type == MT_SPIKE && tmthing->flags & MF_SOLID) + if (tm.thing->type == MT_SPIKE && tm.thing->flags & MF_SOLID) { - if (thing->z > tmthing->z + tmthing->height) + if (thing->z > tm.thing->z + tm.thing->height) return BMIT_CONTINUE; // overhead - if (thing->z + thing->height < tmthing->z) + if (thing->z + thing->height < tm.thing->z) return BMIT_CONTINUE; // underneath - if (tmthing->eflags & MFE_VERTICALFLIP) - P_SetOrigin(thing, thing->x, thing->y, tmthing->z - thing->height - FixedMul(FRACUNIT, tmthing->scale)); + if (tm.thing->eflags & MFE_VERTICALFLIP) + P_SetOrigin(thing, thing->x, thing->y, tm.thing->z - thing->height - FixedMul(FRACUNIT, tm.thing->scale)); else - P_SetOrigin(thing, thing->x, thing->y, tmthing->z + tmthing->height + FixedMul(FRACUNIT, tmthing->scale)); + P_SetOrigin(thing, thing->x, thing->y, tm.thing->z + tm.thing->height + FixedMul(FRACUNIT, tm.thing->scale)); if (thing->flags & MF_SHOOTABLE) - P_DamageMobj(thing, tmthing, tmthing, 1, 0); + P_DamageMobj(thing, tm.thing, tm.thing, 1, 0); return BMIT_CONTINUE; } if (thing->flags & MF_PAIN) { // Player touches painful thing sitting on the floor // see if it went over / under - if (thing->z > tmthing->z + tmthing->height) + if (thing->z > tm.thing->z + tm.thing->height) return BMIT_CONTINUE; // overhead - if (thing->z + thing->height < tmthing->z) + if (thing->z + thing->height < tm.thing->z) return BMIT_CONTINUE; // underneath - if (tmthing->flags & MF_SHOOTABLE && thing->health > 0) + if (tm.thing->flags & MF_SHOOTABLE && thing->health > 0) { UINT32 damagetype = (thing->info->mass & 0xFF); - if (P_DamageMobj(tmthing, thing, thing, 1, damagetype) && (damagetype = (thing->info->mass>>8))) + if (P_DamageMobj(tm.thing, thing, thing, 1, damagetype) && (damagetype = (thing->info->mass>>8))) S_StartSound(thing, damagetype); } return BMIT_CONTINUE; } - else if (tmthing->flags & MF_PAIN && thing->player) + else if (tm.thing->flags & MF_PAIN && thing->player) { // Painful thing splats player in the face // see if it went over / under - if (tmthing->z > thing->z + thing->height) + if (tm.thing->z > thing->z + thing->height) return BMIT_CONTINUE; // overhead - if (tmthing->z + tmthing->height < thing->z) + if (tm.thing->z + tm.thing->height < thing->z) return BMIT_CONTINUE; // underneath - if (thing->flags & MF_SHOOTABLE && tmthing->health > 0) + if (thing->flags & MF_SHOOTABLE && tm.thing->health > 0) { - UINT32 damagetype = (tmthing->info->mass & 0xFF); + UINT32 damagetype = (tm.thing->info->mass & 0xFF); - if (P_DamageMobj(thing, tmthing, tmthing, 1, damagetype) && (damagetype = (tmthing->info->mass>>8))) - S_StartSound(tmthing, damagetype); + if (P_DamageMobj(thing, tm.thing, tm.thing, 1, damagetype) && (damagetype = (tm.thing->info->mass>>8))) + S_StartSound(tm.thing, damagetype); } return BMIT_CONTINUE; } // check for skulls slamming into things - if (tmthing->flags2 & MF2_SKULLFLY) + if (tm.thing->flags2 & MF2_SKULLFLY) { // see if it went over / under - if (tmthing->z > thing->z + thing->height) + if (tm.thing->z > thing->z + thing->height) return BMIT_CONTINUE; // overhead - if (tmthing->z + tmthing->height < thing->z) + if (tm.thing->z + tm.thing->height < thing->z) return BMIT_CONTINUE; // underneath - tmthing->flags2 &= ~MF2_SKULLFLY; - tmthing->momx = tmthing->momy = tmthing->momz = 0; + tm.thing->flags2 &= ~MF2_SKULLFLY; + tm.thing->momx = tm.thing->momy = tm.thing->momz = 0; return BMIT_ABORT; // stop moving } @@ -717,7 +727,7 @@ static BlockItReturn_t PIT_CheckThing(mobj_t *thing) if (thing->type == MT_SHRINK_GUN || thing->type == MT_SHRINK_PARTICLE) { - if (tmthing->type != MT_PLAYER) + if (tm.thing->type != MT_PLAYER) { return BMIT_CONTINUE; } @@ -727,334 +737,334 @@ static BlockItReturn_t PIT_CheckThing(mobj_t *thing) // Use special collision for the laser gun. // The laser sprite itself is just a visual, // the gun itself does the colliding for us. - if (tmthing->z > thing->z) + if (tm.thing->z > thing->z) { return BMIT_CONTINUE; // overhead } - if (tmthing->z + tmthing->height < thing->floorz) + if (tm.thing->z + tm.thing->height < thing->floorz) { return BMIT_CONTINUE; // underneath } } else { - if (tmthing->z > thing->z + thing->height) + if (tm.thing->z > thing->z + thing->height) { return BMIT_CONTINUE; // overhead } - if (tmthing->z + tmthing->height < thing->z) + if (tm.thing->z + tm.thing->height < thing->z) { return BMIT_CONTINUE; // underneath } } - return Obj_ShrinkLaserCollide(thing, tmthing) ? BMIT_CONTINUE : BMIT_ABORT; + return Obj_ShrinkLaserCollide(thing, tm.thing) ? BMIT_CONTINUE : BMIT_ABORT; } - else if (tmthing->type == MT_SHRINK_GUN || tmthing->type == MT_SHRINK_PARTICLE) + else if (tm.thing->type == MT_SHRINK_GUN || tm.thing->type == MT_SHRINK_PARTICLE) { if (thing->type != MT_PLAYER) { return BMIT_CONTINUE; } - if (tmthing->type == MT_SHRINK_GUN) + if (tm.thing->type == MT_SHRINK_GUN) { // Use special collision for the laser gun. // The laser sprite itself is just a visual, // the gun itself does the colliding for us. - if (thing->z > tmthing->z) + if (thing->z > tm.thing->z) { return BMIT_CONTINUE; // overhead } - if (thing->z + thing->height < tmthing->floorz) + if (thing->z + thing->height < tm.thing->floorz) { return BMIT_CONTINUE; // underneath } } else { - if (tmthing->z > thing->z + thing->height) + if (tm.thing->z > thing->z + thing->height) { return BMIT_CONTINUE; // overhead } - if (tmthing->z + tmthing->height < thing->z) + if (tm.thing->z + tm.thing->height < thing->z) { return BMIT_CONTINUE; // underneath } } - return Obj_ShrinkLaserCollide(tmthing, thing) ? BMIT_CONTINUE : BMIT_ABORT; + return Obj_ShrinkLaserCollide(tm.thing, thing) ? BMIT_CONTINUE : BMIT_ABORT; } - if (tmthing->type == MT_SMK_ICEBLOCK) + if (tm.thing->type == MT_SMK_ICEBLOCK) { // see if it went over / under - if (tmthing->z > thing->z + thing->height) + if (tm.thing->z > thing->z + thing->height) return BMIT_CONTINUE; // overhead - if (tmthing->z + tmthing->height < thing->z) + if (tm.thing->z + tm.thing->height < thing->z) return BMIT_CONTINUE; // underneath - return K_SMKIceBlockCollide(tmthing, thing) ? BMIT_CONTINUE : BMIT_ABORT; + return K_SMKIceBlockCollide(tm.thing, thing) ? BMIT_CONTINUE : BMIT_ABORT; } else if (thing->type == MT_SMK_ICEBLOCK) { // see if it went over / under - if (tmthing->z > thing->z + thing->height) + if (tm.thing->z > thing->z + thing->height) return BMIT_CONTINUE; // overhead - if (tmthing->z + tmthing->height < thing->z) + if (tm.thing->z + tm.thing->height < thing->z) return BMIT_CONTINUE; // underneath - return K_SMKIceBlockCollide(thing, tmthing) ? BMIT_CONTINUE : BMIT_ABORT; + return K_SMKIceBlockCollide(thing, tm.thing) ? BMIT_CONTINUE : BMIT_ABORT; } - if (tmthing->type == MT_EGGMANITEM || tmthing->type == MT_EGGMANITEM_SHIELD) + if (tm.thing->type == MT_EGGMANITEM || tm.thing->type == MT_EGGMANITEM_SHIELD) { // see if it went over / under - if (tmthing->z > thing->z + thing->height) + if (tm.thing->z > thing->z + thing->height) return BMIT_CONTINUE; // overhead - if (tmthing->z + tmthing->height < thing->z) + if (tm.thing->z + tm.thing->height < thing->z) return BMIT_CONTINUE; // underneath - return K_EggItemCollide(tmthing, thing) ? BMIT_CONTINUE : BMIT_ABORT; + return K_EggItemCollide(tm.thing, thing) ? BMIT_CONTINUE : BMIT_ABORT; } else if (thing->type == MT_EGGMANITEM || thing->type == MT_EGGMANITEM_SHIELD) { // see if it went over / under - if (tmthing->z > thing->z + thing->height) + if (tm.thing->z > thing->z + thing->height) return BMIT_CONTINUE; // overhead - if (tmthing->z + tmthing->height < thing->z) + if (tm.thing->z + tm.thing->height < thing->z) return BMIT_CONTINUE; // underneath - return K_EggItemCollide(thing, tmthing) ? BMIT_CONTINUE : BMIT_ABORT; + return K_EggItemCollide(thing, tm.thing) ? BMIT_CONTINUE : BMIT_ABORT; } - if (tmthing->type == MT_RANDOMITEM) + if (tm.thing->type == MT_RANDOMITEM) return BMIT_CONTINUE; // Bubble Shield reflect if (((thing->type == MT_BUBBLESHIELD && thing->target->player && thing->target->player->bubbleblowup) || (thing->player && thing->player->bubbleblowup)) - && (tmthing->type == MT_ORBINAUT || tmthing->type == MT_JAWZ - || tmthing->type == MT_BANANA || tmthing->type == MT_EGGMANITEM || tmthing->type == MT_BALLHOG - || tmthing->type == MT_SSMINE || tmthing->type == MT_LANDMINE || tmthing->type == MT_SINK - || tmthing->type == MT_GARDENTOP - || (tmthing->type == MT_PLAYER && thing->target != tmthing))) + && (tm.thing->type == MT_ORBINAUT || tm.thing->type == MT_JAWZ + || tm.thing->type == MT_BANANA || tm.thing->type == MT_EGGMANITEM || tm.thing->type == MT_BALLHOG + || tm.thing->type == MT_SSMINE || tm.thing->type == MT_LANDMINE || tm.thing->type == MT_SINK + || tm.thing->type == MT_GARDENTOP + || (tm.thing->type == MT_PLAYER && thing->target != tm.thing))) { // see if it went over / under - if (tmthing->z > thing->z + thing->height) + if (tm.thing->z > thing->z + thing->height) return BMIT_CONTINUE; // overhead - if (tmthing->z + tmthing->height < thing->z) + if (tm.thing->z + tm.thing->height < thing->z) return BMIT_CONTINUE; // underneath - return K_BubbleShieldCollide(thing, tmthing) ? BMIT_CONTINUE : BMIT_ABORT; + return K_BubbleShieldCollide(thing, tm.thing) ? BMIT_CONTINUE : BMIT_ABORT; } - else if (((tmthing->type == MT_BUBBLESHIELD && tmthing->target->player && tmthing->target->player->bubbleblowup) - || (tmthing->player && tmthing->player->bubbleblowup)) + else if (((tm.thing->type == MT_BUBBLESHIELD && tm.thing->target->player && tm.thing->target->player->bubbleblowup) + || (tm.thing->player && tm.thing->player->bubbleblowup)) && (thing->type == MT_ORBINAUT || thing->type == MT_JAWZ || thing->type == MT_BANANA || thing->type == MT_EGGMANITEM || thing->type == MT_BALLHOG - || thing->type == MT_SSMINE || tmthing->type == MT_LANDMINE || thing->type == MT_SINK + || thing->type == MT_SSMINE || tm.thing->type == MT_LANDMINE || thing->type == MT_SINK || thing->type == MT_GARDENTOP - || (thing->type == MT_PLAYER && tmthing->target != thing))) + || (thing->type == MT_PLAYER && tm.thing->target != thing))) { // see if it went over / under - if (tmthing->z > thing->z + thing->height) + if (tm.thing->z > thing->z + thing->height) return BMIT_CONTINUE; // overhead - if (tmthing->z + tmthing->height < thing->z) + if (tm.thing->z + tm.thing->height < thing->z) return BMIT_CONTINUE; // underneath - return K_BubbleShieldCollide(tmthing, thing) ? BMIT_CONTINUE : BMIT_ABORT; + return K_BubbleShieldCollide(tm.thing, thing) ? BMIT_CONTINUE : BMIT_ABORT; } // double make sure bubbles won't collide with anything else - if (thing->type == MT_BUBBLESHIELD || tmthing->type == MT_BUBBLESHIELD) + if (thing->type == MT_BUBBLESHIELD || tm.thing->type == MT_BUBBLESHIELD) return BMIT_CONTINUE; // Droptarget reflect if ((thing->type == MT_DROPTARGET || thing->type == MT_DROPTARGET_SHIELD) - && (tmthing->type == MT_ORBINAUT || tmthing->type == MT_JAWZ - || tmthing->type == MT_BANANA || tmthing->type == MT_EGGMANITEM || tmthing->type == MT_BALLHOG - || tmthing->type == MT_SSMINE || tmthing->type == MT_LANDMINE || tmthing->type == MT_SINK - || tmthing->type == MT_GARDENTOP - || (tmthing->type == MT_PLAYER))) + && (tm.thing->type == MT_ORBINAUT || tm.thing->type == MT_JAWZ + || tm.thing->type == MT_BANANA || tm.thing->type == MT_EGGMANITEM || tm.thing->type == MT_BALLHOG + || tm.thing->type == MT_SSMINE || tm.thing->type == MT_LANDMINE || tm.thing->type == MT_SINK + || tm.thing->type == MT_GARDENTOP + || (tm.thing->type == MT_PLAYER))) { // see if it went over / under - if (tmthing->z > thing->z + thing->height) + if (tm.thing->z > thing->z + thing->height) return BMIT_CONTINUE; // overhead - if (tmthing->z + tmthing->height < thing->z) + if (tm.thing->z + tm.thing->height < thing->z) return BMIT_CONTINUE; // underneath - return K_DropTargetCollide(thing, tmthing) ? BMIT_CONTINUE : BMIT_ABORT; + return K_DropTargetCollide(thing, tm.thing) ? BMIT_CONTINUE : BMIT_ABORT; } - else if ((tmthing->type == MT_DROPTARGET || tmthing->type == MT_DROPTARGET_SHIELD) + else if ((tm.thing->type == MT_DROPTARGET || tm.thing->type == MT_DROPTARGET_SHIELD) && (thing->type == MT_ORBINAUT || thing->type == MT_JAWZ || thing->type == MT_BANANA || thing->type == MT_EGGMANITEM || thing->type == MT_BALLHOG - || thing->type == MT_SSMINE || tmthing->type == MT_LANDMINE || thing->type == MT_SINK + || thing->type == MT_SSMINE || tm.thing->type == MT_LANDMINE || thing->type == MT_SINK || thing->type == MT_GARDENTOP || (thing->type == MT_PLAYER))) { // see if it went over / under - if (tmthing->z > thing->z + thing->height) + if (tm.thing->z > thing->z + thing->height) return BMIT_CONTINUE; // overhead - if (tmthing->z + tmthing->height < thing->z) + if (tm.thing->z + tm.thing->height < thing->z) return BMIT_CONTINUE; // underneath - return K_DropTargetCollide(tmthing, thing) ? BMIT_CONTINUE : BMIT_ABORT; + return K_DropTargetCollide(tm.thing, thing) ? BMIT_CONTINUE : BMIT_ABORT; } // double make sure drop targets won't collide with anything else - if (thing->type == MT_DROPTARGET || tmthing->type == MT_DROPTARGET - || thing->type == MT_DROPTARGET_SHIELD || tmthing->type == MT_DROPTARGET_SHIELD) + if (thing->type == MT_DROPTARGET || tm.thing->type == MT_DROPTARGET + || thing->type == MT_DROPTARGET_SHIELD || tm.thing->type == MT_DROPTARGET_SHIELD) return BMIT_CONTINUE; - if (tmthing->type == MT_ORBINAUT || tmthing->type == MT_JAWZ - || tmthing->type == MT_ORBINAUT_SHIELD || tmthing->type == MT_JAWZ_SHIELD - || tmthing->type == MT_GARDENTOP) + if (tm.thing->type == MT_ORBINAUT || tm.thing->type == MT_JAWZ + || tm.thing->type == MT_ORBINAUT_SHIELD || tm.thing->type == MT_JAWZ_SHIELD + || tm.thing->type == MT_GARDENTOP) { // see if it went over / under - if (tmthing->z > thing->z + thing->height) + if (tm.thing->z > thing->z + thing->height) return BMIT_CONTINUE; // overhead - if (tmthing->z + tmthing->height < thing->z) + if (tm.thing->z + tm.thing->height < thing->z) return BMIT_CONTINUE; // underneath - return Obj_OrbinautJawzCollide(tmthing, thing) ? BMIT_CONTINUE : BMIT_ABORT; + return Obj_OrbinautJawzCollide(tm.thing, thing) ? BMIT_CONTINUE : BMIT_ABORT; } else if (thing->type == MT_ORBINAUT || thing->type == MT_JAWZ || thing->type == MT_ORBINAUT_SHIELD || thing->type == MT_JAWZ_SHIELD || thing->type == MT_GARDENTOP) { // see if it went over / under - if (tmthing->z > thing->z + thing->height) + if (tm.thing->z > thing->z + thing->height) return BMIT_CONTINUE; // overhead - if (tmthing->z + tmthing->height < thing->z) + if (tm.thing->z + tm.thing->height < thing->z) return BMIT_CONTINUE; // underneath - return Obj_OrbinautJawzCollide(thing, tmthing) ? BMIT_CONTINUE : BMIT_ABORT; + return Obj_OrbinautJawzCollide(thing, tm.thing) ? BMIT_CONTINUE : BMIT_ABORT; } - if (tmthing->type == MT_BANANA || tmthing->type == MT_BANANA_SHIELD || tmthing->type == MT_BALLHOG) + if (tm.thing->type == MT_BANANA || tm.thing->type == MT_BANANA_SHIELD || tm.thing->type == MT_BALLHOG) { // see if it went over / under - if (tmthing->z > thing->z + thing->height) + if (tm.thing->z > thing->z + thing->height) return BMIT_CONTINUE; // overhead - if (tmthing->z + tmthing->height < thing->z) + if (tm.thing->z + tm.thing->height < thing->z) return BMIT_CONTINUE; // underneath - return K_BananaBallhogCollide(tmthing, thing) ? BMIT_CONTINUE : BMIT_ABORT; + return K_BananaBallhogCollide(tm.thing, thing) ? BMIT_CONTINUE : BMIT_ABORT; } else if (thing->type == MT_BANANA || thing->type == MT_BANANA_SHIELD || thing->type == MT_BALLHOG) { // see if it went over / under - if (tmthing->z > thing->z + thing->height) + if (tm.thing->z > thing->z + thing->height) return BMIT_CONTINUE; // overhead - if (tmthing->z + tmthing->height < thing->z) + if (tm.thing->z + tm.thing->height < thing->z) return BMIT_CONTINUE; // underneath - return K_BananaBallhogCollide(thing, tmthing) ? BMIT_CONTINUE : BMIT_ABORT; + return K_BananaBallhogCollide(thing, tm.thing) ? BMIT_CONTINUE : BMIT_ABORT; } - if (tmthing->type == MT_SSMINE || tmthing->type == MT_SSMINE_SHIELD) + if (tm.thing->type == MT_SSMINE || tm.thing->type == MT_SSMINE_SHIELD) { // see if it went over / under - if (tmthing->z > thing->z + thing->height) + if (tm.thing->z > thing->z + thing->height) return BMIT_CONTINUE; // overhead - if (tmthing->z + tmthing->height < thing->z) + if (tm.thing->z + tm.thing->height < thing->z) return BMIT_CONTINUE; // underneath - return K_MineCollide(tmthing, thing) ? BMIT_CONTINUE : BMIT_ABORT; + return K_MineCollide(tm.thing, thing) ? BMIT_CONTINUE : BMIT_ABORT; } else if (thing->type == MT_SSMINE || thing->type == MT_SSMINE_SHIELD) { // see if it went over / under - if (tmthing->z > thing->z + thing->height) + if (tm.thing->z > thing->z + thing->height) return BMIT_CONTINUE; // overhead - if (tmthing->z + tmthing->height < thing->z) + if (tm.thing->z + tm.thing->height < thing->z) return BMIT_CONTINUE; // underneath - return K_MineCollide(thing, tmthing) ? BMIT_CONTINUE : BMIT_ABORT; + return K_MineCollide(thing, tm.thing) ? BMIT_CONTINUE : BMIT_ABORT; } - if (tmthing->type == MT_LANDMINE) + if (tm.thing->type == MT_LANDMINE) { // see if it went over / under - if (tmthing->z > thing->z + thing->height) + if (tm.thing->z > thing->z + thing->height) return BMIT_CONTINUE; // overhead - if (tmthing->z + tmthing->height < thing->z) + if (tm.thing->z + tm.thing->height < thing->z) return BMIT_CONTINUE; // underneath - return K_LandMineCollide(tmthing, thing) ? BMIT_CONTINUE : BMIT_ABORT; + return K_LandMineCollide(tm.thing, thing) ? BMIT_CONTINUE : BMIT_ABORT; } else if (thing->type == MT_LANDMINE) { // see if it went over / under - if (tmthing->z > thing->z + thing->height) + if (tm.thing->z > thing->z + thing->height) return BMIT_CONTINUE; // overhead - if (tmthing->z + tmthing->height < thing->z) + if (tm.thing->z + tm.thing->height < thing->z) return BMIT_CONTINUE; // underneath - return K_LandMineCollide(thing, tmthing) ? BMIT_CONTINUE : BMIT_ABORT; + return K_LandMineCollide(thing, tm.thing) ? BMIT_CONTINUE : BMIT_ABORT; } - if (tmthing->type == MT_SINK) + if (tm.thing->type == MT_SINK) { // see if it went over / under - if (tmthing->z > thing->z + thing->height) + if (tm.thing->z > thing->z + thing->height) return BMIT_CONTINUE; // overhead - if (tmthing->z + tmthing->height < thing->z) + if (tm.thing->z + tm.thing->height < thing->z) return BMIT_CONTINUE; // underneath - return K_KitchenSinkCollide(tmthing, thing) ? BMIT_CONTINUE : BMIT_ABORT; + return K_KitchenSinkCollide(tm.thing, thing) ? BMIT_CONTINUE : BMIT_ABORT; } else if (thing->type == MT_SINK) { // see if it went over / under - if (tmthing->z > thing->z + thing->height) + if (tm.thing->z > thing->z + thing->height) return BMIT_CONTINUE; // overhead - if (tmthing->z + tmthing->height < thing->z) + if (tm.thing->z + tm.thing->height < thing->z) return BMIT_CONTINUE; // underneath - return K_KitchenSinkCollide(thing, tmthing) ? BMIT_CONTINUE : BMIT_ABORT; + return K_KitchenSinkCollide(thing, tm.thing) ? BMIT_CONTINUE : BMIT_ABORT; } - if (tmthing->type == MT_FALLINGROCK) + if (tm.thing->type == MT_FALLINGROCK) { // see if it went over / under - if (tmthing->z > thing->z + thing->height) + if (tm.thing->z > thing->z + thing->height) return BMIT_CONTINUE; // overhead - if (tmthing->z + tmthing->height < thing->z) + if (tm.thing->z + tm.thing->height < thing->z) return BMIT_CONTINUE; // underneath - return K_FallingRockCollide(tmthing, thing) ? BMIT_CONTINUE : BMIT_ABORT; + return K_FallingRockCollide(tm.thing, thing) ? BMIT_CONTINUE : BMIT_ABORT; } else if (thing->type == MT_FALLINGROCK) { // see if it went over / under - if (tmthing->z > thing->z + thing->height) + if (tm.thing->z > thing->z + thing->height) return BMIT_CONTINUE; // overhead - if (tmthing->z + tmthing->height < thing->z) + if (tm.thing->z + tm.thing->height < thing->z) return BMIT_CONTINUE; // underneath - return K_FallingRockCollide(thing, tmthing) ? BMIT_CONTINUE : BMIT_ABORT; + return K_FallingRockCollide(thing, tm.thing) ? BMIT_CONTINUE : BMIT_ABORT; } //} if ((thing->type == MT_SPRINGSHELL || thing->type == MT_YELLOWSHELL) && thing->health > 0 - && (tmthing->player || (tmthing->flags & MF_PUSHABLE)) && tmthing->health > 0) + && (tm.thing->player || (tm.thing->flags & MF_PUSHABLE)) && tm.thing->health > 0) { // Multiplying by -1 inherently flips "less than" and "greater than" - fixed_t tmz = ((thing->eflags & MFE_VERTICALFLIP) ? -(tmthing->z + tmthing->height) : tmthing->z); - fixed_t tmznext = ((thing->eflags & MFE_VERTICALFLIP) ? -tmthing->momz : tmthing->momz) + tmz; + fixed_t tmz = ((thing->eflags & MFE_VERTICALFLIP) ? -(tm.thing->z + tm.thing->height) : tm.thing->z); + fixed_t tmznext = ((thing->eflags & MFE_VERTICALFLIP) ? -tm.thing->momz : tm.thing->momz) + tmz; fixed_t thzh = ((thing->eflags & MFE_VERTICALFLIP) ? -thing->z : thing->z + thing->height); //fixed_t sprarea = FixedMul(8*FRACUNIT, thing->scale) * P_MobjFlip(thing); //if ((tmznext <= thzh && tmz > thzh) || (tmznext > thzh - sprarea && tmznext < thzh)) if (tmznext <= thzh) { - P_DoSpring(thing, tmthing); + P_DoSpring(thing, tm.thing); // return BMIT_CONTINUE; } //else if (tmz > thzh - sprarea && tmz < thzh) // Don't damage people springing up / down @@ -1062,20 +1072,20 @@ static BlockItReturn_t PIT_CheckThing(mobj_t *thing) } // missiles can hit other things - if (tmthing->flags & MF_MISSILE) + if (tm.thing->flags & MF_MISSILE) { - UINT8 damagetype = (tmthing->info->mass ^ DMG_WOMBO); + UINT8 damagetype = (tm.thing->info->mass ^ DMG_WOMBO); // see if it went over / under - if (tmthing->z > thing->z + thing->height) + if (tm.thing->z > thing->z + thing->height) return BMIT_CONTINUE; // overhead - if (tmthing->z + tmthing->height < thing->z) + if (tm.thing->z + tm.thing->height < thing->z) return BMIT_CONTINUE; // underneath - if (tmthing->target && tmthing->target->type == thing->type) + if (tm.thing->target && tm.thing->target->type == thing->type) { // Don't hit same species as originator. - if (thing == tmthing->target) + if (thing == tm.thing->target) return BMIT_CONTINUE; if (thing->type != MT_PLAYER) @@ -1093,40 +1103,40 @@ static BlockItReturn_t PIT_CheckThing(mobj_t *thing) } // damage / explode - P_DamageMobj(thing, tmthing, tmthing->target, 1, damagetype); + P_DamageMobj(thing, tm.thing, tm.thing->target, 1, damagetype); // don't traverse any more return BMIT_ABORT; } - if (thing->flags & MF_PUSHABLE && (tmthing->player || tmthing->flags & MF_PUSHABLE) - && tmthing->z + tmthing->height > thing->z && tmthing->z < thing->z + thing->height - && !(netgame && tmthing->player && tmthing->player->spectator)) // Push thing! + if (thing->flags & MF_PUSHABLE && (tm.thing->player || tm.thing->flags & MF_PUSHABLE) + && tm.thing->z + tm.thing->height > thing->z && tm.thing->z < thing->z + thing->height + && !(netgame && tm.thing->player && tm.thing->player->spectator)) // Push thing! { if (thing->flags2 & MF2_SLIDEPUSH) // Make it slide { - if (tmthing->momy > 0 && tmthing->momy > FixedMul(4*FRACUNIT, thing->scale) && tmthing->momy > thing->momy) + if (tm.thing->momy > 0 && tm.thing->momy > FixedMul(4*FRACUNIT, thing->scale) && tm.thing->momy > thing->momy) { thing->momy += FixedMul(PUSHACCEL, thing->scale); - tmthing->momy -= FixedMul(PUSHACCEL, thing->scale); + tm.thing->momy -= FixedMul(PUSHACCEL, thing->scale); } - else if (tmthing->momy < 0 && tmthing->momy < FixedMul(-4*FRACUNIT, thing->scale) - && tmthing->momy < thing->momy) + else if (tm.thing->momy < 0 && tm.thing->momy < FixedMul(-4*FRACUNIT, thing->scale) + && tm.thing->momy < thing->momy) { thing->momy -= FixedMul(PUSHACCEL, thing->scale); - tmthing->momy += FixedMul(PUSHACCEL, thing->scale); + tm.thing->momy += FixedMul(PUSHACCEL, thing->scale); } - if (tmthing->momx > 0 && tmthing->momx > FixedMul(4*FRACUNIT, thing->scale) - && tmthing->momx > thing->momx) + if (tm.thing->momx > 0 && tm.thing->momx > FixedMul(4*FRACUNIT, thing->scale) + && tm.thing->momx > thing->momx) { thing->momx += FixedMul(PUSHACCEL, thing->scale); - tmthing->momx -= FixedMul(PUSHACCEL, thing->scale); + tm.thing->momx -= FixedMul(PUSHACCEL, thing->scale); } - else if (tmthing->momx < 0 && tmthing->momx < FixedMul(-4*FRACUNIT, thing->scale) - && tmthing->momx < thing->momx) + else if (tm.thing->momx < 0 && tm.thing->momx < FixedMul(-4*FRACUNIT, thing->scale) + && tm.thing->momx < thing->momx) { thing->momx -= FixedMul(PUSHACCEL, thing->scale); - tmthing->momx += FixedMul(PUSHACCEL, thing->scale); + tm.thing->momx += FixedMul(PUSHACCEL, thing->scale); } if (thing->momx > FixedMul(thing->info->speed, thing->scale)) @@ -1140,88 +1150,88 @@ static BlockItReturn_t PIT_CheckThing(mobj_t *thing) } else { - if (tmthing->momx > FixedMul(4*FRACUNIT, thing->scale)) - tmthing->momx = FixedMul(4*FRACUNIT, thing->scale); - else if (tmthing->momx < FixedMul(-4*FRACUNIT, thing->scale)) - tmthing->momx = FixedMul(-4*FRACUNIT, thing->scale); - if (tmthing->momy > FixedMul(4*FRACUNIT, thing->scale)) - tmthing->momy = FixedMul(4*FRACUNIT, thing->scale); - else if (tmthing->momy < FixedMul(-4*FRACUNIT, thing->scale)) - tmthing->momy = FixedMul(-4*FRACUNIT, thing->scale); + if (tm.thing->momx > FixedMul(4*FRACUNIT, thing->scale)) + tm.thing->momx = FixedMul(4*FRACUNIT, thing->scale); + else if (tm.thing->momx < FixedMul(-4*FRACUNIT, thing->scale)) + tm.thing->momx = FixedMul(-4*FRACUNIT, thing->scale); + if (tm.thing->momy > FixedMul(4*FRACUNIT, thing->scale)) + tm.thing->momy = FixedMul(4*FRACUNIT, thing->scale); + else if (tm.thing->momy < FixedMul(-4*FRACUNIT, thing->scale)) + tm.thing->momy = FixedMul(-4*FRACUNIT, thing->scale); - thing->momx = tmthing->momx; - thing->momy = tmthing->momy; + thing->momx = tm.thing->momx; + thing->momy = tm.thing->momy; } if (thing->type != MT_GARGOYLE || P_IsObjectOnGround(thing)) S_StartSound(thing, thing->info->activesound); - P_SetTarget(&thing->target, tmthing); + P_SetTarget(&thing->target, tm.thing); } // check for special pickup - if (thing->flags & MF_SPECIAL && tmthing->player) + if (thing->flags & MF_SPECIAL && tm.thing->player) { - P_TouchSpecialThing(thing, tmthing, true); // can remove thing + P_TouchSpecialThing(thing, tm.thing, true); // can remove thing return BMIT_CONTINUE; } // check again for special pickup - if (tmthing->flags & MF_SPECIAL && thing->player) + if (tm.thing->flags & MF_SPECIAL && thing->player) { - P_TouchSpecialThing(tmthing, thing, true); // can remove thing + P_TouchSpecialThing(tm.thing, thing, true); // can remove thing return BMIT_CONTINUE; } // Sprite Spikes! // Do not return because solidity code comes below. - if (tmthing->type == MT_SPIKE && tmthing->flags & MF_SOLID && thing->player) // moving spike rams into player?! + if (tm.thing->type == MT_SPIKE && tm.thing->flags & MF_SOLID && thing->player) // moving spike rams into player?! { - if (tmthing->eflags & MFE_VERTICALFLIP) + if (tm.thing->eflags & MFE_VERTICALFLIP) { - if (thing->z + thing->height <= tmthing->z + FixedMul(FRACUNIT, tmthing->scale) - && thing->z + thing->height + thing->momz >= tmthing->z + FixedMul(FRACUNIT, tmthing->scale) + tmthing->momz) - P_DamageMobj(thing, tmthing, tmthing, 1, DMG_NORMAL); + if (thing->z + thing->height <= tm.thing->z + FixedMul(FRACUNIT, tm.thing->scale) + && thing->z + thing->height + thing->momz >= tm.thing->z + FixedMul(FRACUNIT, tm.thing->scale) + tm.thing->momz) + P_DamageMobj(thing, tm.thing, tm.thing, 1, DMG_NORMAL); } - else if (thing->z >= tmthing->z + tmthing->height - FixedMul(FRACUNIT, tmthing->scale) - && thing->z + thing->momz <= tmthing->z + tmthing->height - FixedMul(FRACUNIT, tmthing->scale) + tmthing->momz) - P_DamageMobj(thing, tmthing, tmthing, 1, DMG_NORMAL); + else if (thing->z >= tm.thing->z + tm.thing->height - FixedMul(FRACUNIT, tm.thing->scale) + && thing->z + thing->momz <= tm.thing->z + tm.thing->height - FixedMul(FRACUNIT, tm.thing->scale) + tm.thing->momz) + P_DamageMobj(thing, tm.thing, tm.thing, 1, DMG_NORMAL); } - else if (thing->type == MT_SPIKE && thing->flags & MF_SOLID && tmthing->player) // unfortunate player falls into spike?! + else if (thing->type == MT_SPIKE && thing->flags & MF_SOLID && tm.thing->player) // unfortunate player falls into spike?! { if (thing->eflags & MFE_VERTICALFLIP) { - if (tmthing->z + tmthing->height <= thing->z - FixedMul(FRACUNIT, thing->scale) - && tmthing->z + tmthing->height + tmthing->momz >= thing->z - FixedMul(FRACUNIT, thing->scale)) - P_DamageMobj(tmthing, thing, thing, 1, DMG_NORMAL); + if (tm.thing->z + tm.thing->height <= thing->z - FixedMul(FRACUNIT, thing->scale) + && tm.thing->z + tm.thing->height + tm.thing->momz >= thing->z - FixedMul(FRACUNIT, thing->scale)) + P_DamageMobj(tm.thing, thing, thing, 1, DMG_NORMAL); } - else if (tmthing->z >= thing->z + thing->height + FixedMul(FRACUNIT, thing->scale) - && tmthing->z + tmthing->momz <= thing->z + thing->height + FixedMul(FRACUNIT, thing->scale)) - P_DamageMobj(tmthing, thing, thing, 1, DMG_NORMAL); + else if (tm.thing->z >= thing->z + thing->height + FixedMul(FRACUNIT, thing->scale) + && tm.thing->z + tm.thing->momz <= thing->z + thing->height + FixedMul(FRACUNIT, thing->scale)) + P_DamageMobj(tm.thing, thing, thing, 1, DMG_NORMAL); } - if (tmthing->type == MT_WALLSPIKE && tmthing->flags & MF_SOLID && thing->player) // wall spike impales player + if (tm.thing->type == MT_WALLSPIKE && tm.thing->flags & MF_SOLID && thing->player) // wall spike impales player { fixed_t bottomz, topz; - bottomz = tmthing->z; - topz = tmthing->z + tmthing->height; - if (tmthing->eflags & MFE_VERTICALFLIP) - bottomz -= FixedMul(FRACUNIT, tmthing->scale); + bottomz = tm.thing->z; + topz = tm.thing->z + tm.thing->height; + if (tm.thing->eflags & MFE_VERTICALFLIP) + bottomz -= FixedMul(FRACUNIT, tm.thing->scale); else - topz += FixedMul(FRACUNIT, tmthing->scale); + topz += FixedMul(FRACUNIT, tm.thing->scale); if (thing->z + thing->height > bottomz // above bottom && thing->z < topz) // below top // don't check angle, the player was clearly in the way in this case - P_DamageMobj(thing, tmthing, tmthing, 1, DMG_NORMAL); + P_DamageMobj(thing, tm.thing, tm.thing, 1, DMG_NORMAL); } - else if (thing->type == MT_WALLSPIKE && thing->flags & MF_SOLID && tmthing->player) + else if (thing->type == MT_WALLSPIKE && thing->flags & MF_SOLID && tm.thing->player) { fixed_t bottomz, topz; - angle_t touchangle = R_PointToAngle2(thing->tracer->x, thing->tracer->y, tmthing->x, tmthing->y); + angle_t touchangle = R_PointToAngle2(thing->tracer->x, thing->tracer->y, tm.thing->x, tm.thing->y); - if (P_PlayerInPain(tmthing->player) && (tmthing->momx || tmthing->momy)) + if (P_PlayerInPain(tm.thing->player) && (tm.thing->momx || tm.thing->momy)) { - angle_t playerangle = R_PointToAngle2(0, 0, tmthing->momx, tmthing->momy) - touchangle; + angle_t playerangle = R_PointToAngle2(0, 0, tm.thing->momx, tm.thing->momy) - touchangle; if (playerangle > ANGLE_180) playerangle = InvAngle(playerangle); if (playerangle < ANGLE_90) @@ -1236,103 +1246,103 @@ static BlockItReturn_t PIT_CheckThing(mobj_t *thing) else topz += FixedMul(FRACUNIT, thing->scale); - if (tmthing->z + tmthing->height > bottomz // above bottom - && tmthing->z < topz // below top + if (tm.thing->z + tm.thing->height > bottomz // above bottom + && tm.thing->z < topz // below top && !P_MobjWasRemoved(thing->tracer)) // this probably wouldn't work if we didn't have a tracer { // use base as a reference point to determine what angle you touched the spike at touchangle = thing->angle - touchangle; if (touchangle > ANGLE_180) touchangle = InvAngle(touchangle); if (touchangle <= ANGLE_22h) // if you touched it at this close an angle, you get poked! - P_DamageMobj(tmthing, thing, thing, 1, DMG_NORMAL); + P_DamageMobj(tm.thing, thing, thing, 1, DMG_NORMAL); } } if (thing->flags & MF_PUSHABLE) { - if (tmthing->type == MT_FAN || tmthing->type == MT_STEAM) - P_DoFanAndGasJet(tmthing, thing); + if (tm.thing->type == MT_FAN || tm.thing->type == MT_STEAM) + P_DoFanAndGasJet(tm.thing, thing); } - if (tmthing->flags & MF_PUSHABLE) + if (tm.thing->flags & MF_PUSHABLE) { if (thing->type == MT_FAN || thing->type == MT_STEAM) { - P_DoFanAndGasJet(thing, tmthing); + P_DoFanAndGasJet(thing, tm.thing); return BMIT_CONTINUE; } else if (thing->flags & MF_SPRING) { - if ( thing->z <= tmthing->z + tmthing->height - && tmthing->z <= thing->z + thing->height) - if (P_DoSpring(thing, tmthing)) + if ( thing->z <= tm.thing->z + tm.thing->height + && tm.thing->z <= thing->z + thing->height) + if (P_DoSpring(thing, tm.thing)) return BMIT_ABORT; return BMIT_CONTINUE; } } // thanks to sal for solidenemies dot lua - if (thing->flags & (MF_ENEMY|MF_BOSS) && tmthing->flags & (MF_ENEMY|MF_BOSS)) + if (thing->flags & (MF_ENEMY|MF_BOSS) && tm.thing->flags & (MF_ENEMY|MF_BOSS)) { - if ((thing->z + thing->height >= tmthing->z) - && (tmthing->z + tmthing->height >= thing->z)) + if ((thing->z + thing->height >= tm.thing->z) + && (tm.thing->z + tm.thing->height >= thing->z)) return BMIT_ABORT; } if (thing->player) { - if (tmthing->type == MT_FAN || tmthing->type == MT_STEAM) - P_DoFanAndGasJet(tmthing, thing); + if (tm.thing->type == MT_FAN || tm.thing->type == MT_STEAM) + P_DoFanAndGasJet(tm.thing, thing); } - if (tmthing->player) // Is the moving/interacting object the player? + if (tm.thing->player) // Is the moving/interacting object the player? { - if (!tmthing->health) + if (!tm.thing->health) return BMIT_CONTINUE; if (thing->type == MT_FAN || thing->type == MT_STEAM) - P_DoFanAndGasJet(thing, tmthing); + P_DoFanAndGasJet(thing, tm.thing); else if (thing->flags & MF_SPRING) { - if ( thing->z <= tmthing->z + tmthing->height - && tmthing->z <= thing->z + thing->height) - if (P_DoSpring(thing, tmthing)) + if ( thing->z <= tm.thing->z + tm.thing->height + && tm.thing->z <= thing->z + thing->height) + if (P_DoSpring(thing, tm.thing)) return BMIT_ABORT; return BMIT_CONTINUE; } else if (thing->player) // bounce when players collide { // see if it went over / under - if (tmthing->z > thing->z + thing->height) + if (tm.thing->z > thing->z + thing->height) return BMIT_CONTINUE; // overhead - if (tmthing->z + tmthing->height < thing->z) + if (tm.thing->z + tm.thing->height < thing->z) return BMIT_CONTINUE; // underneath - if (thing->player->hyudorotimer || tmthing->player->hyudorotimer) + if (thing->player->hyudorotimer || tm.thing->player->hyudorotimer) { return BMIT_CONTINUE; } if ((gametyperules & GTR_BUMPERS) - && ((thing->player->bumpers && !tmthing->player->bumpers) - || (tmthing->player->bumpers && !thing->player->bumpers))) + && ((thing->player->bumpers && !tm.thing->player->bumpers) + || (tm.thing->player->bumpers && !thing->player->bumpers))) { return BMIT_CONTINUE; } // The bump has to happen last - if (P_IsObjectOnGround(thing) && tmthing->momz < 0 && tmthing->player->trickpanel) + if (P_IsObjectOnGround(thing) && tm.thing->momz < 0 && tm.thing->player->trickpanel) { - P_DamageMobj(thing, tmthing, tmthing, 1, DMG_WIPEOUT|DMG_STEAL); + P_DamageMobj(thing, tm.thing, tm.thing, 1, DMG_WIPEOUT|DMG_STEAL); } - else if (P_IsObjectOnGround(tmthing) && thing->momz < 0 && thing->player->trickpanel) + else if (P_IsObjectOnGround(tm.thing) && thing->momz < 0 && thing->player->trickpanel) { - P_DamageMobj(tmthing, thing, thing, 1, DMG_WIPEOUT|DMG_STEAL); + P_DamageMobj(tm.thing, thing, thing, 1, DMG_WIPEOUT|DMG_STEAL); } - if (K_KartBouncing(tmthing, thing) == true) + if (K_KartBouncing(tm.thing, thing) == true) { - K_PvPTouchDamage(tmthing, thing); + K_PvPTouchDamage(tm.thing, thing); } return BMIT_CONTINUE; @@ -1340,48 +1350,48 @@ static BlockItReturn_t PIT_CheckThing(mobj_t *thing) else if (thing->type == MT_BLUEROBRA_HEAD || thing->type == MT_BLUEROBRA_JOINT) { // see if it went over / under - if (tmthing->z > thing->z + thing->height) + if (tm.thing->z > thing->z + thing->height) return BMIT_CONTINUE; // overhead - if (tmthing->z + tmthing->height < thing->z) + if (tm.thing->z + tm.thing->height < thing->z) return BMIT_CONTINUE; // underneath if (!thing->health) return BMIT_CONTINUE; // dead - if (tmthing->player->invincibilitytimer > 0 - || K_IsBigger(tmthing, thing) == true) + if (tm.thing->player->invincibilitytimer > 0 + || K_IsBigger(tm.thing, thing) == true) { if (thing->type == MT_BLUEROBRA_JOINT) - P_KillMobj(thing->target, tmthing, tmthing, DMG_NORMAL); + P_KillMobj(thing->target, tm.thing, tm.thing, DMG_NORMAL); else - P_KillMobj(thing, tmthing, tmthing, DMG_NORMAL); + P_KillMobj(thing, tm.thing, tm.thing, DMG_NORMAL); return BMIT_CONTINUE; } else { - K_KartSolidBounce(tmthing, thing); + K_KartSolidBounce(tm.thing, thing); return BMIT_CONTINUE; } } else if (thing->type == MT_SMK_PIPE) { // see if it went over / under - if (tmthing->z > thing->z + thing->height) + if (tm.thing->z > thing->z + thing->height) return BMIT_CONTINUE; // overhead - if (tmthing->z + tmthing->height < thing->z) + if (tm.thing->z + tm.thing->height < thing->z) return BMIT_CONTINUE; // underneath if (!thing->health) return BMIT_CONTINUE; // dead - if (tmthing->player->invincibilitytimer > 0 - || K_IsBigger(tmthing, thing) == true) + if (tm.thing->player->invincibilitytimer > 0 + || K_IsBigger(tm.thing, thing) == true) { - P_KillMobj(thing, tmthing, tmthing, DMG_NORMAL); + P_KillMobj(thing, tm.thing, tm.thing, DMG_NORMAL); return BMIT_CONTINUE; // kill } - K_KartSolidBounce(tmthing, thing); + K_KartSolidBounce(tm.thing, thing); return BMIT_CONTINUE; } else if (thing->type == MT_SMK_THWOMP) @@ -1392,38 +1402,38 @@ static BlockItReturn_t PIT_CheckThing(mobj_t *thing) if (!thwompsactive) return BMIT_CONTINUE; // not active yet - if ((tmthing->z < thing->z) && (thing->z >= thing->movefactor-(256<z < thing->z) && (thing->z >= thing->movefactor-(256<extravalue1 = 1; // purposely try to stomp on players early //S_StartSound(thing, sfx_s1bb); } // see if it went over / under - if (tmthing->z > thing->z + thing->height) + if (tm.thing->z > thing->z + thing->height) return BMIT_CONTINUE; // overhead - if (tmthing->z + tmthing->height < thing->z) + if (tm.thing->z + tm.thing->height < thing->z) return BMIT_CONTINUE; // underneath // kill - if (tmthing->player->invincibilitytimer > 0 - || K_IsBigger(tmthing, thing) == true) + if (tm.thing->player->invincibilitytimer > 0 + || K_IsBigger(tm.thing, thing) == true) { - P_KillMobj(thing, tmthing, tmthing, DMG_NORMAL); + P_KillMobj(thing, tm.thing, tm.thing, DMG_NORMAL); return BMIT_CONTINUE; } // no interaction - if (tmthing->player->flashing > 0 || tmthing->player->hyudorotimer > 0 || tmthing->player->spinouttimer > 0) + if (tm.thing->player->flashing > 0 || tm.thing->player->hyudorotimer > 0 || tm.thing->player->spinouttimer > 0) return BMIT_CONTINUE; // collide - if (tmthing->z < thing->z && thing->momz < 0) - P_DamageMobj(tmthing, thing, thing, 1, DMG_TUMBLE); + if (tm.thing->z < thing->z && thing->momz < 0) + P_DamageMobj(tm.thing, thing, thing, 1, DMG_TUMBLE); else { - if ((K_KartSolidBounce(tmthing, thing) == true) && (thing->flags2 & MF2_AMBUSH)) + if ((K_KartSolidBounce(tm.thing, thing) == true) && (thing->flags2 & MF2_AMBUSH)) { - P_DamageMobj(tmthing, thing, thing, 1, DMG_WIPEOUT); + P_DamageMobj(tm.thing, thing, thing, 1, DMG_WIPEOUT); } } @@ -1432,49 +1442,49 @@ static BlockItReturn_t PIT_CheckThing(mobj_t *thing) else if (thing->type == MT_KART_LEFTOVER) { // see if it went over / under - if (tmthing->z > thing->z + thing->height) + if (tm.thing->z > thing->z + thing->height) return BMIT_CONTINUE; // overhead - if (tmthing->z + tmthing->height < thing->z) + if (tm.thing->z + tm.thing->height < thing->z) return BMIT_CONTINUE; // underneath - K_KartBouncing(tmthing, thing); + K_KartBouncing(tm.thing, thing); return BMIT_CONTINUE; } else if (thing->flags & MF_SOLID) { // see if it went over / under - if (tmthing->z > thing->z + thing->height) + if (tm.thing->z > thing->z + thing->height) return BMIT_CONTINUE; // overhead - if (tmthing->z + tmthing->height < thing->z) + if (tm.thing->z + tm.thing->height < thing->z) return BMIT_CONTINUE; // underneath - K_KartSolidBounce(tmthing, thing); + K_KartSolidBounce(tm.thing, thing); return BMIT_CONTINUE; } } - if ((tmthing->flags & MF_SPRING || tmthing->type == MT_STEAM || tmthing->type == MT_SPIKE || tmthing->type == MT_WALLSPIKE) && (thing->player)) + if ((tm.thing->flags & MF_SPRING || tm.thing->type == MT_STEAM || tm.thing->type == MT_SPIKE || tm.thing->type == MT_WALLSPIKE) && (thing->player)) ; // springs, gas jets and springs should never be able to step up onto a player // z checking at last // Treat noclip things as non-solid! else if ((thing->flags & (MF_SOLID|MF_NOCLIP)) == MF_SOLID - && (tmthing->flags & (MF_SOLID|MF_NOCLIP)) == MF_SOLID) + && (tm.thing->flags & (MF_SOLID|MF_NOCLIP)) == MF_SOLID) { fixed_t topz, tmtopz; - if (tmthing->eflags & MFE_VERTICALFLIP) + if (tm.thing->eflags & MFE_VERTICALFLIP) { // pass under - tmtopz = tmthing->z; + tmtopz = tm.thing->z; if (tmtopz > thing->z + thing->height) { - if (thing->z + thing->height > tmfloorz) + if (thing->z + thing->height > tm.floorz) { - tmfloorz = thing->z + thing->height; - tmfloorrover = NULL; - tmfloorslope = NULL; - tmfloorpic = -1; + tm.floorz = thing->z + thing->height; + tm.floorrover = NULL; + tm.floorslope = NULL; + tm.floorpic = -1; } return BMIT_CONTINUE; } @@ -1485,40 +1495,40 @@ static BlockItReturn_t PIT_CheckThing(mobj_t *thing) // (dont climb max. 24units while already in air) // since return false doesn't handle momentum properly, // we lie to P_TryMove() so it's always too high - if (tmthing->player && tmthing->z + tmthing->height > topz - && tmthing->z + tmthing->height < tmthing->ceilingz) + if (tm.thing->player && tm.thing->z + tm.thing->height > topz + && tm.thing->z + tm.thing->height < tm.thing->ceilingz) { if (thing->flags & MF_GRENADEBOUNCE && (thing->flags & MF_MONITOR || thing->info->flags & MF_MONITOR)) // Gold monitor hack... return BMIT_ABORT; - tmfloorz = tmceilingz = topz; // block while in air - tmceilingrover = NULL; - tmceilingslope = NULL; - tmceilingpic = -1; - tmfloorthing = thing; // needed for side collision + tm.floorz = tm.ceilingz = topz; // block while in air + tm.ceilingrover = NULL; + tm.ceilingslope = NULL; + tm.ceilingpic = -1; + P_SetTarget(&tm.floorthing, thing); // needed for side collision } - else if (topz < tmceilingz && tmthing->z <= thing->z+thing->height) + else if (topz < tm.ceilingz && tm.thing->z <= thing->z+thing->height) { - tmceilingz = topz; - tmceilingrover = NULL; - tmceilingslope = NULL; - tmceilingpic = -1; - tmfloorthing = thing; // thing we may stand on + tm.ceilingz = topz; + tm.ceilingrover = NULL; + tm.ceilingslope = NULL; + tm.ceilingpic = -1; + P_SetTarget(&tm.floorthing, thing); // thing we may stand on } } else { // pass under - tmtopz = tmthing->z + tmthing->height; + tmtopz = tm.thing->z + tm.thing->height; if (tmtopz < thing->z) { - if (thing->z < tmceilingz) + if (thing->z < tm.ceilingz) { - tmceilingz = thing->z; - tmceilingrover = NULL; - tmceilingslope = NULL; - tmceilingpic = -1; + tm.ceilingz = thing->z; + tm.ceilingrover = NULL; + tm.ceilingslope = NULL; + tm.ceilingpic = -1; } return BMIT_CONTINUE; } @@ -1529,25 +1539,25 @@ static BlockItReturn_t PIT_CheckThing(mobj_t *thing) // (dont climb max. 24units while already in air) // since return false doesn't handle momentum properly, // we lie to P_TryMove() so it's always too high - if (tmthing->player && tmthing->z < topz - && tmthing->z > tmthing->floorz) + if (tm.thing->player && tm.thing->z < topz + && tm.thing->z > tm.thing->floorz) { if (thing->flags & MF_GRENADEBOUNCE && (thing->flags & MF_MONITOR || thing->info->flags & MF_MONITOR)) // Gold monitor hack... return BMIT_ABORT; - tmfloorz = tmceilingz = topz; // block while in air - tmfloorrover = NULL; - tmfloorslope = NULL; - tmfloorpic = -1; - tmfloorthing = thing; // needed for side collision + tm.floorz = tm.ceilingz = topz; // block while in air + tm.floorrover = NULL; + tm.floorslope = NULL; + tm.floorpic = -1; + P_SetTarget(&tm.floorthing, thing); // needed for side collision } - else if (topz > tmfloorz && tmthing->z+tmthing->height >= thing->z) + else if (topz > tm.floorz && tm.thing->z+tm.thing->height >= thing->z) { - tmfloorz = topz; - tmfloorrover = NULL; - tmfloorslope = NULL; - tmfloorpic = -1; - tmfloorthing = thing; // thing we may stand on + tm.floorz = topz; + tm.floorrover = NULL; + tm.floorslope = NULL; + tm.floorpic = -1; + P_SetTarget(&tm.floorthing, thing); // thing we may stand on } } } @@ -1557,19 +1567,19 @@ static BlockItReturn_t PIT_CheckThing(mobj_t *thing) } // PIT_CheckCameraLine -// Adjusts tmfloorz and tmceilingz as lines are contacted - FOR CAMERA ONLY +// Adjusts tm.floorz and tm.ceilingz as lines are contacted - FOR CAMERA ONLY static BlockItReturn_t PIT_CheckCameraLine(line_t *ld) { if (ld->polyobj && !(ld->polyobj->flags & POF_SOLID)) return BMIT_CONTINUE; - if (tmbbox[BOXRIGHT] <= ld->bbox[BOXLEFT] || tmbbox[BOXLEFT] >= ld->bbox[BOXRIGHT] - || tmbbox[BOXTOP] <= ld->bbox[BOXBOTTOM] || tmbbox[BOXBOTTOM] >= ld->bbox[BOXTOP]) + if (tm.bbox[BOXRIGHT] <= ld->bbox[BOXLEFT] || tm.bbox[BOXLEFT] >= ld->bbox[BOXRIGHT] + || tm.bbox[BOXTOP] <= ld->bbox[BOXBOTTOM] || tm.bbox[BOXBOTTOM] >= ld->bbox[BOXTOP]) { return BMIT_CONTINUE; } - if (P_BoxOnLineSide(tmbbox, ld) != -1) + if (P_BoxOnLineSide(tm.bbox, ld) != -1) return BMIT_CONTINUE; // A line has been hit @@ -1584,7 +1594,7 @@ static BlockItReturn_t PIT_CheckCameraLine(line_t *ld) // could be crossed in either order. // this line is out of the if so upper and lower textures can be hit by a splat - blockingline = ld; + tm.blockingline = ld; if (!ld->backsector) // one sided line { if (P_PointOnLineSide(mapcampointer->x, mapcampointer->y, ld)) @@ -1596,22 +1606,22 @@ static BlockItReturn_t PIT_CheckCameraLine(line_t *ld) P_CameraLineOpening(ld); // adjust floor / ceiling heights - if (opentop < tmceilingz) + if (opentop < tm.ceilingz) { - tmceilingz = opentop; - ceilingline = ld; + tm.ceilingz = opentop; + tm.ceilingline = ld; } - if (openbottom > tmfloorz) + if (openbottom > tm.floorz) { - tmfloorz = openbottom; + tm.floorz = openbottom; } - if (highceiling > tmdrpoffceilz) - tmdrpoffceilz = highceiling; + if (highceiling > tm.drpoffceilz) + tm.drpoffceilz = highceiling; - if (lowfloor < tmdropoffz) - tmdropoffz = lowfloor; + if (lowfloor < tm.dropoffz) + tm.dropoffz = lowfloor; return BMIT_CONTINUE; } @@ -1657,44 +1667,44 @@ boolean P_IsLineTripWire(const line_t *ld) // // PIT_CheckLine -// Adjusts tmfloorz and tmceilingz as lines are contacted +// Adjusts tm.floorz and tm.ceilingz as lines are contacted // static BlockItReturn_t PIT_CheckLine(line_t *ld) { - const fixed_t thingtop = tmthing->z + tmthing->height; + const fixed_t thingtop = tm.thing->z + tm.thing->height; if (ld->polyobj && !(ld->polyobj->flags & POF_SOLID)) return BMIT_CONTINUE; - if (tmbbox[BOXRIGHT] <= ld->bbox[BOXLEFT] || tmbbox[BOXLEFT] >= ld->bbox[BOXRIGHT] - || tmbbox[BOXTOP] <= ld->bbox[BOXBOTTOM] || tmbbox[BOXBOTTOM] >= ld->bbox[BOXTOP]) + if (tm.bbox[BOXRIGHT] <= ld->bbox[BOXLEFT] || tm.bbox[BOXLEFT] >= ld->bbox[BOXRIGHT] + || tm.bbox[BOXTOP] <= ld->bbox[BOXBOTTOM] || tm.bbox[BOXBOTTOM] >= ld->bbox[BOXTOP]) return BMIT_CONTINUE; - if (P_BoxOnLineSide(tmbbox, ld) != -1) + if (P_BoxOnLineSide(tm.bbox, ld) != -1) return BMIT_CONTINUE; - if (tmthing->flags & MF_PAPERCOLLISION) // Caution! Turning whilst up against a wall will get you stuck. You probably shouldn't give the player this flag. + if (tm.thing->flags & MF_PAPERCOLLISION) // Caution! Turning whilst up against a wall will get you stuck. You probably shouldn't give the player this flag. { fixed_t cosradius, sinradius; - cosradius = FixedMul(tmthing->radius, FINECOSINE(tmthing->angle>>ANGLETOFINESHIFT)); - sinradius = FixedMul(tmthing->radius, FINESINE(tmthing->angle>>ANGLETOFINESHIFT)); - if (P_PointOnLineSide(tmx - cosradius, tmy - sinradius, ld) - == P_PointOnLineSide(tmx + cosradius, tmy + sinradius, ld)) + cosradius = FixedMul(tm.thing->radius, FINECOSINE(tm.thing->angle>>ANGLETOFINESHIFT)); + sinradius = FixedMul(tm.thing->radius, FINESINE(tm.thing->angle>>ANGLETOFINESHIFT)); + if (P_PointOnLineSide(tm.x - cosradius, tm.y - sinradius, ld) + == P_PointOnLineSide(tm.x + cosradius, tm.y + sinradius, ld)) return BMIT_CONTINUE; // the line doesn't cross between collider's start or end #ifdef PAPER_COLLISIONCORRECTION { fixed_t dist; vertex_t result; angle_t langle; - P_ClosestPointOnLine(tmx, tmy, ld, &result); + P_ClosestPointOnLine(tm.x, tm.y, ld, &result); langle = R_PointToAngle2(ld->v1->x, ld->v1->y, ld->v2->x, ld->v2->y); - langle += ANGLE_90*(P_PointOnLineSide(tmx, tmy, ld) ? -1 : 1); - dist = abs(FixedMul(tmthing->radius, FINECOSINE((tmthing->angle - langle)>>ANGLETOFINESHIFT))); + langle += ANGLE_90*(P_PointOnLineSide(tm.x, tm.y, ld) ? -1 : 1); + dist = abs(FixedMul(tm.thing->radius, FINECOSINE((tm.thing->angle - langle)>>ANGLETOFINESHIFT))); cosradius = FixedMul(dist, FINECOSINE(langle>>ANGLETOFINESHIFT)); sinradius = FixedMul(dist, FINESINE(langle>>ANGLETOFINESHIFT)); - tmthing->flags |= MF_NOCLIP; - P_MoveOrigin(tmthing, result.x + cosradius - tmthing->momx, result.y + sinradius - tmthing->momy, tmthing->z); - tmthing->flags &= ~MF_NOCLIP; + tm.thing->flags |= MF_NOCLIP; + P_MoveOrigin(tm.thing, result.x + cosradius - tm.thing->momx, result.y + sinradius - tm.thing->momy, tm.thing->z); + tm.thing->flags &= ~MF_NOCLIP; } #endif } @@ -1711,11 +1721,11 @@ static BlockItReturn_t PIT_CheckLine(line_t *ld) // could be crossed in either order. // this line is out of the if so upper and lower textures can be hit by a splat - blockingline = ld; + tm.blockingline = ld; { - UINT8 shouldCollide = LUA_HookMobjLineCollide(tmthing, blockingline); // checks hook for thing's type - if (P_MobjWasRemoved(tmthing)) + UINT8 shouldCollide = LUA_HookMobjLineCollide(tm.thing, tm.blockingline); // checks hook for thing's type + if (P_MobjWasRemoved(tm.thing)) return BMIT_CONTINUE; // one of them was removed??? if (shouldCollide == 1) return BMIT_ABORT; // force collide @@ -1725,50 +1735,50 @@ static BlockItReturn_t PIT_CheckLine(line_t *ld) if (!ld->backsector) // one sided line { - if (P_PointOnLineSide(tmthing->x, tmthing->y, ld)) + if (P_PointOnLineSide(tm.thing->x, tm.thing->y, ld)) return BMIT_CONTINUE; // don't hit the back side return BMIT_ABORT; } - if (P_IsLineBlocking(ld, tmthing)) + if (P_IsLineBlocking(ld, tm.thing)) return BMIT_ABORT; // set openrange, opentop, openbottom - P_LineOpening(ld, tmthing); + P_LineOpening(ld, tm.thing); // adjust floor / ceiling heights - if (opentop < tmceilingz) + if (opentop < tm.ceilingz) { - tmceilingz = opentop; - ceilingline = ld; - tmceilingrover = openceilingrover; - tmceilingslope = opentopslope; - tmceilingpic = opentoppic; - tmceilingstep = openceilingstep; - if (thingtop == tmthing->ceilingz) + tm.ceilingz = opentop; + tm.ceilingline = ld; + tm.ceilingrover = openceilingrover; + tm.ceilingslope = opentopslope; + tm.ceilingpic = opentoppic; + tm.ceilingstep = openceilingstep; + if (thingtop == tm.thing->ceilingz) { - tmthing->ceilingdrop = openceilingdrop; + tm.thing->ceilingdrop = openceilingdrop; } } - if (openbottom > tmfloorz) + if (openbottom > tm.floorz) { - tmfloorz = openbottom; - tmfloorrover = openfloorrover; - tmfloorslope = openbottomslope; - tmfloorpic = openbottompic; - tmfloorstep = openfloorstep; - if (tmthing->z == tmthing->floorz) + tm.floorz = openbottom; + tm.floorrover = openfloorrover; + tm.floorslope = openbottomslope; + tm.floorpic = openbottompic; + tm.floorstep = openfloorstep; + if (tm.thing->z == tm.thing->floorz) { - tmthing->floordrop = openfloordrop; + tm.thing->floordrop = openfloordrop; } } - if (highceiling > tmdrpoffceilz) - tmdrpoffceilz = highceiling; + if (highceiling > tm.drpoffceilz) + tm.drpoffceilz = highceiling; - if (lowfloor < tmdropoffz) - tmdropoffz = lowfloor; + if (lowfloor < tm.dropoffz) + tm.dropoffz = lowfloor; // we've crossed the line if (P_SpecialIsLinedefCrossType(ld)) @@ -1779,14 +1789,14 @@ static BlockItReturn_t PIT_CheckLine(line_t *ld) { fixed_t textop, texbottom; - P_GetMidtextureTopBottom(ld, tmx, tmy, + P_GetMidtextureTopBottom(ld, tm.x, tm.y, &textop, &texbottom); /* The effect handling is done later but it won't know the height values anymore. So don't even add this line to the list unless this thing clips the tripwire's midtexture. */ - if (tmthing->z <= textop && thingtop >= texbottom) + if (tm.thing->z <= textop && thingtop >= texbottom) add_spechit(ld); } @@ -1813,22 +1823,22 @@ static BlockItReturn_t PIT_CheckLine(line_t *ld) // // out: // newsubsec -// tmfloorz -// tmceilingz -// tmdropoffz -// tmdrpoffceilz +// tm.floorz +// tm.ceilingz +// tm.dropoffz +// tm.drpoffceilz // the lowest point contacted // (monsters won't move to a dropoff) // speciallines[] // numspeciallines // -// tmfloorz -// the nearest floor or thing's top under tmthing -// tmceilingz -// the nearest ceiling or thing's bottom over tmthing +// tm.floorz +// the nearest floor or thing's top under tm.thing +// tm.ceilingz +// the nearest ceiling or thing's bottom over tm.thing // -boolean P_CheckPosition(mobj_t *thing, fixed_t x, fixed_t y) +boolean P_CheckPosition(mobj_t *thing, fixed_t x, fixed_t y, TryMoveResult_t *result) { INT32 thingtop = thing->z + thing->height; INT32 xl, xh, yl, yh, bx, by; @@ -1843,35 +1853,35 @@ boolean P_CheckPosition(mobj_t *thing, fixed_t x, fixed_t y) I_Error("Previously-removed Thing of type %u crashes P_CheckPosition!", thing->type); #endif - P_SetTarget(&tmthing, thing); - tmflags = thing->flags; + P_SetTarget(&tm.thing, thing); + tm.flags = thing->flags; - tmx = x; - tmy = y; + tm.x = x; + tm.y = y; - tmbbox[BOXTOP] = y + tmthing->radius; - tmbbox[BOXBOTTOM] = y - tmthing->radius; - tmbbox[BOXRIGHT] = x + tmthing->radius; - tmbbox[BOXLEFT] = x - tmthing->radius; + tm.bbox[BOXTOP] = y + tm.thing->radius; + tm.bbox[BOXBOTTOM] = y - tm.thing->radius; + tm.bbox[BOXRIGHT] = x + tm.thing->radius; + tm.bbox[BOXLEFT] = x - tm.thing->radius; newsubsec = R_PointInSubsector(x, y); - ceilingline = blockingline = NULL; + tm.ceilingline = tm.blockingline = NULL; // The base floor / ceiling is from the subsector // that contains the point. // Any contacted lines the step closer together // will adjust them. - tmfloorz = tmdropoffz = P_GetFloorZ(thing, newsubsec->sector, x, y, NULL); //newsubsec->sector->floorheight; - tmceilingz = P_GetCeilingZ(thing, newsubsec->sector, x, y, NULL); //newsubsec->sector->ceilingheight; - tmfloorrover = NULL; - tmceilingrover = NULL; - tmfloorslope = newsubsec->sector->f_slope; - tmceilingslope = newsubsec->sector->c_slope; - tmfloorpic = newsubsec->sector->floorpic; - tmceilingpic = newsubsec->sector->ceilingpic; + tm.floorz = tm.dropoffz = P_GetFloorZ(thing, newsubsec->sector, x, y, NULL); //newsubsec->sector->floorheight; + tm.ceilingz = P_GetCeilingZ(thing, newsubsec->sector, x, y, NULL); //newsubsec->sector->ceilingheight; + tm.floorrover = NULL; + tm.ceilingrover = NULL; + tm.floorslope = newsubsec->sector->f_slope; + tm.ceilingslope = newsubsec->sector->c_slope; + tm.floorpic = newsubsec->sector->floorpic; + tm.ceilingpic = newsubsec->sector->ceilingpic; - tmfloorstep = 0; - tmceilingstep = 0; + tm.floorstep = 0; + tm.ceilingstep = 0; if (thingtop < thing->ceilingz) { @@ -1883,7 +1893,7 @@ boolean P_CheckPosition(mobj_t *thing, fixed_t x, fixed_t y) thing->floordrop = 0; } - // Check list of fake floors and see if tmfloorz/tmceilingz need to be altered. + // Check list of fake floors and see if tm.floorz/tm.ceilingz need to be altered. if (newsubsec->sector->ffloors) { ffloor_t *rover; @@ -1918,20 +1928,22 @@ boolean P_CheckPosition(mobj_t *thing, fixed_t x, fixed_t y) // Land on the top or the bottom, depending on gravity flip. if (!(thing->eflags & MFE_VERTICALFLIP) && thing->z >= topheight - sinklevel && thing->momz <= 0) { - if (tmfloorz < topheight - sinklevel) { - tmfloorz = topheight - sinklevel; - tmfloorrover = rover; - tmfloorslope = *rover->t_slope; - tmfloorpic = *rover->toppic; + if (tm.floorz < topheight - sinklevel) + { + tm.floorz = topheight - sinklevel; + tm.floorrover = rover; + tm.floorslope = *rover->t_slope; + tm.floorpic = *rover->toppic; } } else if (thing->eflags & MFE_VERTICALFLIP && thingtop <= bottomheight + sinklevel && thing->momz >= 0) { - if (tmceilingz > bottomheight + sinklevel) { - tmceilingz = bottomheight + sinklevel; - tmceilingrover = rover; - tmceilingslope = *rover->b_slope; - tmceilingpic = *rover->bottompic; + if (tm.ceilingz > bottomheight + sinklevel) + { + tm.ceilingz = bottomheight + sinklevel; + tm.ceilingrover = rover; + tm.ceilingslope = *rover->b_slope; + tm.ceilingpic = *rover->bottompic; } } } @@ -1951,11 +1963,12 @@ boolean P_CheckPosition(mobj_t *thing, fixed_t x, fixed_t y) { if (thing->z < topheight && bottomheight < thingtop) { - if (tmfloorz < thing->z) { - tmfloorz = thing->z; - tmfloorrover = rover; - tmfloorslope = NULL; - tmfloorpic = *rover->toppic; + if (tm.floorz < thing->z) + { + tm.floorz = thing->z; + tm.floorrover = rover; + tm.floorslope = NULL; + tm.floorpic = *rover->toppic; } } // Quicksand blocks never change heights otherwise. @@ -1967,22 +1980,23 @@ boolean P_CheckPosition(mobj_t *thing, fixed_t x, fixed_t y) delta2 = thingtop - (bottomheight + ((topheight - bottomheight)/2)); - if (topheight > tmfloorz && abs(delta1) < abs(delta2) + if (topheight > tm.floorz && abs(delta1) < abs(delta2) && !(rover->fofflags & FOF_REVERSEPLATFORM)) { - tmfloorz = tmdropoffz = topheight; - tmfloorrover = rover; - tmfloorslope = *rover->t_slope; - tmfloorpic = *rover->toppic; + tm.floorz = tm.dropoffz = topheight; + tm.floorrover = rover; + tm.floorslope = *rover->t_slope; + tm.floorpic = *rover->toppic; } - if (bottomheight < tmceilingz && abs(delta1) >= abs(delta2) + + if (bottomheight < tm.ceilingz && abs(delta1) >= abs(delta2) && !(rover->fofflags & FOF_PLATFORM) && !(thing->type == MT_SKIM && (rover->fofflags & FOF_SWIMMABLE))) { - tmceilingz = tmdrpoffceilz = bottomheight; - tmceilingrover = rover; - tmceilingslope = *rover->b_slope; - tmceilingpic = *rover->bottompic; + tm.ceilingz = tm.drpoffceilz = bottomheight; + tm.ceilingrover = rover; + tm.ceilingslope = *rover->b_slope; + tm.ceilingpic = *rover->bottompic; } } } @@ -1992,18 +2006,19 @@ boolean P_CheckPosition(mobj_t *thing, fixed_t x, fixed_t y) // based on their origin point, and can overlap // into adjacent blocks by up to MAXRADIUS units. - xl = (unsigned)(tmbbox[BOXLEFT] - bmaporgx - MAXRADIUS)>>MAPBLOCKSHIFT; - xh = (unsigned)(tmbbox[BOXRIGHT] - bmaporgx + MAXRADIUS)>>MAPBLOCKSHIFT; - yl = (unsigned)(tmbbox[BOXBOTTOM] - bmaporgy - MAXRADIUS)>>MAPBLOCKSHIFT; - yh = (unsigned)(tmbbox[BOXTOP] - bmaporgy + MAXRADIUS)>>MAPBLOCKSHIFT; + xl = (unsigned)(tm.bbox[BOXLEFT] - bmaporgx - MAXRADIUS)>>MAPBLOCKSHIFT; + xh = (unsigned)(tm.bbox[BOXRIGHT] - bmaporgx + MAXRADIUS)>>MAPBLOCKSHIFT; + yl = (unsigned)(tm.bbox[BOXBOTTOM] - bmaporgy - MAXRADIUS)>>MAPBLOCKSHIFT; + yh = (unsigned)(tm.bbox[BOXTOP] - bmaporgy + MAXRADIUS)>>MAPBLOCKSHIFT; BMBOUNDFIX(xl, xh, yl, yh); - // Check polyobjects and see if tmfloorz/tmceilingz need to be altered + // Check polyobjects and see if tm.floorz/tm.ceilingz need to be altered { validcount++; for (by = yl; by <= yh; by++) + { for (bx = xl; bx <= xh; bx++) { INT32 offset; @@ -2029,7 +2044,7 @@ boolean P_CheckPosition(mobj_t *thing, fixed_t x, fixed_t y) po->validcount = validcount; - if (!P_BBoxInsidePolyobj(po, tmbbox) + if (!P_BBoxInsidePolyobj(po, tm.bbox) || !(po->flags & POF_SOLID)) { plink = (polymaplink_t *)(plink->link.next); @@ -2053,35 +2068,38 @@ boolean P_CheckPosition(mobj_t *thing, fixed_t x, fixed_t y) delta1 = thing->z - (polybottom + ((polytop - polybottom)/2)); delta2 = thingtop - (polybottom + ((polytop - polybottom)/2)); - if (polytop > tmfloorz && abs(delta1) < abs(delta2)) { - tmfloorz = tmdropoffz = polytop; - tmfloorslope = NULL; - tmfloorrover = NULL; - tmfloorpic = polysec->ceilingpic; + if (polytop > tm.floorz && abs(delta1) < abs(delta2)) + { + tm.floorz = tm.dropoffz = polytop; + tm.floorslope = NULL; + tm.floorrover = NULL; + tm.floorpic = polysec->ceilingpic; } - if (polybottom < tmceilingz && abs(delta1) >= abs(delta2)) { - tmceilingz = tmdrpoffceilz = polybottom; - tmceilingslope = NULL; - tmceilingrover = NULL; - tmceilingpic = polysec->floorpic; + if (polybottom < tm.ceilingz && abs(delta1) >= abs(delta2)) + { + tm.ceilingz = tm.drpoffceilz = polybottom; + tm.ceilingslope = NULL; + tm.ceilingrover = NULL; + tm.ceilingpic = polysec->floorpic; } } plink = (polymaplink_t *)(plink->link.next); } } + } } - // tmfloorthing is set when tmfloorz comes from a thing's top - tmfloorthing = NULL; - tmhitthing = NULL; + // tm.floorthing is set when tm.floorz comes from a thing's top + P_SetTarget(&tm.floorthing, NULL); + P_SetTarget(&tm.hitthing, NULL); validcount++; // reset special lines numspechit = 0U; - if (tmflags & MF_NOCLIP) + if (tm.flags & MF_NOCLIP) return true; // Check things first, possibly picking things up. @@ -2090,24 +2108,45 @@ boolean P_CheckPosition(mobj_t *thing, fixed_t x, fixed_t y) if (!(thing->flags & MF_NOCLIPTHING)) { for (bx = xl; bx <= xh; bx++) + { for (by = yl; by <= yh; by++) { if (!P_BlockThingsIterator(bx, by, PIT_CheckThing)) + { blockval = false; + } else - tmhitthing = tmfloorthing; - if (P_MobjWasRemoved(tmthing)) + { + P_SetTarget(&tm.hitthing, tm.floorthing); + } + + if (P_MobjWasRemoved(tm.thing)) + { return false; + } } + } } validcount++; // check lines for (bx = xl; bx <= xh; bx++) + { for (by = yl; by <= yh; by++) + { if (!P_BlockLinesIterator(bx, by, PIT_CheckLine)) + { blockval = false; + } + } + } + + if (result != NULL) + { + result->line = tm.blockingline; + result->mo = tm.hitthing; + } return blockval; } @@ -2147,23 +2186,23 @@ boolean P_CheckCameraPosition(fixed_t x, fixed_t y, camera_t *thiscam) INT32 xl, xh, yl, yh, bx, by; subsector_t *newsubsec; - tmx = x; - tmy = y; + tm.x = x; + tm.y = y; - tmbbox[BOXTOP] = y + thiscam->radius; - tmbbox[BOXBOTTOM] = y - thiscam->radius; - tmbbox[BOXRIGHT] = x + thiscam->radius; - tmbbox[BOXLEFT] = x - thiscam->radius; + tm.bbox[BOXTOP] = y + thiscam->radius; + tm.bbox[BOXBOTTOM] = y - thiscam->radius; + tm.bbox[BOXRIGHT] = x + thiscam->radius; + tm.bbox[BOXLEFT] = x - thiscam->radius; newsubsec = R_PointInSubsector(x, y); - ceilingline = blockingline = NULL; + tm.ceilingline = tm.blockingline = NULL; mapcampointer = thiscam; if (newsubsec->sector->flags & MSF_NOCLIPCAMERA) { // Camera noclip on entire sector. - tmfloorz = tmdropoffz = thiscam->z; - tmceilingz = tmdrpoffceilz = thiscam->z + thiscam->height; + tm.floorz = tm.dropoffz = thiscam->z; + tm.ceilingz = tm.drpoffceilz = thiscam->z + thiscam->height; return true; } @@ -2171,26 +2210,26 @@ boolean P_CheckCameraPosition(fixed_t x, fixed_t y, camera_t *thiscam) // that contains the point. // Any contacted lines the step closer together // will adjust them. - tmfloorz = tmdropoffz = P_CameraGetFloorZ(thiscam, newsubsec->sector, x, y, NULL); + tm.floorz = tm.dropoffz = P_CameraGetFloorZ(thiscam, newsubsec->sector, x, y, NULL); - tmceilingz = P_CameraGetCeilingZ(thiscam, newsubsec->sector, x, y, NULL); + tm.ceilingz = P_CameraGetCeilingZ(thiscam, newsubsec->sector, x, y, NULL); // Cameras use the heightsec's heights rather then the actual sector heights. // If you can see through it, why not move the camera through it too? if (newsubsec->sector->heightsec >= 0) { - tmfloorz = tmdropoffz = sectors[newsubsec->sector->heightsec].floorheight; - tmceilingz = tmdrpoffceilz = sectors[newsubsec->sector->heightsec].ceilingheight; + tm.floorz = tm.dropoffz = sectors[newsubsec->sector->heightsec].floorheight; + tm.ceilingz = tm.drpoffceilz = sectors[newsubsec->sector->heightsec].ceilingheight; } // Use preset camera clipping heights if set with Sector Special Parameters whose control sector has Camera Intangible special -Red if (newsubsec->sector->camsec >= 0) { - tmfloorz = tmdropoffz = sectors[newsubsec->sector->camsec].floorheight; - tmceilingz = tmdrpoffceilz = sectors[newsubsec->sector->camsec].ceilingheight; + tm.floorz = tm.dropoffz = sectors[newsubsec->sector->camsec].floorheight; + tm.ceilingz = tm.drpoffceilz = sectors[newsubsec->sector->camsec].ceilingheight; } - // Check list of fake floors and see if tmfloorz/tmceilingz need to be altered. + // Check list of fake floors and see if tm.floorz/tm.ceilingz need to be altered. if (newsubsec->sector->ffloors) { ffloor_t *rover; @@ -2210,13 +2249,13 @@ boolean P_CheckCameraPosition(fixed_t x, fixed_t y, camera_t *thiscam) + ((topheight - bottomheight)/2)); delta2 = thingtop - (bottomheight + ((topheight - bottomheight)/2)); - if (topheight > tmfloorz && abs(delta1) < abs(delta2)) + if (topheight > tm.floorz && abs(delta1) < abs(delta2)) { - tmfloorz = tmdropoffz = topheight; + tm.floorz = tm.dropoffz = topheight; } - if (bottomheight < tmceilingz && abs(delta1) >= abs(delta2)) + if (bottomheight < tm.ceilingz && abs(delta1) >= abs(delta2)) { - tmceilingz = tmdrpoffceilz = bottomheight; + tm.ceilingz = tm.drpoffceilz = bottomheight; } } } @@ -2226,14 +2265,14 @@ boolean P_CheckCameraPosition(fixed_t x, fixed_t y, camera_t *thiscam) // based on their origin point, and can overlap // into adjacent blocks by up to MAXRADIUS units. - xl = (unsigned)(tmbbox[BOXLEFT] - bmaporgx)>>MAPBLOCKSHIFT; - xh = (unsigned)(tmbbox[BOXRIGHT] - bmaporgx)>>MAPBLOCKSHIFT; - yl = (unsigned)(tmbbox[BOXBOTTOM] - bmaporgy)>>MAPBLOCKSHIFT; - yh = (unsigned)(tmbbox[BOXTOP] - bmaporgy)>>MAPBLOCKSHIFT; + xl = (unsigned)(tm.bbox[BOXLEFT] - bmaporgx)>>MAPBLOCKSHIFT; + xh = (unsigned)(tm.bbox[BOXRIGHT] - bmaporgx)>>MAPBLOCKSHIFT; + yl = (unsigned)(tm.bbox[BOXBOTTOM] - bmaporgy)>>MAPBLOCKSHIFT; + yh = (unsigned)(tm.bbox[BOXTOP] - bmaporgy)>>MAPBLOCKSHIFT; BMBOUNDFIX(xl, xh, yl, yh); - // Check polyobjects and see if tmfloorz/tmceilingz need to be altered + // Check polyobjects and see if tm.floorz/tm.ceilingz need to be altered { validcount++; @@ -2293,11 +2332,11 @@ boolean P_CheckCameraPosition(fixed_t x, fixed_t y, camera_t *thiscam) delta1 = thiscam->z - (polybottom + ((polytop - polybottom)/2)); delta2 = thingtop - (polybottom + ((polytop - polybottom)/2)); - if (polytop > tmfloorz && abs(delta1) < abs(delta2)) - tmfloorz = tmdropoffz = polytop; + if (polytop > tm.floorz && abs(delta1) < abs(delta2)) + tm.floorz = tm.dropoffz = polytop; - if (polybottom < tmceilingz && abs(delta1) >= abs(delta2)) - tmceilingz = tmdrpoffceilz = polybottom; + if (polybottom < tm.ceilingz && abs(delta1) >= abs(delta2)) + tm.ceilingz = tm.drpoffceilz = polybottom; } plink = (polymaplink_t *)(plink->link.next); } @@ -2330,7 +2369,7 @@ boolean P_TryCameraMove(fixed_t x, fixed_t y, camera_t *thiscam) UINT8 i; - floatok = false; + tm.floatok = false; for (i = 0; i <= r_splitscreen; i++) { @@ -2354,7 +2393,7 @@ boolean P_TryCameraMove(fixed_t x, fixed_t y, camera_t *thiscam) if (!(players[displayplayers[i]].pflags & PF_NOCONTEST)) // Time Over should not clip through walls { - floatok = true; + tm.floatok = true; thiscam->floorz = thiscam->z; thiscam->ceilingz = thiscam->z + thiscam->height; thiscam->x = x; @@ -2380,18 +2419,18 @@ boolean P_TryCameraMove(fixed_t x, fixed_t y, camera_t *thiscam) if (!P_CheckCameraPosition(tryx, tryy, thiscam)) return false; // solid wall or thing - if (tmceilingz - tmfloorz < thiscam->height) + if (tm.ceilingz - tm.floorz < thiscam->height) return false; // doesn't fit - floatok = true; + tm.floatok = true; - if (tmceilingz - thiscam->z < thiscam->height) + if (tm.ceilingz - thiscam->z < thiscam->height) { - if (s == thiscam->subsector && tmceilingz >= thiscam->z) + if (s == thiscam->subsector && tm.ceilingz >= thiscam->z) { - floatok = true; - thiscam->floorz = tmfloorz; - thiscam->ceilingz = tmfloorz + thiscam->height; + tm.floatok = true; + thiscam->floorz = tm.floorz; + thiscam->ceilingz = tm.floorz + thiscam->height; thiscam->x = x; thiscam->y = y; thiscam->subsector = s; @@ -2401,21 +2440,21 @@ boolean P_TryCameraMove(fixed_t x, fixed_t y, camera_t *thiscam) return false; // mobj must lower itself to fit } - if ((tmfloorz - thiscam->z > MAXCAMERASTEPMOVE)) + if ((tm.floorz - thiscam->z > MAXCAMERASTEPMOVE)) return false; // too big a step up } while(tryx != x || tryy != y); } else { - tmfloorz = P_CameraGetFloorZ(thiscam, thiscam->subsector->sector, x, y, NULL); - tmceilingz = P_CameraGetCeilingZ(thiscam, thiscam->subsector->sector, x, y, NULL); + tm.floorz = P_CameraGetFloorZ(thiscam, thiscam->subsector->sector, x, y, NULL); + tm.ceilingz = P_CameraGetCeilingZ(thiscam, thiscam->subsector->sector, x, y, NULL); } // the move is ok, // so link the thing into its new position - thiscam->floorz = tmfloorz; - thiscam->ceilingz = tmceilingz; + thiscam->floorz = tm.floorz; + thiscam->ceilingz = tm.ceilingz; thiscam->x = x; thiscam->y = y; thiscam->subsector = s; @@ -2467,37 +2506,14 @@ BlockItReturn_t PIT_PushableMoved(mobj_t *thing) // These are all non-static map variables that are changed for each and every single mobj // See, changing player's momx/y would possibly trigger stuff as if the player were running somehow, so this must be done to keep the player standing // All this so players can ride gargoyles! - boolean oldfltok = floatok; - fixed_t oldflrz = tmfloorz; - fixed_t oldceilz = tmceilingz; - mobj_t *oldflrthing = tmfloorthing; - mobj_t *oldthing = tmthing; - line_t *oldceilline = ceilingline; - line_t *oldblockline = blockingline; - ffloor_t *oldflrrover = tmfloorrover; - ffloor_t *oldceilrover = tmceilingrover; - pslope_t *oldfslope = tmfloorslope; - pslope_t *oldcslope = tmceilingslope; - INT32 oldfpic = tmfloorpic; - INT32 oldcpic = tmceilingpic; + tm_t oldtm = tm; // Move the player - P_TryMove(thing, thing->x+stand->momx, thing->y+stand->momy, true); + P_TryMove(thing, thing->x + stand->momx, thing->y + stand->momy, true, NULL); // Now restore EVERYTHING so the gargoyle doesn't keep the player's tmstuff and break - floatok = oldfltok; - tmfloorz = oldflrz; - tmceilingz = oldceilz; - tmfloorthing = oldflrthing; - P_SetTarget(&tmthing, oldthing); - ceilingline = oldceilline; - blockingline = oldblockline; - tmfloorrover = oldflrrover; - tmceilingrover = oldceilrover; - tmfloorslope = oldfslope; - tmceilingslope = oldcslope; - tmfloorpic = oldfpic; - tmceilingpic = oldcpic; + P_RestoreTMStruct(oldtm); + thing->momz = stand->momz; } else @@ -2559,14 +2575,15 @@ increment_move fixed_t x, fixed_t y, boolean allowdropoff, - fixed_t * return_stairjank) + fixed_t * return_stairjank, + TryMoveResult_t * result) { fixed_t tryx = thing->x; fixed_t tryy = thing->y; fixed_t radius = thing->radius; fixed_t thingtop; fixed_t stairjank = 0; - floatok = false; + tm.floatok = false; // reset this to 0 at the start of each trymove call as it's only used here numspechitint = 0U; @@ -2578,14 +2595,6 @@ increment_move // And Big Large (tm) movements can skip over slopes. radius = min(radius, 16*mapobjectscale); -#if 0 - if (thing->hitlag > 0) - { - // Do not move during hitlag - return false; - } -#endif - do { if (thing->flags & MF_NOCLIP) { @@ -2609,25 +2618,30 @@ increment_move tryy = y; } - if (!P_CheckPosition(thing, tryx, tryy)) + if (!P_CheckPosition(thing, tryx, tryy, result)) + { return false; // solid wall or thing + } // copy into the spechitint buffer from spechit spechitint_copyinto(); if (!(thing->flags & MF_NOCLIP)) { - //All things are affected by their scale. + // All things are affected by their scale. fixed_t maxstep = P_GetThingStepUp(thing, tryx, tryy); - if (tmceilingz - tmfloorz < thing->height) + if (tm.ceilingz - tm.floorz < thing->height) { - if (tmfloorthing) - tmhitthing = tmfloorthing; + if (tm.floorthing != NULL) + { + P_SetTarget(&tm.hitthing, tm.floorthing); + } + return false; // doesn't fit } - floatok = true; + tm.floatok = true; if (maxstep > 0) { @@ -2637,15 +2651,15 @@ increment_move thingtop = thing->z + thing->height; // Step up - if (thing->z < tmfloorz) + if (thing->z < tm.floorz) { - if (tmfloorstep <= maxstep) + if (tm.floorstep <= maxstep) { if (!flipped) - stairjank = tmfloorstep; + stairjank = tm.floorstep; - thing->z = thing->floorz = tmfloorz; - thing->floorrover = tmfloorrover; + thing->z = thing->floorz = tm.floorz; + thing->floorrover = tm.floorrover; thing->eflags |= MFE_JUSTSTEPPEDDOWN; } else @@ -2653,15 +2667,15 @@ increment_move return false; // mobj must raise itself to fit } } - else if (tmceilingz < thingtop) + else if (tm.ceilingz < thingtop) { - if (tmceilingstep <= maxstep) + if (tm.ceilingstep <= maxstep) { if (flipped) - stairjank = tmceilingstep; + stairjank = tm.ceilingstep; - thing->z = ( thing->ceilingz = tmceilingz ) - thing->height; - thing->ceilingrover = tmceilingrover; + thing->z = ( thing->ceilingz = tm.ceilingz ) - thing->height; + thing->ceilingrover = tm.ceilingrover; thing->eflags |= MFE_JUSTSTEPPEDDOWN; } else @@ -2676,44 +2690,46 @@ increment_move // If the floor difference is MAXSTEPMOVE or less, and the sector isn't Section1:14, ALWAYS // step down! Formerly required a Section1:13 sector for the full MAXSTEPMOVE, but no more. - if (thingtop == thing->ceilingz && tmceilingz > thingtop && tmceilingz - thingtop <= maxstep) + if (thingtop == thing->ceilingz && tm.ceilingz > thingtop && tm.ceilingz - thingtop <= maxstep) { if (flipped) - stairjank = (tmceilingz - thingtop); + stairjank = (tm.ceilingz - thingtop); - thing->z = (thing->ceilingz = tmceilingz) - thing->height; - thing->ceilingrover = tmceilingrover; + thing->z = (thing->ceilingz = tm.ceilingz) - thing->height; + thing->ceilingrover = tm.ceilingrover; thing->eflags |= MFE_JUSTSTEPPEDDOWN; thing->ceilingdrop = 0; } - else if (thing->z == thing->floorz && tmfloorz < thing->z && thing->z - tmfloorz <= maxstep) + else if (thing->z == thing->floorz && tm.floorz < thing->z && thing->z - tm.floorz <= maxstep) { if (!flipped) - stairjank = (thing->z - tmfloorz); + stairjank = (thing->z - tm.floorz); - thing->z = thing->floorz = tmfloorz; - thing->floorrover = tmfloorrover; + thing->z = thing->floorz = tm.floorz; + thing->floorrover = tm.floorrover; thing->eflags |= MFE_JUSTSTEPPEDDOWN; thing->floordrop = 0; } } } - if (!allowdropoff && !(thing->flags & MF_FLOAT) && thing->type != MT_SKIM && !tmfloorthing) + if (!allowdropoff && !(thing->flags & MF_FLOAT) && thing->type != MT_SKIM && !tm.floorthing) { if (thing->eflags & MFE_VERTICALFLIP) { - if (tmdrpoffceilz - tmceilingz > maxstep) + if (tm.drpoffceilz - tm.ceilingz > maxstep) return false; } - else if (tmfloorz - tmdropoffz > maxstep) + else if (tm.floorz - tm.dropoffz > maxstep) return false; // don't stand over a dropoff } } } while (tryx != x || tryy != y); if (return_stairjank) + { *return_stairjank = stairjank; + } return true; } @@ -2722,15 +2738,15 @@ increment_move // P_CheckMove // Check if a P_TryMove would be successful. // -boolean P_CheckMove(mobj_t *thing, fixed_t x, fixed_t y, boolean allowdropoff) +boolean P_CheckMove(mobj_t *thing, fixed_t x, fixed_t y, boolean allowdropoff, TryMoveResult_t *result) { - boolean moveok; + boolean moveok = false; mobj_t *hack = P_SpawnMobjFromMobj(thing, 0, 0, 0, MT_RAY); hack->radius = thing->radius; hack->height = thing->height; - moveok = increment_move(hack, x, y, allowdropoff, NULL); + moveok = increment_move(hack, x, y, allowdropoff, NULL, result); P_RemoveMobj(hack); return moveok; @@ -2740,7 +2756,7 @@ boolean P_CheckMove(mobj_t *thing, fixed_t x, fixed_t y, boolean allowdropoff) // P_TryMove // Attempt to move to a new position. // -boolean P_TryMove(mobj_t *thing, fixed_t x, fixed_t y, boolean allowdropoff) +boolean P_TryMove(mobj_t *thing, fixed_t x, fixed_t y, boolean allowdropoff, TryMoveResult_t *result) { fixed_t oldx = thing->x; fixed_t oldy = thing->y; @@ -2748,9 +2764,15 @@ boolean P_TryMove(mobj_t *thing, fixed_t x, fixed_t y, boolean allowdropoff) fixed_t stairjank = 0; pslope_t *oldslope = thing->standingslope; - // The move is ok! - if (!increment_move(thing, x, y, allowdropoff, &stairjank)) + // Is the move OK? + if (increment_move(thing, x, y, allowdropoff, &stairjank, result) == false) + { + if (result != NULL) + { + result->success = false; + } return false; + } // If it's a pushable object, check if anything is // standing on top and move it, too. @@ -2777,21 +2799,21 @@ boolean P_TryMove(mobj_t *thing, fixed_t x, fixed_t y, boolean allowdropoff) // Link the thing into its new position P_UnsetThingPosition(thing); - thing->floorz = tmfloorz; - thing->ceilingz = tmceilingz; - thing->floorrover = tmfloorrover; - thing->ceilingrover = tmceilingrover; + thing->floorz = tm.floorz; + thing->ceilingz = tm.ceilingz; + thing->floorrover = tm.floorrover; + thing->ceilingrover = tm.ceilingrover; if (!(thing->flags & MF_NOCLIPHEIGHT)) { // Assign thing's standingslope if needed - if (thing->z <= tmfloorz && !(thing->eflags & MFE_VERTICALFLIP)) + if (thing->z <= tm.floorz && !(thing->eflags & MFE_VERTICALFLIP)) { - K_UpdateMobjTerrain(thing, tmfloorpic); + K_UpdateMobjTerrain(thing, tm.floorpic); - if (!startingonground && tmfloorslope) + if (!startingonground && tm.floorslope) { - P_HandleSlopeLanding(thing, tmfloorslope); + P_HandleSlopeLanding(thing, tm.floorslope); } if (thing->momz <= 0) @@ -2799,7 +2821,7 @@ boolean P_TryMove(mobj_t *thing, fixed_t x, fixed_t y, boolean allowdropoff) angle_t oldPitch = thing->pitch; angle_t oldRoll = thing->roll; - thing->standingslope = tmfloorslope; + thing->standingslope = tm.floorslope; P_SetPitchRollFromSlope(thing, thing->standingslope); if (thing->player) @@ -2808,13 +2830,13 @@ boolean P_TryMove(mobj_t *thing, fixed_t x, fixed_t y, boolean allowdropoff) } } } - else if (thing->z+thing->height >= tmceilingz && (thing->eflags & MFE_VERTICALFLIP)) + else if (thing->z+thing->height >= tm.ceilingz && (thing->eflags & MFE_VERTICALFLIP)) { - K_UpdateMobjTerrain(thing, tmceilingpic); + K_UpdateMobjTerrain(thing, tm.ceilingpic); - if (!startingonground && tmceilingslope) + if (!startingonground && tm.ceilingslope) { - P_HandleSlopeLanding(thing, tmceilingslope); + P_HandleSlopeLanding(thing, tm.ceilingslope); } if (thing->momz >= 0) @@ -2822,7 +2844,7 @@ boolean P_TryMove(mobj_t *thing, fixed_t x, fixed_t y, boolean allowdropoff) angle_t oldPitch = thing->pitch; angle_t oldRoll = thing->roll; - thing->standingslope = tmceilingslope; + thing->standingslope = tm.ceilingslope; P_SetPitchRollFromSlope(thing, thing->standingslope); if (thing->player) @@ -2869,7 +2891,7 @@ boolean P_TryMove(mobj_t *thing, fixed_t x, fixed_t y, boolean allowdropoff) thing->x = x; thing->y = y; - if (tmfloorthing) + if (tm.floorthing) thing->eflags &= ~MFE_ONGROUND; // not on real floor else thing->eflags |= MFE_ONGROUND; @@ -2896,10 +2918,15 @@ boolean P_TryMove(mobj_t *thing, fixed_t x, fixed_t y, boolean allowdropoff) } } + if (result != NULL) + { + result->success = true; + } + return true; } -boolean P_SceneryTryMove(mobj_t *thing, fixed_t x, fixed_t y) +boolean P_SceneryTryMove(mobj_t *thing, fixed_t x, fixed_t y, TryMoveResult_t *result) { fixed_t tryx, tryy; @@ -2919,20 +2946,20 @@ boolean P_SceneryTryMove(mobj_t *thing, fixed_t x, fixed_t y) else tryy = y; - if (!P_CheckPosition(thing, tryx, tryy)) + if (!P_CheckPosition(thing, tryx, tryy, result)) return false; // solid wall or thing if (!(thing->flags & MF_NOCLIP)) { const fixed_t maxstep = P_BaseStepUp(); - if (tmceilingz - tmfloorz < thing->height) + if (tm.ceilingz - tm.floorz < thing->height) return false; // doesn't fit - if (tmceilingz - thing->z < thing->height) + if (tm.ceilingz - thing->z < thing->height) return false; // mobj must lower itself to fit - if (tmfloorz - thing->z > maxstep) + if (tm.floorz - thing->z > maxstep) return false; // too big a step up } } while(tryx != x || tryy != y); @@ -2941,14 +2968,14 @@ boolean P_SceneryTryMove(mobj_t *thing, fixed_t x, fixed_t y) // so link the thing into its new position P_UnsetThingPosition(thing); - thing->floorz = tmfloorz; - thing->ceilingz = tmceilingz; - thing->floorrover = tmfloorrover; - thing->ceilingrover = tmceilingrover; + thing->floorz = tm.floorz; + thing->ceilingz = tm.ceilingz; + thing->floorrover = tm.floorrover; + thing->ceilingrover = tm.ceilingrover; thing->x = x; thing->y = y; - if (tmfloorthing) + if (tm.floorthing) thing->eflags &= ~MFE_ONGROUND; // not on real floor else thing->eflags |= MFE_ONGROUND; @@ -3071,22 +3098,22 @@ static boolean P_ThingHeightClip(mobj_t *thing) if (thing->flags & MF_NOCLIPHEIGHT) return true; - P_CheckPosition(thing, thing->x, thing->y); + P_CheckPosition(thing, thing->x, thing->y, NULL); if (P_MobjWasRemoved(thing)) return true; - floormoved = (thing->eflags & MFE_VERTICALFLIP && tmceilingz != thing->ceilingz) - || (!(thing->eflags & MFE_VERTICALFLIP) && tmfloorz != thing->floorz); + floormoved = (thing->eflags & MFE_VERTICALFLIP && tm.ceilingz != thing->ceilingz) + || (!(thing->eflags & MFE_VERTICALFLIP) && tm.floorz != thing->floorz); - thing->floorz = tmfloorz; - thing->ceilingz = tmceilingz; - thing->floorrover = tmfloorrover; - thing->ceilingrover = tmceilingrover; + thing->floorz = tm.floorz; + thing->ceilingz = tm.ceilingz; + thing->floorrover = tm.floorrover; + thing->ceilingrover = tm.ceilingrover; // Ugly hack?!?! As long as just ceilingz is the lowest, // you'll still get crushed, right? - if (tmfloorz > oldfloorz+thing->height) + if (tm.floorz > oldfloorz+thing->height) return true; if (onfloor && !(thing->flags & MF_NOGRAVITY) && floormoved) @@ -3110,15 +3137,15 @@ static boolean P_ThingHeightClip(mobj_t *thing) thing->z = thing->floorz; } } - else if (!tmfloorthing) + else if (!tm.floorthing) { // don't adjust a floating monster unless forced to if (thing->eflags & MFE_VERTICALFLIP) { - if (!onfloor && thing->z < tmfloorz) + if (!onfloor && thing->z < tm.floorz) thing->z = thing->floorz; } - else if (!onfloor && thing->z + thing->height > tmceilingz) + else if (!onfloor && thing->z + thing->height > tm.ceilingz) thing->z = thing->ceilingz - thing->height; } @@ -3199,42 +3226,25 @@ static void P_HitCameraSlideLine(line_t *ld, camera_t *thiscam) static void P_HitSlideLine(line_t *ld) { INT32 side; - angle_t lineangle, moveangle, deltaangle; - fixed_t movelen, newlen; - - if (ld->slopetype == ST_HORIZONTAL) - { - tmymove = 0; - return; - } - - if (ld->slopetype == ST_VERTICAL) - { - tmxmove = 0; - return; - } + angle_t lineangle; + fixed_t nx, ny; + fixed_t d; side = P_PointOnLineSide(slidemo->x, slidemo->y, ld); - - lineangle = ld->angle; + lineangle = ld->angle - ANGLE_90; if (side == 1) lineangle += ANGLE_180; - moveangle = R_PointToAngle2(0, 0, tmxmove, tmymove); - deltaangle = moveangle-lineangle; - - if (deltaangle > ANGLE_180) - deltaangle += ANGLE_180; - lineangle >>= ANGLETOFINESHIFT; - deltaangle >>= ANGLETOFINESHIFT; - movelen = R_PointToDist2(0, 0, tmxmove, tmymove); - newlen = FixedMul(movelen, FINECOSINE(deltaangle)); + nx = FINECOSINE(lineangle); + ny = FINESINE(lineangle); - tmxmove = FixedMul(newlen, FINECOSINE(lineangle)); - tmymove = FixedMul(newlen, FINESINE(lineangle)); + d = FixedMul(tmxmove, nx) + FixedMul(tmymove, ny); + + tmxmove -= FixedMul(nx, d); + tmymove -= FixedMul(ny, d); } // @@ -3368,6 +3378,7 @@ isblocking: return false; // stop } +/* static boolean PTR_LineIsBlocking(line_t *li) { // one-sided linedefs are always solid to sliding movement. @@ -3391,7 +3402,9 @@ static boolean PTR_LineIsBlocking(line_t *li) return false; } +*/ +/* static boolean PTR_SlideTraverse(intercept_t *in) { line_t *li; @@ -3421,6 +3434,7 @@ static boolean PTR_SlideTraverse(intercept_t *in) return false; // stop } +*/ // // P_SlideCameraMove @@ -3577,186 +3591,85 @@ static void P_CheckLavaWall(mobj_t *mo, sector_t *sec) // // This is a kludgy mess. // -void P_SlideMove(mobj_t *mo) +void P_SlideMove(mobj_t *mo, TryMoveResult_t *result) { - fixed_t leadx, leady, trailx, traily, newx, newy; - INT16 hitcount = 0; + fixed_t newx, newy; boolean success = false; - boolean papercol = false; vertex_t v1, v2; // fake vertexes line_t junk; // fake linedef if (P_MobjWasRemoved(mo)) return; - if (tmhitthing && mo->z + mo->height > tmhitthing->z && mo->z < tmhitthing->z + tmhitthing->height) + if (result == NULL) + return; + + if (result->mo && mo->z + mo->height > result->mo->z && mo->z < result->mo->z + result->mo->height) { // Don't mess with your momentum if it's a pushable object. Pushables do their own crazy things already. - if (tmhitthing->flags & MF_PUSHABLE) + if (result->mo->flags & MF_PUSHABLE) return; - if (tmhitthing->flags & MF_PAPERCOLLISION) + if (result->mo->flags & MF_PAPERCOLLISION) { - fixed_t cosradius, sinradius, num, den; + fixed_t cosradius, sinradius; - // trace along the three leading corners - if (mo->momx > 0) - { - leadx = mo->x + mo->radius; - trailx = mo->x - mo->radius; - } - else - { - leadx = mo->x - mo->radius; - trailx = mo->x + mo->radius; - } - - if (mo->momy > 0) - { - leady = mo->y + mo->radius; - traily = mo->y - mo->radius; - } - else - { - leady = mo->y - mo->radius; - traily = mo->y + mo->radius; - } - - papercol = true; slidemo = mo; bestslideline = &junk; - cosradius = FixedMul(tmhitthing->radius, FINECOSINE(tmhitthing->angle>>ANGLETOFINESHIFT)); - sinradius = FixedMul(tmhitthing->radius, FINESINE(tmhitthing->angle>>ANGLETOFINESHIFT)); + cosradius = FixedMul(result->mo->radius, FINECOSINE(result->mo->angle>>ANGLETOFINESHIFT)); + sinradius = FixedMul(result->mo->radius, FINESINE(result->mo->angle>>ANGLETOFINESHIFT)); - v1.x = tmhitthing->x - cosradius; - v1.y = tmhitthing->y - sinradius; - v2.x = tmhitthing->x + cosradius; - v2.y = tmhitthing->y + sinradius; + v1.x = result->mo->x - cosradius; + v1.y = result->mo->y - sinradius; + v2.x = result->mo->x + cosradius; + v2.y = result->mo->y + sinradius; - // Can we box collision our way into smooth movement..? - if (sinradius && mo->y + mo->radius <= min(v1.y, v2.y)) - { - mo->momy = 0; - P_TryMove(mo, mo->x + mo->momx, min(v1.y, v2.y) - mo->radius, true); - return; - } - else if (sinradius && mo->y - mo->radius >= max(v1.y, v2.y)) - { - mo->momy = 0; - P_TryMove(mo, mo->x + mo->momx, max(v1.y, v2.y) + mo->radius, true); - return; - } - else if (cosradius && mo->x + mo->radius <= min(v1.x, v2.x)) - { - mo->momx = 0; - P_TryMove(mo, min(v1.x, v2.x) - mo->radius, mo->y + mo->momy, true); - return; - } - else if (cosradius && mo->x - mo->radius >= max(v1.x, v2.x)) - { - mo->momx = 0; - P_TryMove(mo, max(v1.x, v2.x) + mo->radius, mo->y + mo->momy, true); - return; - } - - // nope, gotta fuck around with a fake linedef! + // gotta fuck around with a fake linedef! junk.v1 = &v1; junk.v2 = &v2; junk.dx = 2*cosradius; // v2.x - v1.x; junk.dy = 2*sinradius; // v2.y - v1.y; junk.slopetype = !cosradius ? ST_VERTICAL : !sinradius ? ST_HORIZONTAL : - ((sinradius > 0) == (cosradius > 0)) ? ST_POSITIVE : ST_NEGATIVE; - - bestslidefrac = FRACUNIT+1; - - den = FixedMul(junk.dy>>8, mo->momx) - FixedMul(junk.dx>>8, mo->momy); - - if (!den) - bestslidefrac = 0; - else - { - fixed_t frac; -#define P_PaperTraverse(startx, starty) \ - num = FixedMul((v1.x - leadx)>>8, junk.dy) + FixedMul((leady - v1.y)>>8, junk.dx); \ - frac = FixedDiv(num, den); \ - if (frac < bestslidefrac) \ - bestslidefrac = frac - P_PaperTraverse(leadx, leady); - P_PaperTraverse(trailx, leady); - P_PaperTraverse(leadx, traily); -#undef dowork - } + ((sinradius > 0) == (cosradius > 0)) ? ST_POSITIVE : ST_NEGATIVE; goto papercollision; } // Thankfully box collisions are a lot simpler than arbitrary lines. There's only four possible cases. - if (mo->y + mo->radius <= tmhitthing->y - tmhitthing->radius) + if (mo->y + mo->radius <= result->mo->y - result->mo->radius) { mo->momy = 0; - P_TryMove(mo, mo->x + mo->momx, tmhitthing->y - tmhitthing->radius - mo->radius, true); + P_TryMove(mo, mo->x + mo->momx, result->mo->y - result->mo->radius - mo->radius, true, NULL); } - else if (mo->y - mo->radius >= tmhitthing->y + tmhitthing->radius) + else if (mo->y - mo->radius >= result->mo->y + result->mo->radius) { mo->momy = 0; - P_TryMove(mo, mo->x + mo->momx, tmhitthing->y + tmhitthing->radius + mo->radius, true); + P_TryMove(mo, mo->x + mo->momx, result->mo->y + result->mo->radius + mo->radius, true, NULL); } - else if (mo->x + mo->radius <= tmhitthing->x - tmhitthing->radius) + else if (mo->x + mo->radius <= result->mo->x - result->mo->radius) { mo->momx = 0; - P_TryMove(mo, tmhitthing->x - tmhitthing->radius - mo->radius, mo->y + mo->momy, true); + P_TryMove(mo, result->mo->x - result->mo->radius - mo->radius, mo->y + mo->momy, true, NULL); } - else if (mo->x - mo->radius >= tmhitthing->x + tmhitthing->radius) + else if (mo->x - mo->radius >= result->mo->x + result->mo->radius) { mo->momx = 0; - P_TryMove(mo, tmhitthing->x + tmhitthing->radius + mo->radius, mo->y + mo->momy, true); + P_TryMove(mo, result->mo->x + result->mo->radius + mo->radius, mo->y + mo->momy, true, NULL); } else mo->momx = mo->momy = 0; + return; } slidemo = mo; - bestslideline = NULL; + bestslideline = result->line; -retry: - if ((++hitcount == 3) || papercol) - goto stairstep; // don't loop forever - - // trace along the three leading corners - if (mo->momx > 0) - { - leadx = mo->x + mo->radius; - trailx = mo->x - mo->radius; - } - else - { - leadx = mo->x - mo->radius; - trailx = mo->x + mo->radius; - } - - if (mo->momy > 0) - { - leady = mo->y + mo->radius; - traily = mo->y - mo->radius; - } - else - { - leady = mo->y - mo->radius; - traily = mo->y + mo->radius; - } - - bestslidefrac = FRACUNIT+1; - - P_PathTraverse(leadx, leady, leadx + mo->momx, leady + mo->momy, - PT_ADDLINES, PTR_SlideTraverse); - P_PathTraverse(trailx, leady, trailx + mo->momx, leady + mo->momy, - PT_ADDLINES, PTR_SlideTraverse); - P_PathTraverse(leadx, traily, leadx + mo->momx, traily + mo->momy, - PT_ADDLINES, PTR_SlideTraverse); + if (bestslideline == NULL) + return; if (bestslideline && mo->player && bestslideline->sidenum[1] != 0xffff) { @@ -3765,39 +3678,8 @@ retry: } papercollision: - // move up to the wall - if (bestslidefrac == FRACUNIT+1) - { - // the move must have hit the middle, so stairstep -stairstep: - if (!P_TryMove(mo, mo->x, mo->y + mo->momy, true)) //Allow things to drop off. - P_TryMove(mo, mo->x + mo->momx, mo->y, true); - return; - } - - // fudge a bit to make sure it doesn't hit - bestslidefrac -= 0x800; - if (bestslidefrac > 0) - { - newx = FixedMul(mo->momx, bestslidefrac); - newy = FixedMul(mo->momy, bestslidefrac); - - if (!P_TryMove(mo, mo->x + newx, mo->y + newy, true)) - goto stairstep; - } - - // Now continue along the wall. - // First calculate remainder. - bestslidefrac = FRACUNIT - (bestslidefrac+0x800); - - if (bestslidefrac > FRACUNIT) - bestslidefrac = FRACUNIT; - - if (bestslidefrac <= 0) - return; - - tmxmove = FixedMul(mo->momx, bestslidefrac); - tmymove = FixedMul(mo->momy, bestslidefrac); + tmxmove = mo->momx; + tmymove = mo->momy; P_HitSlideLine(bestslideline); // clip the moves @@ -3805,31 +3687,47 @@ stairstep: mo->momy = tmymove; do { - if (tmxmove > mo->radius) { + if (tmxmove > mo->radius) + { newx = mo->x + mo->radius; tmxmove -= mo->radius; - } else if (tmxmove < -mo->radius) { + } + else if (tmxmove < -mo->radius) + { newx = mo->x - mo->radius; tmxmove += mo->radius; - } else { + } + else + { newx = mo->x + tmxmove; tmxmove = 0; } - if (tmymove > mo->radius) { + + if (tmymove > mo->radius) + { newy = mo->y + mo->radius; tmymove -= mo->radius; - } else if (tmymove < -mo->radius) { + } + else if (tmymove < -mo->radius) + { newy = mo->y - mo->radius; tmymove += mo->radius; - } else { + } + else + { newy = mo->y + tmymove; tmymove = 0; } - if (!P_TryMove(mo, newx, newy, true)) { - if (success || P_MobjWasRemoved(mo)) + + if (!P_TryMove(mo, newx, newy, true, NULL)) + { + if (success || P_MobjWasRemoved(mo)) return; // Good enough!! - else - goto retry; + + // the move must have hit the middle, so stairstep + if (!P_TryMove(mo, mo->x, mo->y + mo->momy, true, NULL)) // Allow things to drop off. + P_TryMove(mo, mo->x + mo->momx, mo->y, true, NULL); + return; } success = true; } while(tmxmove || tmymove); @@ -3841,64 +3739,33 @@ stairstep: // Bounce move, for players. // -void P_BouncePlayerMove(mobj_t *mo) +static void P_BouncePlayerMove(mobj_t *mo, TryMoveResult_t *result) { - fixed_t leadx, leady; - fixed_t trailx, traily; fixed_t mmomx = 0, mmomy = 0; fixed_t oldmomx = mo->momx, oldmomy = mo->momy; - if (!mo->player) + if (P_MobjWasRemoved(mo) == true) + return; + + if (mo->player == NULL) + return; + + if (result == NULL) return; if (mo->player->spectator) { - P_SlideMove(mo); + P_SlideMove(mo, result); return; } - slidemo = mo; - mmomx = mo->player->rmomx; mmomy = mo->player->rmomy; - // trace along the three leading corners - if (mo->momx > 0) - { - leadx = mo->x + mo->radius; - trailx = mo->x - mo->radius; - } - else - { - leadx = mo->x - mo->radius; - trailx = mo->x + mo->radius; - } + slidemo = mo; + bestslideline = result->line; - if (mo->momy > 0) - { - leady = mo->y + mo->radius; - traily = mo->y - mo->radius; - } - else - { - leady = mo->y - mo->radius; - traily = mo->y + mo->radius; - } - - bestslidefrac = FRACUNIT + 1; - - P_PathTraverse(leadx, leady, leadx + mmomx, leady + mmomy, PT_ADDLINES, PTR_SlideTraverse); - P_PathTraverse(trailx, leady, trailx + mmomx, leady + mmomy, PT_ADDLINES, PTR_SlideTraverse); - P_PathTraverse(leadx, traily, leadx + mmomx, traily + mmomy, PT_ADDLINES, PTR_SlideTraverse); - - // Now continue along the wall. - // First calculate remainder. - bestslidefrac = FRACUNIT - bestslidefrac; - - if (bestslidefrac > FRACUNIT) - bestslidefrac = FRACUNIT; - - if (bestslidefrac <= 0) + if (bestslideline == NULL) return; if (mo->eflags & MFE_JUSTBOUNCEDWALL) // Stronger push-out @@ -3923,7 +3790,7 @@ void P_BouncePlayerMove(mobj_t *mo) if (bestslideline && (bestslideline->flags & ML_NOTBOUNCY)) { // SRB2Kart: Non-bouncy line! - P_SlideMove(mo); + P_SlideMove(mo, result); return; } @@ -3940,8 +3807,9 @@ void P_BouncePlayerMove(mobj_t *mo) if (!P_IsLineTripWire(bestslideline)) { - if (!P_TryMove(mo, mo->x + tmxmove, mo->y + tmymove, true)) { - P_TryMove(mo, mo->x - oldmomx, mo->y - oldmomy, true); + if (!P_TryMove(mo, mo->x + tmxmove, mo->y + tmymove, true, NULL)) + { + P_TryMove(mo, mo->x - oldmomx, mo->y - oldmomy, true, NULL); } } } @@ -3951,12 +3819,8 @@ void P_BouncePlayerMove(mobj_t *mo) // // The momx / momy move is bad, so try to bounce off a wall. // -void P_BounceMove(mobj_t *mo) +void P_BounceMove(mobj_t *mo, TryMoveResult_t *result) { - fixed_t leadx, leady; - fixed_t trailx, traily; - fixed_t newx, newy; - INT32 hitcount; fixed_t mmomx = 0, mmomy = 0; if (P_MobjWasRemoved(mo)) @@ -3964,89 +3828,23 @@ void P_BounceMove(mobj_t *mo) if (mo->player) { - P_BouncePlayerMove(mo); + P_BouncePlayerMove(mo, result); return; } if (mo->eflags & MFE_JUSTBOUNCEDWALL) { - P_SlideMove(mo); + P_SlideMove(mo, result); return; } - slidemo = mo; - hitcount = 0; - -retry: - if (++hitcount == 3) - goto bounceback; // don't loop forever - mmomx = mo->momx; mmomy = mo->momy; - // trace along the three leading corners - if (mo->momx > 0) - { - leadx = mo->x + mo->radius; - trailx = mo->x - mo->radius; - } - else - { - leadx = mo->x - mo->radius; - trailx = mo->x + mo->radius; - } + slidemo = mo; + bestslideline = result->line; - if (mo->momy > 0) - { - leady = mo->y + mo->radius; - traily = mo->y - mo->radius; - } - else - { - leady = mo->y - mo->radius; - traily = mo->y + mo->radius; - } - - bestslidefrac = FRACUNIT + 1; - - P_PathTraverse(leadx, leady, leadx + mmomx, leady + mmomy, PT_ADDLINES, PTR_SlideTraverse); - P_PathTraverse(trailx, leady, trailx + mmomx, leady + mmomy, PT_ADDLINES, PTR_SlideTraverse); - P_PathTraverse(leadx, traily, leadx + mmomx, traily + mmomy, PT_ADDLINES, PTR_SlideTraverse); - - // move up to the wall - if (bestslidefrac == FRACUNIT + 1) - { - // the move must have hit the middle, so bounce straight back -bounceback: - if (P_TryMove(mo, mo->x - mmomx, mo->y - mmomy, true)) - { - mo->momx *= -1; - mo->momy *= -1; - mo->momx = FixedMul(mo->momx, (FRACUNIT - (FRACUNIT>>2) - (FRACUNIT>>3))); - mo->momy = FixedMul(mo->momy, (FRACUNIT - (FRACUNIT>>2) - (FRACUNIT>>3))); - } - return; - } - - // fudge a bit to make sure it doesn't hit - bestslidefrac -= 0x800; - if (bestslidefrac > 0) - { - newx = FixedMul(mmomx, bestslidefrac); - newy = FixedMul(mmomy, bestslidefrac); - - if (!P_TryMove(mo, mo->x + newx, mo->y + newy, true)) - goto bounceback; - } - - // Now continue along the wall. - // First calculate remainder. - bestslidefrac = FRACUNIT - bestslidefrac; - - if (bestslidefrac > FRACUNIT) - bestslidefrac = FRACUNIT; - - if (bestslidefrac <= 0) + if (bestslideline == NULL) return; if (mo->type == MT_SHELL) @@ -4071,24 +3869,21 @@ bounceback: tmymove = FixedMul(mmomy, (FRACUNIT - (FRACUNIT>>2) - (FRACUNIT>>3))); } - // Some walls aren't bouncy even if you are - if (bestslideline && (bestslideline->flags & ML_NOTBOUNCY)) - { - // SRB2Kart: Non-bouncy line! - P_SlideMove(mo); - return; - } - P_HitBounceLine(bestslideline); // clip the moves mo->momx = tmxmove; mo->momy = tmymove; - if (!P_TryMove(mo, mo->x + tmxmove, mo->y + tmymove, true)) + if (!P_TryMove(mo, mo->x + tmxmove, mo->y + tmymove, true, NULL)) { if (P_MobjWasRemoved(mo)) return; - goto retry; + + // the move must have hit the middle, so bounce straight back + mo->momx *= -1; + mo->momy *= -1; + mo->momx = FixedMul(mo->momx, (FRACUNIT - (FRACUNIT>>2) - (FRACUNIT>>3))); + mo->momy = FixedMul(mo->momy, (FRACUNIT - (FRACUNIT>>2) - (FRACUNIT>>3))); } } @@ -4779,13 +4574,13 @@ void P_DelPrecipSeclist(mprecipsecnode_t *node) static inline BlockItReturn_t PIT_GetSectors(line_t *ld) { - if (tmbbox[BOXRIGHT] <= ld->bbox[BOXLEFT] || - tmbbox[BOXLEFT] >= ld->bbox[BOXRIGHT] || - tmbbox[BOXTOP] <= ld->bbox[BOXBOTTOM] || - tmbbox[BOXBOTTOM] >= ld->bbox[BOXTOP]) + if (tm.bbox[BOXRIGHT] <= ld->bbox[BOXLEFT] || + tm.bbox[BOXLEFT] >= ld->bbox[BOXRIGHT] || + tm.bbox[BOXTOP] <= ld->bbox[BOXBOTTOM] || + tm.bbox[BOXBOTTOM] >= ld->bbox[BOXTOP]) return BMIT_CONTINUE; - if (P_BoxOnLineSide(tmbbox, ld) != -1) + if (P_BoxOnLineSide(tm.bbox, ld) != -1) return BMIT_CONTINUE; if (ld->polyobj) // line belongs to a polyobject, don't add it @@ -4798,7 +4593,7 @@ static inline BlockItReturn_t PIT_GetSectors(line_t *ld) // allowed to move to this position, then the sector_list // will be attached to the Thing's mobj_t at touching_sectorlist. - sector_list = P_AddSecnode(ld->frontsector,tmthing,sector_list); + sector_list = P_AddSecnode(ld->frontsector,tm.thing,sector_list); // Don't assume all lines are 2-sided, since some Things // like MT_TFOG are allowed regardless of whether their radius takes @@ -4806,7 +4601,7 @@ static inline BlockItReturn_t PIT_GetSectors(line_t *ld) // Use sidedefs instead of 2s flag to determine two-sidedness. if (ld->backsector) - sector_list = P_AddSecnode(ld->backsector, tmthing, sector_list); + sector_list = P_AddSecnode(ld->backsector, tm.thing, sector_list); return BMIT_CONTINUE; } @@ -4814,13 +4609,13 @@ static inline BlockItReturn_t PIT_GetSectors(line_t *ld) // Tails 08-25-2002 static inline BlockItReturn_t PIT_GetPrecipSectors(line_t *ld) { - if (preciptmbbox[BOXRIGHT] <= ld->bbox[BOXLEFT] || - preciptmbbox[BOXLEFT] >= ld->bbox[BOXRIGHT] || - preciptmbbox[BOXTOP] <= ld->bbox[BOXBOTTOM] || - preciptmbbox[BOXBOTTOM] >= ld->bbox[BOXTOP]) + if (tm.precipbbox[BOXRIGHT] <= ld->bbox[BOXLEFT] || + tm.precipbbox[BOXLEFT] >= ld->bbox[BOXRIGHT] || + tm.precipbbox[BOXTOP] <= ld->bbox[BOXBOTTOM] || + tm.precipbbox[BOXBOTTOM] >= ld->bbox[BOXTOP]) return BMIT_CONTINUE; - if (P_BoxOnLineSide(preciptmbbox, ld) != -1) + if (P_BoxOnLineSide(tm.precipbbox, ld) != -1) return BMIT_CONTINUE; if (ld->polyobj) // line belongs to a polyobject, don't add it @@ -4833,7 +4628,7 @@ static inline BlockItReturn_t PIT_GetPrecipSectors(line_t *ld) // allowed to move to this position, then the sector_list // will be attached to the Thing's mobj_t at touching_sectorlist. - precipsector_list = P_AddPrecipSecnode(ld->frontsector, tmprecipthing, precipsector_list); + precipsector_list = P_AddPrecipSecnode(ld->frontsector, tm.precipthing, precipsector_list); // Don't assume all lines are 2-sided, since some Things // like MT_TFOG are allowed regardless of whether their radius takes @@ -4841,7 +4636,7 @@ static inline BlockItReturn_t PIT_GetPrecipSectors(line_t *ld) // Use sidedefs instead of 2s flag to determine two-sidedness. if (ld->backsector) - precipsector_list = P_AddPrecipSecnode(ld->backsector, tmprecipthing, precipsector_list); + precipsector_list = P_AddPrecipSecnode(ld->backsector, tm.precipthing, precipsector_list); return BMIT_CONTINUE; } @@ -4853,8 +4648,7 @@ void P_CreateSecNodeList(mobj_t *thing, fixed_t x, fixed_t y) { INT32 xl, xh, yl, yh, bx, by; msecnode_t *node = sector_list; - mobj_t *saved_tmthing = tmthing; /* cph - see comment at func end */ - fixed_t saved_tmx = tmx, saved_tmy = tmy; /* ditto */ + tm_t ptm = tm; /* cph - see comment at func end */ // First, clear out the existing m_thing fields. As each node is // added or verified as needed, m_thing will be set properly. When @@ -4867,23 +4661,23 @@ void P_CreateSecNodeList(mobj_t *thing, fixed_t x, fixed_t y) node = node->m_sectorlist_next; } - P_SetTarget(&tmthing, thing); - tmflags = thing->flags; + P_SetTarget(&tm.thing, thing); + tm.flags = thing->flags; - tmx = x; - tmy = y; + tm.x = x; + tm.y = y; - tmbbox[BOXTOP] = y + tmthing->radius; - tmbbox[BOXBOTTOM] = y - tmthing->radius; - tmbbox[BOXRIGHT] = x + tmthing->radius; - tmbbox[BOXLEFT] = x - tmthing->radius; + tm.bbox[BOXTOP] = y + tm.thing->radius; + tm.bbox[BOXBOTTOM] = y - tm.thing->radius; + tm.bbox[BOXRIGHT] = x + tm.thing->radius; + tm.bbox[BOXLEFT] = x - tm.thing->radius; validcount++; // used to make sure we only process a line once - xl = (unsigned)(tmbbox[BOXLEFT] - bmaporgx)>>MAPBLOCKSHIFT; - xh = (unsigned)(tmbbox[BOXRIGHT] - bmaporgx)>>MAPBLOCKSHIFT; - yl = (unsigned)(tmbbox[BOXBOTTOM] - bmaporgy)>>MAPBLOCKSHIFT; - yh = (unsigned)(tmbbox[BOXTOP] - bmaporgy)>>MAPBLOCKSHIFT; + xl = (unsigned)(tm.bbox[BOXLEFT] - bmaporgx)>>MAPBLOCKSHIFT; + xh = (unsigned)(tm.bbox[BOXRIGHT] - bmaporgx)>>MAPBLOCKSHIFT; + yl = (unsigned)(tm.bbox[BOXBOTTOM] - bmaporgy)>>MAPBLOCKSHIFT; + yh = (unsigned)(tm.bbox[BOXTOP] - bmaporgy)>>MAPBLOCKSHIFT; BMBOUNDFIX(xl, xh, yl, yh); @@ -4910,26 +4704,14 @@ void P_CreateSecNodeList(mobj_t *thing, fixed_t x, fixed_t y) } /* cph - - * This is the strife we get into for using global variables. tmthing + * This is the strife we get into for using global variables. tm.thing * is being used by several different functions calling * P_BlockThingIterator, including functions that can be called *from* - * P_BlockThingIterator. Using a global tmthing is not reentrant. + * P_BlockThingIterator. Using a global tm.thing is not reentrant. * OTOH for Boom/MBF demos we have to preserve the buggy behavior. * Fun. We restore its previous value unless we're in a Boom/MBF demo. */ - P_SetTarget(&tmthing, saved_tmthing); - - /* And, duh, the same for tmx/y - cph 2002/09/22 - * And for tmbbox - cph 2003/08/10 */ - tmx = saved_tmx, tmy = saved_tmy; - - if (tmthing) - { - tmbbox[BOXTOP] = tmy + tmthing->radius; - tmbbox[BOXBOTTOM] = tmy - tmthing->radius; - tmbbox[BOXRIGHT] = tmx + tmthing->radius; - tmbbox[BOXLEFT] = tmx - tmthing->radius; - } + P_RestoreTMStruct(ptm); } // More crazy crap Tails 08-25-2002 @@ -4937,7 +4719,7 @@ void P_CreatePrecipSecNodeList(precipmobj_t *thing,fixed_t x,fixed_t y) { INT32 xl, xh, yl, yh, bx, by; mprecipsecnode_t *node = precipsector_list; - precipmobj_t *saved_tmthing = tmprecipthing; /* cph - see comment at func end */ + tm_t ptm = tm; /* cph - see comment at func end */ // First, clear out the existing m_thing fields. As each node is // added or verified as needed, m_thing will be set properly. When @@ -4950,19 +4732,19 @@ void P_CreatePrecipSecNodeList(precipmobj_t *thing,fixed_t x,fixed_t y) node = node->m_sectorlist_next; } - tmprecipthing = thing; + tm.precipthing = thing; - preciptmbbox[BOXTOP] = y + 2*FRACUNIT; - preciptmbbox[BOXBOTTOM] = y - 2*FRACUNIT; - preciptmbbox[BOXRIGHT] = x + 2*FRACUNIT; - preciptmbbox[BOXLEFT] = x - 2*FRACUNIT; + tm.precipbbox[BOXTOP] = y + 2*FRACUNIT; + tm.precipbbox[BOXBOTTOM] = y - 2*FRACUNIT; + tm.precipbbox[BOXRIGHT] = x + 2*FRACUNIT; + tm.precipbbox[BOXLEFT] = x - 2*FRACUNIT; validcount++; // used to make sure we only process a line once - xl = (unsigned)(preciptmbbox[BOXLEFT] - bmaporgx)>>MAPBLOCKSHIFT; - xh = (unsigned)(preciptmbbox[BOXRIGHT] - bmaporgx)>>MAPBLOCKSHIFT; - yl = (unsigned)(preciptmbbox[BOXBOTTOM] - bmaporgy)>>MAPBLOCKSHIFT; - yh = (unsigned)(preciptmbbox[BOXTOP] - bmaporgy)>>MAPBLOCKSHIFT; + xl = (unsigned)(tm.precipbbox[BOXLEFT] - bmaporgx)>>MAPBLOCKSHIFT; + xh = (unsigned)(tm.precipbbox[BOXRIGHT] - bmaporgx)>>MAPBLOCKSHIFT; + yl = (unsigned)(tm.precipbbox[BOXBOTTOM] - bmaporgy)>>MAPBLOCKSHIFT; + yh = (unsigned)(tm.precipbbox[BOXTOP] - bmaporgy)>>MAPBLOCKSHIFT; BMBOUNDFIX(xl, xh, yl, yh); @@ -4989,27 +4771,27 @@ void P_CreatePrecipSecNodeList(precipmobj_t *thing,fixed_t x,fixed_t y) } /* cph - - * This is the strife we get into for using global variables. tmthing + * This is the strife we get into for using global variables. tm.thing * is being used by several different functions calling * P_BlockThingIterator, including functions that can be called *from* - * P_BlockThingIterator. Using a global tmthing is not reentrant. + * P_BlockThingIterator. Using a global tm.thing is not reentrant. * OTOH for Boom/MBF demos we have to preserve the buggy behavior. * Fun. We restore its previous value unless we're in a Boom/MBF demo. */ - tmprecipthing = saved_tmthing; + P_RestoreTMStruct(ptm); } /* cphipps 2004/08/30 - - * Must clear tmthing at tic end, as it might contain a pointer to a removed thinker, or the level might have ended/been ended and we clear the objects it was pointing too. Hopefully we don't need to carry this between tics for sync. */ + * Must clear tm.thing at tic end, as it might contain a pointer to a removed thinker, or the level might have ended/been ended and we clear the objects it was pointing too. Hopefully we don't need to carry this between tics for sync. */ void P_MapStart(void) { - if (tmthing) - I_Error("P_MapStart: tmthing set!"); + if (tm.thing) + I_Error("P_MapStart: tm.thing set!"); } void P_MapEnd(void) { - P_SetTarget(&tmthing, NULL); + P_SetTarget(&tm.thing, NULL); } // P_FloorzAtPos diff --git a/src/p_maputl.c b/src/p_maputl.c index ab810e437..7eb4a7e19 100644 --- a/src/p_maputl.c +++ b/src/p_maputl.c @@ -379,8 +379,8 @@ void P_CameraLineOpening(line_t *linedef) } else { - frontfloor = P_CameraGetFloorZ (mapcampointer, front, tmx, tmy, linedef); - frontceiling = P_CameraGetCeilingZ(mapcampointer, front, tmx, tmy, linedef); + frontfloor = P_CameraGetFloorZ (mapcampointer, front, tm.x, tm.y, linedef); + frontceiling = P_CameraGetCeilingZ(mapcampointer, front, tm.x, tm.y, linedef); } if (back->camsec >= 0) @@ -397,8 +397,8 @@ void P_CameraLineOpening(line_t *linedef) } else { - backfloor = P_CameraGetFloorZ(mapcampointer, back, tmx, tmy, linedef); - backceiling = P_CameraGetCeilingZ(mapcampointer, back, tmx, tmy, linedef); + backfloor = P_CameraGetFloorZ(mapcampointer, back, tm.x, tm.y, linedef); + backceiling = P_CameraGetCeilingZ(mapcampointer, back, tm.x, tm.y, linedef); } { @@ -440,8 +440,8 @@ void P_CameraLineOpening(line_t *linedef) if (!(rover->fofflags & FOF_BLOCKOTHERS) || !(rover->fofflags & FOF_RENDERALL) || !(rover->fofflags & FOF_EXISTS) || (rover->master->frontsector->flags & MSF_NOCLIPCAMERA)) continue; - topheight = P_CameraGetFOFTopZ(mapcampointer, front, rover, tmx, tmy, linedef); - bottomheight = P_CameraGetFOFBottomZ(mapcampointer, front, rover, tmx, tmy, linedef); + topheight = P_CameraGetFOFTopZ(mapcampointer, front, rover, tm.x, tm.y, linedef); + bottomheight = P_CameraGetFOFBottomZ(mapcampointer, front, rover, tm.x, tm.y, linedef); delta1 = abs(mapcampointer->z - (bottomheight + ((topheight - bottomheight)/2))); delta2 = abs(thingtop - (bottomheight + ((topheight - bottomheight)/2))); @@ -464,8 +464,8 @@ void P_CameraLineOpening(line_t *linedef) if (!(rover->fofflags & FOF_BLOCKOTHERS) || !(rover->fofflags & FOF_RENDERALL) || !(rover->fofflags & FOF_EXISTS) || (rover->master->frontsector->flags & MSF_NOCLIPCAMERA)) continue; - topheight = P_CameraGetFOFTopZ(mapcampointer, back, rover, tmx, tmy, linedef); - bottomheight = P_CameraGetFOFBottomZ(mapcampointer, back, rover, tmx, tmy, linedef); + topheight = P_CameraGetFOFTopZ(mapcampointer, back, rover, tm.x, tm.y, linedef); + bottomheight = P_CameraGetFOFBottomZ(mapcampointer, back, rover, tm.x, tm.y, linedef); delta1 = abs(mapcampointer->z - (bottomheight + ((topheight - bottomheight)/2))); delta2 = abs(thingtop - (bottomheight + ((topheight - bottomheight)/2))); @@ -614,7 +614,7 @@ void P_LineOpening(line_t *linedef, mobj_t *mobj) return; } - P_ClosestPointOnLine(tmx, tmy, linedef, &cross); + P_ClosestPointOnLine(tm.x, tm.y, linedef, &cross); // Treat polyobjects kind of like 3D Floors if (linedef->polyobj && (linedef->polyobj->flags & POF_TESTHEIGHT)) @@ -656,8 +656,8 @@ void P_LineOpening(line_t *linedef, mobj_t *mobj) fixed_t height[2]; const sector_t * sector[2] = { front, back }; - height[FRONT] = P_GetCeilingZ(mobj, front, tmx, tmy, linedef); - height[BACK] = P_GetCeilingZ(mobj, back, tmx, tmy, linedef); + height[FRONT] = P_GetCeilingZ(mobj, front, tm.x, tm.y, linedef); + height[BACK] = P_GetCeilingZ(mobj, back, tm.x, tm.y, linedef); hi = ( height[0] < height[1] ); lo = ! hi; @@ -676,8 +676,8 @@ void P_LineOpening(line_t *linedef, mobj_t *mobj) openceilingdrop = ( topedge[hi] - topedge[lo] ); } - height[FRONT] = P_GetFloorZ(mobj, front, tmx, tmy, linedef); - height[BACK] = P_GetFloorZ(mobj, back, tmx, tmy, linedef); + height[FRONT] = P_GetFloorZ(mobj, front, tm.x, tm.y, linedef); + height[BACK] = P_GetFloorZ(mobj, back, tm.x, tm.y, linedef); hi = ( height[0] < height[1] ); lo = ! hi; @@ -818,8 +818,8 @@ void P_LineOpening(line_t *linedef, mobj_t *mobj) || (rover->fofflags & FOF_BLOCKOTHERS && !mobj->player))) continue; - topheight = P_GetFOFTopZ(mobj, front, rover, tmx, tmy, linedef); - bottomheight = P_GetFOFBottomZ(mobj, front, rover, tmx, tmy, linedef); + topheight = P_GetFOFTopZ(mobj, front, rover, tm.x, tm.y, linedef); + bottomheight = P_GetFOFBottomZ(mobj, front, rover, tm.x, tm.y, linedef); delta1 = abs(mobj->z - (bottomheight + ((topheight - bottomheight)/2))); delta2 = abs(thingtop - (bottomheight + ((topheight - bottomheight)/2))); @@ -862,8 +862,8 @@ void P_LineOpening(line_t *linedef, mobj_t *mobj) || (rover->fofflags & FOF_BLOCKOTHERS && !mobj->player))) continue; - topheight = P_GetFOFTopZ(mobj, back, rover, tmx, tmy, linedef); - bottomheight = P_GetFOFBottomZ(mobj, back, rover, tmx, tmy, linedef); + topheight = P_GetFOFTopZ(mobj, back, rover, tm.x, tm.y, linedef); + bottomheight = P_GetFOFBottomZ(mobj, back, rover, tm.x, tm.y, linedef); delta1 = abs(mobj->z - (bottomheight + ((topheight - bottomheight)/2))); delta2 = abs(thingtop - (bottomheight + ((topheight - bottomheight)/2))); @@ -1596,16 +1596,16 @@ boolean P_RadiusLinesCheck(fixed_t radius, fixed_t x, fixed_t y, INT32 xl, xh, yl, yh; INT32 bx, by; - tmbbox[BOXTOP] = y + radius; - tmbbox[BOXBOTTOM] = y - radius; - tmbbox[BOXRIGHT] = x + radius; - tmbbox[BOXLEFT] = x - radius; + tm.bbox[BOXTOP] = y + radius; + tm.bbox[BOXBOTTOM] = y - radius; + tm.bbox[BOXRIGHT] = x + radius; + tm.bbox[BOXLEFT] = x - radius; // check lines - xl = (unsigned)(tmbbox[BOXLEFT] - bmaporgx)>>MAPBLOCKSHIFT; - xh = (unsigned)(tmbbox[BOXRIGHT] - bmaporgx)>>MAPBLOCKSHIFT; - yl = (unsigned)(tmbbox[BOXBOTTOM] - bmaporgy)>>MAPBLOCKSHIFT; - yh = (unsigned)(tmbbox[BOXTOP] - bmaporgy)>>MAPBLOCKSHIFT; + xl = (unsigned)(tm.bbox[BOXLEFT] - bmaporgx)>>MAPBLOCKSHIFT; + xh = (unsigned)(tm.bbox[BOXRIGHT] - bmaporgx)>>MAPBLOCKSHIFT; + yl = (unsigned)(tm.bbox[BOXBOTTOM] - bmaporgy)>>MAPBLOCKSHIFT; + yh = (unsigned)(tm.bbox[BOXTOP] - bmaporgy)>>MAPBLOCKSHIFT; for (bx = xl; bx <= xh; bx++) for (by = yl; by <= yh; by++) diff --git a/src/p_maputl.h b/src/p_maputl.h index 29e7d4de9..b53bddfd1 100644 --- a/src/p_maputl.h +++ b/src/p_maputl.h @@ -53,7 +53,6 @@ line_t * P_FindNearestLine(const fixed_t x, const fixed_t y, const sector_t *, c void P_UnsetPrecipThingPosition(precipmobj_t *thing); void P_SetPrecipitationThingPosition(precipmobj_t *thing); void P_CreatePrecipSecNodeList(precipmobj_t *thing, fixed_t x,fixed_t y); -boolean P_SceneryTryMove(mobj_t *thing, fixed_t x, fixed_t y); void P_HitSpecialLines(mobj_t *thing, fixed_t x, fixed_t y, fixed_t momx, fixed_t momy); boolean P_GetMidtextureTopBottom(line_t *linedef, fixed_t x, fixed_t y, fixed_t *return_top, fixed_t *return_bottom); @@ -85,8 +84,6 @@ boolean P_BlockThingsIterator(INT32 x, INT32 y, BlockItReturn_t(*func)(mobj_t *) extern divline_t trace; -extern fixed_t tmbbox[4]; // p_map.c - // call your user function for each line of the blockmap in the // bbox defined by the radius //boolean P_RadiusLinesCheck(fixed_t radius, fixed_t x, fixed_t y, diff --git a/src/p_mobj.c b/src/p_mobj.c index d5924de51..ac0312dec 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -1491,12 +1491,12 @@ bustupdone: // static boolean P_CheckSkyHit(mobj_t *mo) { - if (ceilingline && ceilingline->backsector - && ceilingline->backsector->ceilingpic == skyflatnum - && ceilingline->frontsector - && ceilingline->frontsector->ceilingpic == skyflatnum - && (mo->z >= ceilingline->frontsector->ceilingheight - || mo->z >= ceilingline->backsector->ceilingheight)) + if (tm.ceilingline && tm.ceilingline->backsector + && tm.ceilingline->backsector->ceilingpic == skyflatnum + && tm.ceilingline->frontsector + && tm.ceilingline->frontsector->ceilingpic == skyflatnum + && (mo->z >= tm.ceilingline->frontsector->ceilingheight + || mo->z >= tm.ceilingline->backsector->ceilingheight)) return true; return false; } @@ -1513,6 +1513,7 @@ void P_XYMovement(mobj_t *mo) pslope_t *oldslope = NULL; vector3_t slopemom = {0,0,0}; fixed_t predictedz = 0; + TryMoveResult_t result = {0}; I_Assert(mo != NULL); I_Assert(!P_MobjWasRemoved(mo)); @@ -1595,13 +1596,13 @@ void P_XYMovement(mobj_t *mo) } //} - if (!P_TryMove(mo, mo->x + xmove, mo->y + ymove, true) + if (!P_TryMove(mo, mo->x + xmove, mo->y + ymove, true, &result) && !(P_MobjWasRemoved(mo) || mo->eflags & MFE_SPRUNG)) { // blocked move moved = false; - if (LUA_HookMobjMoveBlocked(mo, tmhitthing, blockingline)) + if (LUA_HookMobjMoveBlocked(mo, tm.hitthing, tm.blockingline)) { if (P_MobjWasRemoved(mo)) return; @@ -1626,7 +1627,7 @@ void P_XYMovement(mobj_t *mo) // draw damage on wall //SPLAT TEST ---------------------------------------------------------- #ifdef WALLSPLATS - if (blockingline && mo->type != MT_REDRING && mo->type != MT_FIREBALL + if (tm.blockingline && mo->type != MT_REDRING && mo->type != MT_FIREBALL && !(mo->flags2 & (MF2_AUTOMATIC|MF2_RAILRING|MF2_BOUNCERING|MF2_EXPLOSION|MF2_SCATTER))) // set by last P_TryMove() that failed { @@ -1634,13 +1635,13 @@ void P_XYMovement(mobj_t *mo) divline_t misl; fixed_t frac; - P_MakeDivline(blockingline, &divl); + P_MakeDivline(tm.blockingline, &divl); misl.x = mo->x; misl.y = mo->y; misl.dx = mo->momx; misl.dy = mo->momy; frac = P_InterceptVector(&divl, &misl); - R_AddWallSplat(blockingline, P_PointOnLineSide(mo->x,mo->y,blockingline), + R_AddWallSplat(tm.blockingline, P_PointOnLineSide(mo->x,mo->y,tm.blockingline), "A_DMG3", mo->z, frac, SPLATDRAWMODE_SHADE); } #endif @@ -1691,7 +1692,7 @@ void P_XYMovement(mobj_t *mo) walltransferred = true; - P_SlideMove(mo); + P_SlideMove(mo, &result); xmove = ymove = 0; @@ -1726,14 +1727,14 @@ void P_XYMovement(mobj_t *mo) } else if (mo->flags & MF_SLIDEME) { - P_SlideMove(mo); + P_SlideMove(mo, &result); if (P_MobjWasRemoved(mo)) return; xmove = ymove = 0; } else { - P_BounceMove(mo); + P_BounceMove(mo, &result); if (P_MobjWasRemoved(mo)) return; xmove = ymove = 0; @@ -1895,16 +1896,19 @@ void P_XYMovement(mobj_t *mo) void P_RingXYMovement(mobj_t *mo) { + TryMoveResult_t result = {0}; + I_Assert(mo != NULL); I_Assert(!P_MobjWasRemoved(mo)); - if (!P_SceneryTryMove(mo, mo->x + mo->momx, mo->y + mo->momy)) - P_BounceMove(mo); + if (!P_SceneryTryMove(mo, mo->x + mo->momx, mo->y + mo->momy, &result)) + P_BounceMove(mo, &result); } void P_SceneryXYMovement(mobj_t *mo) { fixed_t oldx, oldy; // reducing bobbing/momentum on ice when up against walls + TryMoveResult_t result = {0}; I_Assert(mo != NULL); I_Assert(!P_MobjWasRemoved(mo)); @@ -1912,8 +1916,8 @@ void P_SceneryXYMovement(mobj_t *mo) oldx = mo->x; oldy = mo->y; - if (!P_SceneryTryMove(mo, mo->x + mo->momx, mo->y + mo->momy)) - P_BounceMove(mo); + if (!P_SceneryTryMove(mo, mo->x + mo->momx, mo->y + mo->momy, &result)) + P_BounceMove(mo, &result); if (P_MobjWasRemoved(mo)) return; @@ -2367,15 +2371,15 @@ boolean P_ZMovement(mobj_t *mo) return true; } - P_CheckPosition(mo, mo->x, mo->y); // Sets mo->standingslope correctly + P_CheckPosition(mo, mo->x, mo->y, NULL); // Sets mo->standingslope correctly if (P_MobjWasRemoved(mo)) // mobjs can be removed by P_CheckPosition -- Monster Iestyn 31/07/21 return false; - K_UpdateMobjTerrain(mo, ((mo->eflags & MFE_VERTICALFLIP) ? tmceilingpic : tmfloorpic)); + K_UpdateMobjTerrain(mo, ((mo->eflags & MFE_VERTICALFLIP) ? tm.ceilingpic : tm.floorpic)); - if (((mo->eflags & MFE_VERTICALFLIP) ? tmceilingslope : tmfloorslope) && (mo->type != MT_STEAM)) + if (((mo->eflags & MFE_VERTICALFLIP) ? tm.ceilingslope : tm.floorslope) && (mo->type != MT_STEAM)) { - mo->standingslope = (mo->eflags & MFE_VERTICALFLIP) ? tmceilingslope : tmfloorslope; + mo->standingslope = (mo->eflags & MFE_VERTICALFLIP) ? tm.ceilingslope : tm.floorslope; P_SetPitchRollFromSlope(mo, mo->standingslope); P_ReverseQuantizeMomentumToSlope(&mom, mo->standingslope); } @@ -2591,11 +2595,11 @@ boolean P_ZMovement(mobj_t *mo) } } else - mom.z = (tmfloorthing ? tmfloorthing->momz : 0); + mom.z = (tm.floorthing ? tm.floorthing->momz : 0); } - else if (tmfloorthing) - mom.z = tmfloorthing->momz; + else if (tm.floorthing) + mom.z = tm.floorthing->momz; if (mo->standingslope) { // MT_STEAM will never have a standingslope, see above. P_QuantizeMomentumToSlope(&mom, mo->standingslope); @@ -2834,7 +2838,7 @@ void P_PlayerZMovement(mobj_t *mo) mo->z = mo->floorz; } - K_UpdateMobjTerrain(mo, (mo->eflags & MFE_VERTICALFLIP ? tmceilingpic : tmfloorpic)); + K_UpdateMobjTerrain(mo, (mo->eflags & MFE_VERTICALFLIP ? tm.ceilingpic : tm.floorpic)); // Get up if you fell. if (mo->player->panim == PA_HURT && mo->player->spinouttimer == 0 && mo->player->tumbleBounces == 0) @@ -2842,10 +2846,10 @@ void P_PlayerZMovement(mobj_t *mo) P_SetPlayerMobjState(mo, S_KART_STILL); } - if (!mo->standingslope && (mo->eflags & MFE_VERTICALFLIP ? tmceilingslope : tmfloorslope)) + if (!mo->standingslope && (mo->eflags & MFE_VERTICALFLIP ? tm.ceilingslope : tm.floorslope)) { // Handle landing on slope during Z movement - P_HandleSlopeLanding(mo, (mo->eflags & MFE_VERTICALFLIP ? tmceilingslope : tmfloorslope)); + P_HandleSlopeLanding(mo, (mo->eflags & MFE_VERTICALFLIP ? tm.ceilingslope : tm.floorslope)); } if (P_MobjFlip(mo) * mo->momz < 0) // falling @@ -2860,12 +2864,12 @@ void P_PlayerZMovement(mobj_t *mo) if (clipmomz) { - mo->momz = (tmfloorthing ? tmfloorthing->momz : 0); + mo->momz = (tm.floorthing ? tm.floorthing->momz : 0); } } - else if (tmfloorthing) + else if (tm.floorthing) { - mo->momz = tmfloorthing->momz; + mo->momz = tm.floorthing->momz; } } else @@ -2985,7 +2989,7 @@ boolean P_SceneryZMovement(mobj_t *mo) if (!(mo->flags & MF_SLIDEME) && (mo->z <= mo->floorz || mo->z+mo->height >= mo->ceilingz)) { // set standingslope - P_TryMove(mo, mo->x, mo->y, true); + P_TryMove(mo, mo->x, mo->y, true, NULL); mo->momz = -mo->momz; if (mo->standingslope) { @@ -3083,9 +3087,9 @@ boolean P_SceneryZMovement(mobj_t *mo) { mo->eflags |= MFE_JUSTHITFLOOR; // Spin Attack - if (tmfloorthing) - mo->momz = tmfloorthing->momz; - else if (!tmfloorthing) + if (tm.floorthing) + mo->momz = tm.floorthing->momz; + else if (!tm.floorthing) mo->momz = 0; } } @@ -3218,14 +3222,15 @@ boolean P_CanRunOnWater(mobj_t *mobj, ffloor_t *rover) // We start water run IF we can step onto it! if (surfDiff <= maxStep && surfDiff >= 0) { - if (ourZAng < 0) + pslope_t *groundSlope = (flip ? mobj->subsector->sector->c_slope : mobj->subsector->sector->f_slope); + if (groundSlope != NULL && groundSlope->zangle != 0) { fixed_t floorheight = flip ? P_GetSectorCeilingZAt(mobj->subsector->sector, mobj->x, mobj->y) : P_GetSectorFloorZAt(mobj->subsector->sector, mobj->x, mobj->y); fixed_t floorDiff = flip ? (floorheight - mobjbottom) : (mobjbottom - floorheight); if (floorDiff <= maxStep && floorDiff >= -maxStep) { - // ... but NOT if going down and real floor is in range. - // FIXME: Count solid FOFs in this check + // ... but NOT if downward-sloping real floor is in range. + // FIXME: Count solid FOFs in these checks return false; } } @@ -3801,8 +3806,8 @@ boolean P_CameraThinker(player_t *player, camera_t *thiscam, boolean resetcalled } thiscam->subsector = R_PointInSubsector(thiscam->x, thiscam->y); - thiscam->floorz = tmfloorz; - thiscam->ceilingz = tmceilingz; + thiscam->floorz = tm.floorz; + thiscam->ceilingz = tm.ceilingz; if (thiscam->momz || player->mo->pmomz) { @@ -3959,9 +3964,9 @@ static void P_PlayerMobjThinker(mobj_t *mobj) mobj->y += mobj->momy; mobj->z += mobj->momz; P_SetThingPosition(mobj); - P_CheckPosition(mobj, mobj->x, mobj->y); - mobj->floorz = tmfloorz; - mobj->ceilingz = tmceilingz; + P_CheckPosition(mobj, mobj->x, mobj->y, NULL); + mobj->floorz = tm.floorz; + mobj->ceilingz = tm.ceilingz; goto animonly; } @@ -3976,7 +3981,7 @@ static void P_PlayerMobjThinker(mobj_t *mobj) return; } else - P_TryMove(mobj, mobj->x, mobj->y, true); + P_TryMove(mobj, mobj->x, mobj->y, true, NULL); P_CheckCrumblingPlatforms(mobj); @@ -3991,7 +3996,7 @@ static void P_PlayerMobjThinker(mobj_t *mobj) || P_IsObjectInGoop(mobj)) { P_PlayerZMovement(mobj); - P_CheckPosition(mobj, mobj->x, mobj->y); // Need this to pick up objects! + P_CheckPosition(mobj, mobj->x, mobj->y, NULL); // Need this to pick up objects! if (P_MobjWasRemoved(mobj)) return; @@ -4181,7 +4186,7 @@ static void P_RingThinker(mobj_t *mobj) if (mobj->momz) { P_RingZMovement(mobj); - P_CheckPosition(mobj, mobj->x, mobj->y); // Need this to pick up objects! + P_CheckPosition(mobj, mobj->x, mobj->y, NULL); // Need this to pick up objects! if (P_MobjWasRemoved(mobj)) return; @@ -5330,7 +5335,7 @@ void P_RunOverlays(void) P_SetUnderlayPosition(mo); else P_SetThingPosition(mo); - P_CheckPosition(mo, mo->x, mo->y); + P_CheckPosition(mo, mo->x, mo->y, NULL); } P_SetTarget(&overlaycap, NULL); } @@ -7694,6 +7699,109 @@ static boolean P_MobjRegularThink(mobj_t *mobj) mobj->renderflags = (mobj->renderflags & ~RF_TRANSMASK)|(trans << RF_TRANSSHIFT); } break; + case MT_MAGICIANBOX: + { + fixed_t destx, desty; + fixed_t zoff = 0; + + // EV1: rotation rate + // EV2: lifetime + // cusval: responsible for disappear FX (should only happen once) + + // S_MAGICANBOX: sides, starting angle is set in the spawner (SetRandomFakePlayerSkin) + // S_MAGICIANBOX_TOP, S_MAGICIANBOX_BOTTOM: splats with their own offset sprite sets + + mobj->extravalue2--; + + if (mobj->extravalue2 == 0) + { + P_RemoveMobj(mobj); + break; + } + else if (mobj->extravalue2 < TICRATE/3) + { + P_SetTarget(&mobj->target, NULL); + if (mobj->extravalue2 & 1) + mobj->renderflags |= RF_DONTDRAW; + else + mobj->renderflags &= ~RF_DONTDRAW; + } + else if (mobj->extravalue2 == TICRATE/3 && !P_MobjWasRemoved(mobj->target)) + { + mobj->momx = mobj->target->momx; + mobj->momy = mobj->target->momy; + mobj->momz = mobj->target->momz; + + if (mobj->state == &states[S_MAGICIANBOX]) // sides + P_Thrust(mobj, mobj->angle + ANGLE_90, 32*mapobjectscale); + + mobj->flags &= ~MF_NOGRAVITY; + mobj->momz += 10*mapobjectscale; + if (mobj->state == &states[S_MAGICIANBOX_BOTTOM]) + mobj->momz *= -1; + + if (!mobj->cusval) // Some stuff should only occur once per box + return true; + + S_StartSound(mobj, sfx_kc2e); + S_StartSound(mobj, sfx_s3k9f); + + if (mobj->target->player->hyudorotimer) + { + P_RemoveMobj(mobj); + break; + } + else + { + K_SpawnMagicianParticles(mobj, 5); + } + return true; + } + else if (mobj->target && !P_MobjWasRemoved(mobj->target)) + { + mobj->renderflags &= ~RF_DONTDRAW; + mobj->renderflags |= (mobj->target->renderflags & RF_DONTDRAW); + // NB: This depends on order of thinker execution! + // SetRandomFakePlayerSkin (r_skins.c) sets cusval on the bottom (last) side (i=5). + // This writes to the player's visibility only after every other side has ticked and inherited it. + if (mobj->cusval) + mobj->target->renderflags |= RF_DONTDRAW; + } + + if (P_MobjWasRemoved(mobj->target) || !mobj->target->health || !mobj->target->player) { + mobj->extravalue2 = min(mobj->extravalue2, TICRATE/3); + return true; + } + + mobj->extravalue1 += 1; + + mobj->angle += ANG1*mobj->extravalue1; + mobj->scale = mobj->target->scale; + + destx = mobj->target->x; + desty = mobj->target->y; + + if (mobj->state == &states[S_MAGICIANBOX]) // sides + { + destx += FixedMul(mobj->radius*2, FINECOSINE((mobj->angle+ANGLE_90) >> ANGLETOFINESHIFT)); + desty += FixedMul(mobj->radius*2, FINESINE((mobj->angle+ANGLE_90) >> ANGLETOFINESHIFT)); + } + else if (mobj->state == &states[S_MAGICIANBOX_TOP]) // top + { + zoff = mobj->radius*4; + } + + if (mobj->flags2 & MF2_AMBUSH) + { + P_SetOrigin(mobj, destx, desty, mobj->target->z + zoff); + mobj->flags2 &= ~MF2_AMBUSH; + } + else + { + P_MoveOrigin(mobj, destx, desty, mobj->target->z + zoff); + } + break; + } case MT_LIGHTNINGSHIELD: { fixed_t destx, desty; @@ -8408,7 +8516,7 @@ static boolean P_MobjRegularThink(mobj_t *mobj) mobj->movecount += mobj->lastlook; - if (!(P_TryMove(mobj->tracer, mobj->x + ((mobj->extravalue1<movecount), mobj->y + ((mobj->extravalue2<movecount), true)) + if (!(P_TryMove(mobj->tracer, mobj->x + ((mobj->extravalue1<movecount), mobj->y + ((mobj->extravalue2<movecount), true, NULL)) || (mobj->movecount >= 16) // maximum travel time || (mobj->tracer->z <= mobj->tracer->floorz) // Through the floor || ((mobj->tracer->z + mobj->tracer->height) >= mobj->tracer->ceilingz)) // Through the ceiling @@ -9451,7 +9559,9 @@ void P_MobjThinker(mobj_t *mobj) mobj->eflags &= ~(MFE_PUSHED|MFE_SPRUNG|MFE_JUSTBOUNCEDWALL|MFE_DAMAGEHITLAG|MFE_SLOPELAUNCHED); - tmfloorthing = tmhitthing = NULL; + // sal: what the hell? is there any reason this isn't done, like, literally ANYWHERE else? + P_SetTarget(&tm.floorthing, NULL); + P_SetTarget(&tm.hitthing, NULL); // Sector flag MSF_TRIGGERLINE_MOBJ allows ANY mobj to trigger a linedef exec P_CheckMobjTrigger(mobj, false); @@ -9607,7 +9717,7 @@ void P_MobjThinker(mobj_t *mobj) { if (!P_ZMovement(mobj)) return; // mobj was removed - P_CheckPosition(mobj, mobj->x, mobj->y); // Need this to pick up objects! + P_CheckPosition(mobj, mobj->x, mobj->y, NULL); // Need this to pick up objects! if (P_MobjWasRemoved(mobj)) return; } @@ -9631,7 +9741,7 @@ void P_MobjThinker(mobj_t *mobj) || mobj->type == MT_JAWZ || (mobj->type == MT_DROPTARGET && mobj->reactiontime)) { - P_TryMove(mobj, mobj->x, mobj->y, true); // Sets mo->standingslope correctly + P_TryMove(mobj, mobj->x, mobj->y, true, NULL); // Sets mo->standingslope correctly if (P_MobjWasRemoved(mobj)) // anything that calls checkposition can be lethal return; @@ -9729,7 +9839,7 @@ boolean P_RailThinker(mobj_t *mobj) { if (!P_ZMovement(mobj)) return true; // mobj was removed - //P_CheckPosition(mobj, mobj->x, mobj->y); + //P_CheckPosition(mobj, mobj->x, mobj->y, NULL); } return P_MobjWasRemoved(mobj) || (x == mobj->x && y == mobj->y && z == mobj->z); @@ -9745,7 +9855,7 @@ void P_PushableThinker(mobj_t *mobj) // it has to be pushable RIGHT NOW for this part to happen if (mobj->flags & MF_PUSHABLE && !(mobj->momx || mobj->momy)) - P_TryMove(mobj, mobj->x, mobj->y, true); + P_TryMove(mobj, mobj->x, mobj->y, true, NULL); if (mobj->fuse == 1) // it would explode in the MobjThinker code { @@ -9806,13 +9916,13 @@ void P_SceneryThinker(mobj_t *mobj) { if (!P_SceneryZMovement(mobj)) return; // mobj was removed - P_CheckPosition(mobj, mobj->x, mobj->y); // Need this to pick up objects! + P_CheckPosition(mobj, mobj->x, mobj->y, NULL); // Need this to pick up objects! if (P_MobjWasRemoved(mobj)) return; - mobj->floorz = tmfloorz; - mobj->ceilingz = tmceilingz; - mobj->floorrover = tmfloorrover; - mobj->ceilingrover = tmceilingrover; + mobj->floorz = tm.floorz; + mobj->ceilingz = tm.ceilingz; + mobj->floorrover = tm.floorrover; + mobj->ceilingrover = tm.ceilingrover; } else { @@ -13348,7 +13458,7 @@ boolean P_CheckMissileSpawn(mobj_t *th) th->z += th->momz>>1; } - if (!P_TryMove(th, th->x, th->y, true)) + if (!P_TryMove(th, th->x, th->y, true, NULL)) { P_ExplodeMissile(th); return false; diff --git a/src/p_polyobj.c b/src/p_polyobj.c index cd946e5ee..de0a36bd1 100644 --- a/src/p_polyobj.c +++ b/src/p_polyobj.c @@ -762,7 +762,7 @@ static void Polyobj_removeFromBlockmap(polyobj_t *po) // Movement functions // A version of Lee's routine from p_maputl.c that accepts an mobj pointer -// argument instead of using tmthing. Returns true if the line isn't contacted +// argument instead of using tm.thing. Returns true if the line isn't contacted // and false otherwise. static inline boolean Polyobj_untouched(line_t *ld, mobj_t *mo) { @@ -805,11 +805,11 @@ static void Polyobj_pushThing(polyobj_t *po, line_t *line, mobj_t *mo) // if object doesn't fit at desired location, possibly hurt it if (po->damage && (mo->flags & MF_SHOOTABLE)) { - P_CheckPosition(mo, mo->x + momx, mo->y + momy); - mo->floorz = tmfloorz; - mo->ceilingz = tmceilingz; - mo->floorrover = tmfloorrover; - mo->ceilingrover = tmceilingrover; + P_CheckPosition(mo, mo->x + momx, mo->y + momy, NULL); + mo->floorz = tm.floorz; + mo->ceilingz = tm.ceilingz; + mo->floorrover = tm.floorrover; + mo->ceilingrover = tm.ceilingrover; } } @@ -851,7 +851,7 @@ static void Polyobj_slideThing(mobj_t *mo, fixed_t dx, fixed_t dy) mo->player->onconveyor = 1; } else - P_TryMove(mo, mo->x+dx, mo->y+dy, true); + P_TryMove(mo, mo->x+dx, mo->y+dy, true, NULL); } // Causes objects resting on top of the polyobject to 'ride' with its movement. diff --git a/src/p_saveg.c b/src/p_saveg.c index c9ede8b78..1d58992f2 100644 --- a/src/p_saveg.c +++ b/src/p_saveg.c @@ -151,6 +151,8 @@ static void P_NetArchivePlayers(void) WRITEUINT8(save_p, players[i].skincolor); WRITEINT32(save_p, players[i].skin); WRITEUINT32(save_p, players[i].availabilities); + WRITEUINT8(save_p, players[i].fakeskin); + WRITEUINT8(save_p, players[i].lastfakeskin); WRITEUINT32(save_p, players[i].score); WRITESINT8(save_p, players[i].lives); WRITESINT8(save_p, players[i].xtralife); @@ -470,6 +472,8 @@ static void P_NetUnArchivePlayers(void) players[i].skincolor = READUINT8(save_p); players[i].skin = READINT32(save_p); players[i].availabilities = READUINT32(save_p); + players[i].fakeskin = READUINT8(save_p); + players[i].lastfakeskin = READUINT8(save_p); players[i].score = READUINT32(save_p); players[i].lives = READSINT8(save_p); players[i].xtralife = READSINT8(save_p); // Ring Extra Life counter diff --git a/src/p_setup.c b/src/p_setup.c index efadfedd9..92f054eb6 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -7465,7 +7465,7 @@ boolean P_LoadLevel(boolean fromnetsave, boolean reloadinggamestate) P_ResetTubeWaypoints(); - P_MapStart(); // tmthing can be used starting from this point + P_MapStart(); // tm.thing can be used starting from this point // init anything that P_SpawnSlopes/P_LoadThings needs to know P_InitSpecials(); @@ -7570,7 +7570,7 @@ boolean P_LoadLevel(boolean fromnetsave, boolean reloadinggamestate) P_RunCachedActions(); - P_MapEnd(); // tmthing is no longer needed from this point onwards + P_MapEnd(); // tm.thing is no longer needed from this point onwards // Took me 3 hours to figure out why my progression kept on getting overwritten with the titlemap... if (!titlemapinaction) @@ -7629,9 +7629,9 @@ boolean P_LoadLevel(boolean fromnetsave, boolean reloadinggamestate) G_CopyTiccmd(&players[i].cmd, &netcmds[buf][i], 1); } P_PreTicker(2); - P_MapStart(); // just in case MapLoad modifies tmthing + P_MapStart(); // just in case MapLoad modifies tm.thing LUA_HookInt(gamemap, HOOK(MapLoad)); - P_MapEnd(); // just in case MapLoad modifies tmthing + P_MapEnd(); // just in case MapLoad modifies tm.thing } K_TimerReset(); diff --git a/src/p_sight.c b/src/p_sight.c index 4a8ccab39..64bba3969 100644 --- a/src/p_sight.c +++ b/src/p_sight.c @@ -749,10 +749,10 @@ static boolean P_CrossBotTraversalSubsector(size_t num, register traceblocking_t } // set openrange, opentop, openbottom - tmx = tb->compareThing->x; - tmy = tb->compareThing->y; + tm.x = tb->compareThing->x; + tm.y = tb->compareThing->y; P_LineOpening(line, tb->compareThing); - maxstep = P_GetThingStepUp(tb->compareThing, tmx, tmy); + maxstep = P_GetThingStepUp(tb->compareThing, tm.x, tm.y); if ((openrange < tb->compareThing->height) // doesn't fit || (opentop - tb->compareThing->z < tb->compareThing->height) // mobj is too high diff --git a/src/p_spec.c b/src/p_spec.c index 31af5b0e6..07ec1f102 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -1928,6 +1928,17 @@ static void K_HandleLapIncrement(player_t *player) P_DoPlayerExit(player); P_SetupSignExit(player); } + else + { + UINT32 skinflags = (demo.playback) + ? demo.skinlist[demo.currentskinid[(player-players)]].flags + : skins[player->skin].flags; + if (skinflags & SF_IRONMAN) + { + SetRandomFakePlayerSkin(player, true); + } + } + if (player->laps > player->latestlap) { diff --git a/src/p_user.c b/src/p_user.c index b43311d38..1f58384df 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -1264,6 +1264,8 @@ void P_DoPlayerExit(player_t *player) if (!player->spectator) { + ClearFakePlayerSkin(player); + if ((gametyperules & GTR_CIRCUIT)) // If in Race Mode, allow { K_KartUpdatePosition(player); @@ -4167,6 +4169,35 @@ void P_PlayerThink(player_t *player) { player->stairjank--; } + + // Random skin / "ironman" + { + UINT32 skinflags = (demo.playback) + ? demo.skinlist[demo.currentskinid[playeri]].flags + : skins[player->skin].flags; + + if (skinflags & SF_IRONMAN) // we are Heavy Magician + { + if (player->charflags & SF_IRONMAN) // no fakeskin yet + { + if (leveltime >= starttime && !player->exiting) + { + if (player->fakeskin != MAXSKINS) + { + SetFakePlayerSkin(player, player->fakeskin); + } + else if (!(gametyperules & GTR_CIRCUIT)) + { + SetRandomFakePlayerSkin(player, false); + } + } + } + else if (player->exiting) // wearing a fakeskin, but need to display signpost postrace etc + { + ClearFakePlayerSkin(player); + } + } + } K_KartPlayerThink(player, cmd); // SRB2kart diff --git a/src/r_main.c b/src/r_main.c index 6c1ccf299..2c781509c 100644 --- a/src/r_main.c +++ b/src/r_main.c @@ -180,6 +180,8 @@ consvar_t cv_maxportals = CVAR_INIT ("maxportals", "2", CV_SAVE, maxportals_cons consvar_t cv_renderstats = CVAR_INIT ("renderstats", "Off", 0, CV_OnOff, NULL); +consvar_t cv_drawpickups = CVAR_INIT ("drawpickups", "Yes", CV_CHEAT, CV_YesNo, NULL); + void SplitScreen_OnChange(void) { UINT8 i; @@ -1646,4 +1648,6 @@ void R_RegisterEngineStuff(void) // Frame interpolation/uncapped CV_RegisterVar(&cv_fpscap); + + CV_RegisterVar(&cv_drawpickups); } diff --git a/src/r_main.h b/src/r_main.h index e7f5b9d4c..c3e60a0ca 100644 --- a/src/r_main.h +++ b/src/r_main.h @@ -117,6 +117,7 @@ extern consvar_t cv_drawdist, cv_drawdist_precip; extern consvar_t cv_fov[MAXSPLITSCREENPLAYERS]; extern consvar_t cv_skybox; extern consvar_t cv_tailspickup; +extern consvar_t cv_drawpickups; // Called by startup code. void R_Init(void); diff --git a/src/r_skins.c b/src/r_skins.c index 0557e9e88..9779fdcfc 100644 --- a/src/r_skins.c +++ b/src/r_skins.c @@ -27,6 +27,8 @@ #include "p_local.h" #include "dehacked.h" // get_number (for thok) #include "m_cond.h" +#include "k_kart.h" +#include "m_random.h" #if 0 #include "k_kart.h" // K_KartResetPlayerColor #endif @@ -334,6 +336,136 @@ void SetPlayerSkinByNum(INT32 playernum, INT32 skinnum) SetPlayerSkinByNum(playernum, 0); // not found, put in the default skin } +// Set mo skin but not player_t skin, for ironman +void SetFakePlayerSkin(player_t* player, INT32 skinid) +{ + if (player->fakeskin != skinid) + { + if (player->fakeskin != MAXSKINS) + player->lastfakeskin = player->fakeskin; + player->fakeskin = skinid; + } + + if (demo.playback) + { + player->kartspeed = demo.skinlist[skinid].kartspeed; + player->kartweight = demo.skinlist[skinid].kartweight; + player->charflags = demo.skinlist[skinid].flags; + skinid = demo.skinlist[skinid].mapping; + } + else + { + player->kartspeed = skins[skinid].kartspeed; + player->kartweight = skins[skinid].kartweight; + player->charflags = skins[skinid].flags; + } + + player->mo->skin = &skins[skinid]; +} + +// Loudly rerandomize +void SetRandomFakePlayerSkin(player_t* player, boolean fast) +{ + INT32 i; + UINT8 usableskins = 0, maxskinpick; + UINT8 grabskins[MAXSKINS]; + + maxskinpick = (demo.playback ? demo.numskins : numskins); + + for (i = 0; i < maxskinpick; i++) + { + if (i == player->lastfakeskin) + continue; + if (demo.playback) + { + if (demo.skinlist[i].flags & SF_IRONMAN) + continue; + } + else if (skins[i].flags & SF_IRONMAN) + continue; + /*if (K_SkinLocked(i)) + continue;*/ + grabskins[usableskins++] = i; + } + + i = grabskins[P_RandomKey(PR_RANDOMSKIN, usableskins)]; + + SetFakePlayerSkin(player, i); + + if (player->mo) + { + S_StartSound(player->mo, sfx_kc33); + S_StartSound(player->mo, sfx_cdfm44); + + mobj_t *parent = player->mo; + fixed_t baseangle = P_RandomRange(PR_DECORATION, 0, 359); + INT32 j; + + for (j = 0; j < 6; j++) // 0-3 = sides, 4 = top, 5 = bottom + { + mobj_t *box = P_SpawnMobjFromMobj(parent, 0, 0, 0, MT_MAGICIANBOX); + P_SetTarget(&box->target, parent); + box->angle = FixedAngle((baseangle + j*90) * FRACUNIT); + box->flags2 |= MF2_AMBUSH; + if (fast) + { + box->extravalue1 = 10; // Rotation rate + box->extravalue2 = 5*TICRATE/4; // Lifetime + } + else + { + box->extravalue1 = 1; + box->extravalue2 = 3*TICRATE/2; + } + + // cusval controls behavior that should run only once, like disappear FX and RF_DONTDRAW handling. + // NB: Order of thinker execution matters here! + // We want the other sides to inherit the player's "existing" RF_DONTDRAW before the last side writes to it. + // See the MT_MAGICIANBOX thinker in p_mobj.c. + if (j == 5) + box->cusval = 1; + else + box->cusval = 0; + + if (j > 3) + { + P_SetMobjState(box, (j == 4) ? S_MAGICIANBOX_TOP : S_MAGICIANBOX_BOTTOM); + box->renderflags |= RF_NOSPLATBILLBOARD; + box->angle = FixedAngle(baseangle*FRACUNIT); + } + } + + K_SpawnMagicianParticles(player->mo, 10); + } +} + +// Return to base skin from an SF_IRONMAN randomization +void ClearFakePlayerSkin(player_t* player) +{ + UINT8 skinid; + UINT32 flags; + + if (demo.playback) + { + skinid = demo.currentskinid[(player-players)]; + flags = demo.skinlist[skinid].flags; + } + else + { + skinid = player->skin; + flags = skins[player->skin].flags; + } + + if ((flags & SF_IRONMAN) && !P_MobjWasRemoved(player->mo)) + { + SetFakePlayerSkin(player, skinid); + S_StartSound(player->mo, sfx_s3k9f); + K_SpawnMagicianParticles(player->mo, 5); + } + + player->fakeskin = MAXSKINS; +} + // // Add skins from a pwad, each skin preceded by 'S_SKIN' marker // @@ -482,8 +614,8 @@ static boolean R_ProcessPatchableFields(skin_t *skin, char *stoken, char *value) // parameters for individual character flags // these are uppercase so they can be concatenated with SF_ // 1, true, yes are all valid values - GETFLAG(HIRES) GETFLAG(MACHINE) + GETFLAG(IRONMAN) #undef GETFLAG else // let's check if it's a sound, otherwise error out diff --git a/src/r_skins.h b/src/r_skins.h index ded45a71f..1cc06cca4 100644 --- a/src/r_skins.h +++ b/src/r_skins.h @@ -81,6 +81,9 @@ void R_InitSkins(void); void SetPlayerSkin(INT32 playernum,const char *skinname); void SetPlayerSkinByNum(INT32 playernum,INT32 skinnum); // Tails 03-16-2002 +void SetFakePlayerSkin(player_t* player, INT32 skinnum); +void SetRandomFakePlayerSkin(player_t* player, boolean fast); +void ClearFakePlayerSkin(player_t* player); boolean R_SkinUsable(INT32 playernum, INT32 skinnum); UINT32 R_GetSkinAvailabilities(void); INT32 R_SkinAvailable(const char *name); diff --git a/src/r_splats.c b/src/r_splats.c index 80ff44743..011e1d9eb 100644 --- a/src/r_splats.c +++ b/src/r_splats.c @@ -181,7 +181,7 @@ void R_DrawFloorSplat(vissprite_t *spr) splat.height = spr->patch->height; splat.scale = mobj->scale; - if (mobj->skin && ((skin_t *)mobj->skin)->flags & SF_HIRES) + if (mobj->skin && ((skin_t *)mobj->skin)->highresscale != FRACUNIT) splat.scale = FixedMul(splat.scale, ((skin_t *)mobj->skin)->highresscale); if (spr->rotateflags & SRF_3D || renderflags & RF_NOSPLATBILLBOARD) diff --git a/src/r_things.c b/src/r_things.c index 41dfc8585..87b19eb6b 100644 --- a/src/r_things.c +++ b/src/r_things.c @@ -945,7 +945,7 @@ static void R_DrawVisSprite(vissprite_t *vis) frac = vis->startfrac; windowtop = windowbottom = sprbotscreen = INT32_MAX; - if (!(vis->cut & SC_PRECIP) && vis->mobj->skin && ((skin_t *)vis->mobj->skin)->flags & SF_HIRES) + if (!(vis->cut & SC_PRECIP) && vis->mobj->skin && ((skin_t *)vis->mobj->skin)->highresscale != FRACUNIT) this_scale = FixedMul(this_scale, ((skin_t *)vis->mobj->skin)->highresscale); if (this_scale <= 0) @@ -1410,7 +1410,7 @@ static void R_ProjectDropShadow( shadow->gzt = groundz + patch->height * shadowyscale / 2; shadow->gz = shadow->gzt - patch->height * shadowyscale; shadow->texturemid = FixedMul(interp.scale, FixedDiv(shadow->gzt - viewz, shadowyscale)); - if (thing->skin && ((skin_t *)thing->skin)->flags & SF_HIRES) + if (thing->skin && ((skin_t *)thing->skin)->highresscale != FRACUNIT) shadow->texturemid = FixedMul(shadow->texturemid, ((skin_t *)thing->skin)->highresscale); shadow->scalestep = 0; shadow->shear.tan = shadowskew; // repurposed variable @@ -1797,7 +1797,7 @@ static void R_ProjectSprite(mobj_t *thing) I_Assert(lump < max_spritelumps); - if (thing->skin && ((skin_t *)thing->skin)->flags & SF_HIRES) + if (thing->skin && ((skin_t *)thing->skin)->highresscale != FRACUNIT) this_scale = FixedMul(this_scale, ((skin_t *)thing->skin)->highresscale); spr_width = spritecachedinfo[lump].width; @@ -3443,6 +3443,26 @@ boolean R_ThingVisible (mobj_t *thing) if (thing->sprite == SPR_NULL) return false; + if (!cv_drawpickups.value) + { + switch (thing->type) + { + case MT_RING: + case MT_FLINGRING: + case MT_BLUESPHERE: + case MT_RANDOMITEM: + case MT_SPHEREBOX: + case MT_ITEMCAPSULE: + case MT_ITEMCAPSULE_PART: + case MT_BATTLECAPSULE: + case MT_BATTLECAPSULE_PIECE: + return false; + + default: + break; + } + } + if (r_viewmobj && (thing == r_viewmobj || (r_viewmobj->player && r_viewmobj->player->followmobj == thing))) return false; diff --git a/src/v_video.c b/src/v_video.c index 2636b9a6e..2df56c9a4 100644 --- a/src/v_video.c +++ b/src/v_video.c @@ -619,10 +619,6 @@ void V_DrawStretchyFixedPatch(fixed_t x, fixed_t y, fixed_t pscale, fixed_t vsca colfrac = FixedDiv(FRACUNIT, fdup); rowfrac = FixedDiv(FRACUNIT, vdup); - // So it turns out offsets aren't scaled in V_NOSCALESTART unless V_OFFSET is applied ...poo, that's terrible - // For now let's just at least give V_OFFSET the ability to support V_FLIP - // I'll probably make a better fix for 2.2 where I don't have to worry about breaking existing support for stuff - // -- Monster Iestyn 29/10/18 { fixed_t offsetx = 0, offsety = 0; @@ -633,15 +629,17 @@ void V_DrawStretchyFixedPatch(fixed_t x, fixed_t y, fixed_t pscale, fixed_t vsca offsetx = FixedMul(patch->leftoffset<topoffset<height - patch->topoffset)<topoffset<= vid.width) // don't draw off the right of the screen (WRAP PREVENTION) break; } + column = (const column_t *)((const UINT8 *)(patch->columns) + (patch->columnofs[col>>FRACBITS])); while (column->topdelta != 0xff) @@ -709,17 +708,31 @@ void V_DrawStretchyFixedPatch(fixed_t x, fixed_t y, fixed_t pscale, fixed_t vsca topdelta += prevdelta; prevdelta = topdelta; source = (const UINT8 *)(column) + 3; + dest = desttop; if (scrn & V_FLIP) - dest = deststart + (destend - desttop); + dest = deststart + (destend - dest); dest += FixedInt(FixedMul(topdelta<>FRACBITS) < column->length; ofs += rowfrac) + if (scrn & V_VFLIP) { - if (dest >= screens[scrn&V_PARAMMASK]) // don't draw off the top of the screen (CRASH PREVENTION) - *dest = patchdrawfunc(dest, source, ofs); - dest += vid.width; + for (ofs = (column->length << FRACBITS)-1; dest < deststop && ofs >= 0; ofs -= rowfrac) + { + if (dest >= screens[scrn&V_SCREENMASK]) // don't draw off the top of the screen (CRASH PREVENTION) + *dest = patchdrawfunc(dest, source, ofs); + dest += vid.width; + } } + else + { + for (ofs = 0; dest < deststop && ofs < (column->length << FRACBITS); ofs += rowfrac) + { + if (dest >= screens[scrn&V_SCREENMASK]) // don't draw off the top of the screen (CRASH PREVENTION) + *dest = patchdrawfunc(dest, source, ofs); + dest += vid.width; + } + } + column = (const column_t *)((const UINT8 *)column + column->length + 4); } } @@ -778,7 +791,7 @@ void V_DrawCroppedPatch(fixed_t x, fixed_t y, fixed_t pscale, INT32 scrn, patch_ y -= FixedMul(patch->topoffset<leftoffset<>FRACBITS) < column->length && (((ofs>>FRACBITS) - sy) + topdelta) < h; ofs += rowfrac) { - if (dest >= screens[scrn&V_PARAMMASK]) // don't draw off the top of the screen (CRASH PREVENTION) + if (dest >= screens[scrn&V_SCREENMASK]) // don't draw off the top of the screen (CRASH PREVENTION) *dest = patchdrawfunc(dest, source, ofs); dest += vid.width; } diff --git a/src/v_video.h b/src/v_video.h index 34800e7b4..1803d0818 100644 --- a/src/v_video.h +++ b/src/v_video.h @@ -82,11 +82,14 @@ void V_CubeApply(RGBA_t *input); #define V_GetColor(color) (pLocalPalette[color&0xFF]) #define V_GetMasterColor(color) (pMasterPalette[color&0xFF]) -// Bottom 8 bits are used for parameter (screen or character) +// Bottom 8 bits are used for parameter (character) #define V_PARAMMASK 0x000000FF -// strings/characters only -#define V_STRINGDANCE 0x00000002 +// Bottom bit is used for screen (patches) +#define V_SCREENMASK 0x0000000F + +#define V_STRINGDANCE 0x00000002 // (strings/characters only) funny undertale +#define V_VFLIP 0x00000010 // (patches only) Vertical flip // flags hacked in scrn (not supported by all functions (see src)) // patch scaling uses bits 9 and 10