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) || return t->type == MT_BANANA || (t->type == MT_ORBINAUT && t->flags2 & MF2_AMBUSH) || t->type == MT_JAWZ_DUD ||
(t == MT_EGGMANITEM) || (t == MT_SSMINE_SHIELD)); 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; 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)) P_InstaThrust(t2, angle, momentum);
{ if (!t2->player)
if (!t2->momx && !t2->momy) t2->angle = angle;
if (K_BubbleReflectingTrapItem(t2))
{ {
// Stupid hack: Toss trap/dud items into the air
t2->momz += (24*t2->scale) * P_MobjFlip(t2); t2->momz += (24*t2->scale) * P_MobjFlip(t2);
} t2->z += t2->momz;
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);
}
} }
if (!isplayer) if (!t2->player)
{ {
if (t2->type == MT_JAWZ) if (t2->type == MT_JAWZ)
P_SetTarget(&t2->tracer, t2->target); // Back to the source! P_SetTarget(&t2->tracer, t2->target); // Back to the source!
P_SetTarget(&t2->target, owner); // Let the source reflect it back again! 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); S_StartSound(t1, sfx_s3k44);
} }
@ -633,7 +623,7 @@ boolean K_BubbleShieldCollide(mobj_t *t1, mobj_t *t2)
// Drain my stuff please. // Drain my stuff please.
K_BubbleShieldCollideDrain(t1->target->player, t1); 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) 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); boolean K_LandMineCollide(mobj_t *t1, mobj_t *t2);
void K_ThunderShieldAttack(mobj_t *actor, fixed_t size); 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_BubbleShieldCanReflect(mobj_t *t1, mobj_t *t2);
boolean K_BubbleShieldCollide(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; 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 // Bubble Shield reflect
if (thing->type == MT_BUBBLESHIELD && !P_MobjWasRemoved(thing->target) && thing->target->player && thing->target->player->bubbleblowup) 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) if (thing->type == MT_BUBBLESHIELD || g_tm.thing->type == MT_BUBBLESHIELD)
return BMIT_CONTINUE; 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 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) || 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->slopepitch = 0;
mobj->sloperoll = 0; mobj->sloperoll = 0;
mobj->flags &= ~(MF_NOCLIP|MF_NOCLIPTHING);
P_MoveOrigin(mobj, mobj->target->x, mobj->target->y, mobj->target->z); P_MoveOrigin(mobj, mobj->target->x, mobj->target->y, mobj->target->z);
mobj->flags |= MF_NOCLIP|MF_NOCLIPTHING;
break; break;
} }
case MT_BUBBLESHLD_DEBRIS: case MT_BUBBLESHLD_DEBRIS:
@ -9380,7 +9382,7 @@ static boolean P_MobjRegularThink(mobj_t *mobj)
if (curstate != S_INVISIBLE) if (curstate != S_INVISIBLE)
{ {
// "Despawn" and play the glass landing sound. // "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); P_SetMobjState(mobj, S_INVISIBLE);
} }
} }