From 7adde499c72ac637ddac0665ef60b34dbed03d7e Mon Sep 17 00:00:00 2001 From: Antonio Martinez Date: Thu, 29 May 2025 21:22:04 -0400 Subject: [PATCH 1/6] WIP: Alternate lightning --- src/d_player.h | 1 + src/k_kart.c | 31 +++++++++++++++++++++++++++++-- src/k_kart.h | 3 +++ src/lua_playerlib.c | 4 ++++ src/p_saveg.cpp | 2 ++ 5 files changed, 39 insertions(+), 2 deletions(-) diff --git a/src/d_player.h b/src/d_player.h index 8552ddf26..3abcaa18b 100644 --- a/src/d_player.h +++ b/src/d_player.h @@ -833,6 +833,7 @@ struct player_t UINT16 flamedash; // Flame Shield dash power UINT16 flamemeter; // Flame Shield dash meter left UINT8 flamelength; // Flame Shield dash meter, number of segments + UINT8 lightningcharge; // Lightning Shield attack timer UINT16 counterdash; // Flame Shield boost without the flame, largely. Used in places where awarding thrust would affect player control. diff --git a/src/k_kart.c b/src/k_kart.c index acde0305b..e21d80566 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -1480,6 +1480,9 @@ static boolean K_HasInfiniteTether(player_t *player) return true; } + if (player->lightningcharge) + return true; + if (player->eggmanexplode > 0) return true; @@ -1610,7 +1613,7 @@ static boolean K_TryDraft(player_t *player, mobj_t *dest, fixed_t minDist, fixed player->draftpower -= 3*add/4; } - if (gametyperules & GTR_CLOSERPLAYERS) + if (gametyperules & GTR_CLOSERPLAYERS || player->curshield == KSHIELD_LIGHTNING || player->lightningcharge) { // Double speed in smaller environments player->draftpower += add; @@ -10687,6 +10690,28 @@ void K_KartPlayerThink(player_t *player, ticcmd_t *cmd) K_FlameDashLeftoverSmoke(player->mo); } + if (player->lightningcharge) + { + player->lightningcharge++; + + /* + if (onground) + P_Thrust(player->mo, player->mo->angle, player->mo->scale); + */ + + if (player->lightningcharge == LIGHTNING_CHARGE) + { + K_DoLightningShield(player); + P_Thrust(player->mo, player->mo->angle, 100*player->mo->scale); + player->tiregrease = TICRATE/4; + player->lightningcharge = 0; + } + } + else + { + S_StopSoundByID(player->mo, LIGHTNING_SOUND); + } + if (P_IsObjectOnGround(player->mo) && player->trickpanel != TRICKSTATE_NONE) { if (P_MobjFlip(player->mo) * player->mo->momz <= 0) @@ -14721,7 +14746,9 @@ void K_MoveKartPlayer(player_t *player, boolean onground) if (ATTACK_IS_DOWN && !HOLDING_ITEM && NO_HYUDORO) { - K_DoLightningShield(player); + // K_DoLightningShield(player); + player->lightningcharge = 1; + S_StartSound(player->mo, LIGHTNING_SOUND); if (player->itemamount > 0) { // Why is this a conditional? diff --git a/src/k_kart.h b/src/k_kart.h index aff3b7596..356edb487 100644 --- a/src/k_kart.h +++ b/src/k_kart.h @@ -59,6 +59,9 @@ Make sure this matches the actual number of states #define TIMEATTACK_START (TICRATE*10) +#define LIGHTNING_CHARGE (TICRATE*2) +#define LIGHTNING_SOUND (sfx_s3k84) + #define OVERDRIVE_STARTUP (0) #define AMPLEVEL (15) diff --git a/src/lua_playerlib.c b/src/lua_playerlib.c index 65e2b894a..91b4908aa 100644 --- a/src/lua_playerlib.c +++ b/src/lua_playerlib.c @@ -494,6 +494,8 @@ static int player_get(lua_State *L) lua_pushinteger(L, plr->flamemeter); else if (fastcmp(field,"flamelength")) lua_pushinteger(L, plr->flamelength); + else if (fastcmp(field,"lightningcharge")) + lua_pushinteger(L, plr->lightningcharge); else if (fastcmp(field,"ballhogcharge")) lua_pushinteger(L, plr->ballhogcharge); else if (fastcmp(field,"ballhogtap")) @@ -1133,6 +1135,8 @@ static int player_set(lua_State *L) plr->flamemeter = luaL_checkinteger(L, 3); else if (fastcmp(field,"flamelength")) plr->flamelength = luaL_checkinteger(L, 3); + else if (fastcmp(field,"lightningcharge")) + plr->lightningcharge = luaL_checkinteger(L, 3); else if (fastcmp(field,"ballhogcharge")) plr->ballhogcharge = luaL_checkinteger(L, 3); else if (fastcmp(field,"ballhogtap")) diff --git a/src/p_saveg.cpp b/src/p_saveg.cpp index 41463eead..a8c1db997 100644 --- a/src/p_saveg.cpp +++ b/src/p_saveg.cpp @@ -560,6 +560,7 @@ static void P_NetArchivePlayers(savebuffer_t *save) WRITEUINT16(save->p, players[i].counterdash); WRITEUINT16(save->p, players[i].flamemeter); WRITEUINT8(save->p, players[i].flamelength); + WRITEUINT8(save->p, players[i].lightningcharge); WRITEUINT16(save->p, players[i].ballhogcharge); WRITEUINT8(save->p, players[i].ballhogtap); @@ -1225,6 +1226,7 @@ static void P_NetUnArchivePlayers(savebuffer_t *save) players[i].counterdash = READUINT16(save->p); players[i].flamemeter = READUINT16(save->p); players[i].flamelength = READUINT8(save->p); + players[i].lightningcharge = READUINT8(save->p); players[i].ballhogcharge = READUINT16(save->p); players[i].ballhogtap = READUINT8(save->p); From 58cc1312cb895eb856cc8c9aa21be6c7143f10f7 Mon Sep 17 00:00:00 2001 From: Antonio Martinez Date: Fri, 18 Jul 2025 17:52:25 -0400 Subject: [PATCH 2/6] 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)) From 3b9dd416d928e04cce1e3470ad1d8e1e33c66479 Mon Sep 17 00:00:00 2001 From: Antonio Martinez Date: Fri, 18 Jul 2025 18:17:31 -0400 Subject: [PATCH 3/6] Lightning Attack polish --- src/p_mobj.c | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/src/p_mobj.c b/src/p_mobj.c index f54bbe0e0..db2efd7f3 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -6735,10 +6735,24 @@ static void P_MobjSceneryThink(mobj_t *mobj) return; } + UINT8 SHRINK = 5; + UINT8 timer = (LIGHTNING_CHARGE - mobj->target->player->lightningcharge); UINT8 target = timer/10 + 1; - P_SetScale(mobj, (mobj->destscale = (5*mobj->target->scale)>>2)); + fixed_t myscale = (5*mobj->target->scale)>>2; + if (timer <= SHRINK) + { + myscale = Easing_InSine(FRACUNIT*(SHRINK - timer)/SHRINK, myscale, 0); + } + else + { + UINT8 pretimer = LIGHTNING_CHARGE - SHRINK; + fixed_t scalefactor = FRACUNIT * (timer - SHRINK) / pretimer; + myscale = Easing_Linear(scalefactor, 5*myscale/4, myscale); + } + + P_SetScale(mobj, (mobj->destscale = myscale)); 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. From bb90323f32c70218e80697b25d353b910bc3e097 Mon Sep 17 00:00:00 2001 From: VelocitOni Date: Fri, 18 Jul 2025 20:56:56 -0400 Subject: [PATCH 4/6] Lightning Shield louder Lightning Shield Charge plays at 4x distance --- src/sounds.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/sounds.c b/src/sounds.c index bb8c55633..4af86b79d 100644 --- a/src/sounds.c +++ b/src/sounds.c @@ -534,7 +534,7 @@ sfxinfo_t S_sfx[NUMSFX] = {"s3k81", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Burst"}, {"s3k82", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Burst"}, {"s3k83", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Collapsing"}, - {"s3k84", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Powering up"}, + {"s3k84", false, 64, 8, -1, NULL, 0, -1, -1, LUMPERROR, "Powering up"}, // Lightning Shield Charge {"s3k85", false, 64, 24, -1, NULL, 0, -1, -1, LUMPERROR, "Powering down"}, {"s3k86", false, 128, 8, -1, NULL, 0, -1, -1, LUMPERROR, "Alarm"}, {"s3k87", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Bounce"}, From 1a914726e77896eacf5e525f4abc23c7f7674ba6 Mon Sep 17 00:00:00 2001 From: Antonio Martinez Date: Fri, 18 Jul 2025 22:01:15 -0400 Subject: [PATCH 5/6] Lightning Attack blocks item slot --- src/k_kart.c | 30 ++++++++++++++++++------------ 1 file changed, 18 insertions(+), 12 deletions(-) diff --git a/src/k_kart.c b/src/k_kart.c index f37173f4b..457e368b7 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -10690,6 +10690,11 @@ void K_KartPlayerThink(player_t *player, ticcmd_t *cmd) K_FlameDashLeftoverSmoke(player->mo); } + if (player->curshield != KSHIELD_LIGHTNING) + { + player->lightningcharge = 0; + } + if (player->lightningcharge) { player->lightningcharge++; @@ -10705,6 +10710,18 @@ void K_KartPlayerThink(player_t *player, ticcmd_t *cmd) P_Thrust(player->mo, onground ? player->mo->angle : K_MomentumAngle(player->mo), 100*player->mo->scale); player->tiregrease = TICRATE/4; player->lightningcharge = 0; + + if (player->itemamount > 0) + { + // Why is this a conditional? + // Lightning shield: the only item that allows you to + // activate a mine while you're out of its radius, + // the SAME tic it sets your itemamount to 0 + // ...:dumbestass: + player->itemamount--; + K_PlayAttackTaunt(player->mo); + player->botvars.itemconfirm = 0; + } } } else @@ -14744,7 +14761,7 @@ void K_MoveKartPlayer(player_t *player, boolean onground) Obj_SpawnLightningShieldVisuals(shield); } - if (ATTACK_IS_DOWN && !HOLDING_ITEM && NO_HYUDORO) + if (ATTACK_IS_DOWN && !HOLDING_ITEM && NO_HYUDORO && !player->lightningcharge) { // K_DoLightningShield(player); player->lightningcharge = 1; @@ -14765,17 +14782,6 @@ void K_MoveKartPlayer(player_t *player, boolean onground) P_SetTarget(&at3->target, player->mo); S_StartSound(player->mo, LIGHTNING_SOUND); - if (player->itemamount > 0) - { - // Why is this a conditional? - // Lightning shield: the only item that allows you to - // activate a mine while you're out of its radius, - // the SAME tic it sets your itemamount to 0 - // ...:dumbestass: - player->itemamount--; - K_PlayAttackTaunt(player->mo); - player->botvars.itemconfirm = 0; - } } break; case KITEM_GARDENTOP: From 6c9d1c6b908f11e0cadcd0798976f2b6fb46ccb1 Mon Sep 17 00:00:00 2001 From: Antonio Martinez Date: Fri, 18 Jul 2025 22:07:36 -0400 Subject: [PATCH 6/6] Why was this here --- src/k_kart.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/k_kart.c b/src/k_kart.c index 457e368b7..79c247ad1 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -10708,7 +10708,7 @@ void K_KartPlayerThink(player_t *player, ticcmd_t *cmd) { K_DoLightningShield(player); P_Thrust(player->mo, onground ? player->mo->angle : K_MomentumAngle(player->mo), 100*player->mo->scale); - player->tiregrease = TICRATE/4; + // player->tiregrease = TICRATE/4; player->lightningcharge = 0; if (player->itemamount > 0)