Merge branch 'sal-waypoints' into 'waypoints'

Sal edits to waypoints

See merge request KartKrew/Kart!202
This commit is contained in:
Sal 2020-03-20 20:43:27 -04:00
commit aeb6567b53
21 changed files with 11147 additions and 10463 deletions

View file

@ -1886,8 +1886,6 @@ void SendWeaponPref(void)
buf[0] = 0;
if (cv_flipcam.value)
buf[0] |= 1;
if (cv_analog.value)
buf[0] |= 2;
SendNetXCmd(XD_WEAPONPREF, buf, 1);
}
@ -1898,8 +1896,6 @@ void SendWeaponPref2(void)
buf[0] = 0;
if (cv_flipcam2.value)
buf[0] |= 1;
if (cv_analog2.value)
buf[0] |= 2;
SendNetXCmd2(XD_WEAPONPREF, buf, 1);
}
@ -1910,8 +1906,6 @@ void SendWeaponPref3(void)
buf[0] = 0;
if (cv_flipcam3.value)
buf[0] |= 1;
if (cv_analog3.value)
buf[0] |= 2;
SendNetXCmd3(XD_WEAPONPREF, buf, 1);
}
@ -1922,8 +1916,6 @@ void SendWeaponPref4(void)
buf[0] = 0;
if (cv_flipcam4.value)
buf[0] |= 1;
if (cv_analog4.value)
buf[0] |= 2;
SendNetXCmd4(XD_WEAPONPREF, buf, 1);
}
@ -1931,11 +1923,9 @@ static void Got_WeaponPref(UINT8 **cp,INT32 playernum)
{
UINT8 prefs = READUINT8(*cp);
players[playernum].pflags &= ~(PF_FLIPCAM|PF_ANALOGMODE);
players[playernum].pflags &= ~(PF_FLIPCAM);
if (prefs & 1)
players[playernum].pflags |= PF_FLIPCAM;
if (prefs & 2)
players[playernum].pflags |= PF_ANALOGMODE;
}
static void Got_PowerLevel(UINT8 **cp,INT32 playernum)
@ -2857,13 +2847,15 @@ static void Got_Respawn(UINT8 **cp, INT32 playernum)
return;
}
// incase the above checks were modified to allow sending a respawn on these occasions:
if (players[respawnplayer].mo && !P_IsObjectOnGround(players[respawnplayer].mo))
return;
if (players[respawnplayer].mo)
P_DamageMobj(players[respawnplayer].mo, NULL, NULL, 10000);
demo_extradata[playernum] |= DXD_RESPAWN;
{
// incase the above checks were modified to allow sending a respawn on these occasions:
if (!P_IsObjectOnGround(players[respawnplayer].mo))
return;
K_DoIngameRespawn(&players[respawnplayer]);
demo_extradata[playernum] |= DXD_RESPAWN;
}
}
/** Deals with an ::XD_RANDOMSEED message in a netgame.

View file

@ -121,7 +121,7 @@ typedef enum
/*** misc ***/
PF_FORCESTRAFE = 1<<29, // Turning inputs are translated into strafing inputs
PF_ANALOGMODE = 1<<30, // Analog mode?
PF_HITFINISHLINE = 1<<30, // Already hit the finish line this tic
// free: 1<<30 and 1<<31
} pflags_t;
@ -330,6 +330,7 @@ typedef enum
k_springstars, // Spawn stars around a player when they hit a spring
k_springcolor, // Color of spring stars
k_killfield, // How long have you been in the kill field, stay in too long and lose a bumper
k_wrongway, // Display WRONG WAY on screen
NUMKARTSTUFF
} kartstufftype_t;

View file

@ -6648,6 +6648,11 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit
// DEZ respawn laser
"S_DEZLASER",
"S_DEZLASER_TRAIL1",
"S_DEZLASER_TRAIL2",
"S_DEZLASER_TRAIL3",
"S_DEZLASER_TRAIL4",
"S_DEZLASER_TRAIL5",
// Audience Members
"S_RANDOMAUDIENCE",
@ -8167,7 +8172,7 @@ static const char *const PLAYERFLAG_LIST[] = {
/*** misc ***/
"FORCESTRAFE", // Translate turn inputs into strafe inputs
"ANALOGMODE", // Analog mode?
"HITFINISHLINE", // Already hit the finish line this tic
NULL // stop loop here.
};
@ -8485,7 +8490,8 @@ static const char *const KARTSTUFF_LIST[] = {
"TIREGREASE",
"SPRINGSTARS",
"SPRINGCOLOR",
"KILLFIELD"
"KILLFIELD",
"WRONGWAY"
};
#endif

View file

@ -2597,7 +2597,7 @@ void G_PlayerReborn(INT32 player)
jointime = players[player].jointime;
splitscreenindex = players[player].splitscreenindex;
spectator = players[player].spectator;
pflags = (players[player].pflags & (PF_TIMEOVER|PF_FLIPCAM|PF_TAGIT|PF_TAGGED|PF_ANALOGMODE|PF_WANTSTOJOIN));
pflags = (players[player].pflags & (PF_TIMEOVER|PF_FLIPCAM|PF_TAGIT|PF_TAGGED|PF_WANTSTOJOIN));
// As long as we're not in multiplayer, carry over cheatcodes from map to map
if (!(netgame || multiplayer))
@ -4935,7 +4935,10 @@ void G_ReadDemoExtraData(void)
if (extradata & DXD_RESPAWN)
{
if (players[p].mo)
P_DamageMobj(players[p].mo, NULL, NULL, 10000); // Is this how this should work..?
{
// Is this how this should work..?
K_DoIngameRespawn(&players[p]);
}
}
if (extradata & DXD_SKIN)
{

View file

@ -2863,7 +2863,12 @@ state_t states[NUMSTATES] =
{SPR_KBLN, FF_FULLBRIGHT|1, -1, {NULL}, 0, 0, S_BATTLEBUMPER2}, // S_BATTLEBUMPER2
{SPR_KBLN, FF_FULLBRIGHT|2, -1, {NULL}, 0, 0, S_BATTLEBUMPER3}, // S_BATTLEBUMPER3
{SPR_DEZL, FF_FULLBRIGHT|FF_PAPERSPRITE, 8, {NULL}, 0, 0, S_NULL}, // S_DEZLASER
{SPR_DEZL, FF_FULLBRIGHT|FF_PAPERSPRITE, 8, {NULL}, 0, 0, S_NULL}, // S_DEZLASER
{SPR_DEZL, FF_FULLBRIGHT|1, 2, {NULL}, 0, 0, S_DEZLASER_TRAIL2}, // S_DEZLASER_TRAIL1
{SPR_DEZL, FF_FULLBRIGHT|2, 2, {NULL}, 0, 0, S_DEZLASER_TRAIL3}, // S_DEZLASER_TRAIL2
{SPR_DEZL, FF_FULLBRIGHT|FF_PAPERSPRITE|3, 4, {NULL}, 0, 0, S_DEZLASER_TRAIL4}, // S_DEZLASER_TRAIL3
{SPR_DEZL, FF_FULLBRIGHT|2, 2, {NULL}, 0, 0, S_DEZLASER_TRAIL5}, // S_DEZLASER_TRAIL4
{SPR_DEZL, FF_FULLBRIGHT|1, 2, {NULL}, 0, 0, S_NULL}, // S_DEZLASER_TRAIL5
{SPR_NULL, 0, 1, {A_RandomStateRange}, S_AUDIENCE_CHAO_CHEER1, S_AUDIENCE_CHAO_CHEER2, S_RANDOMAUDIENCE}, // S_RANDOMAUDIENCE
@ -16036,7 +16041,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
S_SPB_DEAD, // deathstate
S_NULL, // xdeathstate
sfx_s3k5d, // deathsound
96*FRACUNIT, // speed
80*FRACUNIT, // speed
24*FRACUNIT, // radius
48*FRACUNIT, // height
0, // display offset

View file

@ -3537,6 +3537,11 @@ typedef enum state
// DEZ Laser respawn
S_DEZLASER,
S_DEZLASER_TRAIL1,
S_DEZLASER_TRAIL2,
S_DEZLASER_TRAIL3,
S_DEZLASER_TRAIL4,
S_DEZLASER_TRAIL5,
// Audience Members
S_RANDOMAUDIENCE,

20715
src/k_kart.c

File diff suppressed because it is too large Load diff

View file

@ -27,6 +27,7 @@ void K_KartBouncing(mobj_t *mobj1, mobj_t *mobj2, boolean bounce, boolean solid)
void K_KartPainEnergyFling(player_t *player);
void K_FlipFromObject(mobj_t *mo, mobj_t *master);
void K_MatchGenericExtraFlags(mobj_t *mo, mobj_t *master);
void K_DoIngameRespawn(player_t *player);
void K_RespawnChecker(player_t *player);
void K_KartMoveAnimation(player_t *player);
void K_KartPlayerHUDUpdate(player_t *player);

View file

@ -11,9 +11,9 @@ static const UINT32 SPARKLES_PER_CONNECTION = 16U;
// Some defaults for the size of the dynamically allocated sets for pathfinding. These are kept for the purpose of
// allocating a size that is less likely to need reallocating again during the pathfinding.
static const size_t OPENSET_BASE_SIZE = 16U;
static const size_t CLOSEDSET_BASE_SIZE = 256U;
static const size_t NODESARRAY_BASE_SIZE = 256U;
#define OPENSET_BASE_SIZE (16U)
#define CLOSEDSET_BASE_SIZE (256U)
#define NODESARRAY_BASE_SIZE (256U)
static waypoint_t *waypointheap = NULL;
static waypoint_t *firstwaypoint = NULL;
@ -221,8 +221,11 @@ waypoint_t *K_GetClosestWaypointToMobj(mobj_t *const mobj)
for (i = 0; i < numwaypoints; i++)
{
checkwaypoint = &waypointheap[i];
checkdist = P_AproxDistance(mobj->x - checkwaypoint->mobj->x, mobj->y - checkwaypoint->mobj->y);
checkdist = P_AproxDistance(checkdist, mobj->z - checkwaypoint->mobj->z);
checkdist = P_AproxDistance(
(mobj->x / FRACUNIT) - (checkwaypoint->mobj->x / FRACUNIT),
(mobj->y / FRACUNIT) - (checkwaypoint->mobj->y / FRACUNIT));
checkdist = P_AproxDistance(checkdist, (mobj->z / FRACUNIT) - (checkwaypoint->mobj->z / FRACUNIT));
if (checkdist < closestdist)
{
@ -235,6 +238,52 @@ waypoint_t *K_GetClosestWaypointToMobj(mobj_t *const mobj)
return closestwaypoint;
}
/*--------------------------------------------------
waypoint_t *K_GetBestWaypointForMobj(mobj_t *const mobj)
See header file for description.
--------------------------------------------------*/
waypoint_t *K_GetBestWaypointForMobj(mobj_t *const mobj)
{
waypoint_t *bestwaypoint = NULL;
if ((mobj == NULL) || P_MobjWasRemoved(mobj))
{
CONS_Debug(DBG_GAMELOGIC, "NULL mobj in K_GetBestWaypointForMobj.\n");
}
else
{
size_t i = 0U;
waypoint_t *checkwaypoint = NULL;
fixed_t closestdist = INT32_MAX;
fixed_t checkdist = INT32_MAX;
for (i = 0; i < numwaypoints; i++)
{
checkwaypoint = &waypointheap[i];
checkdist = P_AproxDistance(
(mobj->x / FRACUNIT) - (checkwaypoint->mobj->x / FRACUNIT),
(mobj->y / FRACUNIT) - (checkwaypoint->mobj->y / FRACUNIT));
checkdist = P_AproxDistance(checkdist, ((mobj->z / FRACUNIT) - (checkwaypoint->mobj->z / FRACUNIT)) * 4);
if (checkdist < closestdist)
{
if (!P_CheckSight(mobj, checkwaypoint->mobj))
{
// Save sight checks for the end, so we only do it if we have to
continue;
}
bestwaypoint = checkwaypoint;
closestdist = checkdist;
}
}
}
return bestwaypoint;
}
/*--------------------------------------------------
size_t K_GetWaypointHeapIndex(waypoint_t *waypoint)
@ -378,11 +427,11 @@ void K_DebugWaypointsVisualise(void)
}
else if (waypoint->numnextwaypoints == 0 || waypoint->numprevwaypoints == 0)
{
debugmobj->color = SKINCOLOR_ORANGE;
debugmobj->color = SKINCOLOR_YELLOW;
}
else if (waypoint == players[displayplayers[0]].nextwaypoint)
{
debugmobj->color = SKINCOLOR_YELLOW;
debugmobj->color = SKINCOLOR_GREEN;
}
else
{

View file

@ -151,6 +151,22 @@ UINT32 K_GetCircuitLength(void);
waypoint_t *K_GetClosestWaypointToMobj(mobj_t *const mobj);
/*--------------------------------------------------
waypoint_t *K_GetBestWaypointForMobj(mobj_t *const mobj)
Similar to K_GetClosestWaypointToMobj, but prioritizes horizontal distance over vertical distance, and
sight checks to ensure that the waypoint and mobj are the in same area. Can potentially return NULL if
there are no visible waypoints.
Input Arguments:-
mobj - mobj to get the waypoint for.
Return:-
The best waypoint for the mobj, or NULL if there were no matches
--------------------------------------------------*/
waypoint_t *K_GetBestWaypointForMobj(mobj_t *const mobj);
/*--------------------------------------------------
boolean K_PathfindToWaypoint(
waypoint_t *const sourcewaypoint,

View file

@ -292,9 +292,18 @@ void Command_CheatNoClip_f(void)
REQUIRE_NOULTIMATE;
plyr = &players[consoleplayer];
if (!plyr->mo || P_MobjWasRemoved(plyr->mo))
return;
plyr->pflags ^= PF_NOCLIP;
CONS_Printf(M_GetText("No Clipping %s\n"), plyr->pflags & PF_NOCLIP ? M_GetText("On") : M_GetText("Off"));
if (plyr->pflags & PF_NOCLIP)
plyr->mo->flags |= MF_NOCLIP;
else
plyr->mo->flags &= ~MF_NOCLIP;
G_SetGameModified(multiplayer, true);
}

View file

@ -8451,7 +8451,7 @@ static void SpawnSPBTrailRings(mobj_t *actor)
{
if (leveltime % 6 == 0)
{
mobj_t *ring = P_SpawnMobj(actor->x - actor->momx, actor->y - actor->momx,
mobj_t *ring = P_SpawnMobj(actor->x - actor->momx, actor->y - actor->momy,
actor->z - actor->momz + (24*mapobjectscale), MT_RING);
ring->threshold = 10;
ring->fuse = 120*TICRATE;
@ -8462,11 +8462,15 @@ static void SpawnSPBTrailRings(mobj_t *actor)
void A_SPBChase(mobj_t *actor)
{
player_t *player = NULL;
player_t *scplayer = NULL; // secondary target for seeking
UINT8 i;
UINT8 bestrank = UINT8_MAX;
fixed_t dist;
angle_t hang, vang;
fixed_t wspeed, xyspeed, zspeed;
fixed_t pdist = 1536<<FRACBITS; // best player distance when seeking
angle_t pangle; // angle between us and the player
#ifdef HAVE_BLUA
if (LUA_CallAction("A_SPBChase", actor))
return;
@ -8478,9 +8482,9 @@ void A_SPBChase(mobj_t *actor)
if (actor->threshold) // Just fired, go straight.
{
actor->lastlook = -1;
actor->cusval = -1;
spbplace = -1;
P_InstaThrust(actor, actor->angle, wspeed);
actor->flags &= ~MF_NOCLIPTHING; // just in case.
return;
}
@ -8506,18 +8510,22 @@ void A_SPBChase(mobj_t *actor)
}
}
// lastlook = last player num targetted
// cvmem = stored speed
// cusval = next waypoint heap index
// extravalue1 = SPB movement mode
// extravalue2 = mode misc option
if (actor->extravalue1 == 1) // MODE: TARGETING
{
actor->cusval = -1; // Reset waypoint
if (actor->tracer && actor->tracer->health)
{
fixed_t defspeed = wspeed;
fixed_t range = (160*actor->tracer->scale);
fixed_t cx = 0, cy =0;
// we're tailing a player, now's a good time to regain our damage properties
actor->flags &= ~MF_NOCLIPTHING;
// Play the intimidating gurgle
if (!S_SoundPlaying(actor, actor->info->activesound))
S_StartSound(actor, actor->info->activesound);
@ -8648,9 +8656,7 @@ void A_SPBChase(mobj_t *actor)
else if (actor->extravalue1 == 2) // MODE: WAIT...
{
actor->momx = actor->momy = actor->momz = 0; // Stoooop
// don't hurt players that have nothing to do with this:
actor->flags |= MF_NOCLIPTHING;
actor->cusval = -1; // Reset waypoint
if (actor->lastlook != -1
&& playeringame[actor->lastlook]
@ -8676,8 +8682,11 @@ void A_SPBChase(mobj_t *actor)
}
else // MODE: SEEKING
{
waypoint_t *closestwaypoint = NULL;
waypoint_t *nextwaypoint = NULL;
waypoint_t *lastwaypoint = NULL;
waypoint_t *bestwaypoint = NULL;
waypoint_t *nextwaypoint = NULL;
waypoint_t *tempwaypoint = NULL;
actor->lastlook = -1; // Just make sure this is reset
if (!player || !player->mo || player->mo->health <= 0 || player->kartstuff[k_respawn])
@ -8690,17 +8699,35 @@ void A_SPBChase(mobj_t *actor)
}
// Found someone, now get close enough to initiate the slaughter...
// Seeking SPB can now hurt people
actor->flags &= ~MF_NOCLIPTHING;
P_SetTarget(&actor->tracer, player->mo);
spbplace = bestrank;
dist = P_AproxDistance(P_AproxDistance(actor->x-actor->tracer->x, actor->y-actor->tracer->y), actor->z-actor->tracer->z);
closestwaypoint = K_GetClosestWaypointToMobj(actor);
if (closestwaypoint != NULL)
// Move along the waypoints until you get close enough
if (actor->cusval > -1 && actor->extravalue2 > 0)
{
// Previously set nextwaypoint
lastwaypoint = K_GetWaypointFromIndex((size_t)actor->cusval);
tempwaypoint = K_GetBestWaypointForMobj(actor);
// check if the tempwaypoint corresponds to lastwaypoint's next ID at least;
// This is to avoid situations where the SPB decides to suicide jump down a bridge because it found a COMPLETELY unrelated waypoint down there.
if (K_GetWaypointID(tempwaypoint) == K_GetWaypointNextID(lastwaypoint) || K_GetWaypointID(tempwaypoint) == K_GetWaypointID(lastwaypoint))
// either our previous or curr waypoint ID, sure, take it
bestwaypoint = tempwaypoint;
else
bestwaypoint = K_GetWaypointFromIndex((size_t)actor->extravalue2); // keep going from the PREVIOUS wp.
}
else
bestwaypoint = K_GetBestWaypointForMobj(actor);
if (bestwaypoint == NULL && lastwaypoint == NULL)
{
// We have invalid waypoints all around, so use closest to try and make it non-NULL.
bestwaypoint = K_GetClosestWaypointToMobj(actor);
}
if (bestwaypoint != NULL)
{
const boolean huntbackwards = false;
boolean useshortcuts = false;
@ -8712,15 +8739,25 @@ void A_SPBChase(mobj_t *actor)
}
nextwaypoint = K_GetNextWaypointToDestination(
closestwaypoint, player->nextwaypoint, useshortcuts, huntbackwards);
bestwaypoint, player->nextwaypoint, useshortcuts, huntbackwards);
}
if (nextwaypoint == NULL && lastwaypoint != NULL)
{
// Restore to the last nextwaypoint
nextwaypoint = lastwaypoint;
}
if (nextwaypoint != NULL)
{
const fixed_t xywaypointdist = P_AproxDistance(
actor->x - nextwaypoint->mobj->x, actor->y - nextwaypoint->mobj->y);
hang = R_PointToAngle2(actor->x, actor->y, nextwaypoint->mobj->x, nextwaypoint->mobj->y);
vang = R_PointToAngle2(0, actor->z, xywaypointdist, nextwaypoint->mobj->z);
actor->cusval = (INT32)K_GetWaypointHeapIndex(nextwaypoint);
actor->extravalue2 = (INT32)K_GetWaypointHeapIndex(bestwaypoint); // save our last best, used above.
}
else
{
@ -8736,13 +8773,13 @@ void A_SPBChase(mobj_t *actor)
if (invert)
input = InvAngle(input);
input = FixedAngle(AngleFixed(input)/8);
// Slow down when turning; it looks better and makes U-turns not unfair
xyspeed = FixedMul(wspeed, max(0, (((180<<FRACBITS) - AngleFixed(input)) / 90) - FRACUNIT));
input = FixedAngle(AngleFixed(input)/4);
if (invert)
input = InvAngle(input);
actor->angle += input;
// Smoothly rotate vert angle
@ -8751,13 +8788,13 @@ void A_SPBChase(mobj_t *actor)
if (invert)
input = InvAngle(input);
input = FixedAngle(AngleFixed(input)/8);
// Slow down when turning; might as well do it for momz, since we do it above too
zspeed = FixedMul(wspeed, max(0, (((180<<FRACBITS) - AngleFixed(input)) / 90) - FRACUNIT));
input = FixedAngle(AngleFixed(input)/4);
if (invert)
input = InvAngle(input);
actor->movedir += input;
}
@ -8765,18 +8802,49 @@ void A_SPBChase(mobj_t *actor)
actor->momy = FixedMul(FixedMul(xyspeed, FINESINE(actor->angle>>ANGLETOFINESHIFT)), FINECOSINE(actor->movedir>>ANGLETOFINESHIFT));
actor->momz = FixedMul(zspeed, FINESINE(actor->movedir>>ANGLETOFINESHIFT));
// see if a player is near us, if they are, try to hit them by slightly thrusting towards them, otherwise, bleh!
for (i=0; i < MAXPLAYERS; i++)
{
if (!playeringame[i] || players[i].spectator || players[i].exiting)
continue; // not in-game
if (R_PointToDist2(actor->x, actor->y, players[i].mo->x, players[i].mo->y) < pdist)
{
pdist = R_PointToDist2(actor->x, actor->y, players[i].mo->x, players[i].mo->y);
scplayer = &players[i]; // it doesn't matter if we override this guy now.
}
}
// different player from our main target, try and ram into em~!
if (scplayer && scplayer != player)
{
pangle = actor->angle - R_PointToAngle2(actor->x, actor->y,scplayer->mo->x, scplayer->mo->y);
// check if the angle wouldn't make us LOSE speed...
if ((INT32)pangle/ANG1 >= -80 && (INT32)pangle/ANG1 <= 80) // allow for around 80 degrees
{
// Thrust us towards the guy, try to screw em up!
P_Thrust(actor, R_PointToAngle2(actor->x, actor->y, scplayer->mo->x, scplayer->mo->y), actor->movefactor/4); // not too fast though.
}
}
// Spawn a trail of rings behind the SPB!
SpawnSPBTrailRings(actor);
if (dist <= (3072*actor->tracer->scale)) // Close enough to target?
if (dist <= (1024*actor->tracer->scale)) // Close enough to target?
{
S_StartSound(actor, actor->info->attacksound); // Siren sound; might not need this anymore, but I'm keeping it for now just for debugging.
S_StartSound(actor, actor->info->attacksound);
actor->extravalue1 = 1; // TARGET ACQUIRED
actor->extravalue2 = 7*TICRATE;
actor->cvmem = wspeed;
}
}
// Finally, no matter what, the spb should not be able to be under the ground, or above the ceiling;
if (actor->z < actor->floorz)
actor->z = actor->floorz;
else if (actor->z > actor->ceilingz - actor->height)
actor->z = actor->ceilingz - actor->height;
return;
}
@ -10618,8 +10686,8 @@ void A_RemoteDamage(mobj_t *actor)
if (locvar2 == 1) // Kill mobj!
{
if (target->player) // players die using P_DamageMobj instead for some reason
P_DamageMobj(target, source, source, 10000);
if (target->player)
K_DoIngameRespawn(target->player);
else
P_KillMobj(target, source, source);
}

View file

@ -180,7 +180,6 @@ boolean P_LookForEnemies(player_t *player);
void P_NukeEnemies(mobj_t *inflictor, mobj_t *source, fixed_t radius);
void P_HomingAttack(mobj_t *source, mobj_t *enemy); /// \todo doesn't belong in p_user
//boolean P_SuperReady(player_t *player);
boolean P_AnalogMove(player_t *player);
/*boolean P_TransferToNextMare(player_t *player);
UINT8 P_FindLowestMare(void);*/
UINT8 P_FindLowestLap(void);

View file

@ -129,8 +129,6 @@ boolean P_TeleportMove(mobj_t *thing, fixed_t x, fixed_t y, fixed_t z)
// MOVEMENT ITERATOR FUNCTIONS
// =========================================================================
//#define TELEPORTJANK
// For our intermediate buffer, remove any duplicate entries by adding each one to
// a temprary buffer if it's not already in there, copy the temporary buffer back over the intermediate afterwards
static void spechitint_removedups(void)
@ -225,6 +223,8 @@ static boolean P_SpecialIsLinedefCrossType(UINT16 ldspecial)
return linedefcrossspecial;
}
//#define TELEPORTJANK
boolean P_DoSpring(mobj_t *spring, mobj_t *object)
{
//INT32 pflags;
@ -256,7 +256,7 @@ boolean P_DoSpring(mobj_t *spring, mobj_t *object)
object->eflags |= MFE_SPRUNG; // apply this flag asap!
spring->flags &= ~(MF_SOLID|MF_SPECIAL); // De-solidify
#ifdef TELEPORTJANK
#if 0
if (horizspeed && vertispeed) // Mimic SA
{
object->momx = object->momy = 0;
@ -1007,12 +1007,20 @@ static boolean PIT_CheckThing(mobj_t *thing)
if (thing->type == MT_PLAYER)
{
S_StartSound(NULL, sfx_bsnipe); //let all players hear it.
mobj_t *explosion;
S_StartSound(NULL, sfx_bsnipe); // let all players hear it.
HU_SetCEchoFlags(0);
HU_SetCEchoDuration(5);
HU_DoCEcho(va("%s\\was hit by a kitchen sink.\\\\\\\\", player_names[thing->player-players]));
I_OutputMsg("%s was hit by a kitchen sink.\n", player_names[thing->player-players]);
P_DamageMobj(thing, tmthing, tmthing->target, 10000);
explosion = P_SpawnMobj(thing->x, thing->y, thing->z, MT_SPBEXPLOSION);
explosion->extravalue1 = 1; // Tell K_ExplodePlayer to use extra knockback
if (tmthing->target && !P_MobjWasRemoved(tmthing->target))
P_SetTarget(&explosion->target, tmthing->target);
P_KillMobj(tmthing, thing, thing);
}
@ -1271,15 +1279,23 @@ static boolean PIT_CheckThing(mobj_t *thing)
}
else if (thing->type == MT_SINK)
{
mobj_t *explosion;
if ((thing->target == tmthing) && (thing->threshold > 0))
return true;
S_StartSound(NULL, sfx_cgot); //let all players hear it.
S_StartSound(NULL, sfx_bsnipe); // let all players hear it.
HU_SetCEchoFlags(0);
HU_SetCEchoDuration(5);
HU_DoCEcho(va("%s\\was hit by a kitchen sink.\\\\\\\\", player_names[tmthing->player-players]));
I_OutputMsg("%s was hit by a kitchen sink.\n", player_names[tmthing->player-players]);
P_DamageMobj(tmthing, thing, thing->target, 10000);
explosion = P_SpawnMobj(tmthing->x, tmthing->y, tmthing->z, MT_SPBEXPLOSION);
explosion->extravalue1 = 1; // Tell K_ExplodePlayer to use extra knockback
if (thing->target && !P_MobjWasRemoved(thing->target))
P_SetTarget(&explosion->target, thing->target);
P_KillMobj(thing, tmthing, tmthing);
}
@ -1419,7 +1435,7 @@ static boolean PIT_CheckThing(mobj_t *thing)
thing->angle = tmthing->angle;
if (!demo.playback || P_AnalogMove(thing->player))
if (!demo.playback)
{
if (thing->player == &players[consoleplayer])
localangle[0] = thing->angle;
@ -1664,7 +1680,7 @@ static boolean PIT_CheckThing(mobj_t *thing)
{
// Objects kill you if it falls from above.
if (thing != tmthing->target)
P_DamageMobj(thing, tmthing, tmthing->target, 10000);
K_DoIngameRespawn(thing->player);
tmthing->momz = -tmthing->momz/2; // Bounce, just for fun!
// The tmthing->target allows the pusher of the object
@ -2082,7 +2098,7 @@ static boolean PIT_CheckLine(line_t *ld)
if (P_BoxOnLineSide(tmbbox, ld) != -1)
return true;
if (tmthing->flags & MF_PAPERCOLLISION) // Caution! Turning whilst up against a wall will get you stuck. You probably shouldn't give the player this flag.
if (tmthing->flags & MF_PAPERCOLLISION) // Caution! Turning whilst up against a wall will get you stuck. You probably shouldn't give the player this flag.
{
fixed_t cosradius, sinradius;
cosradius = FixedMul(tmthing->radius, FINECOSINE(tmthing->angle>>ANGLETOFINESHIFT));
@ -2883,8 +2899,10 @@ boolean P_TryMove(mobj_t *thing, fixed_t x, fixed_t y, boolean allowdropoff)
// reset this to 0 at the start of each trymove call as it's only used here
numspechitint = 0U;
if (radius < MAXRADIUS/2)
radius = MAXRADIUS/2;
// This makes sure that there are no freezes from computing extremely small movements.
// Originally was MAXRADIUS/2, but that causes some inconsistencies for small players.
if (radius < mapobjectscale)
radius = mapobjectscale;
do {
if (thing->flags & MF_NOCLIP) {

View file

@ -47,6 +47,7 @@ consvar_t cv_splats = {"splats", "On", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0
actioncache_t actioncachehead;
static mobj_t *overlaycap = NULL;
mobj_t *kitemcap = NULL; // Used for Kart offensive items (the ones that can get removed by sizedown)
mobj_t *waypointcap = NULL;
void P_InitCachedActions(void)
@ -1655,18 +1656,11 @@ void P_XYMovement(mobj_t *mo)
{
mo->health--;
if (mo->health == 0)
mo->destscale = 1;
}
else
{
if (mo->scale < mapobjectscale/16)
{
P_RemoveMobj(mo);
return;
}
mo->destscale = 0;
}
}
//}
if (!P_TryMove(mo, mo->x + xmove, mo->y + ymove, true) && !(mo->eflags & MFE_SPRUNG))
{
// blocked move
@ -6105,6 +6099,71 @@ static boolean P_AddShield(mobj_t *thing)
return true;
}*/
// Kartitem stuff.
boolean P_IsKartItem(INT32 type)
{
if (type == MT_EGGMANITEM || type == MT_EGGMANITEM_SHIELD ||
type == MT_BANANA || type == MT_BANANA_SHIELD ||
type == MT_ORBINAUT || type == MT_ORBINAUT_SHIELD ||
type == MT_JAWZ || type == MT_JAWZ_DUD || type == MT_JAWZ_SHIELD ||
type == MT_SSMINE || type == MT_SSMINE_SHIELD ||
type == MT_SINK || type == MT_SINK_SHIELD ||
type == MT_SPB)
return true;
else
return false;
}
// Called when a kart item "thinks"
void P_AddKartItem(mobj_t *thing)
{
I_Assert(thing != NULL);
if (kitemcap == NULL)
P_SetTarget(&kitemcap, thing);
else {
mobj_t *mo;
for (mo = kitemcap; mo && mo->itnext; mo = mo->itnext)
;
I_Assert(mo != NULL);
I_Assert(mo->itnext == NULL);
P_SetTarget(&mo->itnext, thing);
}
P_SetTarget(&thing->itnext, NULL);
}
// Called only when a kart item is removed
// Keeps the hnext list from corrupting.
static void P_RemoveKartItem(mobj_t *thing)
{
mobj_t *mo;
for (mo = kitemcap; mo; mo = mo->itnext)
if (mo->itnext == thing)
{
P_SetTarget(&mo->itnext, thing->itnext);
P_SetTarget(&thing->itnext, NULL);
return;
}
}
// Doesn't actually do anything since items have their own thinkers,
// but this is necessary for the sole purpose of updating kitemcap
void P_RunKartItems(void)
{
mobj_t *mobj, *next;
for (mobj = kitemcap; mobj; mobj = next)
{
next = mobj->itnext;
P_SetTarget(&mobj->itnext, NULL);
}
P_SetTarget(&kitemcap, NULL);
}
void P_RunOverlays(void)
{
// run overlays
@ -6538,16 +6597,25 @@ void P_MobjThinker(mobj_t *mobj)
mobj->z -= mobj->height - oldheight;
if (mobj->scale == mobj->destscale)
{
/// \todo Lua hook for "reached destscale"?
switch(mobj->type)
if (mobj->scale == 0)
{
case MT_EGGMOBILE_FIRE:
mobj->destscale = FRACUNIT;
mobj->scalespeed = FRACUNIT>>4;
break;
default:
break;
P_RemoveMobj(mobj);
return;
}
switch (mobj->type)
{
case MT_EGGMOBILE_FIRE:
mobj->destscale = FRACUNIT;
mobj->scalespeed = FRACUNIT>>4;
break;
default:
break;
}
}
}
if (mobj->type == MT_GHOST && mobj->fuse > 0 // Not guaranteed to be MF_SCENERY or not MF_SCENERY!
@ -9728,6 +9796,12 @@ for (i = ((mobj->flags2 & MF2_STRONGBOX) ? strongboxamt : weakboxamt); i; --i) s
}
}
if (P_MobjWasRemoved(mobj))
return; // obligatory paranoia check
if (P_IsKartItem(mobj->type)) // mobj is a kart item we want on the list:
P_AddKartItem(mobj); // add to kitem list
// Can end up here if a player dies.
if (mobj->player)
P_CyclePlayerMobjState(mobj);
@ -10408,6 +10482,10 @@ mobj_t *P_SpawnMobj(fixed_t x, fixed_t y, fixed_t z, mobjtype_t type)
}
}
break;
case MT_BOSS3WAYPOINT:
// Remove before release
CONS_Alert(CONS_WARNING, "Boss waypoints are deprecated. Did you forget to remove the old checkpoints, too?\n");
break;
default:
break;
}
@ -10563,6 +10641,9 @@ void P_RemoveMobj(mobj_t *mobj)
if (mobj->type == MT_SPB)
spbplace = -1;
if (P_IsKartItem(mobj->type))
P_RemoveKartItem(mobj);
mobj->health = 0; // Just because
// unlink from sector and block lists
@ -11148,6 +11229,9 @@ void P_SpawnPlayer(INT32 playernum)
// Spawn with a pity shield if necessary.
//P_DoPityCheck(p);
if (p->kartstuff[k_respawn] != 0)
p->mo->flags |= MF_NOCLIP|MF_NOCLIPHEIGHT|MF_NOCLIPTHING|MF_NOGRAVITY;
if (G_BattleGametype()) // SRB2kart
{
mobj_t *overheadarrow = P_SpawnMobj(mobj->x, mobj->y, mobj->z + P_GetPlayerHeight(p)+16*FRACUNIT, MT_PLAYERARROW);
@ -11364,11 +11448,10 @@ void P_MovePlayerToStarpost(INT32 playernum)
sector->ceilingheight;
if (mobj->player->kartstuff[k_starpostflip])
z = (p->starpostz<<FRACBITS) - FixedMul(128<<FRACBITS, mapobjectscale) - mobj->height;
z = (p->starpostz<<FRACBITS) - (128 * mapobjectscale) - mobj->height;
else
z = (p->starpostz<<FRACBITS) + FixedMul(128<<FRACBITS, mapobjectscale);
z = (p->starpostz<<FRACBITS) + (128 * mapobjectscale);
//z = (p->starpostz + 128) << FRACBITS; // reverse gravity exists, pls
mobj->player->kartstuff[k_starpostflip] = 0;
if (z < floor)
@ -11962,7 +12045,7 @@ ML_NOCLIMB : Direction not controllable
case MT_WAYPOINT:
{
size_t line;
mobj->radius = 256*FRACUNIT;
mobj->radius = 384*FRACUNIT;
// Same reason as for MT_SPINMACEPOINT we can't use the function to find the linedef
for (line = 0; line < numlines; line++)
{

View file

@ -319,6 +319,9 @@ typedef struct mobj_s
struct mobj_s *hnext;
struct mobj_s *hprev;
// One last pointer for kart item lists
struct mobj_s *itnext;
INT32 health; // for player this is rings + 1
// Movement direction, movement generation (zig-zagging).
@ -437,12 +440,18 @@ typedef struct actioncache_s
extern actioncache_t actioncachehead;
extern mobj_t *kitemcap;
extern mobj_t *waypointcap;
void P_InitCachedActions(void);
void P_RunCachedActions(void);
void P_AddCachedAction(mobj_t *mobj, INT32 statenum);
// kartitem stuff: Returns true if the specified 'type' is one of the kart item constants we want in the kitemcap list
boolean P_IsKartItem(INT32 type);
void P_AddKartItem(mobj_t *thing); // needs to be called in k_kart.c
void P_RunKartItems(void);
// check mobj against water content, before movement code
void P_MobjCheckWater(mobj_t *mobj);

View file

@ -957,9 +957,11 @@ typedef enum
MD2_HNEXT = 1<<7,
MD2_HPREV = 1<<8,
MD2_COLORIZED = 1<<9,
MD2_WAYPOINTCAP = 1<<10
MD2_WAYPOINTCAP = 1<<10,
MD2_KITEMCAP = 1<<11,
MD2_ITNEXT = 1<<12
#ifdef ESLOPE
, MD2_SLOPE = 1<<11
, MD2_SLOPE = 1<<13
#endif
} mobj_diff2_t;
@ -1151,6 +1153,8 @@ static void SaveMobjThinker(const thinker_t *th, const UINT8 type)
diff2 |= MD2_HNEXT;
if (mobj->hprev)
diff2 |= MD2_HPREV;
if (mobj->itnext)
diff2 |= MD2_ITNEXT;
#ifdef ESLOPE
if (mobj->standingslope)
diff2 |= MD2_SLOPE;
@ -1159,6 +1163,8 @@ static void SaveMobjThinker(const thinker_t *th, const UINT8 type)
diff2 |= MD2_COLORIZED;
if (mobj == waypointcap)
diff2 |= MD2_WAYPOINTCAP;
if (mobj == kitemcap)
diff2 |= MD2_KITEMCAP;
if (diff2 != 0)
diff |= MD_MORE;
@ -1274,6 +1280,8 @@ static void SaveMobjThinker(const thinker_t *th, const UINT8 type)
WRITEUINT32(save_p, mobj->hnext->mobjnum);
if (diff2 & MD2_HPREV)
WRITEUINT32(save_p, mobj->hprev->mobjnum);
if (diff2 & MD2_ITNEXT)
WRITEUINT32(save_p, mobj->itnext->mobjnum);
#ifdef ESLOPE
if (diff2 & MD2_SLOPE)
WRITEUINT16(save_p, mobj->standingslope->id);
@ -2151,6 +2159,8 @@ static void LoadMobjThinker(actionf_p1 thinker)
mobj->hnext = (mobj_t *)(size_t)READUINT32(save_p);
if (diff2 & MD2_HPREV)
mobj->hprev = (mobj_t *)(size_t)READUINT32(save_p);
if (diff2 & MD2_ITNEXT)
mobj->itnext = (mobj_t *)(size_t)READUINT32(save_p);
#ifdef ESLOPE
if (diff2 & MD2_SLOPE)
{
@ -2192,6 +2202,9 @@ static void LoadMobjThinker(actionf_p1 thinker)
if (diff2 & MD2_WAYPOINTCAP)
P_SetTarget(&waypointcap, mobj);
if (diff2 & MD2_KITEMCAP)
P_SetTarget(&kitemcap, mobj);
mobj->info = (mobjinfo_t *)next; // temporarily, set when leave this function
}
@ -3044,6 +3057,13 @@ static void P_RelinkPointers(void)
if (!(mobj->hprev = P_FindNewPosition(temp)))
CONS_Debug(DBG_GAMELOGIC, "hprev not found on %d\n", mobj->type);
}
if (mobj->itnext)
{
temp = (UINT32)(size_t)mobj->itnext;
mobj->itnext = NULL;
if (!(mobj->itnext = P_FindNewPosition(temp)))
CONS_Debug(DBG_GAMELOGIC, "itnext not found on %d\n", mobj->type);
}
if (mobj->player && mobj->player->capsule)
{
temp = (UINT32)(size_t)mobj->player->capsule;
@ -3324,7 +3344,7 @@ static void P_NetArchiveMisc(void)
WRITEUINT32(save_p, hyubgone);
WRITEUINT32(save_p, mapreset);
for (i = 0; i < MAXPLAYERS; i++)
for (i = 0; i < MAXPLAYERS; i++)
WRITEINT16(save_p, nospectategrief[i]);
WRITEUINT8(save_p, thwompsactive);
@ -3447,7 +3467,7 @@ static inline boolean P_NetUnArchiveMisc(void)
hyubgone = READUINT32(save_p);
mapreset = READUINT32(save_p);
for (i = 0; i < MAXPLAYERS; i++)
for (i = 0; i < MAXPLAYERS; i++)
nospectategrief[i] = READINT16(save_p);
thwompsactive = (boolean)READUINT8(save_p);

View file

@ -2,7 +2,7 @@
//-----------------------------------------------------------------------------
// Copyright (C) 1993-1996 by id Software, Inc.
// Copyright (C) 1998-2000 by DooM Legacy Team.
// Copyright (C) 1999-2018 by Sonic Team Junior.
// Copyright (C) 1999-2020 by Sonic Team Junior.
//
// This program is free software distributed under the
// terms of the GNU General Public License, version 2.
@ -14,6 +14,7 @@
#include "doomdef.h"
#include "doomstat.h"
#include "p_local.h"
#include "p_slopes.h"
#include "r_main.h"
#include "r_state.h"
@ -103,12 +104,20 @@ static fixed_t P_InterceptVector2(divline_t *v2, divline_t *v1)
static boolean P_CrossSubsecPolyObj(polyobj_t *po, register los_t *los)
{
size_t i;
sector_t *polysec;
if (!(po->flags & POF_RENDERALL))
return true; // the polyobject isn't visible, so we can ignore it
polysec = po->lines[0]->backsector;
for (i = 0; i < po->numLines; ++i)
{
line_t *line = po->lines[i];
divline_t divl;
const vertex_t *v1,*v2;
fixed_t frac;
fixed_t topslope, bottomslope;
// already checked other side?
if (line->validcount == validcount)
@ -140,7 +149,22 @@ static boolean P_CrossSubsecPolyObj(polyobj_t *po, register los_t *los)
continue;
// stop because it is not two sided
return false;
//if (!(po->flags & POF_TESTHEIGHT))
//return false;
frac = P_InterceptVector2(&los->strace, &divl);
// get slopes of top and bottom of this polyobject line
topslope = FixedDiv(polysec->ceilingheight - los->sightzstart , frac);
bottomslope = FixedDiv(polysec->floorheight - los->sightzstart , frac);
if (topslope >= los->topslope && bottomslope <= los->bottomslope)
return false; // view completely blocked
// TODO: figure out if it's worth considering partially blocked cases or not?
// maybe to adjust los's top/bottom slopes if needed
//if (los->topslope <= los->bottomslope)
//return false;
}
return true;
@ -193,6 +217,15 @@ static boolean P_CrossSubsector(size_t num, register los_t *los)
const sector_t *front, *back;
const vertex_t *v1,*v2;
fixed_t frac;
fixed_t frontf, backf, frontc, backc;
#ifdef ESLOPE
fixed_t fracx, fracy;
#endif
/* SRB2Kart doesn't have this?
if (seg->glseg)
continue;
*/
// already checked other side?
if (line->validcount == validcount)
@ -227,36 +260,51 @@ static boolean P_CrossSubsector(size_t num, register los_t *los)
if (!(line->flags & ML_TWOSIDED))
return false;
// calculate fractional intercept (how far along we are divided by how far we are from t2)
frac = P_InterceptVector2(&los->strace, &divl);
front = seg->frontsector;
back = seg->backsector;
#ifdef ESLOPE
// calculate position at intercept
fracx = los->strace.x + FixedMul(los->strace.dx, frac);
fracy = los->strace.y + FixedMul(los->strace.dy, frac);
// calculate sector heights
frontf = (front->f_slope) ? P_GetZAt(front->f_slope, fracx, fracy) : front->floorheight;
frontc = (front->c_slope) ? P_GetZAt(front->c_slope, fracx, fracy) : front->ceilingheight;
backf = (back->f_slope) ? P_GetZAt(back->f_slope, fracx, fracy) : back->floorheight;
backc = (back->c_slope) ? P_GetZAt(back->c_slope, fracx, fracy) : back->ceilingheight;
#else
frontf = front->floorheight;
frontc = front->ceilingheight;
backf = back->floorheight;
backc = back->ceilingheight;
#endif
// crosses a two sided line
// no wall to block sight with?
if ((front = seg->frontsector)->floorheight ==
(back = seg->backsector)->floorheight &&
front->ceilingheight == back->ceilingheight)
if (frontf == backf && frontc == backc
&& !front->ffloors & !back->ffloors) // (and no FOFs)
continue;
// possible occluder
// because of ceiling height differences
popentop = front->ceilingheight < back->ceilingheight ?
front->ceilingheight : back->ceilingheight ;
popentop = min(frontc, backc);
// because of floor height differences
popenbottom = front->floorheight > back->floorheight ?
front->floorheight : back->floorheight ;
popenbottom = max(frontf, backf);
// quick test for totally closed doors
if (popenbottom >= popentop)
return false;
frac = P_InterceptVector2(&los->strace, &divl);
if (front->floorheight != back->floorheight)
if (frontf != backf)
{
fixed_t slope = FixedDiv(popenbottom - los->sightzstart , frac);
if (slope > los->bottomslope)
los->bottomslope = slope;
}
if (front->ceilingheight != back->ceilingheight)
if (frontc != backc)
{
fixed_t slope = FixedDiv(popentop - los->sightzstart , frac);
if (slope < los->topslope)
@ -265,6 +313,58 @@ static boolean P_CrossSubsector(size_t num, register los_t *los)
if (los->topslope <= los->bottomslope)
return false;
// Monster Iestyn: check FOFs!
if (front->ffloors || back->ffloors)
{
ffloor_t *rover;
fixed_t topslope, bottomslope;
fixed_t topz, bottomz;
// check front sector's FOFs first
for (rover = front->ffloors; rover; rover = rover->next)
{
if (!(rover->flags & FF_EXISTS)
|| !(rover->flags & FF_RENDERSIDES) || rover->flags & FF_TRANSLUCENT)
{
continue;
}
#ifdef ESLOPE
topz = (*rover->t_slope) ? P_GetZAt(*rover->t_slope, fracx, fracy) : *rover->topheight;
bottomz = (*rover->b_slope) ? P_GetZAt(*rover->b_slope, fracx, fracy) : *rover->bottomheight;
#else
topz = *rover->topheight;
bottomz = *rover->bottomheight;
#endif
topslope = FixedDiv(topz - los->sightzstart , frac);
bottomslope = FixedDiv(bottomz - los->sightzstart , frac);
if (topslope >= los->topslope && bottomslope <= los->bottomslope)
return false; // view completely blocked
}
// check back sector's FOFs as well
for (rover = back->ffloors; rover; rover = rover->next)
{
if (!(rover->flags & FF_EXISTS)
|| !(rover->flags & FF_RENDERSIDES) || rover->flags & FF_TRANSLUCENT)
{
continue;
}
#ifdef ESLOPE
topz = (*rover->t_slope) ? P_GetZAt(*rover->t_slope, fracx, fracy) : *rover->topheight;
bottomz = (*rover->b_slope) ? P_GetZAt(*rover->b_slope, fracx, fracy) : *rover->bottomheight;
#else
topz = *rover->topheight;
bottomz = *rover->bottomheight;
#endif
topslope = FixedDiv(topz - los->sightzstart , frac);
bottomslope = FixedDiv(bottomz - los->sightzstart , frac);
if (topslope >= los->topslope && bottomslope <= los->bottomslope)
return false; // view completely blocked
}
// TODO: figure out if it's worth considering partially blocked cases or not?
// maybe to adjust los's top/bottom slopes if needed
}
}
// passed the subsector ok
@ -375,6 +475,8 @@ boolean P_CheckSight(mobj_t *t1, mobj_t *t2)
if (s1 == s2) // Both sectors are the same.
{
ffloor_t *rover;
fixed_t topz1, bottomz1; // top, bottom heights at t1's position
fixed_t topz2, bottomz2; // likewise but for t2
for (rover = s1->ffloors; rover; rover = rover->next)
{
@ -382,14 +484,35 @@ boolean P_CheckSight(mobj_t *t1, mobj_t *t2)
/// \todo Improve by checking fog density/translucency
/// and setting a sight limit.
if (!(rover->flags & FF_EXISTS)
|| !(rover->flags & FF_RENDERPLANES) || rover->flags & FF_TRANSLUCENT)
|| !(rover->flags & FF_RENDERPLANES) /*|| (rover->flags & FF_TRANSLUCENT)*/)
{
continue;
}
#ifdef ESLOPE
if (*rover->t_slope)
{
topz1 = P_GetZAt(*rover->t_slope, t1->x, t1->y);
topz2 = P_GetZAt(*rover->t_slope, t2->x, t2->y);
}
else
topz1 = topz2 = *rover->topheight;
if (*rover->b_slope)
{
bottomz1 = P_GetZAt(*rover->b_slope, t1->x, t1->y);
bottomz2 = P_GetZAt(*rover->b_slope, t2->x, t2->y);
}
else
bottomz1 = bottomz2 = *rover->bottomheight;
#else
topz1 = topz2 = *rover->topheight;
bottomz1 = bottomz2 = *rover->bottomheight;
#endif
// Check for blocking floors here.
if ((los.sightzstart < *rover->bottomheight && t2->z >= *rover->topheight)
|| (los.sightzstart >= *rover->topheight && t2->z + t2->height < *rover->bottomheight))
if ((los.sightzstart < bottomz1 && t2->z >= topz2)
|| (los.sightzstart >= topz1 && t2->z + t2->height < bottomz2))
{
// no way to see through that
return false;
@ -400,19 +523,19 @@ boolean P_CheckSight(mobj_t *t1, mobj_t *t2)
if (!(rover->flags & FF_INVERTPLANES))
{
if (los.sightzstart >= *rover->topheight && t2->z + t2->height < *rover->topheight)
if (los.sightzstart >= topz1 && t2->z + t2->height < topz2)
return false; // blocked by upper outside plane
if (los.sightzstart < *rover->bottomheight && t2->z >= *rover->bottomheight)
if (los.sightzstart < bottomz1 && t2->z >= bottomz2)
return false; // blocked by lower outside plane
}
if (rover->flags & FF_INVERTPLANES || rover->flags & FF_BOTHPLANES)
{
if (los.sightzstart < *rover->topheight && t2->z >= *rover->topheight)
if (los.sightzstart < topz1 && t2->z >= topz2)
return false; // blocked by upper inside plane
if (los.sightzstart >= *rover->bottomheight && t2->z + t2->height < *rover->bottomheight)
if (los.sightzstart >= bottomz1 && t2->z + t2->height < bottomz2)
return false; // blocked by lower inside plane
}
}

View file

@ -1705,41 +1705,6 @@ boolean P_RunTriggerLinedef(line_t *triggerline, mobj_t *actor, sector_t *caller
if (!(ALL7EMERALDS(emeralds)))
return false;
}
else if (GETSECSPECIAL(caller->special, 2) == 7) // SRB2Kart: reusing for Race Lap executor
{
UINT8 lap;
if (actor && actor->player && triggerline->flags & ML_EFFECT4)
{
/*if (maptol & TOL_NIGHTS)
lap = actor->player->mare;
else*/
lap = actor->player->laps;
}
else
{
/*if (maptol & TOL_NIGHTS)
lap = P_FindLowestMare();
else*/
lap = P_FindLowestLap();
}
if (triggerline->flags & ML_NOCLIMB) // Need higher than or equal to
{
if (lap < (sides[triggerline->sidenum[0]].textureoffset >> FRACBITS))
return false;
}
else if (triggerline->flags & ML_BLOCKMONSTERS) // Need lower than or equal to
{
if (lap > (sides[triggerline->sidenum[0]].textureoffset >> FRACBITS))
return false;
}
else // Need equal to
{
if (lap != (sides[triggerline->sidenum[0]].textureoffset >> FRACBITS))
return false;
}
}
// If we were not triggered by a sector type especially for the purpose,
// a Linedef Executor linedef trigger is not handling sector triggers properly, return.
@ -1937,15 +1902,17 @@ boolean P_RunTriggerLinedef(line_t *triggerline, mobj_t *actor, sector_t *caller
else
// These special types work only once
if (specialtype == 302 // Once
|| specialtype == 304 // Ring count - Once
|| specialtype == 307 // Character ability - Once
|| specialtype == 308 // Race only - Once
|| specialtype == 315 // No of pushables - Once
|| specialtype == 318 // Unlockable trigger - Once
|| specialtype == 320 // Unlockable - Once
|| specialtype == 321 || specialtype == 322 // Trigger on X calls - Continuous + Each Time
|| specialtype == 328 // Encore Load
|| specialtype == 399) // Level Load
|| specialtype == 304 // Ring count - Once
|| specialtype == 307 // Character ability - Once
|| specialtype == 308 // Race only - Once
|| specialtype == 315 // No of pushables - Once
|| specialtype == 318 // Unlockable trigger - Once
|| specialtype == 320 // Unlockable - Once
|| specialtype == 321 || specialtype == 322 // Trigger on X calls - Continuous + Each Time
|| specialtype == 328 // Encore Load
|| specialtype == 399 // Level Load
|| specialtype == 2002 // SRB2Kart Race Lap
)
triggerline->special = 0; // Clear it out
return true;
@ -1981,6 +1948,7 @@ void P_LinedefExecute(INT16 tag, mobj_t *actor, sector_t *caller)
if (lines[masterline].special == 313
|| lines[masterline].special == 399
|| lines[masterline].special == 328
|| lines[masterline].special == 2002 // SRB2Kart race lap trigger
// Each-time executors handle themselves, too
|| lines[masterline].special == 301 // Each time
|| lines[masterline].special == 306 // Character ability - Each time
@ -2096,7 +2064,7 @@ static void K_HandleLapIncrement(player_t *player)
{
if ((player->starpostnum == numstarposts) || (player->laps == 0))
{
UINT8 i = 0;
size_t i = 0;
UINT8 nump = 0;
for (i = 0; i < MAXPLAYERS; i++)
@ -2172,17 +2140,42 @@ static void K_HandleLapIncrement(player_t *player)
P_SetupSignExit(player);
}
//player->starpostangle = player->starposttime = player->starpostnum = 0;
//player->starpostx = player->starposty = player->starpostz = 0;
// Play the starpost sound for 'consistency'
// S_StartSound(player->mo, sfx_strpst);
// Figure out how many are playing on the last lap, to prevent spectate griefing
if (!nospectategrief && player->laps > (UINT8)(cv_numlaps.value))
nospectategrief = nump;
thwompsactive = true; // Lap 2 effects
for (i = 0; i < numlines; i++)
{
if (lines[i].special == 2002) // Race lap trigger
{
UINT8 lap;
if (lines[i].flags & ML_EFFECT4)
{
lap = player->laps;
}
else
{
lap = P_FindLowestLap();
}
if (lines[i].flags & ML_NOCLIMB) // Need higher than or equal to
{
if (lap < (sides[lines[i].sidenum[0]].textureoffset >> FRACBITS))
continue;
}
else if (lines[i].flags & ML_BLOCKMONSTERS) // Need lower than or equal to
{
if (lap > (sides[lines[i].sidenum[0]].textureoffset >> FRACBITS))
continue;
}
else // Need equal to
{
if (lap != (sides[lines[i].sidenum[0]].textureoffset >> FRACBITS))
continue;
}
P_RunTriggerLinedef(&lines[i], player->mo, NULL);
}
}
}
else if (player->starpostnum)
{
@ -2196,7 +2189,7 @@ static void K_HandleLapDecrement(player_t *player)
{
if (player)
{
if (player->laps > 0)
if ((player->starpostnum == 0) && (player->laps > 0))
{
player->starpostnum = numstarposts;
player->laps--;
@ -2220,7 +2213,7 @@ void P_CrossSpecialLine(line_t *line, INT32 side, mobj_t *thing)
{
case 2001: // Finish Line
{
if (G_RaceGametype() && !(player->exiting))
if (G_RaceGametype() && !(player->exiting) && !(player->pflags & PF_HITFINISHLINE))
{
if (((line->flags & (ML_NOCLIMB)) && (side == 0))
|| (!(line->flags & (ML_NOCLIMB)) && (side == 1))) // crossed from behind to infront
@ -2231,6 +2224,8 @@ void P_CrossSpecialLine(line_t *line, INT32 side, mobj_t *thing)
{
K_HandleLapDecrement(player);
}
player->pflags |= PF_HITFINISHLINE;
}
}
break;
@ -3776,10 +3771,10 @@ void P_ProcessSpecialSector(player_t *player, sector_t *sector, sector_t *rovers
case 6: // Death Pit (Camera Mod)
case 7: // Death Pit (No Camera Mod)
if (roversector || P_MobjReadyToTrigger(player->mo, sector))
P_DamageMobj(player->mo, NULL, NULL, 10000);
K_DoIngameRespawn(player);
break;
case 8: // Instant Kill
P_DamageMobj(player->mo, NULL, NULL, 10000);
K_DoIngameRespawn(player);
break;
case 9: // Ring Drainer (Floor Touch)
case 10: // Ring Drainer (No Floor Touch)
@ -4017,7 +4012,7 @@ DoneSection2:
if (player->mo->scale > mapobjectscale)
linespeed = FixedMul(linespeed, mapobjectscale + (player->mo->scale - mapobjectscale));
if (!demo.playback || P_AnalogMove(player))
if (!demo.playback)
{
if (player == &players[consoleplayer])
localangle[0] = player->mo->angle;
@ -5782,6 +5777,8 @@ void P_SpawnSpecials(INT32 fromnetsave)
switch(GETSECSPECIAL(sector->special, 4))
{
case 10: // Circuit finish line (Unused)
// Remove before release
CONS_Alert(CONS_WARNING, "Finish line sector type is deprecated.\n");
break;
}
}
@ -6712,12 +6709,15 @@ void P_SpawnSpecials(INT32 fromnetsave)
sectors[s].midmap = lines[i].frontsector->midmap;
break;
// SRB2Kart
case 2000: // Waypoint Parameters
break;
case 2001: // Finish Line
if (G_RaceGametype())
circuitmap = true;
break;
case 2002: // Linedef Trigger: Race Lap
break;
default:
break;
}
@ -6938,8 +6938,8 @@ void T_Scroll(scroll_t *s)
height = P_GetSpecialBottomZ(thing, sec, psec);
if (!(thing->flags & MF_NOCLIP)) // Thing must be clipped
if (!(thing->flags & MF_NOGRAVITY || thing->z+thing->height != height)) // Thing must a) be non-floating and have z+height == height
if (!(thing->flags & MF_NOCLIP) && // Thing must be clipped
(!(thing->flags & MF_NOGRAVITY || thing->z+thing->height != height))) // Thing must a) be non-floating and have z+height == height
{
// Move objects only if on floor
// non-floating, and clipped.
@ -7014,8 +7014,8 @@ void T_Scroll(scroll_t *s)
height = P_GetSpecialTopZ(thing, sec, psec);
if (!(thing->flags & MF_NOCLIP)) // Thing must be clipped
if (!(thing->flags & MF_NOGRAVITY || thing->z != height))// Thing must a) be non-floating and have z == height
if (!(thing->flags & MF_NOCLIP) && // Thing must be clipped
(!(thing->flags & MF_NOGRAVITY || thing->z != height))) // Thing must a) be non-floating and have z == height
{
// Move objects only if on floor or underwater,
// non-floating, and clipped.
@ -7910,7 +7910,7 @@ void T_Pusher(pusher_t *p)
thing->player->pflags |= PF_SLIDING;
thing->angle = R_PointToAngle2 (0, 0, xspeed<<(FRACBITS-PUSH_FACTOR), yspeed<<(FRACBITS-PUSH_FACTOR));
if (!demo.playback || P_AnalogMove(thing->player))
if (!demo.playback)
{
if (thing->player == &players[consoleplayer])
{

View file

@ -173,6 +173,7 @@ void P_InitThinkers(void)
{
thinkercap.prev = thinkercap.next = &thinkercap;
waypointcap = NULL;
kitemcap = NULL;
}
//
@ -629,6 +630,9 @@ void P_Ticker(boolean run)
if (runemeraldmanager)
P_EmeraldManager(); // Power stone mode*/
// formality so kitemcap gets updated properly each frame.
P_RunKartItems();
if (run)
{
P_RunThinkers();

View file

@ -3716,11 +3716,6 @@ void P_Telekinesis(player_t *player, fixed_t thrust, fixed_t range)
player->pflags |= PF_THOKKED;
}
boolean P_AnalogMove(player_t *player)
{
return player->pflags & PF_ANALOGMODE;
}
//
// P_GetPlayerControlDirection
//
@ -3763,14 +3758,6 @@ boolean P_AnalogMove(player_t *player)
origtempangle = tempangle = 0; // relative to the axis rather than the player!
controlplayerdirection = R_PointToAngle2(0, 0, player->mo->momx, player->mo->momy);
}
else if (P_AnalogMove(player) && thiscam->chase)
{
if (player->awayviewtics)
origtempangle = tempangle = player->awayviewmobj->angle;
else
origtempangle = tempangle = thiscam->angle;
controlplayerdirection = player->mo->angle;
}
else
{
origtempangle = tempangle = player->mo->angle;
@ -3994,7 +3981,6 @@ static void P_3dMovement(player_t *player)
angle_t dangle; // replaces old quadrants bits
//boolean dangleflip = false; // SRB2kart - toaster
//fixed_t normalspd = FixedMul(player->normalspeed, player->mo->scale);
boolean analogmove = false;
fixed_t oldMagnitude, newMagnitude;
#ifdef ESLOPE
vector3_t totalthrust;
@ -4006,8 +3992,6 @@ static void P_3dMovement(player_t *player)
// Get the old momentum; this will be needed at the end of the function! -SH
oldMagnitude = R_PointToDist2(player->mo->momx - player->cmomx, player->mo->momy - player->cmomy, 0, 0);
analogmove = P_AnalogMove(player);
cmd = &player->cmd;
if ((player->exiting || mapreset) || player->pflags & PF_STASIS || player->kartstuff[k_spinouttimer]) // pw_introcam?
@ -4020,19 +4004,13 @@ static void P_3dMovement(player_t *player)
if (!(player->pflags & PF_FORCESTRAFE) && !player->kartstuff[k_pogospring])
cmd->sidemove = 0;
if (analogmove)
{
movepushangle = (cmd->angleturn<<16 /* not FRACBITS */);
}
if (player->kartstuff[k_drift] != 0)
movepushangle = player->mo->angle-(ANGLE_45/5)*player->kartstuff[k_drift];
else if (player->kartstuff[k_spinouttimer] || player->kartstuff[k_wipeoutslow]) // if spun out, use the boost angle
movepushangle = (angle_t)player->kartstuff[k_boostangle];
else
{
if (player->kartstuff[k_drift] != 0)
movepushangle = player->mo->angle-(ANGLE_45/5)*player->kartstuff[k_drift];
else if (player->kartstuff[k_spinouttimer] || player->kartstuff[k_wipeoutslow]) // if spun out, use the boost angle
movepushangle = (angle_t)player->kartstuff[k_boostangle];
else
movepushangle = player->mo->angle;
}
movepushangle = player->mo->angle;
movepushsideangle = movepushangle-ANGLE_90;
// cmomx/cmomy stands for the conveyor belt speed.
@ -6191,69 +6169,6 @@ static void P_MovePlayer(player_t *player)
player->pflags &= ~PF_STARTDASH;
*/
//////////////////
//ANALOG CONTROL//
//////////////////
#if 0
// This really looks like it should be moved to P_3dMovement. -Red
if (P_AnalogMove(player)
&& (cmd->forwardmove != 0 || cmd->sidemove != 0) && !player->climbing && !twodlevel && !(player->mo->flags2 & MF2_TWOD))
{
// If travelling slow enough, face the way the controls
// point and not your direction of movement.
if (player->speed < FixedMul(5*FRACUNIT, player->mo->scale) || player->pflags & PF_GLIDING || !onground)
{
angle_t tempangle;
tempangle = (cmd->angleturn << 16);
#ifdef REDSANALOG // Ease to it. Chillax. ~Red
tempangle += R_PointToAngle2(0, 0, cmd->forwardmove*FRACUNIT, -cmd->sidemove*FRACUNIT);
{
fixed_t tweenvalue = max(abs(cmd->forwardmove), abs(cmd->sidemove));
if (tweenvalue < 10 && (cmd->buttons & (BT_FORWARD|BT_BACKWARD)) == (BT_FORWARD|BT_BACKWARD)) {
tempangle = (cmd->angleturn << 16);
tweenvalue = 16;
}
tweenvalue *= tweenvalue*tweenvalue*1536;
//if (player->pflags & PF_GLIDING)
//tweenvalue >>= 1;
tempangle -= player->mo->angle;
if (tempangle < ANGLE_180 && tempangle > tweenvalue)
player->mo->angle += tweenvalue;
else if (tempangle >= ANGLE_180 && InvAngle(tempangle) > tweenvalue)
player->mo->angle -= tweenvalue;
else
player->mo->angle += tempangle;
}
#else
// Less math this way ~Red
player->mo->angle = R_PointToAngle2(0, 0, cmd->forwardmove*FRACUNIT, -cmd->sidemove*FRACUNIT)+tempangle;
#endif
}
// Otherwise, face the direction you're travelling.
else if (player->panim == PA_WALK || player->panim == PA_RUN || player->panim == PA_ROLL
/*|| ((player->mo->state >= &states[S_PLAY_ABL1] && player->mo->state <= &states[S_PLAY_SPC4]) && player->charability == CA_FLY)*/) // SRB2kart - idk
player->mo->angle = R_PointToAngle2(0, 0, player->rmomx, player->rmomy);
// Update the local angle control.
if (player == &players[consoleplayer])
localangle[0] = player->mo->angle;
else if (player == &players[displayplayers[1]])
localangle[1] = player->mo->angle;
else if (player == &players[displayplayers[2]])
localangle[2] = player->mo->angle;
else if (player == &players[displayplayers[3]])
localangle[3] = player->mo->angle;
}
#endif
///////////////////////////
//BOMB SHIELD ACTIVATION,//
//HOMING, AND OTHER COOL //
@ -8132,12 +8047,6 @@ void P_PlayerThink(player_t *player)
// The timer might've reached zero, but we'll run the remote view camera anyway by setting it to -1.
}
/// \note do this in the cheat code
if (player->pflags & PF_NOCLIP)
player->mo->flags |= MF_NOCLIP;
else
player->mo->flags &= ~MF_NOCLIP;
cmd = &player->cmd;
// SRB2kart
@ -8370,26 +8279,7 @@ void P_PlayerThink(player_t *player)
player->mo->reactiontime--;
else if (player->mo->tracer && player->mo->tracer->type == MT_TUBEWAYPOINT)
{
// SRB2kart - don't need no rope hangin'
//if (player->pflags & PF_ROPEHANG)
//{
// if (!P_AnalogMove(player))
// player->mo->angle = (cmd->angleturn<<16 /* not FRACBITS */);
// ticruned++;
// if ((cmd->angleturn & TICCMD_RECEIVED) == 0)
// ticmiss++;
// P_DoRopeHang(player);
// P_SetPlayerMobjState(player->mo, S_PLAY_CARRY);
// P_DoJumpStuff(player, &player->cmd);
//}
//else
{
P_DoZoomTube(player);
//if (!(player->panim == PA_ROLL) && player->charability2 == CA2_SPINDASH) // SRB2kart
// P_SetPlayerMobjState(player->mo, S_PLAY_ATK1);
}
P_DoZoomTube(player);
player->rmomx = player->rmomy = 0; // no actual momentum from your controls
P_ResetScore(player);
}