diff --git a/src/info.c b/src/info.c index f8c30e83a..e0756d795 100644 --- a/src/info.c +++ b/src/info.c @@ -15481,7 +15481,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = { // MT_FLAMESHIELD -1, // doomednum - S_FLAMESHIELD1, // spawnstate + S_INVISIBLE, // spawnstate 1000, // spawnhealth S_NULL, // seestate sfx_None, // seesound diff --git a/src/k_kart.c b/src/k_kart.c index 4879bd517..cbb0050b4 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -14193,6 +14193,8 @@ void K_MoveKartPlayer(player_t *player, boolean onground) P_SetTarget(&shield->target, player->mo); S_StartSound(player->mo, sfx_s3k3e); player->curshield = KSHIELD_FLAME; + + Obj_SpawnFlameShieldVisuals(shield); } if (!HOLDING_ITEM && NO_HYUDORO) diff --git a/src/k_objects.h b/src/k_objects.h index a3468cb8e..cbdb189a7 100644 --- a/src/k_objects.h +++ b/src/k_objects.h @@ -457,6 +457,10 @@ boolean Obj_TickBubbleShieldVisual(mobj_t *mobj); void Obj_SpawnLightningShieldVisuals(mobj_t *source); boolean Obj_TickLightningShieldVisual(mobj_t *mobj); +/* Flame Shield */ +void Obj_SpawnFlameShieldVisuals(mobj_t *source); +boolean Obj_TickFlameShieldVisual(mobj_t *mobj); + #ifdef __cplusplus } // extern "C" #endif diff --git a/src/objects/CMakeLists.txt b/src/objects/CMakeLists.txt index 1b9b26f0f..d82a2d77c 100644 --- a/src/objects/CMakeLists.txt +++ b/src/objects/CMakeLists.txt @@ -63,6 +63,7 @@ target_sources(SRB2SDL2 PRIVATE bubble-shield.cpp flybot767.c lightning-shield.cpp + flame-shield.cpp ) add_subdirectory(versus) diff --git a/src/objects/flame-shield.cpp b/src/objects/flame-shield.cpp new file mode 100644 index 000000000..bed96c97a --- /dev/null +++ b/src/objects/flame-shield.cpp @@ -0,0 +1,82 @@ +// DR. ROBOTNIK'S RING RACERS +//----------------------------------------------------------------------------- +// Copyright (C) 2025 by James Robert Roman +// Copyright (C) 2025 by Kart Krew +// +// This program is free software distributed under the +// terms of the GNU General Public License, version 2. +// See the 'LICENSE' file for more details. +//----------------------------------------------------------------------------- + +#include "objects.hpp" + +#include "../tables.h" + +using namespace srb2::objects; + +namespace +{ + +struct Shield : Mobj +{ + void target() = delete; + Mobj* follow() const { return Mobj::target(); } + void follow(Mobj* n) { Mobj::target(n); } + + player_t* player() const { return follow()->player; } + + bool valid() const { return Mobj::valid(follow()) && player(); } +}; + +struct Visual : Mobj +{ + void target() = delete; + Shield* shield() const { return Mobj::target(); } + void shield(Shield* n) { Mobj::target(n); } + + bool valid() const { return Mobj::valid(shield()) && shield()->valid(); } + + static void spawn + ( Shield* shield, + statenum_t state, + int offset) + { + if (!shield->valid()) + return; + + Visual* x = Mobj::spawn(shield->pos(), MT_FLAMESHIELD_VISUAL); + x->scale(5 * shield->follow()->scale() / 4); + x->state(state); + x->shield(shield); + x->linkdraw(shield->follow(), offset); + } + + bool tick() + { + if (!valid()) + { + remove(); + return false; + } + + move_origin(shield()->pos()); + + renderflags = (renderflags & ~RF_DONTDRAW) | + (shield()->state()->num() == S_INVISIBLE ? 0 : RF_DONTDRAW); + + return true; + } +}; + +}; // namespace + +void Obj_SpawnFlameShieldVisuals(mobj_t *shield) +{ + Visual::spawn(static_cast(shield), S_FLMA1, 1); + Visual::spawn(static_cast(shield), S_FLMB1, -1); +} + +boolean Obj_TickFlameShieldVisual(mobj_t *mobj) +{ + return static_cast(mobj)->tick(); +} diff --git a/src/p_mobj.c b/src/p_mobj.c index ea6bb86df..e5b0e9530 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -6674,6 +6674,14 @@ static void P_MobjSceneryThink(mobj_t *mobj) } break; } + case MT_FLAMESHIELD_VISUAL: + { + if (!Obj_TickFlameShieldVisual(mobj)) + { + return; + } + break; + } default: if (mobj->fuse) { // Scenery object fuse! Very basic! @@ -8722,8 +8730,8 @@ static boolean P_MobjRegularThink(mobj_t *mobj) else { if (curstate >= S_FLAMESHIELDDASH1 && curstate <= S_FLAMESHIELDDASH12) - P_SetMobjState(mobj, S_FLAMESHIELD1); - mobj->dispoffset = ((curstate - S_FLAMESHIELD1) & 1) ? -1 : 1; + P_SetMobjState(mobj, S_INVISIBLE); + //mobj->dispoffset = ((curstate - S_FLAMESHIELD1) & 1) ? -1 : 1; } mobj->extravalue1 = mobj->target->player->flamedash;