Merge pull request '[FEAT] Egg Mine (Alt. Eggman Monitor)' (#195) from eggmine into next

Reviewed-on: https://codeberg.org/NepDisk/blankart/pulls/195
This commit is contained in:
minenice55 2025-12-10 02:18:44 +01:00
commit 0332c5d3de
14 changed files with 491 additions and 72 deletions

View file

@ -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

View file

@ -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)

View file

@ -605,8 +605,8 @@ _(BOOMPARTICLE)
// Land Mine
_(LANDMINE)
// Egg Mine
// _(EGGMINE_CAPSULE)
// _(EGGMINE_SHIELD)
_(EGGMINE)
_(EGGMINE_SHIELD)
_(BALLHOG) // Ballhog
_(BALLHOGBOOM)

View file

@ -2817,9 +2817,9 @@ _(LANDMINE)
_(LANDMINE_EXPLODE)
// Egg mine
// _(EGGMINE)
// _(EGGMINE_POP)
// _(EGGMINE_SHIELD)
_(EGGMINE)
_(EGGMINE_OVERLAY)
_(EGGMINE_POP)
// Ballhog
_(BALLHOG1)

View file

@ -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))

View file

@ -296,6 +296,122 @@ 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;
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->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)
{
K_DoEggMineStrip(t2, t1, t1->target);
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);
}
else if (t2->flags & MF_SPRING)
{
// Let thrown items hit springs!
sprung = P_DoSpring(t2, t1);
}
else 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);
}
P_KillMobj(t1, t2, t2->target, DMG_INSTAKILL);
}
if (sprung)
{
return false;
}
return true;
}
boolean K_EggMineShieldCollide(mobj_t *t1, mobj_t *t2)
{
if (t1->health <= 0 || t2->health <= 0)
return true;
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);
}
P_KillMobj(t1, t2, t2->target, DMG_INSTAKILL);
return true;
}
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)))
@ -396,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);
}
@ -554,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)
@ -618,7 +736,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 +756,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;
@ -776,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)

View file

@ -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);

View file

@ -2028,24 +2028,93 @@ 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;
}
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);
mo->health = 3;
mo->whiteshadow = true;
mo->lastlook = 1;
}
else
{
mo = K_ThrowKartItem(player, true, MT_EGGMINE, 4, 0);
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 +2527,38 @@ 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->itemtype = MAXKARTITEMS; // aka KITEM_SAD
tmo->player->itemamount = 1;
tmo->player->itemblink = TICRATE;
tmo->player->itemblinkmode = KITEMBLINK_MASHED;
K_SetPlayerItemCooldown(tmo->player, TICRATE, false);
}
}
}

View file

@ -220,6 +220,9 @@ 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_PlayerItemThink(player_t *player, boolean onground);
#ifdef __cplusplus

View file

@ -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)
@ -5065,6 +5085,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:
@ -5385,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,

View file

@ -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;
landMine->destscale = mapobjectscale;
P_SetScale(landMine, 3*actor->scale/4);
landMine->angle = actor->angle;
landMine->momz = (28 * mapobjectscale * P_MobjFlip(actor));
landMine->color = player->skincolor;
}
void A_BallhogExplode(void *thing)
{
mobj_t *actor = thing;

View file

@ -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);

View file

@ -772,6 +772,48 @@ 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_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;
@ -3771,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

View file

@ -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)
{
@ -1799,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)
{
@ -6508,7 +6512,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:
@ -6529,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
@ -7398,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))
@ -8012,7 +8018,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))
{
@ -8021,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;
@ -8796,10 +8803,50 @@ 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)
{
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 +10944,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:
@ -11318,6 +11365,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