Fixup bubble shield reflections

* Reflecting now sends the object directly away from the player, instead of
  flipping their momentum. May or may not help some awkward interactions
* Fixed collisions in general by making the bubble shield run collision
  checks after moving
* Various items now get flung into the air like they're supposed to
* Eggboxes no longer noclip through bubble shields
* Made the debris landing sound less obnoxiously loud
This commit is contained in:
GenericHeroGuy 2025-10-12 22:03:17 +02:00
parent 2db8925c28
commit 9ddeabc55b
4 changed files with 49 additions and 57 deletions

View file

@ -545,52 +545,42 @@ static void K_BubbleShieldCollideDrain(player_t *player, mobj_t *bubble)
}
}
static boolean K_BubbleReflectingTrapItem(mobjtype_t t)
static boolean K_BubbleReflectingTrapItem(const mobj_t *t)
{
return ((t == MT_BANANA) || (t == MT_JAWZ_DUD) || (t == MT_SSMINE) || (t == MT_LANDMINE) ||
(t == MT_EGGMANITEM) || (t == MT_SSMINE_SHIELD));
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;
}
boolean K_BubbleShieldReflect(mobj_t *t1, mobj_t *t2, boolean isplayer)
boolean K_BubbleShieldReflect(mobj_t *t1, mobj_t *t2)
{
mobj_t *owner = t1->player ? t1 : t1->target;
INT32 div = 2;
if (isplayer)
if (!t2->threshold || t2->player)
{
div = 1;
}
angle_t angle = R_PointToAngle2(t1->x, t1->y, t2->x, t2->y);
fixed_t momentum = max(FixedHypot(owner->momx, owner->momy), FixedHypot(t2->momx, t2->momy));
momentum = max(3*momentum/4, 16*mapobjectscale); // do SOMETHING!
if ((!t2->threshold)||(isplayer))
{
if (!t2->momx && !t2->momy)
P_InstaThrust(t2, angle, momentum);
if (!t2->player)
t2->angle = angle;
if (K_BubbleReflectingTrapItem(t2))
{
// Stupid hack: Toss trap/dud items into the air
t2->momz += (24*t2->scale) * P_MobjFlip(t2);
}
else
{
t2->momx = (-1*t2->momx)/div;
t2->momy = (-1*t2->momy)/div;
t2->momz = (-1*t2->momz)/div;
if (!isplayer)
{
t2->angle += ANGLE_180;
}
if (K_BubbleReflectingTrapItem(t2->type))
{
// Stupid hack: Toss trap/dud items into the air
t2->momz += (24*t2->scale) * P_MobjFlip(t2);
}
t2->z += t2->momz;
}
if (!isplayer)
if (!t2->player)
{
if (t2->type == MT_JAWZ)
P_SetTarget(&t2->tracer, t2->target); // Back to the source!
P_SetTarget(&t2->target, owner); // Let the source reflect it back again!
t2->threshold = 10;
if ((t2->type == MT_ORBINAUT && t2->flags2 & MF2_AMBUSH) || t2->type == MT_JAWZ_DUD)
t2->flags |= MF_NOCLIPTHING;
else
t2->threshold = 10;
}
S_StartSound(t1, sfx_s3k44);
}
@ -633,7 +623,7 @@ boolean K_BubbleShieldCollide(mobj_t *t1, mobj_t *t2)
// Drain my stuff please.
K_BubbleShieldCollideDrain(t1->target->player, t1);
}
return K_BubbleShieldReflect(t1, t2, (t2->player) ? true : false);
return K_BubbleShieldReflect(t1, t2);
}
if (t2->flags & MF_SHOOTABLE)

View file

@ -17,7 +17,7 @@ boolean K_MineExplosionCollide(mobj_t *t1, mobj_t *t2);
boolean K_LandMineCollide(mobj_t *t1, mobj_t *t2);
void K_ThunderShieldAttack(mobj_t *actor, fixed_t size);
boolean K_BubbleShieldReflect(mobj_t *t1, mobj_t *t2, boolean isplayer);
boolean K_BubbleShieldReflect(mobj_t *t1, mobj_t *t2);
boolean K_BubbleShieldCanReflect(mobj_t *t1, mobj_t *t2);
boolean K_BubbleShieldCollide(mobj_t *t1, mobj_t *t2);

View file

@ -675,30 +675,6 @@ static BlockItReturn_t PIT_CheckThing(mobj_t *thing)
return K_SMKIceBlockCollide(thing, g_tm.thing) ? BMIT_CONTINUE : BMIT_ABORT;
}
if (g_tm.thing->type == MT_EGGMANITEM || g_tm.thing->type == MT_EGGMANITEM_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_EggItemCollide(g_tm.thing, thing) ? BMIT_CONTINUE : BMIT_ABORT;
}
else if (thing->type == MT_EGGMANITEM || thing->type == MT_EGGMANITEM_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_EggItemCollide(thing, g_tm.thing) ? BMIT_CONTINUE : BMIT_ABORT;
}
if (g_tm.thing->type == MT_RANDOMITEM)
return BMIT_CONTINUE;
// Bubble Shield reflect
if (thing->type == MT_BUBBLESHIELD && !P_MobjWasRemoved(thing->target) && thing->target->player && thing->target->player->bubbleblowup)
{
@ -725,6 +701,30 @@ static BlockItReturn_t PIT_CheckThing(mobj_t *thing)
if (thing->type == MT_BUBBLESHIELD || g_tm.thing->type == MT_BUBBLESHIELD)
return BMIT_CONTINUE;
if (g_tm.thing->type == MT_EGGMANITEM || g_tm.thing->type == MT_EGGMANITEM_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_EggItemCollide(g_tm.thing, thing) ? BMIT_CONTINUE : BMIT_ABORT;
}
else if (thing->type == MT_EGGMANITEM || thing->type == MT_EGGMANITEM_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_EggItemCollide(thing, g_tm.thing) ? BMIT_CONTINUE : BMIT_ABORT;
}
if (g_tm.thing->type == MT_RANDOMITEM)
return BMIT_CONTINUE;
if (g_tm.thing->type == MT_ORBINAUT || g_tm.thing->type == MT_JAWZ || g_tm.thing->type == MT_JAWZ_DUD
|| g_tm.thing->type == MT_ORBINAUT_SHIELD || g_tm.thing->type == MT_JAWZ_SHIELD)
{

View file

@ -9356,7 +9356,9 @@ static boolean P_MobjRegularThink(mobj_t *mobj)
mobj->slopepitch = 0;
mobj->sloperoll = 0;
mobj->flags &= ~(MF_NOCLIP|MF_NOCLIPTHING);
P_MoveOrigin(mobj, mobj->target->x, mobj->target->y, mobj->target->z);
mobj->flags |= MF_NOCLIP|MF_NOCLIPTHING;
break;
}
case MT_BUBBLESHLD_DEBRIS:
@ -9380,7 +9382,7 @@ static boolean P_MobjRegularThink(mobj_t *mobj)
if (curstate != S_INVISIBLE)
{
// "Despawn" and play the glass landing sound.
S_StartSound(mobj, mobj->info->activesound);
S_StartSoundAtVolume(mobj, mobj->info->activesound, 40);
P_SetMobjState(mobj, S_INVISIBLE);
}
}