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:
commit
0332c5d3de
14 changed files with 491 additions and 72 deletions
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -605,8 +605,8 @@ _(BOOMPARTICLE)
|
|||
// Land Mine
|
||||
_(LANDMINE)
|
||||
// Egg Mine
|
||||
// _(EGGMINE_CAPSULE)
|
||||
// _(EGGMINE_SHIELD)
|
||||
_(EGGMINE)
|
||||
_(EGGMINE_SHIELD)
|
||||
|
||||
_(BALLHOG) // Ballhog
|
||||
_(BALLHOGBOOM)
|
||||
|
|
|
|||
|
|
@ -2817,9 +2817,9 @@ _(LANDMINE)
|
|||
_(LANDMINE_EXPLODE)
|
||||
|
||||
// Egg mine
|
||||
// _(EGGMINE)
|
||||
// _(EGGMINE_POP)
|
||||
// _(EGGMINE_SHIELD)
|
||||
_(EGGMINE)
|
||||
_(EGGMINE_OVERLAY)
|
||||
_(EGGMINE_POP)
|
||||
|
||||
// Ballhog
|
||||
_(BALLHOG1)
|
||||
|
|
|
|||
|
|
@ -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))
|
||||
|
|
|
|||
129
src/k_collide.c
129
src/k_collide.c
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
134
src/k_items.c
134
src/k_items.c
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -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
|
||||
|
|
|
|||
93
src/k_kart.c
93
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)
|
||||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
47
src/p_map.c
47
src/p_map.c
|
|
@ -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
|
||||
|
|
|
|||
81
src/p_mobj.c
81
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)
|
||||
{
|
||||
|
|
@ -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
|
||||
|
|
|
|||
Loading…
Reference in a new issue