From f3e64e3c8a01b7c4986235538e66ddc08046648d Mon Sep 17 00:00:00 2001 From: minenice55 Date: Mon, 8 Dec 2025 21:32:54 -0500 Subject: [PATCH 1/9] start hardcoding this --- src/info/mobjs.h | 4 +- src/info/states.h | 6 +- src/k_collide.c | 70 +++++++++++++++++- src/k_items.c | 179 ++++++++++++++++++++++++++++++++++++++++++---- src/p_map.c | 21 ++++++ src/p_mobj.c | 60 +++++++++++++--- 6 files changed, 309 insertions(+), 31 deletions(-) diff --git a/src/info/mobjs.h b/src/info/mobjs.h index f7e5bc3ef..a45912f63 100644 --- a/src/info/mobjs.h +++ b/src/info/mobjs.h @@ -605,8 +605,8 @@ _(BOOMPARTICLE) // Land Mine _(LANDMINE) // Egg Mine -// _(EGGMINE_CAPSULE) -// _(EGGMINE_SHIELD) +_(EGGMINE) +_(EGGMINE_SHIELD) _(BALLHOG) // Ballhog _(BALLHOGBOOM) diff --git a/src/info/states.h b/src/info/states.h index e824bfce6..c58c239e9 100644 --- a/src/info/states.h +++ b/src/info/states.h @@ -2817,9 +2817,9 @@ _(LANDMINE) _(LANDMINE_EXPLODE) // Egg mine -// _(EGGMINE) -// _(EGGMINE_POP) -// _(EGGMINE_SHIELD) +_(EGGMINE) +_(EGGMINE_OVERLAY) +_(EGGMINE_POP) // Ballhog _(BALLHOG1) diff --git a/src/k_collide.c b/src/k_collide.c index d1e4c4e7f..be7bc8579 100644 --- a/src/k_collide.c +++ b/src/k_collide.c @@ -296,6 +296,72 @@ 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; + } + } + t1->momz = zimpulse; + + if (t1->extravalue1 == 0) + { + + K_SpawnEggMineBumpEffect(t1); + t1->extravalue1 = 6; + } +} + +boolean K_EggMineCollide(mobj_t *t1, mobj_t *t2) +{ + if (t1->health <= 0 || t2->health <= 0) + return true; + + if (t2->player || t2->type == MT_EGGMINE || t2->type == MT_EGGMINE_SHIELD) + { + if ((t2 == t1->target || t2->target == t1->target) && t1->threshold > 0) + { + return true; + } + + if (t2->type == MT_PLAYER && t1->health > 1) + { + if (t1->health > 2) + { + S_StartSound(t2, sfx_bsnipe); + P_DamageMobj(t2, t1, t1->target, 1, DMG_FLIPOVER); + P_RemoveMobj(t1); + return true; + } + else if (P_IsObjectOnGround(t2)) + { + S_StartSound(t2, sfx_cdfm37); + t2->momz = 3*t1->scale*P_MobjFlip(t2); + K_SpawnEggMineBumpEffect(t1); + t1->extravalue1 = 6; + return true; + } + } + K_EggMineBounce(t1, t2); + } + return true; +} + boolean K_MineCollide(mobj_t *t1, mobj_t *t2) { if (((t1->target == t2) || (!(t2->flags & (MF_ENEMY|MF_BOSS)) && (t1->target == t2->target))) && (t1->threshold > 0 || (t2->type != MT_PLAYER && t2->threshold > 0))) @@ -618,7 +684,7 @@ boolean K_BubbleShieldCanReflect(mobj_t *t) { return (t->type == MT_ORBINAUT || t->type == MT_JAWZ || t->type == MT_JAWZ_DUD || t->type == MT_BANANA || t->type == MT_EGGMANITEM || t->type == MT_BALLHOG - || t->type == MT_SSMINE || t->type == MT_LANDMINE || t->type == MT_SINK //|| t->type == MT_EGGMINE_CAPSULE + || t->type == MT_SSMINE || t->type == MT_LANDMINE || t->type == MT_SINK || t->type == MT_EGGMINE || t->type == MT_KART_LEFTOVER || t->type == MT_PLAYER); } @@ -638,7 +704,7 @@ static INT16 K_GetBubbleDamage(mobj_t* itm) { case MT_EGGMANITEM: case MT_BALLHOG: - // case MT_EGGMINE_CAPSULE: + case MT_EGGMINE: // Experiment: Let Bubble Shields hard-counter Ballhogs and Eggboxes. dmg = 0; break; diff --git a/src/k_items.c b/src/k_items.c index 69a208da6..98fd900cf 100644 --- a/src/k_items.c +++ b/src/k_items.c @@ -2028,24 +2028,96 @@ void K_PlayerItemThink(player_t *player, boolean onground) } break; case KITEM_EGGMAN: - if (ATTACK_IS_DOWN && !HOLDING_ITEM && NO_HYUDORO) + if (K_IsKartItemAlternate(KITEM_EGGMAN)) { - mobj_t *mo; - player->itemamount--; - K_SetItemOut(player, KITEM_EGGMAN, 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) + if (ATTACK_IS_DOWN && !HOLDING_ITEM && NO_HYUDORO) { - K_FlipFromObject(mo, player->mo); - mo->flags |= MF_NOCLIPTHING; - mo->threshold = 10; - mo->movecount = 1; - mo->movedir = 1; - P_SetTarget(&mo->target, player->mo); - P_SetTarget(&player->mo->hnext, mo); + angle_t newangle; + INT32 moloop; + mobj_t *mo = NULL; + mobj_t *prev = player->mo; + + //K_PlayAttackTaunt(player->mo); + K_SetItemOut(player, KITEM_EGGMAN, IF_ITEMOUT); + S_StartSound(player->mo, sfx_s3k3a); + + for (moloop = 0; moloop < player->itemamount; moloop++) + { + newangle = (player->mo->angle + ANGLE_157h) + FixedAngle(((360 / player->itemamount) * moloop) << FRACBITS) + ANGLE_90; + mo = P_SpawnMobj(player->mo->x, player->mo->y, player->mo->z, MT_EGGMINE_SHIELD); + if (!mo) + { + player->itemamount = moloop; + break; + } + K_EggMineSetup(mo); + mo->flags |= MF_NOCLIPTHING; + mo->angle = newangle; + mo->movecount = player->itemamount; + mo->movedir = mo->lastlook = moloop+1; + + P_SetTarget(&mo->target, player->mo); + P_SetTarget(&mo->hprev, prev); + P_SetTarget(&prev->hnext, mo); + prev = mo; + } + K_BotResetItemConfirm(player, false); + } + else if (ATTACK_IS_DOWN && (player->itemflags & IF_ITEMOUT)) // Egg Mine Thrown + { + mobj_t *mo; + player->itemamount -= 1; + + 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; + } + else + { + mo = K_ThrowKartItem(player, true, MT_EGGMINE, 4, 0); + K_EggMineSetup(mo); + if (player->throwdir == 0) + { + mo->health = 2; + mo->whiteshadow = true; + } + else + { + + mo->health = 1; + mo->whiteshadow = false; + } + mo->lastlook = 1; + } + K_UpdateHnextList(player, false); + K_PlayAttackTaunt(player->mo); + } + } + else + { + if (ATTACK_IS_DOWN && !HOLDING_ITEM && NO_HYUDORO) + { + mobj_t *mo; + player->itemamount--; + K_SetItemOut(player, KITEM_EGGMAN, 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) + { + K_FlipFromObject(mo, player->mo); + mo->flags |= MF_NOCLIPTHING; + mo->threshold = 10; + mo->movecount = 1; + mo->movedir = 1; + P_SetTarget(&mo->target, player->mo); + P_SetTarget(&player->mo->hnext, mo); + } + K_BotResetItemConfirm(player, false); } - K_BotResetItemConfirm(player, false); } break; case KITEM_ORBINAUT: @@ -2458,3 +2530,80 @@ void K_AltShrinkPityIncrease(player_t *player) player->growshrinktimer = ((INT16)shrinktime) * -1; } + +#undef PITY_SHRINKINCREASE_BASE +#undef PITY_SHRINKINCREASE + +void K_SpawnEggMineBumpEffect(mobj_t *mo) +{ + mobj_t *fx = P_SpawnMobj(mo->x, mo->y, mo->z, MT_BUMP); + if (mo->eflags & MFE_VERTICALFLIP) + { + fx->eflags |= MFE_VERTICALFLIP; + } + else + { + fx->eflags |= ~MFE_VERTICALFLIP; + } + fx->scale = mo->scale; + S_StartSound(mo, sfx_cdfm15); +} + +void K_DoEggMineStrip(mobj_t *tmo, mobj_t *inflictor, mobj_t *source) +{ + if (inflictor && (inflictor->type == MT_LANDMINE || inflictor->type == MT_EGGMINE)) + { + if (tmo->player) + { + S_StartSound(tmo, sfx_bewar3); + K_DropItems(tmo->player); + tmo->player->itemblink = TICRATE/2; + tmo->player->itemblinkmode = KITEMBLINK_MASHED; + K_SetPlayerItemCooldown(tmo->player, TICRATE, false); + } + } +} + +void K_EggMinePop(mobj_t *mo) +{ + mobj_t *poof; + mobj_t *landMine; + player_t *player; + + if (mo->lastlook == 0) return; + + poof = P_SpawnMobj(mo->x, mo->y, mo->z, MT_EXPLODE); + S_StartSound(poof, mo->info->deathsound); + + if (!(mo->target && mo->target->player)) return; + + player = mo->target->player; + + landMine = P_SpawnMobj(mo->x, mo->y, mo->z + mo->height/2, MT_LANDMINE); + K_FlipFromObject(landMine, mo); + landMine->threshold = 10; + landMine->target = player->mo; + + P_SetScale(landMine, 3*mo->scale/4); + landMine->destscale = mo->destscale; + + landMine->angle = mo->angle; + + landMine->momz = (28 * mapobjectscale * P_MobjFlip(mo)); + landMine->color = player->skincolor; +} + +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; +} \ No newline at end of file diff --git a/src/p_map.c b/src/p_map.c index a6fdd39cd..3a664cc80 100644 --- a/src/p_map.c +++ b/src/p_map.c @@ -772,6 +772,27 @@ static BlockItReturn_t PIT_CheckThing(mobj_t *thing) return K_EggItemCollide(thing, g_tm.thing) ? BMIT_CONTINUE : BMIT_ABORT; } + if (g_tm.thing->type == MT_EGGMINE) + { + // see if it went over / under + if (g_tm.thing->z > thing->z + thing->height) + return BMIT_CONTINUE; // overhead + if (g_tm.thing->z + g_tm.thing->height < thing->z) + return BMIT_CONTINUE; // underneath + + return K_EggMineCollide(g_tm.thing, thing) ? BMIT_CONTINUE : BMIT_ABORT; + } + else if (thing->type == MT_EGGMINE) + { + // see if it went over / under + if (g_tm.thing->z > thing->z + thing->height) + return BMIT_CONTINUE; // overhead + if (g_tm.thing->z + g_tm.thing->height < thing->z) + return BMIT_CONTINUE; // underneath + + return K_EggMineCollide(thing, g_tm.thing) ? BMIT_CONTINUE : BMIT_ABORT; + } + if (g_tm.thing->type == MT_RANDOMITEM) return BMIT_CONTINUE; diff --git a/src/p_mobj.c b/src/p_mobj.c index 3d0eaf2d0..501b9e539 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -1241,7 +1241,7 @@ fixed_t P_GetMobjGravity(mobj_t *mo) case MT_EGGMANITEM: case MT_SSMINE: case MT_LANDMINE: - // case MT_EGGMINE_CAPSULE: + case MT_EGGMINE: case MT_SINK: if (mo->extravalue2 > 0) { @@ -6508,7 +6508,7 @@ boolean P_IsKartFieldItem(INT32 type) case MT_JAWZ_DUD: case MT_SSMINE: case MT_LANDMINE: - // case MT_EGGMINE_CAPSULE: + case MT_EGGMINE: case MT_BALLHOG: case MT_BUBBLESHIELDTRAP: case MT_SINK: @@ -8012,7 +8012,7 @@ static boolean P_MobjDeadThink(mobj_t *mobj) case MT_BANANA: case MT_EGGMANITEM: case MT_LANDMINE: - // case MT_EGGMINE_CAPSULE: + case MT_EGGMINE: case MT_SPB: if (P_IsObjectOnGround(mobj)) { @@ -8796,10 +8796,52 @@ static boolean P_MobjRegularThink(mobj_t *mobj) if (mobj->threshold > 0) mobj->threshold--; break; - // case MT_EGGMINE_CAPSULE: - // todo - // decrement fuse while on ground - // when fuse runs out pop open and spawn a land mine + case MT_EGGMINE: + mobj->friction = 95*ORIG_FRICTION/100; + if (mobj->momx || mobj->momy) + { + mobj_t *ghost = P_SpawnGhostMobj(mobj); + + if (mobj->target && mobj->target->player) + { + ghost->color = mobj->target->player->skincolor; + ghost->colorized = true; + } + } + + if (P_IsObjectOnGround(mobj)) + { + if (mobj->health > 1 && mobj->threshold == 0) + { + S_StartSound(mobj, mobj->info->activesound); + mobj->health = 1; + mobj->whiteshadow = false; + } + if (!S_SoundPlaying(mobj, sfx_s3kd2l)) + { + S_StartSound(mobj, sfx_s3kd2l); + } + mobj->movefactor -= 1; + if (mobj->movefactor <= 0) + { + K_EggMinePop(mobj); + P_KillMobj(mobj, mobj, NULL, DMG_INSTAKILL); + } + else + if (S_SoundPlaying(mobj, sfx_s3kd2l)) + { + S_StopSoundByID(mobj, sfx_s3kd2l); + } + } + + if (mobj->threshold > 0) + { + mobj->threshold -= 1; + } + if (mobj->extravalue1 > 0) + { + mobj->extravalue1 -= 1; + } break; case MT_SPBEXPLOSION: mobj->health--; @@ -10897,8 +10939,8 @@ static void P_DefaultMobjShadowScale(mobj_t *thing) case MT_SSMINE: case MT_SSMINE_SHIELD: case MT_LANDMINE: - // case MT_EGGMINE_CAPSULE: - // case MT_EGGMINE_SHIELD: + case MT_EGGMINE: + case MT_EGGMINE_SHIELD: case MT_BALLHOG: case MT_SINK: case MT_ROCKETSNEAKER: From 1de19b6cebab40c00a9360113c21c0ded0a170ac Mon Sep 17 00:00:00 2001 From: minenice55 Date: Mon, 8 Dec 2025 21:39:16 -0500 Subject: [PATCH 2/9] eggmine shield --- src/k_collide.c | 37 +++++++++++++++++++++++++++++++++++++ src/p_map.c | 21 +++++++++++++++++++++ 2 files changed, 58 insertions(+) diff --git a/src/k_collide.c b/src/k_collide.c index be7bc8579..564a2677f 100644 --- a/src/k_collide.c +++ b/src/k_collide.c @@ -339,6 +339,13 @@ boolean K_EggMineCollide(mobj_t *t1, mobj_t *t2) return true; } + if (t2->player && t2->player->flamestore && (K_GetShieldFromPlayer(t2->player) == KSHIELD_FLAME)) + { + // Melt item + S_StartSound(t2, sfx_s3k43); + return true; + } + if (t2->type == MT_PLAYER && t1->health > 1) { if (t1->health > 2) @@ -359,9 +366,39 @@ boolean K_EggMineCollide(mobj_t *t1, mobj_t *t2) } K_EggMineBounce(t1, t2); } + else if (K_IsMissileOrKartItem(t2)) + { + if (t2->type == MT_SPB) + { + return false; + } + else + { + P_KillMobj(t2, t1, t1->target, DMG_INSTAKILL); + } + P_KillMobj(t1, t2, t2->target, DMG_INSTAKILL); + } return true; } +boolean K_EggMineShieldCollide(mobj_t *t1, mobj_t *t2) +{ + if (t1->health <= 0 || t2->health <= 0) + return true; + + if (K_IsMissileOrKartItem(t2)) + { + 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); + return true; + } + + return false; +} + boolean K_MineCollide(mobj_t *t1, mobj_t *t2) { if (((t1->target == t2) || (!(t2->flags & (MF_ENEMY|MF_BOSS)) && (t1->target == t2->target))) && (t1->threshold > 0 || (t2->type != MT_PLAYER && t2->threshold > 0))) diff --git a/src/p_map.c b/src/p_map.c index 3a664cc80..cd8215eb6 100644 --- a/src/p_map.c +++ b/src/p_map.c @@ -793,6 +793,27 @@ static BlockItReturn_t PIT_CheckThing(mobj_t *thing) return K_EggMineCollide(thing, g_tm.thing) ? BMIT_CONTINUE : BMIT_ABORT; } + if (g_tm.thing->type == MT_EGGMINE_SHIELD) + { + // see if it went over / under + if (g_tm.thing->z > thing->z + thing->height) + return BMIT_CONTINUE; // overhead + if (g_tm.thing->z + g_tm.thing->height < thing->z) + return BMIT_CONTINUE; // underneath + + return K_EggMineShieldCollide(g_tm.thing, thing) ? BMIT_CONTINUE : BMIT_ABORT; + } + else if (thing->type == MT_EGGMINE_SHIELD) + { + // see if it went over / under + if (g_tm.thing->z > thing->z + thing->height) + return BMIT_CONTINUE; // overhead + if (g_tm.thing->z + g_tm.thing->height < thing->z) + return BMIT_CONTINUE; // underneath + + return K_EggMineShieldCollide(thing, g_tm.thing) ? BMIT_CONTINUE : BMIT_ABORT; + } + if (g_tm.thing->type == MT_RANDOMITEM) return BMIT_CONTINUE; From 3a74330c5ad1b846115d105e648817e8b8bf5351 Mon Sep 17 00:00:00 2001 From: minenice55 Date: Mon, 8 Dec 2025 21:44:53 -0500 Subject: [PATCH 3/9] wall bounce --- src/k_collide.c | 31 ------------------------------- src/k_items.c | 31 +++++++++++++++++++++++++++++++ src/k_items.h | 6 ++++++ src/p_mobj.c | 9 +++++++++ 4 files changed, 46 insertions(+), 31 deletions(-) diff --git a/src/k_collide.c b/src/k_collide.c index 564a2677f..5da5ea542 100644 --- a/src/k_collide.c +++ b/src/k_collide.c @@ -296,37 +296,6 @@ 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; - } - } - t1->momz = zimpulse; - - if (t1->extravalue1 == 0) - { - - K_SpawnEggMineBumpEffect(t1); - t1->extravalue1 = 6; - } -} - boolean K_EggMineCollide(mobj_t *t1, mobj_t *t2) { if (t1->health <= 0 || t2->health <= 0) diff --git a/src/k_items.c b/src/k_items.c index 98fd900cf..f37e8c06e 100644 --- a/src/k_items.c +++ b/src/k_items.c @@ -2606,4 +2606,35 @@ void K_EggMineSetup(mobj_t *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 511cf1054..c900e6429 100644 --- a/src/k_items.h +++ b/src/k_items.h @@ -220,6 +220,12 @@ INT16 K_GetShrinkTime(const player_t *player); boolean K_IsAltShrunk(const player_t *player); 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_EggMinePop(mobj_t *mo); +void K_EggMineSetup(mobj_t *mo); +void K_EggMineBounce(mobj_t *t1, mobj_t *t2); + void K_PlayerItemThink(player_t *player, boolean onground); #ifdef __cplusplus diff --git a/src/p_mobj.c b/src/p_mobj.c index 501b9e539..c8f725cb1 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -1656,6 +1656,15 @@ 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 From 82f459927574cdc663a6e6709f8464a7ea4eb9ff Mon Sep 17 00:00:00 2001 From: minenice55 Date: Mon, 8 Dec 2025 22:09:16 -0500 Subject: [PATCH 4/9] make eggmine pop an action like the lua --- src/info/actions.h | 1 + src/k_items.c | 29 ----------------------------- src/k_items.h | 1 - src/p_enemy.c | 33 +++++++++++++++++++++++++++++++++ src/p_mobj.c | 1 - 5 files changed, 34 insertions(+), 31 deletions(-) diff --git a/src/info/actions.h b/src/info/actions.h index f32aa3438..55aab4bbd 100644 --- a/src/info/actions.h +++ b/src/info/actions.h @@ -213,6 +213,7 @@ _(A_SSMineExplode, SSMINEEXPLODE) _(A_SSMineSearch, GRENADERING) _(A_SSMineExplode, MINEEXPLODE) _(A_LandMineExplode, LANDMINEEXPLODE) +_(A_EggMinePop, EGGMINEPOP) _(A_BallhogExplode, BALLHOGEXPLODE) _(A_LightningFollowPlayer, LIGHTNINGFOLLOWPLAYER) _(A_FZBoomFlash, FZBOOMFLASH) diff --git a/src/k_items.c b/src/k_items.c index f37e8c06e..92aa1c370 100644 --- a/src/k_items.c +++ b/src/k_items.c @@ -2564,35 +2564,6 @@ void K_DoEggMineStrip(mobj_t *tmo, mobj_t *inflictor, mobj_t *source) } } -void K_EggMinePop(mobj_t *mo) -{ - mobj_t *poof; - mobj_t *landMine; - player_t *player; - - if (mo->lastlook == 0) return; - - poof = P_SpawnMobj(mo->x, mo->y, mo->z, MT_EXPLODE); - S_StartSound(poof, mo->info->deathsound); - - if (!(mo->target && mo->target->player)) return; - - player = mo->target->player; - - landMine = P_SpawnMobj(mo->x, mo->y, mo->z + mo->height/2, MT_LANDMINE); - K_FlipFromObject(landMine, mo); - landMine->threshold = 10; - landMine->target = player->mo; - - P_SetScale(landMine, 3*mo->scale/4); - landMine->destscale = mo->destscale; - - landMine->angle = mo->angle; - - landMine->momz = (28 * mapobjectscale * P_MobjFlip(mo)); - landMine->color = player->skincolor; -} - void K_EggMineSetup(mobj_t *mo) { mobj_t *overlay; diff --git a/src/k_items.h b/src/k_items.h index c900e6429..28dbf1b1d 100644 --- a/src/k_items.h +++ b/src/k_items.h @@ -222,7 +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_EggMinePop(mobj_t *mo); void K_EggMineSetup(mobj_t *mo); void K_EggMineBounce(mobj_t *t1, mobj_t *t2); diff --git a/src/p_enemy.c b/src/p_enemy.c index 4c37a2d1f..ecb416e84 100644 --- a/src/p_enemy.c +++ b/src/p_enemy.c @@ -11472,6 +11472,39 @@ void A_LandMineExplode(void *thing) } } +void A_EggMinePop(void *thing) +{ + mobj_t *actor = thing; + mobj_t *poof; + mobj_t *landMine; + player_t *player; + + if (LUA_CallAction(A_EGGMINEPOP, actor)) + return; + + if (actor->lastlook == 0) return; + + poof = P_SpawnMobj(actor->x, actor->y, actor->z, MT_EXPLODE); + S_StartSound(poof, actor->info->deathsound); + + if (!(actor->target && actor->target->player)) return; + + player = actor->target->player; + + landMine = P_SpawnMobj(actor->x, actor->y, actor->z + actor->height/2, MT_LANDMINE); + K_FlipFromObject(landMine, actor); + landMine->threshold = 10; + landMine->target = player->mo; + + P_SetScale(landMine, 3*actor->scale/4); + landMine->destscale = actor->destscale; + + landMine->angle = actor->angle; + + landMine->momz = (28 * mapobjectscale * P_MobjFlip(actor)); + landMine->color = player->skincolor; +} + void A_BallhogExplode(void *thing) { mobj_t *actor = thing; diff --git a/src/p_mobj.c b/src/p_mobj.c index c8f725cb1..ca7398be8 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -8833,7 +8833,6 @@ static boolean P_MobjRegularThink(mobj_t *mobj) mobj->movefactor -= 1; if (mobj->movefactor <= 0) { - K_EggMinePop(mobj); P_KillMobj(mobj, mobj, NULL, DMG_INSTAKILL); } else From 4fd6e4987c7732cc1e2b56f21e3ee49dd5b75e63 Mon Sep 17 00:00:00 2001 From: minenice55 Date: Mon, 8 Dec 2025 22:11:16 -0500 Subject: [PATCH 5/9] hash --- src/d_main.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/d_main.cpp b/src/d_main.cpp index d067fe673..5d8ef4737 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 0xf1d3865cfcb63317 +#define ASSET_HASH_MAIN_PK3 0x5b698b56d8ac5717 #define ASSET_HASH_MAPPATCH_PK3 0x0afd8afc6fc50175 #define ASSET_HASH_BONUSCHARS_KART 0x60e6f13d822a7461 #ifdef USE_PATCH_FILE From 6eb1a6688a05b351d0a9a179b20578adfdd76833 Mon Sep 17 00:00:00 2001 From: minenice55 Date: Tue, 9 Dec 2025 00:38:57 -0500 Subject: [PATCH 6/9] get everything working exactly like the prototype --- src/d_main.cpp | 2 +- src/k_botitem.cpp | 19 +++++++++++++-- src/k_collide.c | 62 +++++++++++++++++++++++++++++++++++++++++------ src/k_collide.h | 3 +++ src/k_items.c | 49 ------------------------------------- src/k_items.h | 2 -- src/k_kart.c | 7 ++++++ src/p_map.c | 5 ++++ src/p_mobj.c | 39 ++++++++++++++++++----------- 9 files changed, 112 insertions(+), 76 deletions(-) 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 From 1f104c7ef553a9668ff0c0a312e7290c4f908dc3 Mon Sep 17 00:00:00 2001 From: minenice55 Date: Tue, 9 Dec 2025 15:39:57 -0500 Subject: [PATCH 7/9] create eggmine missiles closer to the player final misc tweaks too, ready for PR --- src/d_main.cpp | 2 +- src/k_collide.c | 3 +- src/k_kart.c | 84 ++++++++++++++++++++++++++++++------------------- src/p_enemy.c | 2 +- src/p_inter.c | 8 +++-- src/p_mobj.c | 2 ++ 6 files changed, 64 insertions(+), 37 deletions(-) diff --git a/src/d_main.cpp b/src/d_main.cpp index 75bfe8216..7d8b07fca 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 0xfea5cf465c3a62d1 +#define ASSET_HASH_MAIN_PK3 0x82f7ac8f6266e9e3 #define ASSET_HASH_MAPPATCH_PK3 0x5928d3af98c18214 #define ASSET_HASH_BONUSCHARS_KART 0x60e6f13d822a7461 #ifdef USE_PATCH_FILE diff --git a/src/k_collide.c b/src/k_collide.c index fb60b2843..a0fcf0ee5 100644 --- a/src/k_collide.c +++ b/src/k_collide.c @@ -894,7 +894,8 @@ boolean K_SMKIceBlockCollide(mobj_t *t1, mobj_t *t2) if (t2->type == MT_BANANA || t2->type == MT_BANANA_SHIELD || t2->type == MT_EGGMANITEM || t2->type == MT_EGGMANITEM_SHIELD || t2->type == MT_SSMINE || t2->type == MT_SSMINE_SHIELD - || t2->type == MT_ORBINAUT_SHIELD || t2->type == MT_JAWZ_SHIELD) + || t2->type == MT_ORBINAUT_SHIELD || t2->type == MT_JAWZ_SHIELD + || t2->type == MT_EGGMINE_SHIELD) return false; if (t1->health) diff --git a/src/k_kart.c b/src/k_kart.c index 21e7f3419..7098bd58e 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -3828,9 +3828,10 @@ void K_SpawnMineExplosion(mobj_t *source, UINT8 color) static mobj_t *K_SpawnKartMissile(mobj_t *source, mobjtype_t type, angle_t an, INT32 flags2, fixed_t speed) { - mobj_t *th; + mobj_t *missile; fixed_t x, y, z; fixed_t finalspeed = speed; + fixed_t spawndist; mobj_t *throwmo; if (source->player && source->player->speed > K_GetKartSpeed(source->player, false, false)) @@ -3855,82 +3856,101 @@ static mobj_t *K_SpawnKartMissile(mobj_t *source, mobjtype_t type, angle_t an, I z = source->z+source->height - mobjinfo[type].height; } - th = P_SpawnMobj(x, y, z, type); + missile = P_SpawnMobj(x, y, z, type); - th->flags2 |= flags2; + missile->flags2 |= flags2; if (source->flags2 & MF2_WATERRUN) { // Allow certain items to run on water as well! - if (K_ItemMobjAllowedtoWaterRun(th)) + if (K_ItemMobjAllowedtoWaterRun(missile)) { - th->flags2 |= MF2_WATERRUN; + missile->flags2 |= MF2_WATERRUN; } } - th->threshold = 10; + missile->threshold = 10; - if (th->info->seesound) - S_StartSound(source, th->info->seesound); + if (missile->info->seesound) + S_StartSound(source, missile->info->seesound); - P_SetTarget(&th->target, source); + P_SetTarget(&missile->target, source); - if (P_IsObjectOnGround(source)) + if ((type != MT_EGGMINE) && P_IsObjectOnGround(source)) { // floorz and ceilingz aren't properly set to account for FOFs and Polyobjects on spawn // This should set it for FOFs - P_SetOrigin(th, th->x, th->y, th->z); + P_SetOrigin(missile, missile->x, missile->y, missile->z); // spawn on the ground if the player is on the ground if (P_MobjFlip(source) < 0) { - th->z = th->ceilingz - th->height; - th->eflags |= MFE_VERTICALFLIP; + missile->z = missile->ceilingz - missile->height; + missile->eflags |= MFE_VERTICALFLIP; } else - th->z = th->floorz; + missile->z = missile->floorz; } - th->angle = an; + missile->angle = an; - th->momx = FixedMul(finalspeed, FINECOSINE(an>>ANGLETOFINESHIFT)); - th->momy = FixedMul(finalspeed, FINESINE(an>>ANGLETOFINESHIFT)); + missile->momx = FixedMul(finalspeed, FINECOSINE(an>>ANGLETOFINESHIFT)); + missile->momy = FixedMul(finalspeed, FINESINE(an>>ANGLETOFINESHIFT)); switch (type) { case MT_ORBINAUT: if (source && source->player) - th->color = source->player->skincolor; + missile->color = source->player->skincolor; else - th->color = SKINCOLOR_GREY; - th->movefactor = finalspeed; + missile->color = SKINCOLOR_GREY; + missile->movefactor = finalspeed; break; case MT_JAWZ: if (source && source->player) { INT32 lasttarg = source->player->lastjawztarget; - th->cvmem = source->player->skincolor; + missile->cvmem = source->player->skincolor; if ((lasttarg >= 0 && lasttarg < MAXPLAYERS) && playeringame[lasttarg] && !players[lasttarg].spectator && players[lasttarg].mo) { - P_SetTarget(&th->tracer, players[lasttarg].mo); + P_SetTarget(&missile->tracer, players[lasttarg].mo); } } else - th->cvmem = SKINCOLOR_KETCHUP; + missile->cvmem = SKINCOLOR_KETCHUP; /* FALLTHRU */ case MT_JAWZ_DUD: - S_StartSound(th, th->info->activesound); + S_StartSound(missile, missile->info->activesound); /* FALLTHRU */ case MT_SPB: - th->movefactor = finalspeed; + missile->movefactor = finalspeed; break; case MT_BUBBLESHIELDTRAP: - P_SetScale(th, ((5*th->destscale)>>2)*4); - th->destscale = (5*th->destscale)>>2; - S_StartSound(th, sfx_s3kbfl); - S_StartSound(th, sfx_cdfm35); + P_SetScale(missile, ((5*missile->destscale)>>2)*4); + missile->destscale = (5*missile->destscale)>>2; + S_StartSound(missile, sfx_s3kbfl); + S_StartSound(missile, sfx_cdfm35); + break; + case MT_EGGMINE: + // eggmines should spawn closer to the source + P_SetOrigin(missile, + source->x + FixedMul(source->radius + mobjinfo[type].radius, FINECOSINE(an>>ANGLETOFINESHIFT)), + source->y + FixedMul(source->radius + mobjinfo[type].radius, FINESINE(an>>ANGLETOFINESHIFT)), + missile->z + ); + // spawn on the ground if the player is on the ground + if (P_IsObjectOnGround(source)) + { + if (P_MobjFlip(source) < 0) + { + missile->z = missile->ceilingz - missile->height; + missile->eflags |= MFE_VERTICALFLIP; + } + else + missile->z = missile->floorz; + } break; default: break; @@ -3938,15 +3958,15 @@ static mobj_t *K_SpawnKartMissile(mobj_t *source, mobjtype_t type, angle_t an, I if (type != MT_BUBBLESHIELDTRAP) { - x = x + P_ReturnThrustX(source, an, source->radius + th->radius); - y = y + P_ReturnThrustY(source, an, source->radius + th->radius); + x = x + P_ReturnThrustX(source, an, source->radius + missile->radius); + y = y + P_ReturnThrustY(source, an, source->radius + missile->radius); throwmo = P_SpawnMobj(x, y, z, MT_FIREDITEM); throwmo->movecount = 1; throwmo->movedir = source->angle - an; P_SetTarget(&throwmo->target, source); } - return th; + return missile; } UINT16 K_DriftSparkColor(player_t *player, INT32 charge) diff --git a/src/p_enemy.c b/src/p_enemy.c index ecb416e84..37d3d5ceb 100644 --- a/src/p_enemy.c +++ b/src/p_enemy.c @@ -11496,8 +11496,8 @@ void A_EggMinePop(void *thing) landMine->threshold = 10; landMine->target = player->mo; + landMine->destscale = mapobjectscale; P_SetScale(landMine, 3*actor->scale/4); - landMine->destscale = actor->destscale; landMine->angle = actor->angle; diff --git a/src/p_inter.c b/src/p_inter.c index 5b25a2d34..f4e492c5a 100644 --- a/src/p_inter.c +++ b/src/p_inter.c @@ -1432,7 +1432,8 @@ void P_KillMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, UINT8 damaget target->target->player->itemamount--; } else if ((target->type == MT_ORBINAUT_SHIELD && target->target->player->itemtype == KITEM_ORBINAUT) // orbit items - || (target->type == MT_JAWZ_SHIELD && target->target->player->itemtype == KITEM_JAWZ)) + || (target->type == MT_JAWZ_SHIELD && target->target->player->itemtype == KITEM_JAWZ) + || (target->type == MT_EGGMINE_SHIELD && target->target->player->itemtype == KITEM_EGGMAN && K_IsKartItemAlternate(KITEM_EGGMAN))) { if (target->target->player->itemamount) target->target->player->itemamount--; @@ -1443,7 +1444,10 @@ void P_KillMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, UINT8 damaget } if (!target->target->player->itemamount) - target->target->player->itemflags &= ~IF_ITEMOUT; + { + K_UnsetItemOut(target->target->player); + // target->target->player->itemflags &= ~IF_ITEMOUT; + } if (target->target->hnext == target) P_SetTarget(&target->target->hnext, NULL); diff --git a/src/p_mobj.c b/src/p_mobj.c index cbdd45579..9561f6ea8 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -7403,6 +7403,7 @@ static void P_MobjSceneryThink(mobj_t *mobj) case MT_BANANA_SHIELD: case MT_SSMINE_SHIELD: case MT_EGGMANITEM_SHIELD: + case MT_EGGMINE_SHIELD: case MT_SINK_SHIELD: if ((mobj->health > 0 && (!mobj->target || !mobj->target->player || mobj->target->health <= 0 || mobj->target->player->spectator)) @@ -8026,6 +8027,7 @@ static boolean P_MobjDeadThink(mobj_t *mobj) } /* FALLTHRU */ case MT_ORBINAUT_SHIELD: + case MT_EGGMINE_SHIELD: case MT_BANANA_SHIELD: case MT_EGGMANITEM_SHIELD: mobj->renderflags ^= RF_DONTDRAW; From 7df2d13c855abc6feb26b29f6a307a06501d671d Mon Sep 17 00:00:00 2001 From: minenice55 Date: Tue, 9 Dec 2025 17:15:59 -0500 Subject: [PATCH 8/9] let's be funny, flipped by egg mine gives victim one Sad --- src/k_items.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/k_items.c b/src/k_items.c index 67650e466..6f1155148 100644 --- a/src/k_items.c +++ b/src/k_items.c @@ -2554,7 +2554,9 @@ void K_DoEggMineStrip(mobj_t *tmo, mobj_t *inflictor, mobj_t *source) { S_StartSound(tmo, sfx_bewar3); K_DropItems(tmo->player); - tmo->player->itemblink = TICRATE/2; + tmo->player->itemtype = MAXKARTITEMS; // aka KITEM_SAD + tmo->player->itemamount = 1; + tmo->player->itemblink = TICRATE; tmo->player->itemblinkmode = KITEMBLINK_MASHED; K_SetPlayerItemCooldown(tmo->player, TICRATE, false); } From 28e88e8db1064ccd85514ffdf9c2ab3b11edc529 Mon Sep 17 00:00:00 2001 From: minenice55 Date: Tue, 9 Dec 2025 17:19:21 -0500 Subject: [PATCH 9/9] don't drop the Sad item when stripping --- src/k_kart.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/k_kart.c b/src/k_kart.c index 7098bd58e..f64a75c4e 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -5412,7 +5412,7 @@ void K_DropItems(player_t *player) { K_DropHnextList(player); - if (player->mo && !P_MobjWasRemoved(player->mo) && player->itemamount > 0) + if (player->mo && !P_MobjWasRemoved(player->mo) && player->itemamount > 0 && player->itemtype != MAXKARTITEMS) // don't drop KITEM_SAD { mobj_t *drop = K_CreatePaperItem( player->mo->x, player->mo->y, player->mo->z + player->mo->height/2,