mirror of
https://github.com/KartKrewDev/RingRacers.git
synced 2025-10-30 08:01:28 +00:00
Merge branch 'master' of https://git.do.srb2.org/KartKrew/Kart into new-menus
This commit is contained in:
commit
1abfb2745a
27 changed files with 614 additions and 354 deletions
|
|
@ -5150,7 +5150,7 @@ static void SV_Maketic(void)
|
|||
{
|
||||
INT32 i;
|
||||
|
||||
ps_botticcmd_time = 0;
|
||||
PS_ResetBotInfo();
|
||||
|
||||
for (i = 0; i < MAXPLAYERS; i++)
|
||||
{
|
||||
|
|
@ -5159,9 +5159,13 @@ static void SV_Maketic(void)
|
|||
|
||||
if (K_PlayerUsesBotMovement(&players[i]))
|
||||
{
|
||||
precise_t t = I_GetPreciseTime();
|
||||
const precise_t t = I_GetPreciseTime();
|
||||
|
||||
K_BuildBotTiccmd(&players[i], &netcmds[maketic%BACKUPTICS][i]);
|
||||
ps_botticcmd_time += I_GetPreciseTime() - t;
|
||||
|
||||
ps_bots[i].isBot = true;
|
||||
ps_bots[i].total = I_GetPreciseTime() - t;
|
||||
ps_botticcmd_time += ps_bots[i].total;
|
||||
continue;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -61,6 +61,7 @@
|
|||
#include "k_follower.h"
|
||||
#include "doomstat.h"
|
||||
#include "deh_tables.h"
|
||||
#include "m_perfstats.h"
|
||||
|
||||
#ifdef NETGAME_DEVMODE
|
||||
#define CV_RESTRICT CV_NETVAR
|
||||
|
|
@ -533,7 +534,13 @@ consvar_t cv_mute = CVAR_INIT ("mute", "Off", CV_NETVAR|CV_CALL, CV_OnOff, Mute_
|
|||
consvar_t cv_sleep = CVAR_INIT ("cpusleep", "1", CV_SAVE, sleeping_cons_t, NULL);
|
||||
|
||||
static CV_PossibleValue_t perfstats_cons_t[] = {
|
||||
{0, "Off"}, {1, "Rendering"}, {2, "Logic"}, {3, "ThinkFrame"}, {0, NULL}};
|
||||
{PS_OFF, "Off"},
|
||||
{PS_RENDER, "Rendering"},
|
||||
{PS_LOGIC, "Logic"},
|
||||
{PS_BOT, "Bots"},
|
||||
{PS_THINKFRAME, "ThinkFrame"},
|
||||
{0, NULL}
|
||||
};
|
||||
consvar_t cv_perfstats = CVAR_INIT ("perfstats", "Off", 0, perfstats_cons_t, NULL);
|
||||
|
||||
consvar_t cv_director = CVAR_INIT ("director", "Off", 0, CV_OnOff, NULL);
|
||||
|
|
|
|||
|
|
@ -204,11 +204,19 @@ typedef enum
|
|||
|
||||
typedef enum
|
||||
{
|
||||
TRIP_NONE,
|
||||
TRIP_PASSED,
|
||||
TRIP_BLOCKED,
|
||||
TRIPSTATE_NONE,
|
||||
TRIPSTATE_PASSED,
|
||||
TRIPSTATE_BLOCKED,
|
||||
} tripwirestate_t;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
TRIPWIRE_NONE,
|
||||
TRIPWIRE_IGNORE,
|
||||
TRIPWIRE_BOOST,
|
||||
TRIPWIRE_BLASTER,
|
||||
} tripwirepass_t;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
// Unsynced, HUD or clientsided effects
|
||||
|
|
@ -260,6 +268,8 @@ typedef enum
|
|||
#define TUMBLEBOUNCES 3
|
||||
#define TUMBLEGRAVITY (4*FRACUNIT)
|
||||
|
||||
#define TRIPWIRETIME (TICRATE)
|
||||
|
||||
//}
|
||||
|
||||
// for kickstartaccel
|
||||
|
|
@ -444,6 +454,8 @@ typedef struct player_s
|
|||
UINT16 draftleeway; // Leniency timer before removing draft power
|
||||
SINT8 lastdraft; // (-1 to 15) - Last player being drafted
|
||||
|
||||
UINT8 tripwireState; // see tripwirestate_t
|
||||
UINT8 tripwirePass; // see tripwirepass_t
|
||||
UINT16 tripwireLeniency; // When reaching a state that lets you go thru tripwire, you get an extra second leniency after it ends to still go through it.
|
||||
|
||||
UINT16 itemroulette; // Used for the roulette when deciding what item to give you (was "pw_kartitem")
|
||||
|
|
@ -513,8 +525,6 @@ typedef struct player_s
|
|||
|
||||
SINT8 glanceDir; // Direction the player is trying to look backwards in
|
||||
|
||||
UINT8 tripWireState; // see tripwirestate_t
|
||||
|
||||
//
|
||||
|
||||
SINT8 lives;
|
||||
|
|
|
|||
|
|
@ -3805,6 +3805,12 @@ const char *const STATE_LIST[] = { // array length left dynamic for sanity testi
|
|||
"S_BATTLEBUMPER_EXBLAST9",
|
||||
"S_BATTLEBUMPER_EXBLAST10",
|
||||
|
||||
// Tripwire
|
||||
"S_TRIPWIREBOOST_TOP",
|
||||
"S_TRIPWIREBOOST_BOTTOM",
|
||||
"S_TRIPWIREBOOST_BLAST_TOP",
|
||||
"S_TRIPWIREBOOST_BLAST_BOTTOM",
|
||||
|
||||
// DEZ respawn laser
|
||||
"S_DEZLASER",
|
||||
"S_DEZLASER_TRAIL1",
|
||||
|
|
@ -5338,6 +5344,8 @@ const char *const MOBJTYPE_LIST[] = { // array length left dynamic for sanity t
|
|||
"MT_BATTLEBUMPER_DEBRIS",
|
||||
"MT_BATTLEBUMPER_BLAST",
|
||||
|
||||
"MT_TRIPWIREBOOST",
|
||||
|
||||
"MT_DEZLASER",
|
||||
|
||||
"MT_WAYPOINT",
|
||||
|
|
|
|||
|
|
@ -2354,7 +2354,6 @@ void G_PlayerReborn(INT32 player, boolean betweenmaps)
|
|||
p->karthud[khud_fault] = khudfault;
|
||||
p->nocontrol = nocontrol;
|
||||
p->kickstartaccel = kickstartaccel;
|
||||
p->tripWireState = TRIP_NONE;
|
||||
|
||||
p->botvars.rubberband = FRACUNIT;
|
||||
p->botvars.controller = UINT16_MAX;
|
||||
|
|
|
|||
|
|
@ -5129,7 +5129,7 @@ static void HWR_ProjectSprite(mobj_t *thing)
|
|||
R_InterpolateMobjState(thing, FRACUNIT, &interp);
|
||||
}
|
||||
|
||||
dispoffset = thing->info->dispoffset;
|
||||
dispoffset = thing->dispoffset;
|
||||
|
||||
// hitlag vibrating (todo: interp somehow?)
|
||||
if (thing->hitlag > 0 && (thing->eflags & MFE_DAMAGEHITLAG))
|
||||
|
|
|
|||
36
src/info.c
36
src/info.c
|
|
@ -580,7 +580,8 @@ char sprnames[NUMSPRITES + 1][5] =
|
|||
"BEXS", // Battle Bumper Explosion: Shell
|
||||
"BDEB", // Battle Bumper Explosion: Debris
|
||||
"BEXB", // Battle Bumper Explosion: Blast
|
||||
|
||||
"TWBS", // Tripwire Boost
|
||||
"TWBT", // Tripwire BLASTER
|
||||
"DEZL", // DEZ Laser respawn
|
||||
|
||||
// Additional Kart Objects
|
||||
|
|
@ -4361,6 +4362,12 @@ state_t states[NUMSTATES] =
|
|||
{SPR_BEXB, FF_FULLBRIGHT|FF_PAPERSPRITE|FF_TRANS80, 2, {NULL}, 0, 0, S_BATTLEBUMPER_EXBLAST10}, // S_BATTLEBUMPER_EXBLAST9
|
||||
{SPR_BEXB, FF_FULLBRIGHT|FF_PAPERSPRITE|FF_TRANS90, 2, {NULL}, 0, 0, S_NULL}, // S_BATTLEBUMPER_EXBLAST10
|
||||
|
||||
{SPR_TWBS, FF_FULLBRIGHT|FF_ADD|FF_ANIMATE, -1, {NULL}, 6, 2, S_NULL}, // S_TRIPWIREBOOST_TOP
|
||||
{SPR_TWBS, FF_FULLBRIGHT|FF_ADD|FF_ANIMATE|FF_VERTICALFLIP|FF_HORIZONTALFLIP, -1, {NULL}, 6, 2, S_NULL}, // S_TRIPWIREBOOST_BOTTOM
|
||||
|
||||
{SPR_TWBT, FF_FULLBRIGHT|FF_ADD|FF_ANIMATE, -1, {NULL}, 6, 2, S_NULL}, // S_TRIPWIREBOOST_BLAST_TOP
|
||||
{SPR_TWBT, FF_FULLBRIGHT|FF_ADD|FF_ANIMATE|FF_VERTICALFLIP|FF_HORIZONTALFLIP, -1, {NULL}, 6, 2, S_NULL}, // S_TRIPWIREBOOST_BLAST_BOTTOM
|
||||
|
||||
{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
|
||||
|
|
@ -24164,6 +24171,33 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
|
|||
S_NULL // raisestate
|
||||
},
|
||||
|
||||
{ // MT_TRIPWIREBOOST
|
||||
-1, // doomednum
|
||||
S_TRIPWIREBOOST_TOP, // spawnstate
|
||||
1000, // spawnhealth
|
||||
S_TRIPWIREBOOST_BOTTOM, // seestate
|
||||
sfx_None, // seesound
|
||||
8, // reactiontime
|
||||
sfx_None, // attacksound
|
||||
S_NULL, // painstate
|
||||
0, // painchance
|
||||
sfx_None, // painsound
|
||||
S_TRIPWIREBOOST_BLAST_TOP, // meleestate
|
||||
S_TRIPWIREBOOST_BLAST_BOTTOM, // missilestate
|
||||
S_NULL, // deathstate
|
||||
S_NULL, // xdeathstate
|
||||
sfx_None, // deathsound
|
||||
0, // speed
|
||||
8*FRACUNIT, // radius
|
||||
16*FRACUNIT, // height
|
||||
1, // display offset
|
||||
100, // mass
|
||||
0, // damage
|
||||
sfx_None, // activesound
|
||||
MF_NOBLOCKMAP|MF_NOGRAVITY|MF_NOCLIPHEIGHT|MF_NOCLIPTHING|MF_DONTENCOREMAP, // flags
|
||||
S_NULL // raisestate
|
||||
},
|
||||
|
||||
{ // MT_DEZLASER
|
||||
-1, // doomednum
|
||||
S_DEZLASER, // spawnstate
|
||||
|
|
|
|||
10
src/info.h
10
src/info.h
|
|
@ -1126,7 +1126,8 @@ typedef enum sprite
|
|||
SPR_BEXS, // Battle Bumper Explosion: Shell
|
||||
SPR_BDEB, // Battle Bumper Explosion: Debris
|
||||
SPR_BEXB, // Battle Bumper Explosion: Blast
|
||||
|
||||
SPR_TWBS, // Tripwire Boost
|
||||
SPR_TWBT, // Tripwire BLASTER
|
||||
SPR_DEZL, // DEZ Laser respawn
|
||||
|
||||
// Additional Kart Objects
|
||||
|
|
@ -4794,6 +4795,11 @@ typedef enum state
|
|||
S_BATTLEBUMPER_EXBLAST9,
|
||||
S_BATTLEBUMPER_EXBLAST10,
|
||||
|
||||
S_TRIPWIREBOOST_TOP,
|
||||
S_TRIPWIREBOOST_BOTTOM,
|
||||
S_TRIPWIREBOOST_BLAST_TOP,
|
||||
S_TRIPWIREBOOST_BLAST_BOTTOM,
|
||||
|
||||
// DEZ Laser respawn
|
||||
S_DEZLASER,
|
||||
S_DEZLASER_TRAIL1,
|
||||
|
|
@ -6364,6 +6370,8 @@ typedef enum mobj_type
|
|||
MT_BATTLEBUMPER_DEBRIS,
|
||||
MT_BATTLEBUMPER_BLAST,
|
||||
|
||||
MT_TRIPWIREBOOST,
|
||||
|
||||
MT_DEZLASER,
|
||||
|
||||
MT_WAYPOINT,
|
||||
|
|
|
|||
316
src/k_bot.c
316
src/k_bot.c
|
|
@ -28,6 +28,7 @@
|
|||
#include "r_things.h" // numskins
|
||||
#include "k_race.h" // finishBeamLine
|
||||
#include "k_boss.h"
|
||||
#include "m_perfstats.h"
|
||||
|
||||
|
||||
/*--------------------------------------------------
|
||||
|
|
@ -279,7 +280,7 @@ boolean K_BotCanTakeCut(player_t *player)
|
|||
{
|
||||
if (
|
||||
#if 1
|
||||
K_TripwirePassConditions(player) == true
|
||||
K_TripwirePassConditions(player) != TRIPWIRE_NONE
|
||||
#else
|
||||
K_ApplyOffroad(player) == false
|
||||
#endif
|
||||
|
|
@ -347,8 +348,8 @@ static fixed_t K_BotSpeedScaled(player_t *player, fixed_t speed)
|
|||
// Going downhill: FRACUNIT*2
|
||||
slopeMul = FRACUNIT + FINECOSINE(angle >> ANGLETOFINESHIFT);
|
||||
|
||||
// Range: 0.9 to 1.1
|
||||
result = FixedMul(result, (FRACUNIT*9/10) + (slopeMul/10));
|
||||
// Range: 0.5 to 1.5
|
||||
result = FixedMul(result, (FRACUNIT>>1) + (slopeMul >> 1));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -638,133 +639,119 @@ fixed_t K_DistanceOfLineFromPoint(fixed_t v1x, fixed_t v1y, fixed_t v2x, fixed_t
|
|||
--------------------------------------------------*/
|
||||
static botprediction_t *K_CreateBotPrediction(player_t *player)
|
||||
{
|
||||
const precise_t time = I_GetPreciseTime();
|
||||
|
||||
// Stair janking makes it harder to steer, so attempt to steer harder.
|
||||
const UINT8 jankDiv = (player->stairjank > 0 ? 2 : 1);
|
||||
const UINT8 jankDiv = (player->stairjank > 0) ? 2 : 1;
|
||||
|
||||
const INT16 handling = K_GetKartTurnValue(player, KART_FULLTURN) / jankDiv; // Reduce prediction based on how fast you can turn
|
||||
const INT16 normal = KART_FULLTURN; // "Standard" handling to compare to
|
||||
|
||||
const tic_t futuresight = (TICRATE * normal) / max(1, handling); // How far ahead into the future to try and predict
|
||||
const tic_t futuresight = (TICRATE * KART_FULLTURN) / max(1, handling); // How far ahead into the future to try and predict
|
||||
const fixed_t speed = K_BotSpeedScaled(player, P_AproxDistance(player->mo->momx, player->mo->momy));
|
||||
|
||||
const INT32 startDist = (768 * mapobjectscale) / FRACUNIT;
|
||||
const INT32 startDist = (DEFAULT_WAYPOINT_RADIUS * 2 * mapobjectscale) / FRACUNIT;
|
||||
const INT32 distance = ((speed / FRACUNIT) * futuresight) + startDist;
|
||||
|
||||
botprediction_t *predict = Z_Calloc(sizeof(botprediction_t), PU_STATIC, NULL);
|
||||
waypoint_t *wp = player->nextwaypoint;
|
||||
|
||||
INT32 distanceleft = distance;
|
||||
fixed_t smallestradius = INT32_MAX;
|
||||
angle_t angletonext = ANGLE_MAX;
|
||||
|
||||
// Halves radius when encountering a wall on your way to your destination.
|
||||
fixed_t radreduce = FRACUNIT;
|
||||
|
||||
size_t nwp;
|
||||
INT32 distanceleft = distance;
|
||||
fixed_t smallestradius = INT32_MAX;
|
||||
angle_t angletonext = ANGLE_MAX;
|
||||
INT32 disttonext = INT32_MAX;
|
||||
|
||||
waypoint_t *finishLine = K_GetFinishLineWaypoint();
|
||||
waypoint_t *wp = player->nextwaypoint;
|
||||
mobj_t *prevwpmobj = player->mo;
|
||||
|
||||
const boolean useshortcuts = K_BotCanTakeCut(player);
|
||||
const boolean huntbackwards = false;
|
||||
boolean pathfindsuccess = false;
|
||||
path_t pathtofinish = {0};
|
||||
|
||||
botprediction_t *predict = Z_Calloc(sizeof(botprediction_t), PU_STATIC, NULL);
|
||||
size_t i;
|
||||
|
||||
// Reduce distance left by your distance to the starting waypoint.
|
||||
// This prevents looking too far ahead if the closest waypoint is really far away.
|
||||
distanceleft -= P_AproxDistance(player->mo->x - wp->mobj->x, player->mo->y - wp->mobj->y) / FRACUNIT;
|
||||
// Init defaults in case of pathfind failure
|
||||
angletonext = R_PointToAngle2(prevwpmobj->x, prevwpmobj->y, wp->mobj->x, wp->mobj->y);
|
||||
disttonext = P_AproxDistance(prevwpmobj->x - wp->mobj->x, prevwpmobj->y - wp->mobj->y) / FRACUNIT;
|
||||
|
||||
// We don't want to look ahead at all, just go to the first waypoint.
|
||||
if (distanceleft <= 0)
|
||||
{
|
||||
predict->x = wp->mobj->x;
|
||||
predict->y = wp->mobj->y;
|
||||
predict->radius = wp->mobj->radius;
|
||||
return predict;
|
||||
}
|
||||
|
||||
angletonext = R_PointToAngle2(
|
||||
player->mo->x, player->mo->y,
|
||||
wp->mobj->x, wp->mobj->y
|
||||
pathfindsuccess = K_PathfindToWaypoint(
|
||||
player->nextwaypoint, finishLine,
|
||||
&pathtofinish,
|
||||
useshortcuts, huntbackwards
|
||||
);
|
||||
|
||||
// Go through waypoints until we've traveled the distance we wanted to predict ahead!
|
||||
while (distanceleft > 0)
|
||||
// Go through the waypoints until we've traveled the distance we wanted to predict ahead!
|
||||
if (pathfindsuccess == true)
|
||||
{
|
||||
INT32 disttonext = INT32_MAX;
|
||||
|
||||
if (wp->mobj->radius < smallestradius)
|
||||
for (i = 0; i < pathtofinish.numnodes; i++)
|
||||
{
|
||||
smallestradius = wp->mobj->radius;
|
||||
}
|
||||
wp = (waypoint_t *)pathtofinish.array[i].nodedata;
|
||||
|
||||
if (wp->numnextwaypoints == 0)
|
||||
{
|
||||
// Well, this is where I get off.
|
||||
distanceleft = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
// Calculate nextwaypoints index to use
|
||||
// nextwaypoints[0] by default
|
||||
nwp = 0;
|
||||
|
||||
// There are multiple nextwaypoints,
|
||||
// so we need to find the most convenient one to us.
|
||||
// Let's compare the angle to the player's!
|
||||
if (wp->numnextwaypoints > 1)
|
||||
{
|
||||
angle_t delta = ANGLE_MAX;
|
||||
angle_t a = ANGLE_MAX;
|
||||
|
||||
for (i = 0; i < wp->numnextwaypoints; i++)
|
||||
if (i == 0)
|
||||
{
|
||||
if (K_GetWaypointIsEnabled(wp->nextwaypoints[i]) == false)
|
||||
prevwpmobj = player->mo;
|
||||
}
|
||||
else
|
||||
{
|
||||
prevwpmobj = ((waypoint_t *)pathtofinish.array[ i - 1 ].nodedata)->mobj;
|
||||
}
|
||||
|
||||
angletonext = R_PointToAngle2(prevwpmobj->x, prevwpmobj->y, wp->mobj->x, wp->mobj->y);
|
||||
disttonext = P_AproxDistance(prevwpmobj->x - wp->mobj->x, prevwpmobj->y - wp->mobj->y) / FRACUNIT;
|
||||
|
||||
if (P_TraceBotTraversal(player->mo, wp->mobj) == false)
|
||||
{
|
||||
// If we can't get a direct path to this waypoint, predict less.
|
||||
distanceleft -= disttonext;
|
||||
radreduce = FRACUNIT >> 1;
|
||||
}
|
||||
|
||||
if (wp->mobj->radius < smallestradius)
|
||||
{
|
||||
smallestradius = wp->mobj->radius;
|
||||
}
|
||||
|
||||
distanceleft -= disttonext;
|
||||
|
||||
if (distanceleft <= 0)
|
||||
{
|
||||
// We're done!!
|
||||
break;
|
||||
}
|
||||
|
||||
if (i == pathtofinish.numnodes-1 && disttonext > 0)
|
||||
{
|
||||
// We were pathfinding to the finish, but we want to go past it.
|
||||
// Set up a new pathfind.
|
||||
|
||||
waypoint_t *next = NULL;
|
||||
|
||||
if (finishLine->numnextwaypoints == 0)
|
||||
{
|
||||
continue;
|
||||
distanceleft = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
if (K_GetWaypointIsShortcut(wp->nextwaypoints[i]) == true && K_BotCanTakeCut(player) == false)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
// default to first one
|
||||
next = wp->nextwaypoints[0];
|
||||
|
||||
// Unlike the other parts of this function, we're comparing the player's physical position, NOT the position of the waypoint!!
|
||||
// This should roughly correspond with how players will think about path splits.
|
||||
a = R_PointToAngle2(
|
||||
player->mo->x, player->mo->y,
|
||||
wp->nextwaypoints[i]->mobj->x, wp->nextwaypoints[i]->mobj->y
|
||||
pathfindsuccess = K_PathfindToWaypoint(
|
||||
next, finishLine,
|
||||
&pathtofinish,
|
||||
useshortcuts, huntbackwards
|
||||
);
|
||||
if (a > ANGLE_180)
|
||||
{
|
||||
a = InvAngle(a);
|
||||
}
|
||||
|
||||
a = player->mo->angle - a;
|
||||
|
||||
if (a < delta)
|
||||
if (pathfindsuccess == false)
|
||||
{
|
||||
nwp = i;
|
||||
delta = a;
|
||||
distanceleft = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
angletonext = R_PointToAngle2(
|
||||
wp->mobj->x, wp->mobj->y,
|
||||
wp->nextwaypoints[nwp]->mobj->x, wp->nextwaypoints[nwp]->mobj->y
|
||||
);
|
||||
|
||||
disttonext = (INT32)wp->nextwaypointdistances[nwp];
|
||||
|
||||
if (P_TraceBotTraversal(player->mo, wp->nextwaypoints[nwp]->mobj) == false)
|
||||
{
|
||||
// If we can't get a direct path to this waypoint, we don't want to check much further...
|
||||
disttonext *= 2;
|
||||
radreduce = FRACUNIT/2;
|
||||
}
|
||||
|
||||
if (disttonext > distanceleft)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
distanceleft -= disttonext;
|
||||
|
||||
wp = wp->nextwaypoints[nwp];
|
||||
Z_Free(pathtofinish.array);
|
||||
}
|
||||
|
||||
// Set our predicted point's coordinates,
|
||||
|
|
@ -777,10 +764,11 @@ static botprediction_t *K_CreateBotPrediction(player_t *player)
|
|||
if (distanceleft > 0)
|
||||
{
|
||||
// Scaled with the leftover anglemul!
|
||||
predict->x += P_ReturnThrustX(NULL, angletonext, distanceleft * FRACUNIT);
|
||||
predict->y += P_ReturnThrustY(NULL, angletonext, distanceleft * FRACUNIT);
|
||||
predict->x += P_ReturnThrustX(NULL, angletonext, min(disttonext, distanceleft) * FRACUNIT);
|
||||
predict->y += P_ReturnThrustY(NULL, angletonext, min(disttonext, distanceleft) * FRACUNIT);
|
||||
}
|
||||
|
||||
ps_bots[player - players].prediction += I_GetPreciseTime() - time;
|
||||
return predict;
|
||||
}
|
||||
|
||||
|
|
@ -804,9 +792,11 @@ static UINT8 K_TrySpindash(player_t *player)
|
|||
const fixed_t baseAccel = K_GetNewSpeed(player) - oldSpeed;
|
||||
const fixed_t speedDiff = player->speed - player->lastspeed;
|
||||
|
||||
if (player->spindashboost || player->tiregrease)
|
||||
const INT32 angleDiff = AngleDelta(player->mo->angle, K_MomentumAngle(player->mo));
|
||||
|
||||
if (player->spindashboost || player->tiregrease // You just released a spindash, you don't need to try again yet, jeez.
|
||||
|| P_PlayerInPain(player) || !P_IsObjectOnGround(player->mo)) // Not in a state where we want 'em to spindash.
|
||||
{
|
||||
// You just released a spindash, you don't need to try again yet, jeez.
|
||||
player->botvars.spindashconfirm = 0;
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -837,36 +827,13 @@ static UINT8 K_TrySpindash(player_t *player)
|
|||
}
|
||||
}
|
||||
|
||||
// Logic for normal racing.
|
||||
if (player->flashing > 0)
|
||||
{
|
||||
// Don't bother trying to spindash.
|
||||
// Trying to spindash while flashing is fine during POSITION, but not during the actual race.
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (speedDiff < (baseAccel / 4))
|
||||
{
|
||||
if (player->botvars.spindashconfirm < BOTSPINDASHCONFIRM)
|
||||
{
|
||||
player->botvars.spindashconfirm++;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (player->botvars.spindashconfirm > 0)
|
||||
{
|
||||
player->botvars.spindashconfirm--;
|
||||
}
|
||||
}
|
||||
|
||||
if (player->botvars.spindashconfirm >= BOTSPINDASHCONFIRM)
|
||||
{
|
||||
INT32 chargingPoint = (K_GetSpindashChargeTime(player) + difficultyModifier);
|
||||
|
||||
// Release quicker the higher the difficulty is.
|
||||
// Sounds counter-productive, but that's actually the best strategy after the race has started.
|
||||
chargingPoint -= player->botvars.difficulty * difficultyModifier;
|
||||
chargingPoint -= min(DIFFICULTBOT, player->botvars.difficulty) * difficultyModifier;
|
||||
|
||||
if (player->spindash > chargingPoint)
|
||||
{
|
||||
|
|
@ -876,6 +843,25 @@ static UINT8 K_TrySpindash(player_t *player)
|
|||
|
||||
return 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Logic for normal racing.
|
||||
if (speedDiff < (baseAccel / 8) // Moving too slowly
|
||||
|| angleDiff > ANG60) // Being pushed backwards
|
||||
{
|
||||
if (player->botvars.spindashconfirm < BOTSPINDASHCONFIRM)
|
||||
{
|
||||
player->botvars.spindashconfirm++;
|
||||
}
|
||||
}
|
||||
else if (player->botvars.spindashconfirm >= BOTSPINDASHCONFIRM)
|
||||
{
|
||||
if (player->botvars.spindashconfirm > 0)
|
||||
{
|
||||
player->botvars.spindashconfirm--;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// We're doing just fine, we don't need to spindash, thanks.
|
||||
return 0;
|
||||
|
|
@ -1007,29 +993,27 @@ static INT32 K_HandleBotTrack(player_t *player, ticcmd_t *cmd, botprediction_t *
|
|||
// Handle steering towards waypoints!
|
||||
INT32 turnamt = 0;
|
||||
SINT8 turnsign = 0;
|
||||
angle_t moveangle, angle;
|
||||
INT16 anglediff;
|
||||
angle_t moveangle;
|
||||
INT32 anglediff;
|
||||
|
||||
I_Assert(predict != NULL);
|
||||
|
||||
moveangle = player->mo->angle;
|
||||
angle = (moveangle - destangle);
|
||||
anglediff = AngleDeltaSigned(moveangle, destangle);
|
||||
|
||||
if (angle < ANGLE_180)
|
||||
if (anglediff < 0)
|
||||
{
|
||||
turnsign = -1; // Turn right
|
||||
anglediff = AngleFixed(angle)>>FRACBITS;
|
||||
turnsign = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
turnsign = 1; // Turn left
|
||||
anglediff = 360-(AngleFixed(angle)>>FRACBITS);
|
||||
turnsign = -1;
|
||||
}
|
||||
|
||||
anglediff = abs(anglediff);
|
||||
turnamt = KART_FULLTURN * turnsign;
|
||||
|
||||
if (anglediff > 90)
|
||||
if (anglediff > ANGLE_90)
|
||||
{
|
||||
// Wrong way!
|
||||
cmd->forwardmove = -MAXPLMOVE;
|
||||
|
|
@ -1038,7 +1022,7 @@ static INT32 K_HandleBotTrack(player_t *player, ticcmd_t *cmd, botprediction_t *
|
|||
else
|
||||
{
|
||||
const fixed_t playerwidth = (player->mo->radius * 2);
|
||||
fixed_t realrad = predict->radius - (playerwidth * 4); // Remove a "safe" distance away from the edges of the road
|
||||
fixed_t realrad = predict->radius*3/4; // Remove a "safe" distance away from the edges of the road
|
||||
fixed_t rad = realrad;
|
||||
fixed_t dirdist = K_DistanceOfLineFromPoint(
|
||||
player->mo->x, player->mo->y,
|
||||
|
|
@ -1046,19 +1030,26 @@ static INT32 K_HandleBotTrack(player_t *player, ticcmd_t *cmd, botprediction_t *
|
|||
predict->x, predict->y
|
||||
);
|
||||
|
||||
if (realrad < player->mo->radius)
|
||||
if (realrad < playerwidth)
|
||||
{
|
||||
realrad = player->mo->radius;
|
||||
realrad = playerwidth;
|
||||
}
|
||||
|
||||
if (anglediff > 0)
|
||||
{
|
||||
// Become more precise based on how hard you need to turn
|
||||
// This makes predictions into turns a little nicer
|
||||
// Facing 90 degrees away from the predicted point gives you a 1/3 radius
|
||||
rad = FixedMul(rad, ((135 - anglediff) * FRACUNIT) / 135);
|
||||
}
|
||||
// Become more precise based on how hard you need to turn
|
||||
// This makes predictions into turns a little nicer
|
||||
// Facing 90 degrees away from the predicted point gives you 0 radius
|
||||
rad = FixedMul(rad,
|
||||
FixedDiv(max(0, ANGLE_90 - anglediff), ANGLE_90)
|
||||
);
|
||||
|
||||
// Become more precise the slower you're moving
|
||||
// Also helps with turns
|
||||
// Full speed uses full radius
|
||||
rad = FixedMul(rad,
|
||||
FixedDiv(K_BotSpeedScaled(player, player->speed), K_GetKartSpeed(player, false, false))
|
||||
);
|
||||
|
||||
// Cap the radius to reasonable bounds
|
||||
if (rad > realrad)
|
||||
{
|
||||
rad = realrad;
|
||||
|
|
@ -1068,36 +1059,14 @@ static INT32 K_HandleBotTrack(player_t *player, ticcmd_t *cmd, botprediction_t *
|
|||
rad = playerwidth;
|
||||
}
|
||||
|
||||
cmd->buttons |= BT_ACCELERATE;
|
||||
|
||||
// Full speed ahead!
|
||||
cmd->buttons |= BT_ACCELERATE;
|
||||
cmd->forwardmove = MAXPLMOVE;
|
||||
|
||||
if (dirdist <= rad)
|
||||
{
|
||||
fixed_t speedmul = FixedDiv(K_BotSpeedScaled(player, player->speed), K_GetKartSpeed(player, false, false));
|
||||
fixed_t speedrad = rad/4;
|
||||
|
||||
if (speedmul > FRACUNIT)
|
||||
{
|
||||
speedmul = FRACUNIT;
|
||||
}
|
||||
|
||||
// Increase radius with speed
|
||||
// At low speed, the CPU will try to be more accurate
|
||||
// At high speed, they're more likely to lawnmower
|
||||
speedrad += FixedMul(speedmul, rad - speedrad);
|
||||
|
||||
if (speedrad < playerwidth)
|
||||
{
|
||||
speedrad = playerwidth;
|
||||
}
|
||||
|
||||
if (dirdist <= speedrad)
|
||||
{
|
||||
// Don't turn at all
|
||||
turnamt = 0;
|
||||
}
|
||||
// Going the right way, don't turn at all.
|
||||
turnamt = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1254,6 +1223,7 @@ static INT32 K_HandleBotReverse(player_t *player, ticcmd_t *cmd, botprediction_t
|
|||
--------------------------------------------------*/
|
||||
void K_BuildBotTiccmd(player_t *player, ticcmd_t *cmd)
|
||||
{
|
||||
precise_t t = 0;
|
||||
botprediction_t *predict = NULL;
|
||||
boolean trySpindash = true;
|
||||
angle_t destangle = 0;
|
||||
|
|
@ -1328,7 +1298,7 @@ void K_BuildBotTiccmd(player_t *player, ticcmd_t *cmd)
|
|||
|
||||
if (botController != NULL && (botController->flags & ML_EFFECT1))
|
||||
{
|
||||
const fixed_t dist = (player->mo->radius * 4);
|
||||
const fixed_t dist = DEFAULT_WAYPOINT_RADIUS * player->mo->scale;
|
||||
|
||||
// X Offset: Movement direction
|
||||
destangle = FixedAngle(sides[botController->sidenum[0]].textureoffset);
|
||||
|
|
@ -1474,7 +1444,9 @@ void K_BuildBotTiccmd(player_t *player, ticcmd_t *cmd)
|
|||
{
|
||||
// Don't pointlessly try to use rings/sneakers while charging a spindash.
|
||||
// TODO: Allowing projectile items like orbinaut while e-braking would be nice, maybe just pass in the spindash variable?
|
||||
t = I_GetPreciseTime();
|
||||
K_BotItemUsage(player, cmd, turnamt);
|
||||
ps_bots[player - players].item = I_GetPreciseTime() - t;
|
||||
}
|
||||
|
||||
if (turnamt != 0)
|
||||
|
|
|
|||
|
|
@ -28,7 +28,7 @@
|
|||
#define BOTTURNCONFIRM 4
|
||||
|
||||
// How many tics without being able to accelerate before we'll let you spindash.
|
||||
#define BOTSPINDASHCONFIRM (TICRATE/4)
|
||||
#define BOTSPINDASHCONFIRM (2*TICRATE)
|
||||
|
||||
// Point for bots to aim for
|
||||
typedef struct botprediction_s {
|
||||
|
|
|
|||
|
|
@ -27,6 +27,7 @@
|
|||
#include "m_random.h"
|
||||
#include "r_things.h" // numskins
|
||||
#include "p_slopes.h" // P_GetZAt
|
||||
#include "m_perfstats.h"
|
||||
|
||||
struct globalsmuggle
|
||||
{
|
||||
|
|
@ -172,26 +173,24 @@ static boolean K_BotHatesThisSectorsSpecial(player_t *player, sector_t *sec)
|
|||
boolean K_BotHatesThisSector(player_t *player, sector_t *sec, fixed_t x, fixed_t y)
|
||||
{
|
||||
const boolean flip = (player->mo->eflags & MFE_VERTICALFLIP);
|
||||
INT32 specialflag = 0;
|
||||
fixed_t highestfloor = INT32_MAX;
|
||||
sector_t *bestsector = NULL;
|
||||
ffloor_t *rover;
|
||||
|
||||
// TODO: Properly support SF_FLIPSPECIAL_FLOOR / SF_FLIPSPECIAL_CEILING.
|
||||
// An earlier attempt at it caused lots of false positives and other weird
|
||||
// quirks with intangible FOFs.
|
||||
|
||||
if (flip == true)
|
||||
{
|
||||
specialflag = SF_FLIPSPECIAL_CEILING;
|
||||
highestfloor = P_GetZAt(sec->c_slope, x, y, sec->ceilingheight);
|
||||
}
|
||||
else
|
||||
{
|
||||
specialflag = SF_FLIPSPECIAL_FLOOR;
|
||||
highestfloor = P_GetZAt(sec->f_slope, x, y, sec->floorheight);
|
||||
}
|
||||
|
||||
if (sec->flags & specialflag)
|
||||
{
|
||||
bestsector = sec;
|
||||
}
|
||||
bestsector = sec;
|
||||
|
||||
for (rover = sec->ffloors; rover; rover = rover->next)
|
||||
{
|
||||
|
|
@ -209,15 +208,13 @@ boolean K_BotHatesThisSector(player_t *player, sector_t *sec, fixed_t x, fixed_t
|
|||
if (!(rover->flags & FF_BLOCKPLAYER))
|
||||
{
|
||||
if ((top >= player->mo->z) && (bottom <= player->mo->z + player->mo->height)
|
||||
&& K_BotHatesThisSectorsSpecial(player, rover->master->frontsector))
|
||||
&& K_BotHatesThisSectorsSpecial(player, rover->master->frontsector))
|
||||
{
|
||||
// Bad intangible sector at our height, so we DEFINITELY want to avoid
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
if ((rover->flags & FF_BLOCKPLAYER) && !(rover->master->frontsector->flags & specialflag))
|
||||
{
|
||||
// Ignore them, we want the one below it.
|
||||
continue;
|
||||
}
|
||||
|
||||
|
|
@ -225,7 +222,7 @@ boolean K_BotHatesThisSector(player_t *player, sector_t *sec, fixed_t x, fixed_t
|
|||
if (flip == true)
|
||||
{
|
||||
if (bottom < highestfloor
|
||||
&& bottom >= player->mo->z + player->mo->height)
|
||||
&& bottom >= player->mo->z + player->mo->height)
|
||||
{
|
||||
bestsector = rover->master->frontsector;
|
||||
highestfloor = bottom;
|
||||
|
|
@ -234,7 +231,7 @@ boolean K_BotHatesThisSector(player_t *player, sector_t *sec, fixed_t x, fixed_t
|
|||
else
|
||||
{
|
||||
if (top > highestfloor
|
||||
&& top <= player->mo->z)
|
||||
&& top <= player->mo->z)
|
||||
{
|
||||
bestsector = rover->master->frontsector;
|
||||
highestfloor = top;
|
||||
|
|
@ -617,6 +614,8 @@ static BlockItReturn_t K_FindObjectsForNudging(mobj_t *thing)
|
|||
--------------------------------------------------*/
|
||||
void K_NudgePredictionTowardsObjects(botprediction_t *predict, player_t *player)
|
||||
{
|
||||
const precise_t time = I_GetPreciseTime();
|
||||
|
||||
INT32 xl, xh, yl, yh, bx, by;
|
||||
|
||||
fixed_t distToPredict = R_PointToDist2(player->mo->x, player->mo->y, predict->x, predict->y);
|
||||
|
|
@ -731,7 +730,7 @@ void K_NudgePredictionTowardsObjects(botprediction_t *predict, player_t *player)
|
|||
// Check if our side is invalid, if so, don't do the code below.
|
||||
if (gotoSide != -1 && globalsmuggle.gotoObjs[gotoSide] == 0)
|
||||
{
|
||||
// Do not use a side
|
||||
// Do not use a side
|
||||
gotoSide = -1;
|
||||
}
|
||||
|
||||
|
|
@ -773,6 +772,8 @@ void K_NudgePredictionTowardsObjects(botprediction_t *predict, player_t *player)
|
|||
//distToPredict = R_PointToDist2(player->mo->x, player->mo->y, predict->x, predict->y);
|
||||
}
|
||||
}
|
||||
|
||||
ps_bots[player - players].nudge += I_GetPreciseTime() - time;
|
||||
}
|
||||
|
||||
/*--------------------------------------------------
|
||||
|
|
|
|||
|
|
@ -639,7 +639,7 @@ void K_RetireBots(void)
|
|||
--------------------------------------------------*/
|
||||
void K_FakeBotResults(player_t *bot)
|
||||
{
|
||||
const UINT32 distfactor = FixedMul(32 * bot->mo->scale, K_GetKartGameSpeedScalar(gamespeed)) / FRACUNIT;
|
||||
const UINT32 distfactor = FixedMul(32 * mapobjectscale, K_GetKartGameSpeedScalar(gamespeed)) / FRACUNIT;
|
||||
UINT32 worstdist = 0;
|
||||
tic_t besttime = UINT32_MAX;
|
||||
UINT8 numplayers = 0;
|
||||
|
|
|
|||
182
src/k_kart.c
182
src/k_kart.c
|
|
@ -2944,23 +2944,32 @@ boolean K_SlopeResistance(player_t *player)
|
|||
return false;
|
||||
}
|
||||
|
||||
boolean K_TripwirePassConditions(player_t *player)
|
||||
tripwirepass_t K_TripwirePassConditions(player_t *player)
|
||||
{
|
||||
if (
|
||||
player->invincibilitytimer ||
|
||||
player->sneakertimer ||
|
||||
player->growshrinktimer > 0 ||
|
||||
player->sneakertimer
|
||||
)
|
||||
return TRIPWIRE_BLASTER;
|
||||
|
||||
if (
|
||||
player->flamedash ||
|
||||
player->hyudorotimer ||
|
||||
player->speed > 2 * K_GetKartSpeed(player, false, true)
|
||||
)
|
||||
return true;
|
||||
return false;
|
||||
return TRIPWIRE_BOOST;
|
||||
|
||||
if (
|
||||
player->growshrinktimer > 0 ||
|
||||
player->hyudorotimer
|
||||
)
|
||||
return TRIPWIRE_IGNORE;
|
||||
|
||||
return TRIPWIRE_NONE;
|
||||
}
|
||||
|
||||
boolean K_TripwirePass(player_t *player)
|
||||
{
|
||||
return (K_TripwirePassConditions(player) || (player->tripwireLeniency > 0));
|
||||
return (player->tripwirePass != TRIPWIRE_NONE);
|
||||
}
|
||||
|
||||
boolean K_WaterRun(player_t *player)
|
||||
|
|
@ -3667,7 +3676,7 @@ void K_TumblePlayer(player_t *player, mobj_t *inflictor, mobj_t *source)
|
|||
|
||||
player->tumbleBounces = 1;
|
||||
|
||||
if (player->tripWireState == TRIP_PASSED)
|
||||
if (player->tripwireState == TRIPSTATE_PASSED)
|
||||
{
|
||||
player->tumbleHeight = 50;
|
||||
}
|
||||
|
|
@ -3781,15 +3790,15 @@ void K_TumbleInterrupt(player_t *player)
|
|||
|
||||
void K_ApplyTripWire(player_t *player, tripwirestate_t state)
|
||||
{
|
||||
if (state == TRIP_PASSED)
|
||||
if (state == TRIPSTATE_PASSED)
|
||||
S_StartSound(player->mo, sfx_ssa015);
|
||||
else if (state == TRIP_BLOCKED)
|
||||
else if (state == TRIPSTATE_BLOCKED)
|
||||
S_StartSound(player->mo, sfx_kc40);
|
||||
|
||||
player->tripWireState = state;
|
||||
player->tripwireState = state;
|
||||
K_AddHitLag(player->mo, 10, false);
|
||||
|
||||
if (state == TRIP_PASSED && player->spinouttimer &&
|
||||
if (state == TRIPSTATE_PASSED && player->spinouttimer &&
|
||||
player->speed > 2 * K_GetKartSpeed(player, false, true))
|
||||
{
|
||||
K_TumblePlayer(player, NULL, NULL);
|
||||
|
|
@ -4939,90 +4948,6 @@ void K_DriftDustHandling(mobj_t *spawner)
|
|||
}
|
||||
}
|
||||
|
||||
static void K_SpawnTripwireVFX(mobj_t *mo)
|
||||
{
|
||||
tic_t t = leveltime;
|
||||
angle_t ang, aoff;
|
||||
SINT8 sign = 1;
|
||||
boolean altColor = false;
|
||||
mobj_t *dust;
|
||||
boolean drifting = false;
|
||||
UINT8 i;
|
||||
|
||||
I_Assert(mo != NULL);
|
||||
I_Assert(!P_MobjWasRemoved(mo));
|
||||
|
||||
if (!P_IsObjectOnGround(mo))
|
||||
return;
|
||||
|
||||
if (mo->player)
|
||||
{
|
||||
ang = mo->player->drawangle;
|
||||
|
||||
if (mo->player->drift != 0)
|
||||
{
|
||||
drifting = true;
|
||||
ang += (mo->player->drift * ((ANGLE_270 + ANGLE_22h) / 5)); // -112.5 doesn't work. I fucking HATE SRB2 angles
|
||||
if (mo->player->drift < 0)
|
||||
sign = 1;
|
||||
else
|
||||
sign = -1;
|
||||
}
|
||||
}
|
||||
else
|
||||
ang = mo->angle;
|
||||
|
||||
if (drifting == false)
|
||||
{
|
||||
i = (t & 1);
|
||||
|
||||
if (i & 1)
|
||||
sign = -1;
|
||||
else
|
||||
sign = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (t & 1)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
t /= 2;
|
||||
i = (t & 1);
|
||||
}
|
||||
|
||||
aoff = (ang + ANGLE_180) + (ANGLE_45 * sign);
|
||||
|
||||
dust = P_SpawnMobj(mo->x + FixedMul(24*mo->scale, FINECOSINE(aoff>>ANGLETOFINESHIFT)),
|
||||
mo->y + FixedMul(24*mo->scale, FINESINE(aoff>>ANGLETOFINESHIFT)),
|
||||
mo->z, MT_DRIFTDUST);
|
||||
|
||||
P_SetTarget(&dust->target, mo);
|
||||
P_InitAngle(dust, ang - (ANGLE_90 * sign)); // point completely perpendicular from the player
|
||||
P_SetScale(dust, mo->scale);
|
||||
dust->destscale = mo->scale * 6;
|
||||
dust->scalespeed = mo->scale/12;
|
||||
K_FlipFromObject(dust, mo);
|
||||
|
||||
altColor = (sign > 0);
|
||||
|
||||
if ((t / 2) & 1)
|
||||
{
|
||||
dust->tics++; // "randomize" animation
|
||||
altColor = !altColor;
|
||||
}
|
||||
|
||||
dust->colorized = true;
|
||||
dust->color = altColor ? SKINCOLOR_BLOSSOM : SKINCOLOR_JAWZ;
|
||||
|
||||
dust->momx = (4*mo->momx)/5;
|
||||
dust->momy = (4*mo->momy)/5;
|
||||
dust->momz = (4*P_GetMobjZMovement(mo))/5;
|
||||
|
||||
P_Thrust(dust, dust->angle, 4*mo->scale);
|
||||
}
|
||||
|
||||
void K_Squish(mobj_t *mo)
|
||||
{
|
||||
const fixed_t maxstretch = 4*FRACUNIT;
|
||||
|
|
@ -7289,6 +7214,52 @@ static void K_LookForRings(mobj_t *pmo)
|
|||
P_BlockThingsIterator(bx, by, PIT_AttractingRings);
|
||||
}
|
||||
|
||||
static void K_UpdateTripwire(player_t *player)
|
||||
{
|
||||
fixed_t speedThreshold = (3*K_GetKartSpeed(player, false, true))/4;
|
||||
boolean goodSpeed = (player->speed >= speedThreshold);
|
||||
boolean boostExists = (player->tripwireLeniency > 0); // can't be checked later because of subtractions...
|
||||
tripwirepass_t triplevel = K_TripwirePassConditions(player);
|
||||
|
||||
if (triplevel != TRIPWIRE_NONE)
|
||||
{
|
||||
if (!boostExists)
|
||||
{
|
||||
mobj_t *front = P_SpawnMobjFromMobj(player->mo, 0, 0, 0, MT_TRIPWIREBOOST);
|
||||
mobj_t *back = P_SpawnMobjFromMobj(player->mo, 0, 0, 0, MT_TRIPWIREBOOST);
|
||||
|
||||
P_SetTarget(&front->target, player->mo);
|
||||
P_SetTarget(&back->target, player->mo);
|
||||
|
||||
front->dispoffset = 1;
|
||||
front->old_angle = back->old_angle = K_MomentumAngle(player->mo);
|
||||
back->dispoffset = -1;
|
||||
back->extravalue1 = 1;
|
||||
P_SetMobjState(back, S_TRIPWIREBOOST_BOTTOM);
|
||||
}
|
||||
|
||||
player->tripwirePass = triplevel;
|
||||
player->tripwireLeniency = max(player->tripwireLeniency, TRIPWIRETIME);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (boostExists)
|
||||
{
|
||||
player->tripwireLeniency--;
|
||||
if (goodSpeed == false && player->tripwireLeniency > 0)
|
||||
{
|
||||
// Decrease at double speed when your speed is bad.
|
||||
player->tripwireLeniency--;
|
||||
}
|
||||
}
|
||||
|
||||
if (player->tripwireLeniency <= 0)
|
||||
{
|
||||
player->tripwirePass = TRIPWIRE_NONE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** \brief Decreases various kart timers and powers per frame. Called in P_PlayerThink in p_user.c
|
||||
|
||||
\param player player object passed from P_PlayerThink
|
||||
|
|
@ -7644,16 +7615,7 @@ void K_KartPlayerThink(player_t *player, ticcmd_t *cmd)
|
|||
K_HandleTumbleBounce(player);
|
||||
}
|
||||
|
||||
if (player->tripwireLeniency > 0)
|
||||
{
|
||||
player->tripwireLeniency--;
|
||||
K_SpawnTripwireVFX(player->mo);
|
||||
}
|
||||
|
||||
if (K_TripwirePassConditions(player) == true)
|
||||
{
|
||||
player->tripwireLeniency = max(player->tripwireLeniency, TICRATE);
|
||||
}
|
||||
K_UpdateTripwire(player);
|
||||
|
||||
K_KartPlayerHUDUpdate(player);
|
||||
|
||||
|
|
@ -7765,14 +7727,14 @@ void K_KartPlayerThink(player_t *player, ticcmd_t *cmd)
|
|||
// Handle invincibility sfx
|
||||
K_UpdateInvincibilitySounds(player); // Also thanks, VAda!
|
||||
|
||||
if (player->tripWireState != TRIP_NONE)
|
||||
if (player->tripwireState != TRIPSTATE_NONE)
|
||||
{
|
||||
if (player->tripWireState == TRIP_PASSED)
|
||||
if (player->tripwireState == TRIPSTATE_PASSED)
|
||||
S_StartSound(player->mo, sfx_cdfm63);
|
||||
else if (player->tripWireState == TRIP_BLOCKED)
|
||||
else if (player->tripwireState == TRIPSTATE_BLOCKED)
|
||||
S_StartSound(player->mo, sfx_kc4c);
|
||||
|
||||
player->tripWireState = TRIP_NONE;
|
||||
player->tripwireState = TRIPSTATE_NONE;
|
||||
}
|
||||
|
||||
K_KartEbrakeVisuals(player);
|
||||
|
|
|
|||
|
|
@ -121,7 +121,7 @@ void K_StripOther(player_t *player);
|
|||
void K_MomentumToFacing(player_t *player);
|
||||
boolean K_ApplyOffroad(player_t *player);
|
||||
boolean K_SlopeResistance(player_t *player);
|
||||
boolean K_TripwirePassConditions(player_t *player);
|
||||
tripwirepass_t K_TripwirePassConditions(player_t *player);
|
||||
boolean K_TripwirePass(player_t *player);
|
||||
boolean K_WaterRun(player_t *player);
|
||||
void K_ApplyTripWire(player_t *player, tripwirestate_t state);
|
||||
|
|
|
|||
|
|
@ -482,7 +482,7 @@ void LUAh_ThinkFrame(void)
|
|||
if (hookp->type != hook_ThinkFrame)
|
||||
continue;
|
||||
|
||||
if (cv_perfstats.value == 3)
|
||||
if (cv_perfstats.value == PS_THINKFRAME)
|
||||
time_taken = I_GetPreciseTime();
|
||||
PushHook(gL, hookp);
|
||||
if (lua_pcall(gL, 0, 0, 1)) {
|
||||
|
|
@ -491,7 +491,7 @@ void LUAh_ThinkFrame(void)
|
|||
lua_pop(gL, 1);
|
||||
hookp->error = true;
|
||||
}
|
||||
if (cv_perfstats.value == 3)
|
||||
if (cv_perfstats.value == PS_THINKFRAME)
|
||||
{
|
||||
lua_Debug ar;
|
||||
time_taken = I_GetPreciseTime() - time_taken;
|
||||
|
|
|
|||
|
|
@ -99,7 +99,8 @@ enum mobj_e {
|
|||
mobj_sprxoff,
|
||||
mobj_spryoff,
|
||||
mobj_sprzoff,
|
||||
mobj_hitlag
|
||||
mobj_hitlag,
|
||||
mobj_dispoffset
|
||||
};
|
||||
|
||||
static const char *const mobj_opt[] = {
|
||||
|
|
@ -180,6 +181,7 @@ static const char *const mobj_opt[] = {
|
|||
"spryoff",
|
||||
"sprzoff",
|
||||
"hitlag",
|
||||
"dispoffset",
|
||||
NULL};
|
||||
|
||||
#define UNIMPLEMENTED luaL_error(L, LUA_QL("mobj_t") " field " LUA_QS " is not implemented for Lua and cannot be accessed.", mobj_opt[field])
|
||||
|
|
@ -458,6 +460,9 @@ static int mobj_get(lua_State *L)
|
|||
case mobj_hitlag:
|
||||
lua_pushinteger(L, mo->hitlag);
|
||||
break;
|
||||
case mobj_dispoffset:
|
||||
lua_pushinteger(L, mo->dispoffset);
|
||||
break;
|
||||
default: // extra custom variables in Lua memory
|
||||
lua_getfield(L, LUA_REGISTRYINDEX, LREG_EXTVARS);
|
||||
I_Assert(lua_istable(L, -1));
|
||||
|
|
@ -830,6 +835,9 @@ static int mobj_set(lua_State *L)
|
|||
case mobj_hitlag:
|
||||
mo->hitlag = luaL_checkinteger(L, 3);
|
||||
break;
|
||||
case mobj_dispoffset:
|
||||
mo->dispoffset = luaL_checkinteger(L, 3);
|
||||
break;
|
||||
default:
|
||||
lua_getfield(L, LUA_REGISTRYINDEX, LREG_EXTVARS);
|
||||
I_Assert(lua_istable(L, -1));
|
||||
|
|
|
|||
|
|
@ -292,6 +292,10 @@ static int player_get(lua_State *L)
|
|||
lua_pushinteger(L, plr->draftleeway);
|
||||
else if (fastcmp(field,"lastdraft"))
|
||||
lua_pushinteger(L, plr->lastdraft);
|
||||
else if (fastcmp(field,"tripwireState"))
|
||||
lua_pushinteger(L, plr->tripwireState);
|
||||
else if (fastcmp(field,"tripwirePass"))
|
||||
lua_pushinteger(L, plr->tripwirePass);
|
||||
else if (fastcmp(field,"tripwireLeniency"))
|
||||
lua_pushinteger(L, plr->tripwireLeniency);
|
||||
else if (fastcmp(field,"itemroulette"))
|
||||
|
|
@ -646,6 +650,10 @@ static int player_set(lua_State *L)
|
|||
plr->draftleeway = luaL_checkinteger(L, 3);
|
||||
else if (fastcmp(field,"lastdraft"))
|
||||
plr->lastdraft = luaL_checkinteger(L, 3);
|
||||
else if (fastcmp(field,"tripwireState"))
|
||||
plr->tripwireState = luaL_checkinteger(L, 3);
|
||||
else if (fastcmp(field,"tripwirePass"))
|
||||
plr->tripwirePass = luaL_checkinteger(L, 3);
|
||||
else if (fastcmp(field,"tripwireLeniency"))
|
||||
plr->tripwireLeniency = luaL_checkinteger(L, 3);
|
||||
else if (fastcmp(field,"itemroulette"))
|
||||
|
|
|
|||
|
|
@ -18,6 +18,7 @@
|
|||
#include "i_time.h"
|
||||
#include "z_zone.h"
|
||||
#include "p_local.h"
|
||||
#include "g_game.h"
|
||||
|
||||
#ifdef HWRENDER
|
||||
#include "hardware/hw_main.h"
|
||||
|
|
@ -62,6 +63,8 @@ ps_hookinfo_t *thinkframe_hooks = NULL;
|
|||
int thinkframe_hooks_length = 0;
|
||||
int thinkframe_hooks_capacity = 16;
|
||||
|
||||
ps_botinfo_t ps_bots[MAXPLAYERS];
|
||||
|
||||
static INT32 draw_row;
|
||||
|
||||
void PS_SetThinkFrameHookInfo(int index, precise_t time_taken, char* short_src)
|
||||
|
|
@ -85,6 +88,12 @@ void PS_SetThinkFrameHookInfo(int index, precise_t time_taken, char* short_src)
|
|||
thinkframe_hooks_length = index + 1;
|
||||
}
|
||||
|
||||
void PS_ResetBotInfo(void)
|
||||
{
|
||||
memset(ps_bots, 0, sizeof(ps_bots));
|
||||
ps_botticcmd_time = 0;
|
||||
}
|
||||
|
||||
static void PS_SetFrameTime(void)
|
||||
{
|
||||
precise_t currenttime = I_GetPreciseTime();
|
||||
|
|
@ -486,15 +495,126 @@ void M_DrawPerfStats(void)
|
|||
|
||||
PS_SetFrameTime();
|
||||
|
||||
if (cv_perfstats.value == 1) // rendering
|
||||
if (cv_perfstats.value == PS_RENDER) // rendering
|
||||
{
|
||||
M_DrawRenderStats();
|
||||
}
|
||||
else if (cv_perfstats.value == 2) // logic
|
||||
else if (cv_perfstats.value == PS_LOGIC) // logic
|
||||
{
|
||||
M_DrawTickStats();
|
||||
}
|
||||
else if (cv_perfstats.value == 3) // lua thinkframe
|
||||
else if (cv_perfstats.value == PS_BOT) // bot ticcmd
|
||||
{
|
||||
if (vid.width < 640 || vid.height < 400) // low resolution
|
||||
{
|
||||
// it's not gonna fit very well..
|
||||
V_DrawThinString(30, 30, V_MONOSPACE | V_ALLOWLOWERCASE | V_YELLOWMAP, "Not available for resolutions below 640x400");
|
||||
}
|
||||
else // high resolution
|
||||
{
|
||||
precise_t otherTime = 0;
|
||||
int i;
|
||||
|
||||
// text writing position
|
||||
int x = 2;
|
||||
int y = 4;
|
||||
|
||||
for (i = 0; i < MAXPLAYERS; i++)
|
||||
{
|
||||
if (ps_bots[i].isBot == false)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
snprintf(s, sizeof s - 1, "Bot %d (%s):", i + 1, player_names[i]);
|
||||
V_DrawSmallString(x, y, V_MONOSPACE | V_ALLOWLOWERCASE | V_GRAYMAP, s);
|
||||
|
||||
snprintf(s, sizeof s - 1, "%ld", (long)((ps_bots[i].total) / (I_GetPrecisePrecision() / 1000000)));
|
||||
V_DrawRightAlignedSmallString(x + 98, y, V_MONOSPACE | V_ALLOWLOWERCASE | V_GRAYMAP, s);
|
||||
|
||||
y += 4; // repeated code!
|
||||
if (y > 192)
|
||||
{
|
||||
y = 4;
|
||||
x += 106;
|
||||
if (x > 214)
|
||||
break;
|
||||
}
|
||||
|
||||
snprintf(s, sizeof s - 1, "Prediction:");
|
||||
V_DrawSmallString(x, y, V_MONOSPACE | V_ALLOWLOWERCASE | V_YELLOWMAP, s);
|
||||
|
||||
snprintf(s, sizeof s - 1, "%ld", (long)((ps_bots[i].prediction) / (I_GetPrecisePrecision() / 1000000)));
|
||||
V_DrawRightAlignedSmallString(x + 98, y, V_MONOSPACE | V_ALLOWLOWERCASE, s);
|
||||
|
||||
y += 4; // repeated code!
|
||||
if (y > 192)
|
||||
{
|
||||
y = 4;
|
||||
x += 106;
|
||||
if (x > 214)
|
||||
break;
|
||||
}
|
||||
|
||||
snprintf(s, sizeof s - 1, "Nudge:");
|
||||
V_DrawSmallString(x, y, V_MONOSPACE | V_ALLOWLOWERCASE | V_YELLOWMAP, s);
|
||||
|
||||
snprintf(s, sizeof s - 1, "%ld", (long)((ps_bots[i].nudge) / (I_GetPrecisePrecision() / 1000000)));
|
||||
V_DrawRightAlignedSmallString(x + 98, y, V_MONOSPACE | V_ALLOWLOWERCASE, s);
|
||||
|
||||
y += 4; // repeated code!
|
||||
if (y > 192)
|
||||
{
|
||||
y = 4;
|
||||
x += 106;
|
||||
if (x > 214)
|
||||
break;
|
||||
}
|
||||
|
||||
snprintf(s, sizeof s - 1, "Item:");
|
||||
V_DrawSmallString(x, y, V_MONOSPACE | V_ALLOWLOWERCASE | V_YELLOWMAP, s);
|
||||
|
||||
snprintf(s, sizeof s - 1, "%ld", (long)((ps_bots[i].item) / (I_GetPrecisePrecision() / 1000000)));
|
||||
V_DrawRightAlignedSmallString(x + 98, y, V_MONOSPACE | V_ALLOWLOWERCASE, s);
|
||||
|
||||
y += 4; // repeated code!
|
||||
if (y > 192)
|
||||
{
|
||||
y = 4;
|
||||
x += 106;
|
||||
if (x > 214)
|
||||
break;
|
||||
}
|
||||
|
||||
snprintf(s, sizeof s - 1, "Other:");
|
||||
V_DrawSmallString(x, y, V_MONOSPACE | V_ALLOWLOWERCASE | V_YELLOWMAP, s);
|
||||
|
||||
otherTime = ps_bots[i].total - ps_bots[i].prediction - ps_bots[i].nudge - ps_bots[i].item;
|
||||
snprintf(s, sizeof s - 1, "%ld", (long)(otherTime / (I_GetPrecisePrecision() / 1000000)));
|
||||
V_DrawRightAlignedSmallString(x + 98, y, V_MONOSPACE | V_ALLOWLOWERCASE, s);
|
||||
|
||||
y += 4; // repeated code!
|
||||
if (y > 192)
|
||||
{
|
||||
y = 4;
|
||||
x += 106;
|
||||
if (x > 214)
|
||||
break;
|
||||
}
|
||||
|
||||
// add an extra space
|
||||
y += 4; // repeated code!
|
||||
if (y > 192)
|
||||
{
|
||||
y = 4;
|
||||
x += 106;
|
||||
if (x > 214)
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (cv_perfstats.value == PS_THINKFRAME) // lua thinkframe
|
||||
{
|
||||
if (!(gamestate == GS_LEVEL || (gamestate == GS_TITLESCREEN && titlemapinaction)))
|
||||
return;
|
||||
|
|
|
|||
|
|
@ -16,6 +16,15 @@
|
|||
#include "lua_script.h"
|
||||
#include "p_local.h"
|
||||
|
||||
typedef enum
|
||||
{
|
||||
PS_OFF = 0,
|
||||
PS_RENDER,
|
||||
PS_LOGIC,
|
||||
PS_BOT,
|
||||
PS_THINKFRAME,
|
||||
} ps_types_t;
|
||||
|
||||
extern precise_t ps_tictime;
|
||||
|
||||
extern precise_t ps_playerthink_time;
|
||||
|
|
@ -37,6 +46,19 @@ typedef struct
|
|||
|
||||
void PS_SetThinkFrameHookInfo(int index, precise_t time_taken, char* short_src);
|
||||
|
||||
typedef struct
|
||||
{
|
||||
boolean isBot;
|
||||
precise_t total;
|
||||
precise_t prediction; // K_CreateBotPrediction
|
||||
precise_t nudge; // K_NudgePredictionTowardsObjects
|
||||
precise_t item; // K_BotItemUsage
|
||||
} ps_botinfo_t;
|
||||
|
||||
extern ps_botinfo_t ps_bots[MAXPLAYERS];
|
||||
|
||||
void PS_ResetBotInfo(void);
|
||||
|
||||
void M_DrawPerfStats(void);
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -3801,7 +3801,7 @@ void P_BouncePlayerMove(mobj_t *mo)
|
|||
if (P_IsLineTripWire(bestslideline))
|
||||
{
|
||||
// TRIPWIRE CANNOT BE MADE NONBOUNCY
|
||||
K_ApplyTripWire(mo->player, TRIP_BLOCKED);
|
||||
K_ApplyTripWire(mo->player, TRIPSTATE_BLOCKED);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
|
|||
84
src/p_mobj.c
84
src/p_mobj.c
|
|
@ -7156,6 +7156,89 @@ static boolean P_MobjRegularThink(mobj_t *mobj)
|
|||
}
|
||||
}
|
||||
break;
|
||||
case MT_TRIPWIREBOOST:
|
||||
if (!mobj->target || !mobj->target->health
|
||||
|| !mobj->target->player || !mobj->target->player->tripwireLeniency)
|
||||
{
|
||||
P_RemoveMobj(mobj);
|
||||
return false;
|
||||
}
|
||||
|
||||
mobj->angle = K_MomentumAngle(mobj->target);
|
||||
P_MoveOrigin(mobj, mobj->target->x, mobj->target->y, mobj->target->z + (mobj->target->height >> 1));
|
||||
mobj->destscale = mobj->target->scale;
|
||||
P_SetScale(mobj, mobj->target->scale);
|
||||
|
||||
if (mobj->extravalue1)
|
||||
{
|
||||
mobj->angle += ANGLE_180;
|
||||
}
|
||||
|
||||
{
|
||||
fixed_t convSpeed = (mobj->target->player->speed * 100) / K_GetKartSpeed(mobj->target->player, false, true);
|
||||
UINT8 trans = ((mobj->target->player->tripwireLeniency + 1) * (NUMTRANSMAPS+1)) / TRIPWIRETIME;
|
||||
|
||||
if (trans > NUMTRANSMAPS)
|
||||
trans = NUMTRANSMAPS;
|
||||
|
||||
trans = NUMTRANSMAPS - trans;
|
||||
|
||||
if ((trans >= NUMTRANSMAPS) // not a valid visibility
|
||||
|| (convSpeed < 150 && (leveltime & 1)) // < 150% flickering
|
||||
|| (mobj->target->player->tripwirePass < TRIPWIRE_BOOST) // Not strong enough to make an aura
|
||||
|| mobj->target->player->flamedash) // Flameshield dash
|
||||
{
|
||||
mobj->renderflags |= RF_DONTDRAW;
|
||||
}
|
||||
else
|
||||
{
|
||||
boolean blastermode = (convSpeed >= 200) && (mobj->target->player->tripwirePass >= TRIPWIRE_BLASTER);
|
||||
|
||||
mobj->renderflags &= ~(RF_TRANSMASK|RF_DONTDRAW);
|
||||
if (trans != 0)
|
||||
{
|
||||
mobj->renderflags |= (trans << RF_TRANSSHIFT);
|
||||
}
|
||||
mobj->renderflags |= (mobj->target->renderflags & RF_DONTDRAW);
|
||||
|
||||
if (mobj->target->player->invincibilitytimer > 0)
|
||||
{
|
||||
if (mobj->target->player->invincibilitytimer > itemtime+(2*TICRATE))
|
||||
{
|
||||
mobj->color = K_RainbowColor(leveltime / 2);
|
||||
}
|
||||
else
|
||||
{
|
||||
mobj->color = SKINCOLOR_INVINCFLASH;
|
||||
}
|
||||
mobj->colorized = true;
|
||||
}
|
||||
else if (mobj->target->player->curshield == KSHIELD_FLAME)
|
||||
{
|
||||
mobj->color = SKINCOLOR_KETCHUP;
|
||||
mobj->colorized = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
mobj->color = SKINCOLOR_NONE;
|
||||
mobj->colorized = false;
|
||||
}
|
||||
|
||||
if (blastermode == !(mobj->flags2 & MF2_AMBUSH))
|
||||
{
|
||||
mobj->flags2 ^= MF2_AMBUSH;
|
||||
if (blastermode)
|
||||
{
|
||||
P_SetMobjState(mobj, (mobj->extravalue1) ? S_TRIPWIREBOOST_BLAST_BOTTOM : S_TRIPWIREBOOST_BLAST_TOP);
|
||||
}
|
||||
else
|
||||
{
|
||||
P_SetMobjState(mobj, (mobj->extravalue1) ? S_TRIPWIREBOOST_BOTTOM : S_TRIPWIREBOOST_TOP);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
case MT_BOOSTFLAME:
|
||||
if (!mobj->target || !mobj->target->health)
|
||||
{
|
||||
|
|
@ -9834,6 +9917,7 @@ mobj_t *P_SpawnMobj(fixed_t x, fixed_t y, fixed_t z, mobjtype_t type)
|
|||
// Sprite rendering
|
||||
mobj->spritexscale = mobj->spriteyscale = mobj->scale;
|
||||
mobj->spritexoffset = mobj->spriteyoffset = 0;
|
||||
mobj->dispoffset = info->dispoffset;
|
||||
mobj->floorspriteslope = NULL;
|
||||
|
||||
// set subsector and/or block links
|
||||
|
|
|
|||
|
|
@ -408,6 +408,8 @@ typedef struct mobj_s
|
|||
struct terrain_s *terrain; // Terrain definition of the floor this object last hit. NULL when in the air.
|
||||
INT32 hitlag; // Sal-style hit lag, straight from Captain Fetch's jowls
|
||||
|
||||
INT32 dispoffset;
|
||||
|
||||
// WARNING: New fields must be added separately to savegame and Lua.
|
||||
} mobj_t;
|
||||
|
||||
|
|
|
|||
|
|
@ -291,6 +291,8 @@ static void P_NetArchivePlayers(void)
|
|||
WRITEUINT16(save_p, players[i].draftleeway);
|
||||
WRITESINT8(save_p, players[i].lastdraft);
|
||||
|
||||
WRITEUINT8(save_p, players[i].tripwireState);
|
||||
WRITEUINT8(save_p, players[i].tripwirePass);
|
||||
WRITEUINT16(save_p, players[i].tripwireLeniency);
|
||||
|
||||
WRITEUINT16(save_p, players[i].itemroulette);
|
||||
|
|
@ -355,7 +357,6 @@ static void P_NetArchivePlayers(void)
|
|||
WRITEUINT32(save_p, players[i].spheredigestion);
|
||||
|
||||
WRITESINT8(save_p, players[i].glanceDir);
|
||||
WRITEUINT8(save_p, players[i].tripWireState);
|
||||
|
||||
WRITEUINT8(save_p, players[i].typing_timer);
|
||||
WRITEUINT8(save_p, players[i].typing_duration);
|
||||
|
|
@ -575,6 +576,8 @@ static void P_NetUnArchivePlayers(void)
|
|||
players[i].draftleeway = READUINT16(save_p);
|
||||
players[i].lastdraft = READSINT8(save_p);
|
||||
|
||||
players[i].tripwireState = READUINT8(save_p);
|
||||
players[i].tripwirePass = READUINT8(save_p);
|
||||
players[i].tripwireLeniency = READUINT16(save_p);
|
||||
|
||||
players[i].itemroulette = READUINT16(save_p);
|
||||
|
|
@ -639,7 +642,6 @@ static void P_NetUnArchivePlayers(void)
|
|||
players[i].spheredigestion = READUINT32(save_p);
|
||||
|
||||
players[i].glanceDir = READSINT8(save_p);
|
||||
players[i].tripWireState = READUINT8(save_p);
|
||||
|
||||
players[i].typing_timer = READUINT8(save_p);
|
||||
players[i].typing_duration = READUINT8(save_p);
|
||||
|
|
@ -1600,7 +1602,7 @@ typedef enum
|
|||
MD2_SPRITEXOFFSET = 1<<20,
|
||||
MD2_SPRITEYOFFSET = 1<<21,
|
||||
MD2_FLOORSPRITESLOPE = 1<<22,
|
||||
// 1<<23 was taken out, maybe reuse later
|
||||
MD2_DISPOFFSET = 1<<23,
|
||||
MD2_HITLAG = 1<<24,
|
||||
MD2_WAYPOINTCAP = 1<<25,
|
||||
MD2_KITEMCAP = 1<<26,
|
||||
|
|
@ -1841,6 +1843,8 @@ static void SaveMobjThinker(const thinker_t *th, const UINT8 type)
|
|||
}
|
||||
if (mobj->hitlag)
|
||||
diff2 |= MD2_HITLAG;
|
||||
if (mobj->dispoffset)
|
||||
diff2 |= MD2_DISPOFFSET;
|
||||
if (mobj == waypointcap)
|
||||
diff2 |= MD2_WAYPOINTCAP;
|
||||
if (mobj == kitemcap)
|
||||
|
|
@ -2049,6 +2053,10 @@ static void SaveMobjThinker(const thinker_t *th, const UINT8 type)
|
|||
{
|
||||
WRITEINT32(save_p, mobj->hitlag);
|
||||
}
|
||||
if (diff2 & MD2_DISPOFFSET)
|
||||
{
|
||||
WRITEINT32(save_p, mobj->dispoffset);
|
||||
}
|
||||
if (diff2 & MD2_LASTMOMZ)
|
||||
{
|
||||
WRITEINT32(save_p, mobj->lastmomz);
|
||||
|
|
@ -3154,6 +3162,10 @@ static thinker_t* LoadMobjThinker(actionf_p1 thinker)
|
|||
{
|
||||
mobj->hitlag = READINT32(save_p);
|
||||
}
|
||||
if (diff2 & MD2_DISPOFFSET)
|
||||
{
|
||||
mobj->dispoffset = READINT32(save_p);
|
||||
}
|
||||
if (diff2 & MD2_LASTMOMZ)
|
||||
{
|
||||
mobj->lastmomz = READINT32(save_p);
|
||||
|
|
|
|||
|
|
@ -516,6 +516,7 @@ typedef struct {
|
|||
divline_t strace; // from t1 to t2
|
||||
fixed_t bbox[4];
|
||||
mobj_t *compareThing;
|
||||
boolean alreadyHates;
|
||||
} traceblocking_t;
|
||||
|
||||
static boolean P_CrossBlockingSubsector(size_t num, register traceblocking_t *tb)
|
||||
|
|
@ -664,6 +665,7 @@ boolean P_TraceBlockingLines(mobj_t *t1, mobj_t *t2)
|
|||
tb.bbox[BOXTOP] = t2->y, tb.bbox[BOXBOTTOM] = t1->y;
|
||||
|
||||
tb.compareThing = t1;
|
||||
tb.alreadyHates = false;
|
||||
|
||||
// the head node is the last node output
|
||||
return P_CrossBSPNodeBlocking((INT32)numnodes - 1, &tb);
|
||||
|
|
@ -760,31 +762,17 @@ static boolean P_CrossBotTraversalSubsector(size_t num, register traceblocking_t
|
|||
return false;
|
||||
}
|
||||
|
||||
if (tb->compareThing->player != NULL)
|
||||
if (tb->compareThing->player != NULL && tb->alreadyHates == false)
|
||||
{
|
||||
// Treat damage sectors like walls
|
||||
boolean alreadyHates = K_BotHatesThisSector(
|
||||
tb->compareThing->player, tb->compareThing->subsector->sector,
|
||||
tb->compareThing->x, tb->compareThing->y
|
||||
);
|
||||
// Treat damage sectors like walls, if you're not already in a bad sector.
|
||||
vertex_t pos;
|
||||
P_ClosestPointOnLine(tb->compareThing->x, tb->compareThing->y, line, &pos);
|
||||
|
||||
if (alreadyHates == false)
|
||||
if (K_BotHatesThisSector(tb->compareThing->player, line->frontsector, pos.x, pos.y)
|
||||
|| K_BotHatesThisSector(tb->compareThing->player, line->backsector, pos.x, pos.y))
|
||||
{
|
||||
INT32 lineside = 0;
|
||||
vertex_t pos;
|
||||
|
||||
P_ClosestPointOnLine(tb->compareThing->x, tb->compareThing->y, line, &pos);
|
||||
lineside = P_PointOnLineSide(tb->compareThing->x, tb->compareThing->y, line);
|
||||
|
||||
if (K_BotHatesThisSector(
|
||||
tb->compareThing->player,
|
||||
((lineside == 1) ? line->frontsector : line->backsector),
|
||||
pos.x, pos.y
|
||||
))
|
||||
{
|
||||
// This line does not block us, but we don't want to be in it.
|
||||
return false;
|
||||
}
|
||||
// This line does not block us, but we don't want to be in it.
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -864,6 +852,17 @@ boolean P_TraceBotTraversal(mobj_t *t1, mobj_t *t2)
|
|||
tb.bbox[BOXTOP] = t2->y, tb.bbox[BOXBOTTOM] = t1->y;
|
||||
|
||||
tb.compareThing = t1;
|
||||
if (t1->player != NULL)
|
||||
{
|
||||
tb.alreadyHates = K_BotHatesThisSector(
|
||||
t1->player, t1->subsector->sector,
|
||||
t1->x, t1->y
|
||||
);
|
||||
}
|
||||
else
|
||||
{
|
||||
tb.alreadyHates = false;
|
||||
}
|
||||
|
||||
// the head node is the last node output
|
||||
return P_CrossBSPNodeBotTraversal((INT32)numnodes - 1, &tb);
|
||||
|
|
|
|||
|
|
@ -2070,7 +2070,7 @@ void P_CrossSpecialLine(line_t *line, INT32 side, mobj_t *thing)
|
|||
|
||||
if (P_IsLineTripWire(line))
|
||||
{
|
||||
K_ApplyTripWire(player, TRIP_PASSED);
|
||||
K_ApplyTripWire(player, TRIPSTATE_PASSED);
|
||||
}
|
||||
|
||||
switch (line->special)
|
||||
|
|
|
|||
16
src/p_user.c
16
src/p_user.c
|
|
@ -2727,17 +2727,17 @@ static CV_PossibleValue_t CV_CamSpeed[] = {{0, "MIN"}, {1*FRACUNIT, "MAX"}, {0,
|
|||
static CV_PossibleValue_t CV_CamRotate[] = {{-720, "MIN"}, {720, "MAX"}, {0, NULL}};
|
||||
|
||||
consvar_t cv_cam_dist[MAXSPLITSCREENPLAYERS] = {
|
||||
CVAR_INIT ("cam_dist", "160", CV_FLOAT|CV_SAVE, NULL, NULL),
|
||||
CVAR_INIT ("cam2_dist", "160", CV_FLOAT|CV_SAVE, NULL, NULL),
|
||||
CVAR_INIT ("cam3_dist", "160", CV_FLOAT|CV_SAVE, NULL, NULL),
|
||||
CVAR_INIT ("cam4_dist", "160", CV_FLOAT|CV_SAVE, NULL, NULL)
|
||||
CVAR_INIT ("cam_dist", "190", CV_FLOAT|CV_SAVE, NULL, NULL),
|
||||
CVAR_INIT ("cam2_dist", "190", CV_FLOAT|CV_SAVE, NULL, NULL),
|
||||
CVAR_INIT ("cam3_dist", "190", CV_FLOAT|CV_SAVE, NULL, NULL),
|
||||
CVAR_INIT ("cam4_dist", "190", CV_FLOAT|CV_SAVE, NULL, NULL)
|
||||
};
|
||||
|
||||
consvar_t cv_cam_height[MAXSPLITSCREENPLAYERS] = {
|
||||
CVAR_INIT ("cam_height", "50", CV_FLOAT|CV_SAVE, NULL, NULL),
|
||||
CVAR_INIT ("cam2_height", "50", CV_FLOAT|CV_SAVE, NULL, NULL),
|
||||
CVAR_INIT ("cam3_height", "50", CV_FLOAT|CV_SAVE, NULL, NULL),
|
||||
CVAR_INIT ("cam4_height", "50", CV_FLOAT|CV_SAVE, NULL, NULL)
|
||||
CVAR_INIT ("cam_height", "75", CV_FLOAT|CV_SAVE, NULL, NULL),
|
||||
CVAR_INIT ("cam2_height", "75", CV_FLOAT|CV_SAVE, NULL, NULL),
|
||||
CVAR_INIT ("cam3_height", "75", CV_FLOAT|CV_SAVE, NULL, NULL),
|
||||
CVAR_INIT ("cam4_height", "75", CV_FLOAT|CV_SAVE, NULL, NULL)
|
||||
};
|
||||
|
||||
consvar_t cv_cam_still[MAXSPLITSCREENPLAYERS] = {
|
||||
|
|
|
|||
|
|
@ -1503,7 +1503,7 @@ static void R_ProjectSprite(mobj_t *thing)
|
|||
fixed_t paperoffset = 0, paperdistance = 0;
|
||||
angle_t centerangle = 0;
|
||||
|
||||
INT32 dispoffset = thing->info->dispoffset;
|
||||
INT32 dispoffset = thing->dispoffset;
|
||||
|
||||
//SoM: 3/17/2000
|
||||
fixed_t gz = 0, gzt = 0;
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue