Merge branch 'master' into better-splash

This commit is contained in:
Sally Coolatta 2022-09-16 05:00:13 -04:00
commit c936c797f0
16 changed files with 1355 additions and 48 deletions

View file

@ -584,6 +584,8 @@ typedef struct player_s
UINT8 stairjank;
UINT8 shrinkLaserDelay;
#ifdef HWRENDER
fixed_t fovadd; // adjust FOV for hw rendering
#endif

View file

@ -3755,6 +3755,15 @@ const char *const STATE_LIST[] = { // array length left dynamic for sanity testi
// Caked-Up Booty-Sheet Ghost
"S_HYUDORO",
// Grow
"S_GROW_PARTICLE",
// Shrink
"S_SHRINK_GUN",
"S_SHRINK_CHAIN",
"S_SHRINK_LASER",
"S_SHRINK_PARTICLE",
// The legend
"S_SINK",
"S_SINK_SHIELD",
@ -5337,6 +5346,14 @@ const char *const MOBJTYPE_LIST[] = { // array length left dynamic for sanity t
"MT_HYUDORO",
"MT_HYUDORO_CENTER",
"MT_GROW_PARTICLE",
"MT_SHRINK_POHBEE",
"MT_SHRINK_GUN",
"MT_SHRINK_CHAIN",
"MT_SHRINK_LASER",
"MT_SHRINK_PARTICLE",
"MT_SINK", // Kitchen Sink Stuff
"MT_SINK_SHIELD",
"MT_SINKTRAIL",

View file

@ -573,6 +573,9 @@ char sprnames[NUMSPRITES + 1][5] =
"FLML", // Flame Shield speed lines
"FLMF", // Flame Shield flash
"HYUU", // Hyudoro
"GRWP", // Grow
"POHB", // Shrink Poh-Bee
"SHRG", // Shrink gun / laser
"SINK", // Kitchen Sink
"SITR", // Kitchen Sink Trail
"KBLN", // Battle Mode Bumper
@ -4314,6 +4317,13 @@ state_t states[NUMSTATES] =
{SPR_HYUU, FF_FULLBRIGHT, -1, {NULL}, 0, 0, S_NULL}, // S_HYUDORO
{SPR_GRWP, FF_FULLBRIGHT|FF_ANIMATE, 13, {NULL}, 7, 1, S_NULL}, // S_GROW_PARTICLE
{SPR_SHRG, 0, -1, {NULL}, 0, 0, S_NULL}, // S_SHRINK_GUN
{SPR_POHB, 0, -1, {NULL}, 0, 0, S_NULL}, // S_SHRINK_CHAIN
{SPR_SHRG, FF_FULLBRIGHT|1, -1, {NULL}, 0, 0, S_NULL}, // S_SHRINK_LASER
{SPR_SHRG, FF_FULLBRIGHT|2, -1, {NULL}, 0, 0, S_NULL}, // S_SHRINK_PARTICLE
{SPR_SINK, 0, 1, {A_SmokeTrailer}, MT_SINKTRAIL, 0, S_SINK}, // S_SINK
{SPR_SINK, 0|FF_TRANS80|FF_FULLBRIGHT, -1, {NULL}, 0, 0, S_SINK_SHIELD}, // S_SINK_SHIELD
{SPR_SITR, 0, 1, {NULL}, 0, 0, S_SINKTRAIL2}, // S_SINKTRAIL1
@ -24036,6 +24046,168 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
S_NULL // raisestate
},
{ // MT_GROW_PARTICLE
-1, // doomednum
S_GROW_PARTICLE, // 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
4*FRACUNIT, // radius
8*FRACUNIT, // height
0, // display offset
0, // mass
0, // damage
sfx_None, // activesound
MF_SCENERY|MF_NOCLIP|MF_NOCLIPTHING|MF_NOCLIPHEIGHT|MF_NOGRAVITY|MF_DONTENCOREMAP, // flags
S_NULL // raisestate
},
{ // MT_SHRINK_POHBEE
-1, // doomednum
S_HYUDORO, // 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
32*FRACUNIT, // radius
24*FRACUNIT, // height
0, // display offset
0, // mass
0, // damage
sfx_None, // activesound
MF_NOCLIP|MF_NOCLIPTHING|MF_NOCLIPHEIGHT|MF_NOGRAVITY|MF_DONTENCOREMAP, // flags
S_NULL // raisestate
},
{ // MT_SHRINK_GUN
-1, // doomednum
S_SHRINK_GUN, // 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
52*FRACUNIT, // radius
120*FRACUNIT, // height
0, // display offset
0, // mass
0, // damage
sfx_None, // activesound
MF_SPECIAL|MF_NOCLIP|MF_NOCLIPHEIGHT|MF_NOGRAVITY|MF_DONTENCOREMAP, // flags
S_NULL // raisestate
},
{ // MT_SHRINK_CHAIN
-1, // doomednum
S_SHRINK_CHAIN, // 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
26*FRACUNIT, // radius
26*FRACUNIT, // height
0, // display offset
0, // mass
0, // damage
sfx_None, // activesound
MF_SCENERY|MF_NOCLIP|MF_NOCLIPTHING|MF_NOCLIPHEIGHT|MF_NOGRAVITY|MF_DONTENCOREMAP, // flags
S_NULL // raisestate
},
{ // MT_SHRINK_LASER
-1, // doomednum
S_SHRINK_LASER, // 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
16*FRACUNIT, // radius
33*FRACUNIT, // height
0, // display offset
0, // mass
0, // damage
sfx_None, // activesound
MF_SCENERY|MF_NOCLIP|MF_NOCLIPTHING|MF_NOCLIPHEIGHT|MF_NOGRAVITY|MF_DONTENCOREMAP, // flags
S_NULL // raisestate
},
{ // MT_SHRINK_PARTICLE
-1, // doomednum
S_SHRINK_PARTICLE, // 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
26*FRACUNIT, // radius
26*FRACUNIT, // height
0, // display offset
0, // mass
0, // damage
sfx_None, // activesound
MF_SPECIAL|MF_NOCLIP|MF_NOCLIPHEIGHT|MF_NOGRAVITY|MF_DONTENCOREMAP, // flags
S_NULL // raisestate
},
{ // MT_SINK
-1, // doomednum
S_SINK, // spawnstate

View file

@ -1119,6 +1119,9 @@ typedef enum sprite
SPR_FLML, // Flame Shield speed lines
SPR_FLMF, // Flame Shield flash
SPR_HYUU, // Hyudoro
SPR_GRWP, // Grow
SPR_POHB, // Shrink Poh-Bee
SPR_SHRG, // Shrink gun / laser
SPR_SINK, // Kitchen Sink
SPR_SITR, // Kitchen Sink Trail
SPR_KBLN, // Battle Mode Bumper
@ -4745,6 +4748,15 @@ typedef enum state
// Caked-Up Booty-Sheet Ghost
S_HYUDORO,
// Grow
S_GROW_PARTICLE,
// Shrink
S_SHRINK_GUN,
S_SHRINK_CHAIN,
S_SHRINK_LASER,
S_SHRINK_PARTICLE,
// The legend
S_SINK,
S_SINK_SHIELD,
@ -6363,6 +6375,14 @@ typedef enum mobj_type
MT_HYUDORO,
MT_HYUDORO_CENTER,
MT_GROW_PARTICLE,
MT_SHRINK_POHBEE,
MT_SHRINK_GUN,
MT_SHRINK_CHAIN,
MT_SHRINK_LASER,
MT_SHRINK_PARTICLE,
MT_SINK, // Kitchen Sink Stuff
MT_SINK_SHIELD,
MT_SINKTRAIL,

View file

@ -425,6 +425,16 @@ static BlockItReturn_t K_FindObjectsForNudging(mobj_t *thing)
case MT_BUBBLESHIELDTRAP:
K_AddDodgeObject(thing, side, 20);
break;
case MT_SHRINK_GUN:
if (thing->target == globalsmuggle.botmo)
{
K_AddAttackObject(thing, side, 20);
}
else
{
K_AddDodgeObject(thing, side, 20);
}
break;
case MT_RANDOMITEM:
if (anglediff >= 45)
{

View file

@ -355,7 +355,7 @@ static INT32 K_KartItemOddsRace[NUMKARTRESULTS-1][8] =
//P-Odds 0 1 2 3 4 5 6 7
/*Sneaker*/ { 0, 0, 2, 4, 6, 0, 0, 0 }, // Sneaker
/*Rocket Sneaker*/ { 0, 0, 0, 0, 0, 2, 4, 6 }, // Rocket Sneaker
/*Invincibility*/ { 0, 0, 0, 0, 3, 4, 6, 9 }, // Invincibility
/*Invincibility*/ { 0, 0, 0, 0, 3, 4, 5, 7 }, // Invincibility
/*Banana*/ { 2, 3, 1, 0, 0, 0, 0, 0 }, // Banana
/*Eggman Monitor*/ { 1, 2, 0, 0, 0, 0, 0, 0 }, // Eggman Monitor
/*Orbinaut*/ { 5, 5, 2, 2, 0, 0, 0, 0 }, // Orbinaut
@ -365,7 +365,7 @@ static INT32 K_KartItemOddsRace[NUMKARTRESULTS-1][8] =
/*Ballhog*/ { 0, 0, 2, 2, 0, 0, 0, 0 }, // Ballhog
/*Self-Propelled Bomb*/ { 0, 0, 0, 0, 0, 2, 4, 0 }, // Self-Propelled Bomb
/*Grow*/ { 0, 0, 0, 1, 2, 3, 0, 0 }, // Grow
/*Shrink*/ { 0, 0, 0, 0, 0, 0, 2, 0 }, // Shrink
/*Shrink*/ { 0, 0, 0, 0, 0, 1, 3, 2 }, // Shrink
/*Lightning Shield*/ { 1, 0, 0, 0, 0, 0, 0, 0 }, // Lightning Shield
/*Bubble Shield*/ { 0, 1, 2, 1, 0, 0, 0, 0 }, // Bubble Shield
/*Flame Shield*/ { 0, 0, 0, 0, 0, 1, 3, 5 }, // Flame Shield
@ -375,7 +375,7 @@ static INT32 K_KartItemOddsRace[NUMKARTRESULTS-1][8] =
/*Kitchen Sink*/ { 0, 0, 0, 0, 0, 0, 0, 0 }, // Kitchen Sink
/*Drop Target*/ { 3, 0, 0, 0, 0, 0, 0, 0 }, // Drop Target
/*Sneaker x2*/ { 0, 0, 2, 2, 2, 0, 0, 0 }, // Sneaker x2
/*Sneaker x3*/ { 0, 0, 0, 1, 6,10, 5, 0 }, // Sneaker x3
/*Sneaker x3*/ { 0, 0, 0, 1, 6, 9, 5, 0 }, // Sneaker x3
/*Banana x3*/ { 0, 1, 1, 0, 0, 0, 0, 0 }, // Banana x3
/*Banana x10*/ { 0, 0, 0, 1, 0, 0, 0, 0 }, // Banana x10
/*Orbinaut x3*/ { 0, 0, 1, 0, 0, 0, 0, 0 }, // Orbinaut x3
@ -2284,6 +2284,77 @@ void K_SpawnInvincibilitySpeedLines(mobj_t *mo)
fast->destscale = 6*((mo->player->invincibilitytimer/TICRATE)*FRACUNIT)/8;
}
static void K_SpawnGrowShrinkParticles(mobj_t *mo, INT32 timer)
{
const boolean shrink = (timer < 0);
const INT32 maxTime = (10*TICRATE);
const INT32 noTime = (2*TICRATE);
INT32 spawnFreq = 1;
mobj_t *particle = NULL;
fixed_t particleScale = FRACUNIT;
fixed_t particleSpeed = 0;
spawnFreq = abs(timer);
if (spawnFreq < noTime)
{
return;
}
spawnFreq -= noTime;
if (spawnFreq > maxTime)
{
spawnFreq = maxTime;
}
spawnFreq = (maxTime - spawnFreq) / TICRATE / 4;
if (spawnFreq == 0)
{
spawnFreq++;
}
if (leveltime % spawnFreq != 0)
{
return;
}
particle = P_SpawnMobjFromMobj(
mo,
P_RandomRange(-32, 32) * FRACUNIT,
P_RandomRange(-32, 32) * FRACUNIT,
(P_RandomRange(0, 24) + (shrink ? 48 : 0)) * FRACUNIT,
MT_GROW_PARTICLE
);
P_SetTarget(&particle->target, mo);
particle->momx = mo->momx;
particle->momy = mo->momy;
particle->momz = P_GetMobjZMovement(mo);
K_MatchGenericExtraFlags(particle, mo);
particleScale = FixedMul((shrink ? SHRINK_PHYSICS_SCALE : GROW_PHYSICS_SCALE), mapobjectscale);
particleSpeed = mo->scale * 4 * P_MobjFlip(mo); // NOT particleScale
particle->destscale = particleScale;
P_SetScale(particle, particle->destscale);
if (shrink == true)
{
particle->color = SKINCOLOR_KETCHUP;
particle->momz -= particleSpeed;
particle->renderflags |= RF_VERTICALFLIP;
}
else
{
particle->color = SKINCOLOR_SAPPHIRE;
particle->momz += particleSpeed;
}
}
void K_SpawnBumpEffect(mobj_t *mo)
{
mobj_t *fx = P_SpawnMobj(mo->x, mo->y, mo->z, MT_BUMP);
@ -3643,7 +3714,7 @@ void K_SpinPlayer(player_t *player, mobj_t *inflictor, mobj_t *source, INT32 typ
P_SetPlayerMobjState(player->mo, S_KART_SPINOUT);
}
static void K_RemoveGrowShrink(player_t *player)
void K_RemoveGrowShrink(player_t *player)
{
if (player->mo && !P_MobjWasRemoved(player->mo))
{
@ -5582,46 +5653,12 @@ void K_DoSneaker(player_t *player, INT32 type)
static void K_DoShrink(player_t *user)
{
INT32 i;
mobj_t *mobj, *next;
S_StartSound(user->mo, sfx_kc46); // Sound the BANG!
user->pflags |= PF_ATTACKDOWN;
for (i = 0; i < MAXPLAYERS; i++)
{
if (!playeringame[i] || players[i].spectator || !players[i].mo)
continue;
if (&players[i] == user)
continue;
if (players[i].position < user->position)
{
//P_FlashPal(&players[i], PAL_NUKE, 10);
// Grow should get taken away.
if (players[i].growshrinktimer > 0)
K_RemoveGrowShrink(&players[i]);
else
{
// Start shrinking!
K_DropItems(&players[i]);
players[i].growshrinktimer = -(15*TICRATE);
if (players[i].mo && !P_MobjWasRemoved(players[i].mo))
{
players[i].mo->scalespeed = mapobjectscale/TICRATE;
players[i].mo->destscale = FixedMul(mapobjectscale, SHRINK_SCALE);
if (K_PlayerShrinkCheat(&players[i]) == true)
{
players[i].mo->destscale = FixedMul(players[i].mo->destscale, SHRINK_SCALE);
}
S_StartSound(players[i].mo, sfx_kc59);
}
}
}
}
Obj_CreateShrinkPohbees(user);
// kill everything in the kitem list while we're at it:
for (mobj = kitemcap; mobj; mobj = next)
@ -7356,6 +7393,11 @@ void K_KartPlayerThink(player_t *player, ticcmd_t *cmd)
}
}
if (player->growshrinktimer != 0)
{
K_SpawnGrowShrinkParticles(player->mo, player->growshrinktimer);
}
if (gametype == GT_RACE && player->rings <= 0) // spawn ring debt indicator
{
mobj_t *debtflag = P_SpawnMobj(player->mo->x + player->mo->momx, player->mo->y + player->mo->momy,
@ -7520,6 +7562,9 @@ void K_KartPlayerThink(player_t *player, ticcmd_t *cmd)
comebackshowninfo = true; // client has already seen the message
}
if (player->shrinkLaserDelay)
player->shrinkLaserDelay--;
if (player->ringdelay)
player->ringdelay--;
@ -10020,7 +10065,7 @@ void K_MoveKartPlayer(player_t *player, boolean onground)
}
// TODO: gametyperules
player->growshrinktimer = (gametype == GT_BATTLE ? 8 : 12) * TICRATE;
player->growshrinktimer = max(player->growshrinktimer, (gametype == GT_BATTLE ? 8 : 12) * TICRATE);
if (player->invincibilitytimer > 0)
{

View file

@ -71,6 +71,7 @@ void K_AwardPlayerRings(player_t *player, INT32 rings, boolean overload);
void K_DoInstashield(player_t *player);
void K_DoPowerClash(player_t *t1, player_t *t2);
void K_BattleAwardHit(player_t *player, player_t *victim, mobj_t *inflictor, UINT8 bumpersRemoved);
void K_RemoveGrowShrink(player_t *player);
void K_SpinPlayer(player_t *player, mobj_t *inflictor, mobj_t *source, INT32 type);
void K_TumblePlayer(player_t *player, mobj_t *inflictor, mobj_t *source);
void K_TumbleInterrupt(player_t *player);

View file

@ -8,4 +8,11 @@ void Obj_HyudoroThink(mobj_t *actor);
void Obj_HyudoroCenterThink(mobj_t *actor);
void Obj_HyudoroCollide(mobj_t *special, mobj_t *toucher);
/* Shrink */
void Obj_PohbeeThinker(mobj_t *pohbee);
void Obj_PohbeeRemoved(mobj_t *pohbee);
void Obj_ShrinkGunRemoved(mobj_t *gun);
boolean Obj_ShrinkLaserCollide(mobj_t *gun, mobj_t *victim);
void Obj_CreateShrinkPohbees(player_t *owner);
#endif/*k_objects_H*/

View file

@ -1101,6 +1101,40 @@ static boolean K_WaypointPathfindReachedGScore(void *data, void *setupData)
return scoreReached;
}
/*--------------------------------------------------
static boolean K_WaypointPathfindReachedGScoreSpawnable(void *data, void *setupData)
Returns if the current waypoint data reaches our end G score.
Input Arguments:-
data - Should point to a pathfindnode_t to compare
setupData - Should point to the pathfindsetup_t to compare
Return:-
True if the waypoint reached the G score, false otherwise.
--------------------------------------------------*/
static boolean K_WaypointPathfindReachedGScoreSpawnable(void *data, void *setupData)
{
boolean scoreReached = false;
boolean spawnable = false;
if (data == NULL || setupData == NULL)
{
CONS_Debug(DBG_GAMELOGIC, "K_WaypointPathfindReachedGScoreSpawnable received NULL data.\n");
}
else
{
pathfindnode_t *node = (pathfindnode_t *)data;
pathfindsetup_t *setup = (pathfindsetup_t *)setupData;
waypoint_t *wp = (waypoint_t *)node->nodedata;
scoreReached = (node->gscore >= setup->endgscore);
spawnable = K_GetWaypointIsSpawnpoint(wp);
}
return (scoreReached && spawnable);
}
/*--------------------------------------------------
boolean K_PathfindToWaypoint(
waypoint_t *const sourcewaypoint,
@ -1266,6 +1300,89 @@ boolean K_PathfindThruCircuit(
return pathfound;
}
/*--------------------------------------------------
boolean K_PathfindThruCircuitSpawnable(
waypoint_t *const sourcewaypoint,
const UINT32 traveldistance,
path_t *const returnpath,
const boolean useshortcuts,
const boolean huntbackwards)
See header file for description.
--------------------------------------------------*/
boolean K_PathfindThruCircuitSpawnable(
waypoint_t *const sourcewaypoint,
const UINT32 traveldistance,
path_t *const returnpath,
const boolean useshortcuts,
const boolean huntbackwards)
{
boolean pathfound = false;
if (sourcewaypoint == NULL)
{
CONS_Debug(DBG_GAMELOGIC, "NULL sourcewaypoint in K_PathfindThruCircuitSpawnable.\n");
}
else if (finishline == NULL)
{
CONS_Debug(DBG_GAMELOGIC, "NULL finishline in K_PathfindThruCircuitSpawnable.\n");
}
else if (((huntbackwards == false) && (sourcewaypoint->numnextwaypoints == 0))
|| ((huntbackwards == true) && (sourcewaypoint->numprevwaypoints == 0)))
{
CONS_Debug(DBG_GAMELOGIC,
"K_PathfindThruCircuitSpawnable: sourcewaypoint with ID %d has no next waypoint\n",
K_GetWaypointID(sourcewaypoint));
}
else if (((huntbackwards == false) && (finishline->numprevwaypoints == 0))
|| ((huntbackwards == true) && (finishline->numnextwaypoints == 0)))
{
CONS_Debug(DBG_GAMELOGIC,
"K_PathfindThruCircuitSpawnable: finishline with ID %d has no previous waypoint\n",
K_GetWaypointID(finishline));
}
else
{
pathfindsetup_t pathfindsetup = {0};
getconnectednodesfunc nextnodesfunc = K_WaypointPathfindGetNext;
getnodeconnectioncostsfunc nodecostsfunc = K_WaypointPathfindGetNextCosts;
getnodeheuristicfunc heuristicfunc = K_WaypointPathfindGetHeuristic;
getnodetraversablefunc traversablefunc = K_WaypointPathfindTraversableNoShortcuts;
getpathfindfinishedfunc finishedfunc = K_WaypointPathfindReachedGScoreSpawnable;
if (huntbackwards)
{
nextnodesfunc = K_WaypointPathfindGetPrev;
nodecostsfunc = K_WaypointPathfindGetPrevCosts;
}
if (useshortcuts)
{
traversablefunc = K_WaypointPathfindTraversableAllEnabled;
}
pathfindsetup.opensetcapacity = K_GetOpensetBaseSize();
pathfindsetup.closedsetcapacity = K_GetClosedsetBaseSize();
pathfindsetup.nodesarraycapacity = K_GetNodesArrayBaseSize();
pathfindsetup.startnodedata = sourcewaypoint;
pathfindsetup.endnodedata = finishline;
pathfindsetup.endgscore = traveldistance;
pathfindsetup.getconnectednodes = nextnodesfunc;
pathfindsetup.getconnectioncosts = nodecostsfunc;
pathfindsetup.getheuristic = heuristicfunc;
pathfindsetup.gettraversable = traversablefunc;
pathfindsetup.getfinished = finishedfunc;
pathfound = K_PathfindAStar(returnpath, &pathfindsetup);
K_UpdateOpensetBaseSize(pathfindsetup.opensetcapacity);
K_UpdateClosedsetBaseSize(pathfindsetup.closedsetcapacity);
K_UpdateNodesArrayBaseSize(pathfindsetup.nodesarraycapacity);
}
return pathfound;
}
/*--------------------------------------------------
waypoint_t *K_GetNextWaypointToDestination(
waypoint_t *const sourcewaypoint,
@ -2044,6 +2161,7 @@ boolean K_SetupWaypointList(void)
// Loop through the waypointcap here so that all waypoints are added to the heap, and allow easier debugging
for (waypointmobj = waypointcap; waypointmobj; waypointmobj = waypointmobj->tracer)
{
waypointmobj->cusval = (INT32)numwaypoints;
K_SetupWaypoint(waypointmobj);
}

View file

@ -245,6 +245,36 @@ boolean K_PathfindThruCircuit(
const boolean huntbackwards);
/*--------------------------------------------------
boolean K_PathfindThruCircuitSpawnable(
waypoint_t *const sourcewaypoint,
const UINT32 traveldistance,
path_t *const returnpath,
const boolean useshortcuts,
const boolean huntbackwards)
The same as K_PathfindThruCircuit, but continues until hitting a waypoint that
can be respawned at.
Input Arguments:-
sourcewaypoint - The waypoint to start searching from
traveldistance - How far along the circuit it will try to pathfind.
returnpath - The path_t that will contain the final found path
useshortcuts - Whether to use waypoints that are marked as being shortcuts in the search
huntbackwards - Goes through the waypoints backwards if true
Return:-
True if a circuit path could be constructed, false if it couldn't.
--------------------------------------------------*/
boolean K_PathfindThruCircuitSpawnable(
waypoint_t *const sourcewaypoint,
const UINT32 traveldistance,
path_t *const returnpath,
const boolean useshortcuts,
const boolean huntbackwards);
/*--------------------------------------------------
waypoint_t *K_GetNextWaypointToDestination(
waypoint_t *const sourcewaypoint,

View file

@ -1 +1,2 @@
hyudoro.c
shrink.c

782
src/objects/shrink.c Normal file
View file

@ -0,0 +1,782 @@
// DR. ROBOTNIK'S RING RACERS
//-----------------------------------------------------------------------------
// Copyright (C) 2022 by Sally "TehRealSalt" Cochenour
// Copyright (C) 2022 by Kart Krew
//
// This program is free software distributed under the
// terms of the GNU General Public License, version 2.
// See the 'LICENSE' file for more details.
//-----------------------------------------------------------------------------
/// \file shrink.c
/// \brief Shrink laser item code.
#include "../doomdef.h"
#include "../doomstat.h"
#include "../info.h"
#include "../k_kart.h"
#include "../k_objects.h"
#include "../m_random.h"
#include "../p_local.h"
#include "../r_main.h"
#include "../s_sound.h"
#include "../g_game.h"
#include "../z_zone.h"
#include "../k_waypoint.h"
//
// ███████╗██╗██╗░░██╗███╗░░░███╗███████╗
// ██╔════╝██║╚██╗██╔╝████╗░████║██╔════╝
// █████╗░░██║░╚███╔╝░██╔████╔██║█████╗░░
// ██╔══╝░░██║░██╔██╗░██║╚██╔╝██║██╔══╝░░
// ██║░░░░░██║██╔╝╚██╗██║░╚═╝░██║███████╗
// ╚═╝░░░░░╚═╝╚═╝░░╚═╝╚═╝░░░░░╚═╝╚══════╝
//
// vertical flip
//
#define POHBEE_HOVER (256 << FRACBITS)
#define POHBEE_SPEED (128 << FRACBITS)
#define POHBEE_TIME (30 * TICRATE)
#define POHBEE_DIST (4096 << FRACBITS)
#define GUN_SWING (ANGLE_90 - ANG10)
#define GUN_SWINGTIME (4 * TICRATE)
#define CHAIN_SIZE (52)
#define EXTRA_FOR_FIRST (7)
enum
{
POHBEE_MODE_SPAWN,
POHBEE_MODE_ACT,
POHBEE_MODE_DESPAWN,
};
#define pohbee_mode(o) ((o)->cusval)
#define pohbee_timer(o) ((o)->reactiontime)
#define pohbee_waypoint_cur(o) ((o)->extravalue1)
#define pohbee_waypoint_dest(o) ((o)->extravalue2)
#define pohbee_height(o) ((o)->movefactor)
#define pohbee_owner(o) ((o)->target)
#define pohbee_guns(o) ((o)->hnext)
#define gun_offset(o) ((o)->movecount)
#define gun_numsegs(o) ((o)->extravalue1)
#define gun_pohbee(o) ((o)->target)
#define gun_laser(o) ((o)->tracer)
#define gun_chains(o) ((o)->hprev)
#define chain_index(o) ((o)->extravalue1)
enum
{
LASER_SHRINK,
LASER_GROW,
};
static skincolornum_t ShrinkLaserColor(mobj_t *pohbee)
{
UINT8 laserState = LASER_SHRINK;
player_t *owner = NULL;
if (pohbee_owner(pohbee) != NULL && P_MobjWasRemoved(pohbee_owner(pohbee)) == false)
{
owner = pohbee_owner(pohbee)->player;
}
if (owner != NULL && P_IsDisplayPlayer(owner) == true)
{
laserState = LASER_GROW;
if (r_splitscreen > 0 && (leveltime & 1))
{
// TODO: make this properly screen dependent,
// instead of flashing.
laserState = LASER_SHRINK;
}
}
switch (laserState)
{
default:
case LASER_SHRINK:
return SKINCOLOR_KETCHUP;
case LASER_GROW:
return SKINCOLOR_SAPPHIRE;
}
}
static boolean ShrinkLaserActive(mobj_t *pohbee)
{
return (pohbee_mode(pohbee) == POHBEE_MODE_ACT);
}
static void PohbeeMoveTo(mobj_t *pohbee, fixed_t destx, fixed_t desty, fixed_t destz)
{
pohbee->momx = destx - pohbee->x;
pohbee->momy = desty - pohbee->y;
pohbee->momz = destz - pohbee->z;
}
static fixed_t GenericDistance(
fixed_t curx, fixed_t cury, fixed_t curz,
fixed_t destx, fixed_t desty, fixed_t destz)
{
return P_AproxDistance(P_AproxDistance(destx - curx, desty - cury), destz - curz);
}
static fixed_t PohbeeWaypointZ(mobj_t *pohbee, mobj_t *dest)
{
return dest->z + (pohbee_height(pohbee) + FixedMul(POHBEE_HOVER, mapobjectscale) * P_MobjFlip(dest));
}
static void PohbeeSpawn(mobj_t *pohbee)
{
waypoint_t *curWaypoint = NULL;
waypoint_t *destWaypoint = NULL;
fixed_t distLeft = INT32_MAX;
fixed_t newX = pohbee->x;
fixed_t newY = pohbee->y;
fixed_t newZ = pohbee->z;
boolean finalize = false;
const boolean useshortcuts = false;
const boolean huntbackwards = false;
boolean pathfindsuccess = false;
path_t pathtofinish = {0};
size_t pathIndex = 0;
curWaypoint = K_GetWaypointFromIndex((size_t)pohbee_waypoint_cur(pohbee));
destWaypoint = K_GetWaypointFromIndex((size_t)pohbee_waypoint_dest(pohbee));
if (curWaypoint == NULL || destWaypoint == NULL)
{
// Waypoints aren't valid.
// Just transition into the next state.
pohbee_mode(pohbee) = POHBEE_MODE_ACT;
return;
}
distLeft = FixedMul(POHBEE_SPEED, mapobjectscale);
while (distLeft > 0)
{
fixed_t wpX = curWaypoint->mobj->x;
fixed_t wpY = curWaypoint->mobj->y;
fixed_t wpZ = PohbeeWaypointZ(pohbee, curWaypoint->mobj);
fixed_t distToNext = GenericDistance(
newX, newY, newZ,
wpX, wpY, wpZ
);
if (distToNext > distLeft)
{
// Only made it partially there.
newX += FixedMul(FixedDiv(wpX - newX, distToNext), distLeft);
newY += FixedMul(FixedDiv(wpY - newY, distToNext), distLeft);
newZ += FixedMul(FixedDiv(wpZ - newZ, distToNext), distLeft);
distLeft = 0;
}
else
{
// Close enough to the next waypoint,
// move there and remove the distance.
newX = wpX;
newY = wpY;
newZ = wpZ;
distLeft -= distToNext;
if (curWaypoint == destWaypoint)
{
// Reached the end.
finalize = true;
break;
}
// Create waypoint path to our destination.
// Crazy over-engineered, just to catch when
// waypoints are insanely close to each other :P
if (pathfindsuccess == false)
{
pathfindsuccess = K_PathfindToWaypoint(
curWaypoint, destWaypoint,
&pathtofinish,
useshortcuts, huntbackwards
);
if (pathfindsuccess == false)
{
// Path isn't valid.
// Just transition into the next state.
finalize = true;
break;
}
}
pathIndex++;
if (pathIndex >= pathtofinish.numnodes)
{
// Successfully reached the end of the path.
finalize = true;
break;
}
// Now moving to the next waypoint.
curWaypoint = (waypoint_t *)pathtofinish.array[pathIndex].nodedata;
pohbee_waypoint_cur(pohbee) = (INT32)K_GetWaypointHeapIndex(curWaypoint);
}
}
PohbeeMoveTo(pohbee, newX, newY, newZ);
pohbee->angle = K_MomentumAngle(pohbee);
if (finalize == true)
{
// Move to next state
pohbee_mode(pohbee) = POHBEE_MODE_ACT;
}
if (pathfindsuccess == true)
{
Z_Free(pathtofinish.array);
}
}
static void PohbeeAct(mobj_t *pohbee)
{
pohbee_timer(pohbee)--;
if (pohbee_timer(pohbee) <= 0)
{
// Move to next state
pohbee_mode(pohbee) = POHBEE_MODE_DESPAWN;
pohbee->fuse = 5*TICRATE;
}
}
static void PohbeeDespawn(mobj_t *pohbee)
{
pohbee->momz = 16 * pohbee->scale * P_MobjFlip(pohbee);
}
static void DoGunSwing(mobj_t *gun, mobj_t *pohbee)
{
const angle_t angle = gun->angle + ANGLE_90;
const tic_t swingTimer = leveltime + gun_offset(gun);
const angle_t swingAmt = swingTimer * (ANGLE_MAX / GUN_SWINGTIME);
const fixed_t swingCos = FINECOSINE(swingAmt >> ANGLETOFINESHIFT);
const angle_t pitch = -ANGLE_90 + FixedMul(swingCos, GUN_SWING);
const fixed_t dist = gun_numsegs(gun) * CHAIN_SIZE * gun->scale;
fixed_t offsetX = FixedMul(
dist, FixedMul(
FINECOSINE(angle >> ANGLETOFINESHIFT),
FINECOSINE(pitch >> ANGLETOFINESHIFT)
)
);
fixed_t offsetY = FixedMul(
dist, FixedMul(
FINESINE(angle >> ANGLETOFINESHIFT),
FINECOSINE(pitch >> ANGLETOFINESHIFT)
)
);
fixed_t offsetZ = FixedMul(
dist, FINESINE(pitch >> ANGLETOFINESHIFT)
);
PohbeeMoveTo(gun, pohbee->x + offsetX, pohbee->y + offsetY, pohbee->z + offsetZ);
}
static void ShrinkLaserThinker(mobj_t *pohbee, mobj_t *gun, mobj_t *laser)
{
const fixed_t gunX = gun->x + gun->momx;
const fixed_t gunY = gun->y + gun->momy;
const fixed_t gunZ = P_GetMobjFeet(gun) + gun->momz;
PohbeeMoveTo(laser, gunX, gunY, gun->floorz);
if (ShrinkLaserActive(pohbee) == true)
{
mobj_t *particle = NULL;
laser->renderflags &= ~RF_DONTDRAW;
laser->color = gun->color;
if (leveltime & 1)
{
laser->spritexscale = 5*FRACUNIT/2;
}
else
{
laser->spritexscale = FRACUNIT;
}
laser->spriteyscale = FixedDiv(FixedDiv(gunZ - gun->floorz, mapobjectscale), laser->info->height);
particle = P_SpawnMobjFromMobj(
laser,
P_RandomRange(-16, 16) * FRACUNIT,
P_RandomRange(-16, 16) * FRACUNIT,
0,
MT_SHRINK_PARTICLE
);
P_SetTarget(&gun_pohbee(particle), pohbee);
particle->color = laser->color;
P_SetScale(particle, particle->scale * 2);
particle->destscale = 0;
//particle->momz = 2 * particle->scale * P_MobjFlip(particle);
}
else
{
laser->renderflags |= RF_DONTDRAW;
}
}
static void DoGunChains(mobj_t *gun, mobj_t *pohbee)
{
const fixed_t gunX = gun->x + gun->momx;
const fixed_t gunY = gun->y + gun->momy;
const fixed_t gunZ = P_GetMobjHead(gun) + gun->momz;
const fixed_t beeX = pohbee->x + pohbee->momx;
const fixed_t beeY = pohbee->y + pohbee->momy;
const fixed_t beeZ = P_GetMobjFeet(pohbee) + pohbee->momz;
const fixed_t offsetX = (beeX - gunX) / gun_numsegs(gun);
const fixed_t offsetY = (beeY - gunY) / gun_numsegs(gun);
const fixed_t offsetZ = (beeZ - gunZ) / gun_numsegs(gun);
mobj_t *chain = NULL;
fixed_t curX = gunX + (offsetX / 2);
fixed_t curY = gunY + (offsetY / 2);
fixed_t curZ = gunZ + (offsetZ / 2);
chain = gun_chains(gun);
while (chain != NULL && P_MobjWasRemoved(chain) == false)
{
PohbeeMoveTo(chain, curX, curY, curZ);
curX += offsetX;
curY += offsetY;
curZ += offsetZ;
chain = gun_chains(chain);
}
}
static void ShrinkGunThinker(mobj_t *gun)
{
mobj_t *pohbee = gun_pohbee(gun);
if (pohbee == NULL || P_MobjWasRemoved(pohbee) == true)
{
P_RemoveMobj(gun);
return;
}
gun->angle = pohbee->angle;
gun->color = ShrinkLaserColor(pohbee);
DoGunSwing(gun, pohbee);
if (gun_laser(gun) != NULL && P_MobjWasRemoved(gun_laser(gun)) == false)
{
ShrinkLaserThinker(pohbee, gun, gun_laser(gun));
}
DoGunChains(gun, pohbee);
}
void Obj_PohbeeThinker(mobj_t *pohbee)
{
mobj_t *gun = NULL;
pohbee->momx = pohbee->momy = pohbee->momz = 0;
switch (pohbee_mode(pohbee))
{
case POHBEE_MODE_SPAWN:
PohbeeSpawn(pohbee);
break;
case POHBEE_MODE_ACT:
PohbeeAct(pohbee);
break;
case POHBEE_MODE_DESPAWN:
PohbeeDespawn(pohbee);
break;
default:
// failsafe
pohbee_mode(pohbee) = POHBEE_MODE_SPAWN;
break;
}
gun = pohbee_guns(pohbee);
while (gun != NULL && P_MobjWasRemoved(gun) == false)
{
ShrinkGunThinker(gun);
gun = pohbee_guns(gun);
}
}
void Obj_PohbeeRemoved(mobj_t *pohbee)
{
mobj_t *gun = pohbee_guns(pohbee);
while (gun != NULL && P_MobjWasRemoved(gun) == false)
{
mobj_t *nextGun = pohbee_guns(gun);
P_RemoveMobj(gun);
gun = nextGun;
}
}
void Obj_ShrinkGunRemoved(mobj_t *gun)
{
mobj_t *chain = NULL;
if (gun_laser(gun) != NULL && P_MobjWasRemoved(gun_laser(gun)) == false)
{
P_RemoveMobj(gun_laser(gun));
}
chain = gun_chains(gun);
while (chain != NULL && P_MobjWasRemoved(chain) == false)
{
mobj_t *nextChain = gun_chains(chain);
P_RemoveMobj(chain);
chain = nextChain;
}
}
boolean Obj_ShrinkLaserCollide(mobj_t *gun, mobj_t *victim)
{
mobj_t *pohbee = gun_pohbee(gun);
mobj_t *owner = NULL;
INT32 prevTimer = 0;
if (pohbee == NULL || P_MobjWasRemoved(pohbee) == true)
{
return true;
}
if (ShrinkLaserActive(pohbee) == false)
{
return true;
}
if (victim->player->shrinkLaserDelay > 0)
{
victim->player->shrinkLaserDelay = TICRATE;
return true;
}
victim->player->shrinkLaserDelay = TICRATE;
owner = pohbee_owner(pohbee);
prevTimer = victim->player->growshrinktimer;
if (owner != NULL && victim == owner)
{
// Belongs to us. Give us Grow!
if (prevTimer < 0)
{
// Take away Shrink.
K_RemoveGrowShrink(victim->player);
}
else
{
victim->player->growshrinktimer += 3*TICRATE;
S_StartSound(victim, sfx_kc5a);
if (prevTimer <= 0)
{
victim->scalespeed = mapobjectscale/TICRATE;
victim->destscale = FixedMul(mapobjectscale, GROW_SCALE);
if (K_PlayerShrinkCheat(victim->player) == true)
{
victim->destscale = FixedMul(victim->destscale, SHRINK_SCALE);
}
if (victim->player->invincibilitytimer > 0)
{
; // invincibility has priority in P_RestoreMusic, no point in starting here
}
else if (P_IsLocalPlayer(victim->player) == true)
{
S_ChangeMusicSpecial("kgrow");
}
else //used to be "if (P_IsDisplayPlayer(victim->player) == false)"
{
S_StartSound(victim, (cv_kartinvinsfx.value ? sfx_alarmg : sfx_kgrow));
}
P_RestoreMusic(victim->player);
}
}
}
else
{
if (prevTimer > 0)
{
// Take away Grow.
K_RemoveGrowShrink(victim->player);
}
else
{
// Start shrinking!
victim->player->growshrinktimer -= 5*TICRATE;
S_StartSound(victim, sfx_kc59);
if (prevTimer >= 0)
{
//K_DropItems(victim->player);
victim->scalespeed = mapobjectscale/TICRATE;
victim->destscale = FixedMul(mapobjectscale, SHRINK_SCALE);
if (K_PlayerShrinkCheat(victim->player) == true)
{
victim->destscale = FixedMul(victim->destscale, SHRINK_SCALE);
}
}
}
}
return true;
}
static waypoint_t *GetPohbeeWaypoint(waypoint_t *anchor, const UINT32 traveldist, const boolean huntbackwards)
{
const boolean useshortcuts = false;
boolean pathfindsuccess = false;
path_t pathtofinish = {0};
waypoint_t *ret = NULL;
pathfindsuccess = K_PathfindThruCircuitSpawnable(
anchor, traveldist,
&pathtofinish,
useshortcuts, huntbackwards
);
if (pathfindsuccess == true)
{
ret = (waypoint_t *)pathtofinish.array[ pathtofinish.numnodes - 1 ].nodedata;
Z_Free(pathtofinish.array);
}
else
{
ret = anchor;
}
return ret;
}
static waypoint_t *GetPohbeeStart(waypoint_t *anchor)
{
const UINT32 traveldist = FixedMul(POHBEE_DIST >> 1, mapobjectscale) / FRACUNIT;
const boolean huntbackwards = true;
return GetPohbeeWaypoint(anchor, traveldist, huntbackwards);
}
static waypoint_t *GetPohbeeEnd(waypoint_t *anchor)
{
const UINT32 traveldist = FixedMul(POHBEE_DIST, mapobjectscale) / FRACUNIT;
const boolean huntbackwards = false;
return GetPohbeeWaypoint(anchor, traveldist, huntbackwards);
}
static void CreatePohbee(player_t *owner, waypoint_t *start, waypoint_t *end, UINT8 numLasers)
{
mobj_t *pohbee = NULL;
fixed_t size = 0;
INT32 baseSegs = INT32_MAX;
INT32 segVal = INT32_MAX;
mobj_t *prevGun = NULL;
size_t i, j;
if (owner == NULL || owner->mo == NULL || P_MobjWasRemoved(owner->mo) == true
|| start == NULL || end == NULL
|| numLasers == 0)
{
// Invalid inputs
return;
}
// Calculate number of chain segments added per laser.
size = FixedMul(end->mobj->radius, 3*FRACUNIT/2);
segVal = max(1, 1 + ((size / start->mobj->scale) / CHAIN_SIZE) / numLasers);
baseSegs = segVal * numLasers;
// Valid spawning conditions,
// we can start creating each individual part.
pohbee = P_SpawnMobjFromMobj(start->mobj, 0, 0, (baseSegs * CHAIN_SIZE * FRACUNIT) + POHBEE_HOVER * 3, MT_SHRINK_POHBEE);
P_SetTarget(&pohbee_owner(pohbee), owner->mo);
pohbee_mode(pohbee) = POHBEE_MODE_SPAWN;
pohbee_timer(pohbee) = POHBEE_TIME;
pohbee_height(pohbee) = size;
pohbee_waypoint_cur(pohbee) = (INT32)K_GetWaypointHeapIndex(start);
pohbee_waypoint_dest(pohbee) = (INT32)K_GetWaypointHeapIndex(end);
prevGun = pohbee;
for (i = 0; i < numLasers; i++)
{
const UINT8 numSegs = segVal * (i + 1);
mobj_t *gun = P_SpawnMobjFromMobj(pohbee, 0, 0, 0, MT_SHRINK_GUN);
mobj_t *laser = NULL;
mobj_t *prevChain = NULL;
P_SetTarget(&gun_pohbee(gun), pohbee);
P_SetTarget(&pohbee_guns(prevGun), gun);
gun_numsegs(gun) = numSegs;
gun_offset(gun) = P_RandomKey(GUN_SWINGTIME);
laser = P_SpawnMobjFromMobj(gun, 0, 0, 0, MT_SHRINK_LASER);
P_SetTarget(&gun_laser(gun), laser);
prevChain = gun;
for (j = 0; j < numSegs; j++)
{
mobj_t *chain = P_SpawnMobjFromMobj(gun, 0, 0, 0, MT_SHRINK_CHAIN);
P_SetTarget(&gun_chains(prevChain), chain);
chain_index(chain) = j;
prevChain = chain;
}
prevGun = gun;
}
}
void Obj_CreateShrinkPohbees(player_t *owner)
{
UINT8 ownerPos = 1;
struct {
waypoint_t *start;
waypoint_t *end;
UINT8 lasers;
boolean first;
} pohbees[MAXPLAYERS];
size_t numPohbees = 0;
size_t i, j;
if (owner == NULL || owner->mo == NULL || P_MobjWasRemoved(owner->mo) == true)
{
return;
}
ownerPos = owner->position;
for (i = 0; i < MAXPLAYERS; i++)
{
player_t *player = NULL;
waypoint_t *endWaypoint = NULL;
if (playeringame[i] == false)
{
// Not valid.
continue;
}
player = &players[i];
if (player->spectator == true)
{
// Not playing.
continue;
}
if (player->position > ownerPos)
{
// Too far behind.
continue;
}
if (player->nextwaypoint == NULL)
{
// No waypoint?
continue;
}
endWaypoint = GetPohbeeEnd(player->nextwaypoint);
for (j = 0; j < numPohbees; j++)
{
if (pohbees[j].end == endWaypoint)
{
// Increment laser count for the already existing poh-bee,
// if another one would occupy the same space.
pohbees[j].lasers++;
break;
}
}
if (j == numPohbees)
{
// Push a new poh-bee
pohbees[j].start = GetPohbeeStart(player->nextwaypoint);
pohbees[j].end = endWaypoint;
pohbees[j].lasers = 1;
if (player->position == 1)
{
pohbees[j].first = true;
}
numPohbees++;
}
}
for (i = 0; i < numPohbees; i++)
{
CreatePohbee(owner, pohbees[i].start, pohbees[i].end, pohbees[i].lasers);
if (pohbees[i].first == true)
{
// Add a chain of extra ones for 1st place.
waypoint_t *prev = pohbees[i].end;
for (j = 0; j < EXTRA_FOR_FIRST; j++)
{
waypoint_t *new = GetPohbeeEnd(prev);
CreatePohbee(owner, prev, new, 1);
prev = new;
}
}
}
}

View file

@ -32,6 +32,7 @@
#include "hu_stuff.h" // SRB2kart
#include "i_system.h" // SRB2kart
#include "k_terrain.h"
#include "k_objects.h"
#include "r_splats.h"
@ -739,6 +740,81 @@ static BlockItReturn_t PIT_CheckThing(mobj_t *thing)
// SRB2kart 011617 - Colission[sic] code for kart items //{
if (thing->type == MT_SHRINK_GUN || thing->type == MT_SHRINK_PARTICLE)
{
if (tmthing->type != MT_PLAYER)
{
return BMIT_CONTINUE;
}
if (thing->type == MT_SHRINK_GUN)
{
// Use special collision for the laser gun.
// The laser sprite itself is just a visual,
// the gun itself does the colliding for us.
if (tmthing->z > thing->z)
{
return BMIT_CONTINUE; // overhead
}
if (tmthing->z + tmthing->height < thing->floorz)
{
return BMIT_CONTINUE; // underneath
}
}
else
{
if (tmthing->z > thing->z + thing->height)
{
return BMIT_CONTINUE; // overhead
}
if (tmthing->z + tmthing->height < thing->z)
{
return BMIT_CONTINUE; // underneath
}
}
return Obj_ShrinkLaserCollide(thing, tmthing) ? BMIT_CONTINUE : BMIT_ABORT;
}
else if (tmthing->type == MT_SHRINK_GUN || tmthing->type == MT_SHRINK_PARTICLE)
{
if (thing->type != MT_PLAYER)
{
return BMIT_CONTINUE;
}
if (tmthing->type == MT_SHRINK_GUN)
{
// Use special collision for the laser gun.
// The laser sprite itself is just a visual,
// the gun itself does the colliding for us.
if (thing->z > tmthing->z)
{
return BMIT_CONTINUE; // overhead
}
if (thing->z + thing->height < tmthing->floorz)
{
return BMIT_CONTINUE; // underneath
}
}
else
{
if (tmthing->z > thing->z + thing->height)
{
return BMIT_CONTINUE; // overhead
}
if (tmthing->z + tmthing->height < thing->z)
{
return BMIT_CONTINUE; // underneath
}
}
return Obj_ShrinkLaserCollide(tmthing, thing) ? BMIT_CONTINUE : BMIT_ABORT;
}
if (tmthing->type == MT_SMK_ICEBLOCK)
{
// see if it went over / under

View file

@ -7848,6 +7848,11 @@ static boolean P_MobjRegularThink(mobj_t *mobj)
Obj_HyudoroCenterThink(mobj);
break;
}
case MT_SHRINK_POHBEE:
{
Obj_PohbeeThinker(mobj);
break;
}
case MT_ROCKETSNEAKER:
if (!mobj->target || !mobj->target->health)
{
@ -10660,6 +10665,16 @@ void P_RemoveMobj(mobj_t *mobj)
P_SetTarget(&mobj->player->followmobj, NULL);
}
if (mobj->type == MT_SHRINK_POHBEE)
{
Obj_PohbeeRemoved(mobj);
}
if (mobj->type == MT_SHRINK_GUN)
{
Obj_ShrinkGunRemoved(mobj);
}
mobj->health = 0; // Just because
// unlink from sector and block lists

View file

@ -367,6 +367,8 @@ static void P_NetArchivePlayers(void)
WRITEUINT8(save_p, players[i].stairjank);
WRITEUINT8(save_p, players[i].shrinkLaserDelay);
// respawnvars_t
WRITEUINT8(save_p, players[i].respawn.state);
WRITEUINT32(save_p, K_GetWaypointHeapIndex(players[i].respawn.wp));
@ -654,6 +656,8 @@ static void P_NetUnArchivePlayers(void)
players[i].stairjank = READUINT8(save_p);
players[i].shrinkLaserDelay = READUINT8(save_p);
// respawnvars_t
players[i].respawn.state = READUINT8(save_p);
players[i].respawn.wp = (waypoint_t *)(size_t)READUINT32(save_p);

View file

@ -3044,6 +3044,10 @@ boolean P_MoveChaseCamera(player_t *player, camera_t *thiscam, boolean resetcall
subsector_t *newsubsec;
#endif
fixed_t playerScale = FixedDiv(player->mo->scale, mapobjectscale);
fixed_t scaleDiff = playerScale - FRACUNIT;
fixed_t cameraScale = mapobjectscale;
thiscam->old_x = thiscam->x;
thiscam->old_y = thiscam->y;
thiscam->old_z = thiscam->z;
@ -3132,8 +3136,11 @@ boolean P_MoveChaseCamera(player_t *player, camera_t *thiscam, boolean resetcall
return true;
}
thiscam->radius = 20*mapobjectscale;
thiscam->height = 16*mapobjectscale;
// Adjust camera to match Grow/Shrink
cameraScale = FixedMul(cameraScale, FRACUNIT + (scaleDiff / 3));
thiscam->radius = 20*cameraScale;
thiscam->height = 16*cameraScale;
// Don't run while respawning from a starpost
// Inu 4/8/13 Why not?!
@ -3159,8 +3166,8 @@ boolean P_MoveChaseCamera(player_t *player, camera_t *thiscam, boolean resetcall
camspeed = cv_cam_speed[num].value;
camstill = cv_cam_still[num].value;
camrotate = cv_cam_rotate[num].value;
camdist = FixedMul(cv_cam_dist[num].value, mapobjectscale);
camheight = FixedMul(cv_cam_height[num].value, mapobjectscale);
camdist = FixedMul(cv_cam_dist[num].value, cameraScale);
camheight = FixedMul(cv_cam_height[num].value, cameraScale);
if (timeover)
{
@ -3171,8 +3178,8 @@ boolean P_MoveChaseCamera(player_t *player, camera_t *thiscam, boolean resetcall
{
const INT32 introcam = (introtime - leveltime);
camrotate += introcam*5;
camdist += (introcam * mapobjectscale)*3;
camheight += (introcam * mapobjectscale)*2;
camdist += (introcam * cameraScale)*3;
camheight += (introcam * cameraScale)*2;
}
else if (player->exiting) // SRB2Kart: Leave the camera behind while exiting, for dramatic effect!
camstill = true;
@ -3236,7 +3243,7 @@ boolean P_MoveChaseCamera(player_t *player, camera_t *thiscam, boolean resetcall
// sets ideal cam pos
{
const fixed_t speedthreshold = 48*mapobjectscale;
const fixed_t speedthreshold = 48*cameraScale;
const fixed_t olddist = P_AproxDistance(mo->x - thiscam->x, mo->y - thiscam->y);
fixed_t lag, distoffset;
@ -3541,7 +3548,7 @@ boolean P_MoveChaseCamera(player_t *player, camera_t *thiscam, boolean resetcall
// point viewed by the camera
// this point is just 64 unit forward the player
dist = 64*mapobjectscale;
dist = 64*cameraScale;
viewpointx = mo->x + FixedMul(FINECOSINE((angle>>ANGLETOFINESHIFT) & FINEMASK), dist) + xpan;
viewpointy = mo->y + FixedMul(FINESINE((angle>>ANGLETOFINESHIFT) & FINEMASK), dist) + ypan;