From 58cc1312cb895eb856cc8c9aa21be6c7143f10f7 Mon Sep 17 00:00:00 2001 From: Antonio Martinez Date: Fri, 18 Jul 2025 17:52:25 -0400 Subject: [PATCH] Lightning Attack visuals --- src/deh_tables.c | 7 +++++++ src/info.c | 38 ++++++++++++++++++++++++++++++++++++++ src/info.h | 12 ++++++++++++ src/k_kart.c | 18 +++++++++++++++++- src/k_objects.h | 4 ++++ src/p_mobj.c | 39 +++++++++++++++++++++++++++++++++++++++ 6 files changed, 117 insertions(+), 1 deletion(-) diff --git a/src/deh_tables.c b/src/deh_tables.c index acc6be553..eadb207f2 100644 --- a/src/deh_tables.c +++ b/src/deh_tables.c @@ -2011,6 +2011,12 @@ const char *const STATE_LIST[] = { // array length left dynamic for sanity testi "S_THNC2", "S_THNB1", + "S_THND", + "S_THNE", + "S_THNH", + "S_THNF", + "S_THNG", + // Bubble Shield "S_BUBBLESHIELD1", "S_BUBBLESHIELD2", @@ -3664,6 +3670,7 @@ const char *const MOBJTYPE_LIST[] = { // array length left dynamic for sanity t "MT_LIGHTNINGSHIELD", // Shields "MT_LIGHTNINGSHIELD_VISUAL", + "MT_LIGHTNINGATTACK_VISUAL", "MT_BUBBLESHIELD", "MT_BUBBLESHIELD_VISUAL", "MT_FLAMESHIELD", diff --git a/src/info.c b/src/info.c index a1760a822..3405f0873 100644 --- a/src/info.c +++ b/src/info.c @@ -388,6 +388,11 @@ char sprnames[NUMSPRITES + 1][5] = "THNC", // Lightning Shield Top Flash "THNA", // Lightning Shield Top Swoosh "THNB", // Lightning Shield Bottom Swoosh + "THND", // Lightning attack + "THNE", // Lightning attack + "THNH", // Lightning attack + "THNF", // Lightning attack + "THNG", // Lightning attack "BUBS", // Bubble Shield (not Bubs) "BUBT", // Bubble Shield trap "BUBA", // Bubble Shield Outline @@ -2580,6 +2585,12 @@ state_t states[NUMSTATES] = {SPR_THNC, FF_ADD|FF_FULLBRIGHT|FF_ANIMATE, 11, {NULL}, 10, 1, S_THNB1}, // S_THNC2 {SPR_THNB, FF_ADD|FF_FULLBRIGHT|FF_ANIMATE, 43, {NULL}, 42, 1, S_THNC1}, // S_THNB1 + {SPR_THND, FF_ADD|FF_FULLBRIGHT|FF_ANIMATE, -1, {NULL}, 10, 1, S_THND}, // S_THND + {SPR_THNE, FF_FULLBRIGHT|FF_ANIMATE, 34, {NULL}, 33, 1, S_THNH}, // S_THNE + {SPR_NULL, FF_FULLBRIGHT, 34, {NULL}, 33, 1, S_THNE}, // S_THNH + {SPR_THNF, FF_FULLBRIGHT|FF_ANIMATE, 4, {NULL}, 3, 1, S_THNG}, // S_THNF + {SPR_THNG, FF_FULLBRIGHT|FF_ANIMATE, 64, {NULL}, 63, 1, S_THNF}, // S_THNG + {SPR_BUBS, FF_FULLBRIGHT, 2, {NULL}, 0, 0, S_BUBBLESHIELD2}, // S_BUBBLESHIELD1 {SPR_BUBS, FF_FULLBRIGHT|13, 2, {NULL}, 0, 0, S_BUBBLESHIELD3}, // S_BUBBLESHIELD2 {SPR_BUBS, FF_FULLBRIGHT|1, 2, {NULL}, 0, 0, S_BUBBLESHIELD4}, // S_BUBBLESHIELD3 @@ -15603,6 +15614,33 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = S_NULL // raisestate }, + { // MT_LIGHTNINGATTACK_VISUAL + -1, // doomednum + S_THND, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + sfx_None, // seesound + 8, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + 0, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // deathstate + S_NULL, // xdeathstate + sfx_None, // deathsound + 8, // speed + 28*FRACUNIT, // radius + 56*FRACUNIT, // height + 1, // display offset + 16, // mass + 0, // damage + sfx_None, // activesound + MF_NOBLOCKMAP|MF_NOCLIP|MF_NOCLIPTHING|MF_NOCLIPHEIGHT|MF_NOGRAVITY|MF_SCENERY|MF_DONTENCOREMAP, // flags + S_NULL // raisestate + }, + { // MT_BUBBLESHIELD -1, // doomednum S_BUBBLESHIELD1, // spawnstate diff --git a/src/info.h b/src/info.h index ddfe07012..dd99ca9c4 100644 --- a/src/info.h +++ b/src/info.h @@ -929,6 +929,11 @@ typedef enum sprite SPR_THNC, // Lightning Shield Top Flash SPR_THNA, // Lightning Shield Top Swoosh SPR_THNB, // Lightning Shield Bottom Swoosh + SPR_THND, // Lightning Attack + SPR_THNE, // Lightning Attack + SPR_THNH, // Lightning Attack + SPR_THNF, // Lightning Attack + SPR_THNG, // Lightning Attack SPR_BUBS, // Bubble Shield (not Bubs) SPR_BUBT, // Bubble Shield trap SPR_BUBA, // Bubble Shield Outline @@ -3073,6 +3078,12 @@ typedef enum state S_THNC2, S_THNB1, + S_THND, + S_THNE, + S_THNH, + S_THNF, + S_THNG, + // Bubble Shield S_BUBBLESHIELD1, S_BUBBLESHIELD2, @@ -4753,6 +4764,7 @@ typedef enum mobj_type MT_LIGHTNINGSHIELD, // Shields MT_LIGHTNINGSHIELD_VISUAL, + MT_LIGHTNINGATTACK_VISUAL, MT_BUBBLESHIELD, MT_BUBBLESHIELD_VISUAL, MT_FLAMESHIELD, diff --git a/src/k_kart.c b/src/k_kart.c index e21d80566..f37173f4b 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -10702,7 +10702,7 @@ void K_KartPlayerThink(player_t *player, ticcmd_t *cmd) if (player->lightningcharge == LIGHTNING_CHARGE) { K_DoLightningShield(player); - P_Thrust(player->mo, player->mo->angle, 100*player->mo->scale); + P_Thrust(player->mo, onground ? player->mo->angle : K_MomentumAngle(player->mo), 100*player->mo->scale); player->tiregrease = TICRATE/4; player->lightningcharge = 0; } @@ -14748,6 +14748,22 @@ void K_MoveKartPlayer(player_t *player, boolean onground) { // K_DoLightningShield(player); player->lightningcharge = 1; + + mobj_t *at1 = P_SpawnMobjFromMobj(player->mo, 0, 0, 0, MT_LIGHTNINGATTACK_VISUAL); + mobj_t *at2 = P_SpawnMobjFromMobj(player->mo, 0, 0, 0, MT_LIGHTNINGATTACK_VISUAL); + mobj_t *at3 = P_SpawnMobjFromMobj(player->mo, 0, 0, 0, MT_LIGHTNINGATTACK_VISUAL); + + P_SetMobjState(at1, S_THNG); + P_SetMobjState(at2, S_THND); + P_SetMobjState(at3, S_THNH); + + at2->dispoffset = 2; + at3->dispoffset = -1; + + P_SetTarget(&at1->target, player->mo); + P_SetTarget(&at2->target, player->mo); + P_SetTarget(&at3->target, player->mo); + S_StartSound(player->mo, LIGHTNING_SOUND); if (player->itemamount > 0) { diff --git a/src/k_objects.h b/src/k_objects.h index d29dc74cb..402ab2991 100644 --- a/src/k_objects.h +++ b/src/k_objects.h @@ -464,6 +464,10 @@ boolean Obj_TickBubbleShieldVisual(mobj_t *mobj); void Obj_SpawnLightningShieldVisuals(mobj_t *source); boolean Obj_TickLightningShieldVisual(mobj_t *mobj); +/* Lightning Attack */ +void Obj_SpawnLightningAttackVisuals(mobj_t *source); +boolean Obj_TickLightningAttackVisual(mobj_t *mobj); + /* Flame Shield */ void Obj_SpawnFlameShieldVisuals(mobj_t *source); boolean Obj_TickFlameShieldVisual(mobj_t *mobj); diff --git a/src/p_mobj.c b/src/p_mobj.c index c7287ccb9..f54bbe0e0 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -6721,6 +6721,45 @@ static void P_MobjSceneryThink(mobj_t *mobj) } break; } + case MT_LIGHTNINGATTACK_VISUAL: + { + if (!(mobj->target && !P_MobjWasRemoved(mobj->target))) + { + P_RemoveMobj(mobj); + return; + } + + if (!mobj->target->player || !mobj->target->player->lightningcharge) + { + P_RemoveMobj(mobj); + return; + } + + UINT8 timer = (LIGHTNING_CHARGE - mobj->target->player->lightningcharge); + UINT8 target = timer/10 + 1; + + P_SetScale(mobj, (mobj->destscale = (5*mobj->target->scale)>>2)); + + P_MoveOrigin(mobj, mobj->target->x, mobj->target->y, mobj->target->z + mobj->target->height/2); + // Taken from K_FlipFromObject. We just want to flip the visual according to its target, but that's it. + mobj->eflags = (mobj->eflags & ~MFE_VERTICALFLIP)|(mobj->target->eflags & MFE_VERTICALFLIP); + + mobj->extravalue1++; + + if (mobj->extravalue1 > target) + { + mobj->color = SKINCOLOR_WHITE; + mobj->colorized = true; + mobj->extravalue1 = 0; + } + else + { + mobj->colorized = false; + mobj->renderflags &= ~RF_DONTDRAW; + } + + break; + } case MT_FLAMESHIELD_VISUAL: { if (!Obj_TickFlameShieldVisual(mobj))