mirror of
https://github.com/KartKrewDev/RingRacers.git
synced 2025-10-30 08:01:28 +00:00
Merge branch 'master' into tracking-fix
This commit is contained in:
commit
ecb4111bed
19 changed files with 481 additions and 103 deletions
|
|
@ -617,6 +617,7 @@ static inline void resynch_write_player(resynch_pak *rsp, const size_t i)
|
|||
|
||||
rsp->airtime = (tic_t)LONG(players[i].airtime);
|
||||
rsp->driftInput = players[i].driftInput;
|
||||
rsp->airFailsafe = players[i].airFailsafe;
|
||||
|
||||
rsp->trickpanel = (UINT8)players[i].trickpanel;
|
||||
rsp->trickdelay = (boolean)players[i].trickdelay;
|
||||
|
|
@ -779,6 +780,7 @@ static void resynch_read_player(resynch_pak *rsp)
|
|||
|
||||
players[i].airtime = (tic_t)LONG(rsp->airtime);
|
||||
players[i].driftInput = (boolean)rsp->driftInput;
|
||||
players[i].airFailsafe = (boolean)rsp->airFailsafe;
|
||||
|
||||
players[i].trickpanel = (UINT8)rsp->trickpanel;
|
||||
players[i].trickdelay = (boolean)rsp->trickdelay;
|
||||
|
|
|
|||
|
|
@ -281,6 +281,7 @@ typedef struct
|
|||
INT32 kartstuff[NUMKARTSTUFF];
|
||||
tic_t airtime;
|
||||
boolean driftInput;
|
||||
boolean airFailsafe;
|
||||
UINT8 trickpanel;
|
||||
boolean trickdelay;
|
||||
fixed_t trickmomx;
|
||||
|
|
|
|||
|
|
@ -525,6 +525,7 @@ typedef struct player_s
|
|||
respawnvars_t respawn; // Respawn info
|
||||
tic_t airtime; // Keep track of how long you've been in the air
|
||||
boolean driftInput; // Whenever or not try drifting.
|
||||
boolean airFailsafe; // Whenever or not try the air boost
|
||||
|
||||
UINT8 trickpanel; // Trick panel state
|
||||
boolean trickdelay; // Prevent tricks until control stick is neutral
|
||||
|
|
|
|||
|
|
@ -1309,9 +1309,11 @@ void G_PreLevelTitleCard(void)
|
|||
//
|
||||
boolean G_IsTitleCardAvailable(void)
|
||||
{
|
||||
#if 0
|
||||
// The current level has no name.
|
||||
if (!mapheaderinfo[gamemap-1]->lvlttl[0])
|
||||
return false;
|
||||
#endif
|
||||
|
||||
// The title card is available.
|
||||
return true;
|
||||
|
|
|
|||
|
|
@ -698,7 +698,38 @@ static INT32 shader_leveltime = 0;
|
|||
"float fd = fe - fs;\n" \
|
||||
"darkness = clamp((darkness - fs) * (1.0 / fd), 0.0, 1.0);\n" \
|
||||
"}\n" \
|
||||
"final_color = mix(final_color, fade_color, darkness);\n"
|
||||
"float colorBrightness = sqrt((final_color.r * final_color.r) + (final_color.g * final_color.g) + (final_color.b * final_color.b));\n" \
|
||||
"float fogBrightness = sqrt((fade_color.r * fade_color.r) + (fade_color.g * fade_color.g) + (fade_color.b * fade_color.b));\n" \
|
||||
"float colorIntensity = 0.0;\n" \
|
||||
"if (fogBrightness > colorBrightness) {\n" \
|
||||
"colorIntensity = 1.0 - min(final_color.r, min(final_color.g, final_color.b));\n" \
|
||||
"colorIntensity = abs(colorIntensity - (1.0 - fogBrightness));\n" \
|
||||
"} else {\n" \
|
||||
"colorIntensity = max(final_color.r, max(final_color.g, final_color.b));\n" \
|
||||
"colorIntensity = abs(colorIntensity - (fogBrightness));\n" \
|
||||
"}\n" \
|
||||
"colorIntensity *= darkness;\n" \
|
||||
"if (abs(final_color.r - fade_color.r) <= colorIntensity) {\n" \
|
||||
"final_color.r = fade_color.r;\n" \
|
||||
"} else if (final_color.r < fade_color.r) {\n" \
|
||||
"final_color.r += colorIntensity;\n" \
|
||||
"} else {\n" \
|
||||
"final_color.r -= colorIntensity;\n" \
|
||||
"}\n" \
|
||||
"if (abs(final_color.g - fade_color.g) <= colorIntensity) {\n" \
|
||||
"final_color.g = fade_color.g;\n" \
|
||||
"} else if (final_color.g < fade_color.g) {\n" \
|
||||
"final_color.g += colorIntensity;\n" \
|
||||
"} else {\n" \
|
||||
"final_color.g -= colorIntensity;\n" \
|
||||
"}\n" \
|
||||
"if (abs(final_color.b - fade_color.b) <= colorIntensity) {\n" \
|
||||
"final_color.b = fade_color.b;\n" \
|
||||
"} else if (final_color.b < fade_color.b) {\n" \
|
||||
"final_color.b += colorIntensity;\n" \
|
||||
"} else {\n" \
|
||||
"final_color.b -= colorIntensity;\n" \
|
||||
"}\n" \
|
||||
|
||||
#define GLSL_SOFTWARE_FRAGMENT_SHADER \
|
||||
"uniform sampler2D tex;\n" \
|
||||
|
|
|
|||
363
src/k_bot.c
363
src/k_bot.c
|
|
@ -26,6 +26,7 @@
|
|||
#include "d_ticcmd.h"
|
||||
#include "m_random.h"
|
||||
#include "r_things.h" // numskins
|
||||
#include "k_race.h" // finishBeamLine
|
||||
|
||||
|
||||
/*--------------------------------------------------
|
||||
|
|
@ -296,7 +297,7 @@ boolean K_BotCanTakeCut(player_t *player)
|
|||
--------------------------------------------------*/
|
||||
static UINT32 K_BotRubberbandDistance(player_t *player)
|
||||
{
|
||||
const UINT32 spacing = FixedDiv(512 * FRACUNIT, K_GetKartGameSpeedScalar(gamespeed)) / FRACUNIT;
|
||||
const UINT32 spacing = FixedDiv(640 * FRACUNIT, K_GetKartGameSpeedScalar(gamespeed)) / FRACUNIT;
|
||||
const UINT8 portpriority = player - players;
|
||||
UINT8 pos = 0;
|
||||
UINT8 i;
|
||||
|
|
@ -429,8 +430,8 @@ fixed_t K_BotTopSpeedRubberband(player_t *player)
|
|||
}
|
||||
else
|
||||
{
|
||||
// Max at +25% for level 9 bots
|
||||
rubberband = FRACUNIT + ((rubberband - FRACUNIT) / 4);
|
||||
// Max at +10% for level 9 bots
|
||||
rubberband = FRACUNIT + ((rubberband - FRACUNIT) / 10);
|
||||
}
|
||||
|
||||
// Only allow you to go faster than your regular top speed if you're facing the right direction
|
||||
|
|
@ -519,28 +520,35 @@ fixed_t K_BotFrictionRubberband(player_t *player, fixed_t frict)
|
|||
|
||||
See header file for description.
|
||||
--------------------------------------------------*/
|
||||
fixed_t K_DistanceOfLineFromPoint(fixed_t v1x, fixed_t v1y, fixed_t v2x, fixed_t v2y, fixed_t cx, fixed_t cy)
|
||||
fixed_t K_DistanceOfLineFromPoint(fixed_t v1x, fixed_t v1y, fixed_t v2x, fixed_t v2y, fixed_t px, fixed_t py)
|
||||
{
|
||||
fixed_t v1toc[2] = {cx - v1x, cy - v1y};
|
||||
fixed_t v1tov2[2] = {v2x - v1x, v2y - v1y};
|
||||
|
||||
fixed_t mag = FixedMul(v1tov2[0], v1tov2[0]) + FixedMul(v1tov2[1], v1tov2[1]);
|
||||
fixed_t dot = FixedMul(v1toc[0], v1tov2[0]) + FixedMul(v1toc[1], v1tov2[1]);
|
||||
// Copy+paste from P_ClosestPointOnLine :pensive:
|
||||
fixed_t startx = v1x;
|
||||
fixed_t starty = v1y;
|
||||
fixed_t dx = v2x - v1x;
|
||||
fixed_t dy = v2y - v1y;
|
||||
|
||||
fixed_t cx, cy;
|
||||
fixed_t vx, vy;
|
||||
fixed_t magnitude;
|
||||
fixed_t t;
|
||||
fixed_t px, py;
|
||||
|
||||
if (mag == 0)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
cx = px - startx;
|
||||
cy = py - starty;
|
||||
|
||||
t = FixedDiv(dot, mag);
|
||||
vx = dx;
|
||||
vy = dy;
|
||||
|
||||
px = v1x + FixedMul(v1tov2[0], t);
|
||||
py = v1y + FixedMul(v1tov2[1], t);
|
||||
magnitude = R_PointToDist2(v2x, v2y, startx, starty);
|
||||
vx = FixedDiv(vx, magnitude);
|
||||
vy = FixedDiv(vy, magnitude);
|
||||
|
||||
return P_AproxDistance(cx - px, cy - py);
|
||||
t = (FixedMul(vx, cx) + FixedMul(vy, cy));
|
||||
|
||||
vx = FixedMul(vx, t);
|
||||
vy = FixedMul(vy, t);
|
||||
|
||||
return R_PointToDist2(px, py, startx + vx, starty + vy);
|
||||
}
|
||||
|
||||
/*--------------------------------------------------
|
||||
|
|
@ -686,6 +694,145 @@ static botprediction_t *K_CreateBotPrediction(player_t *player)
|
|||
return predict;
|
||||
}
|
||||
|
||||
/*--------------------------------------------------
|
||||
static UINT8 K_TrySpindash(player_t *player)
|
||||
|
||||
Determines conditions where the bot should attempt to spindash.
|
||||
|
||||
Input Arguments:-
|
||||
player - Bot player to check.
|
||||
|
||||
Return:-
|
||||
0 to make the bot drive normally, 1 to e-brake, 2 to e-brake & charge spindash.
|
||||
(TODO: make this an enum)
|
||||
--------------------------------------------------*/
|
||||
static UINT8 K_TrySpindash(player_t *player)
|
||||
{
|
||||
const tic_t difficultyModifier = (TICRATE/6);
|
||||
|
||||
if (player->kartstuff[k_spindashboost] || player->kartstuff[k_tiregrease])
|
||||
{
|
||||
// You just released a spindash, you don't need to try again yet, jeez.
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Try "start boosts" first
|
||||
if (leveltime == starttime)
|
||||
{
|
||||
// Forces them to release, even if they haven't fully charged.
|
||||
// Don't want them to keep charging if they didn't have time to.
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (leveltime < starttime)
|
||||
{
|
||||
INT32 boosthold = starttime - K_GetSpindashChargeTime(player);
|
||||
|
||||
boosthold -= (MAXBOTDIFFICULTY - player->botvars.difficulty) * difficultyModifier;
|
||||
|
||||
if (leveltime >= (unsigned)boosthold)
|
||||
{
|
||||
// Start charging...
|
||||
return 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Just hold your ground and e-brake.
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
// Logic for normal racing.
|
||||
if (player->powers[pw_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 (player->speed < 10*mapobjectscale // Below the speed threshold
|
||||
&& player->kartstuff[k_speedboost] < (FRACUNIT/8)) // If you have other boosts, you can probably trust it.
|
||||
{
|
||||
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;
|
||||
|
||||
if (player->kartstuff[k_spindash] > chargingPoint)
|
||||
{
|
||||
// Time to release.
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 2;
|
||||
}
|
||||
|
||||
// We're doing just fine, we don't need to spindash, thanks.
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*--------------------------------------------------
|
||||
static INT16 K_FindBotController(mobj_t *mo)
|
||||
|
||||
Finds if any bot controller linedefs are tagged to the bot's sector.
|
||||
|
||||
Input Arguments:-
|
||||
mo - The bot player's mobj.
|
||||
|
||||
Return:-
|
||||
Line number of the bot controller. -1 if it doesn't exist.
|
||||
--------------------------------------------------*/
|
||||
static INT16 K_FindBotController(mobj_t *mo)
|
||||
{
|
||||
msecnode_t *node;
|
||||
ffloor_t *rover;
|
||||
INT16 lineNum = -1;
|
||||
|
||||
I_Assert(mo != NULL);
|
||||
I_Assert(!P_MobjWasRemoved(mo));
|
||||
|
||||
for (node = mo->touching_sectorlist; node; node = node->m_sectorlist_next)
|
||||
{
|
||||
if (!node->m_sector)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
lineNum = P_FindSpecialLineFromTag(2004, node->m_sector->tag, -1);
|
||||
|
||||
if (lineNum != -1)
|
||||
{
|
||||
return lineNum;
|
||||
}
|
||||
|
||||
for (rover = node->m_sector->ffloors; rover; rover = rover->next)
|
||||
{
|
||||
sector_t *rs = NULL;
|
||||
|
||||
if (!(rover->flags & FF_EXISTS))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (mo->z > *rover->topheight || mo->z + mo->height < *rover->bottomheight)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
rs = §ors[rover->secnum];
|
||||
lineNum = P_FindSpecialLineFromTag(2004, rs->tag, -1);
|
||||
|
||||
if (lineNum != -1)
|
||||
{
|
||||
return lineNum;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
/*--------------------------------------------------
|
||||
void K_BuildBotTiccmd(player_t *player, ticcmd_t *cmd)
|
||||
|
||||
|
|
@ -694,7 +841,10 @@ static botprediction_t *K_CreateBotPrediction(player_t *player)
|
|||
void K_BuildBotTiccmd(player_t *player, ticcmd_t *cmd)
|
||||
{
|
||||
botprediction_t *predict = NULL;
|
||||
boolean trySpindash = true;
|
||||
UINT8 spindash = 0;
|
||||
INT32 turnamt = 0;
|
||||
INT16 botController = -1;
|
||||
|
||||
// Can't build a ticcmd if we aren't spawned...
|
||||
if (!player->mo)
|
||||
|
|
@ -705,53 +855,87 @@ void K_BuildBotTiccmd(player_t *player, ticcmd_t *cmd)
|
|||
// Remove any existing controls
|
||||
memset(cmd, 0, sizeof(ticcmd_t));
|
||||
|
||||
if (gamestate != GS_LEVEL
|
||||
|| player->mo->scale <= 1) // funny post-finish death
|
||||
if (
|
||||
gamestate != GS_LEVEL
|
||||
|| player->mo->scale <= 1
|
||||
|| player->playerstate == PST_DEAD
|
||||
)
|
||||
{
|
||||
// No need to do anything else.
|
||||
return;
|
||||
}
|
||||
|
||||
if (player->playerstate == PST_DEAD)
|
||||
{
|
||||
cmd->buttons |= BT_ACCELERATE;
|
||||
return;
|
||||
}
|
||||
|
||||
// Complete override of all ticcmd functionality
|
||||
if (LUAh_BotTiccmd(player, cmd))
|
||||
return;
|
||||
|
||||
// Start boost handler
|
||||
if (leveltime <= starttime)
|
||||
{
|
||||
tic_t length = (TICRATE/6);
|
||||
tic_t boosthold = starttime - K_GetSpindashChargeTime(player);
|
||||
|
||||
cmd->buttons |= BT_EBRAKEMASK;
|
||||
|
||||
boosthold -= (MAXBOTDIFFICULTY - player->botvars.difficulty) * length;
|
||||
|
||||
if (leveltime >= boosthold)
|
||||
{
|
||||
cmd->buttons |= BT_DRIFT;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
botController = K_FindBotController(player->mo);
|
||||
|
||||
if (player->trickpanel != 0)
|
||||
{
|
||||
// Trick panel state -- do nothing until a controller line is found, in which case do a trick.
|
||||
|
||||
if (player->trickpanel == 1 && botController != -1)
|
||||
{
|
||||
line_t *controllerLine = &lines[botController];
|
||||
INT32 type = (sides[controllerLine->sidenum[0]].rowoffset / FRACUNIT);
|
||||
|
||||
// Y Offset: Trick type
|
||||
switch (type)
|
||||
{
|
||||
case 1:
|
||||
cmd->turning = KART_FULLTURN;
|
||||
break;
|
||||
case 2:
|
||||
cmd->turning = -KART_FULLTURN;
|
||||
break;
|
||||
case 3:
|
||||
cmd->buttons |= BT_FORWARD;
|
||||
break;
|
||||
case 4:
|
||||
cmd->buttons |= BT_BACKWARD;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Don't do anything else.
|
||||
return;
|
||||
}
|
||||
|
||||
if ((player->nextwaypoint != NULL
|
||||
&& player->nextwaypoint->mobj != NULL
|
||||
&& !P_MobjWasRemoved(player->nextwaypoint->mobj))
|
||||
|| (botController != -1))
|
||||
{
|
||||
// Handle steering towards waypoints!
|
||||
if (player->nextwaypoint != NULL && player->nextwaypoint->mobj != NULL && !P_MobjWasRemoved(player->nextwaypoint->mobj))
|
||||
{
|
||||
SINT8 turnsign = 0;
|
||||
angle_t destangle, moveangle, angle;
|
||||
INT16 anglediff;
|
||||
|
||||
if (botController != -1)
|
||||
{
|
||||
const fixed_t dist = (player->mo->radius * 4);
|
||||
line_t *controllerLine = &lines[botController];
|
||||
|
||||
// X Offset: Movement direction
|
||||
destangle = FixedAngle(sides[controllerLine->sidenum[0]].textureoffset);
|
||||
|
||||
// Overwritten prediction
|
||||
predict = Z_Calloc(sizeof(botprediction_t), PU_LEVEL, NULL);
|
||||
|
||||
predict->x = player->mo->x + FixedMul(dist, FINECOSINE(destangle >> ANGLETOFINESHIFT));
|
||||
predict->y = player->mo->y + FixedMul(dist, FINESINE(destangle >> ANGLETOFINESHIFT));
|
||||
predict->radius = (DEFAULT_WAYPOINT_RADIUS / 4) * mapobjectscale;
|
||||
}
|
||||
else
|
||||
{
|
||||
predict = K_CreateBotPrediction(player);
|
||||
|
||||
destangle = R_PointToAngle2(player->mo->x, player->mo->y, predict->x, predict->y);
|
||||
moveangle = player->mo->angle;
|
||||
}
|
||||
|
||||
moveangle = player->mo->angle;
|
||||
angle = (moveangle - destangle);
|
||||
|
||||
if (angle < ANGLE_180)
|
||||
|
|
@ -777,7 +961,7 @@ void K_BuildBotTiccmd(player_t *player, ticcmd_t *cmd)
|
|||
else
|
||||
{
|
||||
const fixed_t playerwidth = (player->mo->radius * 2);
|
||||
const fixed_t realrad = predict->radius - (playerwidth * 4); // Remove a "safe" distance away from the edges of the road
|
||||
fixed_t realrad = predict->radius - (playerwidth * 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,
|
||||
|
|
@ -853,8 +1037,77 @@ void K_BuildBotTiccmd(player_t *player, ticcmd_t *cmd)
|
|||
}
|
||||
}
|
||||
|
||||
// Handle item usage
|
||||
if (leveltime <= starttime && finishBeamLine != NULL)
|
||||
{
|
||||
const fixed_t distBase = 384*mapobjectscale;
|
||||
const fixed_t distAdjust = 64*mapobjectscale;
|
||||
|
||||
const fixed_t closeDist = distBase + (distAdjust * (9 - player->kartweight));
|
||||
const fixed_t farDist = closeDist + (distAdjust * 2);
|
||||
|
||||
fixed_t distToFinish = K_DistanceOfLineFromPoint(
|
||||
finishBeamLine->v1->x, finishBeamLine->v1->y,
|
||||
finishBeamLine->v2->x, finishBeamLine->v2->y,
|
||||
player->mo->x, player->mo->y
|
||||
);
|
||||
|
||||
// Don't run the spindash code at all until we're in the right place
|
||||
trySpindash = false;
|
||||
|
||||
// If you're too far, enable spindash & stay still.
|
||||
// If you're too close, start backing up.
|
||||
|
||||
if (distToFinish < closeDist)
|
||||
{
|
||||
// Silly way of getting us to reverse, but it respects the above code
|
||||
// where we figure out what the shape of the track looks like.
|
||||
UINT16 oldButtons = cmd->buttons;
|
||||
|
||||
cmd->buttons &= ~(BT_ACCELERATE|BT_BRAKE);
|
||||
|
||||
if (oldButtons & BT_ACCELERATE)
|
||||
{
|
||||
cmd->buttons |= BT_BRAKE;
|
||||
}
|
||||
|
||||
if (oldButtons & BT_BRAKE)
|
||||
{
|
||||
cmd->buttons |= BT_ACCELERATE;
|
||||
}
|
||||
|
||||
cmd->forwardmove = -cmd->forwardmove;
|
||||
}
|
||||
else if (distToFinish < farDist)
|
||||
{
|
||||
// We're in about the right place, spindash now.
|
||||
cmd->forwardmove = 0;
|
||||
trySpindash = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (trySpindash == true)
|
||||
{
|
||||
// Spindashing
|
||||
spindash = K_TrySpindash(player);
|
||||
|
||||
if (spindash > 0)
|
||||
{
|
||||
cmd->buttons |= BT_EBRAKEMASK;
|
||||
cmd->forwardmove = 0;
|
||||
|
||||
if (spindash == 2 && player->speed < 6*mapobjectscale)
|
||||
{
|
||||
cmd->buttons |= BT_DRIFT;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (spindash == 0)
|
||||
{
|
||||
// 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?
|
||||
K_BotItemUsage(player, cmd, turnamt);
|
||||
}
|
||||
|
||||
if (turnamt != 0)
|
||||
{
|
||||
|
|
@ -869,6 +1122,7 @@ void K_BuildBotTiccmd(player_t *player, ticcmd_t *cmd)
|
|||
|
||||
if (turnamt > 0)
|
||||
{
|
||||
// Count up
|
||||
if (player->botvars.turnconfirm < BOTTURNCONFIRM)
|
||||
{
|
||||
player->botvars.turnconfirm++;
|
||||
|
|
@ -876,11 +1130,24 @@ void K_BuildBotTiccmd(player_t *player, ticcmd_t *cmd)
|
|||
}
|
||||
else if (turnamt < 0)
|
||||
{
|
||||
// Count down
|
||||
if (player->botvars.turnconfirm > -BOTTURNCONFIRM)
|
||||
{
|
||||
player->botvars.turnconfirm--;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Back to neutral
|
||||
if (player->botvars.turnconfirm < 0)
|
||||
{
|
||||
player->botvars.turnconfirm++;
|
||||
}
|
||||
else if (player->botvars.turnconfirm > 0)
|
||||
{
|
||||
player->botvars.turnconfirm--;
|
||||
}
|
||||
}
|
||||
|
||||
if (abs(player->botvars.turnconfirm) >= BOTTURNCONFIRM)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -167,9 +167,9 @@ void K_InitGrandPrixBots(void)
|
|||
difficultylevels[10] = max(1, startingdifficulty-5);
|
||||
difficultylevels[11] = max(1, startingdifficulty-6);
|
||||
difficultylevels[12] = max(1, startingdifficulty-6);
|
||||
difficultylevels[13] = max(1, startingdifficulty-6);
|
||||
difficultylevels[13] = max(1, startingdifficulty-7);
|
||||
difficultylevels[14] = max(1, startingdifficulty-7);
|
||||
difficultylevels[15] = max(1, startingdifficulty-7);
|
||||
difficultylevels[15] = max(1, startingdifficulty-8);
|
||||
}
|
||||
|
||||
for (i = 0; i < MAXPLAYERS; i++)
|
||||
|
|
|
|||
|
|
@ -2201,7 +2201,7 @@ static void K_drawKartSpeedometer(void)
|
|||
{
|
||||
case 1: // Sonic Drift 2 style percentage
|
||||
default:
|
||||
convSpeed = (((25*stplyr->speed)/24) * 100) / K_GetKartSpeed(stplyr, false); // Based on top speed! (cheats with the numbers due to some weird discrepancy)
|
||||
convSpeed = (stplyr->speed * 100) / K_GetKartSpeed(stplyr, false); // Based on top speed!
|
||||
labeln = 0;
|
||||
break;
|
||||
case 2: // Kilometers
|
||||
|
|
@ -2220,7 +2220,8 @@ static void K_drawKartSpeedometer(void)
|
|||
}
|
||||
|
||||
// Don't overflow
|
||||
if (convSpeed > 999)
|
||||
// (negative speed IS really high speed :V)
|
||||
if (convSpeed > 999 || convSpeed < 0)
|
||||
convSpeed = 999;
|
||||
|
||||
numbers[0] = ((convSpeed / 100) % 10);
|
||||
|
|
|
|||
85
src/k_kart.c
85
src/k_kart.c
|
|
@ -2470,11 +2470,18 @@ fixed_t K_GetKartSpeed(player_t *player, boolean doboostpower)
|
|||
finalspeed = FixedMul(finalspeed, FRACUNIT + (sphereAdd * player->spheres));
|
||||
}
|
||||
|
||||
if (K_PlayerUsesBotMovement(player) && player->botvars.rival == true)
|
||||
if (K_PlayerUsesBotMovement(player))
|
||||
{
|
||||
// Increase bot speed by 1-10% depending on difficulty
|
||||
fixed_t add = (player->botvars.difficulty * (FRACUNIT/10)) / MAXBOTDIFFICULTY;
|
||||
finalspeed = FixedMul(finalspeed, FRACUNIT + add);
|
||||
|
||||
if (player->botvars.rival == true)
|
||||
{
|
||||
// +10% top speed for the rival
|
||||
finalspeed = FixedMul(finalspeed, 11*FRACUNIT/10);
|
||||
}
|
||||
}
|
||||
|
||||
if (player->mo && !P_MobjWasRemoved(player->mo))
|
||||
finalspeed = FixedMul(finalspeed, player->mo->scale);
|
||||
|
|
@ -6838,7 +6845,15 @@ void K_UpdateDistanceFromFinishLine(player_t *const player)
|
|||
|
||||
INT32 K_GetKartRingPower(player_t *player)
|
||||
{
|
||||
return (((9 - player->kartspeed) + (9 - player->kartweight)) / 2);
|
||||
INT32 ringPower = ((9 - player->kartspeed) + (9 - player->kartweight)) / 2;
|
||||
|
||||
if (K_PlayerUsesBotMovement(player))
|
||||
{
|
||||
// Double for Lv. 9
|
||||
ringPower += (player->botvars.difficulty * ringPower) / MAXBOTDIFFICULTY;
|
||||
}
|
||||
|
||||
return ringPower;
|
||||
}
|
||||
|
||||
// Returns false if this player being placed here causes them to collide with any other player
|
||||
|
|
@ -6984,6 +6999,7 @@ INT32 K_GetKartDriftSparkValue(player_t *player)
|
|||
Stage 1: red sparks
|
||||
Stage 2: blue sparks
|
||||
Stage 3: big large rainbow sparks
|
||||
Stage 0: air failsafe
|
||||
*/
|
||||
void K_SpawnDriftBoostExplosion(player_t *player, int stage)
|
||||
{
|
||||
|
|
@ -7014,6 +7030,11 @@ void K_SpawnDriftBoostExplosion(player_t *player, int stage)
|
|||
S_StartSound(player->mo, sfx_kc5b);
|
||||
S_StartSound(player->mo, sfx_s3kc4l);
|
||||
break;
|
||||
|
||||
case 0:
|
||||
overlay->color = SKINCOLOR_SILVER;
|
||||
overlay->fuse = 16;
|
||||
break;
|
||||
}
|
||||
|
||||
overlay->extravalue1 = stage;
|
||||
|
|
@ -7526,11 +7547,14 @@ static void K_KartSpindash(player_t *player)
|
|||
return;
|
||||
}
|
||||
|
||||
if (player->speed < 6*mapobjectscale && player->powers[pw_flashing] == 0)
|
||||
if (player->speed == 0 && cmd->turning != 0 && leveltime % 8 == 0)
|
||||
{
|
||||
if (cmd->turning != 0 && leveltime % 8 == 0)
|
||||
// Rubber burn turn sfx
|
||||
S_StartSound(player->mo, sfx_ruburn);
|
||||
}
|
||||
|
||||
if (player->speed < 6*player->mo->scale)
|
||||
{
|
||||
if ((cmd->buttons & (BT_DRIFT|BT_BRAKE)) == (BT_DRIFT|BT_BRAKE))
|
||||
{
|
||||
INT16 chargetime = MAXCHARGETIME - ++player->kartstuff[k_spindash];
|
||||
|
|
@ -7547,6 +7571,15 @@ static void K_KartSpindash(player_t *player)
|
|||
K_KartSpindashWind(player->mo);
|
||||
}
|
||||
|
||||
if (player->powers[pw_flashing] > 0 && (leveltime & 1) && player->kartstuff[k_hyudorotimer] == 0)
|
||||
{
|
||||
// Every frame that you're invisible from flashing, spill a ring.
|
||||
// Intentionally a lop-sided trade-off, so the game doesn't become
|
||||
// Funky Kong's Ring Racers.
|
||||
|
||||
P_PlayerRingBurst(player, 1);
|
||||
}
|
||||
|
||||
if (chargetime > 0)
|
||||
{
|
||||
UINT16 soundcharge = 0;
|
||||
|
|
@ -7574,6 +7607,39 @@ static void K_KartSpindash(player_t *player)
|
|||
}
|
||||
}
|
||||
|
||||
static void K_AirFailsafe(player_t *player)
|
||||
{
|
||||
const fixed_t maxSpeed = 6*player->mo->scale;
|
||||
const fixed_t thrustSpeed = 6*player->mo->scale; // 10*player->mo->scale
|
||||
|
||||
ticcmd_t *cmd = &player->cmd;
|
||||
|
||||
if (player->speed > maxSpeed // Above the max speed that you're allowed to use this technique.
|
||||
|| player->respawn.state != RESPAWNST_NONE) // Respawning, you don't need this AND drop dash :V
|
||||
{
|
||||
player->airFailsafe = false;
|
||||
return;
|
||||
}
|
||||
|
||||
if ((cmd->buttons & BT_ACCELERATE) || K_GetForwardMove(player) != 0)
|
||||
{
|
||||
// Queue up later
|
||||
player->airFailsafe = true;
|
||||
return;
|
||||
}
|
||||
|
||||
if (player->airFailsafe == true)
|
||||
{
|
||||
// Push the player forward
|
||||
P_Thrust(player->mo, K_MomentumAngle(player->mo), thrustSpeed);
|
||||
|
||||
S_StartSound(player->mo, sfx_s23c);
|
||||
K_SpawnDriftBoostExplosion(player, 0);
|
||||
|
||||
player->airFailsafe = false;
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// K_AdjustPlayerFriction
|
||||
//
|
||||
|
|
@ -8447,9 +8513,18 @@ void K_MoveKartPlayer(player_t *player, boolean onground)
|
|||
}
|
||||
}
|
||||
|
||||
K_KartDrift(player, P_IsObjectOnGround(player->mo)); // Not using onground, since we don't want this affected by spring pads
|
||||
K_KartDrift(player, onground);
|
||||
K_KartSpindash(player);
|
||||
|
||||
if (onground == false)
|
||||
{
|
||||
K_AirFailsafe(player);
|
||||
}
|
||||
else
|
||||
{
|
||||
player->airFailsafe = false;
|
||||
}
|
||||
|
||||
// Play the starting countdown sounds
|
||||
if (player == &players[g_localplayers[0]]) // Don't play louder in splitscreen
|
||||
{
|
||||
|
|
|
|||
|
|
@ -41,7 +41,7 @@
|
|||
#include "k_bot.h"
|
||||
#include "k_hud.h"
|
||||
|
||||
static line_t *finishBeamLine = NULL;
|
||||
line_t *finishBeamLine = NULL;
|
||||
|
||||
static mobj_t *beamPoints[2];
|
||||
static UINT8 numBeamPoints = 0;
|
||||
|
|
|
|||
|
|
@ -14,6 +14,8 @@
|
|||
|
||||
#include "r_defs.h"
|
||||
|
||||
extern line_t *finishBeamLine;
|
||||
|
||||
#define FINISHLINEBEAM_SPACING (48*mapobjectscale)
|
||||
|
||||
/*--------------------------------------------------
|
||||
|
|
|
|||
|
|
@ -220,6 +220,8 @@ static int player_get(lua_State *L)
|
|||
lua_pushinteger(L, plr->airtime);
|
||||
else if (fastcmp(field,"driftInput"))
|
||||
lua_pushboolean(L, plr->driftInput);
|
||||
else if (fastcmp(field,"airFailsafe"))
|
||||
lua_pushboolean(L, plr->airFailsafe);
|
||||
else if (fastcmp(field,"tumbleBounces"))
|
||||
lua_pushinteger(L, plr->tumbleBounces);
|
||||
else if (fastcmp(field,"tumbleHeight"))
|
||||
|
|
@ -533,6 +535,8 @@ static int player_set(lua_State *L)
|
|||
plr->airtime = (tic_t)luaL_checkinteger(L, 3);
|
||||
else if (fastcmp(field,"driftInput"))
|
||||
plr->driftInput = luaL_checkboolean(L, 3);
|
||||
else if (fastcmp(field,"airFailsafe"))
|
||||
plr->airFailsafe = luaL_checkboolean(L, 3);
|
||||
else if (fastcmp(field,"tumbleBounces"))
|
||||
plr->tumbleBounces = (UINT8)luaL_checkinteger(L, 3);
|
||||
else if (fastcmp(field,"tumbleHeight"))
|
||||
|
|
|
|||
|
|
@ -4229,7 +4229,7 @@ void A_AttractChase(mobj_t *actor)
|
|||
else
|
||||
actor->drawflags &= ~MFD_DONTDRAW;
|
||||
|
||||
// spilled rings have ghost trails and get capped to a certain speed
|
||||
// spilled rings get capped to a certain speed
|
||||
if (actor->type == (mobjtype_t)actor->info->reactiontime)
|
||||
{
|
||||
const fixed_t maxspeed = 4<<FRACBITS;
|
||||
|
|
@ -4241,9 +4241,6 @@ void A_AttractChase(mobj_t *actor)
|
|||
actor->momx = FixedMul(FixedDiv(actor->momx, oldspeed), newspeed);
|
||||
actor->momy = FixedMul(FixedDiv(actor->momy, oldspeed), newspeed);
|
||||
}
|
||||
|
||||
if (!P_IsObjectOnGround(actor))
|
||||
P_SpawnGhostMobj(actor)->tics = 3;
|
||||
}
|
||||
|
||||
if (actor->tracer && actor->tracer->player && actor->tracer->health
|
||||
|
|
|
|||
|
|
@ -2182,10 +2182,7 @@ static void P_FlingBurst
|
|||
mo->momy = (mo->target->momy/2) + FixedMul(FINESINE(fa>>ANGLETOFINESHIFT), ns);
|
||||
|
||||
ns = FixedMul(momz, player->mo->scale);
|
||||
P_SetObjectMomZ(mo, (mo->target->momz/2) + ns, false);
|
||||
|
||||
if (player->mo->eflags & MFE_VERTICALFLIP)
|
||||
mo->momz *= -1;
|
||||
mo->momz = (mo->target->momz/2) + ((ns) * P_MobjFlip(mo));
|
||||
}
|
||||
|
||||
/** Spills an injured player's rings.
|
||||
|
|
@ -2240,6 +2237,6 @@ void P_PlayerRingBurst(player_t *player, INT32 num_rings)
|
|||
while (i < num_rings)
|
||||
{
|
||||
P_FlingBurst(player, fa, z,
|
||||
MT_DEBTSPIKE, 90, 3 * player->mo->scale / 2, i++);
|
||||
MT_DEBTSPIKE, 0, 3 * player->mo->scale / 2, i++);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
10
src/p_mobj.c
10
src/p_mobj.c
|
|
@ -2296,6 +2296,11 @@ boolean P_ZMovement(mobj_t *mo)
|
|||
{
|
||||
mom.x = mom.y = 0;
|
||||
mom.z = -mom.z/2;
|
||||
|
||||
if (mo->fuse == 0)
|
||||
{
|
||||
mo->fuse = 90;
|
||||
}
|
||||
}
|
||||
else if (mo->flags & MF_MISSILE)
|
||||
{
|
||||
|
|
@ -6743,6 +6748,10 @@ static boolean P_MobjRegularThink(mobj_t *mobj)
|
|||
if (mobj->fuse == 16)/* to red*/
|
||||
K_SpawnDriftBoostClip(mobj->target->player);
|
||||
break;
|
||||
|
||||
case 0:/* air failsafe boost */
|
||||
mobj->color = SKINCOLOR_SILVER; // force white
|
||||
break;
|
||||
}
|
||||
|
||||
{
|
||||
|
|
@ -9197,6 +9206,7 @@ static void P_DefaultMobjShadowScale(mobj_t *thing)
|
|||
thing->shadowscale = FRACUNIT;
|
||||
break;
|
||||
case MT_RING:
|
||||
case MT_FLINGRING:
|
||||
case MT_DEBTSPIKE:
|
||||
case MT_FLOATINGITEM:
|
||||
case MT_BLUESPHERE:
|
||||
|
|
|
|||
|
|
@ -258,6 +258,7 @@ static void P_NetArchivePlayers(void)
|
|||
|
||||
WRITEUINT32(save_p, players[i].airtime);
|
||||
WRITEUINT8(save_p, players[i].driftInput);
|
||||
WRITEUINT8(save_p, players[i].airFailsafe);
|
||||
|
||||
WRITEUINT8(save_p, players[i].trickpanel);
|
||||
WRITEUINT8(save_p, players[i].trickdelay);
|
||||
|
|
@ -463,6 +464,7 @@ static void P_NetUnArchivePlayers(void)
|
|||
|
||||
players[i].airtime = READUINT32(save_p);
|
||||
players[i].driftInput = (boolean)READUINT8(save_p);
|
||||
players[i].airFailsafe = (boolean)READUINT8(save_p);
|
||||
|
||||
players[i].trickpanel = READUINT8(save_p);
|
||||
players[i].trickdelay = READUINT8(save_p);
|
||||
|
|
|
|||
|
|
@ -6955,6 +6955,8 @@ void P_SpawnSpecials(boolean fromnetsave)
|
|||
break;
|
||||
case 2003: // Respawn Line
|
||||
break;
|
||||
case 2004: // Bot controller
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
|
|
|
|||
|
|
@ -2632,9 +2632,6 @@ static void P_DeathThink(player_t *player)
|
|||
if (player->deadtimer < INT32_MAX)
|
||||
player->deadtimer++;
|
||||
|
||||
if (player->bot) // don't allow bots to do any of the below, B_CheckRespawn does all they need for respawning already
|
||||
goto notrealplayer;
|
||||
|
||||
if ((player->pflags & PF_GAMETYPEOVER) && (gametyperules & GTR_CIRCUIT))
|
||||
{
|
||||
player->karthud[khud_timeovercam]++;
|
||||
|
|
@ -2677,8 +2674,6 @@ static void P_DeathThink(player_t *player)
|
|||
}
|
||||
}
|
||||
|
||||
notrealplayer:
|
||||
|
||||
if (!player->mo)
|
||||
return;
|
||||
|
||||
|
|
|
|||
|
|
@ -1236,28 +1236,24 @@ static void R_ProjectDropShadow(mobj_t *thing, vissprite_t *vis, fixed_t scale,
|
|||
patch_t *patch;
|
||||
fixed_t xscale, yscale, shadowxscale, shadowyscale, shadowskew, x1, x2;
|
||||
INT32 light = 0;
|
||||
fixed_t scalemul; UINT8 trans;
|
||||
fixed_t floordiff;
|
||||
UINT8 trans = tr_transsub;
|
||||
fixed_t groundz;
|
||||
pslope_t *groundslope;
|
||||
boolean isflipped = thing->eflags & MFE_VERTICALFLIP;
|
||||
|
||||
groundz = R_GetShadowZ(thing, &groundslope);
|
||||
|
||||
if (abs(groundz-viewz)/tz > 4) return; // Prevent stretchy shadows and possible crashes
|
||||
|
||||
floordiff = abs((isflipped ? thing->height : 0) + thing->z - groundz);
|
||||
if (thing->whiteshadow == true)
|
||||
{
|
||||
trans = tr_transadd;
|
||||
}
|
||||
|
||||
trans = floordiff / (100*FRACUNIT) + 3;
|
||||
if (trans >= 9) return;
|
||||
|
||||
scalemul = FixedMul(FRACUNIT - floordiff/640, scale);
|
||||
|
||||
patch = W_CachePatchName((thing->whiteshadow == true ? "LSHADOW" : "DSHADOW"), PU_CACHE);
|
||||
patch = W_CachePatchName("DSHADOW", PU_CACHE);
|
||||
xscale = FixedDiv(projection[viewssnum], tz);
|
||||
yscale = FixedDiv(projectiony[viewssnum], tz);
|
||||
shadowxscale = FixedMul(thing->radius*2, scalemul);
|
||||
shadowyscale = FixedMul(FixedMul(thing->radius*2, scalemul), FixedDiv(abs(groundz - viewz), tz));
|
||||
shadowxscale = FixedMul(thing->radius*2, scale);
|
||||
shadowyscale = FixedMul(FixedMul(thing->radius*2, scale), FixedDiv(abs(groundz - viewz), tz));
|
||||
shadowyscale = min(shadowyscale, shadowxscale) / SHORT(patch->height);
|
||||
shadowxscale /= SHORT(patch->width);
|
||||
shadowskew = 0;
|
||||
|
|
@ -1274,9 +1270,9 @@ static void R_ProjectDropShadow(mobj_t *thing, vissprite_t *vis, fixed_t scale,
|
|||
//CONS_Printf("Shadow is sloped by %d %d\n", xslope, zslope);
|
||||
|
||||
if (viewz < groundz)
|
||||
shadowyscale += FixedMul(FixedMul(thing->radius*2 / SHORT(patch->height), scalemul), zslope);
|
||||
shadowyscale += FixedMul(FixedMul(thing->radius*2 / SHORT(patch->height), scale), zslope);
|
||||
else
|
||||
shadowyscale -= FixedMul(FixedMul(thing->radius*2 / SHORT(patch->height), scalemul), zslope);
|
||||
shadowyscale -= FixedMul(FixedMul(thing->radius*2 / SHORT(patch->height), scale), zslope);
|
||||
|
||||
shadowyscale = abs(shadowyscale);
|
||||
|
||||
|
|
@ -1354,16 +1350,9 @@ static void R_ProjectDropShadow(mobj_t *thing, vissprite_t *vis, fixed_t scale,
|
|||
else
|
||||
shadow->extra_colormap = thing->subsector->sector->extra_colormap;
|
||||
|
||||
shadow->transmap = transtables + (trans<<FF_TRANSSHIFT);
|
||||
shadow->transmap = transtables + ((trans-1) << FF_TRANSSHIFT);
|
||||
|
||||
if (thing->whiteshadow == true)
|
||||
{
|
||||
shadow->colormap = scalelight[LIGHTLEVELS - 1][0]; // full bright!
|
||||
}
|
||||
else
|
||||
{
|
||||
shadow->colormap = scalelight[0][0]; // full dark!
|
||||
}
|
||||
shadow->colormap = colormaps;
|
||||
|
||||
objectsdrawn++;
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue