mirror of
https://github.com/KartKrewDev/RingRacers.git
synced 2025-12-18 05:52:48 +00:00
Battle UFOs, Checkpoints: use srb2::MobjList instead of standard containers
- Net synced; new mechanism in p_link.cpp to automatically manage mobj pointers at the global scope
This commit is contained in:
parent
43d090f699
commit
02bacc9a6f
9 changed files with 149 additions and 73 deletions
|
|
@ -50,6 +50,7 @@ add_executable(SRB2SDL2 MACOSX_BUNDLE WIN32
|
|||
p_floor.c
|
||||
p_inter.c
|
||||
p_lights.c
|
||||
p_link.cpp
|
||||
p_loop.c
|
||||
p_map.c
|
||||
p_mapthing.cpp
|
||||
|
|
|
|||
|
|
@ -821,7 +821,7 @@ void K_BattleInit(boolean singleplayercontext)
|
|||
}
|
||||
|
||||
g_battleufo.due = starttime;
|
||||
g_battleufo.previousId = Obj_GetFirstBattleUFOSpawnerID();
|
||||
g_battleufo.previousId = Obj_RandomBattleUFOSpawnerID() - 1;
|
||||
}
|
||||
|
||||
UINT8 K_Bumpers(player_t *player)
|
||||
|
|
|
|||
|
|
@ -184,8 +184,7 @@ void Obj_BattleUFODeath(mobj_t *ufo);
|
|||
void Obj_LinkBattleUFOSpawner(mobj_t *spawner);
|
||||
void Obj_UnlinkBattleUFOSpawner(mobj_t *spawner);
|
||||
void Obj_SpawnBattleUFOFromSpawner(void);
|
||||
INT32 Obj_GetFirstBattleUFOSpawnerID(void);
|
||||
void Obj_ResetUFOSpawners(void);
|
||||
INT32 Obj_RandomBattleUFOSpawnerID(void);
|
||||
void Obj_BattleUFOBeamThink(mobj_t *beam);
|
||||
|
||||
/* Power-Up Aura */
|
||||
|
|
@ -230,7 +229,6 @@ void Obj_FakeShadowThink(mobj_t *shadow);
|
|||
boolean Obj_FakeShadowZ(const mobj_t *shadow, fixed_t *return_z, pslope_t **return_slope);
|
||||
|
||||
/* Checkpoints */
|
||||
void Obj_ResetCheckpoints(void);
|
||||
void Obj_LinkCheckpoint(mobj_t *end);
|
||||
void Obj_UnlinkCheckpoint(mobj_t *end);
|
||||
void Obj_CheckpointThink(mobj_t *end);
|
||||
|
|
|
|||
|
|
@ -1,9 +1,10 @@
|
|||
#include <algorithm>
|
||||
#include <cstddef>
|
||||
#include <iterator>
|
||||
#include <set>
|
||||
|
||||
#include "../math/fixed.hpp"
|
||||
#include "../mobj.hpp"
|
||||
#include "../mobj_list.hpp"
|
||||
|
||||
#include "../doomdef.h"
|
||||
#include "../m_random.h"
|
||||
|
|
@ -14,6 +15,9 @@
|
|||
|
||||
using srb2::math::Fixed;
|
||||
using srb2::Mobj;
|
||||
using srb2::MobjList;
|
||||
|
||||
extern mobj_t* svg_battleUfoSpawners;
|
||||
|
||||
#define BATTLEUFO_LEG_ZOFFS (3*FRACUNIT) // Spawn height offset from the body
|
||||
#define BATTLEUFO_LEGS (3) // Number of UFO legs to spawn
|
||||
|
|
@ -27,6 +31,10 @@ struct Spawner : Mobj
|
|||
{
|
||||
void thing_args() = delete;
|
||||
INT32 id() const { return this->mobj_t::thing_args[0]; }
|
||||
|
||||
void hnext() = delete;
|
||||
Spawner* next() const { return Mobj::hnext<Spawner>(); }
|
||||
void next(Spawner* n) { Mobj::hnext(n); }
|
||||
};
|
||||
|
||||
struct UFO : Mobj
|
||||
|
|
@ -53,69 +61,43 @@ struct UFO : Mobj
|
|||
}
|
||||
};
|
||||
|
||||
struct SpawnerCompare
|
||||
{
|
||||
bool operator()(const Spawner* a, const Spawner* b) const
|
||||
{
|
||||
return a->id() < b->id();
|
||||
}
|
||||
};
|
||||
|
||||
class SpawnerList
|
||||
{
|
||||
private:
|
||||
std::set<Spawner*, SpawnerCompare> set_;
|
||||
MobjList<Spawner, svg_battleUfoSpawners> list_;
|
||||
|
||||
public:
|
||||
void insert(Spawner* spawner)
|
||||
{
|
||||
auto [it, inserted] = set_.insert(spawner);
|
||||
|
||||
if (inserted)
|
||||
{
|
||||
mobj_t* dummy = nullptr;
|
||||
P_SetTarget(&dummy, spawner);
|
||||
}
|
||||
}
|
||||
|
||||
void erase(Spawner* spawner)
|
||||
{
|
||||
if (set_.erase(spawner))
|
||||
{
|
||||
mobj_t* dummy = spawner;
|
||||
P_SetTarget(&dummy, nullptr);
|
||||
}
|
||||
}
|
||||
void insert(Spawner* spawner) { list_.push_front(spawner); }
|
||||
void erase(Spawner* spawner) { list_.erase(spawner); }
|
||||
|
||||
Spawner* next(INT32 order) const
|
||||
{
|
||||
auto it = std::upper_bound(
|
||||
set_.begin(),
|
||||
set_.end(),
|
||||
order,
|
||||
[](INT32 a, const Spawner* b) { return a < b->id(); }
|
||||
);
|
||||
using T = const Spawner*;
|
||||
|
||||
return it != set_.end() ? *it : *set_.begin();
|
||||
auto it = std::find_if(list_.begin(), list_.end(), [order](T p) { return order < p->id(); });
|
||||
auto min = [&](auto cmp) { return std::min_element(list_.begin(), list_.end(), cmp); };
|
||||
|
||||
return *(it != list_.end()
|
||||
? min([order](T a, T b) { return order < a->id() && a->id() < b->id(); })
|
||||
: min([](T a, T b) { return a->id() < b->id(); }));
|
||||
}
|
||||
|
||||
INT32 random_id() const
|
||||
{
|
||||
if (set_.empty())
|
||||
if (list_.empty())
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
auto it = set_.begin();
|
||||
auto it = list_.begin();
|
||||
std::size_t count = std::distance(it, list_.end());
|
||||
|
||||
std::advance(it, P_RandomKey(PR_BATTLEUFO, set_.size()));
|
||||
|
||||
return (*std::prev(it == set_.begin() ? set_.end() : it))->id();
|
||||
return std::next(it, P_RandomKey(PR_BATTLEUFO, count - 1u))->id();
|
||||
}
|
||||
|
||||
void spawn_ufo() const
|
||||
{
|
||||
if (set_.empty())
|
||||
if (list_.empty())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
|
@ -236,16 +218,11 @@ void Obj_SpawnBattleUFOFromSpawner(void)
|
|||
g_spawners.spawn_ufo();
|
||||
}
|
||||
|
||||
INT32 Obj_GetFirstBattleUFOSpawnerID(void)
|
||||
INT32 Obj_RandomBattleUFOSpawnerID(void)
|
||||
{
|
||||
return g_spawners.random_id();
|
||||
}
|
||||
|
||||
void Obj_ResetUFOSpawners(void)
|
||||
{
|
||||
g_spawners = {};
|
||||
}
|
||||
|
||||
void Obj_BattleUFOBeamThink(mobj_t *beam)
|
||||
{
|
||||
P_SetObjectMomZ(beam, beam->info->speed, true);
|
||||
|
|
|
|||
|
|
@ -8,10 +8,11 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
|
||||
#include <algorithm>
|
||||
#include <vector>
|
||||
|
||||
#include <fmt/format.h>
|
||||
|
||||
#include "../mobj_list.hpp"
|
||||
|
||||
#include "../doomdef.h"
|
||||
#include "../doomtype.h"
|
||||
#include "../info.h"
|
||||
|
|
@ -32,10 +33,13 @@
|
|||
#include "../sounds.h"
|
||||
#include "../tables.h"
|
||||
|
||||
extern mobj_t* svg_checkpoints;
|
||||
|
||||
#define checkpoint_id(o) ((o)->thing_args[0])
|
||||
#define checkpoint_other(o) ((o)->target)
|
||||
#define checkpoint_orb(o) ((o)->tracer)
|
||||
#define checkpoint_arm(o) ((o)->hnext)
|
||||
#define checkpoint_next(o) ((o)->hprev)
|
||||
#define checkpoint_var(o) ((o)->movedir)
|
||||
#define checkpoint_speed(o) ((o)->movecount)
|
||||
#define checkpoint_speed_multiplier(o) ((o)->movefactor)
|
||||
|
|
@ -120,6 +124,9 @@ struct Checkpoint : mobj_t
|
|||
Arm* arm() const { return static_cast<Arm*>(checkpoint_arm(this)); }
|
||||
void arm(Arm* n) { P_SetTarget(&checkpoint_arm(this), n); }
|
||||
|
||||
Checkpoint* next() const { return static_cast<Checkpoint*>(checkpoint_next(this)); }
|
||||
void next(Checkpoint* n) { P_SetTarget(&checkpoint_next(this), n); }
|
||||
|
||||
fixed_t var() const { return checkpoint_var(this); }
|
||||
void var(fixed_t n) { checkpoint_var(this) = n; }
|
||||
|
||||
|
|
@ -391,34 +398,23 @@ private:
|
|||
|
||||
struct CheckpointManager
|
||||
{
|
||||
auto begin() { return vec_.begin(); }
|
||||
auto end() { return vec_.end(); }
|
||||
auto begin() { return list_.begin(); }
|
||||
auto end() { return list_.end(); }
|
||||
|
||||
auto find(INT32 id) { return std::find_if(begin(), end(), [id](Checkpoint* chk) { return chk->id() == id; }); }
|
||||
|
||||
void push_back(Checkpoint* chk) { vec_.push_back(chk); }
|
||||
void push_front(Checkpoint* chk) { list_.push_front(chk); }
|
||||
|
||||
void erase(const Checkpoint* chk)
|
||||
{
|
||||
if (auto it = std::find(vec_.begin(), vec_.end(), chk); it != end())
|
||||
{
|
||||
vec_.erase(it);
|
||||
}
|
||||
}
|
||||
void erase(Checkpoint* chk) { list_.erase(chk); }
|
||||
|
||||
private:
|
||||
std::vector<Checkpoint*> vec_;
|
||||
srb2::MobjList<Checkpoint, svg_checkpoints> list_;
|
||||
};
|
||||
|
||||
CheckpointManager g_checkpoints;
|
||||
|
||||
}; // namespace
|
||||
|
||||
void Obj_ResetCheckpoints(void)
|
||||
{
|
||||
g_checkpoints = {};
|
||||
}
|
||||
|
||||
void Obj_LinkCheckpoint(mobj_t* end)
|
||||
{
|
||||
auto chk = static_cast<Checkpoint*>(end);
|
||||
|
|
@ -456,7 +452,7 @@ void Obj_LinkCheckpoint(mobj_t* end)
|
|||
}
|
||||
else
|
||||
{
|
||||
g_checkpoints.push_back(chk);
|
||||
g_checkpoints.push_front(chk);
|
||||
}
|
||||
|
||||
chk->gingerbread();
|
||||
|
|
@ -464,7 +460,7 @@ void Obj_LinkCheckpoint(mobj_t* end)
|
|||
|
||||
void Obj_UnlinkCheckpoint(mobj_t* end)
|
||||
{
|
||||
auto chk = static_cast<const Checkpoint*>(end);
|
||||
auto chk = static_cast<Checkpoint*>(end);
|
||||
|
||||
g_checkpoints.erase(chk);
|
||||
|
||||
|
|
|
|||
49
src/p_link.cpp
Normal file
49
src/p_link.cpp
Normal file
|
|
@ -0,0 +1,49 @@
|
|||
// DR. ROBOTNIK'S RING RACERS
|
||||
//-----------------------------------------------------------------------------
|
||||
// Copyright (C) 2023 by James Robert Roman
|
||||
//
|
||||
// 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 <functional>
|
||||
#include <initializer_list>
|
||||
|
||||
#include "p_link.h"
|
||||
#include "p_mobj.h"
|
||||
|
||||
|
||||
#define LINK_PACK \
|
||||
svg_battleUfoSpawners,\
|
||||
svg_checkpoints
|
||||
|
||||
|
||||
using link = mobj_t*;
|
||||
using each_ref = std::initializer_list<std::reference_wrapper<mobj_t*>>;
|
||||
|
||||
link LINK_PACK;
|
||||
|
||||
void P_InitMobjPointers(void)
|
||||
{
|
||||
for (mobj_t*& head : each_ref {LINK_PACK})
|
||||
{
|
||||
head = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
void P_SaveMobjPointers(void(*fn)(mobj_t*))
|
||||
{
|
||||
for (mobj_t* head : {LINK_PACK})
|
||||
{
|
||||
fn(head);
|
||||
}
|
||||
}
|
||||
|
||||
void P_LoadMobjPointers(void(*fn)(mobj_t**))
|
||||
{
|
||||
for (mobj_t*& head : each_ref {LINK_PACK})
|
||||
{
|
||||
fn(&head);
|
||||
}
|
||||
}
|
||||
27
src/p_link.h
Normal file
27
src/p_link.h
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
// DR. ROBOTNIK'S RING RACERS
|
||||
//-----------------------------------------------------------------------------
|
||||
// Copyright (C) 2023 by James Robert Roman
|
||||
//
|
||||
// This program is free software distributed under the
|
||||
// terms of the GNU General Public License, version 2.
|
||||
// See the 'LICENSE' file for more details.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#ifndef p_link_h
|
||||
#define p_link_h
|
||||
|
||||
#include "typedef.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
void P_InitMobjPointers(void);
|
||||
void P_SaveMobjPointers(void(*callback)(mobj_t*));
|
||||
void P_LoadMobjPointers(void(*callback)(mobj_t**));
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
#endif
|
||||
|
||||
#endif/*p_link_h*/
|
||||
|
|
@ -36,6 +36,7 @@
|
|||
#include "lua_script.h"
|
||||
#include "p_slopes.h"
|
||||
#include "m_cond.h" // netUnlocked
|
||||
#include "p_link.h"
|
||||
|
||||
// SRB2Kart
|
||||
#include "k_grandprix.h"
|
||||
|
|
@ -50,6 +51,8 @@
|
|||
savedata_t savedata;
|
||||
savedata_cup_t cupsavedata;
|
||||
|
||||
static savebuffer_t *current_savebuffer;
|
||||
|
||||
// Block UINT32s to attempt to ensure that the correct data is
|
||||
// being sent and received
|
||||
#define ARCHIVEBLOCK_MISC 0x7FEEDEED
|
||||
|
|
@ -3839,6 +3842,11 @@ static void SavePolyfadeThinker(savebuffer_t *save, const thinker_t *th, const U
|
|||
WRITEINT32(save->p, ht->timer);
|
||||
}
|
||||
|
||||
static void WriteMobjPointer(mobj_t *mobj)
|
||||
{
|
||||
WRITEUINT32(current_savebuffer->p, SaveMobjnum(mobj));
|
||||
}
|
||||
|
||||
static void P_NetArchiveThinkers(savebuffer_t *save)
|
||||
{
|
||||
const thinker_t *th;
|
||||
|
|
@ -3846,6 +3854,8 @@ static void P_NetArchiveThinkers(savebuffer_t *save)
|
|||
|
||||
WRITEUINT32(save->p, ARCHIVEBLOCK_THINKERS);
|
||||
|
||||
P_SaveMobjPointers(WriteMobjPointer);
|
||||
|
||||
for (i = 0; i < NUM_THINKERLISTS; i++)
|
||||
{
|
||||
UINT32 numsaved = 0;
|
||||
|
|
@ -5238,6 +5248,11 @@ static thinker_t* LoadPolyfadeThinker(savebuffer_t *save, actionf_p1 thinker)
|
|||
return &ht->thinker;
|
||||
}
|
||||
|
||||
static void ReadMobjPointer(mobj_t **mobj_p)
|
||||
{
|
||||
*mobj_p = LoadMobj(READUINT32(current_savebuffer->p));
|
||||
}
|
||||
|
||||
static void P_NetUnArchiveThinkers(savebuffer_t *save)
|
||||
{
|
||||
thinker_t *currentthinker;
|
||||
|
|
@ -5273,6 +5288,8 @@ static void P_NetUnArchiveThinkers(savebuffer_t *save)
|
|||
// we don't want the removed mobjs to come back
|
||||
P_InitThinkers();
|
||||
|
||||
P_LoadMobjPointers(ReadMobjPointer);
|
||||
|
||||
// clear sector thinker pointers so they don't point to non-existant thinkers for all of eternity
|
||||
for (i = 0; i < numsectors; i++)
|
||||
{
|
||||
|
|
@ -5583,12 +5600,19 @@ static mobj_t *RelinkMobj(mobj_t **ptr)
|
|||
return P_SetTarget(ptr, P_FindNewPosition(temp));
|
||||
}
|
||||
|
||||
static void RelinkMobjVoid(mobj_t **ptr)
|
||||
{
|
||||
RelinkMobj(ptr);
|
||||
}
|
||||
|
||||
static void P_RelinkPointers(void)
|
||||
{
|
||||
thinker_t *currentthinker;
|
||||
mobj_t *mobj;
|
||||
UINT32 temp, i;
|
||||
|
||||
P_LoadMobjPointers(RelinkMobjVoid);
|
||||
|
||||
// use info field (value = oldposition) to relink mobjs
|
||||
for (currentthinker = thlist[THINK_MOBJ].next; currentthinker != &thlist[THINK_MOBJ];
|
||||
currentthinker = currentthinker->next)
|
||||
|
|
@ -6648,6 +6672,8 @@ void P_SaveGame(savebuffer_t *save)
|
|||
|
||||
void P_SaveNetGame(savebuffer_t *save, boolean resending)
|
||||
{
|
||||
current_savebuffer = save;
|
||||
|
||||
thinker_t *th;
|
||||
mobj_t *mobj;
|
||||
UINT32 i = 1; // don't start from 0, it'd be confused with a blank pointer otherwise
|
||||
|
|
@ -6724,6 +6750,8 @@ badloadgame:
|
|||
|
||||
boolean P_LoadNetGame(savebuffer_t *save, boolean reloading)
|
||||
{
|
||||
current_savebuffer = save;
|
||||
|
||||
CV_LoadNetVars(&save->p);
|
||||
|
||||
if (!P_NetUnArchiveMisc(save, reloading))
|
||||
|
|
|
|||
|
|
@ -29,6 +29,7 @@
|
|||
#include "r_main.h"
|
||||
#include "r_fps.h"
|
||||
#include "d_clisrv.h" // UpdateChallenges
|
||||
#include "p_link.h"
|
||||
|
||||
// Object place
|
||||
#include "m_cheat.h"
|
||||
|
|
@ -299,8 +300,7 @@ void P_InitThinkers(void)
|
|||
skyboxcenterpnts[i] = skyboxviewpnts[i] = NULL;
|
||||
}
|
||||
|
||||
Obj_ResetUFOSpawners();
|
||||
Obj_ResetCheckpoints();
|
||||
P_InitMobjPointers();
|
||||
}
|
||||
|
||||
//
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue