diff --git a/src/dehacked.c b/src/dehacked.c index ae9ab561a..e361bbc8e 100644 --- a/src/dehacked.c +++ b/src/dehacked.c @@ -8720,6 +8720,30 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit "S_BATTLEBUMPER2", "S_BATTLEBUMPER3", + "S_BATTLEBUMPER_EXCRYSTALA1", + "S_BATTLEBUMPER_EXCRYSTALA2", + "S_BATTLEBUMPER_EXCRYSTALA3", + "S_BATTLEBUMPER_EXCRYSTALA4", + + "S_BATTLEBUMPER_EXCRYSTALB1", + "S_BATTLEBUMPER_EXCRYSTALB2", + "S_BATTLEBUMPER_EXCRYSTALB3", + "S_BATTLEBUMPER_EXCRYSTALB4", + + "S_BATTLEBUMPER_EXCRYSTALC1", + "S_BATTLEBUMPER_EXCRYSTALC2", + "S_BATTLEBUMPER_EXCRYSTALC3", + "S_BATTLEBUMPER_EXCRYSTALC4", + + "S_BATTLEBUMPER_EXSHELLA1", + "S_BATTLEBUMPER_EXSHELLA2", + + "S_BATTLEBUMPER_EXSHELLB1", + "S_BATTLEBUMPER_EXSHELLB2", + + "S_BATTLEBUMPER_EXSHELLC1", + "S_BATTLEBUMPER_EXSHELLC2", + // DEZ respawn laser "S_DEZLASER", "S_DEZLASER_TRAIL1", diff --git a/src/info.c b/src/info.c index 5409bf41a..bedf6e69e 100644 --- a/src/info.c +++ b/src/info.c @@ -563,6 +563,8 @@ char sprnames[NUMSPRITES + 1][5] = "SINK", // Kitchen Sink "SITR", // Kitchen Sink Trail "KBLN", // Battle Mode Bumper + "BEXC", // Battle Bumper Explosion: Crystal + "BEXS", // Battle Bumper Explosion: Shell "DEZL", // DEZ Laser respawn @@ -4402,9 +4404,33 @@ state_t states[NUMSTATES] = {SPR_SITR, 1, 5, {NULL}, 0, 0, S_SINKTRAIL3}, // S_SINKTRAIL2 {SPR_SITR, 2, 3, {NULL}, 0, 0, S_NULL}, // S_SINKTRAIL3 - {SPR_KBLN, FF_FULLBRIGHT, -1, {NULL}, 0, 0, S_BATTLEBUMPER1}, // S_BATTLEBUMPER1 - {SPR_KBLN, FF_FULLBRIGHT|1, -1, {NULL}, 0, 0, S_BATTLEBUMPER2}, // S_BATTLEBUMPER2 - {SPR_KBLN, FF_FULLBRIGHT|2, -1, {NULL}, 0, 0, S_BATTLEBUMPER3}, // S_BATTLEBUMPER3 + {SPR_KBLN, FF_FULLBRIGHT, -1, {NULL}, 0, 0, S_NULL}, // S_BATTLEBUMPER1 + {SPR_KBLN, FF_FULLBRIGHT|1, -1, {NULL}, 0, 0, S_NULL}, // S_BATTLEBUMPER2 + {SPR_KBLN, FF_FULLBRIGHT|2, -1, {NULL}, 0, 0, S_NULL}, // S_BATTLEBUMPER3 + + {SPR_BEXC, FF_SEMIBRIGHT, 1, {NULL}, 0, 0, S_BATTLEBUMPER_EXCRYSTALA2}, // S_BATTLEBUMPER_EXCRYSTALA1 + {SPR_BEXC, FF_FULLBRIGHT|1, 1, {NULL}, 0, 0, S_BATTLEBUMPER_EXCRYSTALA3}, // S_BATTLEBUMPER_EXCRYSTALA2 + {SPR_BEXC, FF_SEMIBRIGHT, 1, {NULL}, 0, 0, S_BATTLEBUMPER_EXCRYSTALA4}, // S_BATTLEBUMPER_EXCRYSTALA3 + {SPR_BEXC, FF_FULLBRIGHT|2, 1, {NULL}, 0, 0, S_BATTLEBUMPER_EXCRYSTALA1}, // S_BATTLEBUMPER_EXCRYSTALA4 + + {SPR_BEXC, FF_SEMIBRIGHT|3, 1, {NULL}, 0, 0, S_BATTLEBUMPER_EXCRYSTALB2}, // S_BATTLEBUMPER_EXCRYSTALB1 + {SPR_BEXC, FF_FULLBRIGHT|4, 1, {NULL}, 0, 0, S_BATTLEBUMPER_EXCRYSTALB3}, // S_BATTLEBUMPER_EXCRYSTALB2 + {SPR_BEXC, FF_SEMIBRIGHT|3, 1, {NULL}, 0, 0, S_BATTLEBUMPER_EXCRYSTALB4}, // S_BATTLEBUMPER_EXCRYSTALB3 + {SPR_BEXC, FF_FULLBRIGHT|5, 1, {NULL}, 0, 0, S_BATTLEBUMPER_EXCRYSTALB1}, // S_BATTLEBUMPER_EXCRYSTALB4 + + {SPR_BEXC, FF_SEMIBRIGHT|6, 1, {NULL}, 0, 0, S_BATTLEBUMPER_EXCRYSTALC2}, // S_BATTLEBUMPER_EXCRYSTALC1 + {SPR_BEXC, FF_FULLBRIGHT|7, 1, {NULL}, 0, 0, S_BATTLEBUMPER_EXCRYSTALC3}, // S_BATTLEBUMPER_EXCRYSTALC2 + {SPR_BEXC, FF_SEMIBRIGHT|6, 1, {NULL}, 0, 0, S_BATTLEBUMPER_EXCRYSTALC4}, // S_BATTLEBUMPER_EXCRYSTALC3 + {SPR_BEXC, FF_FULLBRIGHT|8, 1, {NULL}, 0, 0, S_BATTLEBUMPER_EXCRYSTALC1}, // S_BATTLEBUMPER_EXCRYSTALC4 + + {SPR_BEXS, FF_FULLBRIGHT, 1, {NULL}, 0, 0, S_BATTLEBUMPER_EXSHELLA2}, // S_BATTLEBUMPER_EXSHELLA1 + {SPR_BEXS, FF_FULLBRIGHT|1, 1, {NULL}, 0, 0, S_BATTLEBUMPER_EXSHELLA1}, // S_BATTLEBUMPER_EXSHELLA2 + + {SPR_BEXS, FF_FULLBRIGHT|2, 1, {NULL}, 0, 0, S_BATTLEBUMPER_EXSHELLB2}, // S_BATTLEBUMPER_EXSHELLB1 + {SPR_BEXS, FF_FULLBRIGHT|3, 1, {NULL}, 0, 0, S_BATTLEBUMPER_EXSHELLB1}, // S_BATTLEBUMPER_EXSHELLB2 + + {SPR_BEXS, FF_FULLBRIGHT|4, 1, {NULL}, 0, 0, S_BATTLEBUMPER_EXSHELLC2}, // S_BATTLEBUMPER_EXSHELLC1 + {SPR_BEXS, FF_FULLBRIGHT|5, 1, {NULL}, 0, 0, S_BATTLEBUMPER_EXSHELLC1}, // S_BATTLEBUMPER_EXSHELLC2 {SPR_DEZL, FF_FULLBRIGHT|FF_PAPERSPRITE, 8, {NULL}, 0, 0, S_NULL}, // S_DEZLASER {SPR_DEZL, FF_FULLBRIGHT|1, 2, {NULL}, 0, 0, S_DEZLASER_TRAIL2}, // S_DEZLASER_TRAIL1 @@ -24061,7 +24087,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = sfx_None, // painsound S_NULL, // meleestate S_NULL, // missilestate - S_NULL, // deathstate + S_BATTLEBUMPER_EXCRYSTALA1, // deathstate S_NULL, // xdeathstate sfx_None, // deathsound 4*FRACUNIT, // speed diff --git a/src/info.h b/src/info.h index 483706c90..84ea30757 100644 --- a/src/info.h +++ b/src/info.h @@ -834,6 +834,8 @@ typedef enum sprite SPR_SINK, // Kitchen Sink SPR_SITR, // Kitchen Sink Trail SPR_KBLN, // Battle Mode Bumper + SPR_BEXC, // Battle Bumper Explosion: Crystal + SPR_BEXS, // Battle Bumper Explosion: Shell SPR_DEZL, // DEZ Laser respawn @@ -4571,6 +4573,30 @@ typedef enum state S_BATTLEBUMPER2, S_BATTLEBUMPER3, + S_BATTLEBUMPER_EXCRYSTALA1, + S_BATTLEBUMPER_EXCRYSTALA2, + S_BATTLEBUMPER_EXCRYSTALA3, + S_BATTLEBUMPER_EXCRYSTALA4, + + S_BATTLEBUMPER_EXCRYSTALB1, + S_BATTLEBUMPER_EXCRYSTALB2, + S_BATTLEBUMPER_EXCRYSTALB3, + S_BATTLEBUMPER_EXCRYSTALB4, + + S_BATTLEBUMPER_EXCRYSTALC1, + S_BATTLEBUMPER_EXCRYSTALC2, + S_BATTLEBUMPER_EXCRYSTALC3, + S_BATTLEBUMPER_EXCRYSTALC4, + + S_BATTLEBUMPER_EXSHELLA1, + S_BATTLEBUMPER_EXSHELLA2, + + S_BATTLEBUMPER_EXSHELLB1, + S_BATTLEBUMPER_EXSHELLB2, + + S_BATTLEBUMPER_EXSHELLC1, + S_BATTLEBUMPER_EXSHELLC2, + // DEZ Laser respawn S_DEZLASER, S_DEZLASER_TRAIL1, diff --git a/src/k_kart.c b/src/k_kart.c index cf45256ac..e36845ef7 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -2679,10 +2679,6 @@ void K_DestroyBumpers(player_t *player, UINT8 amount) } player->bumpers -= amount; - - // TODO: Store a bumperlist on the player mobj, - // that way we can do a bumper destruction animation - K_HandleBumperChanges(player, oldBumpers); } diff --git a/src/p_inter.c b/src/p_inter.c index 39dfe7404..29c4cb887 100644 --- a/src/p_inter.c +++ b/src/p_inter.c @@ -1065,12 +1065,6 @@ void P_KillMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, UINT8 damaget { mobj_t *mo; - //if (inflictor && (inflictor->type == MT_SHELL || inflictor->type == MT_FIREBALL)) - // P_SetTarget(&target->tracer, inflictor); - - if (G_IsSpecialStage(gamemap) && target->player && target->player->nightstime > 6) - target->player->nightstime = 6; // Just let P_Ticker take care of the rest. - if (target->flags & (MF_ENEMY|MF_BOSS)) target->momx = target->momy = target->momz = 0; @@ -1096,7 +1090,11 @@ void P_KillMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, UINT8 damaget target->flags &= ~(MF_SHOOTABLE|MF_FLOAT|MF_SPECIAL); target->flags2 &= ~(MF2_SKULLFLY|MF2_NIGHTSPULL); target->health = 0; // This makes it easy to check if something's dead elsewhere. - target->shadowscale = 0; + + if (target->type != MT_BATTLEBUMPER) + { + target->shadowscale = 0; + } if (LUAh_MobjDeath(target, inflictor, source, damagetype) || P_MobjWasRemoved(target)) return; @@ -1219,7 +1217,7 @@ void P_KillMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, UINT8 damaget } } - if ((gametyperules & GTR_BUMPERS)) + if (gametyperules & GTR_BUMPERS) K_CheckBumpers(); target->player->kartstuff[k_pogospring] = 0; @@ -1449,6 +1447,42 @@ void P_KillMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, UINT8 damaget } break; + case MT_BATTLEBUMPER: + { + mobj_t *owner = target->target; + mobj_t *overlay; + + target->flags &= ~MF_NOGRAVITY; + + target->destscale = (3 * target->destscale) / 2; + target->scalespeed = FRACUNIT/100; + + if (owner && !P_MobjWasRemoved(owner)) + { + /* + target->momx = owner->momx / 2; + target->momy = owner->momy / 2; + target->momz = owner->momz / 2; + */ + + P_Thrust(target, R_PointToAngle2(owner->x, owner->y, target->x, target->y), 4 * target->scale); + } + + target->momz += (24 * target->scale) * P_MobjFlip(target); + + target->shadowscale *= 3; + target->fuse = 16; + + overlay = P_SpawnMobjFromMobj(target, 0, 0, 0, MT_OVERLAY); + + P_SetTarget(&target->tracer, overlay); + P_SetTarget(&overlay->target, target); + + overlay->color = target->color; + P_SetMobjState(overlay, S_BATTLEBUMPER_EXSHELLA1); + } + break; + default: break; } @@ -1685,11 +1719,12 @@ static boolean P_KillPlayer(player_t *player, mobj_t *inflictor, mobj_t *source, return false; } + K_DestroyBumpers(player, 1); + switch (type) { case DMG_DEATHPIT: // Respawn kill types - K_DestroyBumpers(player, 1); K_DoIngameRespawn(player); return false; default: diff --git a/src/p_mobj.c b/src/p_mobj.c index 090977559..3c0df40fe 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -1157,6 +1157,7 @@ fixed_t P_GetMobjGravity(mobj_t *mo) break; case MT_WATERDROP: case MT_CYBRAKDEMON: + case MT_BATTLEBUMPER: gravityadd /= 2; break; case MT_BANANA: @@ -1165,7 +1166,10 @@ fixed_t P_GetMobjGravity(mobj_t *mo) case MT_SINK: case MT_EMERALD: if (mo->extravalue2 > 0) + { gravityadd *= mo->extravalue2; + } + gravityadd = (5*gravityadd)/2; break; case MT_KARMAFIREWORK: @@ -5280,15 +5284,52 @@ static void P_MobjSceneryThink(mobj_t *mobj) case MT_BATTLEBUMPER: if (mobj->health <= 0) { - // DO EXPLODE ANIMATION HERE - //CONS_Printf("bumper explosion\n"); - P_RemoveMobj(mobj); - return; - } - else if (mobj->target && mobj->target->player && mobj->target->health > 0 && !mobj->target->player->spectator) - { - // Following a player + mobj->fuse--; + if (mobj->fuse <= 0) + { + statenum_t curState = (mobj->state - states); + + if (curState >= S_BATTLEBUMPER_EXCRYSTALA1 && curState <= S_BATTLEBUMPER_EXCRYSTALA4) + { + P_SetMobjState(mobj, S_BATTLEBUMPER_EXCRYSTALB1); + + if (mobj->tracer && !P_MobjWasRemoved(mobj->tracer)) + { + P_SetMobjState(mobj->tracer, S_BATTLEBUMPER_EXSHELLB1); + } + + mobj->shadowscale *= 3; + mobj->fuse = 24; + break; + } + else if (curState >= S_BATTLEBUMPER_EXCRYSTALB1 && curState <= S_BATTLEBUMPER_EXCRYSTALB4) + { + P_SetMobjState(mobj, S_BATTLEBUMPER_EXCRYSTALC1); + + if (mobj->tracer && !P_MobjWasRemoved(mobj->tracer)) + { + P_SetMobjState(mobj->tracer, S_BATTLEBUMPER_EXSHELLC1); + } + + mobj->shadowscale *= 3; + mobj->fuse = 32; + break; + } + else + { + // TODO: confetti goes here + P_RemoveMobj(mobj); + return; + } + } + + break; + } + + if (mobj->target && !P_MobjWasRemoved(mobj->target) && mobj->target->player + && mobj->target->health > 0 && !mobj->target->player->spectator) + { fixed_t rad = 32*mobj->target->scale; fixed_t offz; angle_t ang, diff; @@ -5320,15 +5361,23 @@ static void P_MobjSceneryThink(mobj_t *mobj) mobj->drawflags = (mobj->target->drawflags & MFD_DONTDRAW); if (mobj->target->eflags & MFE_VERTICALFLIP) + { offz += 4*FRACUNIT; + } else + { offz -= 4*FRACUNIT; + } - if (mobj->tracer && mobj->tracer->player && mobj->tracer->player->mo + if (mobj->tracer && !P_MobjWasRemoved(mobj->tracer) && mobj->tracer->player && mobj->tracer->health > 0 && !mobj->tracer->player->spectator) // STOLEN - mobj->color = mobj->tracer->player->skincolor; // don't do star flashing for stolen bumpers + { + mobj->color = mobj->tracer->color; + } else - mobj->color = mobj->target->color; // but do so if it belongs to you :B + { + mobj->color = mobj->target->color; + } if (mobj->target->player->bumpers < 2) P_SetMobjState(mobj, S_BATTLEBUMPER3); @@ -5338,11 +5387,11 @@ static void P_MobjSceneryThink(mobj_t *mobj) P_SetMobjState(mobj, S_BATTLEBUMPER1); // Shrink your items if the player shrunk too. - mobj->scale = mobj->target->scale; + P_SetScale(mobj, mobj->target->scale); P_UnsetThingPosition(mobj); { - const angle_t fa = ang>>ANGLETOFINESHIFT; + const angle_t fa = ang >> ANGLETOFINESHIFT; mobj->x = mobj->target->x + FixedMul(FINECOSINE(fa), rad); mobj->y = mobj->target->y + FixedMul(FINESINE(fa), rad); mobj->z = mobj->target->z + offz; @@ -5351,9 +5400,9 @@ static void P_MobjSceneryThink(mobj_t *mobj) if (mobj->target->player->bumpers <= mobj->threshold) { - // Sliently remove - P_RemoveMobj(mobj); - return; + // Do bumper destruction + P_KillMobj(mobj, NULL, NULL, DMG_NORMAL); + break; } } else @@ -8366,6 +8415,7 @@ static boolean P_FuseThink(mobj_t *mobj) if (mobj->threshold == 70) newmobj->threshold = 70; } + P_RemoveMobj(mobj); // make sure they disappear return false; case MT_SMK_ICEBLOCK: