From 99ed66ac4659e77ac5abb9e85d9785882dce008d Mon Sep 17 00:00:00 2001 From: TehRealSalt Date: Tue, 21 May 2019 01:01:29 -0400 Subject: [PATCH] Bubble Shield, Flame Shield changes --- src/d_player.h | 7 +- src/dehacked.c | 34 ++++++- src/doomstat.h | 1 + src/g_game.c | 1 + src/info.c | 58 +++++++++++- src/info.h | 30 +++++++ src/k_kart.c | 238 ++++++++++++++++++++++++++++++------------------- src/p_inter.c | 60 ++++++++++++- src/p_map.c | 112 +++++++++++++++++++++++ src/p_mobj.c | 159 ++++++++++++++++++++++++++++++++- 10 files changed, 597 insertions(+), 103 deletions(-) diff --git a/src/d_player.h b/src/d_player.h index c51b12769..d4dc44ea4 100644 --- a/src/d_player.h +++ b/src/d_player.h @@ -300,21 +300,22 @@ typedef enum k_itemtype, // KITEM_ constant for item number k_itemamount, // Amount of said item k_itemheld, // Are you holding an item? + k_holdready, // Hold button-style item is ready to activate // Some items use timers for their duration or effects - //k_thunderanim, // Duration of Thunder Shield's use animation k_curshield, // 0 = no shield, 1 = thunder shield k_hyudorotimer, // Duration of the Hyudoro offroad effect itself k_stealingtimer, // You are stealing an item, this is your timer k_stolentimer, // You are being stolen from, this is your timer k_superring, // Spawn rings on top of you every tic! k_sneakertimer, // Duration of the Sneaker Boost itself - k_levelbooster, // Duration of a level booster's boost (same as sneaker, but separated for ) + k_levelbooster, // Duration of a level booster's boost (same as sneaker, but separated for boost stacking) k_growshrinktimer, // > 0 = Big, < 0 = small k_squishedtimer, // Squished frame timer k_rocketsneakertimer, // Rocket Sneaker duration timer k_invincibilitytimer, // Invincibility timer - k_flameready, // Flame Shield dash ready to activate + k_bubblecool, // Bubble Shield use cooldown + k_bubbleblowup, // Bubble Shield usage blowup k_flamedash, // Flame Shield dash power k_eggmanheld, // Eggman monitor held, separate from k_itemheld so it doesn't stop you from getting items k_eggmanexplode, // Fake item recieved, explode in a few seconds diff --git a/src/dehacked.c b/src/dehacked.c index d7d428bab..5de479c9e 100644 --- a/src/dehacked.c +++ b/src/dehacked.c @@ -6634,6 +6634,35 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit "S_THUNDERSHIELD23", "S_THUNDERSHIELD24", + // Bubble Shield + "S_BUBBLESHIELD1", + "S_BUBBLESHIELD2", + "S_BUBBLESHIELD3", + "S_BUBBLESHIELD4", + "S_BUBBLESHIELD5", + "S_BUBBLESHIELD6", + "S_BUBBLESHIELD7", + "S_BUBBLESHIELD8", + "S_BUBBLESHIELD9", + "S_BUBBLESHIELD10", + "S_BUBBLESHIELD11", + "S_BUBBLESHIELD12", + "S_BUBBLESHIELD13", + "S_BUBBLESHIELD14", + "S_BUBBLESHIELD15", + "S_BUBBLESHIELD16", + "S_BUBBLESHIELD17", + "S_BUBBLESHIELD18", + "S_BUBBLESHIELDBLOWUP", + "S_BUBBLESHIELDTRAP1", + "S_BUBBLESHIELDTRAP2", + "S_BUBBLESHIELDTRAP3", + "S_BUBBLESHIELDTRAP4", + "S_BUBBLESHIELDTRAP5", + "S_BUBBLESHIELDTRAP6", + "S_BUBBLESHIELDTRAP7", + "S_BUBBLESHIELDTRAP8", + // Flame Shield "S_FLAMESHIELD1", "S_FLAMESHIELD2", @@ -7792,6 +7821,7 @@ static const char *const MOBJTYPE_LIST[] = { // array length left dynamic for s "MT_THUNDERSHIELD", // Shields "MT_BUBBLESHIELD", "MT_FLAMESHIELD", + "MT_BUBBLESHIELDTRAP", "MT_SINK", // Kitchen Sink Stuff "MT_SINK_SHIELD", @@ -8463,6 +8493,7 @@ static const char *const KARTSTUFF_LIST[] = { "ITEMTYPE", "ITEMAMOUNT", "ITEMHELD", + "HOLDREADY", "CURSHIELD", "HYUDOROTIMER", @@ -8475,7 +8506,8 @@ static const char *const KARTSTUFF_LIST[] = { "SQUISHEDTIMER", "ROCKETSNEAKERTIMER", "INVINCIBILITYTIMER", - "FLAMEREADY", + "BUBBLECOOL", + "BUBBLEBLOWUP", "FLAMEDASH", "EGGMANHELD", "EGGMANEXPLODE", diff --git a/src/doomstat.h b/src/doomstat.h index 1f855da27..b12e535ee 100644 --- a/src/doomstat.h +++ b/src/doomstat.h @@ -433,6 +433,7 @@ extern INT32 hyudorotime; extern INT32 stealtime; extern INT32 sneakertime; extern INT32 itemtime; +extern INT32 bubbletime; extern INT32 comebacktime; extern INT32 bumptime; extern INT32 wipeoutslowtime; diff --git a/src/g_game.c b/src/g_game.c index 6f08eb7c6..3a5e3d6e9 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -214,6 +214,7 @@ INT32 hyudorotime = 7*TICRATE; INT32 stealtime = TICRATE/2; INT32 sneakertime = TICRATE + (TICRATE/3); INT32 itemtime = 8*TICRATE; +INT32 bubbletime = TICRATE/2; INT32 comebacktime = 10*TICRATE; INT32 bumptime = 6; INT32 wipeoutslowtime = 20; diff --git a/src/info.c b/src/info.c index c87ac4866..f7d60dff3 100644 --- a/src/info.c +++ b/src/info.c @@ -2850,6 +2850,34 @@ state_t states[NUMSTATES] = {SPR_THNS, FF_FULLBRIGHT|1, 2, {NULL}, 0, 0, S_THUNDERSHIELD24}, // S_THUNDERSHIELD23 {SPR_THNS, FF_FULLBRIGHT|0, 2, {NULL}, 0, 0, S_THUNDERSHIELD1}, // S_THUNDERSHIELD24 + {SPR_BUBS, FF_FULLBRIGHT, 2, {NULL}, 0, 0, S_BUBBLESHIELD2}, // S_BUBBLESHIELD1 + {SPR_BUBS, FF_FULLBRIGHT|13, 2, {NULL}, 0, 0, S_BUBBLESHIELD3}, // S_BUBBLESHIELD2 + {SPR_BUBS, FF_FULLBRIGHT|1, 2, {NULL}, 0, 0, S_BUBBLESHIELD4}, // S_BUBBLESHIELD3 + {SPR_BUBS, FF_FULLBRIGHT|13, 2, {NULL}, 0, 0, S_BUBBLESHIELD5}, // S_BUBBLESHIELD4 + {SPR_BUBS, FF_FULLBRIGHT|2, 2, {NULL}, 0, 0, S_BUBBLESHIELD6}, // S_BUBBLESHIELD5 + {SPR_BUBS, FF_FULLBRIGHT|13, 2, {NULL}, 0, 0, S_BUBBLESHIELD7}, // S_BUBBLESHIELD6 + {SPR_BUBS, FF_FULLBRIGHT|3, 2, {NULL}, 0, 0, S_BUBBLESHIELD8}, // S_BUBBLESHIELD7 + {SPR_BUBS, FF_FULLBRIGHT|13, 2, {NULL}, 0, 0, S_BUBBLESHIELD9}, // S_BUBBLESHIELD8 + {SPR_BUBS, FF_FULLBRIGHT|4, 2, {NULL}, 0, 0, S_BUBBLESHIELD10}, // S_BUBBLESHIELD9 + {SPR_BUBS, FF_FULLBRIGHT|13, 2, {NULL}, 0, 0, S_BUBBLESHIELD11}, // S_BUBBLESHIELD10 + {SPR_BUBS, FF_FULLBRIGHT|5, 2, {NULL}, 0, 0, S_BUBBLESHIELD12}, // S_BUBBLESHIELD11 + {SPR_BUBS, FF_FULLBRIGHT|13, 2, {NULL}, 0, 0, S_BUBBLESHIELD13}, // S_BUBBLESHIELD12 + {SPR_BUBS, FF_FULLBRIGHT|6, 2, {NULL}, 0, 0, S_BUBBLESHIELD14}, // S_BUBBLESHIELD13 + {SPR_BUBS, FF_FULLBRIGHT|13, 2, {NULL}, 0, 0, S_BUBBLESHIELD15}, // S_BUBBLESHIELD14 + {SPR_BUBS, FF_FULLBRIGHT|7, 2, {NULL}, 0, 0, S_BUBBLESHIELD16}, // S_BUBBLESHIELD15 + {SPR_BUBS, FF_FULLBRIGHT|13, 2, {NULL}, 0, 0, S_BUBBLESHIELD17}, // S_BUBBLESHIELD16 + {SPR_BUBS, FF_FULLBRIGHT|8, 2, {NULL}, 0, 0, S_BUBBLESHIELD18}, // S_BUBBLESHIELD17 + {SPR_BUBS, FF_FULLBRIGHT|13, 2, {NULL}, 0, 0, S_BUBBLESHIELD1}, // S_BUBBLESHIELD18 + {SPR_BUBS, FF_FULLBRIGHT|13, -1, {NULL}, 0, 0, S_BUBBLESHIELDBLOWUP}, // S_BUBBLESHIELDBLOWUP + {SPR_BUBS, FF_FULLBRIGHT|13, 2, {NULL}, 0, 0, S_BUBBLESHIELDTRAP2}, // S_BUBBLESHIELDTRAP1 + {SPR_BUBS, FF_FULLBRIGHT|14, 2, {NULL}, 0, 0, S_BUBBLESHIELDTRAP3}, // S_BUBBLESHIELDTRAP2 + {SPR_BUBS, FF_FULLBRIGHT|15, 2, {NULL}, 0, 0, S_BUBBLESHIELDTRAP4}, // S_BUBBLESHIELDTRAP3 + {SPR_BUBS, FF_FULLBRIGHT|14, 2, {NULL}, 0, 0, S_BUBBLESHIELDTRAP5}, // S_BUBBLESHIELDTRAP4 + {SPR_BUBS, FF_FULLBRIGHT|13, 2, {NULL}, 0, 0, S_BUBBLESHIELDTRAP6}, // S_BUBBLESHIELDTRAP5 + {SPR_BUBS, FF_FULLBRIGHT|12, 2, {NULL}, 0, 0, S_BUBBLESHIELDTRAP7}, // S_BUBBLESHIELDTRAP6 + {SPR_BUBS, FF_FULLBRIGHT|11, 2, {NULL}, 0, 0, S_BUBBLESHIELDTRAP8}, // S_BUBBLESHIELDTRAP7 + {SPR_BUBS, FF_FULLBRIGHT|12, 2, {NULL}, 0, 0, S_BUBBLESHIELDTRAP1}, // S_BUBBLESHIELDTRAP8 + {SPR_FLMS, FF_FULLBRIGHT, 2, {NULL}, 0, 0, S_FLAMESHIELD2}, // S_FLAMESHIELD1 {SPR_FLMS, FF_FULLBRIGHT|9, 2, {NULL}, 0, 0, S_FLAMESHIELD3}, // S_FLAMESHIELD2 {SPR_FLMS, FF_FULLBRIGHT|1, 2, {NULL}, 0, 0, S_FLAMESHIELD4}, // S_FLAMESHIELD3 @@ -15957,7 +15985,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = { // MT_BUBBLESHIELD -1, // doomednum - S_THUNDERSHIELD1, // spawnstate + S_BUBBLESHIELD1, // spawnstate 1000, // spawnhealth S_NULL, // seestate sfx_None, // seesound @@ -15978,7 +16006,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = 16, // mass 0, // damage sfx_None, // activesound - MF_NOBLOCKMAP|MF_NOCLIP|MF_NOGRAVITY|MF_DONTENCOREMAP, // flags + MF_SPECIAL|MF_NOCLIP|MF_NOGRAVITY|MF_DONTENCOREMAP, // flags S_NULL // raisestate }, @@ -16009,6 +16037,32 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = S_NULL // raisestate }, + { // MT_BUBBLESHIELDTRAP + -1, // doomednum + S_BUBBLESHIELDTRAP1, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + sfx_None, // seesound + 8, // 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 + 8, // speed + 20*FRACUNIT, // radius + 56*FRACUNIT, // height + 1, // display offset + 16, // mass + 0, // damage + sfx_None, // activesound + MF_SPECIAL|MF_NOGRAVITY|MF_DONTENCOREMAP, // flags + S_NULL // raisestate + }, { // MT_SINK -1, // doomednum diff --git a/src/info.h b/src/info.h index a302aa679..000d2fb93 100644 --- a/src/info.h +++ b/src/info.h @@ -3518,6 +3518,35 @@ typedef enum state S_THUNDERSHIELD23, S_THUNDERSHIELD24, + // Bubble Shield + S_BUBBLESHIELD1, + S_BUBBLESHIELD2, + S_BUBBLESHIELD3, + S_BUBBLESHIELD4, + S_BUBBLESHIELD5, + S_BUBBLESHIELD6, + S_BUBBLESHIELD7, + S_BUBBLESHIELD8, + S_BUBBLESHIELD9, + S_BUBBLESHIELD10, + S_BUBBLESHIELD11, + S_BUBBLESHIELD12, + S_BUBBLESHIELD13, + S_BUBBLESHIELD14, + S_BUBBLESHIELD15, + S_BUBBLESHIELD16, + S_BUBBLESHIELD17, + S_BUBBLESHIELD18, + S_BUBBLESHIELDBLOWUP, + S_BUBBLESHIELDTRAP1, + S_BUBBLESHIELDTRAP2, + S_BUBBLESHIELDTRAP3, + S_BUBBLESHIELDTRAP4, + S_BUBBLESHIELDTRAP5, + S_BUBBLESHIELDTRAP6, + S_BUBBLESHIELDTRAP7, + S_BUBBLESHIELDTRAP8, + // Flame Shield S_FLAMESHIELD1, S_FLAMESHIELD2, @@ -4708,6 +4737,7 @@ typedef enum mobj_type MT_THUNDERSHIELD, // Shields MT_BUBBLESHIELD, MT_FLAMESHIELD, + MT_BUBBLESHIELDTRAP, MT_SINK, // Kitchen Sink Stuff MT_SINK_SHIELD, diff --git a/src/k_kart.c b/src/k_kart.c index 904b562fa..72158e807 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -697,7 +697,7 @@ static INT32 K_KartItemOddsRace[NUMKARTRESULTS-1][8] = /*Grow*/ { 0, 0, 0, 1, 1, 2, 0, 0 }, // Grow /*Shrink*/ { 0, 0, 0, 0, 0, 0, 2, 0 }, // Shrink /*Thunder Shield*/ { 1, 2, 0, 0, 0, 0, 0, 0 }, // Thunder Shield - /*Bubble Shield*/ { 0, 0, 0, 0, 0, 0, 0, 0 }, // Bubble Shield + /*Bubble Shield*/ { 0, 0, 0, 1, 2, 0, 0, 0 }, // Bubble Shield /*Flame Shield*/ { 0, 0, 0, 0, 0, 0, 1, 2 }, // Flame Shield /*Hyudoro*/ { 0, 0, 0, 1, 2, 1, 0, 0 }, // Hyudoro /*Pogo Spring*/ { 0, 0, 0, 0, 0, 0, 0, 0 }, // Pogo Spring @@ -1304,8 +1304,11 @@ static fixed_t K_GetMobjWeight(mobj_t *mobj, mobj_t *against) case MT_PLAYER: if (!mobj->player) break; - if (against->player && !against->player->kartstuff[k_spinouttimer] && mobj->player->kartstuff[k_spinouttimer]) - weight = 0; // Do not bump + if (against->player + && ((!against->player->kartstuff[k_spinouttimer] && mobj->player->kartstuff[k_spinouttimer]) + || (against->player->kartstuff[k_itemtype] == KITEM_BUBBLESHIELD && mobj->player->kartstuff[k_itemtype] != KITEM_BUBBLESHIELD) + || (against->type == MT_BUBBLESHIELD))) + weight = 0; // This player does not cause any bump action else { weight = (mobj->player->kartweight) * mobj->scale; @@ -3856,7 +3859,6 @@ static void K_DoThunderShield(player_t *player) angle_t an; S_StartSound(player->mo, sfx_zio3); - //player->kartstuff[k_thunderanim] = 35; P_NukeEnemies(player->mo, player->mo, RING_DIST/4); // spawn vertical bolt @@ -4221,14 +4223,20 @@ void K_DropHnextList(player_t *player) K_DoThunderShield(player); player->kartstuff[k_itemtype] = KITEM_NONE; player->kartstuff[k_itemamount] = 0; - player->kartstuff[k_curshield] = 0; + player->kartstuff[k_curshield] = KSHIELD_NONE; + } + else if (player->kartstuff[k_itemtype] == KITEM_BUBBLESHIELD) + { + player->kartstuff[k_itemtype] = KITEM_NONE; + player->kartstuff[k_itemamount] = 0; + player->kartstuff[k_curshield] = KSHIELD_NONE; } else if (player->kartstuff[k_itemtype] == KITEM_FLAMESHIELD) { - //K_PopFlameShield(player); + K_FlameShieldPop(player->mo); player->kartstuff[k_itemtype] = KITEM_NONE; player->kartstuff[k_itemamount] = 0; - player->kartstuff[k_curshield] = 0; + player->kartstuff[k_curshield] = KSHIELD_NONE; } nextwork = work->hnext; @@ -5043,6 +5051,68 @@ void K_KartPlayerHUDUpdate(player_t *player) #undef RINGANIM_DELAYMAX +// SRB2Kart: blockmap iterate for attraction shield users +static mobj_t *attractmo; +static fixed_t attractdist; +static inline boolean PIT_AttractingRings(mobj_t *thing) +{ + if (!attractmo || P_MobjWasRemoved(attractmo)) + return false; + + if (!attractmo->player) + return false; // not a player + + if (thing->health <= 0 || !thing) + return true; // dead + + if (thing->type != MT_RING && thing->type != MT_FLINGRING) + return true; // not a ring + + if (thing->extravalue1) + return true; // in special ring animation + + if (thing->cusval) + return true; // already attracted + + // see if it went over / under + if (attractmo->z - (attractdist>>2) > thing->z + thing->height) + return true; // overhead + if (attractmo->z + attractmo->height + (attractdist>>2) < thing->z) + return true; // underneath + + if (P_AproxDistance(attractmo->x - thing->x, attractmo->y - thing->y) < attractdist) + return true; // Too far away + + // set target + P_SetTarget(&thing->tracer, attractmo); + // flag to show it's been attracted once before + thing->cusval = 1; + return true; // find other rings +} + +/** Looks for rings near a player in the blockmap. + * + * \param pmo Player object looking for rings to attract + * \sa A_AttractChase + */ +static void K_LookForRings(mobj_t *pmo) +{ + INT32 bx, by, xl, xh, yl, yh; + attractdist = FixedMul(RING_DIST, pmo->scale)>>2; + + // Use blockmap to check for nearby rings + yh = (unsigned)(pmo->y + attractdist - bmaporgy)>>MAPBLOCKSHIFT; + yl = (unsigned)(pmo->y - attractdist - bmaporgy)>>MAPBLOCKSHIFT; + xh = (unsigned)(pmo->x + attractdist - bmaporgx)>>MAPBLOCKSHIFT; + xl = (unsigned)(pmo->x - attractdist - bmaporgx)>>MAPBLOCKSHIFT; + + attractmo = pmo; + + for (by = yl; by <= yh; by++) + for (bx = xl; bx <= xh; bx++) + P_BlockThingsIterator(bx, by, PIT_AttractingRings); +} + /** \brief Decreases various kart timers and powers per frame. Called in P_PlayerThink in p_user.c \param player player object passed from P_PlayerThink @@ -5192,6 +5262,9 @@ void K_KartPlayerThink(player_t *player, ticcmd_t *cmd) player->mo->colorized = false; } + if (player->kartstuff[k_itemtype] == KITEM_NONE) + player->kartstuff[k_holdready] = 0; + // DKR style camera for boosting if (player->karthud[khud_boostcam] != 0 || player->karthud[khud_destboostcam] != 0) { @@ -5382,6 +5455,31 @@ void K_KartPlayerThink(player_t *player, ticcmd_t *cmd) } } + if (player->kartstuff[k_itemtype] == KITEM_THUNDERSHIELD) + { + if (RINGTOTAL(player) < 20 && !player->kartstuff[k_ringlock]) + K_LookForRings(player->mo); + } + + if (player->kartstuff[k_itemtype] == KITEM_BUBBLESHIELD) + { + if (player->kartstuff[k_bubblecool]) + player->kartstuff[k_bubblecool]--; + } + else + { + player->kartstuff[k_bubbleblowup] = 0; + player->kartstuff[k_bubblecool] = 0; + } + + if (player->kartstuff[k_itemtype] != KITEM_FLAMESHIELD + || player->exiting || player->kartstuff[k_spinouttimer] || player->kartstuff[k_squishedtimer]) + { + if (player->kartstuff[k_flamedash]) + K_FlameShieldPop(player->mo); + player->kartstuff[k_flamedash] = 0; + } + // ??? /* if (player->kartstuff[k_jmp] > 1 && onground) @@ -5890,8 +5988,7 @@ void K_StripItems(player_t *player) player->kartstuff[k_stealingtimer] = 0; player->kartstuff[k_stolentimer] = 0; - player->kartstuff[k_curshield] = 0; - //player->kartstuff[k_thunderanim] = 0; + player->kartstuff[k_curshield] = KSHIELD_NONE; player->kartstuff[k_bananadrag] = 0; player->kartstuff[k_sadtimer] = 0; @@ -5914,68 +6011,6 @@ void K_StripOther(player_t *player) } } -// SRB2Kart: blockmap iterate for attraction shield users -static mobj_t *attractmo; -static fixed_t attractdist; -static inline boolean PIT_AttractingRings(mobj_t *thing) -{ - if (!attractmo || P_MobjWasRemoved(attractmo)) - return false; - - if (!attractmo->player) - return false; // not a player - - if (thing->health <= 0 || !thing) - return true; // dead - - if (thing->type != MT_RING && thing->type != MT_FLINGRING) - return true; // not a ring - - if (thing->extravalue1) - return true; // in special ring animation - - if (thing->cusval) - return true; // already attracted - - // see if it went over / under - if (attractmo->z - (attractdist>>2) > thing->z + thing->height) - return true; // overhead - if (attractmo->z + attractmo->height + (attractdist>>2) < thing->z) - return true; // underneath - - if (P_AproxDistance(attractmo->x - thing->x, attractmo->y - thing->y) < attractdist) - return true; // Too far away - - // set target - P_SetTarget(&thing->tracer, attractmo); - // flag to show it's been attracted once before - thing->cusval = 1; - return true; // find other rings -} - -/** Looks for rings near a player in the blockmap. - * - * \param pmo Player object looking for rings to attract - * \sa A_AttractChase - */ -static void K_LookForRings(mobj_t *pmo) -{ - INT32 bx, by, xl, xh, yl, yh; - attractdist = FixedMul(RING_DIST, pmo->scale)>>2; - - // Use blockmap to check for nearby rings - yh = (unsigned)(pmo->y + attractdist - bmaporgy)>>MAPBLOCKSHIFT; - yl = (unsigned)(pmo->y - attractdist - bmaporgy)>>MAPBLOCKSHIFT; - xh = (unsigned)(pmo->x + attractdist - bmaporgx)>>MAPBLOCKSHIFT; - xl = (unsigned)(pmo->x - attractdist - bmaporgx)>>MAPBLOCKSHIFT; - - attractmo = pmo; - - for (by = yl; by <= yh; by++) - for (bx = xl; bx <= xh; bx++) - P_BlockThingsIterator(bx, by, PIT_AttractingRings); -} - // // K_MoveKartPlayer // @@ -6408,12 +6443,44 @@ void K_MoveKartPlayer(player_t *player, boolean onground) case KITEM_BUBBLESHIELD: if (player->kartstuff[k_curshield] != KSHIELD_BUBBLE) { - //mobj_t *shield = P_SpawnMobj(player->mo->x, player->mo->y, player->mo->z, MT_BUBBLESHIELD); - //P_SetScale(shield, (shield->destscale = (5*shield->destscale)>>2)); - //P_SetTarget(&shield->target, player->mo); + mobj_t *shield = P_SpawnMobj(player->mo->x, player->mo->y, player->mo->z, MT_BUBBLESHIELD); + P_SetScale(shield, (shield->destscale = (5*shield->destscale)>>2)); + P_SetTarget(&shield->target, player->mo); S_StartSound(player->mo, sfx_s3k3f); player->kartstuff[k_curshield] = KSHIELD_BUBBLE; } + + if (!HOLDING_ITEM && NO_HYUDORO) + { + if (cmd->buttons & BT_ATTACK) + { + if (player->kartstuff[k_holdready]) + { + if (player->kartstuff[k_bubbleblowup] == 0) + K_PlayAttackTaunt(player->mo); + player->kartstuff[k_bubbleblowup]++; + player->kartstuff[k_bubblecool] = TICRATE+bubbletime; + if (player->kartstuff[k_bubbleblowup] > bubbletime) + { + mobj_t *trap = P_SpawnMobj(player->mo->x, player->mo->y, player->mo->z, MT_BUBBLESHIELDTRAP); + P_SetScale(trap, (5*trap->destscale)>>1); + trap->destscale = (5*trap->destscale)>>2; + P_SetTarget(&trap->target, player->mo); + trap->threshold = 10; + S_StartSound(player->mo, sfx_s3k44); + + player->kartstuff[k_bubbleblowup] = 0; + player->kartstuff[k_itemamount]--; + } + } + } + else + { + if (player->kartstuff[k_bubbleblowup]) + player->kartstuff[k_bubbleblowup]--; + player->kartstuff[k_holdready] = (player->kartstuff[k_bubblecool] ? 0 : 1); + } + } break; case KITEM_FLAMESHIELD: if (player->kartstuff[k_curshield] != KSHIELD_FLAME) @@ -6429,7 +6496,7 @@ void K_MoveKartPlayer(player_t *player, boolean onground) { if (cmd->buttons & BT_ATTACK) { - if (player->kartstuff[k_flameready]) + if (player->kartstuff[k_holdready]) { if (player->kartstuff[k_flamedash] == 0) K_PlayBoostTaunt(player->mo); @@ -6438,7 +6505,7 @@ void K_MoveKartPlayer(player_t *player, boolean onground) { K_FlameShieldPop(player->mo); player->kartstuff[k_flamedash] = 0; - player->kartstuff[k_flameready] = 0; + player->kartstuff[k_holdready] = 0; player->kartstuff[k_itemamount]--; } } @@ -6449,13 +6516,13 @@ void K_MoveKartPlayer(player_t *player, boolean onground) { K_FlameShieldPop(player->mo); player->kartstuff[k_flamedash] = 0; - player->kartstuff[k_flameready] = 0; + player->kartstuff[k_holdready] = 0; player->kartstuff[k_itemamount]--; } else { player->kartstuff[k_flamedash] = 0; - player->kartstuff[k_flameready] = 1; + player->kartstuff[k_holdready] = 1; } } } @@ -6535,21 +6602,6 @@ void K_MoveKartPlayer(player_t *player, boolean onground) if (spbplace == -1 || player->kartstuff[k_position] != spbplace) player->kartstuff[k_ringlock] = 0; // reset ring lock - if (player->kartstuff[k_itemtype] == KITEM_THUNDERSHIELD) - { - if (RINGTOTAL(player) < 20 && !player->kartstuff[k_ringlock]) - K_LookForRings(player->mo); - } - - if (player->kartstuff[k_itemtype] != KITEM_FLAMESHIELD - || player->exiting || player->kartstuff[k_spinouttimer] || player->kartstuff[k_squishedtimer]) - { - if (player->kartstuff[k_flamedash]) - K_FlameShieldPop(player->mo); - player->kartstuff[k_flamedash] = 0; - player->kartstuff[k_flameready] = 0; - } - if (K_GetShieldFromItem(player->kartstuff[k_itemtype]) == KSHIELD_NONE) player->kartstuff[k_curshield] = KSHIELD_NONE; // RESET shield type diff --git a/src/p_inter.c b/src/p_inter.c index 406644a1b..760026944 100644 --- a/src/p_inter.c +++ b/src/p_inter.c @@ -595,11 +595,12 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck) { mobj_t *spbexplode; - if (player->kartstuff[k_invincibilitytimer] > 0 || player->kartstuff[k_growshrinktimer] > 0 || player->kartstuff[k_hyudorotimer] > 0) + if (player->kartstuff[k_bubbleblowup] > 0) { - //player->powers[pw_flashing] = 0; K_DropHnextList(player); - K_StripItems(player); + special->extravalue1 = 2; // WAIT... + special->extravalue2 = 52; // Slightly over the respawn timer length + return; } S_StopSound(special); // Don't continue playing the gurgle or the siren @@ -675,6 +676,59 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck) case MT_BALLOON: // SRB2kart P_SetObjectMomZ(toucher, 20<target == toucher) + return; + + if (special->health <= 0 || toucher->health <= 0) + return; + + if (player->spectator) + return; + + if (special->target->player && special->target->player->kartstuff[k_bubbleblowup] + && !player->kartstuff[k_spinouttimer]) + { + K_SpinPlayer(player, special->target, 0, special, false); + if (player->kartstuff[k_spinouttimer]) // Successfully spun out + K_KartBouncing(toucher, special, false, true); + } + return; + case MT_BUBBLESHIELDTRAP: + if ((special->target == toucher || special->target == toucher->target) && (special->threshold > 0)) + return; + + if (special->tracer && !P_MobjWasRemoved(special->tracer)) + return; + + if (special->health <= 0 || toucher->health <= 0) + return; + + if (!player->mo || player->spectator) + return; + + // kill + /*if (player->kartstuff[k_invincibilitytimer] > 0 + || player->kartstuff[k_growshrinktimer] > 0 + || player->kartstuff[k_flamedash] > 0) + { + P_KillMobj(special, toucher, toucher); + return; + }*/ + + // no interaction + if (player->powers[pw_flashing] > 0 || player->kartstuff[k_hyudorotimer] > 0 + || player->kartstuff[k_squishedtimer] > 0 || player->kartstuff[k_spinouttimer] > 0) + return; + + // attach to player! + P_SetTarget(&special->tracer, toucher); + toucher->flags |= MF_NOGRAVITY; + toucher->momx = (4*toucher->momx)/5; // Huge initial speed cut + toucher->momy = (4*toucher->momy)/5; + toucher->momz = (8*toucher->scale) * P_MobjFlip(toucher); + //S_StartSound(special, sfx_s1a2); + return; // ***************************************** // // Rings, coins, spheres, weapon panels, etc // diff --git a/src/p_map.c b/src/p_map.c index 025d84b02..4f0edfae0 100644 --- a/src/p_map.c +++ b/src/p_map.c @@ -750,6 +750,29 @@ static boolean PIT_CheckThing(mobj_t *thing) if (thing->player && thing->player->kartstuff[k_hyudorotimer]) return true; // no interaction + if ((thing->type == MT_BUBBLESHIELD && thing->target->player && thing->target->player->kartstuff[k_bubbleblowup]) + || (thing->player && thing->player->kartstuff[k_bubbleblowup])) + { + if (!tmthing->threshold) + { + if (!tmthing->momx && !tmthing->momy) + { + tmthing->momz = (32*tmthing->scale) * P_MobjFlip(tmthing); + } + else + { + tmthing->momx = -tmthing->momx; + tmthing->momy = -tmthing->momy; + tmthing->momz = -tmthing->momz; + } + if (tmthing->type == MT_JAWZ) + P_SetTarget(&tmthing->tracer, tmthing->target); // Back to the source! + tmthing->threshold = 10; + S_StartSound(tmthing, sfx_s3k44); + } + return true; + } + if (thing->type == MT_PLAYER) { // Player Damage @@ -851,6 +874,27 @@ static boolean PIT_CheckThing(mobj_t *thing) if (thing->player && thing->player->powers[pw_flashing]) return true; + if ((thing->type == MT_BUBBLESHIELD && thing->target->player && thing->target->player->kartstuff[k_bubbleblowup]) + || (thing->player && thing->player->kartstuff[k_bubbleblowup])) + { + if (!tmthing->threshold) + { + if (!tmthing->momx && !tmthing->momy) + { + tmthing->momz = (32*tmthing->scale) * P_MobjFlip(tmthing); + } + else + { + tmthing->momx = -tmthing->momx; + tmthing->momy = -tmthing->momy; + tmthing->momz = -tmthing->momz; + } + tmthing->threshold = 10; + S_StartSound(tmthing, sfx_s3k44); + } + return true; + } + if (thing->type == MT_PLAYER) { S_StartSound(NULL, sfx_bsnipe); //let all players hear it. @@ -913,6 +957,27 @@ static boolean PIT_CheckThing(mobj_t *thing) if (thing->player && thing->player->powers[pw_flashing]) return true; + if ((thing->type == MT_BUBBLESHIELD && thing->target->player && thing->target->player->kartstuff[k_bubbleblowup]) + || (thing->player && thing->player->kartstuff[k_bubbleblowup])) + { + if (!tmthing->threshold) + { + if (!tmthing->momx && !tmthing->momy) + { + tmthing->momz = (32*tmthing->scale) * P_MobjFlip(tmthing); + } + else + { + tmthing->momx = -tmthing->momx; + tmthing->momy = -tmthing->momy; + tmthing->momz = -tmthing->momz; + } + tmthing->threshold = 10; + S_StartSound(tmthing, sfx_s3k44); + } + return true; + } + if (thing->type == MT_PLAYER) { // Banana snipe! @@ -985,6 +1050,28 @@ static boolean PIT_CheckThing(mobj_t *thing) if (thing->player && thing->player->powers[pw_flashing]) return true; + // Bubble Shield reflect + if ((thing->type == MT_BUBBLESHIELD && thing->target->player && thing->target->player->kartstuff[k_bubbleblowup]) + || (thing->player && thing->player->kartstuff[k_bubbleblowup])) + { + if (!tmthing->threshold) + { + if (!tmthing->momx && !tmthing->momy) + { + tmthing->momz = (32*tmthing->scale) * P_MobjFlip(tmthing); + } + else + { + tmthing->momx = -tmthing->momx; + tmthing->momy = -tmthing->momy; + tmthing->momz = -tmthing->momz; + } + tmthing->threshold = 10; + S_StartSound(tmthing, sfx_s3k44); + } + return true; + } + if (thing->type == MT_PLAYER) { // Bomb punting @@ -1036,6 +1123,31 @@ static boolean PIT_CheckThing(mobj_t *thing) if (tmthing->player && tmthing->player->kartstuff[k_hyudorotimer]) // I thought about doing this for just the objects below but figured it should apply to everything. return true; // no interaction + // Bubble Shield reflect + if (((tmthing->type == MT_BUBBLESHIELD && tmthing->target->player && tmthing->target->player->kartstuff[k_bubbleblowup]) + || (tmthing->player && tmthing->player->kartstuff[k_bubbleblowup])) + && (thing->type != MT_MINEEXPLOSION)) + { + if (!thing->threshold) + { + if (!thing->momx && !thing->momy) + { + thing->momz = (32*thing->scale) * P_MobjFlip(thing); + } + else + { + thing->momx = -thing->momx; + thing->momy = -thing->momy; + thing->momz = -thing->momz; + } + if (thing->type == MT_JAWZ) + P_SetTarget(&thing->tracer, thing->target); // Back to the source! + thing->threshold = 10; + S_StartSound(thing, sfx_s3k44); + } + return true; + } + if (thing->type == MT_ORBINAUT_SHIELD || thing->type == MT_JAWZ_SHIELD || thing->type == MT_ORBINAUT || thing->type == MT_JAWZ || thing->type == MT_JAWZ_DUD) { diff --git a/src/p_mobj.c b/src/p_mobj.c index 7892f3414..775af90e1 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -8399,6 +8399,100 @@ void P_MobjThinker(mobj_t *mobj) P_TeleportMove(mobj, destx, desty, mobj->target->z); break; } + case MT_BUBBLESHIELD: + { + fixed_t destx, desty; + fixed_t scale; + statenum_t curstate; + + if (!mobj->target || !mobj->target->health || !mobj->target->player + || mobj->target->player->kartstuff[k_curshield] != KSHIELD_BUBBLE) + { + P_RemoveMobj(mobj); + return; + } + + scale = (5*mobj->target->destscale)>>2; + curstate = ((mobj->tics == 1) ? (mobj->state->nextstate) : ((statenum_t)(mobj->state-states))); + + if (mobj->target->player->kartstuff[k_bubbleblowup]) + { + INT32 blow = mobj->target->player->kartstuff[k_bubbleblowup]; + + if (curstate != S_BUBBLESHIELDBLOWUP) + P_SetMobjState(mobj, S_BUBBLESHIELDBLOWUP); + + mobj->flags2 &= ~MF2_SHADOW; + scale += (blow * (scale<<1)) / bubbletime; + + mobj->frame = (states[S_BUBBLESHIELDBLOWUP].frame + mobj->extravalue1); + + if (mobj->extravalue1 < 4 && mobj->extravalue2 < blow && !mobj->cvmem && (leveltime & 1)) // Growing + { + mobj->extravalue1++; + if (mobj->extravalue1 >= 4) + mobj->cvmem = 1; // shrink back down + } + else if ((mobj->extravalue1 > -4 && mobj->extravalue2 > blow) + || (mobj->cvmem && mobj->extravalue1 > 0)) // Shrinking + mobj->extravalue1--; + } + else + { + mobj->cvmem = 0; + + if (curstate == S_BUBBLESHIELDBLOWUP) + { + if (mobj->extravalue1 != 0) + { + mobj->frame = (states[S_BUBBLESHIELDBLOWUP].frame + mobj->extravalue1); + + if (mobj->extravalue1 < 0 && (leveltime & 1)) + mobj->extravalue1++; + else if (mobj->extravalue1 > 0) + mobj->extravalue1--; + } + else + { + P_SetMobjState(mobj, S_BUBBLESHIELD1); + mobj->extravalue1 = 0; + } + } + else + { + if (mobj->target->player->kartstuff[k_bubblecool] && ((curstate-S_BUBBLESHIELD1) & 1)) + mobj->flags2 |= MF2_SHADOW; + else + mobj->flags2 &= ~MF2_SHADOW; + } + } + + mobj->extravalue2 = mobj->target->player->kartstuff[k_bubbleblowup]; + P_SetScale(mobj, (mobj->destscale = scale)); + + if (!splitscreen /*&& rendermode != render_soft*/) + { + angle_t viewingangle; + + if (players[displayplayers[0]].awayviewtics) + viewingangle = R_PointToAngle2(mobj->target->x, mobj->target->y, players[displayplayers[0]].awayviewmobj->x, players[displayplayers[0]].awayviewmobj->y); + else if (!camera[0].chase && players[displayplayers[0]].mo) + viewingangle = R_PointToAngle2(mobj->target->x, mobj->target->y, players[displayplayers[0]].mo->x, players[displayplayers[0]].mo->y); + else + viewingangle = R_PointToAngle2(mobj->target->x, mobj->target->y, camera[0].x, camera[0].y); + + destx = mobj->target->x + P_ReturnThrustX(mobj->target, viewingangle, mobj->scale>>4); + desty = mobj->target->y + P_ReturnThrustY(mobj->target, viewingangle, mobj->scale>>4); + } + else + { + destx = mobj->target->x; + desty = mobj->target->y; + } + + P_TeleportMove(mobj, destx, desty, mobj->target->z); + break; + } case MT_FLAMESHIELD: { fixed_t destx, desty; @@ -9122,6 +9216,69 @@ void P_MobjThinker(mobj_t *mobj) } } break; + case MT_BUBBLESHIELDTRAP: + if (mobj->tracer && !P_MobjWasRemoved(mobj->tracer) && mobj->tracer->player) + { + player_t *player = mobj->tracer->player; + + mobj->extravalue1 = 1; + + P_TeleportMove(mobj, + mobj->tracer->x + P_ReturnThrustX(NULL, mobj->tracer->angle+ANGLE_90, (mobj->cvmem)<tracer->y + P_ReturnThrustY(NULL, mobj->tracer->angle+ANGLE_90, (mobj->cvmem)<tracer->z + (P_RandomRange(-abs(mobj->cvmem), abs(mobj->cvmem))<cvmem /= 2; + mobj->momz = 0; + mobj->destscale = (5*mobj->tracer->scale)>>2; + + mobj->tracer->momx = (31*mobj->tracer->momx)/32; + mobj->tracer->momy = (31*mobj->tracer->momy)/32; + mobj->tracer->momz = (8*mobj->tracer->scale) * P_MobjFlip(mobj->tracer); + + if (mobj->movecount > 8*TICRATE) + { + S_StartSound(mobj->tracer, sfx_s3k77); + mobj->tracer->flags &= ~MF_NOGRAVITY; + P_KillMobj(mobj, mobj->tracer, mobj->tracer); + break; + } + + if (abs(player->cmd.driftturn) > 100) + { + INT32 lastsign = 0; + if (mobj->lastlook > 0) + lastsign = 1; + else if (mobj->lastlook < 0) + lastsign = -1; + + if ((player->cmd.driftturn > 0 && lastsign < 0) + || (player->cmd.driftturn < 0 && lastsign > 0)) + { + mobj->movecount += (TICRATE/2); + mobj->cvmem = 8*lastsign; + S_StartSound(mobj, sfx_s3k7a); + } + + mobj->lastlook = player->cmd.driftturn; + } + + mobj->movecount++; + } + else if (mobj->extravalue1) // lost your player somehow, DIE + { + mobj->tracer->flags &= ~MF_NOGRAVITY; + P_KillMobj(mobj, NULL, NULL); + break; + } + else + { + mobj->momz = 0; + mobj->destscale = (5*mapobjectscale)>>2; + if (mobj->threshold > 0) + mobj->threshold--; + } + break; case MT_KARMAFIREWORK: if (mobj->momz == 0) { @@ -10179,7 +10336,7 @@ mobj_t *P_SpawnMobj(fixed_t x, fixed_t y, fixed_t z, mobjtype_t type) case MT_SSMINE: case MT_SSMINE_SHIELD: case MT_BALLHOG: case MT_SINK: case MT_THUNDERSHIELD: case MT_BUBBLESHIELD: case MT_FLAMESHIELD: - case MT_ROCKETSNEAKER: + case MT_ROCKETSNEAKER: case MT_BUBBLESHIELDTRAP: case MT_SPB: P_SpawnShadowMobj(mobj); default: