diff --git a/src/d_main.cpp b/src/d_main.cpp index 5d8ef4737..a2db13c0c 100644 --- a/src/d_main.cpp +++ b/src/d_main.cpp @@ -94,7 +94,7 @@ #define ASSET_HASH_TEXTURES_KART 0xb4211b2f32b6a291 #define ASSET_HASH_CHARS_KART 0x1e68a3e01aa5c68b #define ASSET_HASH_MAPS_KART 0x38558ed00da41ce9 -#define ASSET_HASH_MAIN_PK3 0x5b698b56d8ac5717 +#define ASSET_HASH_MAIN_PK3 0xaf9562709f075a88 #define ASSET_HASH_MAPPATCH_PK3 0x0afd8afc6fc50175 #define ASSET_HASH_BONUSCHARS_KART 0x60e6f13d822a7461 #ifdef USE_PATCH_FILE diff --git a/src/k_botitem.cpp b/src/k_botitem.cpp index 21b9ca3d1..8916cc795 100644 --- a/src/k_botitem.cpp +++ b/src/k_botitem.cpp @@ -1234,7 +1234,7 @@ void K_BotItemUsage(botdata_t *bd, const player_t *player) { K_BotItemEggmanExplosion(bd, player); } - else if (player->itemflags & IF_EGGMANOUT) + else if ((!K_IsKartItemAlternate(KITEM_EGGMAN)) && (player->itemflags & IF_EGGMANOUT)) { K_BotItemEggman(bd, player); } @@ -1291,7 +1291,22 @@ void K_BotItemUsage(botdata_t *bd, const player_t *player) } break; case KITEM_EGGMAN: - K_BotItemEggmanShield(bd, player); + if (K_IsKartItemAlternate(KITEM_EGGMAN)) + { + if (!(player->itemflags & IF_ITEMOUT)) + { + K_BotItemGenericOrbitShield(bd, player); + } + else if (player->position != 1) // Hold onto orbiting items when in 1st :) + { + // about the same usage (?), maybe a dedicated usage function one day + K_BotItemMine(bd, player); + } + } + else + { + K_BotItemEggmanShield(bd, player); + } break; case KITEM_ORBINAUT: if (!(player->itemflags & IF_ITEMOUT)) diff --git a/src/k_collide.c b/src/k_collide.c index 5da5ea542..fb60b2843 100644 --- a/src/k_collide.c +++ b/src/k_collide.c @@ -296,8 +296,43 @@ boolean K_EggItemCollide(mobj_t *t1, mobj_t *t2) return true; } +void K_EggMineBounce(mobj_t *t1, mobj_t *t2) +{ + fixed_t zimpulse; + fixed_t impulse = min(max(FixedMul(R_PointToDist2(0, 0, t2->momx, t2->momy), 115*FRACUNIT/100), 15*mapobjectscale), 45*mapobjectscale); + fixed_t pointx = (t1->x + t2->x)/2; + fixed_t pointy = (t1->y + t2->y)/2; + fixed_t localspacex = t1->x - pointx; + fixed_t localspacey = t1->y - pointy; + angle_t impulseangle = R_PointToAngle2(0, 0, (localspacex + t2->momx)/2, (localspacey + t2->momy)/2); + P_InstaThrust(t1, impulseangle, impulse); + zimpulse = (P_MobjFlip(t1) * min((P_AproxDistance(t2->momx, t2->momy) + P_AproxDistance(t1->momx, t1->momy)), 28*mapobjectscale)) + t2->momz/2; + + if (t2->type == MT_EGGMINE) + { + fixed_t zdiff = (t1->z + (t1->height*P_MobjFlip(t1)/2)) - (t2->z + (t2->height*P_MobjFlip(t2))/2); + zimpulse /= 2; + if (zdiff < 0) + { + zimpulse *= -1; + } + } + // doesn't this look familiar + t1->momz = zimpulse; + t1->z += t1->momz; + + if (t1->extravalue1 == 0) + { + + K_SpawnEggMineBumpEffect(t1); + t1->extravalue1 = 6; + } +} + boolean K_EggMineCollide(mobj_t *t1, mobj_t *t2) { + boolean sprung; + if (t1->health <= 0 || t2->health <= 0) return true; @@ -319,6 +354,7 @@ boolean K_EggMineCollide(mobj_t *t1, mobj_t *t2) { if (t1->health > 2) { + K_DoEggMineStrip(t2, t1, t1->target); S_StartSound(t2, sfx_bsnipe); P_DamageMobj(t2, t1, t1->target, 1, DMG_FLIPOVER); P_RemoveMobj(t1); @@ -335,18 +371,25 @@ boolean K_EggMineCollide(mobj_t *t1, mobj_t *t2) } K_EggMineBounce(t1, t2); } + else if (t2->flags & MF_SPRING) + { + // Let thrown items hit springs! + sprung = P_DoSpring(t2, t1); + } else if (K_IsMissileOrKartItem(t2)) { - if (t2->type == MT_SPB) - { - return false; - } - else + // eggmines don't kill eachother + if (!(t2->type == MT_SPB || t2->type == MT_EGGMINE || t2->type == MT_EGGMINE_SHIELD)) { P_KillMobj(t2, t1, t1->target, DMG_INSTAKILL); } P_KillMobj(t1, t2, t2->target, DMG_INSTAKILL); } + + if (sprung) + { + return false; + } return true; } @@ -357,6 +400,7 @@ boolean K_EggMineShieldCollide(mobj_t *t1, mobj_t *t2) if (K_IsMissileOrKartItem(t2)) { + // eggmines don't kill eachother if (!(t2->type == MT_SPB || t2->type == MT_EGGMINE || t2->type == MT_EGGMINE_SHIELD)) { P_KillMobj(t2, t1, t1->target, DMG_INSTAKILL); @@ -365,7 +409,7 @@ boolean K_EggMineShieldCollide(mobj_t *t1, mobj_t *t2) return true; } - return false; + return true; } boolean K_MineCollide(mobj_t *t1, mobj_t *t2) @@ -468,6 +512,8 @@ boolean K_LandMineCollide(mobj_t *t1, mobj_t *t2) } else { + // these can only come from eggmines now + K_DoEggMineStrip(t2, t1, t1->target); // Player Damage P_DamageMobj(t2, t1, t1->target, 1, DMG_FLIPOVER); } @@ -626,8 +672,8 @@ static void K_BubbleShieldCollideDrain(player_t *player, mobj_t *bubble, INT16 d static boolean K_BubbleReflectingTrapItem(const mobj_t *t) { return t->type == MT_BANANA || (t->type == MT_ORBINAUT && t->flags2 & MF2_AMBUSH) || t->type == MT_JAWZ_DUD || - t->type == MT_EGGMANITEM || t->type == MT_SSMINE || t->type == MT_SSMINE_SHIELD || t->type == MT_LANDMINE;// || - // t->type == MT_EGGMINE_CAPSULE || t->type == MT_EGGMINE_SHIELD; + t->type == MT_EGGMANITEM || t->type == MT_SSMINE || t->type == MT_SSMINE_SHIELD || t->type == MT_LANDMINE || + t->type == MT_EGGMINE; } static boolean K_StrongPlayerBump(const player_t *player) diff --git a/src/k_collide.h b/src/k_collide.h index 8eeb20a4b..958f3f410 100644 --- a/src/k_collide.h +++ b/src/k_collide.h @@ -13,6 +13,9 @@ void K_ItemDamage(mobj_t *t1, mobj_t *t2, boolean clash); boolean K_OrbinautJawzCollide(mobj_t *t1, mobj_t *t2); boolean K_BananaBallhogCollide(mobj_t *t1, mobj_t *t2); boolean K_EggItemCollide(mobj_t *t1, mobj_t *t2); +void K_EggMineBounce(mobj_t *t1, mobj_t *t2); +boolean K_EggMineCollide(mobj_t *t1, mobj_t *t2); +boolean K_EggMineShieldCollide(mobj_t *t1, mobj_t *t2); boolean K_MineCollide(mobj_t *t1, mobj_t *t2); boolean K_MineExplosionCollide(mobj_t *t1, mobj_t *t2); boolean K_LandMineCollide(mobj_t *t1, mobj_t *t2); diff --git a/src/k_items.c b/src/k_items.c index 92aa1c370..67650e466 100644 --- a/src/k_items.c +++ b/src/k_items.c @@ -2050,7 +2050,6 @@ void K_PlayerItemThink(player_t *player, boolean onground) player->itemamount = moloop; break; } - K_EggMineSetup(mo); mo->flags |= MF_NOCLIPTHING; mo->angle = newangle; mo->movecount = player->itemamount; @@ -2071,7 +2070,6 @@ void K_PlayerItemThink(player_t *player, boolean onground) if (player->throwdir == 1) { mo = K_ThrowKartItem(player, false, MT_EGGMINE, 1, 0); - K_EggMineSetup(mo); mo->health = 3; mo->whiteshadow = true; mo->lastlook = 1; @@ -2079,7 +2077,6 @@ void K_PlayerItemThink(player_t *player, boolean onground) else { mo = K_ThrowKartItem(player, true, MT_EGGMINE, 4, 0); - K_EggMineSetup(mo); if (player->throwdir == 0) { mo->health = 2; @@ -2562,50 +2559,4 @@ void K_DoEggMineStrip(mobj_t *tmo, mobj_t *inflictor, mobj_t *source) K_SetPlayerItemCooldown(tmo->player, TICRATE, false); } } -} - -void K_EggMineSetup(mobj_t *mo) -{ - mobj_t *overlay; - - mo->movefactor = TICRATE; - mo->threshold = 6; - - overlay = P_SpawnMobj(mo->x, mo->y, mo->z, MT_OVERLAY); - overlay->target = mo; - overlay->tracer = mo; - overlay->state = S_EGGMINE_OVERLAY; - overlay->flags2 |= MF2_LINKDRAW; - overlay->dispoffset = -1; -} - -void K_EggMineBounce(mobj_t *t1, mobj_t *t2) -{ - fixed_t zimpulse; - fixed_t impulse = min(max(FixedMul(R_PointToDist2(0, 0, t2->momx, t2->momy), 115*FRACUNIT/100), 15*mapobjectscale), 45*mapobjectscale); - fixed_t pointx = (t1->x + t2->x)/2; - fixed_t pointy = (t1->y + t2->y)/2; - fixed_t localspacex = t1->x - pointx; - fixed_t localspacey = t1->y - pointy; - angle_t impulseangle = R_PointToAngle2(0, 0, (localspacex + t2->momx)/2, (localspacey + t2->momy)/2); - P_InstaThrust(t1, impulseangle, impulse); - - zimpulse = (P_MobjFlip(t1) * min((P_AproxDistance(t2->momx, t2->momy) + P_AproxDistance(t1->momx, t1->momy)), 28*mapobjectscale)) + t2->momz/2; - if (t2->type == MT_EGGMINE); - { - fixed_t zdiff = (t1->z + (t1->height*P_MobjFlip(t1)/2)) - (t2->z + (t2->height*P_MobjFlip(t2))/2); - zimpulse /= 2; - if (zdiff < 0) - { - zimpulse *= -1; - } - } - t1->momz = zimpulse; - - if (t1->extravalue1 == 0) - { - - K_SpawnEggMineBumpEffect(t1); - t1->extravalue1 = 6; - } } \ No newline at end of file diff --git a/src/k_items.h b/src/k_items.h index 28dbf1b1d..9098661a6 100644 --- a/src/k_items.h +++ b/src/k_items.h @@ -222,8 +222,6 @@ void K_AltShrinkPityIncrease(player_t *player); void K_SpawnEggMineBumpEffect(mobj_t *mo); void K_DoEggMineStrip(mobj_t *tmo, mobj_t *inflictor, mobj_t *source); -void K_EggMineSetup(mobj_t *mo); -void K_EggMineBounce(mobj_t *t1, mobj_t *t2); void K_PlayerItemThink(player_t *player, boolean onground); diff --git a/src/k_kart.c b/src/k_kart.c index 05d04ba52..21e7f3419 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -5065,6 +5065,13 @@ void K_DropHnextList(player_t *player) orbit = false; type = MT_EGGMANITEM; break; + case MT_EGGMINE_SHIELD: + orbit = false; + dropall = true; + type = MT_EGGMINE; + + work->lastlook = 0; + break; // intentionally do nothing case MT_ROCKETSNEAKER: case MT_SINK_SHIELD: diff --git a/src/p_map.c b/src/p_map.c index cd8215eb6..2a683add0 100644 --- a/src/p_map.c +++ b/src/p_map.c @@ -3813,6 +3813,11 @@ void P_BounceMove(mobj_t *mo, TryMoveResult_t *result) tmxmove = FixedMul(mmomx, (FRACUNIT - (FRACUNIT>>6) - (FRACUNIT>>5))); tmymove = FixedMul(mmomy, (FRACUNIT - (FRACUNIT>>6) - (FRACUNIT>>5))); } + else if (mo->type == MT_EGGMINE) + { + tmxmove = mmomx/3; + tmymove = mmomy/3; + } else if (mo->type == MT_THROWNGRENADE || mo->type == MT_CYBRAKDEMON_NAPALM_BOMB_LARGE) { // Quickly decay speed as it bounces diff --git a/src/p_mobj.c b/src/p_mobj.c index ca7398be8..cbdd45579 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -1656,15 +1656,6 @@ void P_XYMovement(mobj_t *mo) } } //} - else if (mo->type == MT_EGGMINE) - { - if (result.line != NULL) - { - mo->momx /= 3; - mo->momy /= 3; - K_SpawnEggMineBumpEffect(mo); - } - } else if (mo->flags & MF_MISSILE) { // explode a missile @@ -1808,6 +1799,10 @@ void P_XYMovement(mobj_t *mo) fx->eflags &= ~MFE_VERTICALFLIP; fx->scale = mo->scale; } + else if (mo->type == MT_EGGMINE) + { + K_SpawnEggMineBumpEffect(mo); + } switch (mo->type) { @@ -6538,6 +6533,7 @@ boolean P_IsKartItem(INT32 type) case MT_JAWZ_SHIELD: case MT_SSMINE_SHIELD: case MT_SINK_SHIELD: + case MT_EGGMINE_SHIELD: return true; // Primarily for minimap data, handle with care @@ -8835,11 +8831,10 @@ static boolean P_MobjRegularThink(mobj_t *mobj) { P_KillMobj(mobj, mobj, NULL, DMG_INSTAKILL); } - else - if (S_SoundPlaying(mobj, sfx_s3kd2l)) - { - S_StopSoundByID(mobj, sfx_s3kd2l); - } + } + else if (S_SoundPlaying(mobj, sfx_s3kd2l)) + { + S_StopSoundByID(mobj, sfx_s3kd2l); } if (mobj->threshold > 0) @@ -11368,6 +11363,22 @@ mobj_t *P_SpawnMobj(fixed_t x, fixed_t y, fixed_t z, mobjtype_t type) nummaprings++; break; // SRB2Kart + case MT_EGGMINE: + case MT_EGGMINE_SHIELD: + { + mobj_t *overlay = P_SpawnMobj(mobj->x, mobj->y, mobj->z, MT_OVERLAY); + P_SetMobjState(overlay, S_EGGMINE_OVERLAY); + overlay->destscale = mobj->scale; + P_SetScale(overlay, mobj->scale); + P_SetTarget(&overlay->target, mobj); + P_SetTarget(&overlay->tracer, mobj); + overlay->flags2 |= MF2_LINKDRAW; + overlay->dispoffset = -1; + + mobj->movefactor = TICRATE; + mobj->threshold = 6; + break; + } case MT_BUBBLESHIELD: { // Spawn in the damage overlay