mirror of
https://github.com/KartKrewDev/RingRacers.git
synced 2026-04-22 02:00:11 +00:00
Hardcode bustable rocks -- Angel Island + Endless Mine
This commit is contained in:
parent
441d526a15
commit
69541b9422
10 changed files with 427 additions and 3 deletions
|
|
@ -4879,6 +4879,17 @@ const char *const STATE_LIST[] = { // array length left dynamic for sanity testi
|
|||
"S_AIZDB6",
|
||||
"S_AIZDB7",
|
||||
"S_AIZDB8",
|
||||
|
||||
// MT_AZROCKS
|
||||
"S_AZROCKS",
|
||||
"S_AZROCKS_RESPAWN",
|
||||
"S_AZROCKS_PARTICLE1",
|
||||
|
||||
// MT_EMROCKS
|
||||
"S_EMROCKS",
|
||||
"S_EMROCKS_RESPAWN",
|
||||
"S_EMROCKS_PARTICLE1",
|
||||
"S_EMROCKS_PARTICLE2",
|
||||
};
|
||||
|
||||
// RegEx to generate this from info.h: ^\tMT_([^,]+), --> \t"MT_\1",
|
||||
|
|
@ -6130,6 +6141,12 @@ const char *const MOBJTYPE_LIST[] = { // array length left dynamic for sanity t
|
|||
"MT_AIZ_TREE",
|
||||
"MT_AIZ_FERN3",
|
||||
"MT_AIZ_DDB",
|
||||
|
||||
"MT_AZROCKS",
|
||||
"MT_AZROCKS_PARTICLE",
|
||||
|
||||
"MT_EMROCKS",
|
||||
"MT_EMROCKS_PARTICLE",
|
||||
};
|
||||
|
||||
const char *const MOBJFLAG_LIST[] = {
|
||||
|
|
|
|||
119
src/info.c
119
src/info.c
|
|
@ -1010,6 +1010,10 @@ char sprnames[NUMSPRITES + 1][5] =
|
|||
"AZR1",
|
||||
"AZR2",
|
||||
|
||||
"EMR1",
|
||||
"EMR2",
|
||||
"EMR3",
|
||||
|
||||
// First person view sprites; this is a sprite so that it can be replaced by a specialized MD2 draw later
|
||||
"VIEW",
|
||||
};
|
||||
|
|
@ -5749,6 +5753,17 @@ state_t states[NUMSTATES] =
|
|||
{SPR_AIZ6, 5, 8, {NULL}, 0, 0, S_AIZDB7}, // S_AIZDB6
|
||||
{SPR_AIZ6, 6, 8, {NULL}, 0, 0, S_AIZDB8}, // S_AIZDB7
|
||||
{SPR_AIZ6, 7, 10, {NULL}, 0, 0, S_AIZDB1}, // S_AIZDB8
|
||||
|
||||
// MT_AZROCKS
|
||||
{SPR_AZR1, 0, -1, {NULL}, 0, 0, S_AZROCKS}, // S_AZROCKS
|
||||
{SPR_NULL, 0, -1, {NULL}, 0, 0, S_AZROCKS}, // S_AZROCKS_RESPAWN
|
||||
{SPR_AZR2, 0, 5*TICRATE, {NULL}, 0, 0, S_NULL}, // S_AZROCKS_PARTICLE1
|
||||
|
||||
// MT_EMROCKS
|
||||
{SPR_EMR1, 0, -1, {NULL}, 0, 0, S_EMROCKS}, // S_EMROCKS
|
||||
{SPR_NULL, 0, -1, {NULL}, 0, 0, S_EMROCKS}, // S_EMROCKS_RESPAWN
|
||||
{SPR_EMR2, 0, 5*TICRATE, {NULL}, 0, 0, S_NULL}, // S_EMROCKS_PARTICLE1
|
||||
{SPR_EMR3, 0, 5*TICRATE, {NULL}, 0, 0, S_NULL}, // S_EMROCKS_PARTICLE2
|
||||
};
|
||||
|
||||
mobjinfo_t mobjinfo[NUMMOBJTYPES] =
|
||||
|
|
@ -32819,6 +32834,110 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
|
|||
MF_SCENERY, // flags
|
||||
S_NULL // raisestate
|
||||
},
|
||||
{ // MT_AZROCKS
|
||||
470, // doomednum
|
||||
S_AZROCKS, // spawnstate
|
||||
1, // spawnhealth
|
||||
S_NULL, // seestate
|
||||
sfx_None, // seesound
|
||||
0, // 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_s3k59, // deathsound
|
||||
0, // speed
|
||||
48*FRACUNIT, // radius
|
||||
96*FRACUNIT, // height
|
||||
0, // dispoffset
|
||||
0, // mass
|
||||
0, // damage
|
||||
sfx_None, // activesound
|
||||
MF_SPECIAL|MF_NOGRAVITY, // flags
|
||||
S_NULL // raisestate
|
||||
},
|
||||
{ // MT_AZROCKS_PARTICLE
|
||||
-1, // doomednum
|
||||
S_AZROCKS_PARTICLE1, // spawnstate
|
||||
1, // spawnhealth
|
||||
S_NULL, // seestate
|
||||
sfx_None, // seesound
|
||||
0, // 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
|
||||
0, // speed
|
||||
16*FRACUNIT, // radius
|
||||
32*FRACUNIT, // height
|
||||
0, // dispoffset
|
||||
0, // mass
|
||||
0, // damage
|
||||
sfx_None, // activesound
|
||||
MF_NOCLIPHEIGHT|MF_SCENERY|MF_NOBLOCKMAP, // flags
|
||||
S_NULL // raisestate
|
||||
},
|
||||
{ // MT_EMROCKS
|
||||
467, // doomednum
|
||||
S_EMROCKS, // spawnstate
|
||||
1, // spawnhealth
|
||||
S_NULL, // seestate
|
||||
sfx_None, // seesound
|
||||
0, // 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_s3k59, // deathsound
|
||||
0, // speed
|
||||
48*FRACUNIT, // radius
|
||||
96*FRACUNIT, // height
|
||||
0, // dispoffset
|
||||
0, // mass
|
||||
0, // damage
|
||||
sfx_None, // activesound
|
||||
MF_SPECIAL|MF_NOGRAVITY, // flags
|
||||
S_NULL // raisestate
|
||||
},
|
||||
{ // MT_EMROCKS_PARTICLE
|
||||
-1, // doomednum
|
||||
S_EMROCKS_PARTICLE1, // spawnstate
|
||||
1, // spawnhealth
|
||||
S_NULL, // seestate
|
||||
sfx_None, // seesound
|
||||
0, // 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
|
||||
0, // speed
|
||||
16*FRACUNIT, // radius
|
||||
32*FRACUNIT, // height
|
||||
0, // dispoffset
|
||||
0, // mass
|
||||
0, // damage
|
||||
sfx_None, // activesound
|
||||
MF_NOCLIPHEIGHT|MF_SCENERY|MF_NOBLOCKMAP, // flags
|
||||
S_NULL // raisestate
|
||||
},
|
||||
};
|
||||
|
||||
|
||||
|
|
|
|||
21
src/info.h
21
src/info.h
|
|
@ -1564,6 +1564,10 @@ typedef enum sprite
|
|||
SPR_AZR1,
|
||||
SPR_AZR2,
|
||||
|
||||
SPR_EMR1,
|
||||
SPR_EMR2,
|
||||
SPR_EMR3,
|
||||
|
||||
// First person view sprites; this is a sprite so that it can be replaced by a specialized MD2 draw later
|
||||
SPR_VIEW,
|
||||
|
||||
|
|
@ -6174,6 +6178,17 @@ typedef enum state
|
|||
S_AIZDB7,
|
||||
S_AIZDB8,
|
||||
|
||||
// MT_AZROCKS
|
||||
S_AZROCKS,
|
||||
S_AZROCKS_RESPAWN,
|
||||
S_AZROCKS_PARTICLE1,
|
||||
|
||||
// MT_EMROCKS
|
||||
S_EMROCKS,
|
||||
S_EMROCKS_RESPAWN,
|
||||
S_EMROCKS_PARTICLE1,
|
||||
S_EMROCKS_PARTICLE2,
|
||||
|
||||
S_FIRSTFREESLOT,
|
||||
S_LASTFREESLOT = S_FIRSTFREESLOT + NUMSTATEFREESLOTS - 1,
|
||||
NUMSTATES
|
||||
|
|
@ -7445,6 +7460,12 @@ typedef enum mobj_type
|
|||
MT_AIZ_FERN3,
|
||||
MT_AIZ_DDB,
|
||||
|
||||
MT_AZROCKS,
|
||||
MT_AZROCKS_PARTICLE,
|
||||
|
||||
MT_EMROCKS,
|
||||
MT_EMROCKS_PARTICLE,
|
||||
|
||||
MT_FIRSTFREESLOT,
|
||||
MT_LASTFREESLOT = MT_FIRSTFREESLOT + NUMMOBJFREESLOTS - 1,
|
||||
NUMMOBJTYPES
|
||||
|
|
|
|||
|
|
@ -339,6 +339,13 @@ void Obj_FuelCanisterTouch(mobj_t *special, mobj_t *toucher);
|
|||
void Obj_FuelCanisterExplosionTouch(mobj_t *special, mobj_t *toucher);
|
||||
boolean Obj_FuelCanisterExplosionThink(mobj_t *mo);
|
||||
|
||||
/* Bustable Rocks */
|
||||
void Obj_LinkRocks(mobj_t *mo);
|
||||
void Obj_UnlinkRocks(mobj_t *mo);
|
||||
void Obj_TouchRocks(mobj_t *special, mobj_t *toucher);
|
||||
void Obj_UpdateRocks(void);
|
||||
void Obj_AnimateEndlessMineRocks(mobj_t *mo);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -47,6 +47,7 @@ target_sources(SRB2SDL2 PRIVATE
|
|||
crate.cpp
|
||||
spear.cpp
|
||||
fuel.cpp
|
||||
rocks.cpp
|
||||
)
|
||||
|
||||
add_subdirectory(versus)
|
||||
|
|
|
|||
210
src/objects/rocks.cpp
Normal file
210
src/objects/rocks.cpp
Normal file
|
|
@ -0,0 +1,210 @@
|
|||
// DR. ROBOTNIK'S RING RACERS
|
||||
//-----------------------------------------------------------------------------
|
||||
// Copyright (C) 2023 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.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
// Original Lua script by Sal
|
||||
// Hardcoded by jartha
|
||||
|
||||
#include <array>
|
||||
#include <cstdlib>
|
||||
|
||||
#include "../math/fixed.hpp"
|
||||
#include "../math/vec.hpp"
|
||||
#include "../mobj.hpp"
|
||||
#include "../mobj_list.hpp"
|
||||
|
||||
#include "../d_player.h"
|
||||
#include "../doomstat.h"
|
||||
#include "../info.h"
|
||||
#include "../k_objects.h"
|
||||
#include "../m_fixed.h"
|
||||
#include "../p_pspr.h"
|
||||
#include "../sounds.h"
|
||||
#include "../tables.h"
|
||||
|
||||
using srb2::Mobj;
|
||||
using srb2::MobjList;
|
||||
using srb2::math::Fixed;
|
||||
using srb2::math::Vec2;
|
||||
|
||||
extern mobj_t* svg_rocks;
|
||||
|
||||
namespace
|
||||
{
|
||||
|
||||
struct AngelIsland
|
||||
{
|
||||
static constexpr statenum_t kRespawnState = S_AZROCKS_RESPAWN;
|
||||
static constexpr mobjtype_t kParticleType = MT_AZROCKS_PARTICLE;
|
||||
static constexpr std::array<statenum_t, 2> kParticleStates = {S_AZROCKS_PARTICLE1, S_AZROCKS_PARTICLE1};
|
||||
};
|
||||
|
||||
struct EndlessMine
|
||||
{
|
||||
static constexpr statenum_t kRespawnState = S_EMROCKS_RESPAWN;
|
||||
static constexpr mobjtype_t kParticleType = MT_EMROCKS_PARTICLE;
|
||||
static constexpr std::array<statenum_t, 2> kParticleStates = {S_EMROCKS_PARTICLE1, S_EMROCKS_PARTICLE2};
|
||||
};
|
||||
|
||||
struct AnyRocks : Mobj
|
||||
{
|
||||
void hnext() = delete;
|
||||
AnyRocks* next() const { return Mobj::hnext<AnyRocks>(); }
|
||||
void next(AnyRocks* n) { Mobj::hnext(n); }
|
||||
|
||||
template <typename F>
|
||||
bool visit(F&& visitor);
|
||||
};
|
||||
|
||||
template <class Config>
|
||||
struct Rocks : AnyRocks
|
||||
{
|
||||
bool busted() const { return state()->num() == Config::kRespawnState; }
|
||||
|
||||
void respawn()
|
||||
{
|
||||
if (busted())
|
||||
{
|
||||
tics = 2; // respawn soon
|
||||
}
|
||||
}
|
||||
|
||||
void touch(Mobj* toucher)
|
||||
{
|
||||
if (busted())
|
||||
{
|
||||
if (tics > 0)
|
||||
{
|
||||
tics = 2; // postpone respawn
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
slow(toucher);
|
||||
bust(toucher);
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
static void slow(Mobj* toucher)
|
||||
{
|
||||
const player_t* p = toucher->player;
|
||||
|
||||
if (p->sneakertimer || p->invincibilitytimer || p->growshrinktimer > 0 || p->hyudorotimer)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
toucher->momx /= 2;
|
||||
toucher->momy /= 2;
|
||||
toucher->momz = toucher->flip(std::abs(2 * toucher->momz / 3));
|
||||
}
|
||||
|
||||
void bust(Mobj* toucher)
|
||||
{
|
||||
vfx(toucher, 1);
|
||||
vfx(toucher, 2);
|
||||
vfx(toucher, 3);
|
||||
|
||||
voice(info->deathsound);
|
||||
state(Config::kRespawnState);
|
||||
}
|
||||
|
||||
void vfx(Mobj* toucher, int i)
|
||||
{
|
||||
fixed_t zvar = flip((i + 1) * 4 * mapobjectscale);
|
||||
angle_t avar = ANGLE_45 * (i - 2);
|
||||
|
||||
auto part = [&](angle_t angle, statenum_t state)
|
||||
{
|
||||
Mobj* h = spawn_from<Mobj>({Vec2<Fixed> {}, zvar}, Config::kParticleType);
|
||||
h->state(state);
|
||||
h->angle = angle;
|
||||
h->instathrust(angle, 4 * mapobjectscale);
|
||||
h->momz = zvar;
|
||||
return h;
|
||||
};
|
||||
|
||||
static_assert(Config::kParticleStates.size() == 2);
|
||||
|
||||
part(toucher->angle + ANGLE_90 - avar, Config::kParticleStates[0]);
|
||||
part(toucher->angle - ANGLE_90 + avar, Config::kParticleStates[1]);
|
||||
}
|
||||
};
|
||||
|
||||
struct AngelIslandRocks : Rocks<AngelIsland>
|
||||
{
|
||||
};
|
||||
|
||||
struct EndlessMineRocks : Rocks<EndlessMine>
|
||||
{
|
||||
};
|
||||
|
||||
template <typename F>
|
||||
bool AnyRocks::visit(F&& visitor)
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
case MT_AZROCKS:
|
||||
visitor(static_cast<AngelIslandRocks*>(this));
|
||||
break;
|
||||
|
||||
case MT_EMROCKS:
|
||||
visitor(static_cast<EndlessMineRocks*>(this));
|
||||
break;
|
||||
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
MobjList<AnyRocks, svg_rocks> rocks_list;
|
||||
|
||||
}; // namespace
|
||||
|
||||
void Obj_LinkRocks(mobj_t* mo)
|
||||
{
|
||||
rocks_list.push_front(static_cast<AnyRocks*>(mo));
|
||||
}
|
||||
|
||||
void Obj_UnlinkRocks(mobj_t* mo)
|
||||
{
|
||||
rocks_list.erase(static_cast<AnyRocks*>(mo));
|
||||
}
|
||||
|
||||
void Obj_TouchRocks(mobj_t* special, mobj_t* toucher)
|
||||
{
|
||||
static_cast<AnyRocks*>(special)->visit([&](auto rocks) { rocks->touch(static_cast<Mobj*>(toucher)); });
|
||||
}
|
||||
|
||||
void Obj_UpdateRocks(void)
|
||||
{
|
||||
for (AnyRocks* h : rocks_list)
|
||||
{
|
||||
h->visit([](auto rocks) { rocks->respawn(); });
|
||||
}
|
||||
}
|
||||
|
||||
void Obj_AnimateEndlessMineRocks(mobj_t *mo)
|
||||
{
|
||||
// sync colors with sky animation
|
||||
constexpr int kFrames = 8;
|
||||
constexpr int kDiff = kFrames - 2;
|
||||
constexpr int kTotal = kFrames + kDiff;
|
||||
|
||||
UINT8 f = ((leveltime / 6) % kTotal);
|
||||
|
||||
if (f >= kFrames)
|
||||
{
|
||||
f = kTotal - f;
|
||||
}
|
||||
|
||||
mo->frame = (mo->frame & ~FF_FRAMEMASK) | f;
|
||||
}
|
||||
|
|
@ -1007,6 +1007,13 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck)
|
|||
return;
|
||||
}
|
||||
|
||||
case MT_AZROCKS:
|
||||
case MT_EMROCKS:
|
||||
{
|
||||
Obj_TouchRocks(special, toucher);
|
||||
return;
|
||||
}
|
||||
|
||||
default: // SOC or script pickup
|
||||
P_SetTarget(&special->target, toucher);
|
||||
break;
|
||||
|
|
|
|||
|
|
@ -16,7 +16,8 @@
|
|||
|
||||
#define LINK_PACK \
|
||||
svg_battleUfoSpawners,\
|
||||
svg_checkpoints
|
||||
svg_checkpoints,\
|
||||
svg_rocks
|
||||
|
||||
|
||||
using link = mobj_t*;
|
||||
|
|
|
|||
29
src/p_mobj.c
29
src/p_mobj.c
|
|
@ -3156,6 +3156,15 @@ boolean P_SceneryZMovement(mobj_t *mo)
|
|||
return false;
|
||||
}
|
||||
break;
|
||||
case MT_EMROCKS_PARTICLE:
|
||||
// Hits the ground
|
||||
if (mo->momz <= 0 && mo->z + mo->momz <= mo->floorz - mo->height)
|
||||
{
|
||||
P_KillMobj(mo, NULL, NULL, DMG_NORMAL);
|
||||
if (P_MobjWasRemoved(mo))
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
|
@ -6880,6 +6889,11 @@ static void P_MobjSceneryThink(mobj_t *mobj)
|
|||
}
|
||||
break;
|
||||
}
|
||||
case MT_EMROCKS_PARTICLE:
|
||||
{
|
||||
Obj_AnimateEndlessMineRocks(mobj);
|
||||
break;
|
||||
}
|
||||
case MT_VWREF:
|
||||
case MT_VWREB:
|
||||
{
|
||||
|
|
@ -10285,6 +10299,11 @@ static boolean P_MobjRegularThink(mobj_t *mobj)
|
|||
}
|
||||
break;
|
||||
}
|
||||
case MT_EMROCKS:
|
||||
{
|
||||
Obj_AnimateEndlessMineRocks(mobj);
|
||||
break;
|
||||
}
|
||||
|
||||
case MT_BALLOON:
|
||||
{
|
||||
|
|
@ -11793,6 +11812,10 @@ mobj_t *P_SpawnMobj(fixed_t x, fixed_t y, fixed_t z, mobjtype_t type)
|
|||
case MT_GPZ_SEASAW_SPAWN:
|
||||
Obj_GPZSeasawSpawn(mobj);
|
||||
break;
|
||||
case MT_AZROCKS:
|
||||
case MT_EMROCKS:
|
||||
Obj_LinkRocks(mobj);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
|
@ -12067,6 +12090,12 @@ void P_RemoveMobj(mobj_t *mobj)
|
|||
Obj_UnlinkCheckpoint(mobj);
|
||||
break;
|
||||
}
|
||||
case MT_AZROCKS:
|
||||
case MT_EMROCKS:
|
||||
{
|
||||
Obj_UnlinkRocks(mobj);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
break;
|
||||
|
|
|
|||
16
src/p_spec.c
16
src/p_spec.c
|
|
@ -1933,12 +1933,14 @@ static void K_HandleLapIncrement(player_t *player)
|
|||
{
|
||||
size_t i = 0;
|
||||
UINT8 nump = 0;
|
||||
UINT8 lowestLap;
|
||||
UINT8 lowestLap = UINT8_MAX;
|
||||
|
||||
for (i = 0; i < MAXPLAYERS; i++)
|
||||
{
|
||||
if (!playeringame[i] || players[i].spectator)
|
||||
continue;
|
||||
if (players[i].laps < lowestLap)
|
||||
lowestLap = players[i].laps;
|
||||
nump++;
|
||||
}
|
||||
|
||||
|
|
@ -2090,7 +2092,17 @@ static void K_HandleLapIncrement(player_t *player)
|
|||
}
|
||||
|
||||
thwompsactive = true; // Lap 2 effects
|
||||
lowestLap = P_FindLowestLap();
|
||||
|
||||
{
|
||||
UINT8 prevLowest = lowestLap;
|
||||
|
||||
lowestLap = P_FindLowestLap();
|
||||
|
||||
if (lowestLap > prevLowest) // last place finished the lap
|
||||
{
|
||||
Obj_UpdateRocks();
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < numlines; i++)
|
||||
{
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue