mirror of
https://github.com/KartKrewDev/RingRacers.git
synced 2026-04-27 04:21:47 +00:00
Merge branch 'hyudoro-release-prep' into 'master'
Misc. code changes in preparation for Hyudoro final pass + debugcheese cvar See merge request KartKrew/Kart!1503
This commit is contained in:
commit
63db455211
26 changed files with 692 additions and 181 deletions
|
|
@ -773,6 +773,7 @@ extern CV_PossibleValue_t capsuletest_cons_t[];
|
||||||
void CapsuleTest_OnChange(void);
|
void CapsuleTest_OnChange(void);
|
||||||
consvar_t cv_capsuletest = OnlineCheat("capsuletest", "Off").values(capsuletest_cons_t).onchange(CapsuleTest_OnChange).description("Force item capsule spawning rules");
|
consvar_t cv_capsuletest = OnlineCheat("capsuletest", "Off").values(capsuletest_cons_t).onchange(CapsuleTest_OnChange).description("Force item capsule spawning rules");
|
||||||
|
|
||||||
|
consvar_t cv_debugcheese = OnlineCheat("debugcheese", "Off").on_off().description("Disable checks that prevent farming item boxes");
|
||||||
consvar_t cv_debugencorevote = OnlineCheat("debugencorevote", "Off").on_off().description("Force encore choice to appear on vote screen");
|
consvar_t cv_debugencorevote = OnlineCheat("debugencorevote", "Off").on_off().description("Force encore choice to appear on vote screen");
|
||||||
|
|
||||||
void ForceSkin_OnChange(void);
|
void ForceSkin_OnChange(void);
|
||||||
|
|
|
||||||
|
|
@ -78,7 +78,8 @@ typedef enum
|
||||||
PF_KICKSTARTACCEL = 1<<4, // Accessibility feature: Is accelerate in kickstart mode?
|
PF_KICKSTARTACCEL = 1<<4, // Accessibility feature: Is accelerate in kickstart mode?
|
||||||
|
|
||||||
PF_POINTME = 1<<5, // An object is calling for my attention (via Obj_PointPlayersToMobj). Unset every frame!
|
PF_POINTME = 1<<5, // An object is calling for my attention (via Obj_PointPlayersToMobj). Unset every frame!
|
||||||
// 1<<6 free
|
|
||||||
|
PF_CASTSHADOW = 1<<6, // Something is casting a shadow on the player
|
||||||
|
|
||||||
PF_WANTSTOJOIN = 1<<7, // Spectator that wants to join
|
PF_WANTSTOJOIN = 1<<7, // Spectator that wants to join
|
||||||
|
|
||||||
|
|
@ -442,6 +443,7 @@ struct itemroulette_t
|
||||||
boolean eggman;
|
boolean eggman;
|
||||||
boolean ringbox;
|
boolean ringbox;
|
||||||
boolean autoroulette;
|
boolean autoroulette;
|
||||||
|
UINT8 reserved;
|
||||||
};
|
};
|
||||||
|
|
||||||
// enum for bot item priorities
|
// enum for bot item priorities
|
||||||
|
|
|
||||||
|
|
@ -3792,6 +3792,7 @@ const char *const STATE_LIST[] = { // array length left dynamic for sanity testi
|
||||||
|
|
||||||
// Caked-Up Booty-Sheet Ghost
|
// Caked-Up Booty-Sheet Ghost
|
||||||
"S_HYUDORO",
|
"S_HYUDORO",
|
||||||
|
"S_HYUDORO_RETURNING",
|
||||||
|
|
||||||
// Grow
|
// Grow
|
||||||
"S_GROW_PARTICLE",
|
"S_GROW_PARTICLE",
|
||||||
|
|
@ -5923,8 +5924,8 @@ const char *const MAPTHINGFLAG_LIST[4] = {
|
||||||
const char *const PLAYERFLAG_LIST[] = {
|
const char *const PLAYERFLAG_LIST[] = {
|
||||||
"GODMODE",
|
"GODMODE",
|
||||||
|
|
||||||
// free: 1<<1 and 1<<2 (name un-matchable)
|
"\x01", // free: 1<<1 (name un-matchable)
|
||||||
"\x01",
|
|
||||||
"AUTOROULETTE", // Item box accessibility
|
"AUTOROULETTE", // Item box accessibility
|
||||||
|
|
||||||
// Look back VFX has been spawned
|
// Look back VFX has been spawned
|
||||||
|
|
@ -5932,9 +5933,10 @@ const char *const PLAYERFLAG_LIST[] = {
|
||||||
"GAINAX",
|
"GAINAX",
|
||||||
|
|
||||||
// Accessibility and cheats
|
// Accessibility and cheats
|
||||||
"KICKSTARTACCEL", // Is accelerate in kickstart mode?
|
"KICKSTARTACCEL", // Accessibility feature: Is accelerate in kickstart mode?
|
||||||
"GODMODE",
|
"POINTME", // An object is calling for my attention (via Obj_PointPlayersToMobj). Unset every frame!
|
||||||
"NOCLIP",
|
|
||||||
|
"CASTSHADOW", // Something is casting a shadow on the player
|
||||||
|
|
||||||
"WANTSTOJOIN", // Spectator that wants to join
|
"WANTSTOJOIN", // Spectator that wants to join
|
||||||
|
|
||||||
|
|
@ -5966,8 +5968,11 @@ const char *const PLAYERFLAG_LIST[] = {
|
||||||
"HITFINISHLINE", // Already hit the finish line this tic
|
"HITFINISHLINE", // Already hit the finish line this tic
|
||||||
"WRONGWAY", // Moving the wrong way with respect to waypoints?
|
"WRONGWAY", // Moving the wrong way with respect to waypoints?
|
||||||
|
|
||||||
"SHRINKME",
|
"SHRINKME", // "Shrink me" cheat preference
|
||||||
"SHRINKACTIVE",
|
"SHRINKACTIVE", // "Shrink me" cheat is in effect. (Can't be disabled mid-race)
|
||||||
|
|
||||||
|
"VOID", // Removed from reality! When leaving hitlag, reenable visibility+collision and kill speed.
|
||||||
|
"NOFASTFALL", // Has already done ebrake/fastfall behavior for this input. Fastfalling needs a new input to prevent unwanted bounces on unexpected airtime.
|
||||||
|
|
||||||
NULL // stop loop here.
|
NULL // stop loop here.
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -251,7 +251,7 @@ tic_t starttime = 3;
|
||||||
const tic_t bulbtime = TICRATE/2;
|
const tic_t bulbtime = TICRATE/2;
|
||||||
UINT8 numbulbs = 1;
|
UINT8 numbulbs = 1;
|
||||||
|
|
||||||
INT32 hyudorotime = 7*TICRATE;
|
INT32 hyudorotime = 14*TICRATE;
|
||||||
INT32 stealtime = TICRATE/2;
|
INT32 stealtime = TICRATE/2;
|
||||||
INT32 sneakertime = TICRATE + (TICRATE/3);
|
INT32 sneakertime = TICRATE + (TICRATE/3);
|
||||||
INT32 itemtime = 8*TICRATE;
|
INT32 itemtime = 8*TICRATE;
|
||||||
|
|
|
||||||
|
|
@ -4508,6 +4508,7 @@ state_t states[NUMSTATES] =
|
||||||
{SPR_GTAR, FF_FULLBRIGHT|FF_PAPERSPRITE, -1, {NULL}, 5, 2, S_NULL}, // S_GARDENTOPARROW
|
{SPR_GTAR, FF_FULLBRIGHT|FF_PAPERSPRITE, -1, {NULL}, 5, 2, S_NULL}, // S_GARDENTOPARROW
|
||||||
|
|
||||||
{SPR_HYUU, FF_FULLBRIGHT, -1, {NULL}, 0, 0, S_NULL}, // S_HYUDORO
|
{SPR_HYUU, FF_FULLBRIGHT, -1, {NULL}, 0, 0, S_NULL}, // S_HYUDORO
|
||||||
|
{SPR_HYUU, FF_FULLBRIGHT|1, -1, {NULL}, 0, 0, S_NULL}, // S_HYUDORO_RETURNING
|
||||||
|
|
||||||
{SPR_GRWP, FF_FULLBRIGHT|FF_ANIMATE, 13, {NULL}, 7, 1, S_NULL}, // S_GROW_PARTICLE
|
{SPR_GRWP, FF_FULLBRIGHT|FF_ANIMATE, 13, {NULL}, 7, 1, S_NULL}, // S_GROW_PARTICLE
|
||||||
|
|
||||||
|
|
@ -24667,13 +24668,13 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
|
||||||
S_NULL, // xdeathstate
|
S_NULL, // xdeathstate
|
||||||
sfx_None, // deathsound
|
sfx_None, // deathsound
|
||||||
0, // speed
|
0, // speed
|
||||||
32*FRACUNIT, // radius
|
40*FRACUNIT, // radius
|
||||||
24*FRACUNIT, // height
|
80*FRACUNIT, // height
|
||||||
0, // display offset
|
0, // display offset
|
||||||
0, // mass
|
0, // mass
|
||||||
0, // damage
|
0, // damage
|
||||||
sfx_None, // activesound
|
sfx_None, // activesound
|
||||||
MF_SPECIAL|MF_NOCLIP|MF_NOGRAVITY|MF_DONTENCOREMAP|MF_APPLYTERRAIN, // flags
|
MF_SPECIAL|MF_NOCLIP|MF_NOCLIPHEIGHT|MF_NOGRAVITY|MF_DONTENCOREMAP|MF_APPLYTERRAIN|MF_NOSQUISH, // flags
|
||||||
S_NULL // raisestate
|
S_NULL // raisestate
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -4950,6 +4950,7 @@ typedef enum state
|
||||||
|
|
||||||
// Caked-Up Booty-Sheet Ghost
|
// Caked-Up Booty-Sheet Ghost
|
||||||
S_HYUDORO,
|
S_HYUDORO,
|
||||||
|
S_HYUDORO_RETURNING,
|
||||||
|
|
||||||
// Grow
|
// Grow
|
||||||
S_GROW_PARTICLE,
|
S_GROW_PARTICLE,
|
||||||
|
|
|
||||||
|
|
@ -218,7 +218,7 @@ static inline boolean PIT_SSMineChecks(mobj_t *thing)
|
||||||
if (!(thing->flags & MF_SHOOTABLE) || (thing->flags & MF_SCENERY))
|
if (!(thing->flags & MF_SHOOTABLE) || (thing->flags & MF_SCENERY))
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
if (thing->player && thing->player->spectator)
|
if (thing->player && (thing->player->spectator || thing->player->hyudorotimer > 0))
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
if (P_AproxDistance(P_AproxDistance(thing->x - grenade->x, thing->y - grenade->y), thing->z - grenade->z) > explodedist)
|
if (P_AproxDistance(P_AproxDistance(thing->x - grenade->x, thing->y - grenade->y), thing->z - grenade->z) > explodedist)
|
||||||
|
|
|
||||||
|
|
@ -1413,6 +1413,10 @@ static void K_drawKartItem(void)
|
||||||
else
|
else
|
||||||
localpatch[1] = kp_nodraw;
|
localpatch[1] = kp_nodraw;
|
||||||
}
|
}
|
||||||
|
else if (stplyr->itemRoulette.reserved > 0)
|
||||||
|
{
|
||||||
|
localpatch[1] = kp_nodraw;
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (stplyr->itemamount <= 0)
|
if (stplyr->itemamount <= 0)
|
||||||
|
|
|
||||||
|
|
@ -448,7 +448,8 @@ bool is_object_tracking_target(const mobj_t* mobj)
|
||||||
return inDuel == false && battleovertime.enabled;
|
return inDuel == false && battleovertime.enabled;
|
||||||
|
|
||||||
case MT_EMERALD:
|
case MT_EMERALD:
|
||||||
return (specialstageinfo.valid && specialstageinfo.ufo) || is_player_tracking_target();
|
return Obj_EmeraldCanHUDTrack(mobj) &&
|
||||||
|
((specialstageinfo.valid && specialstageinfo.ufo) || is_player_tracking_target());
|
||||||
|
|
||||||
case MT_MONITOR:
|
case MT_MONITOR:
|
||||||
return is_player_tracking_target() && Obj_MonitorGetEmerald(mobj) != 0;
|
return is_player_tracking_target() && Obj_MonitorGetEmerald(mobj) != 0;
|
||||||
|
|
|
||||||
22
src/k_kart.c
22
src/k_kart.c
|
|
@ -4323,7 +4323,11 @@ void K_ApplyTripWire(player_t *player, tripwirestate_t state)
|
||||||
}
|
}
|
||||||
|
|
||||||
player->tripwireState = state;
|
player->tripwireState = state;
|
||||||
|
|
||||||
|
if (player->hyudorotimer <= 0)
|
||||||
|
{
|
||||||
K_AddHitLag(player->mo, 10, false);
|
K_AddHitLag(player->mo, 10, false);
|
||||||
|
}
|
||||||
|
|
||||||
if (state == TRIPSTATE_PASSED && player->spinouttimer &&
|
if (state == TRIPSTATE_PASSED && player->spinouttimer &&
|
||||||
player->speed > 2 * K_GetKartSpeed(player, false, true))
|
player->speed > 2 * K_GetKartSpeed(player, false, true))
|
||||||
|
|
@ -7734,6 +7738,8 @@ void K_KartPlayerThink(player_t *player, ticcmd_t *cmd)
|
||||||
|
|
||||||
player->cameraOffset = 0;
|
player->cameraOffset = 0;
|
||||||
|
|
||||||
|
player->pflags &= ~(PF_CASTSHADOW);
|
||||||
|
|
||||||
if (player->curshield == KSHIELD_TOP)
|
if (player->curshield == KSHIELD_TOP)
|
||||||
{
|
{
|
||||||
mobj_t *top = K_GetGardenTop(player);
|
mobj_t *top = K_GetGardenTop(player);
|
||||||
|
|
@ -11661,23 +11667,19 @@ void K_MoveKartPlayer(player_t *player, boolean onground)
|
||||||
|
|
||||||
if (player->hyudorotimer > 0)
|
if (player->hyudorotimer > 0)
|
||||||
{
|
{
|
||||||
if (leveltime & 1)
|
player->mo->renderflags |= RF_DONTDRAW | RF_MODULATE;
|
||||||
{
|
|
||||||
player->mo->renderflags |= RF_DONTDRAW;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (player->hyudorotimer >= (TICRATE/2) && player->hyudorotimer <= hyudorotime-(TICRATE/2))
|
|
||||||
player->mo->renderflags &= ~K_GetPlayerDontDrawFlag(player);
|
player->mo->renderflags &= ~K_GetPlayerDontDrawFlag(player);
|
||||||
else
|
|
||||||
player->mo->renderflags &= ~RF_DONTDRAW;
|
if (!(leveltime & 1) && (player->hyudorotimer < (TICRATE/2) || player->hyudorotimer > hyudorotime-(TICRATE/2)))
|
||||||
|
{
|
||||||
|
player->mo->renderflags &= ~(RF_DONTDRAW | RF_BLENDMASK);
|
||||||
}
|
}
|
||||||
|
|
||||||
player->flashing = player->hyudorotimer; // We'll do this for now, let's people know about the invisible people through subtle hints
|
player->flashing = player->hyudorotimer; // We'll do this for now, let's people know about the invisible people through subtle hints
|
||||||
}
|
}
|
||||||
else if (player->hyudorotimer == 0)
|
else if (player->hyudorotimer == 0)
|
||||||
{
|
{
|
||||||
player->mo->renderflags &= ~RF_DONTDRAW;
|
player->mo->renderflags &= ~RF_BLENDMASK;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (player->trickpanel == 1)
|
if (player->trickpanel == 1)
|
||||||
|
|
|
||||||
|
|
@ -17,6 +17,7 @@ void Obj_HyudoroDeploy(mobj_t *master);
|
||||||
void Obj_HyudoroThink(mobj_t *actor);
|
void Obj_HyudoroThink(mobj_t *actor);
|
||||||
void Obj_HyudoroCenterThink(mobj_t *actor);
|
void Obj_HyudoroCenterThink(mobj_t *actor);
|
||||||
void Obj_HyudoroCollide(mobj_t *special, mobj_t *toucher);
|
void Obj_HyudoroCollide(mobj_t *special, mobj_t *toucher);
|
||||||
|
boolean Obj_HyudoroShadowZ(mobj_t *actor, fixed_t *return_z, pslope_t **return_slope);
|
||||||
|
|
||||||
/* Garden Top */
|
/* Garden Top */
|
||||||
void Obj_GardenTopDeploy(mobj_t *rider);
|
void Obj_GardenTopDeploy(mobj_t *rider);
|
||||||
|
|
@ -213,6 +214,13 @@ void Obj_EmeraldThink(mobj_t *emerald);
|
||||||
void Obj_EmeraldFlareThink(mobj_t *flare);
|
void Obj_EmeraldFlareThink(mobj_t *flare);
|
||||||
void Obj_BeginEmeraldOrbit(mobj_t *emerald, mobj_t *target, fixed_t radius, INT32 revolution_time, tic_t fuse);
|
void Obj_BeginEmeraldOrbit(mobj_t *emerald, mobj_t *target, fixed_t radius, INT32 revolution_time, tic_t fuse);
|
||||||
void Obj_GiveEmerald(mobj_t *emerald);
|
void Obj_GiveEmerald(mobj_t *emerald);
|
||||||
|
void Obj_SetEmeraldAwardee(mobj_t *emerald, mobj_t *awardee);
|
||||||
|
boolean Obj_EmeraldCanHUDTrack(const mobj_t *emerald);
|
||||||
|
|
||||||
|
/* Fake Shadow */
|
||||||
|
mobj_t *Obj_SpawnFakeShadow(mobj_t *from);
|
||||||
|
void Obj_FakeShadowThink(mobj_t *shadow);
|
||||||
|
boolean Obj_FakeShadowZ(const mobj_t *shadow, fixed_t *return_z, pslope_t **return_slope);
|
||||||
|
|
||||||
/* Checkpoints */
|
/* Checkpoints */
|
||||||
void Obj_ResetCheckpoints(void);
|
void Obj_ResetCheckpoints(void);
|
||||||
|
|
|
||||||
|
|
@ -1509,6 +1509,7 @@ void K_StopRoulette(itemroulette_t *const roulette)
|
||||||
roulette->active = false;
|
roulette->active = false;
|
||||||
roulette->eggman = false;
|
roulette->eggman = false;
|
||||||
roulette->ringbox = false;
|
roulette->ringbox = false;
|
||||||
|
roulette->reserved = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*--------------------------------------------------
|
/*--------------------------------------------------
|
||||||
|
|
@ -1574,6 +1575,12 @@ void K_KartItemRoulette(player_t *const player, ticcmd_t *const cmd)
|
||||||
itemroulette_t *const roulette = &player->itemRoulette;
|
itemroulette_t *const roulette = &player->itemRoulette;
|
||||||
boolean confirmItem = false;
|
boolean confirmItem = false;
|
||||||
|
|
||||||
|
if (roulette->reserved > 0)
|
||||||
|
{
|
||||||
|
roulette->reserved--;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// This makes the roulette cycle through items.
|
// This makes the roulette cycle through items.
|
||||||
// If this isn't active, you shouldn't be here.
|
// If this isn't active, you shouldn't be here.
|
||||||
if (roulette->active == false)
|
if (roulette->active == false)
|
||||||
|
|
|
||||||
|
|
@ -29,4 +29,5 @@ target_sources(SRB2SDL2 PRIVATE
|
||||||
sneaker-panel.c
|
sneaker-panel.c
|
||||||
emerald.c
|
emerald.c
|
||||||
checkpoint.cpp
|
checkpoint.cpp
|
||||||
|
shadow.cpp
|
||||||
)
|
)
|
||||||
|
|
|
||||||
|
|
@ -15,6 +15,8 @@
|
||||||
#define emerald_target_radius(o) ((o)->extravalue2)
|
#define emerald_target_radius(o) ((o)->extravalue2)
|
||||||
#define emerald_z_shift(o) ((o)->reactiontime)
|
#define emerald_z_shift(o) ((o)->reactiontime)
|
||||||
#define emerald_scale_rate(o) ((o)->movefactor)
|
#define emerald_scale_rate(o) ((o)->movefactor)
|
||||||
|
#define emerald_orbit(o) ((o)->target)
|
||||||
|
#define emerald_award(o) ((o)->tracer)
|
||||||
|
|
||||||
// Think of this like EMERALD_SPEED_UP / EMERALD_SPEED_UP_RATE
|
// Think of this like EMERALD_SPEED_UP / EMERALD_SPEED_UP_RATE
|
||||||
#define EMERALD_SPEED_UP (1) // speed up by this much...
|
#define EMERALD_SPEED_UP (1) // speed up by this much...
|
||||||
|
|
@ -84,7 +86,7 @@ static fixed_t get_target_z(mobj_t *emerald)
|
||||||
{
|
{
|
||||||
fixed_t shift = FixedMul(emerald_z_shift(emerald), FRACUNIT - get_suck_factor(emerald));
|
fixed_t shift = FixedMul(emerald_z_shift(emerald), FRACUNIT - get_suck_factor(emerald));
|
||||||
|
|
||||||
return center_of(emerald->target) + get_bob(emerald) + shift;
|
return center_of(emerald_orbit(emerald)) + get_bob(emerald) + shift;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void speed_up(mobj_t *emerald)
|
static void speed_up(mobj_t *emerald)
|
||||||
|
|
@ -116,8 +118,8 @@ static void Obj_EmeraldOrbitPlayer(mobj_t *emerald)
|
||||||
|
|
||||||
P_MoveOrigin(
|
P_MoveOrigin(
|
||||||
emerald,
|
emerald,
|
||||||
emerald->target->x + x,
|
emerald_orbit(emerald)->x + x,
|
||||||
emerald->target->y + y,
|
emerald_orbit(emerald)->y + y,
|
||||||
get_target_z(emerald)
|
get_target_z(emerald)
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
@ -133,9 +135,9 @@ static void Obj_EmeraldOrbitPlayer(mobj_t *emerald)
|
||||||
|
|
||||||
void Obj_EmeraldThink(mobj_t *emerald)
|
void Obj_EmeraldThink(mobj_t *emerald)
|
||||||
{
|
{
|
||||||
if (!P_MobjWasRemoved(emerald->target))
|
if (!P_MobjWasRemoved(emerald_orbit(emerald)))
|
||||||
{
|
{
|
||||||
switch (emerald->target->type)
|
switch (emerald_orbit(emerald)->type)
|
||||||
{
|
{
|
||||||
case MT_SPECIAL_UFO:
|
case MT_SPECIAL_UFO:
|
||||||
Obj_UFOEmeraldThink(emerald);
|
Obj_UFOEmeraldThink(emerald);
|
||||||
|
|
@ -256,7 +258,7 @@ static void spawn_lens_flare(mobj_t *emerald)
|
||||||
mobj_t *flare = P_SpawnMobjFromMobj(emerald, 0, 0, 0, MT_EMERALDFLARE);
|
mobj_t *flare = P_SpawnMobjFromMobj(emerald, 0, 0, 0, MT_EMERALDFLARE);
|
||||||
|
|
||||||
P_SetTarget(&flare->target, emerald);
|
P_SetTarget(&flare->target, emerald);
|
||||||
P_InstaScale(flare, emerald->target->scale);
|
P_InstaScale(flare, emerald_orbit(emerald)->scale);
|
||||||
|
|
||||||
flare->color = emerald->color;
|
flare->color = emerald->color;
|
||||||
flare->colorized = true;
|
flare->colorized = true;
|
||||||
|
|
@ -265,7 +267,7 @@ static void spawn_lens_flare(mobj_t *emerald)
|
||||||
|
|
||||||
// FIXME: linkdraw doesn't work consistently, so I drew it on top of everyting (and through walls)
|
// FIXME: linkdraw doesn't work consistently, so I drew it on top of everyting (and through walls)
|
||||||
#if 0
|
#if 0
|
||||||
P_SetTarget(&flare->tracer, emerald->target);
|
P_SetTarget(&flare->tracer, emerald_orbit(emerald));
|
||||||
flare->flags2 |= MF2_LINKDRAW;
|
flare->flags2 |= MF2_LINKDRAW;
|
||||||
flare->dispoffset = 1000;
|
flare->dispoffset = 1000;
|
||||||
#endif
|
#endif
|
||||||
|
|
@ -273,7 +275,12 @@ static void spawn_lens_flare(mobj_t *emerald)
|
||||||
|
|
||||||
void Obj_BeginEmeraldOrbit(mobj_t *emerald, mobj_t *target, fixed_t radius, INT32 revolution_time, tic_t fuse)
|
void Obj_BeginEmeraldOrbit(mobj_t *emerald, mobj_t *target, fixed_t radius, INT32 revolution_time, tic_t fuse)
|
||||||
{
|
{
|
||||||
P_SetTarget(&emerald->target, target);
|
P_SetTarget(&emerald_orbit(emerald), target);
|
||||||
|
|
||||||
|
if (P_MobjWasRemoved(emerald_award(emerald)))
|
||||||
|
{
|
||||||
|
P_SetTarget(&emerald_award(emerald), target);
|
||||||
|
}
|
||||||
|
|
||||||
emerald_anim_start(emerald) = leveltime;
|
emerald_anim_start(emerald) = leveltime;
|
||||||
emerald_revolution_time(emerald) = revolution_time;
|
emerald_revolution_time(emerald) = revolution_time;
|
||||||
|
|
@ -297,14 +304,9 @@ void Obj_BeginEmeraldOrbit(mobj_t *emerald, mobj_t *target, fixed_t radius, INT3
|
||||||
spawn_lens_flare(emerald);
|
spawn_lens_flare(emerald);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Obj_GiveEmerald(mobj_t *emerald)
|
static void give_player(mobj_t *emerald)
|
||||||
{
|
{
|
||||||
if (P_MobjWasRemoved(emerald->target))
|
player_t *player = emerald_award(emerald)->player;
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
player_t *player = emerald->target->player;
|
|
||||||
|
|
||||||
if (!player)
|
if (!player)
|
||||||
{
|
{
|
||||||
|
|
@ -314,5 +316,51 @@ void Obj_GiveEmerald(mobj_t *emerald)
|
||||||
player->emeralds |= emerald_type(emerald);
|
player->emeralds |= emerald_type(emerald);
|
||||||
K_CheckEmeralds(player);
|
K_CheckEmeralds(player);
|
||||||
|
|
||||||
S_StartSound(emerald->target, emerald->info->deathsound);
|
S_StartSound(emerald_award(emerald), emerald->info->deathsound);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Obj_GiveEmerald(mobj_t *emerald)
|
||||||
|
{
|
||||||
|
if (P_MobjWasRemoved(emerald_orbit(emerald)) || P_MobjWasRemoved(emerald_award(emerald)))
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// FIXME: emerald orbiting behavior should become its own object. For now,
|
||||||
|
// though, enjoy these special conditions!
|
||||||
|
switch (emerald_award(emerald)->type)
|
||||||
|
{
|
||||||
|
case MT_PLAYER:
|
||||||
|
give_player(emerald);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case MT_ITEMCAPSULE: // objects/hyudoro.c
|
||||||
|
// DMG_INSTAKILL to kill it without respawning later
|
||||||
|
P_KillMobj(emerald_award(emerald), emerald_orbit(emerald), emerald_orbit(emerald), DMG_INSTAKILL);
|
||||||
|
|
||||||
|
if (emerald_orbit(emerald)->player)
|
||||||
|
{
|
||||||
|
// Unlock item for stacked Hyudoros
|
||||||
|
emerald_orbit(emerald)->player->itemRoulette.reserved = 0;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Obj_SetEmeraldAwardee(mobj_t *emerald, mobj_t *awardee)
|
||||||
|
{
|
||||||
|
P_SetTarget(&emerald_award(emerald), awardee);
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean Obj_EmeraldCanHUDTrack(const mobj_t *emerald)
|
||||||
|
{
|
||||||
|
if (!P_MobjWasRemoved(emerald_award(emerald)) && emerald_award(emerald)->type == MT_ITEMCAPSULE)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -22,11 +22,13 @@
|
||||||
#include "../s_sound.h"
|
#include "../s_sound.h"
|
||||||
#include "../g_game.h"
|
#include "../g_game.h"
|
||||||
#include "../k_hitlag.h"
|
#include "../k_hitlag.h"
|
||||||
|
#include "../p_slopes.h"
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
HYU_PATROL,
|
HYU_PATROL,
|
||||||
HYU_RETURN,
|
HYU_RETURN,
|
||||||
HYU_HOVER,
|
HYU_HOVER,
|
||||||
|
HYU_ORBIT,
|
||||||
};
|
};
|
||||||
|
|
||||||
// TODO: make these general functions
|
// TODO: make these general functions
|
||||||
|
|
@ -37,34 +39,26 @@ K_GetSpeed (mobj_t *mobj)
|
||||||
return FixedHypot(mobj->momx, mobj->momy);
|
return FixedHypot(mobj->momx, mobj->momy);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
|
||||||
K_ChangePlayerItem
|
|
||||||
( player_t * player,
|
|
||||||
INT32 itemtype,
|
|
||||||
INT32 itemamount)
|
|
||||||
{
|
|
||||||
player->itemtype = itemtype;
|
|
||||||
player->itemamount = itemamount;
|
|
||||||
K_UnsetItemOut(player);
|
|
||||||
}
|
|
||||||
|
|
||||||
#define hyudoro_mode(o) ((o)->extravalue1)
|
#define hyudoro_mode(o) ((o)->extravalue1)
|
||||||
#define hyudoro_itemtype(o) ((o)->movefactor)
|
#define hyudoro_itemtype(o) ((o)->movefactor)
|
||||||
#define hyudoro_itemcount(o) ((o)->movecount)
|
#define hyudoro_itemcount(o) ((o)->movecount)
|
||||||
#define hyudoro_hover_stack(o) ((o)->threshold)
|
#define hyudoro_hover_stack(o) ((o)->threshold)
|
||||||
#define hyudoro_next(o) ((o)->tracer)
|
#define hyudoro_next(o) ((o)->tracer)
|
||||||
#define hyudoro_stackpos(o) ((o)->reactiontime)
|
#define hyudoro_stackpos(o) ((o)->reactiontime)
|
||||||
#define hyudoro_delivered(o) (hyudoro_itemtype(o) == KITEM_NONE)
|
|
||||||
|
|
||||||
// cannot be combined
|
// cannot be combined
|
||||||
#define hyudoro_center(o) ((o)->target)
|
#define hyudoro_center(o) ((o)->target)
|
||||||
#define hyudoro_target(o) ((o)->target)
|
#define hyudoro_target(o) ((o)->target)
|
||||||
|
|
||||||
#define hyudoro_stolefrom(o) ((o)->hnext)
|
#define hyudoro_stolefrom(o) ((o)->hnext)
|
||||||
|
#define hyudoro_capsule(o) ((o)->hprev)
|
||||||
|
#define hyudoro_timer(o) ((o)->movedir)
|
||||||
|
|
||||||
#define hyudoro_center_max_radius(o) ((o)->threshold)
|
#define hyudoro_center_max_radius(o) ((o)->threshold)
|
||||||
#define hyudoro_center_master(o) ((o)->target)
|
#define hyudoro_center_master(o) ((o)->target)
|
||||||
|
|
||||||
|
#define HYU_VISUAL_HEIGHT (24)
|
||||||
|
|
||||||
static angle_t
|
static angle_t
|
||||||
trace_angle (mobj_t *hyu)
|
trace_angle (mobj_t *hyu)
|
||||||
{
|
{
|
||||||
|
|
@ -90,7 +84,8 @@ get_look_angle (mobj_t *thing)
|
||||||
static boolean
|
static boolean
|
||||||
is_hyudoro (mobj_t *thing)
|
is_hyudoro (mobj_t *thing)
|
||||||
{
|
{
|
||||||
return thing && thing->type == MT_HYUDORO;
|
return !P_MobjWasRemoved(thing) &&
|
||||||
|
thing->type == MT_HYUDORO;
|
||||||
}
|
}
|
||||||
|
|
||||||
static mobj_t *
|
static mobj_t *
|
||||||
|
|
@ -115,7 +110,7 @@ sine_bob
|
||||||
angle_t a,
|
angle_t a,
|
||||||
fixed_t sineofs)
|
fixed_t sineofs)
|
||||||
{
|
{
|
||||||
hyu->sprzoff = FixedMul(hyu->height,
|
hyu->sprzoff = FixedMul(HYU_VISUAL_HEIGHT * hyu->scale,
|
||||||
sineofs + FINESINE(a >> ANGLETOFINESHIFT));
|
sineofs + FINESINE(a >> ANGLETOFINESHIFT));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -129,6 +124,13 @@ bob_in_place
|
||||||
(ANGLE_MAX / bob_speed), -(3*FRACUNIT/4));
|
(ANGLE_MAX / bob_speed), -(3*FRACUNIT/4));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
reset_shadow (mobj_t *hyu)
|
||||||
|
{
|
||||||
|
hyu->shadowcolor = 15;
|
||||||
|
hyu->whiteshadow = true;
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
project_hyudoro (mobj_t *hyu)
|
project_hyudoro (mobj_t *hyu)
|
||||||
{
|
{
|
||||||
|
|
@ -150,6 +152,36 @@ project_hyudoro (mobj_t *hyu)
|
||||||
hyu->angle = angle + ANGLE_90;
|
hyu->angle = angle + ANGLE_90;
|
||||||
|
|
||||||
sine_bob(hyu, angle, FRACUNIT);
|
sine_bob(hyu, angle, FRACUNIT);
|
||||||
|
|
||||||
|
hyu->z = P_GetZAt(center->standingslope, hyu->x, hyu->y,
|
||||||
|
P_GetMobjGround(center));
|
||||||
|
|
||||||
|
if (P_IsObjectFlipped(hyu))
|
||||||
|
{
|
||||||
|
hyu->z -= hyu->height;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
rise_thru_stack (mobj_t *hyu)
|
||||||
|
{
|
||||||
|
mobj_t *target = hyudoro_target(hyu);
|
||||||
|
|
||||||
|
fixed_t spacer = ((target->height / 2) +
|
||||||
|
(HYU_VISUAL_HEIGHT * hyu->scale * 2));
|
||||||
|
|
||||||
|
fixed_t sink = hyudoro_stackpos(hyu) * spacer;
|
||||||
|
|
||||||
|
fixed_t zofs = abs(hyu->momz);
|
||||||
|
fixed_t d = (zofs - sink);
|
||||||
|
fixed_t speed = d / 8;
|
||||||
|
|
||||||
|
if (abs(d) < abs(speed))
|
||||||
|
zofs = sink;
|
||||||
|
else
|
||||||
|
zofs -= speed;
|
||||||
|
|
||||||
|
hyu->momz = zofs * P_MobjFlip(target);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
|
@ -161,19 +193,18 @@ project_hyudoro_hover (mobj_t *hyu)
|
||||||
angle_t ang = get_look_angle(target) + ANGLE_67h;
|
angle_t ang = get_look_angle(target) + ANGLE_67h;
|
||||||
fixed_t rad = (target->radius * 2) + hyu->radius;
|
fixed_t rad = (target->radius * 2) + hyu->radius;
|
||||||
|
|
||||||
fixed_t zofs = hyudoro_stackpos(hyu) *
|
|
||||||
((target->height / 2) + (hyu->height * 2));
|
|
||||||
|
|
||||||
P_MoveOrigin(hyu,
|
P_MoveOrigin(hyu,
|
||||||
target->x - P_ReturnThrustX(hyu, ang, rad),
|
target->x - P_ReturnThrustX(hyu, ang, rad),
|
||||||
target->y - P_ReturnThrustY(hyu, ang, rad),
|
target->y - P_ReturnThrustY(hyu, ang, rad),
|
||||||
target->z + (zofs * P_MobjFlip(target)));
|
target->z);
|
||||||
|
|
||||||
// Cancel momentum from HYU_RETURN.
|
// Cancel momentum from HYU_RETURN.
|
||||||
// (And anything else! I don't trust this game!!)
|
// (And anything else! I don't trust this game!!)
|
||||||
hyu->momx = 0;
|
hyu->momx = 0;
|
||||||
hyu->momy = 0;
|
hyu->momy = 0;
|
||||||
|
|
||||||
|
rise_thru_stack(hyu);
|
||||||
|
|
||||||
hyu->angle = ang;
|
hyu->angle = ang;
|
||||||
|
|
||||||
// copies sprite tilting
|
// copies sprite tilting
|
||||||
|
|
@ -183,18 +214,28 @@ project_hyudoro_hover (mobj_t *hyu)
|
||||||
bob_in_place(hyu, 64);
|
bob_in_place(hyu, 64);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static boolean
|
||||||
spawn_hyudoro_shadow (mobj_t *hyu)
|
project_hyudoro_orbit (mobj_t *hyu)
|
||||||
{
|
{
|
||||||
mobj_t *shadow = P_SpawnMobjFromMobj(
|
mobj_t *orbit = hyudoro_target(hyu);
|
||||||
hyu, 0, 0, 0, MT_SHADOW);
|
|
||||||
|
|
||||||
shadow->whiteshadow = true;
|
if (P_MobjWasRemoved(orbit))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
shadow->shadowscale = hyu->shadowscale;
|
P_MoveOrigin(hyu, orbit->x, orbit->y, orbit->z);
|
||||||
hyu->shadowscale = 0;
|
hyu->destscale = orbit->scale;
|
||||||
|
|
||||||
P_SetTarget(&shadow->tracer, hyu);
|
mobj_t *facing = orbit->target;
|
||||||
|
|
||||||
|
if (!P_MobjWasRemoved(facing))
|
||||||
|
{
|
||||||
|
hyu->angle = R_PointToAngle2(
|
||||||
|
hyu->x, hyu->y, facing->x, facing->y);
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static mobj_t *
|
static mobj_t *
|
||||||
|
|
@ -251,12 +292,6 @@ do_confused (mobj_t *hyu)
|
||||||
// Hyudoro is confused.
|
// Hyudoro is confused.
|
||||||
// Spin around, try to find a new target.
|
// Spin around, try to find a new target.
|
||||||
|
|
||||||
if (hyudoro_delivered(hyu))
|
|
||||||
{
|
|
||||||
// Already delivered, not confused
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Try to find new target
|
// Try to find new target
|
||||||
P_SetTarget(&hyudoro_target(hyu),
|
P_SetTarget(&hyudoro_target(hyu),
|
||||||
find_duel_target(hyudoro_stolefrom(hyu)));
|
find_duel_target(hyudoro_stolefrom(hyu)));
|
||||||
|
|
@ -267,7 +302,7 @@ do_confused (mobj_t *hyu)
|
||||||
// Bob very fast
|
// Bob very fast
|
||||||
bob_in_place(hyu, 32);
|
bob_in_place(hyu, 32);
|
||||||
|
|
||||||
hyu->sprzoff += hyu->height;
|
hyu->sprzoff += HYU_VISUAL_HEIGHT * hyu->scale;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
|
@ -304,37 +339,38 @@ move_to_player (mobj_t *hyu)
|
||||||
|
|
||||||
hyu->z = target->z; // stay level with target
|
hyu->z = target->z; // stay level with target
|
||||||
hyu->angle = angle;
|
hyu->angle = angle;
|
||||||
|
|
||||||
|
hyu->color = target->color;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
deliver_item (mobj_t *hyu)
|
deliver_item (mobj_t *hyu)
|
||||||
{
|
{
|
||||||
mobj_t *target = hyudoro_target(hyu);
|
/* set physical position to visual position in stack */
|
||||||
player_t *player = target->player;
|
hyu->z += hyu->momz;
|
||||||
|
hyu->momz = 0;
|
||||||
|
|
||||||
P_SetTarget(&hyudoro_target(hyu), NULL);
|
mobj_t *emerald = P_SpawnMobjFromMobj(
|
||||||
|
hyu, 0, 0, 0, MT_EMERALD);
|
||||||
|
|
||||||
if (player)
|
/* only want emerald for its orbiting behavior, so make
|
||||||
{
|
it invisible */
|
||||||
K_ChangePlayerItem(player,
|
P_SetMobjState(emerald, S_INVISIBLE);
|
||||||
hyudoro_itemtype(hyu),
|
|
||||||
player->itemamount + hyudoro_itemcount(hyu));
|
|
||||||
}
|
|
||||||
|
|
||||||
S_StartSound(target, sfx_itpick);
|
Obj_BeginEmeraldOrbit(
|
||||||
|
emerald, hyudoro_target(hyu), 0, 64, 128);
|
||||||
|
|
||||||
// Stop moving here
|
/* See Obj_GiveEmerald. I won't risk relying on the
|
||||||
hyu->momx = 0;
|
Hyudoro object in case it is removed first. So go
|
||||||
hyu->momy = 0;
|
through the capsule instead. */
|
||||||
|
Obj_SetEmeraldAwardee(emerald, hyudoro_capsule(hyu));
|
||||||
|
|
||||||
hyu->tics = 4;
|
/* hyudoro will teleport to emerald (orbit the player) */
|
||||||
|
hyudoro_mode(hyu) = HYU_ORBIT;
|
||||||
|
P_SetTarget(&hyudoro_target(hyu), emerald);
|
||||||
|
|
||||||
hyu->destscale = target->scale / 4;
|
hyu->renderflags &= ~(RF_DONTDRAW | RF_BLENDMASK);
|
||||||
hyu->scalespeed =
|
reset_shadow(hyu);
|
||||||
abs(hyu->scale - hyu->destscale) / hyu->tics;
|
|
||||||
|
|
||||||
// sets as already delivered
|
|
||||||
hyudoro_itemtype(hyu) = KITEM_NONE;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
|
@ -351,7 +387,17 @@ append_hyudoro
|
||||||
}
|
}
|
||||||
|
|
||||||
hyudoro_stackpos(hyu) = lastpos + 1;
|
hyudoro_stackpos(hyu) = lastpos + 1;
|
||||||
*head = hyu;
|
P_SetTarget(head, hyu);
|
||||||
|
|
||||||
|
/* only first in list gets a shadow */
|
||||||
|
if (lastpos == 0)
|
||||||
|
{
|
||||||
|
reset_shadow(hyu);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
hyu->shadowcolor = 31;/* black - hide it */
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
|
@ -359,29 +405,104 @@ pop_hyudoro (mobj_t **head)
|
||||||
{
|
{
|
||||||
mobj_t *hyu = *head;
|
mobj_t *hyu = *head;
|
||||||
|
|
||||||
INT32 lastpos;
|
if (!is_hyudoro(hyu))
|
||||||
INT32 thispos;
|
|
||||||
|
|
||||||
if (is_hyudoro(hyu))
|
|
||||||
{
|
{
|
||||||
lastpos = hyudoro_stackpos(hyu);
|
return;
|
||||||
hyu = hyudoro_next(hyu);
|
}
|
||||||
|
|
||||||
|
INT32 lastpos = hyudoro_stackpos(hyu);
|
||||||
|
|
||||||
while (is_hyudoro(hyu))
|
|
||||||
{
|
{
|
||||||
thispos = hyudoro_stackpos(hyu);
|
mobj_t *next = hyudoro_next(hyu);
|
||||||
|
|
||||||
|
P_SetTarget(head, next);
|
||||||
|
P_SetTarget(&hyudoro_next(hyu), NULL);
|
||||||
|
|
||||||
|
hyu = next;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!is_hyudoro(hyu))
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
reset_shadow(hyu);/* show it */
|
||||||
|
|
||||||
|
do
|
||||||
|
{
|
||||||
|
INT32 thispos = hyudoro_stackpos(hyu);
|
||||||
|
|
||||||
hyudoro_stackpos(hyu) = lastpos;
|
hyudoro_stackpos(hyu) = lastpos;
|
||||||
lastpos = thispos;
|
lastpos = thispos;
|
||||||
|
|
||||||
hyu = hyudoro_next(hyu);
|
hyu = hyudoro_next(hyu);
|
||||||
}
|
}
|
||||||
|
while (is_hyudoro(hyu));
|
||||||
}
|
}
|
||||||
|
|
||||||
*head = hyu;
|
static mobj_t *
|
||||||
|
spawn_capsule (mobj_t *hyu)
|
||||||
|
{
|
||||||
|
mobj_t *caps = P_SpawnMobjFromMobj(
|
||||||
|
hyu, 0, 0, 0, MT_ITEMCAPSULE);
|
||||||
|
|
||||||
|
/* hyudoro only needs its own shadow */
|
||||||
|
caps->shadowscale = 0;
|
||||||
|
|
||||||
|
caps->flags |=
|
||||||
|
MF_NOGRAVITY |
|
||||||
|
MF_NOCLIP |
|
||||||
|
MF_NOCLIPTHING |
|
||||||
|
MF_NOCLIPHEIGHT;
|
||||||
|
|
||||||
|
/* signal that this item capsule always puts items in the HUD */
|
||||||
|
caps->flags2 |= MF2_STRONGBOX;
|
||||||
|
|
||||||
|
P_SetTarget(&hyudoro_capsule(hyu), caps);
|
||||||
|
|
||||||
|
/* capsule teleports to hyudoro */
|
||||||
|
P_SetTarget(&caps->target, hyu);
|
||||||
|
|
||||||
|
/* so it looks like hyudoro is holding it */
|
||||||
|
caps->sprzoff = 20 * hyu->scale;
|
||||||
|
|
||||||
|
return caps;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void hyudoro_set_held_item_from_player
|
static void
|
||||||
|
update_capsule_position (mobj_t *hyu)
|
||||||
|
{
|
||||||
|
mobj_t *caps = hyudoro_capsule(hyu);
|
||||||
|
|
||||||
|
if (P_MobjWasRemoved(caps))
|
||||||
|
return;
|
||||||
|
|
||||||
|
caps->extravalue1 = hyu->scale / 3;
|
||||||
|
|
||||||
|
/* hold it in the hyudoro's hands */
|
||||||
|
const fixed_t r = hyu->radius;
|
||||||
|
caps->sprxoff = FixedMul(r, FCOS(hyu->angle));
|
||||||
|
caps->spryoff = FixedMul(r, FSIN(hyu->angle));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
set_item
|
||||||
|
( mobj_t * hyu,
|
||||||
|
INT32 item,
|
||||||
|
INT32 amount)
|
||||||
|
{
|
||||||
|
mobj_t *caps = P_MobjWasRemoved(hyudoro_capsule(hyu))
|
||||||
|
? spawn_capsule(hyu) : hyudoro_capsule(hyu);
|
||||||
|
|
||||||
|
hyudoro_itemtype(hyu) = item;
|
||||||
|
hyudoro_itemcount(hyu) = amount;
|
||||||
|
|
||||||
|
caps->threshold = hyudoro_itemtype(hyu);
|
||||||
|
caps->movecount = hyudoro_itemcount(hyu);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
hyudoro_set_held_item_from_player
|
||||||
( mobj_t * hyu,
|
( mobj_t * hyu,
|
||||||
player_t * player)
|
player_t * player)
|
||||||
{
|
{
|
||||||
|
|
@ -409,15 +530,13 @@ static void hyudoro_set_held_item_from_player
|
||||||
itemCooldowns[player->itemtype - 1] = 0;
|
itemCooldowns[player->itemtype - 1] = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
hyudoro_itemtype(hyu) = KITEM_KITCHENSINK;
|
set_item(hyu, KITEM_KITCHENSINK, 1);
|
||||||
hyudoro_itemcount(hyu) = 1;
|
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
hyudoro_itemtype(hyu) = player->itemtype;
|
set_item(hyu, player->itemtype, player->itemamount);
|
||||||
hyudoro_itemcount(hyu) = player->itemamount;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static boolean
|
static boolean
|
||||||
|
|
@ -443,6 +562,8 @@ hyudoro_patrol_hit_player
|
||||||
if (player->hyudorotimer)
|
if (player->hyudorotimer)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
player->pflags |= PF_CASTSHADOW;
|
||||||
|
|
||||||
// NO ITEM?
|
// NO ITEM?
|
||||||
if (!player->itemamount)
|
if (!player->itemamount)
|
||||||
return false;
|
return false;
|
||||||
|
|
@ -453,9 +574,19 @@ hyudoro_patrol_hit_player
|
||||||
|
|
||||||
hyudoro_set_held_item_from_player(hyu, player);
|
hyudoro_set_held_item_from_player(hyu, player);
|
||||||
|
|
||||||
|
if (!P_MobjWasRemoved(hyudoro_capsule(hyu)))
|
||||||
|
{
|
||||||
|
hyudoro_capsule(hyu)->extravalue2 = player->skincolor;
|
||||||
|
}
|
||||||
|
|
||||||
K_StripItems(player);
|
K_StripItems(player);
|
||||||
|
|
||||||
|
/* do not make 1st place invisible */
|
||||||
|
if (player->position != 1)
|
||||||
|
{
|
||||||
player->hyudorotimer = hyudorotime;
|
player->hyudorotimer = hyudorotime;
|
||||||
|
}
|
||||||
|
|
||||||
player->stealingtimer = hyudorotime;
|
player->stealingtimer = hyudorotime;
|
||||||
|
|
||||||
P_SetTarget(&hyudoro_stolefrom(hyu), toucher);
|
P_SetTarget(&hyudoro_stolefrom(hyu), toucher);
|
||||||
|
|
@ -473,6 +604,14 @@ hyudoro_patrol_hit_player
|
||||||
|
|
||||||
hyu->renderflags &= ~(RF_DONTDRAW);
|
hyu->renderflags &= ~(RF_DONTDRAW);
|
||||||
|
|
||||||
|
// Reset shadow to default (after alt_shadow)
|
||||||
|
reset_shadow(hyu);
|
||||||
|
|
||||||
|
// This will flicker the shadow
|
||||||
|
hyudoro_timer(hyu) = 18;
|
||||||
|
|
||||||
|
P_SetMobjState(hyu, S_HYUDORO_RETURNING);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -488,16 +627,13 @@ award_immediately (mobj_t *hyu)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (player->itemamount &&
|
if (!P_CanPickupItem(player, 1))
|
||||||
player->itemtype != hyudoro_itemtype(hyu))
|
|
||||||
{
|
|
||||||
return false;
|
return false;
|
||||||
}
|
|
||||||
|
|
||||||
// Same as picking up paper items; get stacks
|
// Prevent receiving any more items or even stacked
|
||||||
// immediately
|
// Hyudoros! Put on a timer so roulette cannot become
|
||||||
if (!P_CanPickupItem(player, 3))
|
// locked permanently.
|
||||||
return false;
|
player->itemRoulette.reserved = 2*TICRATE;
|
||||||
}
|
}
|
||||||
|
|
||||||
deliver_item(hyu);
|
deliver_item(hyu);
|
||||||
|
|
@ -544,6 +680,96 @@ hyudoro_hover_await_stack (mobj_t *hyu)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
trail_ghosts
|
||||||
|
( mobj_t * hyu,
|
||||||
|
boolean colorize)
|
||||||
|
{
|
||||||
|
// Spawns every other frame
|
||||||
|
if (leveltime & 1)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
mobj_t *ghost = P_SpawnGhostMobj(hyu);
|
||||||
|
|
||||||
|
// Flickers every frame
|
||||||
|
ghost->extravalue1 = 1;
|
||||||
|
ghost->extravalue2 = 2;
|
||||||
|
|
||||||
|
// copy per-splitscreen-player visibility
|
||||||
|
ghost->renderflags =
|
||||||
|
(hyu->renderflags & RF_DONTDRAW);
|
||||||
|
|
||||||
|
ghost->colorized = colorize;
|
||||||
|
|
||||||
|
ghost->tics = 8;
|
||||||
|
|
||||||
|
P_SetTarget(&ghost->tracer, hyu);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
trail_glow (mobj_t *hyu)
|
||||||
|
{
|
||||||
|
mobj_t *ghost = P_SpawnGhostMobj(hyu);
|
||||||
|
|
||||||
|
// Flickers every frame
|
||||||
|
ghost->extravalue1 = 1;
|
||||||
|
ghost->extravalue2 = 0;
|
||||||
|
|
||||||
|
ghost->renderflags = RF_ADD | RF_TRANS80;
|
||||||
|
|
||||||
|
ghost->tics = 2; // this actually does last one tic
|
||||||
|
|
||||||
|
ghost->momz = hyu->momz; // copy stack position
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
blend_hover_hyudoro (mobj_t *hyu)
|
||||||
|
{
|
||||||
|
player_t *player = get_hyudoro_target_player(hyu);
|
||||||
|
|
||||||
|
hyu->renderflags &= ~(RF_BLENDMASK);
|
||||||
|
|
||||||
|
if (!player)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 1st place: Hyudoro stack is unusable, so make a visual
|
||||||
|
indication */
|
||||||
|
if (player->position == 1)
|
||||||
|
{
|
||||||
|
hyu->renderflags |= RF_MODULATE;
|
||||||
|
trail_glow(hyu);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
alt_shadow (mobj_t *hyu)
|
||||||
|
{
|
||||||
|
/* spaced out pulse, fake randomness */
|
||||||
|
switch (leveltime % (7 + ((leveltime / 8) % 3)))
|
||||||
|
{
|
||||||
|
default:
|
||||||
|
hyu->shadowcolor = 15;
|
||||||
|
hyu->whiteshadow = false;
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
hyu->shadowcolor = 5;
|
||||||
|
hyu->whiteshadow = true;
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
hyu->shadowcolor = 181;
|
||||||
|
hyu->whiteshadow = true;
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
hyu->shadowcolor = 255;
|
||||||
|
hyu->whiteshadow = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
Obj_InitHyudoroCenter (mobj_t * center, mobj_t * master)
|
Obj_InitHyudoroCenter (mobj_t * center, mobj_t * master)
|
||||||
{
|
{
|
||||||
|
|
@ -572,7 +798,7 @@ Obj_InitHyudoroCenter (mobj_t * center, mobj_t * master)
|
||||||
hyu->renderflags &= ~(K_GetPlayerDontDrawFlag(master->player));
|
hyu->renderflags &= ~(K_GetPlayerDontDrawFlag(master->player));
|
||||||
}
|
}
|
||||||
|
|
||||||
spawn_hyudoro_shadow(hyu); // this sucks btw
|
Obj_SpawnFakeShadow(hyu); // this sucks btw
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|
@ -584,51 +810,60 @@ Obj_HyudoroDeploy (mobj_t *master)
|
||||||
center->angle = master->angle;
|
center->angle = master->angle;
|
||||||
Obj_InitHyudoroCenter(center, master);
|
Obj_InitHyudoroCenter(center, master);
|
||||||
|
|
||||||
|
// Update floorz to the correct position by indicating
|
||||||
|
// that it should be recalculated by P_MobjThinker.
|
||||||
|
center->floorz = master->z;
|
||||||
|
center->ceilingz = master->z + master->height;
|
||||||
|
center->z = P_GetMobjGround(center) - P_MobjFlip(center);
|
||||||
|
|
||||||
S_StartSound(master, sfx_s3k92); // scary ghost noise
|
S_StartSound(master, sfx_s3k92); // scary ghost noise
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
Obj_HyudoroThink (mobj_t *hyu)
|
Obj_HyudoroThink (mobj_t *hyu)
|
||||||
{
|
{
|
||||||
// Might get set from clipping slopes
|
|
||||||
hyu->momz = 0;
|
|
||||||
|
|
||||||
switch (hyudoro_mode(hyu))
|
switch (hyudoro_mode(hyu))
|
||||||
{
|
{
|
||||||
case HYU_PATROL:
|
case HYU_PATROL:
|
||||||
if (hyudoro_center(hyu))
|
if (hyudoro_center(hyu))
|
||||||
project_hyudoro(hyu);
|
project_hyudoro(hyu);
|
||||||
|
|
||||||
if (leveltime & 1)
|
trail_ghosts(hyu, false);
|
||||||
{
|
alt_shadow(hyu);
|
||||||
mobj_t *ghost = P_SpawnGhostMobj(hyu);
|
|
||||||
|
|
||||||
// Flickers every frame
|
|
||||||
ghost->extravalue1 = 1;
|
|
||||||
ghost->extravalue2 = 2;
|
|
||||||
|
|
||||||
// copy per-splitscreen-player visibility
|
|
||||||
ghost->renderflags =
|
|
||||||
(hyu->renderflags & RF_DONTDRAW);
|
|
||||||
|
|
||||||
ghost->tics = 8;
|
|
||||||
|
|
||||||
P_SetTarget(&ghost->tracer, hyu);
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case HYU_RETURN:
|
case HYU_RETURN:
|
||||||
move_to_player(hyu);
|
move_to_player(hyu);
|
||||||
|
trail_ghosts(hyu, true);
|
||||||
|
|
||||||
|
if (hyudoro_timer(hyu) > 0)
|
||||||
|
hyu->whiteshadow = !hyu->whiteshadow;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case HYU_HOVER:
|
case HYU_HOVER:
|
||||||
if (hyudoro_target(hyu))
|
if (hyudoro_target(hyu))
|
||||||
{
|
{
|
||||||
project_hyudoro_hover(hyu);
|
project_hyudoro_hover(hyu);
|
||||||
hyudoro_hover_await_stack(hyu);
|
|
||||||
|
if (hyudoro_hover_await_stack(hyu))
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
blend_hover_hyudoro(hyu);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case HYU_ORBIT:
|
||||||
|
if (!project_hyudoro_orbit(hyu))
|
||||||
|
{
|
||||||
|
P_RemoveMobj(hyu);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
update_capsule_position(hyu);
|
||||||
|
|
||||||
|
if (hyudoro_timer(hyu) > 0)
|
||||||
|
hyudoro_timer(hyu)--;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|
@ -656,3 +891,21 @@ Obj_HyudoroCollide
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
boolean
|
||||||
|
Obj_HyudoroShadowZ
|
||||||
|
( mobj_t * hyu,
|
||||||
|
fixed_t * return_z,
|
||||||
|
pslope_t ** return_slope)
|
||||||
|
{
|
||||||
|
if (hyudoro_mode(hyu) != HYU_PATROL)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (P_MobjWasRemoved(hyudoro_center(hyu)))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
*return_z = hyu->z;
|
||||||
|
*return_slope = hyudoro_center(hyu)->standingslope;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
|
||||||
109
src/objects/shadow.cpp
Normal file
109
src/objects/shadow.cpp
Normal file
|
|
@ -0,0 +1,109 @@
|
||||||
|
#include <optional>
|
||||||
|
#include <utility>
|
||||||
|
|
||||||
|
#include "../info.h"
|
||||||
|
#include "../k_objects.h"
|
||||||
|
#include "../p_local.h"
|
||||||
|
#include "../p_mobj.h"
|
||||||
|
#include "../p_tick.h"
|
||||||
|
#include "../typedef.h"
|
||||||
|
|
||||||
|
#define shadow_follow(o) ((o)->tracer)
|
||||||
|
|
||||||
|
struct Shadow : mobj_t
|
||||||
|
{
|
||||||
|
mobj_t* follow() const { return shadow_follow(this); }
|
||||||
|
void follow(mobj_t* n) { P_SetTarget(&shadow_follow(this), n); }
|
||||||
|
|
||||||
|
static Shadow* spawn(mobj_t* from)
|
||||||
|
{
|
||||||
|
return static_cast<Shadow*>(P_SpawnMobjFromMobj(from, 0, 0, 0, MT_SHADOW))->init(from);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool valid() const { return !P_MobjWasRemoved(this) && !P_MobjWasRemoved(follow()); }
|
||||||
|
|
||||||
|
std::optional<std::pair<fixed_t, pslope_t*>> z_position() const
|
||||||
|
{
|
||||||
|
switch (follow()->type)
|
||||||
|
{
|
||||||
|
case MT_HYUDORO: {
|
||||||
|
fixed_t z;
|
||||||
|
pslope_t* slope;
|
||||||
|
|
||||||
|
if (Obj_HyudoroShadowZ(follow(), &z, &slope))
|
||||||
|
{
|
||||||
|
return {{z, slope}};
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
void destroy() { P_RemoveMobj(this); }
|
||||||
|
|
||||||
|
void move()
|
||||||
|
{
|
||||||
|
whiteshadow = follow()->whiteshadow;
|
||||||
|
shadowcolor = follow()->shadowcolor;
|
||||||
|
|
||||||
|
P_MoveOrigin(this, follow()->x, follow()->y, P_GetMobjFeet(follow()));
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
Shadow* init(mobj_t* from)
|
||||||
|
{
|
||||||
|
shadowscale = from->shadowscale;
|
||||||
|
from->shadowscale = 0;
|
||||||
|
|
||||||
|
follow(from);
|
||||||
|
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
mobj_t* Obj_SpawnFakeShadow(mobj_t* from)
|
||||||
|
{
|
||||||
|
return Shadow::spawn(from);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Obj_FakeShadowThink(mobj_t* shadow)
|
||||||
|
{
|
||||||
|
auto x = static_cast<Shadow*>(shadow);
|
||||||
|
|
||||||
|
if (!x->valid())
|
||||||
|
{
|
||||||
|
x->destroy();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
x->move();
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean Obj_FakeShadowZ(const mobj_t* shadow, fixed_t* return_z, pslope_t** return_slope)
|
||||||
|
{
|
||||||
|
auto x = static_cast<const Shadow*>(shadow);
|
||||||
|
|
||||||
|
if (!x->valid())
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto pair = x->z_position();
|
||||||
|
|
||||||
|
if (!pair)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto [z, slope] = *pair;
|
||||||
|
|
||||||
|
*return_z = z;
|
||||||
|
*return_slope = slope;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
@ -115,7 +115,7 @@ void P_RampConstant(const BasicFF_t *FFInfo, INT32 Start, INT32 End)
|
||||||
//
|
//
|
||||||
boolean P_CanPickupItem(player_t *player, UINT8 weapon)
|
boolean P_CanPickupItem(player_t *player, UINT8 weapon)
|
||||||
{
|
{
|
||||||
if (player->exiting || mapreset || (player->pflags & PF_ELIMINATED))
|
if (player->exiting || mapreset || (player->pflags & PF_ELIMINATED) || player->itemRoulette.reserved)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
// 0: Sphere/Ring
|
// 0: Sphere/Ring
|
||||||
|
|
@ -165,6 +165,13 @@ boolean P_CanPickupItem(player_t *player, UINT8 weapon)
|
||||||
// 1 = floating item, 2 = perma ring, 3 = capsule
|
// 1 = floating item, 2 = perma ring, 3 = capsule
|
||||||
boolean P_IsPickupCheesy(player_t *player, UINT8 type)
|
boolean P_IsPickupCheesy(player_t *player, UINT8 type)
|
||||||
{
|
{
|
||||||
|
extern consvar_t cv_debugcheese;
|
||||||
|
|
||||||
|
if (cv_debugcheese.value)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
if (player->lastpickupdistance && player->lastpickuptype == type)
|
if (player->lastpickupdistance && player->lastpickuptype == type)
|
||||||
{
|
{
|
||||||
UINT32 distancedelta = min(player->distancetofinish - player->lastpickupdistance, player->lastpickupdistance - player->distancetofinish);
|
UINT32 distancedelta = min(player->distancetofinish - player->lastpickupdistance, player->lastpickupdistance - player->distancetofinish);
|
||||||
|
|
@ -1680,7 +1687,7 @@ void P_KillMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, UINT8 damaget
|
||||||
INT16 spacing = (target->radius >> 1) / target->scale;
|
INT16 spacing = (target->radius >> 1) / target->scale;
|
||||||
|
|
||||||
// set respawn fuse
|
// set respawn fuse
|
||||||
if (K_CapsuleTimeAttackRules() == true) // no respawns
|
if (damagetype == DMG_INSTAKILL || K_CapsuleTimeAttackRules() == true) // no respawns
|
||||||
;
|
;
|
||||||
else if (target->threshold == KITEM_SUPERRING)
|
else if (target->threshold == KITEM_SUPERRING)
|
||||||
target->fuse = 20*TICRATE;
|
target->fuse = 20*TICRATE;
|
||||||
|
|
@ -1745,6 +1752,9 @@ void P_KillMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, UINT8 damaget
|
||||||
{
|
{
|
||||||
player_t *player = source->player;
|
player_t *player = source->player;
|
||||||
|
|
||||||
|
// MF2_STRONGBOX: always put the item right in the hotbar!
|
||||||
|
if (!(target->flags2 & MF2_STRONGBOX))
|
||||||
|
{
|
||||||
// special behavior for ring capsules
|
// special behavior for ring capsules
|
||||||
if (target->threshold == KITEM_SUPERRING)
|
if (target->threshold == KITEM_SUPERRING)
|
||||||
{
|
{
|
||||||
|
|
@ -1758,6 +1768,7 @@ void P_KillMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, UINT8 damaget
|
||||||
K_ThrowKartItem(player, true, MT_SPB, 1, 0, 0);
|
K_ThrowKartItem(player, true, MT_SPB, 1, 0, 0);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (target->threshold < 1 || target->threshold >= NUMKARTITEMS) // bruh moment prevention
|
if (target->threshold < 1 || target->threshold >= NUMKARTITEMS) // bruh moment prevention
|
||||||
{
|
{
|
||||||
|
|
@ -2294,7 +2305,7 @@ static void AddNullHitlag(player_t *player, tic_t oldHitlag)
|
||||||
// 1) repeating damage doesn't count
|
// 1) repeating damage doesn't count
|
||||||
// 2) new damage sources still count
|
// 2) new damage sources still count
|
||||||
|
|
||||||
if (player->timeshit <= player->timeshitprev)
|
if (player->timeshit <= player->timeshitprev || player->hyudorotimer > 0)
|
||||||
{
|
{
|
||||||
player->nullHitlag += (player->mo->hitlag - oldHitlag);
|
player->nullHitlag += (player->mo->hitlag - oldHitlag);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
45
src/p_mobj.c
45
src/p_mobj.c
|
|
@ -4371,7 +4371,8 @@ static void P_ItemCapsulePartThinker(mobj_t *mobj)
|
||||||
else // alive
|
else // alive
|
||||||
{
|
{
|
||||||
mobj_t *target = mobj->target;
|
mobj_t *target = mobj->target;
|
||||||
fixed_t targetScale, z;
|
fixed_t targetScale;
|
||||||
|
fixed_t x, y, z;
|
||||||
|
|
||||||
if (P_MobjWasRemoved(target))
|
if (P_MobjWasRemoved(target))
|
||||||
{
|
{
|
||||||
|
|
@ -4394,19 +4395,23 @@ static void P_ItemCapsulePartThinker(mobj_t *mobj)
|
||||||
else
|
else
|
||||||
K_GenericExtraFlagsNoZAdjust(mobj, target);
|
K_GenericExtraFlagsNoZAdjust(mobj, target);
|
||||||
|
|
||||||
|
x = target->x + target->sprxoff;
|
||||||
|
y = target->y + target->spryoff;
|
||||||
|
z = target->z + target->sprzoff;
|
||||||
|
|
||||||
if (mobj->eflags & MFE_VERTICALFLIP)
|
if (mobj->eflags & MFE_VERTICALFLIP)
|
||||||
z = target->z + target->height - mobj->height - FixedMul(mobj->scale, mobj->movefactor);
|
z += target->height - mobj->height - FixedMul(mobj->scale, mobj->movefactor);
|
||||||
else
|
else
|
||||||
z = target->z + FixedMul(mobj->scale, mobj->movefactor);
|
z += FixedMul(mobj->scale, mobj->movefactor);
|
||||||
|
|
||||||
// rotate & move to capsule
|
// rotate & move to capsule
|
||||||
mobj->angle += mobj->movedir;
|
mobj->angle += mobj->movedir;
|
||||||
if (mobj->flags2 & MF2_CLASSICPUSH) // centered
|
if (mobj->flags2 & MF2_CLASSICPUSH) // centered
|
||||||
P_MoveOrigin(mobj, target->x, target->y, z);
|
P_MoveOrigin(mobj, x, y, z);
|
||||||
else
|
else
|
||||||
P_MoveOrigin(mobj,
|
P_MoveOrigin(mobj,
|
||||||
target->x + P_ReturnThrustX(mobj, mobj->angle + ANGLE_90, mobj->radius),
|
x + P_ReturnThrustX(mobj, mobj->angle + ANGLE_90, mobj->radius),
|
||||||
target->y + P_ReturnThrustY(mobj, mobj->angle + ANGLE_90, mobj->radius),
|
y + P_ReturnThrustY(mobj, mobj->angle + ANGLE_90, mobj->radius),
|
||||||
z);
|
z);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -4438,7 +4443,9 @@ static void P_RefreshItemCapsuleParts(mobj_t *mobj)
|
||||||
}
|
}
|
||||||
|
|
||||||
// update cap colors
|
// update cap colors
|
||||||
if (itemType == KITEM_SUPERRING)
|
if (mobj->extravalue2)
|
||||||
|
color = mobj->extravalue2;
|
||||||
|
else if (itemType == KITEM_SUPERRING)
|
||||||
{
|
{
|
||||||
color = SKINCOLOR_GOLD;
|
color = SKINCOLOR_GOLD;
|
||||||
newRenderFlags |= RF_SEMIBRIGHT;
|
newRenderFlags |= RF_SEMIBRIGHT;
|
||||||
|
|
@ -4482,6 +4489,9 @@ static void P_RefreshItemCapsuleParts(mobj_t *mobj)
|
||||||
count = mobj->movecount;
|
count = mobj->movecount;
|
||||||
break;
|
break;
|
||||||
case KITEM_SUPERRING: // always display the number, and multiply it by 5
|
case KITEM_SUPERRING: // always display the number, and multiply it by 5
|
||||||
|
if (mobj->flags2 & MF2_STRONGBOX)
|
||||||
|
count = mobj->movecount * 20; // give Super Rings
|
||||||
|
else
|
||||||
count = mobj->movecount * 5;
|
count = mobj->movecount * 5;
|
||||||
break;
|
break;
|
||||||
case KITEM_SAD: // never display the number
|
case KITEM_SAD: // never display the number
|
||||||
|
|
@ -5782,16 +5792,10 @@ static void P_MobjSceneryThink(mobj_t *mobj)
|
||||||
switch (mobj->type)
|
switch (mobj->type)
|
||||||
{
|
{
|
||||||
case MT_SHADOW:
|
case MT_SHADOW:
|
||||||
if (mobj->tracer)
|
Obj_FakeShadowThink(mobj);
|
||||||
|
|
||||||
|
if (P_MobjWasRemoved(mobj))
|
||||||
{
|
{
|
||||||
P_MoveOrigin(mobj,
|
|
||||||
mobj->tracer->x,
|
|
||||||
mobj->tracer->y,
|
|
||||||
mobj->tracer->z);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
P_RemoveMobj(mobj);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
@ -7297,6 +7301,14 @@ static boolean P_MobjRegularThink(mobj_t *mobj)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case MT_ITEMCAPSULE:
|
case MT_ITEMCAPSULE:
|
||||||
|
if (!P_MobjWasRemoved(mobj->target))
|
||||||
|
{
|
||||||
|
P_MoveOrigin(mobj,
|
||||||
|
mobj->target->x + mobj->target->sprxoff,
|
||||||
|
mobj->target->y + mobj->target->spryoff,
|
||||||
|
mobj->target->z + mobj->target->sprzoff);
|
||||||
|
}
|
||||||
|
|
||||||
// scale the capsule
|
// scale the capsule
|
||||||
if (mobj->scale < mobj->extravalue1)
|
if (mobj->scale < mobj->extravalue1)
|
||||||
{
|
{
|
||||||
|
|
@ -10408,6 +10420,7 @@ static void P_DefaultMobjShadowScale(mobj_t *thing)
|
||||||
{
|
{
|
||||||
thing->shadowscale = 0;
|
thing->shadowscale = 0;
|
||||||
thing->whiteshadow = ((thing->frame & FF_BRIGHTMASK) == FF_FULLBRIGHT);
|
thing->whiteshadow = ((thing->frame & FF_BRIGHTMASK) == FF_FULLBRIGHT);
|
||||||
|
thing->shadowcolor = 15;
|
||||||
|
|
||||||
switch (thing->type)
|
switch (thing->type)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -415,6 +415,7 @@ struct mobj_t
|
||||||
|
|
||||||
fixed_t shadowscale; // If this object casts a shadow, and the size relative to radius
|
fixed_t shadowscale; // If this object casts a shadow, and the size relative to radius
|
||||||
boolean whiteshadow; // Use white shadow, set to true by default for fullbright objects
|
boolean whiteshadow; // Use white shadow, set to true by default for fullbright objects
|
||||||
|
UINT8 shadowcolor; // Palette index to use for rendering the shadow
|
||||||
|
|
||||||
fixed_t sprxoff, spryoff, sprzoff; // Sprite offsets in real space, does NOT affect position or collision
|
fixed_t sprxoff, spryoff, sprzoff; // Sprite offsets in real space, does NOT affect position or collision
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -628,6 +628,7 @@ static void P_NetArchivePlayers(savebuffer_t *save)
|
||||||
WRITEUINT8(save->p, players[i].itemRoulette.eggman);
|
WRITEUINT8(save->p, players[i].itemRoulette.eggman);
|
||||||
WRITEUINT8(save->p, players[i].itemRoulette.ringbox);
|
WRITEUINT8(save->p, players[i].itemRoulette.ringbox);
|
||||||
WRITEUINT8(save->p, players[i].itemRoulette.autoroulette);
|
WRITEUINT8(save->p, players[i].itemRoulette.autoroulette);
|
||||||
|
WRITEUINT8(save->p, players[i].itemRoulette.reserved);
|
||||||
|
|
||||||
// sonicloopsvars_t
|
// sonicloopsvars_t
|
||||||
WRITEFIXED(save->p, players[i].loop.radius);
|
WRITEFIXED(save->p, players[i].loop.radius);
|
||||||
|
|
@ -1114,6 +1115,7 @@ static void P_NetUnArchivePlayers(savebuffer_t *save)
|
||||||
players[i].itemRoulette.eggman = (boolean)READUINT8(save->p);
|
players[i].itemRoulette.eggman = (boolean)READUINT8(save->p);
|
||||||
players[i].itemRoulette.ringbox = (boolean)READUINT8(save->p);
|
players[i].itemRoulette.ringbox = (boolean)READUINT8(save->p);
|
||||||
players[i].itemRoulette.autoroulette = (boolean)READUINT8(save->p);
|
players[i].itemRoulette.autoroulette = (boolean)READUINT8(save->p);
|
||||||
|
players[i].itemRoulette.reserved = READUINT8(save->p);
|
||||||
|
|
||||||
// sonicloopsvars_t
|
// sonicloopsvars_t
|
||||||
players[i].loop.radius = READFIXED(save->p);
|
players[i].loop.radius = READFIXED(save->p);
|
||||||
|
|
@ -3023,6 +3025,7 @@ static void SaveMobjThinker(savebuffer_t *save, const thinker_t *th, const UINT8
|
||||||
{
|
{
|
||||||
WRITEFIXED(save->p, mobj->shadowscale);
|
WRITEFIXED(save->p, mobj->shadowscale);
|
||||||
WRITEUINT8(save->p, mobj->whiteshadow);
|
WRITEUINT8(save->p, mobj->whiteshadow);
|
||||||
|
WRITEUINT8(save->p, mobj->shadowcolor);
|
||||||
}
|
}
|
||||||
if (diff2 & MD2_RENDERFLAGS)
|
if (diff2 & MD2_RENDERFLAGS)
|
||||||
{
|
{
|
||||||
|
|
@ -4249,6 +4252,7 @@ static thinker_t* LoadMobjThinker(savebuffer_t *save, actionf_p1 thinker)
|
||||||
{
|
{
|
||||||
mobj->shadowscale = READFIXED(save->p);
|
mobj->shadowscale = READFIXED(save->p);
|
||||||
mobj->whiteshadow = READUINT8(save->p);
|
mobj->whiteshadow = READUINT8(save->p);
|
||||||
|
mobj->shadowcolor = READUINT8(save->p);
|
||||||
}
|
}
|
||||||
if (diff2 & MD2_RENDERFLAGS)
|
if (diff2 & MD2_RENDERFLAGS)
|
||||||
mobj->renderflags = READUINT32(save->p);
|
mobj->renderflags = READUINT32(save->p);
|
||||||
|
|
|
||||||
|
|
@ -128,6 +128,8 @@ UINT8 *ds_source; // points to the start of a flat
|
||||||
UINT8 *ds_brightmap; // start of brightmap flat
|
UINT8 *ds_brightmap; // start of brightmap flat
|
||||||
UINT8 *ds_transmap; // one of the translucency tables
|
UINT8 *ds_transmap; // one of the translucency tables
|
||||||
|
|
||||||
|
UINT8 dc_shadowcolor;
|
||||||
|
|
||||||
// Vectors for Software's tilted slope drawers
|
// Vectors for Software's tilted slope drawers
|
||||||
floatv3_t *ds_su, *ds_sv, *ds_sz;
|
floatv3_t *ds_su, *ds_sv, *ds_sz;
|
||||||
floatv3_t *ds_sup, *ds_svp, *ds_szp;
|
floatv3_t *ds_sup, *ds_svp, *ds_szp;
|
||||||
|
|
|
||||||
|
|
@ -59,6 +59,8 @@ extern INT32 dc_numlights, dc_maxlights;
|
||||||
//Fix TUTIFRUTI
|
//Fix TUTIFRUTI
|
||||||
extern INT32 dc_texheight;
|
extern INT32 dc_texheight;
|
||||||
|
|
||||||
|
extern UINT8 dc_shadowcolor;
|
||||||
|
|
||||||
// -----------------------
|
// -----------------------
|
||||||
// SPAN DRAWING CODE STUFF
|
// SPAN DRAWING CODE STUFF
|
||||||
// -----------------------
|
// -----------------------
|
||||||
|
|
|
||||||
|
|
@ -584,9 +584,7 @@ void R_DrawDropShadowColumn_8(void)
|
||||||
dest = &topleft[dc_yl*vid.width + dc_x];
|
dest = &topleft[dc_yl*vid.width + dc_x];
|
||||||
|
|
||||||
{
|
{
|
||||||
#define DSCOLOR 15 // palette index for the color of the shadow
|
register const UINT8 *transmap_offset = dc_transmap + (dc_colormap[dc_shadowcolor] << 8);
|
||||||
register const UINT8 *transmap_offset = dc_transmap + (dc_colormap[DSCOLOR] << 8);
|
|
||||||
#undef DSCOLOR
|
|
||||||
while ((count -= 2) >= 0)
|
while ((count -= 2) >= 0)
|
||||||
{
|
{
|
||||||
*dest = *(transmap_offset + (*dest));
|
*dest = *(transmap_offset + (*dest));
|
||||||
|
|
|
||||||
|
|
@ -10,6 +10,7 @@
|
||||||
|
|
||||||
#include "d_player.h"
|
#include "d_player.h"
|
||||||
#include "info.h"
|
#include "info.h"
|
||||||
|
#include "k_objects.h"
|
||||||
#include "p_tick.h"
|
#include "p_tick.h"
|
||||||
#include "r_splats.h"
|
#include "r_splats.h"
|
||||||
#include "r_things.h"
|
#include "r_things.h"
|
||||||
|
|
@ -27,6 +28,11 @@ INT32 R_ThingLightLevel(mobj_t* thing)
|
||||||
// Darken on every other frame of instawhip cooldown
|
// Darken on every other frame of instawhip cooldown
|
||||||
lightlevel -= 128;
|
lightlevel -= 128;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (player->pflags & PF_CASTSHADOW)
|
||||||
|
{
|
||||||
|
lightlevel -= 255;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return lightlevel;
|
return lightlevel;
|
||||||
|
|
@ -59,3 +65,21 @@ boolean R_SplatSlope(mobj_t* mobj, vector3_t position, pslope_t* slope)
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
boolean R_CustomShadowZ(mobj_t* thing, fixed_t *z, pslope_t** slope)
|
||||||
|
{
|
||||||
|
switch (thing->type)
|
||||||
|
{
|
||||||
|
case MT_SHADOW:
|
||||||
|
if (Obj_FakeShadowZ(thing, z, slope))
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -926,6 +926,7 @@ static void R_DrawVisSprite(vissprite_t *vis)
|
||||||
{
|
{
|
||||||
R_SetColumnFunc(COLDRAWFUNC_DROPSHADOW, false);
|
R_SetColumnFunc(COLDRAWFUNC_DROPSHADOW, false);
|
||||||
dc_transmap = vis->transmap;
|
dc_transmap = vis->transmap;
|
||||||
|
dc_shadowcolor = vis->color;
|
||||||
}
|
}
|
||||||
else if (!(vis->cut & SC_PRECIP) &&
|
else if (!(vis->cut & SC_PRECIP) &&
|
||||||
R_ThingIsFlashing(vis->mobj)) // Bosses "flash"
|
R_ThingIsFlashing(vis->mobj)) // Bosses "flash"
|
||||||
|
|
@ -1314,6 +1315,14 @@ fixed_t R_GetShadowZ(
|
||||||
sector_t *sector;
|
sector_t *sector;
|
||||||
ffloor_t *rover;
|
ffloor_t *rover;
|
||||||
|
|
||||||
|
if (R_CustomShadowZ(thing, &groundz, &groundslope))
|
||||||
|
{
|
||||||
|
if (shadowslope != NULL)
|
||||||
|
*shadowslope = groundslope;
|
||||||
|
|
||||||
|
return groundz;
|
||||||
|
}
|
||||||
|
|
||||||
// for frame interpolation
|
// for frame interpolation
|
||||||
interpmobjstate_t interp = {0};
|
interpmobjstate_t interp = {0};
|
||||||
|
|
||||||
|
|
@ -1543,6 +1552,8 @@ static void R_ProjectDropShadow(
|
||||||
shadow->transmap = R_GetBlendTable(thing->whiteshadow ? AST_ADD : AST_SUBTRACT, 0);
|
shadow->transmap = R_GetBlendTable(thing->whiteshadow ? AST_ADD : AST_SUBTRACT, 0);
|
||||||
shadow->colormap = colormaps;
|
shadow->colormap = colormaps;
|
||||||
|
|
||||||
|
shadow->color = thing->shadowcolor;
|
||||||
|
|
||||||
objectsdrawn++;
|
objectsdrawn++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -95,6 +95,7 @@ boolean R_ThingIsFlashing(mobj_t *thing);
|
||||||
|
|
||||||
INT32 R_ThingLightLevel(mobj_t *thing);
|
INT32 R_ThingLightLevel(mobj_t *thing);
|
||||||
boolean R_SplatSlope(mobj_t *thing, vector3_t position, pslope_t *slope);
|
boolean R_SplatSlope(mobj_t *thing, vector3_t position, pslope_t *slope);
|
||||||
|
boolean R_CustomShadowZ(mobj_t *thing, fixed_t *return_z, pslope_t **return_slope);
|
||||||
|
|
||||||
// --------------
|
// --------------
|
||||||
// MASKED DRAWING
|
// MASKED DRAWING
|
||||||
|
|
@ -225,6 +226,7 @@ struct vissprite_t
|
||||||
fixed_t spritexoffset, spriteyoffset;
|
fixed_t spritexoffset, spriteyoffset;
|
||||||
|
|
||||||
fixed_t shadowscale;
|
fixed_t shadowscale;
|
||||||
|
UINT8 color; // palette index
|
||||||
|
|
||||||
INT16 clipbot[MAXVIDWIDTH], cliptop[MAXVIDWIDTH];
|
INT16 clipbot[MAXVIDWIDTH], cliptop[MAXVIDWIDTH];
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue