Dapple up
Add all the bubble shield VFX
This commit is contained in:
parent
641f6ae865
commit
a2d83f4b5f
9 changed files with 255 additions and 10 deletions
|
|
@ -103,7 +103,7 @@ extern "C" {
|
|||
|
||||
// Special Hashing.
|
||||
//#define NOFILEHASH
|
||||
//#define NOVERIFYIWADS
|
||||
#define NOVERIFYIWADS
|
||||
|
||||
// Uncheck this to compile debugging code
|
||||
//#define RANGECHECK
|
||||
|
|
|
|||
|
|
@ -612,6 +612,7 @@ _(THUNDERSHIELD) // Shields
|
|||
_(BUBBLESHIELD)
|
||||
_(FLAMESHIELD)
|
||||
_(BUBBLESHIELDTRAP)
|
||||
_(BUBBLESHLD_DEBRIS)
|
||||
|
||||
_(SINK) // Kitchen Sink Stuff
|
||||
_(SINK_SHIELD)
|
||||
|
|
|
|||
|
|
@ -445,6 +445,8 @@ _(BHBM) // Ballhog BOOM
|
|||
_(SPBM) // Self-Propelled Bomb
|
||||
_(THNS) // Thunder Shield
|
||||
_(BUBS) // Bubble Shield (not Bubs)
|
||||
_(BUBC) // Bubble Shield damage
|
||||
_(BSDB) // Bubble Shield shatter debris
|
||||
_(BWVE) // Bubble Shield waves
|
||||
_(FLMS) // Flame Shield
|
||||
_(FLMD) // Flame Shield dash
|
||||
|
|
|
|||
|
|
@ -2888,7 +2888,7 @@ _(THUNDERSHIELD22)
|
|||
_(THUNDERSHIELD23)
|
||||
_(THUNDERSHIELD24)
|
||||
|
||||
// Bubble Shield
|
||||
// Bubble Shield: Standard Sprites
|
||||
_(BUBBLESHIELD1)
|
||||
_(BUBBLESHIELD2)
|
||||
_(BUBBLESHIELD3)
|
||||
|
|
@ -2917,6 +2917,17 @@ _(BUBBLESHIELDTRAP6)
|
|||
_(BUBBLESHIELDTRAP7)
|
||||
_(BUBBLESHIELDTRAP8)
|
||||
|
||||
// Bubble Shield: Damage Visuals
|
||||
_(BUBLSHLD_DMG_1)
|
||||
_(BUBLSHLD_DMG_2)
|
||||
_(BUBLSHLD_DMG_3)
|
||||
_(BUBLSHLD_DMG_4)
|
||||
_(BUBBLEDEBRIS_1)
|
||||
_(BUBBLEDEBRIS_2)
|
||||
_(BUBBLEDEBRIS_3)
|
||||
_(BUBBLEDEBRIS_4)
|
||||
_(BUBBLEDEBRIS_5)
|
||||
|
||||
// Flame Shield
|
||||
_(FLAMESHIELD1)
|
||||
_(FLAMESHIELD2)
|
||||
|
|
|
|||
|
|
@ -545,6 +545,12 @@ static void K_BubbleShieldCollideDrain(player_t *player, mobj_t *bubble)
|
|||
}
|
||||
}
|
||||
|
||||
static boolean K_BubbleReflectingTrapItem(mobjtype_t t)
|
||||
{
|
||||
return ((t == MT_BANANA) || (t == MT_JAWZ_DUD) || (t == MT_SSMINE) || (t == MT_LANDMINE) ||
|
||||
(t == MT_EGGMANITEM) || (t == MT_SSMINE_SHIELD));
|
||||
}
|
||||
|
||||
boolean K_BubbleShieldReflect(mobj_t *t1, mobj_t *t2, boolean isplayer)
|
||||
{
|
||||
mobj_t *owner = t1->player ? t1 : t1->target;
|
||||
|
|
@ -571,6 +577,12 @@ boolean K_BubbleShieldReflect(mobj_t *t1, mobj_t *t2, boolean 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)
|
||||
|
|
|
|||
71
src/k_kart.c
71
src/k_kart.c
|
|
@ -5227,12 +5227,76 @@ void K_DropHnextList(player_t *player)
|
|||
}
|
||||
}
|
||||
|
||||
// Bubble shield break SFX and VFX (maybe, hopefully)
|
||||
static void K_BreakBubbleShield(player_t *player)
|
||||
#define MAXSHARDCOUNT 40
|
||||
#define SHARDROT (360 * FRACUNIT / 40)
|
||||
static void K_BreakBubbleShield(player_t* player)
|
||||
{
|
||||
if (!player->mo->shieldtracer)
|
||||
{
|
||||
// No shield tracer, assume there's no bubble shield.
|
||||
return;
|
||||
}
|
||||
|
||||
// TODO: Some more dramatic SFX and VFX (DSS3K59, bubble shield shards fly all over)
|
||||
S_StartSound(player->mo, sfx_s3k4b);
|
||||
mobj_t* shard;
|
||||
|
||||
fixed_t move_magnitude, shieldrad, shieldscale, scalediff;
|
||||
vector2_t mul_vec;
|
||||
vector3_t mom;
|
||||
fixed_t randang, randzang;
|
||||
INT32 flip = P_MobjFlip(player->mo);
|
||||
|
||||
shieldscale = player->mo->shieldtracer->scale;
|
||||
|
||||
scalediff = shieldscale - mapobjectscale;
|
||||
shieldrad = FixedMul(player->mo->shieldtracer->radius, shieldscale);
|
||||
|
||||
mul_vec.x = FRACUNIT;
|
||||
mul_vec.y = 0;
|
||||
|
||||
INT32 i;
|
||||
for (i = 0; i < MAXSHARDCOUNT; i++)
|
||||
{
|
||||
mul_vec.x = FRACUNIT;
|
||||
mul_vec.y = 0;
|
||||
|
||||
randang = (SHARDROT * (i + 1));
|
||||
randzang = (P_RandomRange(23, 157) * FRACUNIT);
|
||||
move_magnitude =
|
||||
FixedMul((P_RandomRange(4, 16) * FRACUNIT), mapobjectscale + (scalediff / 4));
|
||||
|
||||
FV2_Rotate(&mul_vec, randzang);
|
||||
|
||||
// Do shitty initial 3D rotations around the shield's radius.
|
||||
shard = P_SpawnMobj(
|
||||
player->mo->shieldtracer->x +
|
||||
FixedMul(FixedMul(mul_vec.x, shieldrad), FCOS(FixedAngle(randang))),
|
||||
player->mo->shieldtracer->y +
|
||||
FixedMul(FixedMul(mul_vec.x, shieldrad), FSIN(FixedAngle(randang))),
|
||||
player->mo->shieldtracer->z + FixedMul(mul_vec.y * flip, shieldrad),
|
||||
MT_BUBBLESHLD_DEBRIS);
|
||||
|
||||
if (shard)
|
||||
{
|
||||
//CONS_Printf(M_GetText("randzang: %d, randang: %d\n"), randzang / FRACUNIT, randang / FRACUNIT);
|
||||
|
||||
mul_vec.x = FixedMul(move_magnitude, mul_vec.x);
|
||||
mul_vec.y = FixedMul(move_magnitude, mul_vec.y * flip);
|
||||
|
||||
mom.x = FixedMul(mul_vec.x, FCOS(FixedAngle(randang)));
|
||||
mom.y = FixedMul(mul_vec.x, FSIN(FixedAngle(randang)));
|
||||
mom.z = mul_vec.y;
|
||||
|
||||
shard->momx = mom.x + player->mo->momx;
|
||||
shard->momy = mom.y + player->mo->momy;
|
||||
shard->momz = mom.z + player->mo->momz;
|
||||
}
|
||||
}
|
||||
|
||||
S_StartSound(player->mo, sfx_kc41);
|
||||
}
|
||||
#undef MAXSHARDCOUNT
|
||||
#undef SHARDROT
|
||||
|
||||
// For getting hit!
|
||||
void K_PopPlayerShield(player_t *player)
|
||||
|
|
@ -10583,6 +10647,7 @@ void K_MoveKartPlayer(player_t *player, boolean onground)
|
|||
mobj_t *shield = P_SpawnMobj(player->mo->x, player->mo->y, player->mo->z, MT_BUBBLESHIELD);
|
||||
P_SetScale(shield, (shield->destscale = (5*shield->destscale)>>2));
|
||||
P_SetTarget(&shield->target, player->mo);
|
||||
P_SetTarget(&player->mo->shieldtracer, shield);
|
||||
S_StartSound(player->mo, sfx_s3k3f);
|
||||
player->curshield = KSHIELD_BUBBLE;
|
||||
|
||||
|
|
|
|||
146
src/p_mobj.c
146
src/p_mobj.c
|
|
@ -68,6 +68,18 @@ mobj_t *boss3cap = NULL;
|
|||
|
||||
mobj_t *mobjcache = NULL;
|
||||
|
||||
// Bubble Shield overlay spritescales.
|
||||
static fixed_t bubbleoverlayscales[4][2] = {
|
||||
// All scales are raw 16.16 fixed-point numbers based on FRACUNIT.
|
||||
{65536, 65536}, // 1.0, 1.0
|
||||
{65536, 59667}, // 1.0, 0.9104477
|
||||
{90593, 61623}, // 1.382352, 0.940298
|
||||
{100231, 53798} // 1.529411, 0.820895
|
||||
};
|
||||
static statenum_t bubbledamagestates[5] = { S_INVISIBLE, S_BUBLSHLD_DMG_1, S_BUBLSHLD_DMG_2, S_BUBLSHLD_DMG_3, S_BUBLSHLD_DMG_4 };
|
||||
|
||||
|
||||
|
||||
void P_InitCachedActions(void)
|
||||
{
|
||||
actioncachehead.prev = actioncachehead.next = &actioncachehead;
|
||||
|
|
@ -9159,11 +9171,27 @@ static boolean P_MobjRegularThink(mobj_t *mobj)
|
|||
case MT_BUBBLESHIELD:
|
||||
{
|
||||
fixed_t scale;
|
||||
statenum_t curstate;
|
||||
statenum_t curstate, overlaystate;
|
||||
|
||||
if (!mobj->target || !mobj->target->health || !mobj->target->player
|
||||
|| mobj->target->player->curshield != KSHIELD_BUBBLE)
|
||||
{
|
||||
if ((mobj->target->shieldtracer) && (mobj->target->shieldtracer->mobjnum == mobj->mobjnum))
|
||||
{
|
||||
// We're being traced by this object; unset its shieldtracer.
|
||||
P_SetTarget(&mobj->target->shieldtracer, NULL);
|
||||
}
|
||||
if (mobj->tracer && (!mobj->tracer->player))
|
||||
{
|
||||
// Remove the tracer (overlay)
|
||||
if (!P_MobjWasRemoved(mobj->tracer))
|
||||
{
|
||||
P_RemoveMobj(mobj->tracer);
|
||||
}
|
||||
|
||||
P_SetTarget(&mobj->tracer, NULL);
|
||||
}
|
||||
|
||||
P_RemoveMobj(mobj);
|
||||
return false;
|
||||
}
|
||||
|
|
@ -9171,6 +9199,11 @@ static boolean P_MobjRegularThink(mobj_t *mobj)
|
|||
scale = (5*mobj->target->scale)>>2;
|
||||
curstate = ((mobj->tics == 1) ? (mobj->state->nextstate) : ((statenum_t)(mobj->state-states)));
|
||||
|
||||
// Lookup for rescaling the "bubble damage" overlay
|
||||
UINT8 frame, scale_idx;
|
||||
|
||||
frame = scale_idx = 0;
|
||||
|
||||
if (mobj->target->player->bubbleblowup)
|
||||
{
|
||||
INT32 blow = mobj->target->player->bubbleblowup;
|
||||
|
|
@ -9185,6 +9218,10 @@ static boolean P_MobjRegularThink(mobj_t *mobj)
|
|||
scale += (blow * ((3*scale)>>1)) / bubbletime;
|
||||
|
||||
mobj->frame = CLAMP(states[S_BUBBLESHIELDBLOWUP].frame + mobj->extravalue1, states[S_BUBBLESHIELDBLOWUP].frame, states[S_BUBBLESHIELDBLOWUP].frame + 3);
|
||||
|
||||
frame = mobj->frame & FF_FRAMEMASK;
|
||||
scale_idx = CLAMP(frame - 9, 0, 3);
|
||||
|
||||
if ((mobj->target->player->bubbleblowup > bubbletime) && (leveltime & 1))
|
||||
{
|
||||
mobj->color = SKINCOLOR_WHITE;
|
||||
|
|
@ -9247,6 +9284,9 @@ static boolean P_MobjRegularThink(mobj_t *mobj)
|
|||
{
|
||||
mobj->frame = (states[S_BUBBLESHIELDBLOWUP].frame + mobj->extravalue1);
|
||||
|
||||
frame = mobj->frame & FF_FRAMEMASK;
|
||||
scale_idx = CLAMP(frame - 9, 0, 3);
|
||||
|
||||
if (mobj->extravalue1 < 0 && (leveltime & 1))
|
||||
mobj->extravalue1++;
|
||||
else if (mobj->extravalue1 > 0)
|
||||
|
|
@ -9270,15 +9310,92 @@ static boolean P_MobjRegularThink(mobj_t *mobj)
|
|||
mobj->extravalue2 = mobj->target->player->bubbleblowup;
|
||||
P_SetScale(mobj, (mobj->destscale = scale));
|
||||
|
||||
mobj->pitch = mobj->target->pitch;
|
||||
mobj->roll = mobj->target->roll;
|
||||
if (mobj->tracer && (!P_MobjWasRemoved(mobj->tracer)))
|
||||
{
|
||||
if (mobj->tracer->type == MT_OVERLAY)
|
||||
{
|
||||
fixed_t health_scalar;
|
||||
|
||||
P_SetScale(mobj->tracer, mobj->destscale);
|
||||
|
||||
mobj->slopepitch = mobj->target->slopepitch;
|
||||
mobj->sloperoll = mobj->target->sloperoll;
|
||||
mobj->tracer->threshold |= OV_DONTXYSCALE;
|
||||
|
||||
mobj->tracer->spritexscale = FixedMul(mobj->spritexscale, bubbleoverlayscales[scale_idx][0]);
|
||||
mobj->tracer->spriteyscale = FixedMul(mobj->spriteyscale, bubbleoverlayscales[scale_idx][1]);
|
||||
|
||||
health_scalar = mobj->target->player->bubblehealth * FRACUNIT / MAXBUBBLEHEALTH;
|
||||
health_scalar = 5 - CLAMP(health_scalar / (FRACUNIT / 5), 1, 5);
|
||||
|
||||
overlaystate = ((mobj->tracer->tics == 1) ? (mobj->tracer->state->nextstate) : ((statenum_t)(mobj->tracer->state-states)));
|
||||
|
||||
// Depending on the level of damage done to the shield, show some cracks.
|
||||
if (overlaystate != bubbledamagestates[health_scalar])
|
||||
{
|
||||
P_SetMobjState(mobj->tracer, bubbledamagestates[health_scalar]);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Very silently detach ourselves from our tracer and try a
|
||||
// damage-control fix.
|
||||
P_SetTarget(&mobj->tracer, NULL);
|
||||
|
||||
mobj_t *spawn = P_SpawnMobj(mobj->x, mobj->z, mobj->z, MT_OVERLAY);
|
||||
spawn->destscale = mobj->scale;
|
||||
P_SetScale(spawn, mobj->scale);
|
||||
P_SetTarget(&mobj->tracer, spawn);
|
||||
P_SetTarget(&spawn->target, mobj);
|
||||
}
|
||||
}
|
||||
|
||||
// Don't sloperoll Bubble Shields since it messes with the shatter VFX
|
||||
mobj->pitch = 0;
|
||||
mobj->roll = 0;
|
||||
|
||||
mobj->slopepitch = 0;
|
||||
mobj->sloperoll = 0;
|
||||
|
||||
P_MoveOrigin(mobj, mobj->target->x, mobj->target->y, mobj->target->z);
|
||||
break;
|
||||
}
|
||||
case MT_BUBBLESHLD_DEBRIS:
|
||||
{
|
||||
statenum_t curstate;
|
||||
curstate = ((mobj->tics == 1) ? (mobj->state->nextstate) : ((statenum_t)(mobj->state-states)));
|
||||
|
||||
if (curstate != S_INVISIBLE)
|
||||
{
|
||||
mobj->rollangle += ANG1 * 4;
|
||||
}
|
||||
else
|
||||
{
|
||||
mobj->rollangle = 0;
|
||||
}
|
||||
|
||||
if ((P_IsObjectOnGround(mobj)) && (!mobj->threshold))
|
||||
{
|
||||
mobj->threshold = (TICRATE / 2);
|
||||
|
||||
if (curstate != S_INVISIBLE)
|
||||
{
|
||||
// "Despawn" and play the glass landing sound.
|
||||
S_StartSound(mobj, mobj->info->activesound);
|
||||
P_SetMobjState(mobj, S_INVISIBLE);
|
||||
}
|
||||
}
|
||||
|
||||
if (mobj->threshold)
|
||||
{
|
||||
mobj->threshold--;
|
||||
|
||||
if (!mobj->threshold)
|
||||
{
|
||||
P_RemoveMobj(mobj);
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
case MT_FLAMESHIELD:
|
||||
{
|
||||
statenum_t curstate;
|
||||
|
|
@ -10389,6 +10506,8 @@ void P_MobjThinker(mobj_t *mobj)
|
|||
P_SetTarget(&mobj->hprev, NULL);
|
||||
if (mobj->itnext && P_MobjWasRemoved(mobj->itnext))
|
||||
P_SetTarget(&mobj->itnext, NULL);
|
||||
if (mobj->shieldtracer && P_MobjWasRemoved(mobj->shieldtracer))
|
||||
P_SetTarget(&mobj->shieldtracer, NULL);
|
||||
|
||||
if (mobj->flags & MF_NOTHINK)
|
||||
return;
|
||||
|
|
@ -11282,6 +11401,23 @@ mobj_t *P_SpawnMobj(fixed_t x, fixed_t y, fixed_t z, mobjtype_t type)
|
|||
nummaprings++;
|
||||
break;
|
||||
// SRB2Kart
|
||||
case MT_BUBBLESHIELD:
|
||||
{
|
||||
// Spawn in the damage overlay
|
||||
mobj_t *spawn = P_SpawnMobj(mobj->x, mobj->z, mobj->z, MT_OVERLAY);
|
||||
spawn->destscale = mobj->scale;
|
||||
P_SetScale(spawn, mobj->scale);
|
||||
P_SetTarget(&mobj->tracer, spawn);
|
||||
P_SetTarget(&spawn->target, mobj);
|
||||
break;
|
||||
}
|
||||
case MT_BUBBLESHLD_DEBRIS:
|
||||
{
|
||||
statenum_t shardset[] = {S_BUBBLEDEBRIS_1, S_BUBBLEDEBRIS_2, S_BUBBLEDEBRIS_3, S_BUBBLEDEBRIS_4, S_BUBBLEDEBRIS_5};
|
||||
P_SetMobjState(mobj, shardset[P_RandomRange(0, 4)]);
|
||||
|
||||
break;
|
||||
}
|
||||
case MT_ITEMCAPSULE:
|
||||
{
|
||||
// set default item & count
|
||||
|
|
|
|||
|
|
@ -387,6 +387,8 @@ struct mobj_t
|
|||
|
||||
mobj_t *tracer; // Thing being chased/attacked for tracers.
|
||||
|
||||
mobj_t *shieldtracer; // Blankart: Shield mobj, currently only for certain VFX
|
||||
|
||||
fixed_t friction;
|
||||
fixed_t movefactor;
|
||||
fixed_t gravity;
|
||||
|
|
|
|||
|
|
@ -2118,6 +2118,7 @@ typedef enum
|
|||
MD3_MISCCAP = 1<<1,
|
||||
MD3_BAKEDOFFSET = 1<<2,
|
||||
MD3_EXTVAL3 = 1<<3,
|
||||
MD3_SHIELDTRACER = 1<<4,
|
||||
} mobj_diff3_t;
|
||||
|
||||
typedef enum
|
||||
|
|
@ -2435,6 +2436,8 @@ static void SaveMobjThinker(savebuffer_t *save, const thinker_t *th, const UINT8
|
|||
diff3 |= MD3_BAKEDOFFSET;
|
||||
if (mobj->extravalue3)
|
||||
diff3 |= MD3_EXTVAL3;
|
||||
if (mobj->shieldtracer)
|
||||
diff3 |= MD3_SHIELDTRACER;
|
||||
|
||||
if (diff3 != 0)
|
||||
diff2 |= MD2_MORE;
|
||||
|
|
@ -2725,6 +2728,10 @@ static void SaveMobjThinker(savebuffer_t *save, const thinker_t *th, const UINT8
|
|||
{
|
||||
WRITEINT32(save->p, mobj->extravalue3);
|
||||
}
|
||||
if (diff3 & MD3_SHIELDTRACER)
|
||||
{
|
||||
WRITEUINT32(save->p, mobj->shieldtracer->mobjnum);
|
||||
}
|
||||
|
||||
WRITEUINT32(save->p, mobj->mobjnum);
|
||||
}
|
||||
|
|
@ -4028,6 +4035,10 @@ static thinker_t* LoadMobjThinker(savebuffer_t *save, actionf_p1 thinker, UINT8
|
|||
{
|
||||
mobj->extravalue3 = READINT32(save->p);
|
||||
}
|
||||
if (diff3 & MD3_SHIELDTRACER)
|
||||
{
|
||||
mobj->shieldtracer = (mobj_t *)(size_t)READUINT32(save->p);
|
||||
}
|
||||
|
||||
// Reset some non-synch values
|
||||
mobj->sloperoll = 0;
|
||||
|
|
@ -5097,6 +5108,11 @@ static void P_RelinkPointers(void)
|
|||
if (!RelinkMobj(&mobj->terrainOverlay))
|
||||
CONS_Debug(DBG_GAMELOGIC, "terrainOverlay not found on %d\n", mobj->type);
|
||||
}
|
||||
if (mobj->shieldtracer)
|
||||
{
|
||||
if (!RelinkMobj(&mobj->shieldtracer))
|
||||
CONS_Debug(DBG_GAMELOGIC, "shieldtracer not found on %d\n", mobj->type);
|
||||
}
|
||||
for (i = 0; i < MAXPLAYERS; i++)
|
||||
{
|
||||
if (!playeringame[i])
|
||||
|
|
|
|||
Loading…
Reference in a new issue