mirror of
https://github.com/KartKrewDev/RingRacers.git
synced 2025-10-30 08:01:28 +00:00
Ball switch
This commit is contained in:
parent
0ae5071bbb
commit
643cf46b61
9 changed files with 345 additions and 6 deletions
|
|
@ -4671,6 +4671,11 @@ const char *const STATE_LIST[] = { // array length left dynamic for sanity testi
|
|||
"S_CHECKPOINT_SPARK9",
|
||||
"S_CHECKPOINT_SPARK10",
|
||||
"S_CHECKPOINT_SPARK11",
|
||||
|
||||
"S_BALLSWITCH_BALL",
|
||||
"S_BALLSWITCH_BALL_ACTIVE",
|
||||
"S_BALLSWITCH_PAD",
|
||||
"S_BALLSWITCH_PAD_ACTIVE",
|
||||
};
|
||||
|
||||
// RegEx to generate this from info.h: ^\tMT_([^,]+), --> \t"MT_\1",
|
||||
|
|
@ -5823,6 +5828,9 @@ const char *const MOBJTYPE_LIST[] = { // array length left dynamic for sanity t
|
|||
|
||||
"MT_CHECKPOINT_END",
|
||||
"MT_SCRIPT_THING",
|
||||
|
||||
"MT_BALLSWITCH_BALL",
|
||||
"MT_BALLSWITCH_PAD",
|
||||
};
|
||||
|
||||
const char *const MOBJFLAG_LIST[] = {
|
||||
|
|
|
|||
61
src/info.c
61
src/info.c
|
|
@ -892,6 +892,8 @@ char sprnames[NUMSPRITES + 1][5] =
|
|||
"CPT2", // Checkpoint Stick
|
||||
"CPT3", // Checkpoint Base
|
||||
|
||||
"SA2S", // SA2-style Ball Switch
|
||||
|
||||
// First person view sprites; this is a sprite so that it can be replaced by a specialized MD2 draw later
|
||||
"VIEW",
|
||||
};
|
||||
|
|
@ -5417,6 +5419,11 @@ state_t states[NUMSTATES] =
|
|||
{SPR_SGNS, FF_ADD|FF_FULLBRIGHT|8, 1, {NULL}, 0, 0, S_CHECKPOINT_SPARK10}, // S_CHECKPOINT_SPARK9
|
||||
{SPR_SGNS, FF_ADD|FF_FULLBRIGHT|3, 1, {NULL}, 0, 0, S_CHECKPOINT_SPARK11}, // S_CHECKPOINT_SPARK10
|
||||
{SPR_SGNS, FF_ADD|FF_FULLBRIGHT|2, 1, {NULL}, 0, 0, S_CHECKPOINT_SPARK1}, // S_CHECKPOINT_SPARK11
|
||||
|
||||
{SPR_SA2S, FF_SEMIBRIGHT|3, -1, {NULL}, 0, 0, S_NULL}, // S_BALLSWITCH_BALL
|
||||
{SPR_SA2S, FF_FULLBRIGHT|FF_ANIMATE|FF_GLOBALANIM|4, -1, {NULL}, 1, 1, S_NULL}, // S_BALLSWITCH_BALL_ACTIVE
|
||||
{SPR_SA2S, FF_FLOORSPRITE|FF_SEMIBRIGHT, -1, {NULL}, 0, 0, S_NULL}, // S_BALLSWITCH_PAD
|
||||
{SPR_SA2S, FF_FLOORSPRITE|FF_FULLBRIGHT|FF_ANIMATE|FF_GLOBALANIM|1, -1, {NULL}, 1, 1, S_NULL}, // S_BALLSWITCH_PAD_ACTIVE
|
||||
};
|
||||
|
||||
mobjinfo_t mobjinfo[NUMMOBJTYPES] =
|
||||
|
|
@ -30381,6 +30388,60 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
|
|||
MF_NOBLOCKMAP|MF_NOCLIP|MF_NOCLIPHEIGHT|MF_NOCLIPTHING|MF_NOGRAVITY|MF_SCENERY, // flags
|
||||
S_NULL // raisestate
|
||||
},
|
||||
|
||||
{ // MT_BALLSWITCH_BALL
|
||||
5000, // doomednum
|
||||
S_BALLSWITCH_BALL, // spawnstate
|
||||
1000, // 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
|
||||
36*FRACUNIT, // radius
|
||||
64*FRACUNIT, // height
|
||||
0, // display offset
|
||||
0, // mass
|
||||
0, // damage
|
||||
sfx_None, // activesound
|
||||
MF_SPECIAL|MF_SHOOTABLE|MF_NOGRAVITY, // flags
|
||||
S_NULL // raisestate
|
||||
},
|
||||
|
||||
{ // MT_BALLSWITCH_PAD
|
||||
-1, // doomednum
|
||||
S_BALLSWITCH_PAD, // spawnstate
|
||||
1000, // 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
|
||||
64*FRACUNIT, // radius
|
||||
16*FRACUNIT, // height
|
||||
0, // display offset
|
||||
0, // mass
|
||||
0, // damage
|
||||
sfx_None, // activesound
|
||||
MF_NOBLOCKMAP|MF_NOCLIP|MF_NOCLIPHEIGHT|MF_NOCLIPTHING|MF_NOGRAVITY|MF_SCENERY, // flags
|
||||
S_NULL // raisestate
|
||||
},
|
||||
};
|
||||
|
||||
skincolor_t skincolors[MAXSKINCOLORS] = {
|
||||
|
|
|
|||
10
src/info.h
10
src/info.h
|
|
@ -1446,6 +1446,8 @@ typedef enum sprite
|
|||
SPR_CPT2, // Checkpoint Stick
|
||||
SPR_CPT3, // Checkpoint Base
|
||||
|
||||
SPR_SA2S, // SA2-style Ball Switch
|
||||
|
||||
// First person view sprites; this is a sprite so that it can be replaced by a specialized MD2 draw later
|
||||
SPR_VIEW,
|
||||
|
||||
|
|
@ -5845,6 +5847,11 @@ typedef enum state
|
|||
S_CHECKPOINT_SPARK10,
|
||||
S_CHECKPOINT_SPARK11,
|
||||
|
||||
S_BALLSWITCH_BALL,
|
||||
S_BALLSWITCH_BALL_ACTIVE,
|
||||
S_BALLSWITCH_PAD,
|
||||
S_BALLSWITCH_PAD_ACTIVE,
|
||||
|
||||
S_FIRSTFREESLOT,
|
||||
S_LASTFREESLOT = S_FIRSTFREESLOT + NUMSTATEFREESLOTS - 1,
|
||||
NUMSTATES
|
||||
|
|
@ -7016,6 +7023,9 @@ typedef enum mobj_type
|
|||
MT_CHECKPOINT_END,
|
||||
MT_SCRIPT_THING,
|
||||
|
||||
MT_BALLSWITCH_BALL,
|
||||
MT_BALLSWITCH_PAD,
|
||||
|
||||
MT_FIRSTFREESLOT,
|
||||
MT_LASTFREESLOT = MT_FIRSTFREESLOT + NUMMOBJFREESLOTS - 1,
|
||||
NUMMOBJTYPES
|
||||
|
|
|
|||
|
|
@ -931,16 +931,12 @@ boolean K_InstaWhipCollide(mobj_t *shield, mobj_t *victim)
|
|||
}
|
||||
else
|
||||
{
|
||||
if (victim->type == MT_ORBINAUT || victim->type == MT_JAWZ || victim->type == MT_GACHABOM
|
||||
|| victim->type == MT_BANANA || victim->type == MT_EGGMANITEM || victim->type == MT_BALLHOG
|
||||
|| victim->type == MT_SSMINE || victim->type == MT_LANDMINE || victim->type == MT_SINK
|
||||
|| victim->type == MT_GARDENTOP || victim->type == MT_DROPTARGET || victim->type == MT_BATTLECAPSULE
|
||||
|| victim->type == MT_MONITOR || victim->type == MT_SPECIAL_UFO || victim->type == MT_BATTLEUFO)
|
||||
if (victim->flags & MF_SHOOTABLE)
|
||||
{
|
||||
// Monitor hack. We can hit monitors once per instawhip, no multihit shredding!
|
||||
// Damage values in Obj_MonitorGetDamage.
|
||||
// Apply to UFO also -- steelt 29062023
|
||||
if (victim->type == MT_MONITOR || victim->type == MT_BATTLEUFO)
|
||||
if (victim->type == MT_MONITOR || victim->type == MT_BATTLEUFO || victim->type == MT_BALLSWITCH_BALL)
|
||||
{
|
||||
if (shield->extravalue1 == 1)
|
||||
return false;
|
||||
|
|
|
|||
|
|
@ -233,6 +233,12 @@ boolean Obj_GetCheckpointRespawnPosition(const mobj_t *checkpoint, vector3_t *re
|
|||
angle_t Obj_GetCheckpointRespawnAngle(const mobj_t *checkpoint);
|
||||
void Obj_ActivateCheckpointInstantly(mobj_t* mobj);
|
||||
|
||||
/* Ball Switch */
|
||||
void Obj_BallSwitchInit(mobj_t *mobj);
|
||||
void Obj_BallSwitchThink(mobj_t *mobj);
|
||||
void Obj_BallSwitchTouched(mobj_t *mobj, mobj_t *toucher);
|
||||
void Obj_BallSwitchDamaged(mobj_t *mobj, mobj_t *inflictor, mobj_t *source);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -30,4 +30,5 @@ target_sources(SRB2SDL2 PRIVATE
|
|||
emerald.c
|
||||
checkpoint.cpp
|
||||
shadow.cpp
|
||||
ball-switch.cpp
|
||||
)
|
||||
|
|
|
|||
237
src/objects/ball-switch.cpp
Normal file
237
src/objects/ball-switch.cpp
Normal file
|
|
@ -0,0 +1,237 @@
|
|||
#include "../k_objects.h"
|
||||
|
||||
#include "../doomdef.h"
|
||||
#include "../info.h"
|
||||
#include "../p_local.h"
|
||||
#include "../r_main.h"
|
||||
#include "../k_hitlag.h"
|
||||
|
||||
#define ball_pad(o) ((o)->target)
|
||||
#define ball_instawhipped(o) ((o)->extravalue1) // see instawhip collide
|
||||
|
||||
#define ball_cooldown(o) ((o)->cvmem)
|
||||
|
||||
#define ball_activedefer(o) ((o)->extravalue2)
|
||||
#define ball_activator(o) ((o)->tracer)
|
||||
|
||||
namespace
|
||||
{
|
||||
|
||||
struct BallSwitch_Pad : mobj_t
|
||||
{
|
||||
statenum_t Anim() const { return static_cast<statenum_t>(this->state - states); }
|
||||
void Anim(statenum_t n)
|
||||
{
|
||||
if (Anim() != n)
|
||||
{
|
||||
P_SetMobjState(this, n);
|
||||
}
|
||||
}
|
||||
|
||||
void Spawned()
|
||||
{
|
||||
renderflags |= RF_FLOORSPRITE|RF_NOSPLATBILLBOARD|RF_SLOPESPLAT|RF_NOSPLATROLLANGLE;
|
||||
}
|
||||
|
||||
void Tick(boolean active)
|
||||
{
|
||||
if (active == true)
|
||||
{
|
||||
Anim(S_BALLSWITCH_PAD_ACTIVE);
|
||||
}
|
||||
else
|
||||
{
|
||||
Anim(S_BALLSWITCH_PAD);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
struct BallSwitch_Ball : mobj_t
|
||||
{
|
||||
BallSwitch_Pad *Pad() const { return static_cast<BallSwitch_Pad *>( ball_pad(this) ); }
|
||||
void Pad(BallSwitch_Pad *n) { P_SetTarget(&ball_pad(this), n); }
|
||||
|
||||
statenum_t Anim() const { return static_cast<statenum_t>(this->state - states); }
|
||||
void Anim(statenum_t n)
|
||||
{
|
||||
if (Anim() != n)
|
||||
{
|
||||
P_SetMobjState(this, n);
|
||||
}
|
||||
}
|
||||
|
||||
INT32 Cooldown() const { return ball_cooldown(this); }
|
||||
void Cooldown(INT32 n) { ball_cooldown(this) = n; }
|
||||
boolean Active() const { return (ball_cooldown(this) != 0); }
|
||||
|
||||
boolean DeferActivation() const { return ball_activedefer(this); }
|
||||
mobj_t *Activator() const { return ball_activator(this); }
|
||||
|
||||
void DeferActivation(boolean n, mobj_t *src)
|
||||
{
|
||||
ball_activedefer(this) = n;
|
||||
P_SetTarget(&ball_activator(this), src);
|
||||
}
|
||||
|
||||
SINT8 IntSign(int value) const
|
||||
{
|
||||
if (value > 0)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (value < 0)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void Spawned()
|
||||
{
|
||||
Pad( static_cast<BallSwitch_Pad *>( P_SpawnMobjFromMobj(this, 0, 0, 0, MT_BALLSWITCH_PAD) ) );
|
||||
Pad()->Spawned();
|
||||
|
||||
this->z += Pad()->height * P_MobjFlip(this);
|
||||
}
|
||||
|
||||
void Tick()
|
||||
{
|
||||
if (P_MobjWasRemoved(Pad()) == true)
|
||||
{
|
||||
P_RemoveMobj(this);
|
||||
return;
|
||||
}
|
||||
|
||||
ball_instawhipped(this) = 0;
|
||||
|
||||
if (DeferActivation() == true)
|
||||
{
|
||||
P_ActivateThingSpecial(this, Activator());
|
||||
Cooldown(-1); // maybe later?
|
||||
DeferActivation(false, nullptr);
|
||||
}
|
||||
|
||||
fixed_t ourZ = P_GetMobjFeet(this);
|
||||
fixed_t theirZ = P_GetMobjHead(Pad());
|
||||
|
||||
fixed_t dist = P_AproxDistance(P_AproxDistance(Pad()->x - this->x, Pad()->y - this->y), theirZ - ourZ);
|
||||
fixed_t move = P_AproxDistance(P_AproxDistance(this->momx, this->momy), this->momz);
|
||||
|
||||
constexpr INT32 accelScale = 4;
|
||||
|
||||
if (dist < accelScale * this->scale && move < accelScale * this->scale)
|
||||
{
|
||||
P_SetOrigin(this, Pad()->x, Pad()->y, theirZ);
|
||||
this->momx = this->momy = this->momz = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
static constexpr const INT32 accel[2] = { FRACUNIT*3/4, FRACUNIT*3/16 };
|
||||
constexpr fixed_t frict = FRACUNIT*99/100;
|
||||
|
||||
this->momx = FixedMul(this->momx, frict);
|
||||
this->momy = FixedMul(this->momy, frict);
|
||||
this->momz = FixedMul(this->momz, frict);
|
||||
|
||||
SINT8 xSign = IntSign(Pad()->x - this->x);
|
||||
SINT8 ySign = IntSign(Pad()->y - this->y);
|
||||
SINT8 zSign = IntSign(theirZ - ourZ);
|
||||
|
||||
boolean xAway = (IntSign(this->momx) == xSign);
|
||||
boolean yAway = (IntSign(this->momy) == ySign);
|
||||
boolean zAway = (IntSign(this->momz) == zSign);
|
||||
|
||||
this->momx += FixedMul(accel[xAway], accelScale * this->scale) * xSign;
|
||||
this->momy += FixedMul(accel[yAway], accelScale * this->scale) * ySign;
|
||||
this->momz += FixedMul(accel[zAway], accelScale * this->scale) * zSign;
|
||||
|
||||
this->angle += FixedAngle(move * 2);
|
||||
if (dist > this->radius * 2)
|
||||
{
|
||||
P_Thrust(this, this->angle, (move / accelScale) * 2 / 3);
|
||||
}
|
||||
}
|
||||
|
||||
if (Active() == true)
|
||||
{
|
||||
INT32 cool = Cooldown();
|
||||
if (cool > 0)
|
||||
{
|
||||
Cooldown(cool - 1);
|
||||
}
|
||||
|
||||
Anim(S_BALLSWITCH_BALL_ACTIVE);
|
||||
}
|
||||
else
|
||||
{
|
||||
Anim(S_BALLSWITCH_BALL);
|
||||
}
|
||||
|
||||
Pad()->Tick(Active());
|
||||
}
|
||||
|
||||
void Push(mobj_t *toucher, const fixed_t pushValue, const fixed_t repelValue)
|
||||
{
|
||||
fixed_t push = FixedMul(pushValue, toucher->scale);
|
||||
fixed_t repel = FixedMul(repelValue, this->scale);
|
||||
|
||||
angle_t thrustAngle = R_PointToAngle2(toucher->x, toucher->y, this->x, this->y);
|
||||
fixed_t thrustAngleCos = FINECOSINE(thrustAngle >> ANGLETOFINESHIFT);
|
||||
fixed_t thrustAngleSin = FINESINE(thrustAngle >> ANGLETOFINESHIFT);
|
||||
|
||||
fixed_t thisZ = this->z + (this->height / 2);
|
||||
fixed_t toucherZ = toucher->z + (toucher->height / 2);
|
||||
|
||||
angle_t thrustPitch = R_PointToAngle2(0, toucherZ, R_PointToDist2(toucher->x, toucher->y, this->x, this->y), thisZ);
|
||||
fixed_t thrustPitchCos = FINECOSINE(thrustPitch >> ANGLETOFINESHIFT);
|
||||
fixed_t thrustPitchSin = FINESINE(thrustPitch >> ANGLETOFINESHIFT);
|
||||
|
||||
this->momx += FixedMul(FixedMul(push, thrustAngleCos), thrustPitchCos);
|
||||
this->momy += FixedMul(FixedMul(push, thrustAngleSin), thrustPitchCos);
|
||||
this->momz += FixedMul(push, thrustPitchSin);
|
||||
|
||||
toucher->momx -= FixedMul(FixedMul(repel, thrustAngleCos), thrustPitchCos);
|
||||
toucher->momy -= FixedMul(FixedMul(repel, thrustAngleSin), thrustPitchCos);
|
||||
toucher->momz -= FixedMul(repel, thrustPitchSin);
|
||||
}
|
||||
|
||||
void Touch(mobj_t *toucher)
|
||||
{
|
||||
Push(toucher, 4 << FRACBITS, 6 << FRACBITS);
|
||||
}
|
||||
|
||||
void Hit(mobj_t *inflictor, mobj_t *source)
|
||||
{
|
||||
Push(inflictor, 64 << FRACBITS, 1 << FRACBITS);
|
||||
K_SetHitLagForObjects(this, inflictor, source, 4, true);
|
||||
DeferActivation(true, source);
|
||||
}
|
||||
};
|
||||
|
||||
}; // namespace
|
||||
|
||||
void Obj_BallSwitchInit(mobj_t *mobj)
|
||||
{
|
||||
BallSwitch_Ball *ball = static_cast<BallSwitch_Ball *>(mobj);
|
||||
ball->Spawned();
|
||||
}
|
||||
|
||||
void Obj_BallSwitchThink(mobj_t *mobj)
|
||||
{
|
||||
BallSwitch_Ball *ball = static_cast<BallSwitch_Ball *>(mobj);
|
||||
ball->Tick();
|
||||
}
|
||||
|
||||
void Obj_BallSwitchTouched(mobj_t *mobj, mobj_t *toucher)
|
||||
{
|
||||
BallSwitch_Ball *ball = static_cast<BallSwitch_Ball *>(mobj);
|
||||
ball->Touch(toucher);
|
||||
}
|
||||
|
||||
void Obj_BallSwitchDamaged(mobj_t *mobj, mobj_t *inflictor, mobj_t *source)
|
||||
{
|
||||
BallSwitch_Ball *ball = static_cast<BallSwitch_Ball *>(mobj);
|
||||
ball->Hit(inflictor, source);
|
||||
}
|
||||
|
|
@ -817,6 +817,12 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck)
|
|||
Obj_DashRingTouch(special, player);
|
||||
return;
|
||||
|
||||
case MT_BALLSWITCH_BALL:
|
||||
{
|
||||
Obj_BallSwitchTouched(special, toucher);
|
||||
return;
|
||||
}
|
||||
|
||||
default: // SOC or script pickup
|
||||
P_SetTarget(&special->target, toucher);
|
||||
break;
|
||||
|
|
@ -2398,6 +2404,12 @@ boolean P_DamageMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 da
|
|||
return false;
|
||||
}
|
||||
|
||||
if (target->type == MT_BALLSWITCH_BALL)
|
||||
{
|
||||
Obj_BallSwitchDamaged(target, inflictor, source);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!force)
|
||||
{
|
||||
if (!spbpop)
|
||||
|
|
|
|||
|
|
@ -9703,6 +9703,11 @@ static boolean P_MobjRegularThink(mobj_t *mobj)
|
|||
case MT_RAINBOWDASHRING:
|
||||
Obj_RainbowDashRingThink(mobj);
|
||||
break;
|
||||
case MT_BALLSWITCH_BALL:
|
||||
{
|
||||
Obj_BallSwitchThink(mobj);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
// check mobj against possible water content, before movement code
|
||||
P_MobjCheckWater(mobj);
|
||||
|
|
@ -11142,6 +11147,9 @@ mobj_t *P_SpawnMobj(fixed_t x, fixed_t y, fixed_t z, mobjtype_t type)
|
|||
case MT_SNEAKERPANELSPAWNER:
|
||||
Obj_SneakerPanelSpawnerSpawn(mobj);
|
||||
break;
|
||||
case MT_BALLSWITCH_BALL:
|
||||
Obj_BallSwitchInit(mobj);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue