diff --git a/src/cvars.cpp b/src/cvars.cpp index 9336becb2..1c0812598 100644 --- a/src/cvars.cpp +++ b/src/cvars.cpp @@ -906,6 +906,7 @@ void Dummymenuplayer_OnChange(void); consvar_t cv_dummymenuplayer = MenuDummy("dummymenuplayer", "P1").onchange(Dummymenuplayer_OnChange).values({{0, "NOPE"}, {1, "P1"}, {2, "P2"}, {3, "P3"}, {4, "P4"}}); consvar_t cv_dummyprofileautoroulette = MenuDummy("dummyprofileautoroulette", "Off").on_off(); +consvar_t cv_dummyprofilelitesteer = MenuDummy("dummyprofilelitesteer", "On").on_off(); consvar_t cv_dummyprofilekickstart = MenuDummy("dummyprofilekickstart", "Off").on_off(); consvar_t cv_dummyprofilename = MenuDummy("dummyprofilename", ""); consvar_t cv_dummyprofileplayername = MenuDummy("dummyprofileplayername", ""); @@ -1012,6 +1013,13 @@ consvar_t cv_autoroulette[MAXSPLITSCREENPLAYERS] = { Player("autoroulette4", "Off").on_off().onchange(weaponPrefChange4), }; +consvar_t cv_litesteer[MAXSPLITSCREENPLAYERS] = { + Player("litesteer", "On").on_off().onchange(weaponPrefChange), + Player("litesteer2", "On").on_off().onchange(weaponPrefChange2), + Player("litesteer3", "On").on_off().onchange(weaponPrefChange3), + Player("litesteer4", "On").on_off().onchange(weaponPrefChange4), +}; + consvar_t cv_cam_dist[MAXSPLITSCREENPLAYERS] = { Player("cam_dist", "190").floating_point(), Player("cam2_dist", "190").floating_point(), diff --git a/src/d_clisrv.c b/src/d_clisrv.c index ce142ffd1..1e01c8779 100644 --- a/src/d_clisrv.c +++ b/src/d_clisrv.c @@ -5619,7 +5619,7 @@ static INT16 Consistancy(void) if (TypeIsNetSynced(mo->type) == false) continue; - if (mo->flags & (MF_SPECIAL | MF_SOLID | MF_PUSHABLE | MF_BOSS | MF_MISSILE | MF_SPRING | MF_MONITOR | MF_FIRE | MF_ENEMY | MF_PAIN | MF_STICKY)) + if (mo->flags & (MF_SPECIAL | MF_SOLID | MF_PUSHABLE | MF_BOSS | MF_MISSILE | MF_SPRING | MF_ELEMENTAL | MF_FIRE | MF_ENEMY | MF_PAIN | MF_DONTPUNT)) { ret -= mo->type; ret += mo->x; diff --git a/src/d_netcmd.c b/src/d_netcmd.c index 776d8568d..10ff36129 100644 --- a/src/d_netcmd.c +++ b/src/d_netcmd.c @@ -1229,6 +1229,7 @@ enum { WP_KICKSTARTACCEL = 1<<0, WP_SHRINKME = 1<<1, WP_AUTOROULETTE = 1<<2, + WP_LITESTEER = 1<<3, }; void WeaponPref_Send(UINT8 ssplayer) @@ -1241,6 +1242,9 @@ void WeaponPref_Send(UINT8 ssplayer) if (cv_autoroulette[ssplayer].value) prefs |= WP_AUTOROULETTE; + if (cv_litesteer[ssplayer].value) + prefs |= WP_LITESTEER; + if (cv_shrinkme[ssplayer].value) prefs |= WP_SHRINKME; @@ -1259,6 +1263,9 @@ void WeaponPref_Save(UINT8 **cp, INT32 playernum) if (player->pflags & PF_AUTOROULETTE) prefs |= WP_AUTOROULETTE; + if (player->pflags & PF_LITESTEER) + prefs |= WP_LITESTEER; + if (player->pflags & PF_SHRINKME) prefs |= WP_SHRINKME; diff --git a/src/d_player.h b/src/d_player.h index a49ccb8ad..d9d46979d 100644 --- a/src/d_player.h +++ b/src/d_player.h @@ -64,6 +64,14 @@ typedef enum PST_REBORN } playerstate_t; +typedef enum +{ + IF_USERINGS = 1, // Have to be not holding the item button to change from using rings to using items (or vice versa) - prevents weirdness + IF_ITEMOUT = 1<<1, // Are you holding an item out? + IF_EGGMANOUT = 1<<2, // Eggman mark held, separate from IF_ITEMOUT so it doesn't stop you from getting items + IF_HOLDREADY = 1<<3, // Hold button-style item is ready to activate +} itemflags_t; + // // Player internal flags // @@ -95,11 +103,9 @@ typedef enum PF_RINGLOCK = 1<<13, // Prevent picking up rings while SPB is locked on - // The following four flags are mutually exclusive, although they can also all be off at the same time. If we ever run out of pflags, eventually turn them into a seperate five(+) mode UINT8..? - PF_USERINGS = 1<<14, // Have to be not holding the item button to change from using rings to using items (or vice versa) - prevents weirdness - PF_ITEMOUT = 1<<15, // Are you holding an item out? - PF_EGGMANOUT = 1<<16, // Eggman mark held, separate from PF_ITEMOUT so it doesn't stop you from getting items - PF_HOLDREADY = 1<<17, // Hold button-style item is ready to activate + PF_LITESTEER = 1<<14, // Hold Down to shallow turn (digital only) + + //15-17 free, was previously itemflags stuff PF_DRIFTINPUT = 1<<18, // Drifting! PF_GETSPARKS = 1<<19, // Can get sparks @@ -942,6 +948,8 @@ struct player_t UINT8 ringboxdelay; // Delay until Ring Box auto-activates UINT8 ringboxaward; // Where did we stop? + UINT8 itemflags; // holds IF_ flags (see itemflags_t) + fixed_t outrun; // Milky Way road effect uint8_t public_key[PUBKEYLENGTH]; diff --git a/src/deh_tables.c b/src/deh_tables.c index e80bcb37a..7175b7a35 100644 --- a/src/deh_tables.c +++ b/src/deh_tables.c @@ -6014,13 +6014,13 @@ const char *const MOBJFLAG_LIST[] = { "SLOPE", "MISSILE", "SPRING", - "MONITOR", + "ELEMENTAL", "NOTHINK", "NOCLIPHEIGHT", "ENEMY", "SCENERY", "PAIN", - "STICKY", + "DONTPUNT", "APPLYTERRAIN", "NOCLIPTHING", "GRENADEBOUNCE", @@ -6120,11 +6120,10 @@ const char *const PLAYERFLAG_LIST[] = { "RINGLOCK", // Prevent picking up rings while SPB is locked on - // The following four flags are mutually exclusive, although they can also all be off at the same time. If we ever run out of pflags, eventually turn them into a seperate five(+) mode UINT8..? - "USERINGS", // Have to be not holding the item button to change from using rings to using items (or vice versa) - prevents weirdness - "ITEMOUT", // Are you holding an item out? - "EGGMANOUT", // Eggman mark held, separate from PF_ITEMOUT so it doesn't stop you from getting items - "HOLDREADY", // Hold button-style item is ready to activate + "LITESTEER", // Shallow digital turn with DOWN + "\x01", // Free + "\x01", // Free + "\x01", // Free "DRIFTINPUT", // Drifting! "GETSPARKS", // Can get sparks diff --git a/src/g_build_ticcmd.cpp b/src/g_build_ticcmd.cpp index 81d431a12..6dca175da 100644 --- a/src/g_build_ticcmd.cpp +++ b/src/g_build_ticcmd.cpp @@ -380,7 +380,7 @@ class TiccmdBuilder // ugly with the current abstractions, though, and there's a fortunate trick here: // if you can input full strength turns on both axes, either you're using a fucking // square gate, or you're not on an analog device. - if (joystickvector.yaxis >= JOYAXISRANGE && abs(cmd->turning) == KART_FULLTURN) // >= beacuse some analog devices can go past JOYAXISRANGE (?!) + if (cv_litesteer[ssplayer - 1].value && joystickvector.yaxis >= JOYAXISRANGE && abs(cmd->turning) == KART_FULLTURN) // >= beacuse some analog devices can go past JOYAXISRANGE (?!) cmd->turning /= 2; } diff --git a/src/g_demo.c b/src/g_demo.c index d039ddfdd..3a6bd1430 100644 --- a/src/g_demo.c +++ b/src/g_demo.c @@ -127,6 +127,7 @@ demoghost *ghosts = NULL; #define DEMO_SHRINKME 0x04 #define DEMO_BOT 0x08 #define DEMO_AUTOROULETTE 0x10 +#define DEMO_LITESTEER 0x20 // For demos #define ZT_FWD 0x0001 @@ -1329,7 +1330,7 @@ readghosttic: z = READFIXED(g->p); angle = READANGLE(g->p); if (!(mobjinfo[type].flags & MF_SHOOTABLE) - || !(mobjinfo[type].flags & (MF_ENEMY|MF_MONITOR)) + || !(mobjinfo[type].flags & MF_ENEMY) || health != 0 || i >= 4) // only spawn for the first 4 hits per frame, to prevent ghosts from splode-spamming too bad. continue; poof = P_SpawnMobj(x, y, z, MT_GHOST); @@ -2480,6 +2481,8 @@ void G_BeginRecording(void) i |= DEMO_KICKSTART; if (player->pflags & PF_AUTOROULETTE) i |= DEMO_AUTOROULETTE; + if (player->pflags & PF_LITESTEER) + i |= DEMO_LITESTEER; if (player->pflags & PF_SHRINKME) i |= DEMO_SHRINKME; if (player->bot == true) @@ -3447,6 +3450,11 @@ void G_DoPlayDemo(const char *defdemoname) else players[p].pflags &= ~PF_AUTOROULETTE; + if (flags & DEMO_LITESTEER) + players[p].pflags |= PF_LITESTEER; + else + players[p].pflags &= ~PF_LITESTEER; + if (flags & DEMO_SHRINKME) players[p].pflags |= PF_SHRINKME; else diff --git a/src/g_game.c b/src/g_game.c index 687af8a7f..c66923d2a 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -2127,7 +2127,7 @@ void G_PlayerReborn(INT32 player, boolean betweenmaps) totalring = players[player].totalring; xtralife = players[player].xtralife; - pflags = (players[player].pflags & (PF_WANTSTOJOIN|PF_KICKSTARTACCEL|PF_SHRINKME|PF_SHRINKACTIVE|PF_AUTOROULETTE)); + pflags = (players[player].pflags & (PF_WANTSTOJOIN|PF_KICKSTARTACCEL|PF_SHRINKME|PF_SHRINKACTIVE|PF_AUTOROULETTE|PF_LITESTEER)); // SRB2kart memcpy(&itemRoulette, &players[player].itemRoulette, sizeof (itemRoulette)); @@ -2145,7 +2145,7 @@ void G_PlayerReborn(INT32 player, boolean betweenmaps) { rings = 0; } - else if (modeattacking & ATTACKING_SPB) + else if (G_TimeAttackStart()) { rings = 20; } @@ -2175,7 +2175,7 @@ void G_PlayerReborn(INT32 player, boolean betweenmaps) } else { - if (players[player].pflags & PF_ITEMOUT) + if (players[player].itemflags & IF_ITEMOUT) { itemtype = 0; itemamount = 0; diff --git a/src/g_game.h b/src/g_game.h index fc747ae7b..9464a6e8a 100644 --- a/src/g_game.h +++ b/src/g_game.h @@ -99,6 +99,7 @@ extern consvar_t cv_pauseifunfocused; extern consvar_t cv_kickstartaccel[MAXSPLITSCREENPLAYERS]; extern consvar_t cv_autoroulette[MAXSPLITSCREENPLAYERS]; +extern consvar_t cv_litesteer[MAXSPLITSCREENPLAYERS]; extern consvar_t cv_shrinkme[MAXSPLITSCREENPLAYERS]; extern consvar_t cv_deadzone[MAXSPLITSCREENPLAYERS]; diff --git a/src/info.c b/src/info.c index e777c2784..546cd2b68 100644 --- a/src/info.c +++ b/src/info.c @@ -4848,12 +4848,12 @@ state_t states[NUMSTATES] = {SPR_FLEN, FF_FULLBRIGHT|1, 3, {NULL}, 0, 0, S_FLINGENERGY3}, // S_FLINGENERGY2, {SPR_FLEN, FF_FULLBRIGHT|2, 3, {NULL}, 0, 0, S_NULL}, // S_FLINGENERGY3, - {SPR_CLAS, FF_FULLBRIGHT|FF_TRANS30, 2, {A_PlayActiveSound}, 0, 0, S_CLASH2}, // S_CLASH1 - {SPR_CLAS, FF_FULLBRIGHT|FF_TRANS30|1, 2, {NULL}, 0, 0, S_CLASH3}, // S_CLASH2 - {SPR_CLAS, FF_FULLBRIGHT|FF_TRANS30|2, 2, {NULL}, 0, 0, S_CLASH4}, // S_CLASH3 - {SPR_CLAS, FF_FULLBRIGHT|FF_TRANS30|3, 2, {NULL}, 0, 0, S_CLASH5}, // S_CLASH4 - {SPR_CLAS, FF_FULLBRIGHT|FF_TRANS30|4, 2, {NULL}, 0, 0, S_CLASH6}, // S_CLASH5 - {SPR_CLAS, FF_FULLBRIGHT|FF_TRANS30|5, 2, {NULL}, 0, 0, S_NULL}, // S_CLASH6 + {SPR_CLAS, FF_FULLBRIGHT|FF_ADD, 2, {A_PlayActiveSound}, 0, 0, S_CLASH2}, // S_CLASH1 + {SPR_CLAS, FF_FULLBRIGHT|FF_ADD|1, 2, {NULL}, 0, 0, S_CLASH3}, // S_CLASH2 + {SPR_CLAS, FF_FULLBRIGHT|FF_ADD|2, 2, {NULL}, 0, 0, S_CLASH4}, // S_CLASH3 + {SPR_CLAS, FF_FULLBRIGHT|FF_ADD|3, 2, {NULL}, 0, 0, S_CLASH5}, // S_CLASH4 + {SPR_CLAS, FF_FULLBRIGHT|FF_ADD|4, 2, {NULL}, 0, 0, S_CLASH6}, // S_CLASH5 + {SPR_CLAS, FF_FULLBRIGHT|FF_ADD|5, 2, {NULL}, 0, 0, S_NULL}, // S_CLASH6 {SPR_PSHW, FF_FULLBRIGHT, 3, {NULL}, 0, 0, S_FIREDITEM2}, // S_FIREDITEM1 {SPR_PSHW, FF_FULLBRIGHT|1, 3, {NULL}, 0, 0, S_FIREDITEM3}, // S_FIREDITEM2 @@ -5775,7 +5775,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = 1000, // mass MT_THOK, // damage sfx_None, // activesound - MF_SOLID|MF_SHOOTABLE|MF_DONTENCOREMAP|MF_APPLYTERRAIN|MF_SLOPE, // flags + MF_SOLID|MF_SHOOTABLE|MF_DONTENCOREMAP|MF_APPLYTERRAIN|MF_SLOPE|MF_DONTPUNT, // flags (statenum_t)MT_THOK // raisestate }, @@ -9581,7 +9581,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = 100, // mass MT_RING_ICON, // damage sfx_None, // activesound - MF_SOLID|MF_SHOOTABLE|MF_MONITOR, // flags + MF_SOLID|MF_SHOOTABLE, // flags S_NULL // raisestate }, @@ -9608,7 +9608,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = 100, // mass MT_PITY_ICON, // damage sfx_None, // activesound - MF_SOLID|MF_SHOOTABLE|MF_MONITOR, // flags + MF_SOLID|MF_SHOOTABLE, // flags S_NULL // raisestate }, @@ -9635,7 +9635,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = 100, // mass MT_ATTRACT_ICON,// damage sfx_None, // activesound - MF_SOLID|MF_SHOOTABLE|MF_MONITOR, // flags + MF_SOLID|MF_SHOOTABLE, // flags S_NULL // raisestate }, @@ -9662,7 +9662,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = 100, // mass MT_FORCE_ICON, // damage sfx_None, // activesound - MF_SOLID|MF_SHOOTABLE|MF_MONITOR, // flags + MF_SOLID|MF_SHOOTABLE, // flags S_NULL // raisestate }, @@ -9689,7 +9689,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = 100, // mass MT_ARMAGEDDON_ICON, // damage sfx_None, // activesound - MF_SOLID|MF_SHOOTABLE|MF_MONITOR, // flags + MF_SOLID|MF_SHOOTABLE, // flags S_NULL // raisestate }, @@ -9716,7 +9716,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = 100, // mass MT_WHIRLWIND_ICON, // damage sfx_None, // activesound - MF_SOLID|MF_SHOOTABLE|MF_MONITOR, // flags + MF_SOLID|MF_SHOOTABLE, // flags S_NULL // raisestate }, @@ -9743,7 +9743,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = 100, // mass MT_ELEMENTAL_ICON, // damage sfx_None, // activesound - MF_SOLID|MF_SHOOTABLE|MF_MONITOR, // flags + MF_SOLID|MF_SHOOTABLE, // flags S_NULL // raisestate }, @@ -9770,7 +9770,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = 100, // mass MT_SNEAKERS_ICON, // damage sfx_None, // activesound - MF_SOLID|MF_SHOOTABLE|MF_MONITOR, // flags + MF_SOLID|MF_SHOOTABLE, // flags S_NULL // raisestate }, @@ -9797,7 +9797,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = 100, // mass MT_INVULN_ICON, // damage sfx_None, // activesound - MF_SOLID|MF_SHOOTABLE|MF_MONITOR, // flags + MF_SOLID|MF_SHOOTABLE, // flags S_NULL // raisestate }, @@ -9824,7 +9824,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = 100, // mass MT_1UP_ICON, // damage sfx_None, // activesound - MF_SOLID|MF_SHOOTABLE|MF_MONITOR, // flags + MF_SOLID|MF_SHOOTABLE, // flags S_NULL // raisestate }, @@ -9851,7 +9851,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = 100, // mass MT_EGGMAN_ICON, // damage sfx_None, // activesound - MF_SOLID|MF_SHOOTABLE|MF_MONITOR, // flags + MF_SOLID|MF_SHOOTABLE, // flags S_NULL // raisestate }, @@ -9878,7 +9878,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = 100, // mass MT_MIXUP_ICON, // damage sfx_None, // activesound - MF_SOLID|MF_SHOOTABLE|MF_MONITOR, // flags + MF_SOLID|MF_SHOOTABLE, // flags S_NULL // raisestate }, @@ -9905,7 +9905,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = 100, // mass MT_UNKNOWN, // damage sfx_None, // activesound - MF_SOLID|MF_SHOOTABLE|MF_MONITOR, // flags + MF_SOLID|MF_SHOOTABLE, // flags S_NULL // raisestate }, @@ -9932,7 +9932,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = 100, // mass MT_GRAVITY_ICON, // damage sfx_None, // activesound - MF_SOLID|MF_SHOOTABLE|MF_MONITOR, // flags + MF_SOLID|MF_SHOOTABLE, // flags S_NULL // raisestate }, @@ -9959,7 +9959,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = 100, // mass MT_RECYCLER_ICON, // damage sfx_None, // activesound - MF_SOLID|MF_SHOOTABLE|MF_MONITOR, // flags + MF_SOLID|MF_SHOOTABLE, // flags S_NULL // raisestate }, @@ -9986,7 +9986,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = 100, // mass MT_SCORE1K_ICON, // damage sfx_None, // activesound - MF_SOLID|MF_SHOOTABLE|MF_MONITOR, // flags + MF_SOLID|MF_SHOOTABLE, // flags S_NULL // raisestate }, @@ -10013,7 +10013,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = 100, // mass MT_SCORE10K_ICON, // damage sfx_None, // activesound - MF_SOLID|MF_SHOOTABLE|MF_MONITOR, // flags + MF_SOLID|MF_SHOOTABLE, // flags S_NULL // raisestate }, @@ -10040,7 +10040,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = 100, // mass MT_FLAMEAURA_ICON, // damage sfx_None, // activesound - MF_SOLID|MF_SHOOTABLE|MF_MONITOR, // flags + MF_SOLID|MF_SHOOTABLE, // flags S_NULL // raisestate }, @@ -10067,7 +10067,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = 100, // mass MT_BUBBLEWRAP_ICON, // damage sfx_None, // activesound - MF_SOLID|MF_SHOOTABLE|MF_MONITOR, // flags + MF_SOLID|MF_SHOOTABLE, // flags S_NULL // raisestate }, @@ -10094,7 +10094,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = 100, // mass MT_THUNDERCOIN_ICON, // damage sfx_None, // activesound - MF_SOLID|MF_SHOOTABLE|MF_MONITOR, // flags + MF_SOLID|MF_SHOOTABLE, // flags S_NULL // raisestate }, @@ -10121,7 +10121,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = 100, // mass MT_PITY_ICON, // damage sfx_None, // activesound - MF_SOLID|MF_SHOOTABLE|MF_MONITOR|MF_GRENADEBOUNCE, // flags + MF_SOLID|MF_SHOOTABLE|MF_GRENADEBOUNCE, // flags S_NULL // raisestate }, @@ -10148,7 +10148,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = 100, // mass MT_ATTRACT_ICON,// damage sfx_None, // activesound - MF_SOLID|MF_SHOOTABLE|MF_MONITOR|MF_GRENADEBOUNCE, // flags + MF_SOLID|MF_SHOOTABLE|MF_GRENADEBOUNCE, // flags S_NULL // raisestate }, @@ -10175,7 +10175,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = 100, // mass MT_FORCE_ICON, // damage sfx_None, // activesound - MF_SOLID|MF_SHOOTABLE|MF_MONITOR|MF_GRENADEBOUNCE, // flags + MF_SOLID|MF_SHOOTABLE|MF_GRENADEBOUNCE, // flags S_NULL // raisestate }, @@ -10202,7 +10202,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = 100, // mass MT_ARMAGEDDON_ICON, // damage sfx_None, // activesound - MF_SOLID|MF_SHOOTABLE|MF_MONITOR|MF_GRENADEBOUNCE, // flags + MF_SOLID|MF_SHOOTABLE|MF_GRENADEBOUNCE, // flags S_NULL // raisestate }, @@ -10229,7 +10229,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = 100, // mass MT_WHIRLWIND_ICON, // damage sfx_None, // activesound - MF_SOLID|MF_SHOOTABLE|MF_MONITOR|MF_GRENADEBOUNCE, // flags + MF_SOLID|MF_SHOOTABLE|MF_GRENADEBOUNCE, // flags S_NULL // raisestate }, @@ -10256,7 +10256,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = 100, // mass MT_ELEMENTAL_ICON, // damage sfx_None, // activesound - MF_SOLID|MF_SHOOTABLE|MF_MONITOR|MF_GRENADEBOUNCE, // flags + MF_SOLID|MF_SHOOTABLE|MF_GRENADEBOUNCE, // flags S_NULL // raisestate }, @@ -10283,7 +10283,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = 100, // mass MT_SNEAKERS_ICON, // damage sfx_None, // activesound - MF_SOLID|MF_SHOOTABLE|MF_MONITOR|MF_GRENADEBOUNCE, // flags + MF_SOLID|MF_SHOOTABLE|MF_GRENADEBOUNCE, // flags S_NULL // raisestate }, @@ -10310,7 +10310,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = 100, // mass MT_INVULN_ICON, // damage sfx_None, // activesound - MF_SOLID|MF_SHOOTABLE|MF_MONITOR|MF_GRENADEBOUNCE, // flags + MF_SOLID|MF_SHOOTABLE|MF_GRENADEBOUNCE, // flags S_NULL // raisestate }, @@ -10337,7 +10337,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = 100, // mass MT_EGGMAN_ICON, // damage sfx_None, // activesound - MF_SOLID|MF_SHOOTABLE|MF_MONITOR|MF_GRENADEBOUNCE, // flags + MF_SOLID|MF_SHOOTABLE|MF_GRENADEBOUNCE, // flags S_NULL // raisestate }, @@ -10364,7 +10364,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = 100, // mass MT_GRAVITY_ICON, // damage sfx_None, // activesound - MF_SOLID|MF_SHOOTABLE|MF_MONITOR|MF_GRENADEBOUNCE, // flags + MF_SOLID|MF_SHOOTABLE|MF_GRENADEBOUNCE, // flags S_NULL // raisestate }, @@ -10391,7 +10391,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = 100, // mass MT_FLAMEAURA_ICON, // damage sfx_None, // activesound - MF_SOLID|MF_SHOOTABLE|MF_MONITOR|MF_GRENADEBOUNCE, // flags + MF_SOLID|MF_SHOOTABLE|MF_GRENADEBOUNCE, // flags S_NULL // raisestate }, @@ -10418,7 +10418,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = 100, // mass MT_BUBBLEWRAP_ICON, // damage sfx_None, // activesound - MF_SOLID|MF_SHOOTABLE|MF_MONITOR|MF_GRENADEBOUNCE, // flags + MF_SOLID|MF_SHOOTABLE|MF_GRENADEBOUNCE, // flags S_NULL // raisestate }, @@ -10445,7 +10445,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = 100, // mass MT_THUNDERCOIN_ICON, // damage sfx_None, // activesound - MF_SOLID|MF_SHOOTABLE|MF_MONITOR|MF_GRENADEBOUNCE, // flags + MF_SOLID|MF_SHOOTABLE|MF_GRENADEBOUNCE, // flags S_NULL // raisestate }, @@ -10472,7 +10472,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = 100, // mass MT_RING_ICON, // damage sfx_None, // activesound - MF_SOLID|MF_SHOOTABLE|MF_MONITOR, // flags + MF_SOLID|MF_SHOOTABLE, // flags S_NULL // raisestate }, @@ -10499,7 +10499,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = 100, // mass MT_RING_ICON, // damage sfx_None, // activesound - MF_SOLID|MF_SHOOTABLE|MF_MONITOR, // flags + MF_SOLID|MF_SHOOTABLE, // flags S_NULL // raisestate }, @@ -14651,13 +14651,13 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = S_NULL, // xdeathstate sfx_None, // deathsound 5*FRACUNIT, // speed - 8*FRACUNIT, // radius - 8*FRACUNIT, // height + 16*FRACUNIT, // radius + 32*FRACUNIT, // height 0, // display offset DMG_NORMAL, // mass 0, // damage sfx_None, // activesound - MF_NOGRAVITY|MF_MISSILE|MF_PAIN, // flags + MF_NOGRAVITY|MF_MISSILE|MF_PAIN|MF_NOSQUISH|MF_NOHITLAGFORME|MF_ELEMENTAL, // flags S_NULL // raisestate }, @@ -23144,7 +23144,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = 100, // mass 0, // damage sfx_None, // activesound - MF_NOGRAVITY|MF_NOCLIPHEIGHT|MF_DONTENCOREMAP, // flags + MF_NOGRAVITY|MF_NOCLIPHEIGHT|MF_DONTENCOREMAP|MF_DONTPUNT, // flags S_NULL // raisestate }, @@ -24197,7 +24197,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = 100, // mass 1, // damage sfx_peel, // activesound - MF_SHOOTABLE|MF_DONTENCOREMAP|MF_APPLYTERRAIN|MF_SLOPE, // flags + MF_SHOOTABLE|MF_DONTENCOREMAP|MF_APPLYTERRAIN|MF_SLOPE|MF_DONTPUNT, // flags S_NULL // raisestate }, @@ -24224,7 +24224,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = 100, // mass 1, // damage sfx_None, // activesound - MF_SHOOTABLE|MF_NOGRAVITY|MF_SCENERY|MF_DONTENCOREMAP|MF_APPLYTERRAIN|MF_SLOPE, // flags + MF_SHOOTABLE|MF_NOGRAVITY|MF_SCENERY|MF_DONTENCOREMAP|MF_APPLYTERRAIN|MF_SLOPE|MF_DONTPUNT, // flags S_NULL // raisestate }, @@ -24278,7 +24278,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = 100, // mass 1, // damage sfx_s3k96, // activesound - MF_SHOOTABLE|MF_DONTENCOREMAP|MF_APPLYTERRAIN|MF_SLOPE, // flags + MF_SHOOTABLE|MF_DONTENCOREMAP|MF_APPLYTERRAIN|MF_SLOPE|MF_DONTPUNT, // flags S_NULL // raisestate }, @@ -24305,7 +24305,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = 100, // mass 1, // damage sfx_None, // activesound - MF_SHOOTABLE|MF_NOGRAVITY|MF_SCENERY|MF_DONTENCOREMAP|MF_APPLYTERRAIN|MF_SLOPE, // flags + MF_SHOOTABLE|MF_NOGRAVITY|MF_SCENERY|MF_DONTENCOREMAP|MF_APPLYTERRAIN|MF_SLOPE|MF_DONTPUNT, // flags S_NULL // raisestate }, @@ -24332,7 +24332,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = 100, // mass 1, // damage sfx_s3kc0s, // activesound - MF_SHOOTABLE|MF_DONTENCOREMAP|MF_APPLYTERRAIN|MF_SLOPE, // flags + MF_SHOOTABLE|MF_DONTENCOREMAP|MF_APPLYTERRAIN|MF_SLOPE|MF_DONTPUNT, // flags S_NULL // raisestate }, @@ -24359,7 +24359,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = 100, // mass 1, // damage sfx_None, // activesound - MF_SHOOTABLE|MF_NOGRAVITY|MF_SCENERY|MF_DONTENCOREMAP|MF_APPLYTERRAIN|MF_SLOPE, // flags + MF_SHOOTABLE|MF_NOGRAVITY|MF_SCENERY|MF_DONTENCOREMAP|MF_APPLYTERRAIN|MF_SLOPE|MF_DONTPUNT, // flags S_NULL // raisestate }, @@ -24413,7 +24413,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = 100, // mass 1, // damage sfx_s3k5c, // activesound - MF_SHOOTABLE|MF_DONTENCOREMAP|MF_APPLYTERRAIN|MF_SLOPE, // flags + MF_SHOOTABLE|MF_DONTENCOREMAP|MF_APPLYTERRAIN|MF_SLOPE|MF_DONTPUNT, // flags S_NULL // raisestate }, @@ -24440,7 +24440,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = 100, // mass 1, // damage sfx_None, // activesound - MF_SHOOTABLE|MF_NOGRAVITY|MF_SCENERY|MF_DONTENCOREMAP|MF_APPLYTERRAIN|MF_SLOPE, // flags + MF_SHOOTABLE|MF_NOGRAVITY|MF_SCENERY|MF_DONTENCOREMAP|MF_APPLYTERRAIN|MF_SLOPE|MF_DONTPUNT, // flags S_NULL // raisestate }, @@ -24548,7 +24548,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = 0, // mass 0, // damage sfx_s3k5c, // activesound - MF_SHOOTABLE|MF_DONTENCOREMAP|MF_APPLYTERRAIN|MF_SLOPE, // flags + MF_SHOOTABLE|MF_DONTENCOREMAP|MF_APPLYTERRAIN|MF_SLOPE|MF_DONTPUNT, // flags S_NULL // raisestate }, @@ -24575,7 +24575,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = 100, // mass 1, // damage sfx_s3k96, // activesound - MF_SPECIAL|MF_DONTENCOREMAP|MF_APPLYTERRAIN|MF_SLOPE, // flags + MF_SPECIAL|MF_DONTENCOREMAP|MF_APPLYTERRAIN|MF_SLOPE|MF_DONTPUNT, // flags S_NULL // raisestate }, @@ -24602,7 +24602,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = 100, // mass 1, // damage sfx_None, // activesound - MF_SPECIAL|MF_NOGRAVITY|MF_SCENERY|MF_DONTENCOREMAP|MF_APPLYTERRAIN|MF_SLOPE, // flags + MF_SPECIAL|MF_NOGRAVITY|MF_SCENERY|MF_DONTENCOREMAP|MF_APPLYTERRAIN|MF_SLOPE|MF_DONTPUNT, // flags S_NULL // raisestate }, @@ -24656,7 +24656,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = 100, // mass 1, // damage sfx_None, // activesound - MF_SHOOTABLE|MF_DONTENCOREMAP|MF_APPLYTERRAIN, // flags + MF_SHOOTABLE|MF_DONTENCOREMAP|MF_APPLYTERRAIN|MF_DONTPUNT, // flags S_NULL // raisestate }, @@ -24710,7 +24710,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = 100, // mass 1, // damage sfx_kc64, // activesound - MF_SOLID|MF_NOGRAVITY|MF_NOCLIP|MF_NOCLIPHEIGHT|MF_DONTENCOREMAP, // flags + MF_SOLID|MF_NOGRAVITY|MF_NOCLIP|MF_NOCLIPHEIGHT|MF_DONTENCOREMAP|MF_DONTPUNT, // flags S_NULL // raisestate }, @@ -24953,7 +24953,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = 100, // mass 0, // damage sfx_None, // activesound - MF_NOCLIPTHING|MF_DONTENCOREMAP, // flags + MF_NOCLIPTHING|MF_DONTENCOREMAP|MF_DONTPUNT, // flags S_NULL // raisestate }, @@ -25250,7 +25250,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = 100, // mass 1, // damage sfx_s3k5c, // activesound - MF_SHOOTABLE|MF_DONTENCOREMAP|MF_APPLYTERRAIN, // flags + MF_SHOOTABLE|MF_DONTENCOREMAP|MF_APPLYTERRAIN|MF_DONTPUNT, // flags S_NULL // raisestate }, @@ -25277,7 +25277,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = 100, // mass 1, // damage sfx_None, // activesound - MF_NOGRAVITY|MF_SCENERY|MF_DONTENCOREMAP|MF_APPLYTERRAIN|MF_SLOPE, // flags + MF_NOGRAVITY|MF_SCENERY|MF_DONTENCOREMAP|MF_APPLYTERRAIN|MF_SLOPE|MF_DONTPUNT, // flags S_NULL // raisestate }, @@ -25331,7 +25331,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = 100, // mass 1, // damage sfx_s3k96, // activesound - MF_SHOOTABLE|MF_DONTENCOREMAP|MF_APPLYTERRAIN|MF_SLOPE, // flags + MF_SHOOTABLE|MF_DONTENCOREMAP|MF_APPLYTERRAIN|MF_SLOPE|MF_DONTPUNT, // flags S_NULL // raisestate }, @@ -25385,7 +25385,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = 0, // mass 0, // damage sfx_None, // activesound - MF_SPECIAL|MF_DONTENCOREMAP|MF_APPLYTERRAIN, // flags + MF_SPECIAL|MF_DONTENCOREMAP|MF_APPLYTERRAIN|MF_DONTPUNT, // flags S_NULL // raisestate }, @@ -30709,7 +30709,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = 0, // mass 0, // damage sfx_None, // activesound - MF_SPECIAL|MF_NOGRAVITY|MF_NOCLIP|MF_NOCLIPHEIGHT, // flags + MF_SPECIAL|MF_NOGRAVITY|MF_NOCLIP|MF_NOCLIPHEIGHT|MF_DONTPUNT, // flags S_NULL // raisestate }, diff --git a/src/k_botitem.c b/src/k_botitem.c index c483afdb5..ee9fe577e 100644 --- a/src/k_botitem.c +++ b/src/k_botitem.c @@ -440,7 +440,7 @@ static boolean K_BotRevealsGenericTrap(player_t *player, INT16 turnamt, boolean --------------------------------------------------*/ static void K_BotItemGenericTrapShield(player_t *player, ticcmd_t *cmd, INT16 turnamt, boolean mine) { - if (player->pflags & PF_ITEMOUT) + if (player->itemflags & IF_ITEMOUT) { return; } @@ -465,7 +465,7 @@ static void K_BotItemGenericTrapShield(player_t *player, ticcmd_t *cmd, INT16 tu --------------------------------------------------*/ static void K_BotItemGenericOrbitShield(player_t *player, ticcmd_t *cmd) { - if (player->pflags & PF_ITEMOUT) + if (player->itemflags & IF_ITEMOUT) { return; } @@ -811,7 +811,7 @@ static boolean K_BotRevealsEggbox(player_t *player) --------------------------------------------------*/ static void K_BotItemEggmanShield(player_t *player, ticcmd_t *cmd) { - if (player->pflags & PF_EGGMANOUT) + if (player->itemflags & IF_EGGMANOUT) { return; } @@ -1221,7 +1221,7 @@ static void K_BotItemBubble(player_t *player, ticcmd_t *cmd) hold = true; } - if (hold && (player->pflags & PF_HOLDREADY)) + if (hold && (player->itemflags & IF_HOLDREADY)) { cmd->buttons |= BT_ATTACK; } @@ -1245,7 +1245,7 @@ static void K_BotItemFlame(player_t *player, ticcmd_t *cmd) { player->botvars.itemconfirm--; } - else if (player->pflags & PF_HOLDREADY) + else if (player->itemflags & IF_HOLDREADY) { INT32 flamemax = player->flamelength; @@ -1532,7 +1532,7 @@ static void K_BotItemRouletteMash(player_t *player, ticcmd_t *cmd) --------------------------------------------------*/ void K_BotItemUsage(player_t *player, ticcmd_t *cmd, INT16 turnamt) { - if (player->pflags & PF_USERINGS) + if (player->itemflags & IF_USERINGS) { if (player->rings > 0) { @@ -1567,7 +1567,7 @@ void K_BotItemUsage(player_t *player, ticcmd_t *cmd, INT16 turnamt) { K_BotItemEggmanExplosion(player, cmd); } - else if (player->pflags & PF_EGGMANOUT) + else if (player->itemflags & IF_EGGMANOUT) { K_BotItemEggman(player, cmd); } @@ -1604,7 +1604,7 @@ void K_BotItemUsage(player_t *player, ticcmd_t *cmd, INT16 turnamt) K_BotItemSneaker(player, cmd); break; case KITEM_BANANA: - if (!(player->pflags & PF_ITEMOUT)) + if (!(player->itemflags & IF_ITEMOUT)) { K_BotItemGenericTrapShield(player, cmd, turnamt, false); } @@ -1617,7 +1617,7 @@ void K_BotItemUsage(player_t *player, ticcmd_t *cmd, INT16 turnamt) K_BotItemEggmanShield(player, cmd); break; case KITEM_ORBINAUT: - if (!(player->pflags & PF_ITEMOUT)) + if (!(player->itemflags & IF_ITEMOUT)) { K_BotItemGenericOrbitShield(player, cmd); } @@ -1627,7 +1627,7 @@ void K_BotItemUsage(player_t *player, ticcmd_t *cmd, INT16 turnamt) } break; case KITEM_JAWZ: - if (!(player->pflags & PF_ITEMOUT)) + if (!(player->itemflags & IF_ITEMOUT)) { K_BotItemGenericOrbitShield(player, cmd); } @@ -1637,7 +1637,7 @@ void K_BotItemUsage(player_t *player, ticcmd_t *cmd, INT16 turnamt) } break; case KITEM_MINE: - if (!(player->pflags & PF_ITEMOUT)) + if (!(player->itemflags & IF_ITEMOUT)) { K_BotItemGenericTrapShield(player, cmd, turnamt, true); } @@ -1654,7 +1654,7 @@ void K_BotItemUsage(player_t *player, ticcmd_t *cmd, INT16 turnamt) K_BotItemBallhog(player, cmd); break; case KITEM_DROPTARGET: - if (!(player->pflags & PF_ITEMOUT)) + if (!(player->itemflags & IF_ITEMOUT)) { K_BotItemGenericTrapShield(player, cmd, turnamt, false); } diff --git a/src/k_botsearch.c b/src/k_botsearch.c index bdc7ecf62..8d0fc1bc7 100644 --- a/src/k_botsearch.c +++ b/src/k_botsearch.c @@ -577,8 +577,8 @@ static BlockItReturn_t K_FindObjectsForNudging(mobj_t *thing) } // Has held item shield else if (K_PlayerAttackSteer(thing, side, 20, - (thing->player->pflags & (PF_ITEMOUT|PF_EGGMANOUT)), - (g_nudgeSearch.botmo->player->pflags & (PF_ITEMOUT|PF_EGGMANOUT)) + (thing->player->itemflags & (IF_ITEMOUT|IF_EGGMANOUT)), + (g_nudgeSearch.botmo->player->itemflags & (IF_ITEMOUT|IF_EGGMANOUT)) )) { break; diff --git a/src/k_collide.cpp b/src/k_collide.cpp index 87a4a6862..76917d2b5 100644 --- a/src/k_collide.cpp +++ b/src/k_collide.cpp @@ -18,6 +18,7 @@ #include "k_podium.h" #include "k_powerup.h" #include "k_hitlag.h" +#include "m_random.h" angle_t K_GetCollideAngle(mobj_t *t1, mobj_t *t2) { @@ -190,7 +191,7 @@ boolean K_EggItemCollide(mobj_t *t1, mobj_t *t2) if (t1->target->hnext == t1) { P_SetTarget(&t1->target->hnext, NULL); - t1->target->player->pflags &= ~PF_EGGMANOUT; + t1->target->player->itemflags &= ~IF_EGGMANOUT; } } @@ -1170,3 +1171,114 @@ boolean K_PvPTouchDamage(mobj_t *t1, mobj_t *t2) return false; } + +void K_PuntHazard(mobj_t *t1, mobj_t *t2) +{ + // TODO: spawn a unique mobjtype other than MT_GHOST + mobj_t *img = P_SpawnGhostMobj(t1); + + K_MakeObjectReappear(t1); + + img->flags &= ~MF_NOGRAVITY; + img->renderflags = t1->renderflags & ~RF_DONTDRAW; + img->extravalue1 = 1; + img->extravalue2 = 2; + img->fuse = 2*TICRATE; + + struct Vector + { + fixed_t x_, y_, z_; + fixed_t h_ = FixedHypot(x_, y_); + fixed_t speed_ = std::max(60 * mapobjectscale, FixedHypot(h_, z_) * 2); + + explicit Vector(fixed_t x, fixed_t y, fixed_t z) : x_(x), y_(y), z_(z) {} + explicit Vector(const mobj_t* mo) : + Vector(std::max( + Vector(mo->x - mo->old_x, mo->y - mo->old_y, mo->z - mo->old_z), + Vector(mo->momx, mo->momy, mo->momz) + )) + { + } + explicit Vector(const Vector&) = default; + + bool operator<(const Vector& b) const { return speed_ < b.speed_; } + + void invert() + { + x_ = -x_; + y_ = -y_; + z_ = -z_; + } + + void thrust(mobj_t* mo) const + { + angle_t yaw = R_PointToAngle2(0, 0, h_, z_); + yaw = std::max(AbsAngle(yaw), static_cast(ANGLE_11hh)) + (yaw & ANGLE_180); + + P_InstaThrust(mo, R_PointToAngle2(0, 0, x_, y_), FixedMul(speed_, FCOS(yaw))); + mo->momz = FixedMul(speed_, FSIN(yaw)); + } + }; + + Vector h_vector(t1); + Vector p_vector(t2); + + h_vector.invert(); + + std::max(h_vector, p_vector).thrust(img); + + K_DoPowerClash(img, t2); // applies hitlag + P_SpawnMobj(t2->x/2 + t1->x/2, t2->y/2 + t1->y/2, t2->z/2 + t1->z/2, MT_ITEMCLASH); +} + +boolean K_PuntCollide(mobj_t *t1, mobj_t *t2) +{ + if (t1->flags & MF_DONTPUNT) + { + return false; + } + + if (!t2->player) + { + return false; + } + + if (!K_PlayerCanPunt(t2->player)) + { + return false; + } + + if (t1->flags & MF_ELEMENTAL) + { + K_MakeObjectReappear(t1); + + // copied from MT_ITEMCAPSULE + UINT8 i; + INT16 spacing = (t1->radius >> 1) / t1->scale; + // dust effects + for (i = 0; i < 10; i++) + { + mobj_t *puff = P_SpawnMobjFromMobj( + t1, + P_RandomRange(PR_ITEM_DEBRIS, -spacing, spacing) * FRACUNIT, + P_RandomRange(PR_ITEM_DEBRIS, -spacing, spacing) * FRACUNIT, + P_RandomRange(PR_ITEM_DEBRIS, 0, 4*spacing) * FRACUNIT, + MT_SPINDASHDUST + ); + + puff->momz = puff->scale * P_MobjFlip(puff); + + P_Thrust(puff, R_PointToAngle2(t2->x, t2->y, puff->x, puff->y), 3*puff->scale); + + puff->momx += t2->momx / 2; + puff->momy += t2->momy / 2; + puff->momz += t2->momz / 2; + } + } + else + { + K_PuntHazard(t1, t2); + } + + return true; +} diff --git a/src/k_collide.h b/src/k_collide.h index 84d9a324e..525e5b9c3 100644 --- a/src/k_collide.h +++ b/src/k_collide.h @@ -33,6 +33,9 @@ boolean K_SMKIceBlockCollide(mobj_t *t1, mobj_t *t2); boolean K_PvPTouchDamage(mobj_t *t1, mobj_t *t2); +void K_PuntHazard(mobj_t *t1, mobj_t *t2); +boolean K_PuntCollide(mobj_t *t1, mobj_t *t2); + #ifdef __cplusplus } // extern "C" #endif diff --git a/src/k_hud.c b/src/k_hud.c index ab26ae388..4f9d94729 100644 --- a/src/k_hud.c +++ b/src/k_hud.c @@ -1453,7 +1453,7 @@ static void K_drawKartItem(void) break; } - if ((stplyr->pflags & PF_ITEMOUT) && !(leveltime & 1)) + if ((stplyr->itemflags & IF_ITEMOUT) && !(leveltime & 1)) localpatch[1] = kp_nodraw; } diff --git a/src/k_kart.c b/src/k_kart.c index a4a2db32e..ddfc36387 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -6824,11 +6824,11 @@ void K_DropHnextList(player_t *player) player->bananadrag = 0; - if (player->pflags & PF_EGGMANOUT) + if (player->itemflags & IF_EGGMANOUT) { - player->pflags &= ~PF_EGGMANOUT; + player->itemflags &= ~IF_EGGMANOUT; } - else if ((player->pflags & PF_ITEMOUT) + else if ((player->itemflags & IF_ITEMOUT) && (dropall || (--player->itemamount <= 0))) { player->itemamount = 0; @@ -7221,11 +7221,11 @@ static void K_MoveHeldObjects(player_t *player) { player->bananadrag = 0; - if (player->pflags & PF_EGGMANOUT) + if (player->itemflags & IF_EGGMANOUT) { - player->pflags &= ~PF_EGGMANOUT; + player->itemflags &= ~IF_EGGMANOUT; } - else if (player->pflags & PF_ITEMOUT) + else if (player->itemflags & IF_ITEMOUT) { player->itemamount = 0; K_UnsetItemOut(player); @@ -7240,11 +7240,11 @@ static void K_MoveHeldObjects(player_t *player) P_SetTarget(&player->mo->hnext, NULL); player->bananadrag = 0; - if (player->pflags & PF_EGGMANOUT) + if (player->itemflags & IF_EGGMANOUT) { - player->pflags &= ~PF_EGGMANOUT; + player->itemflags &= ~IF_EGGMANOUT; } - else if (player->pflags & PF_ITEMOUT) + else if (player->itemflags & IF_ITEMOUT) { player->itemamount = 0; K_UnsetItemOut(player); @@ -8228,7 +8228,7 @@ void K_KartPlayerThink(player_t *player, ticcmd_t *cmd) } if (player->itemtype == KITEM_NONE) - player->pflags &= ~PF_HOLDREADY; + player->itemflags &= ~IF_HOLDREADY; // DKR style camera for boosting if (player->karthud[khud_boostcam] != 0 || player->karthud[khud_destboostcam] != 0) @@ -8610,7 +8610,7 @@ void K_KartPlayerThink(player_t *player, ticcmd_t *cmd) S_StopSoundByID(player->mo, sfx_wchrg2); } - if (player->itemamount || player->respawn.state != RESPAWNST_NONE || player->pflags & (PF_ITEMOUT|PF_EGGMANOUT) || player->rocketsneakertimer || player->ringboxdelay) + if (player->itemamount || player->respawn.state != RESPAWNST_NONE || player->itemflags & (IF_ITEMOUT|IF_EGGMANOUT) || player->rocketsneakertimer || player->ringboxdelay) player->instaWhipCharge = 0; if (player->tiregrease) @@ -8939,7 +8939,7 @@ void K_KartPlayerAfterThink(player_t *player) K_MoveHeldObjects(player); // Jawz reticule (seeking) - if (player->itemtype == KITEM_JAWZ && (player->pflags & PF_ITEMOUT)) + if (player->itemtype == KITEM_JAWZ && (player->itemflags & IF_ITEMOUT)) { const INT32 lastTargID = player->lastjawztarget; mobj_t *lastTarg = NULL; @@ -10430,7 +10430,7 @@ void K_StripItems(player_t *player) K_DropKitchenSink(player); player->itemtype = KITEM_NONE; player->itemamount = 0; - player->pflags &= ~(PF_ITEMOUT|PF_EGGMANOUT); + player->itemflags &= ~(IF_ITEMOUT|IF_EGGMANOUT); if (player->itemRoulette.eggman == false) { @@ -11274,7 +11274,7 @@ static void K_trickPanelTimingVisual(player_t *player, fixed_t momz) void K_SetItemOut(player_t *player) { - player->pflags |= PF_ITEMOUT; + player->itemflags |= IF_ITEMOUT; if (player->mo->scale >= FixedMul(GROW_PHYSICS_SCALE, mapobjectscale)) { @@ -11292,7 +11292,7 @@ void K_SetItemOut(player_t *player) void K_UnsetItemOut(player_t *player) { - player->pflags &= ~PF_ITEMOUT; + player->itemflags &= ~IF_ITEMOUT; player->itemscale = ITEMSCALE_NORMAL; player->bananadrag = 0; } @@ -11304,7 +11304,7 @@ void K_MoveKartPlayer(player_t *player, boolean onground) { ticcmd_t *cmd = &player->cmd; boolean ATTACK_IS_DOWN = ((cmd->buttons & BT_ATTACK) && !(player->oldcmd.buttons & BT_ATTACK) && (player->respawn.state == RESPAWNST_NONE)); - boolean HOLDING_ITEM = (player->pflags & (PF_ITEMOUT|PF_EGGMANOUT)); + boolean HOLDING_ITEM = (player->itemflags & (IF_ITEMOUT|IF_EGGMANOUT)); boolean NO_HYUDORO = (player->stealingtimer == 0); if (!player->exiting) @@ -11330,9 +11330,9 @@ void K_MoveKartPlayer(player_t *player, boolean onground) || player->itemRoulette.active == true || player->rocketsneakertimer || player->eggmanexplode)) - player->pflags |= PF_USERINGS; + player->itemflags |= IF_USERINGS; else - player->pflags &= ~PF_USERINGS; + player->itemflags &= ~IF_USERINGS; } if (player->ringboxdelay) @@ -11373,7 +11373,7 @@ void K_MoveKartPlayer(player_t *player, boolean onground) player->instaWhipCooldown = 0; } - if (leveltime < starttime || player->pflags & (PF_ITEMOUT|PF_EGGMANOUT) || player->rocketsneakertimer || player->instaWhipCooldown) + if (leveltime < starttime || player->itemflags & (IF_ITEMOUT|IF_EGGMANOUT) || player->rocketsneakertimer || player->instaWhipCooldown) { chargingwhip = false; player->instaWhipCharge = 0; @@ -11447,7 +11447,7 @@ void K_MoveKartPlayer(player_t *player, boolean onground) // First, the really specific, finicky items that function without the item being directly in your item slot. { // Ring boosting - if (player->pflags & PF_USERINGS) + if (player->itemflags & IF_USERINGS) { if ((cmd->buttons & BT_ATTACK) && !player->ringdelay && player->rings > 0) { @@ -11471,13 +11471,13 @@ void K_MoveKartPlayer(player_t *player, boolean onground) player->eggmanexplode = 1; } // Eggman Monitor throwing - else if (player->pflags & PF_EGGMANOUT) + else if (player->itemflags & IF_EGGMANOUT) { if (ATTACK_IS_DOWN) { K_ThrowKartItem(player, false, MT_EGGMANITEM, -1, 0, 0); K_PlayAttackTaunt(player->mo); - player->pflags &= ~PF_EGGMANOUT; + player->itemflags &= ~IF_EGGMANOUT; K_UpdateHnextList(player, true); } } @@ -11581,7 +11581,7 @@ void K_MoveKartPlayer(player_t *player, boolean onground) prev = mo; } } - else if (ATTACK_IS_DOWN && (player->pflags & PF_ITEMOUT)) // Banana x3 thrown + else if (ATTACK_IS_DOWN && (player->itemflags & IF_ITEMOUT)) // Banana x3 thrown { K_ThrowKartItem(player, false, MT_BANANA, -1, 0, 0); K_PlayAttackTaunt(player->mo); @@ -11594,7 +11594,7 @@ void K_MoveKartPlayer(player_t *player, boolean onground) { mobj_t *mo; player->itemamount--; - player->pflags |= PF_EGGMANOUT; + player->itemflags |= IF_EGGMANOUT; S_StartSound(player->mo, sfx_s254); mo = P_SpawnMobj(player->mo->x, player->mo->y, player->mo->z, MT_EGGMANITEM_SHIELD); if (mo) @@ -11644,7 +11644,7 @@ void K_MoveKartPlayer(player_t *player, boolean onground) prev = mo; } } - else if (ATTACK_IS_DOWN && (player->pflags & PF_ITEMOUT)) // Orbinaut x3 thrown + else if (ATTACK_IS_DOWN && (player->itemflags & IF_ITEMOUT)) // Orbinaut x3 thrown { K_ThrowKartItem(player, true, MT_ORBINAUT, 1, 0, 0); K_PlayAttackTaunt(player->mo); @@ -11685,7 +11685,7 @@ void K_MoveKartPlayer(player_t *player, boolean onground) prev = mo; } } - else if (ATTACK_IS_DOWN && HOLDING_ITEM && (player->pflags & PF_ITEMOUT)) // Jawz thrown + else if (ATTACK_IS_DOWN && HOLDING_ITEM && (player->itemflags & IF_ITEMOUT)) // Jawz thrown { K_ThrowKartItem(player, true, MT_JAWZ, 1, 0, 0); K_PlayAttackTaunt(player->mo); @@ -11711,12 +11711,12 @@ void K_MoveKartPlayer(player_t *player, boolean onground) P_SetTarget(&player->mo->hnext, mo); } } - else if (ATTACK_IS_DOWN && (player->pflags & PF_ITEMOUT)) + else if (ATTACK_IS_DOWN && (player->itemflags & IF_ITEMOUT)) { K_ThrowKartItem(player, false, MT_SSMINE, 1, 1, 0); K_PlayAttackTaunt(player->mo); player->itemamount--; - player->pflags &= ~PF_ITEMOUT; + player->itemflags &= ~IF_ITEMOUT; K_UpdateHnextList(player, true); } break; @@ -11746,12 +11746,12 @@ void K_MoveKartPlayer(player_t *player, boolean onground) P_SetTarget(&player->mo->hnext, mo); } } - else if (ATTACK_IS_DOWN && (player->pflags & PF_ITEMOUT)) + else if (ATTACK_IS_DOWN && (player->itemflags & IF_ITEMOUT)) { K_ThrowKartItem(player, (player->throwdir > 0), MT_DROPTARGET, -1, 0, 0); K_PlayAttackTaunt(player->mo); player->itemamount--; - player->pflags &= ~PF_ITEMOUT; + player->itemflags &= ~IF_ITEMOUT; K_UpdateHnextList(player, true); } break; @@ -11771,7 +11771,7 @@ void K_MoveKartPlayer(player_t *player, boolean onground) if (player->ballhogcharge == 0) player->ballhogtap = false; - boolean realcharge = (cmd->buttons & BT_ATTACK) && (player->pflags & PF_HOLDREADY) && (player->ballhogcharge < ballhogmax); + boolean realcharge = (cmd->buttons & BT_ATTACK) && (player->itemflags & IF_HOLDREADY) && (player->ballhogcharge < ballhogmax); if ((realcharge && !player->ballhogtap) || (player->ballhogtap && player->ballhogcharge < BALLHOGINCREMENT)) { player->ballhogcharge++; @@ -11794,11 +11794,11 @@ void K_MoveKartPlayer(player_t *player, boolean onground) { if (cmd->buttons & BT_ATTACK) { - player->pflags &= ~PF_HOLDREADY; + player->itemflags &= ~IF_HOLDREADY; } else { - player->pflags |= PF_HOLDREADY; + player->itemflags |= IF_HOLDREADY; } if (player->ballhogcharge > 0) @@ -11834,7 +11834,7 @@ void K_MoveKartPlayer(player_t *player, boolean onground) } player->ballhogcharge = 0; - player->pflags &= ~PF_HOLDREADY; + player->itemflags &= ~IF_HOLDREADY; } } } @@ -11968,7 +11968,7 @@ void K_MoveKartPlayer(player_t *player, boolean onground) if (!HOLDING_ITEM && NO_HYUDORO) { - if ((cmd->buttons & BT_ATTACK) && (player->pflags & PF_HOLDREADY)) + if ((cmd->buttons & BT_ATTACK) && (player->itemflags & IF_HOLDREADY)) { if (player->bubbleblowup == 0) S_StartSound(player->mo, sfx_s3k75); @@ -11988,7 +11988,7 @@ void K_MoveKartPlayer(player_t *player, boolean onground) K_PlayAttackTaunt(player->mo); player->bubbleblowup = 0; player->bubblecool = 0; - player->pflags &= ~PF_HOLDREADY; + player->itemflags &= ~IF_HOLDREADY; player->itemamount--; } } @@ -12001,9 +12001,9 @@ void K_MoveKartPlayer(player_t *player, boolean onground) player->bubbleblowup--; if (player->bubblecool) - player->pflags &= ~PF_HOLDREADY; + player->itemflags &= ~IF_HOLDREADY; else - player->pflags |= PF_HOLDREADY; + player->itemflags |= IF_HOLDREADY; } } break; @@ -12027,7 +12027,7 @@ void K_MoveKartPlayer(player_t *player, boolean onground) flamemax = player->flamelength + TICRATE; // TICRATE leniency period, but we block most effects at flamelength 0 down below - if ((cmd->buttons & BT_ATTACK) && (player->pflags & PF_HOLDREADY)) + if ((cmd->buttons & BT_ATTACK) && (player->itemflags & IF_HOLDREADY)) { const INT32 incr = (gametyperules & GTR_CLOSERPLAYERS) ? 4 : 2; player->flamemeter += incr; @@ -12069,13 +12069,13 @@ void K_MoveKartPlayer(player_t *player, boolean onground) player->flamemeter = 0; player->flamelength = 0; - player->pflags &= ~PF_HOLDREADY; + player->itemflags &= ~IF_HOLDREADY; player->itemamount--; } } else { - player->pflags |= PF_HOLDREADY; + player->itemflags |= IF_HOLDREADY; if (!(gametyperules & GTR_CLOSERPLAYERS) || leveltime % 6 == 0) { @@ -12145,12 +12145,12 @@ void K_MoveKartPlayer(player_t *player, boolean onground) P_SetTarget(&player->mo->hnext, mo); } } - else if (ATTACK_IS_DOWN && HOLDING_ITEM && (player->pflags & PF_ITEMOUT)) // Sink thrown + else if (ATTACK_IS_DOWN && HOLDING_ITEM && (player->itemflags & IF_ITEMOUT)) // Sink thrown { K_ThrowKartItem(player, false, MT_SINK, 1, 2, 0); K_PlayAttackTaunt(player->mo); player->itemamount--; - player->pflags &= ~PF_ITEMOUT; + player->itemflags &= ~IF_ITEMOUT; K_UpdateHnextList(player, true); } break; @@ -12185,7 +12185,7 @@ void K_MoveKartPlayer(player_t *player, boolean onground) // No more! if (!player->itemamount) { - player->pflags &= ~PF_ITEMOUT; + player->itemflags &= ~IF_ITEMOUT; player->itemtype = KITEM_NONE; } @@ -12293,7 +12293,7 @@ void K_MoveKartPlayer(player_t *player, boolean onground) player->tumbleHeight = 30; // Base tumble bounce height player->trickpanel = TRICKSTATE_NONE; P_SetPlayerMobjState(player->mo, S_KART_SPINOUT); - if (player->pflags & (PF_ITEMOUT|PF_EGGMANOUT)) + if (player->itemflags & (IF_ITEMOUT|IF_EGGMANOUT)) { //K_PopPlayerShield(player); // shield is just being yeeted, don't pop K_DropHnextList(player); @@ -13053,4 +13053,40 @@ void K_SetTireGrease(player_t *player, tic_t tics) player->tiregrease = tics; } +// somewhat sensible check for HUD sounds in a post-bot-takeover world +boolean K_IsPlayingDisplayPlayer(player_t *player) +{ + return P_IsDisplayPlayer(player) && (!player->exiting); +} + +boolean K_PlayerCanPunt(player_t *player) +{ + if (player->invincibilitytimer > 0) + { + return true; + } + + if (player->flamedash > 0 && player->itemtype == KITEM_FLAMESHIELD) + { + return true; + } + + if (player->growshrinktimer > 0) + { + return true; + } + + if (player->tripwirePass >= TRIPWIRE_BLASTER && player->speed >= 2 * K_GetKartSpeed(player, false, false)) + { + return true; + } + + return false; +} + +void K_MakeObjectReappear(mobj_t *mo) +{ + (!P_MobjWasRemoved(mo->punt_ref) ? mo->punt_ref : mo)->reappear = leveltime + (30*TICRATE); +} + //} diff --git a/src/k_kart.h b/src/k_kart.h index d5782e550..44b7283dc 100644 --- a/src/k_kart.h +++ b/src/k_kart.h @@ -245,6 +245,11 @@ boolean K_isPlayerInSpecialState(player_t *p); void K_SetTireGrease(player_t *player, tic_t tics); +boolean K_IsPlayingDisplayPlayer(player_t *player); + +boolean K_PlayerCanPunt(player_t *player); +void K_MakeObjectReappear(mobj_t *mo); + #ifdef __cplusplus } // extern "C" #endif diff --git a/src/k_menu.h b/src/k_menu.h index c02f29d50..f4144ac39 100644 --- a/src/k_menu.h +++ b/src/k_menu.h @@ -979,6 +979,7 @@ extern consvar_t cv_dummyprofilename; extern consvar_t cv_dummyprofileplayername; extern consvar_t cv_dummyprofilekickstart; extern consvar_t cv_dummyprofileautoroulette; +extern consvar_t cv_dummyprofilelitesteer; extern consvar_t cv_dummyprofilerumble; void M_ResetOptions(void); diff --git a/src/k_objects.h b/src/k_objects.h index 4a1dec35c..72029bb65 100644 --- a/src/k_objects.h +++ b/src/k_objects.h @@ -141,7 +141,7 @@ void Obj_UpdateRingShooterFace(mobj_t *part); /* Follower Audience */ void Obj_AudienceInit(mobj_t * mobj, mapthing_t *mthing, INT32 followerpick); -void Obj_AudienceThink(mobj_t * mobj, boolean focusonplayer); +void Obj_AudienceThink(mobj_t * mobj, boolean focusonplayer, boolean checkdeathpit); /* Random Item Boxes */ void Obj_RandomItemVisuals(mobj_t *mobj); diff --git a/src/k_profiles.c b/src/k_profiles.c index f1ff15210..cd2491731 100644 --- a/src/k_profiles.c +++ b/src/k_profiles.c @@ -72,6 +72,7 @@ profile_t* PR_MakeProfile( new->followercolor = fcol; new->kickstartaccel = false; new->autoroulette = false; + new->litesteer = true; // Copy from gamecontrol directly as we'll be setting controls up directly in the profile. memcpy(new->controls, controlarray, sizeof(new->controls)); @@ -89,6 +90,7 @@ profile_t* PR_MakeProfileFromPlayer(const char *prname, const char *pname, const // Player bound cvars: new->kickstartaccel = cv_kickstartaccel[pnum].value; new->autoroulette = cv_autoroulette[pnum].value; + new->litesteer = cv_litesteer[pnum].value; new->rumble = cv_rumble[pnum].value; return new; @@ -276,6 +278,7 @@ void PR_SaveProfiles(void) // Consvars. WRITEUINT8(save.p, profilesList[i]->kickstartaccel); WRITEUINT8(save.p, profilesList[i]->autoroulette); + WRITEUINT8(save.p, profilesList[i]->litesteer); WRITEUINT8(save.p, profilesList[i]->rumble); // Controls. @@ -425,6 +428,17 @@ void PR_LoadProfiles(void) profilesList[i]->autoroulette = (boolean)READUINT8(save.p); } + // 7->8, add litesteer + if (version < 8) + { + profilesList[i]->litesteer = true; + + } + else + { + profilesList[i]->litesteer = (boolean)READUINT8(save.p); + } + if (version < 4) { profilesList[i]->rumble = true; @@ -478,6 +492,7 @@ static void PR_ApplyProfile_Settings(profile_t *p, UINT8 playernum) // toggles CV_StealthSetValue(&cv_kickstartaccel[playernum], p->kickstartaccel); CV_StealthSetValue(&cv_autoroulette[playernum], p->autoroulette); + CV_StealthSetValue(&cv_litesteer[playernum], p->litesteer); // set controls... memcpy(&gamecontrol[playernum], p->controls, sizeof(gamecontroldefault)); diff --git a/src/k_profiles.h b/src/k_profiles.h index 3b941500f..e920fe9be 100644 --- a/src/k_profiles.h +++ b/src/k_profiles.h @@ -31,7 +31,7 @@ extern "C" { #define SKINNAMESIZE 16 #define PROFILENAMELEN 6 -#define PROFILEVER 7 +#define PROFILEVER 8 #define MAXPROFILES 16 #define PROFILESFILE "ringprofiles.prf" #define PROFILE_GUEST 0 @@ -74,7 +74,8 @@ struct profile_t // Player-specific consvars. // @TODO: List all of those boolean kickstartaccel; // cv_kickstartaccel - boolean autoroulette; // cv_autoroulette + boolean autoroulette; // cv_autoroulette + boolean litesteer; // cv_litesteer boolean rumble; // cv_rumble // Finally, control data itself diff --git a/src/k_respawn.c b/src/k_respawn.c index 946a62c08..f9c03e499 100644 --- a/src/k_respawn.c +++ b/src/k_respawn.c @@ -297,7 +297,7 @@ void K_DoIngameRespawn(player_t *player) player->respawn.init = true; player->respawn.fast = true; player->respawn.returnspeed = 0; - player->laps = player->lastsafelap; + player->laps = min(player->laps, player->lastsafelap); player->respawn.airtimer = player->airtime; player->respawn.truedeath = !!(player->pflags & PF_FAULT); diff --git a/src/k_roulette.c b/src/k_roulette.c index 1b378aeae..70d00893e 100644 --- a/src/k_roulette.c +++ b/src/k_roulette.c @@ -1622,7 +1622,7 @@ void K_KartItemRoulette(player_t *const player, ticcmd_t *const cmd) // If the roulette finishes or the player presses BT_ATTACK, stop the roulette and calculate the item. // I'm returning via the exact opposite, however, to forgo having another bracket embed. Same result either way, I think. // Finally, if you get past this check, now you can actually start calculating what item you get. - if (confirmItem == true && (player->pflags & (PF_ITEMOUT|PF_EGGMANOUT|PF_USERINGS)) == 0) + if (confirmItem == true && (player->itemflags & (IF_ITEMOUT|IF_EGGMANOUT|IF_USERINGS)) == 0) { if (roulette->eggman == true) { @@ -1633,7 +1633,7 @@ void K_KartItemRoulette(player_t *const player, ticcmd_t *const cmd) //player->karthud[khud_itemblinkmode] = 1; //player->karthud[khud_rouletteoffset] = K_GetRouletteOffset(roulette, FRACUNIT); - if (P_IsDisplayPlayer(player)) + if (K_IsPlayingDisplayPlayer(player)) { S_StartSound(NULL, sfx_itrole); } @@ -1680,7 +1680,7 @@ void K_KartItemRoulette(player_t *const player, ticcmd_t *const cmd) player->karthud[khud_itemblinkmode] = 0; player->karthud[khud_rouletteoffset] = K_GetRouletteOffset(roulette, FRACUNIT); - if (P_IsDisplayPlayer(player)) + if (K_IsPlayingDisplayPlayer(player)) { if (roulette->ringbox) { @@ -1714,7 +1714,7 @@ void K_KartItemRoulette(player_t *const player, ticcmd_t *const cmd) // This makes the roulette produce the random noises. roulette->sound = (roulette->sound + 1) % 8; - if (P_IsDisplayPlayer(player)) + if (K_IsPlayingDisplayPlayer(player)) { if (roulette->ringbox) S_StartSound(NULL, sfx_s240); diff --git a/src/lua_mobjlib.c b/src/lua_mobjlib.c index ce4668038..51751f996 100644 --- a/src/lua_mobjlib.c +++ b/src/lua_mobjlib.c @@ -106,7 +106,9 @@ enum mobj_e { mobj_tid, mobj_special, mobj_args, - mobj_stringargs + mobj_stringargs, + mobj_reappear, + mobj_punt_ref, }; static const char *const mobj_opt[] = { @@ -194,6 +196,8 @@ static const char *const mobj_opt[] = { "special", "args", "stringargs", + "reappear", + "punt_ref", NULL}; #define UNIMPLEMENTED luaL_error(L, LUA_QL("mobj_t") " field " LUA_QS " is not implemented for Lua and cannot be accessed.", mobj_opt[field]) @@ -493,6 +497,17 @@ static int mobj_get(lua_State *L) case mobj_stringargs: LUA_PushUserdata(L, mo->thing_stringargs, META_THINGSTRINGARGS); break; + case mobj_reappear: + lua_pushinteger(L, mo->reappear); + break; + case mobj_punt_ref: + if (mo->punt_ref && P_MobjWasRemoved(mo->punt_ref)) + { // don't put invalid mobj back into Lua. + P_SetTarget(&mo->punt_ref, NULL); + return 0; + } + LUA_PushUserdata(L, mo->punt_ref, META_MOBJ); + break; default: // extra custom variables in Lua memory lua_getfield(L, LUA_REGISTRYINDEX, LREG_EXTVARS); I_Assert(lua_istable(L, -1)); @@ -883,6 +898,18 @@ static int mobj_set(lua_State *L) return NOSET; case mobj_stringargs: return NOSET; + case mobj_reappear: + mo->reappear = luaL_checkinteger(L, 3); + break; + case mobj_punt_ref: + if (lua_isnil(L, 3)) + P_SetTarget(&mo->punt_ref, NULL); + else + { + mobj_t *punt_ref = *((mobj_t **)luaL_checkudata(L, 3, META_MOBJ)); + P_SetTarget(&mo->punt_ref, punt_ref); + } + break; default: lua_getfield(L, LUA_REGISTRYINDEX, LREG_EXTVARS); I_Assert(lua_istable(L, -1)); diff --git a/src/lua_playerlib.c b/src/lua_playerlib.c index ec5aeaad4..2d39cc7c9 100644 --- a/src/lua_playerlib.c +++ b/src/lua_playerlib.c @@ -263,6 +263,8 @@ static int player_get(lua_State *L) lua_pushinteger(L, plr->ringboxdelay); else if (fastcmp(field,"ringboxaward")) lua_pushinteger(L, plr->ringboxaward); + else if (fastcmp(field,"itemflags")) + lua_pushinteger(L, plr->itemflags); else if (fastcmp(field,"drift")) lua_pushinteger(L, plr->drift); else if (fastcmp(field,"driftcharge")) @@ -757,6 +759,8 @@ static int player_set(lua_State *L) plr->ringboxdelay = luaL_checkinteger(L, 3); else if (fastcmp(field,"ringboxaward")) plr->ringboxaward = luaL_checkinteger(L, 3); + else if (fastcmp(field,"itemflags")) + plr->itemflags = luaL_checkinteger(L, 3); else if (fastcmp(field,"drift")) plr->drift = luaL_checkinteger(L, 3); else if (fastcmp(field,"driftcharge")) diff --git a/src/menus/options-profiles-1.c b/src/menus/options-profiles-1.c index ee9f3a40d..bb194a2ee 100644 --- a/src/menus/options-profiles-1.c +++ b/src/menus/options-profiles-1.c @@ -89,6 +89,7 @@ static void M_StartEditProfile(INT32 c) CV_StealthSet(&cv_dummyprofileplayername, optionsmenu.profile->playername); CV_StealthSetValue(&cv_dummyprofilekickstart, optionsmenu.profile->kickstartaccel); CV_StealthSetValue(&cv_dummyprofileautoroulette, optionsmenu.profile->autoroulette); + CV_StealthSetValue(&cv_dummyprofilelitesteer, optionsmenu.profile->litesteer); CV_StealthSetValue(&cv_dummyprofilerumble, optionsmenu.profile->rumble); } else @@ -97,6 +98,7 @@ static void M_StartEditProfile(INT32 c) CV_StealthSet(&cv_dummyprofileplayername, ""); CV_StealthSetValue(&cv_dummyprofilekickstart, 0); // off CV_StealthSetValue(&cv_dummyprofileautoroulette, 0); // off + CV_StealthSetValue(&cv_dummyprofilelitesteer, 1); // on CV_StealthSetValue(&cv_dummyprofilerumble, 1); // on } diff --git a/src/menus/options-profiles-edit-controls.c b/src/menus/options-profiles-edit-controls.c index dc648abd6..0b7e8dcf6 100644 --- a/src/menus/options-profiles-edit-controls.c +++ b/src/menus/options-profiles-edit-controls.c @@ -94,6 +94,9 @@ menuitem_t OPTIONS_ProfileControls[] = { {IT_CONTROL | IT_CVAR, "AUTO ROULETTE", "Item roulette auto-stops on a random result.", NULL, {.cvar = &cv_dummyprofileautoroulette}, 0, 0}, + {IT_CONTROL | IT_CVAR, "LITE STEER", "Hold DOWN on d-pad/keyboard for shallow turns.", + NULL, {.cvar = &cv_dummyprofilelitesteer}, 0, 0}, + {IT_HEADER, "EXTRA", "", NULL, {NULL}, 0, 0}, @@ -191,6 +194,7 @@ static void M_ProfileControlSaveResponse(INT32 choice) // Save the profile optionsmenu.profile->kickstartaccel = cv_dummyprofilekickstart.value; optionsmenu.profile->autoroulette = cv_dummyprofileautoroulette.value; + optionsmenu.profile->litesteer = cv_dummyprofilelitesteer.value; optionsmenu.profile->rumble = cv_dummyprofilerumble.value; memcpy(&optionsmenu.profile->controls, optionsmenu.tempcontrols, sizeof(gamecontroldefault)); @@ -201,6 +205,7 @@ static void M_ProfileControlSaveResponse(INT32 choice) memcpy(&gamecontrol[belongsto], optionsmenu.tempcontrols, sizeof(gamecontroldefault)); CV_SetValue(&cv_kickstartaccel[belongsto], cv_dummyprofilekickstart.value); CV_SetValue(&cv_autoroulette[belongsto], cv_dummyprofileautoroulette.value); + CV_SetValue(&cv_litesteer[belongsto], cv_dummyprofilelitesteer.value); CV_SetValue(&cv_rumble[belongsto], cv_dummyprofilerumble.value); } diff --git a/src/objects/audience.c b/src/objects/audience.c index f1c1a0131..b5814ae16 100644 --- a/src/objects/audience.c +++ b/src/objects/audience.c @@ -29,6 +29,7 @@ Obj_AudienceInit mapthing_t *mthing, INT32 followerpick) { + const boolean ourchoiceofvisuals = (followerpick < 0 || followerpick > numfollowers); INT16 *reflist = NULL; INT16 tempreflist[MAXHEADERFOLLOWERS]; UINT8 numref = 0; @@ -36,9 +37,9 @@ Obj_AudienceInit audience_mainstate(mobj) = S_NULL; // Pick follower - if (mthing != NULL) + if (ourchoiceofvisuals == true) { - if (mthing->thing_stringargs[0] != NULL) + if (mthing != NULL && mthing->thing_stringargs[0] != NULL) { // From mapthing char *stringcopy = Z_StrDup(mthing->thing_stringargs[0]); @@ -56,11 +57,23 @@ Obj_AudienceInit *c = ' '; } - if ((tempreflist[numref++] = K_FollowerAvailable(tok)) == -1) + if ((tempreflist[numref] = K_FollowerAvailable(tok)) == -1) + { CONS_Alert(CONS_WARNING, "Mapthing %s: Follower \"%s\" is invalid!\n", sizeu1(mthing-mapthings), tok); + } + else + numref++; + tok = strtok(NULL, " ,"); } + if (!numref) + { + // This is the one thing a user should definitely be told about. + CONS_Alert(CONS_WARNING, "Mapthing %s: Follower audience has no valid followers to pick from!\n", sizeu1(mthing-mapthings)); + // DO NOT RETURN HERE + } + Z_Free(stringcopy); reflist = tempreflist; @@ -81,8 +94,8 @@ Obj_AudienceInit if (!numref || !reflist) { - // This is the one thing a user should definitely be told about. - CONS_Alert(CONS_WARNING, "Mapthing %s: Follower audience has no valid followers to pick from!\n", sizeu1(mthing-mapthings)); + // Clean up after ourselves. + P_RemoveMobj(mobj); return; } @@ -137,11 +150,11 @@ Obj_AudienceInit } // Handle colors - if (mthing != NULL) + if (ourchoiceofvisuals == true) { UINT16 colorpick = SKINCOLOR_NONE; - if (mthing->thing_stringargs[1] != NULL) + if (mthing != NULL && mthing->thing_stringargs[1] != NULL) { if (!stricmp("Random", mthing->thing_stringargs[1])) { @@ -189,8 +202,17 @@ Obj_AudienceInit void Obj_AudienceThink ( mobj_t * mobj, - boolean focusonplayer) + boolean focusonplayer, + boolean checkdeathpit) { + boolean landed = false; + + if (mobj->fuse && mobj->fuse < (TICRATE/2)) + { + mobj->renderflags ^= RF_DONTDRAW; + return; // no jumping when you hit the floor, your gravity is weird + } + if (audience_mainstate(mobj) == S_NULL) { // Uninitialised, don't do anything funny. @@ -315,15 +337,23 @@ Obj_AudienceThink } else if (mobj->flags2 & MF2_OBJECTFLIP) { - if (mobj->z + mobj->height >= mobj->ceilingz) - { - mobj->momz = -audience_bobamp(mobj); - P_SetMobjState(mobj, audience_mainstate(mobj)); - } + landed = (mobj->z + mobj->height >= mobj->ceilingz); } - else if (mobj->z <= mobj->floorz) + else { - mobj->momz = audience_bobamp(mobj); + landed = (mobj->z <= mobj->floorz); + } + + if (landed == true) + { + if (checkdeathpit && P_CheckDeathPitCollide(mobj)) + { + P_RemoveMobj(mobj); + return; + } + + mobj->momx = mobj->momy = 0; + mobj->momz = P_MobjFlip(mobj)*audience_bobamp(mobj); P_SetMobjState(mobj, audience_mainstate(mobj)); } } diff --git a/src/objects/super-flicky.cpp b/src/objects/super-flicky.cpp index d78de32fd..601ccdf7e 100644 --- a/src/objects/super-flicky.cpp +++ b/src/objects/super-flicky.cpp @@ -765,7 +765,7 @@ mobj_t *Obj_SuperFlickyOwner(const mobj_t* mobj) { const Flicky* x = static_cast(mobj); - return x->source(); + return x->valid() ? x->source() : nullptr; } boolean Obj_IsSuperFlickyWhippable(const mobj_t* mobj) @@ -780,4 +780,4 @@ boolean Obj_IsSuperFlickyTargettingYou(const mobj_t* mobj, mobj_t *player) const Flicky* x = static_cast(mobj); return player == x->chasing(); -} \ No newline at end of file +} diff --git a/src/p_floor.c b/src/p_floor.c index 4b96192c8..1a7f2285a 100644 --- a/src/p_floor.c +++ b/src/p_floor.c @@ -1017,7 +1017,6 @@ static mobj_t *SearchMarioNode(msecnode_t *node) } // Ignore popped monitors, too. if (node->m_thing->health == 0 // this only really applies for monitors - || (!(node->m_thing->flags & MF_MONITOR) && (mobjinfo[node->m_thing->type].flags & MF_MONITOR)) // gold monitor support || (node->m_thing->type == MT_RANDOMITEM)) continue; // Okay, we found something valid. @@ -2344,7 +2343,6 @@ void EV_MarioBlock(ffloor_t *rover, sector_t *sector, mobj_t *puncher) fixed_t topheight = *rover->topheight; mariothink_t *block; mobj_t *thing; - fixed_t oldx = 0, oldy = 0, oldz = 0; I_Assert(puncher != NULL); I_Assert(puncher->player != NULL); @@ -2362,7 +2360,6 @@ void EV_MarioBlock(ffloor_t *rover, sector_t *sector, mobj_t *puncher) S_StartSound(puncher, sfx_mario1); // "Thunk!" sound - puncher is "close enough". else // Found something! { - const boolean itsamonitor = (thing->flags & MF_MONITOR) == MF_MONITOR; // create and initialize new elevator thinker block = Z_Calloc(sizeof (*block), PU_LEVSPEC, NULL); @@ -2383,13 +2380,6 @@ void EV_MarioBlock(ffloor_t *rover, sector_t *sector, mobj_t *puncher) R_CreateInterpolator_SectorPlane(&block->thinker, roversec, false); R_CreateInterpolator_SectorPlane(&block->thinker, roversec, true); - if (itsamonitor) - { - oldx = thing->x; - oldy = thing->y; - oldz = thing->z; - } - P_UnsetThingPosition(thing); thing->x = thing->old_x = sector->soundorg.x; thing->y = thing->old_y = sector->soundorg.y; @@ -2410,16 +2400,5 @@ void EV_MarioBlock(ffloor_t *rover, sector_t *sector, mobj_t *puncher) // "Powerup rise" sound S_StartSound(puncher, sfx_mario9); // Puncher is "close enough" } - - if (itsamonitor && thing) - { - P_UnsetThingPosition(thing); - thing->x = thing->old_x = oldx; - thing->y = thing->old_y = oldy; - thing->z = thing->old_z = oldz; - thing->momx = 1; - thing->momy = 1; - P_SetThingPosition(thing); - } } } diff --git a/src/p_inter.c b/src/p_inter.c index 8852310a0..88da20f74 100644 --- a/src/p_inter.c +++ b/src/p_inter.c @@ -43,6 +43,7 @@ #include "k_hitlag.h" #include "acs/interface.h" #include "k_powerup.h" +#include "k_collide.h" // CTF player names #define CTFTEAMCODE(pl) pl->ctfteam ? (pl->ctfteam == 1 ? "\x85" : "\x84") : "" @@ -153,7 +154,7 @@ boolean P_CanPickupItem(player_t *player, UINT8 weapon) if (player->itemRoulette.active == true || player->ringboxdelay > 0 || (weapon != 3 && player->itemamount) - || (player->pflags & PF_ITEMOUT)) + || (player->itemflags & IF_ITEMOUT)) return false; if (weapon == 3 && K_GetShieldFromItem(player->itemtype) != KSHIELD_NONE) @@ -1537,7 +1538,7 @@ void P_KillMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, UINT8 damaget target->momx = target->momy = target->momz = 0; // SRB2kart - if (target->type != MT_PLAYER && !(target->flags & MF_MONITOR) + if (target->type != MT_PLAYER && !(target->type == MT_ORBINAUT || target->type == MT_ORBINAUT_SHIELD || target->type == MT_JAWZ || target->type == MT_JAWZ_SHIELD || target->type == MT_BANANA || target->type == MT_BANANA_SHIELD @@ -1577,10 +1578,10 @@ void P_KillMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, UINT8 damaget // I wish I knew a better way to do this if (target->target && target->target->player && target->target->player->mo) { - if ((target->target->player->pflags & PF_EGGMANOUT) && target->type == MT_EGGMANITEM_SHIELD) - target->target->player->pflags &= ~PF_EGGMANOUT; + if ((target->target->player->itemflags & IF_EGGMANOUT) && target->type == MT_EGGMANITEM_SHIELD) + target->target->player->itemflags &= ~IF_EGGMANOUT; - if (target->target->player->pflags & PF_ITEMOUT) + if (target->target->player->itemflags & IF_ITEMOUT) { if ((target->type == MT_BANANA_SHIELD && target->target->player->itemtype == KITEM_BANANA) // trail items || (target->type == MT_SSMINE_SHIELD && target->target->player->itemtype == KITEM_MINE) @@ -1608,7 +1609,7 @@ void P_KillMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, UINT8 damaget } if (!target->target->player->itemamount) - target->target->player->pflags &= ~PF_ITEMOUT; + target->target->player->itemflags &= ~IF_ITEMOUT; if (target->target->hnext == target) P_SetTarget(&target->target->hnext, NULL); @@ -1630,7 +1631,7 @@ void P_KillMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, UINT8 damaget // if killed by a player if (source && source->player) { - if (target->flags & MF_MONITOR || target->type == MT_RANDOMITEM) + if (target->type == MT_RANDOMITEM) { P_SetTarget(&target->target, source); @@ -2103,6 +2104,67 @@ void P_KillMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, UINT8 damaget cur = cur->hnext; } + // Spawn three Followers (if possible) + if (mapheaderinfo[gamemap-1]->numFollowers) + { + dir = FixedAngle(P_RandomKey(PR_RANDOMAUDIENCE, 360)*FRACUNIT); + + const fixed_t launchmomentum = 7 * mapobjectscale; + const fixed_t jaggedness = 4; + angle_t launchangle; + UINT8 i; + for (i = 0; i < 6; i++, dir += ANG60) + { + cur = P_SpawnMobj( + target->x, target->y, + target->z + target->height/2, + MT_RANDOMAUDIENCE + ); + + // We check if you have some horrible Lua + if (P_MobjWasRemoved(cur)) + break; + + Obj_AudienceInit(cur, NULL, -1); + + // We check again if the list is invalid + if (P_MobjWasRemoved(cur)) + break; + + cur->hitlag = target->hitlag; + + cur->destscale /= 2; + P_SetScale(cur, cur->destscale/TICRATE); + cur->scalespeed = cur->destscale/TICRATE; + cur->z -= cur->height/2; + + // flags are NOT from the target - just in case it's just been placed on the ceiling as a gimmick + cur->flags2 |= (source->flags2 & MF2_OBJECTFLIP); + cur->eflags |= (source->eflags & MFE_VERTICALFLIP); + + launchangle = FixedAngle( + ( + ( + P_RandomRange(PR_RANDOMAUDIENCE, 12/jaggedness, 24/jaggedness) * jaggedness + ) + (i & 1)*16 + ) * FRACUNIT + ); + + cur->momz = P_MobjFlip(target) // THIS one uses target! + * P_ReturnThrustY(cur, launchangle, launchmomentum); + + cur->angle = dir; + + P_InstaThrust( + cur, cur->angle, + P_ReturnThrustX(cur, launchangle, launchmomentum) + ); + + cur->fuse = (3*TICRATE)/2; + cur->flags |= MF_NOCLIPHEIGHT; + } + } + S_StartSound(target, sfx_mbs60); P_AddBrokenPrison(target, inflictor, source); @@ -2876,6 +2938,14 @@ boolean P_DamageMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 da invincible = false; } + // TODO: doing this from P_DamageMobj limits punting to objects that damage the player. + // And it may be kind of yucky. + // But this is easier than accounting for every condition in PIT_CheckThing! + if (inflictor && K_PuntCollide(inflictor, target)) + { + return false; + } + if (invincible && type != DMG_STUMBLE && type != DMG_WHUMBLE) { const INT32 oldHitlag = target->hitlag; diff --git a/src/p_local.h b/src/p_local.h index 045a59472..4cd26c9fd 100644 --- a/src/p_local.h +++ b/src/p_local.h @@ -595,6 +595,8 @@ mobj_t *P_FindMobjFromTID(mtag_t tid, mobj_t *i, mobj_t *activator); void P_DeleteMobjStringArgs(mobj_t *mobj); +tic_t P_MobjIsReappearing(const mobj_t *mobj); + #ifdef __cplusplus } // extern "C" #endif diff --git a/src/p_map.c b/src/p_map.c index 0da7744cf..69ff25357 100644 --- a/src/p_map.c +++ b/src/p_map.c @@ -528,6 +528,7 @@ static void P_DoFanAndGasJet(mobj_t *spring, mobj_t *object) static BlockItReturn_t PIT_CheckThing(mobj_t *thing) { fixed_t blockdist; + boolean damage = false; if (tm.thing == NULL || P_MobjWasRemoved(tm.thing) == true) return BMIT_STOP; // func just popped our tm.thing, cannot continue. @@ -552,6 +553,10 @@ static BlockItReturn_t PIT_CheckThing(mobj_t *thing) if ((thing->flags & MF_NOCLIPTHING) || !(thing->flags & (MF_SOLID|MF_SPECIAL|MF_PAIN|MF_SHOOTABLE|MF_SPRING))) return BMIT_CONTINUE; + // Thing is respawning + if (P_MobjIsReappearing(thing)) + return BMIT_CONTINUE; + blockdist = thing->radius + tm.thing->radius; if (abs(thing->x - tm.x) >= blockdist || abs(thing->y - tm.y) >= blockdist) @@ -684,10 +689,12 @@ static BlockItReturn_t PIT_CheckThing(mobj_t *thing) if (P_DamageMobj(tm.thing, thing, thing, 1, damagetype) && (damagetype = (thing->info->mass>>8))) S_StartSound(thing, damagetype); - } - if (P_MobjWasRemoved(tm.thing) || P_MobjWasRemoved(thing)) - return BMIT_CONTINUE; + if (P_MobjWasRemoved(tm.thing) || P_MobjWasRemoved(thing)) + return BMIT_CONTINUE; + + damage = true; + } } else if (tm.thing->flags & MF_PAIN && thing->player) { // Painful thing splats player in the face @@ -702,10 +709,12 @@ static BlockItReturn_t PIT_CheckThing(mobj_t *thing) if (P_DamageMobj(thing, tm.thing, tm.thing, 1, damagetype) && (damagetype = (tm.thing->info->mass>>8))) S_StartSound(tm.thing, damagetype); - } - if (P_MobjWasRemoved(tm.thing) || P_MobjWasRemoved(thing)) - return BMIT_CONTINUE; + if (P_MobjWasRemoved(tm.thing) || P_MobjWasRemoved(thing)) + return BMIT_CONTINUE; + + damage = true; + } } // check for skulls slamming into things @@ -1206,7 +1215,7 @@ static BlockItReturn_t PIT_CheckThing(mobj_t *thing) } // missiles can hit other things - if (tm.thing->flags & MF_MISSILE) + if ((tm.thing->flags & MF_MISSILE) && !damage) // if something was already damaged, don't run this { UINT8 damagetype = (tm.thing->info->mass ^ DMG_WOMBO); @@ -1616,7 +1625,10 @@ static BlockItReturn_t PIT_CheckThing(mobj_t *thing) if (tm.thing->z + tm.thing->height < thing->z) return BMIT_CONTINUE; // underneath - K_KartSolidBounce(tm.thing, thing); + if (!K_PuntCollide(thing, tm.thing)) + { + K_KartSolidBounce(tm.thing, thing); + } return BMIT_CONTINUE; } } @@ -2331,7 +2343,8 @@ boolean P_CheckPosition(mobj_t *thing, fixed_t x, fixed_t y, TryMoveResult_t *re // Check things first, possibly picking things up. // MF_NOCLIPTHING: used by camera to not be blocked by things - if (!(thing->flags & MF_NOCLIPTHING)) + // Respawning things should also be intangible to other things + if (!(thing->flags & MF_NOCLIPTHING) && !P_MobjIsReappearing(thing)) { for (bx = xl; bx <= xh; bx++) { @@ -4210,7 +4223,7 @@ static BlockItReturn_t PIT_RadiusAttack(mobj_t *thing) if ((bombdamagetype & DMG_CANTHURTSELF) && bombsource && thing->type == bombsource->type) // ignore the type of guys who dropped the bomb (Jetty-Syn Bomber or Skim can bomb eachother, but not themselves.) return BMIT_CONTINUE; - if ((thing->flags & (MF_MONITOR|MF_SHOOTABLE)) != MF_SHOOTABLE) + if ((thing->flags & MF_SHOOTABLE) != MF_SHOOTABLE) return BMIT_CONTINUE; dx = abs(thing->x - bombspot->x); diff --git a/src/p_mobj.c b/src/p_mobj.c index 715970404..54d62622e 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -1278,6 +1278,10 @@ fixed_t P_GetMobjGravity(mobj_t *mo) } break; } + case MT_RANDOMAUDIENCE: + if (mo->fuse) + gravityadd /= 10; + break; default: break; } @@ -1721,25 +1725,6 @@ void P_XYMovement(mobj_t *mo) P_ExplodeMissile(mo); return; } - else if (mo->flags & MF_STICKY) - { - S_StartSound(mo, mo->info->activesound); - mo->momx = mo->momy = mo->momz = 0; //Full stop! - mo->flags |= MF_NOGRAVITY; //Stay there! - mo->flags &= ~MF_STICKY; //Don't check again! - - // Check for hit against sky here - if (P_CheckSkyHit(mo)) - { - // Hack to prevent missiles exploding - // against the sky. - // Does not handle sky floors. - // Check frontsector as well. - - P_RemoveMobj(mo); - return; - } - } else { boolean walltransferred = false; @@ -5694,12 +5679,12 @@ static void P_FlameJetSceneryThink(mobj_t *mobj) flame->angle = mobj->angle; if (mobj->flags2 & MF2_AMBUSH) // Wave up and down instead of side-to-side - flame->momz = mobj->fuse << (FRACBITS - 2); + flame->momz = (mobj->fuse * mapobjectscale) / 4; else flame->angle += FixedAngle(mobj->fuse<movedir; + strength = 20*mapobjectscale; + strength -= ((20*mapobjectscale)/16)*mobj->movedir; P_InstaThrust(flame, flame->angle, strength); S_StartSound(flame, sfx_fire); @@ -5729,8 +5714,8 @@ static void P_VerticalFlameJetSceneryThink(mobj_t *mobj) flame = P_SpawnMobj(mobj->x, mobj->y, mobj->z, MT_FLAMEJETFLAME); - strength = 20*FRACUNIT; - strength -= ((20*FRACUNIT)/16)*mobj->movedir; + strength = 20*mapobjectscale; + strength -= ((20*mapobjectscale)/16)*mobj->movedir; // If deaf'd, the object spawns on the ceiling. if (mobj->flags2 & MF2_AMBUSH) @@ -5744,7 +5729,7 @@ static void P_VerticalFlameJetSceneryThink(mobj_t *mobj) P_SetMobjState(flame, S_FLAMEJETFLAME7); } - P_InstaThrust(flame, mobj->angle, FixedDiv(mobj->fuse*FRACUNIT, 3*FRACUNIT)); + P_InstaThrust(flame, mobj->angle, (mobj->fuse * mapobjectscale) / 3); S_StartSound(flame, sfx_fire); } @@ -6471,7 +6456,7 @@ static void P_MobjSceneryThink(mobj_t *mobj) break; } - if (mobj->target->player->pflags & PF_ITEMOUT) + if (mobj->target->player->itemflags & IF_ITEMOUT) { if (leveltime & 1) mobj->tracer->renderflags &= ~RF_DONTDRAW; @@ -7270,7 +7255,7 @@ static boolean P_MobjRegularThink(mobj_t *mobj) if (mobj->flags2 & MF2_STRONGBOX) { - Obj_AudienceThink(mobj, true); + Obj_AudienceThink(mobj, true, false); if (P_MobjWasRemoved(mobj)) return false; } @@ -10256,48 +10241,6 @@ static void K_MineExplodeThink(mobj_t *mobj) } } -static void P_MonitorFuseThink(mobj_t *mobj) -{ - mobj_t *newmobj; - - // Special case for ALL monitors. - // If a box's speed is nonzero, it's allowed to respawn as a WRM/SRM. - if (mobj->info->speed != 0 && (mobj->flags2 & (MF2_AMBUSH|MF2_STRONGBOX))) - { - mobjtype_t spawnchance[64]; - INT32 numchoices = 0, i = 0; - - // This define should make it a lot easier to organize and change monitor weights -#define SETMONITORCHANCES(type, strongboxamt, weakboxamt) \ -for (i = ((mobj->flags2 & MF2_STRONGBOX) ? strongboxamt : weakboxamt); i; --i) spawnchance[numchoices++] = type - - // Type SRM WRM - SETMONITORCHANCES(MT_SNEAKERS_BOX, 0, 10); // Super Sneakers - SETMONITORCHANCES(MT_INVULN_BOX, 2, 0); // Invincibility - SETMONITORCHANCES(MT_WHIRLWIND_BOX, 3, 8); // Whirlwind Shield - SETMONITORCHANCES(MT_ELEMENTAL_BOX, 3, 8); // Elemental Shield - SETMONITORCHANCES(MT_ATTRACT_BOX, 2, 0); // Attraction Shield - SETMONITORCHANCES(MT_FORCE_BOX, 3, 3); // Force Shield - SETMONITORCHANCES(MT_ARMAGEDDON_BOX, 2, 0); // Armageddon Shield - SETMONITORCHANCES(MT_MIXUP_BOX, 0, 1); // Teleporters - SETMONITORCHANCES(MT_RECYCLER_BOX, 0, 1); // Recycler - SETMONITORCHANCES(MT_1UP_BOX, 1, 1); // 1-Up - // ======================================= - // Total 16 32 - -#undef SETMONITORCHANCES - - i = P_RandomKey(PR_UNDEFINED, numchoices); // Gotta love those random numbers! - newmobj = P_SpawnMobj(mobj->x, mobj->y, mobj->z, spawnchance[i]); - } - else - newmobj = P_SpawnMobj(mobj->x, mobj->y, mobj->z, mobj->type); - - // Transfer flags2 (ambush, strongbox, objectflip) - newmobj->flags2 = mobj->flags2; - P_RemoveMobj(mobj); // make sure they disappear -} - static boolean P_CanFlickerFuse(mobj_t *mobj) { switch (mobj->type) @@ -10346,11 +10289,6 @@ static boolean P_FuseThink(mobj_t *mobj) if (LUA_HookMobj(mobj, MOBJ_HOOK(MobjFuse)) || P_MobjWasRemoved(mobj)) ; - else if (mobj->info->flags & MF_MONITOR) - { - P_MonitorFuseThink(mobj); - return false; - } else switch (mobj->type) { // gargoyle and snowman handled in P_PushableThinker, not here @@ -10495,6 +10433,8 @@ void P_MobjThinker(mobj_t *mobj) P_SetTarget(&mobj->hprev, NULL); if (mobj->itnext && P_MobjWasRemoved(mobj->itnext)) P_SetTarget(&mobj->itnext, NULL); + if (mobj->punt_ref && P_MobjWasRemoved(mobj->punt_ref)) + P_SetTarget(&mobj->punt_ref, NULL); if (mobj->flags & MF_NOTHINK) return; @@ -10991,7 +10931,9 @@ void P_SceneryThinker(mobj_t *mobj) if (mobj->type == MT_RANDOMAUDIENCE) { - Obj_AudienceThink(mobj, !!(mobj->flags2 & MF2_AMBUSH)); + Obj_AudienceThink(mobj, !!(mobj->flags2 & MF2_AMBUSH), !!(mobj->flags2 & MF2_DONTRESPAWN)); + if (P_MobjWasRemoved(mobj)) + return; } } @@ -11003,6 +10945,10 @@ fixed_t P_GetMobjDefaultScale(mobj_t *mobj) { switch(mobj->type) { + case MT_FLAMEJETFLAME: + return 3*FRACUNIT; + case MT_ITEMCLASH: + return 2*FRACUNIT; case MT_SPECIALSTAGEARCH: return 5*FRACUNIT; case MT_SPECIALSTAGEBOMB: @@ -11558,6 +11504,7 @@ mobj_t *P_SpawnMobj(fixed_t x, fixed_t y, fixed_t z, mobjtype_t type) mobj->y + FINESINE((ang>>ANGLETOFINESHIFT) & FINEMASK), mobj->z, MT_DAYTONAPINETREE_SIDE); side->angle = ang; P_SetTarget(&side->target, mobj); + P_SetTarget(&side->punt_ref, mobj); side->threshold = i; } break; @@ -12042,6 +11989,7 @@ void P_RemoveMobj(mobj_t *mobj) } P_SetTarget(&mobj->itnext, NULL); + P_SetTarget(&mobj->punt_ref, NULL); P_RemoveThingTID(mobj); P_DeleteMobjStringArgs(mobj); @@ -15617,3 +15565,9 @@ void P_DeleteMobjStringArgs(mobj_t *mobj) mobj->script_stringargs[i] = NULL; } } + +tic_t P_MobjIsReappearing(const mobj_t *mobj) +{ + tic_t t = (!P_MobjWasRemoved(mobj->punt_ref) ? mobj->punt_ref : mobj)->reappear; + return t - min(leveltime, t); +} diff --git a/src/p_mobj.h b/src/p_mobj.h index 382bfcd9e..1fbb676bf 100644 --- a/src/p_mobj.h +++ b/src/p_mobj.h @@ -137,8 +137,8 @@ typedef enum MF_MISSILE = 1<<15, // Item is a spring. MF_SPRING = 1<<16, - // Item box - MF_MONITOR = 1<<17, + // Object is elemental. If it is punted, it will evaporate. + MF_ELEMENTAL = 1<<17, // Don't run the thinker for this object. MF_NOTHINK = 1<<18, // Don't adjust z if below or above floorz/ceilingz @@ -149,8 +149,8 @@ typedef enum MF_SCENERY = 1<<21, // Painful (shit hurts). MF_PAIN = 1<<22, - // This mobj will stick to any surface or solid object it touches. - MF_STICKY = 1<<23, + // Object cannot be punted by invincible players. (Default CAN be punted, if it deals damage or is solid.) + MF_DONTPUNT = 1<<23, // Object uses terrain effects. (Overlays, footsteps, etc) MF_APPLYTERRAIN = 1<<24, // for chase camera, don't be blocked by things (partial clipping) @@ -437,6 +437,14 @@ struct mobj_t boolean frozen; + // Object was punted and is temporarily invisible and + // intangible. This is the leveltime that it will + // reappear. + tic_t reappear; + + // If punt_ref, set punt_ref->reappear, treat as if this->reappear + mobj_t *punt_ref; + // WARNING: New fields must be added separately to savegame and Lua. }; diff --git a/src/p_saveg.c b/src/p_saveg.c index a733ab159..6fa7a9363 100644 --- a/src/p_saveg.c +++ b/src/p_saveg.c @@ -571,6 +571,9 @@ static void P_NetArchivePlayers(savebuffer_t *save) WRITEUINT8(save->p, players[i].ringboxdelay); WRITEUINT8(save->p, players[i].ringboxaward); + + WRITEUINT8(save->p, players[i].itemflags); + WRITEFIXED(save->p, players[i].outrun); WRITEUINT8(save->p, players[i].rideroid); @@ -1107,6 +1110,9 @@ static void P_NetUnArchivePlayers(savebuffer_t *save) players[i].ringboxdelay = READUINT8(save->p); players[i].ringboxaward = READUINT8(save->p); + + players[i].itemflags = READUINT8(save->p); + players[i].outrun = READFIXED(save->p); players[i].rideroid = (boolean)READUINT8(save->p); @@ -2043,6 +2049,8 @@ static void ArchiveSectors(savebuffer_t *save) WRITEUINT8(save->p, diff3); if (diff3 & SD_DIFF4) WRITEUINT8(save->p, diff4); + if (diff4 & SD_DIFF5) + WRITEUINT8(save->p, diff5); if (diff & SD_FLOORHT) WRITEFIXED(save->p, ss->floorheight); if (diff & SD_CEILHT) @@ -2682,9 +2690,16 @@ typedef enum MD2_FROZEN = 1<<28, MD2_TERRAIN = 1<<29, MD2_WATERSKIP = 1<<30, - MD2_LIGHTLEVEL = (INT32)(1U<<31), + MD2_MORE = (INT32)(1U<<31), } mobj_diff2_t; +typedef enum +{ + MD3_LIGHTLEVEL = 1, + MD3_REAPPEAR = 1<<1, + MD3_PUNT_REF = 1<<2, +} mobj_diff3_t; + typedef enum { tc_mobj, @@ -2795,12 +2810,14 @@ static void SaveMobjThinker(savebuffer_t *save, const thinker_t *th, const UINT8 const mobj_t *mobj = (const mobj_t *)th; UINT32 diff; UINT32 diff2; + UINT32 diff3; size_t j; if (TypeIsNetSynced(mobj->type) == false) return; diff2 = 0; + diff3 = 0; if (mobj->spawnpoint) { @@ -2982,8 +2999,6 @@ static void SaveMobjThinker(savebuffer_t *save, const thinker_t *th, const UINT8 || (slope->normal.z != FRACUNIT)) diff2 |= MD2_FLOORSPRITESLOPE; } - if (mobj->lightlevel) - diff2 |= MD2_LIGHTLEVEL; if (mobj->hitlag) diff2 |= MD2_HITLAG; if (mobj->waterskip) @@ -3001,6 +3016,16 @@ static void SaveMobjThinker(savebuffer_t *save, const thinker_t *th, const UINT8 if (mobj->terrain != NULL || mobj->terrainOverlay != NULL) diff2 |= MD2_TERRAIN; + if (mobj->lightlevel) + diff3 |= MD3_LIGHTLEVEL; + if (mobj->reappear) + diff3 |= MD3_REAPPEAR; + if (mobj->punt_ref) + diff3 |= MD3_PUNT_REF; + + if (diff3 != 0) + diff2 |= MD2_MORE; + if (diff2 != 0) diff |= MD_MORE; @@ -3012,6 +3037,8 @@ static void SaveMobjThinker(savebuffer_t *save, const thinker_t *th, const UINT8 WRITEUINT32(save->p, diff); if (diff & MD_MORE) WRITEUINT32(save->p, diff2); + if (diff2 & MD2_MORE) + WRITEUINT32(save->p, diff3); WRITEFIXED(save->p, mobj->z); // Force this so 3dfloor problems don't arise. WRITEFIXED(save->p, mobj->floorz); @@ -3249,10 +3276,6 @@ static void SaveMobjThinker(savebuffer_t *save, const thinker_t *th, const UINT8 WRITEFIXED(save->p, slope->normal.y); WRITEFIXED(save->p, slope->normal.z); } - if (diff2 & MD2_LIGHTLEVEL) - { - WRITEINT16(save->p, mobj->lightlevel); - } if (diff2 & MD2_HITLAG) { WRITEINT32(save->p, mobj->hitlag); @@ -3275,6 +3298,19 @@ static void SaveMobjThinker(savebuffer_t *save, const thinker_t *th, const UINT8 WRITEUINT32(save->p, SaveMobjnum(mobj->terrainOverlay)); } + if (diff3 & MD3_LIGHTLEVEL) + { + WRITEINT16(save->p, mobj->lightlevel); + } + if (diff3 & MD3_REAPPEAR) + { + WRITEUINT32(save->p, mobj->reappear); + } + if (diff3 & MD3_PUNT_REF) + { + WRITEUINT32(save->p, mobj->punt_ref->mobjnum); + } + WRITEUINT32(save->p, mobj->mobjnum); } @@ -4148,6 +4184,7 @@ static thinker_t* LoadMobjThinker(savebuffer_t *save, actionf_p1 thinker) mobj_t *mobj; UINT32 diff; UINT32 diff2; + UINT32 diff3; INT32 i; fixed_t z, floorz, ceilingz; ffloor_t *floorrover = NULL, *ceilingrover = NULL; @@ -4159,6 +4196,11 @@ static thinker_t* LoadMobjThinker(savebuffer_t *save, actionf_p1 thinker) else diff2 = 0; + if (diff2 & MD2_MORE) + diff3 = READUINT32(save->p); + else + diff3 = 0; + z = READFIXED(save->p); // Force this so 3dfloor problems don't arise. floorz = READFIXED(save->p); ceilingz = READFIXED(save->p); @@ -4484,10 +4526,6 @@ static thinker_t* LoadMobjThinker(savebuffer_t *save, actionf_p1 thinker) P_UpdateSlopeLightOffset(slope); } - if (diff2 & MD2_LIGHTLEVEL) - { - mobj->lightlevel = READINT16(save->p); - } if (diff2 & MD2_HITLAG) { mobj->hitlag = READINT32(save->p); @@ -4514,6 +4552,19 @@ static thinker_t* LoadMobjThinker(savebuffer_t *save, actionf_p1 thinker) mobj->terrain = NULL; } + if (diff3 & MD3_LIGHTLEVEL) + { + mobj->lightlevel = READINT16(save->p); + } + if (diff3 & MD3_REAPPEAR) + { + mobj->reappear = READUINT32(save->p); + } + if (diff3 & MD3_PUNT_REF) + { + mobj->punt_ref = (mobj_t *)(size_t)READUINT32(save->p); + } + // set sprev, snext, bprev, bnext, subsector P_SetThingPosition(mobj); @@ -5553,6 +5604,13 @@ static void P_RelinkPointers(void) if (!P_SetTarget(&mobj->terrainOverlay, P_FindNewPosition(temp))) CONS_Debug(DBG_GAMELOGIC, "terrainOverlay not found on %d\n", mobj->type); } + if (mobj->punt_ref) + { + temp = (UINT32)(size_t)mobj->punt_ref; + mobj->punt_ref = NULL; + if (!P_SetTarget(&mobj->punt_ref, P_FindNewPosition(temp))) + CONS_Debug(DBG_GAMELOGIC, "punt_ref not found on %d\n", mobj->type); + } } for (i = 0; i < MAXPLAYERS; i++) diff --git a/src/p_user.c b/src/p_user.c index 2c36e7f97..fbb03d497 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -1168,6 +1168,9 @@ mobj_t *P_SpawnGhostMobj(mobj_t *mobj) K_ReduceVFX(ghost, mobj->player); + ghost->reappear = mobj->reappear; + P_SetTarget(&ghost->punt_ref, mobj->punt_ref); + return ghost; } @@ -2714,9 +2717,6 @@ void P_NukeEnemies(mobj_t *inflictor, mobj_t *source, fixed_t radius) if (!(mo->flags & MF_SHOOTABLE) && (mo->type != MT_SPB)) // Don't want to give SPB MF_SHOOTABLE, to ensure it's undamagable through other means continue; - if (mo->flags & MF_MONITOR) - continue; // Monitors cannot be 'nuked'. - if (abs(inflictor->x - mo->x) > radius || abs(inflictor->y - mo->y) > radius || abs(inflictor->z - mo->z) > radius) continue; // Workaround for possible integer overflow in the below -Red @@ -4397,12 +4397,12 @@ void P_PlayerThink(player_t *player) } } + boolean deathcontrolled = (player->respawn.state != RESPAWNST_NONE && player->respawn.truedeath == true) + || (player->pflags & PF_NOCONTEST) || (player->karmadelay); + boolean powercontrolled = (player->hyudorotimer) || (player->growshrinktimer > 0); + // Flash player after being hit. - if (!(player->hyudorotimer // SRB2kart - fixes Hyudoro not flashing when it should. - || player->growshrinktimer > 0 // Grow doesn't flash either. - || (player->respawn.state != RESPAWNST_NONE && player->respawn.truedeath == true) // Respawn timer (for drop dash effect) - || (player->pflags & PF_NOCONTEST) // NO CONTEST explosion - || player->karmadelay)) + if (!deathcontrolled && !powercontrolled) { if (player->flashing > 1 && player->flashing < K_GetKartFlashing(player) && (leveltime & 1)) @@ -4410,6 +4410,10 @@ void P_PlayerThink(player_t *player) else player->mo->renderflags &= ~RF_DONTDRAW; } + else if (!deathcontrolled) + { + player->mo->renderflags &= ~RF_DONTDRAW; + } if (player->stairjank > 0) { diff --git a/src/r_bbox.c b/src/r_bbox.c index 3654565a8..ce4f3d758 100644 --- a/src/r_bbox.c +++ b/src/r_bbox.c @@ -240,7 +240,7 @@ static boolean is_tangible (mobj_t *thing) // These objects probably do nothing! :D if ((thing->flags & (MF_SPECIAL|MF_SOLID|MF_SHOOTABLE |MF_PUSHABLE|MF_BOSS|MF_MISSILE|MF_SPRING - |MF_MONITOR|MF_ENEMY|MF_PAIN|MF_STICKY + |MF_ELEMENTAL|MF_ENEMY|MF_PAIN|MF_DONTPUNT |MF_PICKUPFROMBELOW)) == 0U) { return false; diff --git a/src/r_fps.c b/src/r_fps.c index 61c3eb192..1418b2a22 100644 --- a/src/r_fps.c +++ b/src/r_fps.c @@ -140,6 +140,10 @@ void R_InterpolateView(fixed_t frac) prevview = newview; } + viewx = R_LerpFixed(prevview->x, newview->x, frac); + viewy = R_LerpFixed(prevview->y, newview->y, frac); + viewz = R_LerpFixed(prevview->z, newview->z, frac); + viewangle = R_LerpAngle(prevview->angle, newview->angle, frac); aimingangle = R_LerpAngle(prevview->aim, newview->aim, frac); viewroll = R_LerpAngle(prevview->roll, newview->roll, frac); @@ -147,12 +151,6 @@ void R_InterpolateView(fixed_t frac) viewsin = FINESINE(viewangle>>ANGLETOFINESHIFT); viewcos = FINECOSINE(viewangle>>ANGLETOFINESHIFT); - fixed_t zoom = R_LerpFixed(prevview->zoom, newview->zoom, frac); - - viewx = R_LerpFixed(prevview->x, newview->x, frac) - FixedMul(viewcos, zoom); - viewy = R_LerpFixed(prevview->y, newview->y, frac) - FixedMul(viewsin, zoom); - viewz = R_LerpFixed(prevview->z, newview->z, frac); - viewplayer = newview->player; viewsector = R_PointInSubsector(viewx, viewy)->sector; diff --git a/src/r_fps.h b/src/r_fps.h index f2df84cd9..969c427fa 100644 --- a/src/r_fps.h +++ b/src/r_fps.h @@ -48,7 +48,6 @@ struct viewvars_t { fixed_t x; fixed_t y; fixed_t z; - fixed_t zoom; boolean sky; sector_t *sector; player_t *player; diff --git a/src/r_main.cpp b/src/r_main.cpp index e05c88fe3..7277c2ace 100644 --- a/src/r_main.cpp +++ b/src/r_main.cpp @@ -1244,7 +1244,6 @@ void R_SetupFrame(int s) newview->x = r_viewmobj->x; newview->y = r_viewmobj->y; newview->z = r_viewmobj->z; - newview->zoom = 0; R_SetupCommonFrame(player, r_viewmobj->subsector); } @@ -1253,13 +1252,9 @@ void R_SetupFrame(int s) { r_viewmobj = NULL; - fixed_t x = player->mo ? player->mo->x : thiscam->x; - fixed_t y = player->mo ? player->mo->y : thiscam->y; - - newview->x = x; - newview->y = y; + newview->x = thiscam->x; + newview->y = thiscam->y; newview->z = thiscam->z + (thiscam->height>>1); - newview->zoom = FixedHypot(thiscam->x - x, thiscam->y - y); R_SetupCommonFrame(player, thiscam->subsector); } @@ -1272,7 +1267,6 @@ void R_SetupFrame(int s) newview->x = r_viewmobj->x; newview->y = r_viewmobj->y; newview->z = player->viewz; - newview->zoom = 0; R_SetupCommonFrame(player, r_viewmobj->subsector); } @@ -1303,7 +1297,6 @@ void R_SkyboxFrame(int s) newview->x = r_viewmobj->x; newview->y = r_viewmobj->y; newview->z = r_viewmobj->z; // 26/04/17: use actual Z position instead of spawnpoint angle! - newview->zoom = 0; if (mapheaderinfo[gamemap-1]) { diff --git a/src/r_things.cpp b/src/r_things.cpp index 0ecf02c12..deacfce92 100644 --- a/src/r_things.cpp +++ b/src/r_things.cpp @@ -3746,6 +3746,12 @@ boolean R_ThingVisible (mobj_t *thing) if (r_viewmobj && (thing == r_viewmobj || (r_viewmobj->player && r_viewmobj->player->followmobj == thing))) return false; + if (tic_t t = P_MobjIsReappearing(thing)) + { + // Flicker back in + return t <= 2*TICRATE && (leveltime & 1); + } + if ((viewssnum == 0 && (thing->renderflags & RF_DONTDRAWP1)) || (viewssnum == 1 && (thing->renderflags & RF_DONTDRAWP2)) || (viewssnum == 2 && (thing->renderflags & RF_DONTDRAWP3)) diff --git a/src/s_sound.c b/src/s_sound.c index c0bec85fc..33cf4c3be 100644 --- a/src/s_sound.c +++ b/src/s_sound.c @@ -426,6 +426,7 @@ void S_StartSoundAtVolume(const void *origin_p, sfxenum_t sfx_id, INT32 volume) for (i = 0; i <= r_splitscreen; i++) { player_t *player = &players[displayplayers[i]]; + boolean camaway = false; memset(&listener[i], 0, sizeof (listener[i])); listenmobj[i] = NULL; @@ -442,9 +443,11 @@ void S_StartSoundAtVolume(const void *origin_p, sfxenum_t sfx_id, INT32 volume) else { listenmobj[i] = player->mo; + if (player->exiting) + camaway = true; } - if (origin && origin == listenmobj[i] && !camera[i].freecam) + if (origin && origin == listenmobj[i] && !camera[i].freecam && !camaway) { itsUs = true; } @@ -763,6 +766,9 @@ void S_UpdateSounds(void) if (c->origin != listenmobj[i]) continue; + if (listenmobj[i]->player && listenmobj[i]->player->exiting) + continue; + itsUs = true; } @@ -942,6 +948,9 @@ boolean S_AdjustSoundParams(const mobj_t *listener, const mobj_t *source, INT32 if (!listener) return false; + if (source->thinker.function.acp1 == (actionf_p1)P_MobjThinker && P_MobjIsReappearing(source)) + return false; + // Init listensource with default listener listensource.x = listener->x; listensource.y = listener->y;