mirror of
https://github.com/KartKrewDev/RingRacers.git
synced 2026-04-27 20:41:46 +00:00
Merge branch 'hardcode-lost-colony' into 'master'
Hardcode Lost Colony Fuel Canisters See merge request KartKrew/Kart!1681
This commit is contained in:
commit
49b09a3cf5
14 changed files with 582 additions and 80 deletions
|
|
@ -4860,6 +4860,10 @@ const char *const STATE_LIST[] = { // array length left dynamic for sanity testi
|
||||||
// MT_BSZSLAMP
|
// MT_BSZSLAMP
|
||||||
"S_BSWL",
|
"S_BSWL",
|
||||||
"S_BSWC",
|
"S_BSWC",
|
||||||
|
|
||||||
|
"S_BETA_PARTICLE_WHEEL",
|
||||||
|
"S_BETA_PARTICLE_ICON",
|
||||||
|
"S_BETA_PARTICLE_EXPLOSION",
|
||||||
};
|
};
|
||||||
|
|
||||||
// RegEx to generate this from info.h: ^\tMT_([^,]+), --> \t"MT_\1",
|
// RegEx to generate this from info.h: ^\tMT_([^,]+), --> \t"MT_\1",
|
||||||
|
|
@ -6099,6 +6103,11 @@ const char *const MOBJTYPE_LIST[] = { // array length left dynamic for sanity t
|
||||||
"MT_BSZLAMP_L",
|
"MT_BSZLAMP_L",
|
||||||
"MT_BSZSLAMP",
|
"MT_BSZSLAMP",
|
||||||
"MT_BSZSLCHA",
|
"MT_BSZSLCHA",
|
||||||
|
|
||||||
|
"MT_BETA_EMITTER",
|
||||||
|
"MT_BETA_PARTICLE_PHYSICAL",
|
||||||
|
"MT_BETA_PARTICLE_VISUAL",
|
||||||
|
"MT_BETA_PARTICLE_EXPLOSION",
|
||||||
};
|
};
|
||||||
|
|
||||||
const char *const MOBJFLAG_LIST[] = {
|
const char *const MOBJFLAG_LIST[] = {
|
||||||
|
|
|
||||||
114
src/info.c
114
src/info.c
|
|
@ -999,6 +999,8 @@ char sprnames[NUMSPRITES + 1][5] =
|
||||||
"BSWL",
|
"BSWL",
|
||||||
"BSWC",
|
"BSWC",
|
||||||
|
|
||||||
|
"LCLA",
|
||||||
|
|
||||||
// First person view sprites; this is a sprite so that it can be replaced by a specialized MD2 draw later
|
// First person view sprites; this is a sprite so that it can be replaced by a specialized MD2 draw later
|
||||||
"VIEW",
|
"VIEW",
|
||||||
};
|
};
|
||||||
|
|
@ -5719,6 +5721,10 @@ state_t states[NUMSTATES] =
|
||||||
// MT_BSZSLAMP
|
// MT_BSZSLAMP
|
||||||
{SPR_BSWL, 0|FF_FULLBRIGHT, -1, {NULL}, 0, 0, S_NULL}, // S_BSWL
|
{SPR_BSWL, 0|FF_FULLBRIGHT, -1, {NULL}, 0, 0, S_NULL}, // S_BSWL
|
||||||
{SPR_BSWC, 0|FF_FULLBRIGHT, -1, {NULL}, 0, 0, S_NULL}, // S_BSWC
|
{SPR_BSWC, 0|FF_FULLBRIGHT, -1, {NULL}, 0, 0, S_NULL}, // S_BSWC
|
||||||
|
|
||||||
|
{SPR_LCLA, 0|FF_FULLBRIGHT|FF_PAPERSPRITE, -1, {NULL}, 0, 0, S_NULL}, // S_BETA_PARTICLE_WHEEL
|
||||||
|
{SPR_LCLA, 1|FF_FULLBRIGHT|FF_PAPERSPRITE, -1, {NULL}, 0, 0, S_NULL}, // S_BETA_PARTICLE_ICON
|
||||||
|
{SPR_LCLA, 2|FF_FULLBRIGHT, -1, {NULL}, 0, 0, S_NULL}, // S_BETA_PARTICLE_EXPLOSION
|
||||||
};
|
};
|
||||||
|
|
||||||
mobjinfo_t mobjinfo[NUMMOBJTYPES] =
|
mobjinfo_t mobjinfo[NUMMOBJTYPES] =
|
||||||
|
|
@ -30674,8 +30680,8 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
|
||||||
S_NULL, // xdeathstate
|
S_NULL, // xdeathstate
|
||||||
sfx_None, // deathsound
|
sfx_None, // deathsound
|
||||||
0, // speed
|
0, // speed
|
||||||
0, // radius
|
40*FRACUNIT, // radius
|
||||||
0, // height
|
80*FRACUNIT, // height
|
||||||
0, // display offset
|
0, // display offset
|
||||||
100, // mass
|
100, // mass
|
||||||
1, // damage
|
1, // damage
|
||||||
|
|
@ -32529,6 +32535,110 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
|
||||||
0, // flags
|
0, // flags
|
||||||
S_NULL // raisestate
|
S_NULL // raisestate
|
||||||
},
|
},
|
||||||
|
{ // MT_BETA_EMITTER
|
||||||
|
2699, // doomednum
|
||||||
|
S_INVISIBLE, // 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
|
||||||
|
0, // radius
|
||||||
|
0, // height
|
||||||
|
0, // dispoffset
|
||||||
|
0, // mass
|
||||||
|
0, // damage
|
||||||
|
sfx_None, // activesound
|
||||||
|
MF_NOGRAVITY|MF_NOBLOCKMAP|MF_NOSECTOR|MF_SCENERY, // flags
|
||||||
|
S_NULL // raisestate
|
||||||
|
},
|
||||||
|
{ // MT_BETA_PARTICLE_PHYSICAL
|
||||||
|
-1, // doomednum
|
||||||
|
S_INVISIBLE, // 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
|
||||||
|
24*FRACUNIT, // radius
|
||||||
|
128*FRACUNIT, // height
|
||||||
|
0, // dispoffset
|
||||||
|
0, // mass
|
||||||
|
0, // damage
|
||||||
|
sfx_None, // activesound
|
||||||
|
MF_SPECIAL|MF_NOGRAVITY, // flags
|
||||||
|
S_NULL // raisestate
|
||||||
|
},
|
||||||
|
{ // MT_BETA_PARTICLE_VISUAL
|
||||||
|
-1, // doomednum
|
||||||
|
S_NULL, // 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
|
||||||
|
0, // radius
|
||||||
|
0, // height
|
||||||
|
0, // dispoffset
|
||||||
|
0, // mass
|
||||||
|
0, // damage
|
||||||
|
sfx_None, // activesound
|
||||||
|
MF_NOCLIPTHING|MF_NOCLIPHEIGHT|MF_NOCLIP|MF_SCENERY|MF_NOGRAVITY, // flags
|
||||||
|
S_NULL // raisestate
|
||||||
|
},
|
||||||
|
{ // MT_BETA_PARTICLE_EXPLOSION
|
||||||
|
-1, // doomednum
|
||||||
|
S_BETA_PARTICLE_EXPLOSION, // spawnstate
|
||||||
|
1000, // spawnhealth
|
||||||
|
S_NULL, // seestate
|
||||||
|
sfx_None, // seesound
|
||||||
|
8, // 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
|
||||||
|
40*FRACUNIT, // radius
|
||||||
|
80*FRACUNIT, // height
|
||||||
|
0, // display offset
|
||||||
|
100, // mass
|
||||||
|
1, // damage
|
||||||
|
sfx_None, // activesound
|
||||||
|
MF_NOCLIPHEIGHT|MF_NOGRAVITY|MF_SCENERY|MF_DONTENCOREMAP|MF_NOHITLAGFORME|MF_SPECIAL|MF_DONTPUNT, // flags
|
||||||
|
S_NULL // raisestate
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
11
src/info.h
11
src/info.h
|
|
@ -1553,6 +1553,8 @@ typedef enum sprite
|
||||||
SPR_BSWL,
|
SPR_BSWL,
|
||||||
SPR_BSWC,
|
SPR_BSWC,
|
||||||
|
|
||||||
|
SPR_LCLA,
|
||||||
|
|
||||||
// First person view sprites; this is a sprite so that it can be replaced by a specialized MD2 draw later
|
// First person view sprites; this is a sprite so that it can be replaced by a specialized MD2 draw later
|
||||||
SPR_VIEW,
|
SPR_VIEW,
|
||||||
|
|
||||||
|
|
@ -6144,6 +6146,10 @@ typedef enum state
|
||||||
S_BSWL,
|
S_BSWL,
|
||||||
S_BSWC,
|
S_BSWC,
|
||||||
|
|
||||||
|
S_BETA_PARTICLE_WHEEL,
|
||||||
|
S_BETA_PARTICLE_ICON,
|
||||||
|
S_BETA_PARTICLE_EXPLOSION,
|
||||||
|
|
||||||
S_FIRSTFREESLOT,
|
S_FIRSTFREESLOT,
|
||||||
S_LASTFREESLOT = S_FIRSTFREESLOT + NUMSTATEFREESLOTS - 1,
|
S_LASTFREESLOT = S_FIRSTFREESLOT + NUMSTATEFREESLOTS - 1,
|
||||||
NUMSTATES
|
NUMSTATES
|
||||||
|
|
@ -7403,6 +7409,11 @@ typedef enum mobj_type
|
||||||
MT_BSZSLAMP,
|
MT_BSZSLAMP,
|
||||||
MT_BSZSLCHA,
|
MT_BSZSLCHA,
|
||||||
|
|
||||||
|
MT_BETA_EMITTER,
|
||||||
|
MT_BETA_PARTICLE_PHYSICAL,
|
||||||
|
MT_BETA_PARTICLE_VISUAL,
|
||||||
|
MT_BETA_PARTICLE_EXPLOSION,
|
||||||
|
|
||||||
MT_FIRSTFREESLOT,
|
MT_FIRSTFREESLOT,
|
||||||
MT_LASTFREESLOT = MT_FIRSTFREESLOT + NUMMOBJFREESLOTS - 1,
|
MT_LASTFREESLOT = MT_FIRSTFREESLOT + NUMMOBJFREESLOTS - 1,
|
||||||
NUMMOBJTYPES
|
NUMMOBJTYPES
|
||||||
|
|
|
||||||
|
|
@ -330,6 +330,15 @@ void Obj_TryCrateDamage(mobj_t *target, mobj_t *inflictor);
|
||||||
void Obj_SpearInit(mobj_t *mo);
|
void Obj_SpearInit(mobj_t *mo);
|
||||||
void Obj_SpearThink(mobj_t *mo);
|
void Obj_SpearThink(mobj_t *mo);
|
||||||
|
|
||||||
|
/* Lost Colony Fuel Canister */
|
||||||
|
void Obj_FuelCanisterEmitterInit(mobj_t *mo);
|
||||||
|
boolean Obj_FuelCanisterVisualThink(mobj_t *mo);
|
||||||
|
boolean Obj_FuelCanisterEmitterThink(mobj_t *mo);
|
||||||
|
boolean Obj_FuelCanisterThink(mobj_t *mo);
|
||||||
|
void Obj_FuelCanisterTouch(mobj_t *special, mobj_t *toucher);
|
||||||
|
void Obj_FuelCanisterExplosionTouch(mobj_t *special, mobj_t *toucher);
|
||||||
|
boolean Obj_FuelCanisterExplosionThink(mobj_t *mo);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
} // extern "C"
|
} // extern "C"
|
||||||
#endif
|
#endif
|
||||||
|
|
|
||||||
|
|
@ -8,7 +8,7 @@ target_sources(SRB2SDL2 PRIVATE
|
||||||
orbinaut.c
|
orbinaut.c
|
||||||
jawz.c
|
jawz.c
|
||||||
duel-bomb.c
|
duel-bomb.c
|
||||||
broly.c
|
broly.cpp
|
||||||
ufo.c
|
ufo.c
|
||||||
monitor.c
|
monitor.c
|
||||||
item-spot.c
|
item-spot.c
|
||||||
|
|
@ -46,6 +46,7 @@ target_sources(SRB2SDL2 PRIVATE
|
||||||
ivoball.cpp
|
ivoball.cpp
|
||||||
crate.cpp
|
crate.cpp
|
||||||
spear.cpp
|
spear.cpp
|
||||||
|
fuel.cpp
|
||||||
)
|
)
|
||||||
|
|
||||||
add_subdirectory(versus)
|
add_subdirectory(versus)
|
||||||
|
|
|
||||||
|
|
@ -1,77 +0,0 @@
|
||||||
#include "../doomdef.h"
|
|
||||||
#include "../info.h"
|
|
||||||
#include "../k_kart.h"
|
|
||||||
#include "../k_objects.h"
|
|
||||||
#include "../m_easing.h"
|
|
||||||
#include "../p_local.h"
|
|
||||||
#include "../s_sound.h"
|
|
||||||
|
|
||||||
/* An object may not be visible on the same tic:
|
|
||||||
1) that it spawned
|
|
||||||
2) that it cycles to the next state */
|
|
||||||
#define BUFFER_TICS (2)
|
|
||||||
|
|
||||||
#define broly_duration(o) ((o)->extravalue1)
|
|
||||||
#define broly_maxscale(o) ((o)->extravalue2)
|
|
||||||
|
|
||||||
static inline fixed_t
|
|
||||||
get_unit_linear (const mobj_t *x)
|
|
||||||
{
|
|
||||||
const tic_t t = (x->tics - BUFFER_TICS);
|
|
||||||
|
|
||||||
return t * FRACUNIT / broly_duration(x);
|
|
||||||
}
|
|
||||||
|
|
||||||
mobj_t *
|
|
||||||
Obj_SpawnBrolyKi
|
|
||||||
( mobj_t * source,
|
|
||||||
tic_t duration)
|
|
||||||
{
|
|
||||||
mobj_t *x;
|
|
||||||
|
|
||||||
if (duration <= 0)
|
|
||||||
{
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
x = P_SpawnMobjFromMobj(
|
|
||||||
source, 0, 0, 0, MT_BROLY);
|
|
||||||
|
|
||||||
P_SetTarget(&x->target, source);
|
|
||||||
|
|
||||||
// Shrink into center of source object.
|
|
||||||
x->z = (source->z + source->height / 2);
|
|
||||||
|
|
||||||
x->colorized = true;
|
|
||||||
x->color = source->color;
|
|
||||||
x->hitlag = 0; // do not copy source hitlag
|
|
||||||
|
|
||||||
broly_maxscale(x) = 64 * mapobjectscale;
|
|
||||||
broly_duration(x) = duration;
|
|
||||||
|
|
||||||
x->tics = (duration + BUFFER_TICS);
|
|
||||||
|
|
||||||
K_ReduceVFXForEveryone(x);
|
|
||||||
|
|
||||||
S_StartSound(x, sfx_cdfm74);
|
|
||||||
|
|
||||||
return x;
|
|
||||||
}
|
|
||||||
|
|
||||||
boolean
|
|
||||||
Obj_BrolyKiThink (mobj_t *x)
|
|
||||||
{
|
|
||||||
if (broly_duration(x) <= 0)
|
|
||||||
{
|
|
||||||
P_RemoveMobj(x);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
const fixed_t
|
|
||||||
t = get_unit_linear(x),
|
|
||||||
n = Easing_OutSine(t, 0, broly_maxscale(x));
|
|
||||||
|
|
||||||
P_InstaScale(x, n);
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
38
src/objects/broly.cpp
Normal file
38
src/objects/broly.cpp
Normal file
|
|
@ -0,0 +1,38 @@
|
||||||
|
// 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 "broly.hpp"
|
||||||
|
|
||||||
|
#include "../doomstat.h"
|
||||||
|
#include "../k_kart.h"
|
||||||
|
#include "../sounds.h"
|
||||||
|
|
||||||
|
using namespace srb2::objects;
|
||||||
|
|
||||||
|
mobj_t *
|
||||||
|
Obj_SpawnBrolyKi
|
||||||
|
( mobj_t * source,
|
||||||
|
tic_t duration)
|
||||||
|
{
|
||||||
|
Broly* x = Broly::spawn<Broly>(static_cast<Mobj*>(source), duration, {64 * mapobjectscale, 0});
|
||||||
|
|
||||||
|
x->colorized = true;
|
||||||
|
x->color = source->color;
|
||||||
|
|
||||||
|
K_ReduceVFXForEveryone(x);
|
||||||
|
x->voice(sfx_cdfm74);
|
||||||
|
|
||||||
|
return x;
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean
|
||||||
|
Obj_BrolyKiThink (mobj_t *x)
|
||||||
|
{
|
||||||
|
return static_cast<Broly*>(x)->think();
|
||||||
|
}
|
||||||
96
src/objects/broly.hpp
Normal file
96
src/objects/broly.hpp
Normal file
|
|
@ -0,0 +1,96 @@
|
||||||
|
// 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 objects_broly_hpp
|
||||||
|
#define objects_broly_hpp
|
||||||
|
|
||||||
|
#include <type_traits>
|
||||||
|
|
||||||
|
#include "objects.hpp"
|
||||||
|
|
||||||
|
#include "../info.h"
|
||||||
|
#include "../m_easing.h"
|
||||||
|
|
||||||
|
namespace srb2::objects
|
||||||
|
{
|
||||||
|
|
||||||
|
struct Broly : Mobj
|
||||||
|
{
|
||||||
|
static constexpr mobjtype_t kMobjType = MT_BROLY;
|
||||||
|
|
||||||
|
/* An object may not be visible on the same tic:
|
||||||
|
1) that it spawned
|
||||||
|
2) that it cycles to the next state */
|
||||||
|
static constexpr int kBufferTics = 2;
|
||||||
|
|
||||||
|
void extravalue1() = delete;
|
||||||
|
tic_t duration() const { return mobj_t::extravalue1; }
|
||||||
|
void duration(tic_t n) { mobj_t::extravalue1 = n; }
|
||||||
|
|
||||||
|
void threshold() = delete;
|
||||||
|
void extravalue2() = delete;
|
||||||
|
Vec2<Fixed> size() const { return {mobj_t::threshold, mobj_t::extravalue2}; }
|
||||||
|
void size(const Vec2<Fixed>& n)
|
||||||
|
{
|
||||||
|
mobj_t::threshold = n.x;
|
||||||
|
mobj_t::extravalue2 = n.y;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool valid() const { return duration(); }
|
||||||
|
|
||||||
|
tic_t remaining() const { return tics - kBufferTics; }
|
||||||
|
|
||||||
|
Fixed linear() const { return (remaining() * FRACUNIT) / duration(); }
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
static T* spawn(Mobj* source, tic_t duration, const Vec2<Fixed>& size)
|
||||||
|
{
|
||||||
|
static_assert(std::is_base_of_v<Broly, T>);
|
||||||
|
|
||||||
|
if (duration == 0)
|
||||||
|
{
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
T* x = Mobj::spawn<T>(source->center(), T::kMobjType);
|
||||||
|
|
||||||
|
x->target(source);
|
||||||
|
|
||||||
|
// Shrink into center of source object.
|
||||||
|
x->z -= x->height / 2;
|
||||||
|
|
||||||
|
x->size(size);
|
||||||
|
x->duration(duration);
|
||||||
|
|
||||||
|
x->tics = (duration + kBufferTics);
|
||||||
|
|
||||||
|
return x;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool think()
|
||||||
|
{
|
||||||
|
if (!valid())
|
||||||
|
{
|
||||||
|
remove();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
const Fixed center = z + (height / 2);
|
||||||
|
const Vec2<Fixed> v = size();
|
||||||
|
|
||||||
|
scale(Easing_OutSine(linear(), v.y, v.x));
|
||||||
|
z = center - (height / 2);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
}; // namespace srb2::objects
|
||||||
|
|
||||||
|
#endif/*objects_broly_hpp*/
|
||||||
236
src/objects/fuel.cpp
Normal file
236
src/objects/fuel.cpp
Normal file
|
|
@ -0,0 +1,236 @@
|
||||||
|
// 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 "broly.hpp"
|
||||||
|
#include "objects.hpp"
|
||||||
|
|
||||||
|
#include "../doomdef.h"
|
||||||
|
#include "../doomstat.h"
|
||||||
|
#include "../info.h"
|
||||||
|
#include "../k_objects.h"
|
||||||
|
#include "../sounds.h"
|
||||||
|
#include "../tables.h"
|
||||||
|
|
||||||
|
using namespace srb2::objects;
|
||||||
|
|
||||||
|
namespace
|
||||||
|
{
|
||||||
|
|
||||||
|
struct FuelCanister : Mobj
|
||||||
|
{
|
||||||
|
struct Emitter : Mobj
|
||||||
|
{
|
||||||
|
void thing_args() = delete;
|
||||||
|
tic_t frequency() const { return mobj_t::thing_args[0]; }
|
||||||
|
tic_t initial_timer() const { return mobj_t::thing_args[1]; }
|
||||||
|
|
||||||
|
void extravalue1() = delete;
|
||||||
|
tic_t timer() const { return mobj_t::extravalue1; }
|
||||||
|
void timer(tic_t n) { mobj_t::extravalue1 = n; }
|
||||||
|
|
||||||
|
void init()
|
||||||
|
{
|
||||||
|
timer(initial_timer());
|
||||||
|
}
|
||||||
|
|
||||||
|
bool think()
|
||||||
|
{
|
||||||
|
if (timer() > 0)
|
||||||
|
{
|
||||||
|
timer(timer() - 1);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
timer(frequency());
|
||||||
|
|
||||||
|
FuelCanister::spawn(this);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Vis : Mobj
|
||||||
|
{
|
||||||
|
void extravalue1() = delete;
|
||||||
|
angle_t phys_angle_ofs() const { return mobj_t::extravalue1; }
|
||||||
|
void phys_angle_ofs(angle_t n) { mobj_t::extravalue1 = n; }
|
||||||
|
|
||||||
|
void extravalue2() = delete;
|
||||||
|
angle_t vis_angle_ofs() const { return mobj_t::extravalue2; }
|
||||||
|
void vis_angle_ofs(angle_t n) { mobj_t::extravalue2 = n; }
|
||||||
|
|
||||||
|
bool valid() const { return Mobj::valid() && Mobj::valid(target()); }
|
||||||
|
|
||||||
|
bool think()
|
||||||
|
{
|
||||||
|
if (!valid())
|
||||||
|
{
|
||||||
|
remove();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
const angle_t angleOutward = target()->angle + phys_angle_ofs();
|
||||||
|
|
||||||
|
move_origin({target()->pos2d() + (vector(angleOutward) * Fixed {radius}), target()->z});
|
||||||
|
angle = angleOutward + vis_angle_ofs();
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Explosion : Broly
|
||||||
|
{
|
||||||
|
static constexpr mobjtype_t kMobjType = MT_BETA_PARTICLE_EXPLOSION;
|
||||||
|
|
||||||
|
static Explosion* spawn(Mobj* source)
|
||||||
|
{
|
||||||
|
Explosion* x = Broly::spawn<Explosion>(source, 3*TICRATE, {1, 8 * mapobjectscale});
|
||||||
|
x->voice(sfx_lcfuel);
|
||||||
|
return x;
|
||||||
|
}
|
||||||
|
|
||||||
|
void touch(Mobj* toucher)
|
||||||
|
{
|
||||||
|
if (!P_DamageMobj(toucher, this, this, 1, DMG_NORMAL))
|
||||||
|
{
|
||||||
|
auto& hitlag = toucher->mobj_t::hitlag;
|
||||||
|
|
||||||
|
// Hitlag = remaining duration of explosion
|
||||||
|
if (hitlag >= 0 && hitlag + 0u < remaining())
|
||||||
|
{
|
||||||
|
hitlag = remaining();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool think() { return Broly::think(); }
|
||||||
|
};
|
||||||
|
|
||||||
|
bool valid() const { return Mobj::valid() && momz; }
|
||||||
|
|
||||||
|
static FuelCanister* spawn(Mobj* source)
|
||||||
|
{
|
||||||
|
FuelCanister* caps = source->spawn_from<FuelCanister>({}, MT_BETA_PARTICLE_PHYSICAL);
|
||||||
|
caps->init();
|
||||||
|
return caps;
|
||||||
|
}
|
||||||
|
|
||||||
|
void init()
|
||||||
|
{
|
||||||
|
momz = 8 * scale();
|
||||||
|
z -= momz;
|
||||||
|
|
||||||
|
pieces<Wheel>();
|
||||||
|
pieces<Icon>();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool think()
|
||||||
|
{
|
||||||
|
if (!valid())
|
||||||
|
{
|
||||||
|
remove();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
angle += 8 * ANG1;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void touch(Mobj* toucher)
|
||||||
|
{
|
||||||
|
Explosion::spawn(toucher);
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
struct Wheel
|
||||||
|
{
|
||||||
|
static constexpr int kSides = 6;
|
||||||
|
static constexpr statenum_t kState = S_BETA_PARTICLE_WHEEL;
|
||||||
|
static constexpr int kRadius = 8;
|
||||||
|
static constexpr Fixed kScale = FRACUNIT;
|
||||||
|
static constexpr angle_t kAngleOffset = 0;
|
||||||
|
static constexpr int kZOffset = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Icon
|
||||||
|
{
|
||||||
|
static constexpr int kSides = 2;
|
||||||
|
static constexpr statenum_t kState = S_BETA_PARTICLE_ICON;
|
||||||
|
static constexpr int kRadius = 8;
|
||||||
|
static constexpr Fixed kScale = 3*FRACUNIT/4;
|
||||||
|
static constexpr angle_t kAngleOffset = ANGLE_90;
|
||||||
|
static constexpr int kZOffset = 64;
|
||||||
|
};
|
||||||
|
|
||||||
|
static Vec2<Fixed> vector(angle_t angle) { return {FCOS(angle), FSIN(angle)}; }
|
||||||
|
|
||||||
|
template <class Config>
|
||||||
|
void pieces()
|
||||||
|
{
|
||||||
|
constexpr angle_t kAngleBetween = ANGLE_MAX / Config::kSides;
|
||||||
|
|
||||||
|
const Fixed zOfs = Config::kZOffset * (Fixed {FRACUNIT} / Config::kScale);
|
||||||
|
const Fixed radius = Config::kRadius * scale();
|
||||||
|
const Fixed scale = Config::kScale * this->scale();
|
||||||
|
|
||||||
|
for (int i = 1; i <= Config::kSides; ++i)
|
||||||
|
{
|
||||||
|
angle_t angleOutward = i * kAngleBetween;
|
||||||
|
|
||||||
|
Vis* vis = spawn_from<Vis>({vector(angle + angleOutward) * radius, 0}, MT_BETA_PARTICLE_VISUAL);
|
||||||
|
|
||||||
|
vis->state(Config::kState);
|
||||||
|
vis->target(this);
|
||||||
|
vis->scale(scale);
|
||||||
|
vis->radius = radius;
|
||||||
|
vis->spriteyoffset(zOfs);
|
||||||
|
|
||||||
|
vis->phys_angle_ofs(angleOutward);
|
||||||
|
vis->vis_angle_ofs(Config::kAngleOffset);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
}; // namespace
|
||||||
|
|
||||||
|
void Obj_FuelCanisterEmitterInit(mobj_t *mo)
|
||||||
|
{
|
||||||
|
static_cast<FuelCanister::Emitter*>(mo)->init();
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean Obj_FuelCanisterVisualThink(mobj_t *mo)
|
||||||
|
{
|
||||||
|
return static_cast<FuelCanister::Vis*>(mo)->think();
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean Obj_FuelCanisterEmitterThink(mobj_t *mo)
|
||||||
|
{
|
||||||
|
return static_cast<FuelCanister::Emitter*>(mo)->think();
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean Obj_FuelCanisterThink(mobj_t *mo)
|
||||||
|
{
|
||||||
|
return static_cast<FuelCanister*>(mo)->think();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Obj_FuelCanisterTouch(mobj_t *special, mobj_t *toucher)
|
||||||
|
{
|
||||||
|
static_cast<FuelCanister*>(special)->touch(static_cast<Mobj*>(toucher));
|
||||||
|
}
|
||||||
|
|
||||||
|
void Obj_FuelCanisterExplosionTouch(mobj_t *special, mobj_t *toucher)
|
||||||
|
{
|
||||||
|
static_cast<FuelCanister::Explosion*>(special)->touch(static_cast<Mobj*>(toucher));
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean Obj_FuelCanisterExplosionThink(mobj_t *mo)
|
||||||
|
{
|
||||||
|
return static_cast<FuelCanister::Explosion*>(mo)->think();
|
||||||
|
}
|
||||||
19
src/objects/objects.hpp
Normal file
19
src/objects/objects.hpp
Normal file
|
|
@ -0,0 +1,19 @@
|
||||||
|
#ifndef objects_objects_hpp
|
||||||
|
#define objects_objects_hpp
|
||||||
|
|
||||||
|
#include "../math/fixed.hpp"
|
||||||
|
#include "../math/vec.hpp"
|
||||||
|
#include "../mobj.hpp"
|
||||||
|
|
||||||
|
#include "../k_objects.h"
|
||||||
|
|
||||||
|
namespace srb2::objects
|
||||||
|
{
|
||||||
|
|
||||||
|
using srb2::Mobj;
|
||||||
|
using srb2::math::Fixed;
|
||||||
|
using srb2::math::Vec2;
|
||||||
|
|
||||||
|
}; // namespace srb2::objects
|
||||||
|
|
||||||
|
#endif/*objects_objects_hpp*/
|
||||||
|
|
@ -995,6 +995,18 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case MT_BETA_PARTICLE_PHYSICAL:
|
||||||
|
{
|
||||||
|
Obj_FuelCanisterTouch(special, toucher);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case MT_BETA_PARTICLE_EXPLOSION:
|
||||||
|
{
|
||||||
|
Obj_FuelCanisterExplosionTouch(special, toucher);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
default: // SOC or script pickup
|
default: // SOC or script pickup
|
||||||
P_SetTarget(&special->target, toucher);
|
P_SetTarget(&special->target, toucher);
|
||||||
break;
|
break;
|
||||||
|
|
|
||||||
33
src/p_mobj.c
33
src/p_mobj.c
|
|
@ -6862,6 +6862,24 @@ static void P_MobjSceneryThink(mobj_t *mobj)
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
case MT_BETA_PARTICLE_VISUAL:
|
||||||
|
{
|
||||||
|
Obj_FuelCanisterVisualThink(mobj);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
case MT_BETA_EMITTER:
|
||||||
|
{
|
||||||
|
Obj_FuelCanisterEmitterThink(mobj);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
case MT_BETA_PARTICLE_EXPLOSION:
|
||||||
|
{
|
||||||
|
if (Obj_FuelCanisterExplosionThink(mobj) == false)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
case MT_VWREF:
|
case MT_VWREF:
|
||||||
case MT_VWREB:
|
case MT_VWREB:
|
||||||
{
|
{
|
||||||
|
|
@ -10259,6 +10277,14 @@ static boolean P_MobjRegularThink(mobj_t *mobj)
|
||||||
Obj_SidewaysFreezeThrusterThink(mobj);
|
Obj_SidewaysFreezeThrusterThink(mobj);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case MT_BETA_PARTICLE_PHYSICAL:
|
||||||
|
{
|
||||||
|
if (!Obj_FuelCanisterThink(mobj))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
default:
|
default:
|
||||||
// check mobj against possible water content, before movement code
|
// check mobj against possible water content, before movement code
|
||||||
|
|
@ -11034,6 +11060,8 @@ fixed_t P_GetMobjDefaultScale(mobj_t *mobj)
|
||||||
return 2*FRACUNIT;
|
return 2*FRACUNIT;
|
||||||
case MT_SPEAR:
|
case MT_SPEAR:
|
||||||
return 2*FRACUNIT;
|
return 2*FRACUNIT;
|
||||||
|
case MT_BETA_EMITTER:
|
||||||
|
return 4*FRACUNIT;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
@ -14515,6 +14543,11 @@ static boolean P_SetupSpawnedMapThing(mapthing_t *mthing, mobj_t *mobj)
|
||||||
Obj_SpearInit(mobj);
|
Obj_SpearInit(mobj);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case MT_BETA_EMITTER:
|
||||||
|
{
|
||||||
|
Obj_FuelCanisterEmitterInit(mobj);
|
||||||
|
break;
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1251,6 +1251,8 @@ sfxinfo_t S_sfx[NUMSFX] =
|
||||||
|
|
||||||
{"ivobal", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, // Ivo Ball
|
{"ivobal", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, // Ivo Ball
|
||||||
|
|
||||||
|
{"lcfuel", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Fuel Capsule explodes"},
|
||||||
|
|
||||||
// Damage sounds
|
// Damage sounds
|
||||||
{"dmga1", false, 255, 8, -1, NULL, 0, -1, -1, LUMPERROR, "Damaged"},
|
{"dmga1", false, 255, 8, -1, NULL, 0, -1, -1, LUMPERROR, "Damaged"},
|
||||||
{"dmga2", false, 255, 8, -1, NULL, 0, -1, -1, LUMPERROR, "Damaged"},
|
{"dmga2", false, 255, 8, -1, NULL, 0, -1, -1, LUMPERROR, "Damaged"},
|
||||||
|
|
|
||||||
|
|
@ -1323,6 +1323,9 @@ typedef enum
|
||||||
// Ivo Ball
|
// Ivo Ball
|
||||||
sfx_ivobal,
|
sfx_ivobal,
|
||||||
|
|
||||||
|
// Fuel Capsule
|
||||||
|
sfx_lcfuel,
|
||||||
|
|
||||||
// Damage sounds
|
// Damage sounds
|
||||||
sfx_dmga1,
|
sfx_dmga1,
|
||||||
sfx_dmga2,
|
sfx_dmga2,
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue