diff --git a/src/k_objects.h b/src/k_objects.h index a14dd7dd1..cc2162d96 100644 --- a/src/k_objects.h +++ b/src/k_objects.h @@ -392,6 +392,9 @@ void Obj_SSCabotronMobjSpawn(mobj_t* mo); void Obj_SSCabotronMobjThink(mobj_t* mo); void Obj_SSCabotronStarMobjThink(mobj_t* mo); +/* Talk Point */ +void Obj_TalkPointThink(mobj_t* mo); + #ifdef __cplusplus } // extern "C" #endif diff --git a/src/objects/CMakeLists.txt b/src/objects/CMakeLists.txt index 31c92d74f..fce16395a 100644 --- a/src/objects/CMakeLists.txt +++ b/src/objects/CMakeLists.txt @@ -53,6 +53,7 @@ target_sources(SRB2SDL2 PRIVATE cloud.c waterfall-particle.c sealed-star.c + talk-point.cpp ) add_subdirectory(versus) diff --git a/src/objects/talk-point.cpp b/src/objects/talk-point.cpp new file mode 100644 index 000000000..e423fe071 --- /dev/null +++ b/src/objects/talk-point.cpp @@ -0,0 +1,71 @@ +// DR. ROBOTNIK'S RING RACERS +//------------------------------- +// Copyright (C) 2024 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 "../doomdef.h" +#include "../g_game.h" +#include "../p_spec.h" + +using namespace srb2::objects; + +namespace +{ + +struct TalkPoint : Mobj +{ + void thing_args() = delete; + Fixed radius() const { return mobj_t::thing_args[0] * FRACUNIT; } + bool oneshot() const { return !mobj_t::thing_args[1]; } + bool disabled() const { return mobj_t::thing_args[2]; } + + void think() + { + if (disabled()) + { + // turned off + return; + } + + for (UINT8 i = 0; i < MAXPLAYERS; i++) + { + if (playeringame[i] == false || players[i].spectator == true) + { + continue; + } + + Mobj* player_mobj = static_cast(players[i].mo); + if (!Mobj::valid(player_mobj)) + { + continue; + } + + Fixed dist = (pos2d() - player_mobj->pos2d()).magnitude(); + if (dist < radius()) + { + P_ActivateThingSpecial(this, player_mobj); + + if (oneshot()) + { + remove(); + return; + } + + break; + } + } + } +}; + +}; // namespace + +void Obj_TalkPointThink(mobj_t* mo) +{ + static_cast(mo)->think(); +} diff --git a/src/p_mobj.c b/src/p_mobj.c index dabd3ff6a..31549adc6 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -6458,48 +6458,8 @@ static void P_MobjSceneryThink(mobj_t *mobj) Obj_CheckpointThink(mobj); break; case MT_SCRIPT_THING: - { - if (mobj->thing_args[2] != 0) - { - // turned off - break; - } - - UINT8 i; - for (i = 0; i < MAXPLAYERS; i++) - { - if (playeringame[i] == false || players[i].spectator == true) - { - continue; - } - - player_t *player = &players[i]; - if (P_MobjWasRemoved(player->mo) == true) - { - continue; - } - - fixed_t dist = R_PointToDist2( - mobj->x, mobj->y, - player->mo->x, player->mo->y - ); - - if (dist < mobj->thing_args[0] * FRACUNIT) - { - P_ActivateThingSpecial(mobj, player->mo); - - if (mobj->thing_args[1] == 0) - { - P_RemoveMobj(mobj); - return; - } - - break; - } - } - - break; - } + Obj_TalkPointThink(mobj); + return; case MT_SPIKEDTARGET: { if (P_MobjWasRemoved(mobj->target) || (mobj->target->health <= 0) || (mobj->target->z == mobj->target->floorz))