From d5f970b31d867069c94936f96351b1879c495992 Mon Sep 17 00:00:00 2001 From: Lactozilla Date: Sun, 9 Feb 2025 00:06:59 -0300 Subject: [PATCH 1/2] Implement custom jet fume functionality --- src/d_player.h | 17 ++++----- src/deh_tables.c | 3 +- src/info.c | 4 +-- src/p_user.c | 94 ++++++++++++++++++++++++++++++++++++------------ src/r_skins.c | 4 ++- 5 files changed, 88 insertions(+), 34 deletions(-) diff --git a/src/d_player.h b/src/d_player.h index cdb547d3b..b4453c79b 100644 --- a/src/d_player.h +++ b/src/d_player.h @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2024 by Sonic Team Junior. +// Copyright (C) 1999-2025 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -47,13 +47,14 @@ typedef enum SF_DASHMODE = 1<<11, // Sonic Advance 2 style top speed increase? SF_FASTWAIT = 1<<12, // Faster wait animation? SF_FASTEDGE = 1<<13, // Faster edge teeter? - SF_MULTIABILITY = 1<<14, // Revenge of Final Demo. - SF_NONIGHTSROTATION = 1<<15, // Disable sprite rotation for NiGHTS - SF_NONIGHTSSUPER = 1<<16, // Disable super colors for NiGHTS (if you have SF_SUPER) - SF_NOSUPERSPRITES = 1<<17, // Don't use super sprites while super - SF_NOSUPERJUMPBOOST = 1<<18, // Disable the jump boost given while super (i.e. Knuckles) - SF_CANBUSTWALLS = 1<<19, // Can naturally bust walls on contact? (i.e. Knuckles) - SF_NOSHIELDABILITY = 1<<20, // Disable shield abilities + SF_JETFUME = 1<<14, // Follow item uses Metal Sonic's jet fume behavior + SF_MULTIABILITY = 1<<15, // Revenge of Final Demo. + SF_NONIGHTSROTATION = 1<<16, // Disable sprite rotation for NiGHTS + SF_NONIGHTSSUPER = 1<<17, // Disable super colors for NiGHTS (if you have SF_SUPER) + SF_NOSUPERSPRITES = 1<<18, // Don't use super sprites while super + SF_NOSUPERJUMPBOOST = 1<<19, // Disable the jump boost given while super (i.e. Knuckles) + SF_CANBUSTWALLS = 1<<20, // Can naturally bust walls on contact? (i.e. Knuckles) + SF_NOSHIELDABILITY = 1<<21, // Disable shield abilities // free up to and including 1<<31 } skinflags_t; diff --git a/src/deh_tables.c b/src/deh_tables.c index d71463253..a96adf8ae 100644 --- a/src/deh_tables.c +++ b/src/deh_tables.c @@ -1,7 +1,7 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2024 by Sonic Team Junior. +// Copyright (C) 1999-2025 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -5260,6 +5260,7 @@ struct int_const_s const INT_CONST[] = { {"SF_DASHMODE",SF_DASHMODE}, {"SF_FASTWAIT",SF_FASTWAIT}, {"SF_FASTEDGE",SF_FASTEDGE}, + {"SF_JETFUME",SF_JETFUME}, {"SF_MULTIABILITY",SF_MULTIABILITY}, {"SF_NONIGHTSROTATION",SF_NONIGHTSROTATION}, {"SF_NONIGHTSSUPER",SF_NONIGHTSSUPER}, diff --git a/src/info.c b/src/info.c index 4d3468e10..3998eb88d 100644 --- a/src/info.c +++ b/src/info.c @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2024 by Sonic Team Junior. +// Copyright (C) 1999-2025 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -4187,7 +4187,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = S_NULL, // painstate 0, // painchance sfx_None, // painsound - S_NULL, // meleestate + S_JETFUMEFLASH, // meleestate S_NULL, // missilestate S_NULL, // deathstate S_NULL, // xdeathstate diff --git a/src/p_user.c b/src/p_user.c index 7cc9c02ae..2b2334df7 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2024 by Sonic Team Junior. +// Copyright (C) 1999-2025 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -11515,6 +11515,17 @@ void P_DoTailsOverlay(player_t *player, mobj_t *tails) } // Metal Sonic's jet fume +// +// The follow object's state is set to its spawn state when deactivated. +// When the player is on a moving animation, the follow object goes to its see state. +// When dash mode is entered, the follow object switches to its melee state. +// +// If MF2_FRET is set, the jet fume flashes during dash mode. +// MF2_AMBUSH can be used to enable Metal Sonic's skidding animation. +// If the follow item is MT_METALJETFUME, the above two effects are automatically applied. +// +// MF2_STRONGBOX is internally used to track if the jet fume is in its deactivated state or not. +// MF2_BOSSNOTRAP is internally used to instantly reset the jet fume's scale to its intended scale. void P_DoMetalJetFume(player_t *player, mobj_t *fume) { static const UINT8 FUME_SKINCOLORS[] = @@ -11541,19 +11552,29 @@ void P_DoMetalJetFume(player_t *player, mobj_t *fume) fixed_t heightoffset = ((mo->eflags & MFE_VERTICALFLIP) ? mo->height - (P_GetPlayerHeight(player) >> 1) : (P_GetPlayerHeight(player) >> 1)); panim_t panim = player->panim; tic_t dashmode = min(player->dashmode, DASHMODE_MAX); + boolean ismetaljetfume = fume->type == MT_METALJETFUME; + boolean notmoving = panim != PA_WALK && panim != PA_RUN && panim != PA_DASH; boolean underwater = mo->eflags & MFE_UNDERWATER; statenum_t stat = fume->state-states; boolean resetinterp = false; - if (panim != PA_WALK && panim != PA_RUN && panim != PA_DASH) // turn invisible when not in a coherent movement state + if (notmoving) // deactivate when not in a coherent movement state { - if (stat != fume->info->spawnstate) + if ((fume->flags2 & MF2_STRONGBOX) == 0) + { P_SetMobjState(fume, fume->info->spawnstate); - return; + fume->flags2 |= MF2_STRONGBOX; + } + if (P_MobjWasRemoved(fume) || ismetaljetfume) + return; } - if (player->skidtime) // Rotate during metal sonic's new skid animation - angle += ANGLE_90; + // Rotate on skid animation if follow item is MT_METALJETFUME, or if MF2_AMBUSH is set + if (player->mo->sprite2 == SPR2_SKID) + { + if ((ismetaljetfume && (player->charflags & SF_JETFUME)) || (fume->flags2 & MF2_AMBUSH)) + angle += ANGLE_90; + } if (underwater) // No fume underwater; spawn bubbles instead! { @@ -11590,54 +11611,79 @@ void P_DoMetalJetFume(player_t *player, mobj_t *fume) if (panim == PA_WALK) { - if (stat != fume->info->spawnstate) + if ((fume->flags2 & MF2_STRONGBOX) == 0) { - fume->threshold = 0; P_SetMobjState(fume, fume->info->spawnstate); + fume->threshold = 0; + fume->flags2 &= ~MF2_STRONGBOX; } - return; + if (P_MobjWasRemoved(fume) || ismetaljetfume) + return; } } - if (stat == fume->info->spawnstate) // If currently inivisble, activate! + // If currently deactivated, activate! + if (!notmoving && !underwater && (fume->flags2 & MF2_STRONGBOX)) { P_SetMobjState(fume, (stat = fume->info->seestate)); + if (P_MobjWasRemoved(fume)) + return; P_SetScale(fume, mo->scale, false); + fume->flags2 &= ~MF2_STRONGBOX; resetinterp = true; } - if (dashmode > DASHMODE_THRESHOLD && stat != fume->info->seestate) // If in dashmode, grow really big and flash + // If in dash mode, grow really big + if (dashmode > DASHMODE_THRESHOLD && stat != fume->info->meleestate) { fume->destscale = mo->scale; - fume->flags2 ^= MF2_DONTDRAW; fume->flags2 |= mo->flags2 & MF2_DONTDRAW; + + // Flash if follow item is MT_METALJETFUME, or if MF2_FRET is set + if (ismetaljetfume || (fume->flags2 & MF2_FRET)) + fume->flags2 ^= MF2_DONTDRAW; } else // Otherwise, pick a size and color depending on speed and proximity to dashmode { - if (dashmode == DASHMODE_THRESHOLD && dashmode > (tic_t)fume->movecount) // If just about to enter dashmode, play the startup animation again + // If just about to enter dash mode, play the startup animation again + if (dashmode == DASHMODE_THRESHOLD && dashmode > (tic_t)fume->movecount) { - P_SetMobjState(fume, (stat = fume->info->seestate)); + P_SetMobjState(fume, fume->info->meleestate); + if (P_MobjWasRemoved(fume)) + return; P_SetScale(fume, 2*mo->scale, true); } + fume->flags2 = (fume->flags2 & ~MF2_DONTDRAW) | (mo->flags2 & MF2_DONTDRAW); fume->destscale = (mo->scale + FixedDiv(player->speed, player->normalspeed)) / (underwater ? 6 : 3); fume->color = FUME_SKINCOLORS[(dashmode * sizeof(FUME_SKINCOLORS)) / (DASHMODE_MAX + 1)]; if (underwater) { - fume->frame = (fume->frame & FF_FRAMEMASK) | FF_ANIMATE | (P_RandomRange(0, 9) * FF_TRANS10); + fume->frame = (fume->frame & ~FF_TRANSMASK) | (P_RandomRange(0, 9) << FF_TRANSSHIFT); fume->threshold = 1; } else if (fume->threshold) { - fume->frame = (fume->frame & FF_FRAMEMASK) | fume->state->frame; + fume->frame = (fume->frame & FF_FRAMEMASK) | (fume->state->frame & ~FF_FRAMEMASK); fume->threshold = 0; } } - fume->movecount = dashmode; // keeps track of previous dashmode value so we know whether Metal is entering or leaving it - fume->flags2 = (fume->flags2 & ~MF2_OBJECTFLIP) | (mo->flags2 & MF2_OBJECTFLIP); // Make sure to flip in reverse gravity! - fume->eflags = (fume->eflags & ~MFE_VERTICALFLIP) | (mo->eflags & MFE_VERTICALFLIP); // Make sure to flip in reverse gravity! + // keeps track of previous dash mode value so we know whether Metal is entering or leaving it + fume->movecount = dashmode; + + // Make sure to flip in reverse gravity! + fume->flags2 = (fume->flags2 & ~MF2_OBJECTFLIP) | (mo->flags2 & MF2_OBJECTFLIP); + fume->eflags = (fume->eflags & ~MFE_VERTICALFLIP) | (mo->eflags & MFE_VERTICALFLIP); + + // Set the appropriate scale at spawn + // This is... strange, but I had to choose a flag that a follow object would not ordinarily use. + if ((fume->flags2 & MF2_BOSSNOTRAP) == 0) + { + P_SetScale(fume, fume->destscale, true); + fume->flags2 |= MF2_BOSSNOTRAP; + } // Finally, set its position dist = -mo->radius - FixedMul(fume->info->radius, fume->destscale - mo->scale/3); @@ -11647,9 +11693,10 @@ void P_DoMetalJetFume(player_t *player, mobj_t *fume) fume->y = mo->y + P_ReturnThrustY(fume, angle, dist); fume->z = mo->z + heightoffset - (fume->height >> 1); P_SetThingPosition(fume); - if (resetinterp) R_ResetMobjInterpolationState(fume); + if (resetinterp) + R_ResetMobjInterpolationState(fume); - // If dashmode is high enough, spawn a trail + // If dash mode is high enough, spawn a trail if (player->normalspeed >= skins[player->skin]->normalspeed*2) { mobj_t *ghost = P_SpawnGhostMobj(fume); @@ -11663,6 +11710,8 @@ void P_DoFollowMobj(player_t *player, mobj_t *followmobj) { if (LUA_HookFollowMobj(player, followmobj) || P_MobjWasRemoved(followmobj)) {;} + else if (player->charflags & SF_JETFUME) + P_DoMetalJetFume(player, followmobj); else { switch (followmobj->type) @@ -13164,7 +13213,8 @@ void P_PlayerAfterThink(player_t *player) player->followmobj->colorized = true; break; default: - player->followmobj->flags2 |= MF2_LINKDRAW; + if ((player->charflags & SF_JETFUME) == 0) + player->followmobj->flags2 |= MF2_LINKDRAW; break; } } diff --git a/src/r_skins.c b/src/r_skins.c index f364273e8..d7df6756c 100644 --- a/src/r_skins.c +++ b/src/r_skins.c @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2024 by Sonic Team Junior. +// Copyright (C) 1999-2025 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -730,6 +730,8 @@ static boolean R_ProcessPatchableFields(skin_t *skin, char *stoken, char *value) GETFLAG(MACHINE) GETFLAG(DASHMODE) GETFLAG(FASTEDGE) + GETFLAG(FASTWAIT) + GETFLAG(JETFUME) GETFLAG(MULTIABILITY) GETFLAG(NONIGHTSROTATION) GETFLAG(NONIGHTSSUPER) From 0b84b3688ac4f6c3dd3c5b2227f80a1d8b492e2e Mon Sep 17 00:00:00 2001 From: Lactozilla Date: Sun, 9 Feb 2025 00:25:34 -0300 Subject: [PATCH 2/2] Implement color cycling toggle --- src/p_user.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/p_user.c b/src/p_user.c index 2b2334df7..51eefb314 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -11520,8 +11520,9 @@ void P_DoTailsOverlay(player_t *player, mobj_t *tails) // When the player is on a moving animation, the follow object goes to its see state. // When dash mode is entered, the follow object switches to its melee state. // -// If MF2_FRET is set, the jet fume flashes during dash mode. +// If MF2_FRET is set, the jet fume will flash during dash mode. // MF2_AMBUSH can be used to enable Metal Sonic's skidding animation. +// MF2_JUSTATTACKED will enable the color cycling. // If the follow item is MT_METALJETFUME, the above two effects are automatically applied. // // MF2_STRONGBOX is internally used to track if the jet fume is in its deactivated state or not. @@ -11656,7 +11657,10 @@ void P_DoMetalJetFume(player_t *player, mobj_t *fume) fume->flags2 = (fume->flags2 & ~MF2_DONTDRAW) | (mo->flags2 & MF2_DONTDRAW); fume->destscale = (mo->scale + FixedDiv(player->speed, player->normalspeed)) / (underwater ? 6 : 3); - fume->color = FUME_SKINCOLORS[(dashmode * sizeof(FUME_SKINCOLORS)) / (DASHMODE_MAX + 1)]; + + // Do color cycling if follow item is MT_METALJETFUME, or if MF2_JUSTATTACKED is set + if (ismetaljetfume || (fume->flags2 & MF2_JUSTATTACKED)) + fume->color = FUME_SKINCOLORS[(dashmode * sizeof(FUME_SKINCOLORS)) / (DASHMODE_MAX + 1)]; if (underwater) {