mirror of
https://github.com/KartKrewDev/RingRacers.git
synced 2026-04-28 04:51:42 +00:00
Move ticcmd generation code from g_game.c to g_build_ticcmd.cpp
This commit is contained in:
parent
b209b321f6
commit
368ffb79b8
3 changed files with 433 additions and 388 deletions
|
|
@ -16,6 +16,7 @@ add_executable(SRB2SDL2 MACOSX_BUNDLE WIN32
|
||||||
z_zone.c
|
z_zone.c
|
||||||
f_finale.c
|
f_finale.c
|
||||||
f_wipe.c
|
f_wipe.c
|
||||||
|
g_build_ticcmd.cpp
|
||||||
g_demo.c
|
g_demo.c
|
||||||
g_game.c
|
g_game.c
|
||||||
g_input.c
|
g_input.c
|
||||||
|
|
|
||||||
432
src/g_build_ticcmd.cpp
Normal file
432
src/g_build_ticcmd.cpp
Normal file
|
|
@ -0,0 +1,432 @@
|
||||||
|
// DR. ROBOTNIK'S RING RACERS
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// Copyright (C) 1993-1996 by id Software, Inc.
|
||||||
|
// Copyright (C) 1998-2000 by DooM Legacy Team.
|
||||||
|
// Copyright (C) 1999-2020 by Sonic Team Junior.
|
||||||
|
// Copyright (C) 2023 by Kart Krew.
|
||||||
|
//
|
||||||
|
// This program is free software distributed under the
|
||||||
|
// terms of the GNU General Public License, version 2.
|
||||||
|
// See the 'LICENSE' file for more details.
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
|
#include <cmath>
|
||||||
|
|
||||||
|
#include "console.h"
|
||||||
|
#include "d_player.h"
|
||||||
|
#include "d_ticcmd.h"
|
||||||
|
#include "doomstat.h"
|
||||||
|
#include "doomtype.h"
|
||||||
|
#include "g_demo.h"
|
||||||
|
#include "g_game.h"
|
||||||
|
#include "g_input.h"
|
||||||
|
#include "g_state.h"
|
||||||
|
#include "g_party.h"
|
||||||
|
#include "hu_stuff.h"
|
||||||
|
#include "i_joy.h"
|
||||||
|
#include "i_system.h"
|
||||||
|
#include "k_bot.h"
|
||||||
|
#include "k_director.h"
|
||||||
|
#include "k_kart.h"
|
||||||
|
#include "k_menu.h"
|
||||||
|
#include "lua_hook.h"
|
||||||
|
#include "m_cheat.h"
|
||||||
|
#include "m_fixed.h"
|
||||||
|
#include "p_local.h"
|
||||||
|
#include "p_mobj.h"
|
||||||
|
#include "p_tick.h"
|
||||||
|
#include "tables.h"
|
||||||
|
|
||||||
|
namespace
|
||||||
|
{
|
||||||
|
|
||||||
|
struct joystickvector2_t
|
||||||
|
{
|
||||||
|
INT32 xaxis;
|
||||||
|
INT32 yaxis;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Take a magnitude of two axes, and adjust it to take out the deadzone
|
||||||
|
// Will return a value between 0 and JOYAXISRANGE
|
||||||
|
INT32 G_BasicDeadZoneCalculation(INT32 magnitude, fixed_t deadZone)
|
||||||
|
{
|
||||||
|
const INT32 jdeadzone = (JOYAXISRANGE * deadZone) / FRACUNIT;
|
||||||
|
INT32 deadzoneAppliedValue = 0;
|
||||||
|
INT32 adjustedMagnitude = std::abs(magnitude);
|
||||||
|
|
||||||
|
if (jdeadzone >= JOYAXISRANGE && adjustedMagnitude >= JOYAXISRANGE) // If the deadzone and magnitude are both 100%...
|
||||||
|
return JOYAXISRANGE; // ...return 100% input directly, to avoid dividing by 0
|
||||||
|
else if (adjustedMagnitude > jdeadzone) // Otherwise, calculate how much the magnitude exceeds the deadzone
|
||||||
|
{
|
||||||
|
adjustedMagnitude = std::min(adjustedMagnitude, JOYAXISRANGE);
|
||||||
|
|
||||||
|
adjustedMagnitude -= jdeadzone;
|
||||||
|
|
||||||
|
deadzoneAppliedValue = (adjustedMagnitude * JOYAXISRANGE) / (JOYAXISRANGE - jdeadzone);
|
||||||
|
}
|
||||||
|
|
||||||
|
return deadzoneAppliedValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get the actual sensible radial value for a joystick axis when accounting for a deadzone
|
||||||
|
void G_HandleAxisDeadZone(UINT8 splitnum, joystickvector2_t *joystickvector)
|
||||||
|
{
|
||||||
|
INT32 gamepadStyle = Joystick[splitnum].bGamepadStyle;
|
||||||
|
fixed_t deadZone = cv_deadzone[splitnum].value;
|
||||||
|
|
||||||
|
// When gamepadstyle is "true" the values are just -1, 0, or 1. This is done in the interface code.
|
||||||
|
if (!gamepadStyle)
|
||||||
|
{
|
||||||
|
// Get the total magnitude of the 2 axes
|
||||||
|
INT32 magnitude = (joystickvector->xaxis * joystickvector->xaxis) + (joystickvector->yaxis * joystickvector->yaxis);
|
||||||
|
INT32 normalisedXAxis;
|
||||||
|
INT32 normalisedYAxis;
|
||||||
|
INT32 normalisedMagnitude;
|
||||||
|
double dMagnitude = std::sqrt((double)magnitude);
|
||||||
|
magnitude = (INT32)dMagnitude;
|
||||||
|
|
||||||
|
// Get the normalised xy values from the magnitude
|
||||||
|
normalisedXAxis = (joystickvector->xaxis * magnitude) / JOYAXISRANGE;
|
||||||
|
normalisedYAxis = (joystickvector->yaxis * magnitude) / JOYAXISRANGE;
|
||||||
|
|
||||||
|
// Apply the deadzone to the magnitude to give a correct value between 0 and JOYAXISRANGE
|
||||||
|
normalisedMagnitude = G_BasicDeadZoneCalculation(magnitude, deadZone);
|
||||||
|
|
||||||
|
// Apply the deadzone to the xy axes
|
||||||
|
joystickvector->xaxis = (normalisedXAxis * normalisedMagnitude) / JOYAXISRANGE;
|
||||||
|
joystickvector->yaxis = (normalisedYAxis * normalisedMagnitude) / JOYAXISRANGE;
|
||||||
|
|
||||||
|
// Cap the values so they don't go above the correct maximum
|
||||||
|
joystickvector->xaxis = std::min(joystickvector->xaxis, JOYAXISRANGE);
|
||||||
|
joystickvector->xaxis = std::max(joystickvector->xaxis, -JOYAXISRANGE);
|
||||||
|
joystickvector->yaxis = std::min(joystickvector->yaxis, JOYAXISRANGE);
|
||||||
|
joystickvector->yaxis = std::max(joystickvector->yaxis, -JOYAXISRANGE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Turning was removed from G_BuildTiccmd to prevent easy client hacking.
|
||||||
|
// This brings back the camera prediction that was lost.
|
||||||
|
void G_DoAnglePrediction(ticcmd_t *cmd, INT32 realtics, UINT8 ssplayer, UINT8 viewnum, player_t *player)
|
||||||
|
{
|
||||||
|
angle_t angleChange = 0;
|
||||||
|
|
||||||
|
// Chasecam stops in these situations, so local cam should stop too.
|
||||||
|
// Otherwise it'll jerk when it resumes.
|
||||||
|
if (player->playerstate == PST_DEAD)
|
||||||
|
return;
|
||||||
|
if (player->mo != NULL && !P_MobjWasRemoved(player->mo) && player->mo->hitlag > 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
while (realtics > 0)
|
||||||
|
{
|
||||||
|
localsteering[ssplayer - 1] = K_UpdateSteeringValue(localsteering[ssplayer - 1], cmd->turning);
|
||||||
|
angleChange = K_GetKartTurnValue(player, localsteering[ssplayer - 1]) << TICCMD_REDUCE;
|
||||||
|
|
||||||
|
realtics--;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
// Left here in case it needs unsealing later. This tried to replicate an old localcam function, but this behavior was unpopular in tests.
|
||||||
|
//if (player->pflags & PF_DRIFTEND)
|
||||||
|
{
|
||||||
|
localangle[ssplayer - 1] = player->mo->angle;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
localangle[viewnum] += angleChange;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}; // namespace
|
||||||
|
|
||||||
|
void G_BuildTiccmd(ticcmd_t *cmd, INT32 realtics, UINT8 ssplayer)
|
||||||
|
{
|
||||||
|
const UINT8 forplayer = ssplayer-1;
|
||||||
|
const UINT8 viewnum = G_PartyPosition(g_localplayers[forplayer]);
|
||||||
|
|
||||||
|
INT32 forward;
|
||||||
|
|
||||||
|
joystickvector2_t joystickvector;
|
||||||
|
|
||||||
|
player_t *player = &players[g_localplayers[forplayer]];
|
||||||
|
//camera_t *thiscam = &camera[forplayer];
|
||||||
|
//boolean *kbl = &keyboard_look[forplayer];
|
||||||
|
//boolean *rd = &resetdown[forplayer];
|
||||||
|
//const boolean mouseaiming = player->spectator;
|
||||||
|
|
||||||
|
if (demo.playback) return;
|
||||||
|
|
||||||
|
// Is there any reason this can't just be I_BaseTiccmd?
|
||||||
|
switch (ssplayer)
|
||||||
|
{
|
||||||
|
case 2:
|
||||||
|
G_CopyTiccmd(cmd, I_BaseTiccmd2(), 1);
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
G_CopyTiccmd(cmd, I_BaseTiccmd3(), 1);
|
||||||
|
break;
|
||||||
|
case 4:
|
||||||
|
G_CopyTiccmd(cmd, I_BaseTiccmd4(), 1);
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
default:
|
||||||
|
G_CopyTiccmd(cmd, I_BaseTiccmd(), 1); // empty, or external driver
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
cmd->angle = localangle[viewnum] >> TICCMD_REDUCE;
|
||||||
|
|
||||||
|
// why build a ticcmd if we're paused?
|
||||||
|
// Or, for that matter, if we're being reborn.
|
||||||
|
if (paused || P_AutoPause() || (gamestate == GS_LEVEL && player->playerstate == PST_REBORN))
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
cmd->flags = 0;
|
||||||
|
|
||||||
|
if (menuactive || chat_on || CON_Ready())
|
||||||
|
{
|
||||||
|
cmd->flags |= TICCMD_TYPING;
|
||||||
|
|
||||||
|
if (hu_keystrokes)
|
||||||
|
{
|
||||||
|
cmd->flags |= TICCMD_KEYSTROKE;
|
||||||
|
}
|
||||||
|
|
||||||
|
goto aftercmdinput;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (G_IsPartyLocal(displayplayers[forplayer]) == false)
|
||||||
|
{
|
||||||
|
if (M_MenuButtonPressed(forplayer, MBT_A))
|
||||||
|
{
|
||||||
|
G_AdjustView(ssplayer, 1, true);
|
||||||
|
K_ToggleDirector(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (M_MenuButtonPressed(forplayer, MBT_X))
|
||||||
|
{
|
||||||
|
G_AdjustView(ssplayer, -1, true);
|
||||||
|
K_ToggleDirector(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (player->spectator == true)
|
||||||
|
{
|
||||||
|
// duplication of fire
|
||||||
|
if (G_PlayerInputDown(forplayer, gc_item, 0))
|
||||||
|
{
|
||||||
|
cmd->buttons |= BT_ATTACK;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (M_MenuButtonPressed(forplayer, MBT_R))
|
||||||
|
{
|
||||||
|
K_ToggleDirector(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
goto aftercmdinput;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (K_PlayerUsesBotMovement(player))
|
||||||
|
{
|
||||||
|
// Bot ticcmd is generated by K_BuildBotTiccmd
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
joystickvector.xaxis = G_PlayerInputAnalog(forplayer, gc_right, 0) - G_PlayerInputAnalog(forplayer, gc_left, 0);
|
||||||
|
joystickvector.yaxis = 0;
|
||||||
|
G_HandleAxisDeadZone(forplayer, &joystickvector);
|
||||||
|
|
||||||
|
// For kart, I've turned the aim axis into a digital axis because we only
|
||||||
|
// use it for aiming to throw items forward/backward and the vote screen
|
||||||
|
// This mean that the turn axis will still be gradient but up/down will be 0
|
||||||
|
// until the stick is pushed far enough
|
||||||
|
joystickvector.yaxis = G_PlayerInputAnalog(forplayer, gc_down, 0) - G_PlayerInputAnalog(forplayer, gc_up, 0);
|
||||||
|
|
||||||
|
if (encoremode)
|
||||||
|
{
|
||||||
|
joystickvector.xaxis = -joystickvector.xaxis;
|
||||||
|
}
|
||||||
|
|
||||||
|
forward = 0;
|
||||||
|
cmd->turning = 0;
|
||||||
|
cmd->aiming = 0;
|
||||||
|
|
||||||
|
if (joystickvector.xaxis != 0)
|
||||||
|
{
|
||||||
|
cmd->turning -= (joystickvector.xaxis * KART_FULLTURN) / JOYAXISRANGE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (player->spectator || objectplacing) // SRB2Kart: spectators need special controls
|
||||||
|
{
|
||||||
|
if (G_PlayerInputDown(forplayer, gc_accel, 0))
|
||||||
|
{
|
||||||
|
cmd->buttons |= BT_ACCELERATE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (G_PlayerInputDown(forplayer, gc_brake, 0))
|
||||||
|
{
|
||||||
|
cmd->buttons |= BT_BRAKE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (G_PlayerInputDown(forplayer, gc_lookback, 0))
|
||||||
|
{
|
||||||
|
cmd->aiming -= joystickvector.yaxis;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (joystickvector.yaxis < 0)
|
||||||
|
{
|
||||||
|
forward += MAXPLMOVE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (joystickvector.yaxis > 0)
|
||||||
|
{
|
||||||
|
forward -= MAXPLMOVE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// forward with key or button // SRB2kart - we use an accel/brake instead of forward/backward.
|
||||||
|
INT32 value = G_PlayerInputAnalog(forplayer, gc_accel, 0);
|
||||||
|
if (value != 0)
|
||||||
|
{
|
||||||
|
cmd->buttons |= BT_ACCELERATE;
|
||||||
|
forward += ((value * MAXPLMOVE) / JOYAXISRANGE);
|
||||||
|
}
|
||||||
|
|
||||||
|
value = G_PlayerInputAnalog(forplayer, gc_brake, 0);
|
||||||
|
if (value != 0)
|
||||||
|
{
|
||||||
|
cmd->buttons |= BT_BRAKE;
|
||||||
|
forward -= ((value * MAXPLMOVE) / JOYAXISRANGE);
|
||||||
|
}
|
||||||
|
|
||||||
|
// But forward/backward IS used for aiming.
|
||||||
|
if (joystickvector.yaxis != 0)
|
||||||
|
{
|
||||||
|
cmd->throwdir -= (joystickvector.yaxis * KART_FULLTURN) / JOYAXISRANGE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// drift
|
||||||
|
if (G_PlayerInputDown(forplayer, gc_drift, 0))
|
||||||
|
{
|
||||||
|
cmd->buttons |= BT_DRIFT;
|
||||||
|
}
|
||||||
|
|
||||||
|
// C
|
||||||
|
if (G_PlayerInputDown(forplayer, gc_spindash, 0))
|
||||||
|
{
|
||||||
|
cmd->buttons |= BT_SPINDASHMASK;
|
||||||
|
}
|
||||||
|
|
||||||
|
// fire
|
||||||
|
if (G_PlayerInputDown(forplayer, gc_item, 0))
|
||||||
|
{
|
||||||
|
cmd->buttons |= BT_ATTACK;
|
||||||
|
}
|
||||||
|
|
||||||
|
// rear view
|
||||||
|
if (G_PlayerInputDown(forplayer, gc_lookback, 0))
|
||||||
|
{
|
||||||
|
cmd->buttons |= BT_LOOKBACK;
|
||||||
|
}
|
||||||
|
|
||||||
|
// respawn
|
||||||
|
if (G_PlayerInputDown(forplayer, gc_respawn, 0))
|
||||||
|
{
|
||||||
|
cmd->buttons |= (BT_RESPAWN | BT_EBRAKEMASK);
|
||||||
|
}
|
||||||
|
|
||||||
|
// mp general function button
|
||||||
|
if (G_PlayerInputDown(forplayer, gc_vote, 0))
|
||||||
|
{
|
||||||
|
cmd->buttons |= BT_VOTE;
|
||||||
|
}
|
||||||
|
|
||||||
|
// lua buttons a thru c
|
||||||
|
if (G_PlayerInputDown(forplayer, gc_luaa, 0)) { cmd->buttons |= BT_LUAA; }
|
||||||
|
if (G_PlayerInputDown(forplayer, gc_luab, 0)) { cmd->buttons |= BT_LUAB; }
|
||||||
|
if (G_PlayerInputDown(forplayer, gc_luac, 0)) { cmd->buttons |= BT_LUAC; }
|
||||||
|
|
||||||
|
// spectator aiming shit, ahhhh...
|
||||||
|
/*
|
||||||
|
{
|
||||||
|
INT32 player_invert = invertmouse ? -1 : 1;
|
||||||
|
INT32 screen_invert =
|
||||||
|
(player->mo && (player->mo->eflags & MFE_VERTICALFLIP)
|
||||||
|
&& (!thiscam->chase)) //because chasecam's not inverted
|
||||||
|
? -1 : 1; // set to -1 or 1 to multiply
|
||||||
|
|
||||||
|
axis = PlayerJoyAxis(ssplayer, AXISLOOK);
|
||||||
|
if (analogjoystickmove && axis != 0 && lookaxis && player->spectator)
|
||||||
|
cmd->aiming += (axis<<16) * screen_invert;
|
||||||
|
|
||||||
|
// spring back if not using keyboard neither mouselookin'
|
||||||
|
if (*kbl == false && !lookaxis && !mouseaiming)
|
||||||
|
cmd->aiming = 0;
|
||||||
|
|
||||||
|
if (player->spectator)
|
||||||
|
{
|
||||||
|
if (PlayerInputDown(ssplayer, gc_lookup) || (gamepadjoystickmove && axis < 0))
|
||||||
|
{
|
||||||
|
cmd->aiming += KB_LOOKSPEED * screen_invert;
|
||||||
|
*kbl = true;
|
||||||
|
}
|
||||||
|
else if (PlayerInputDown(ssplayer, gc_lookdown) || (gamepadjoystickmove && axis > 0))
|
||||||
|
{
|
||||||
|
cmd->aiming -= KB_LOOKSPEED * screen_invert;
|
||||||
|
*kbl = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (PlayerInputDown(ssplayer, gc_centerview)) // No need to put a spectator limit on this one though :V
|
||||||
|
cmd->aiming = 0;
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
cmd->forwardmove += (SINT8)forward;
|
||||||
|
|
||||||
|
aftercmdinput:
|
||||||
|
|
||||||
|
/* Lua: Allow this hook to overwrite ticcmd.
|
||||||
|
We check if we're actually in a level because for some reason this Hook would run in menus and on the titlescreen otherwise.
|
||||||
|
Be aware that within this hook, nothing but this player's cmd can be edited (otherwise we'd run in some pretty bad synching problems since this is clientsided, or something)
|
||||||
|
|
||||||
|
Possible usages for this are:
|
||||||
|
-Forcing the player to perform an action, which could otherwise require terrible, terrible hacking to replicate.
|
||||||
|
-Preventing the player to perform an action, which would ALSO require some weirdo hacks.
|
||||||
|
-Making some galaxy brain autopilot Lua if you're a masochist
|
||||||
|
-Making a Mario Kart 8 Deluxe tier baby mode that steers you away from walls and whatnot. You know what, do what you want!
|
||||||
|
*/
|
||||||
|
if (addedtogame && gamestate == GS_LEVEL)
|
||||||
|
{
|
||||||
|
LUA_HookTiccmd(player, cmd, HOOK(PlayerCmd));
|
||||||
|
|
||||||
|
// Send leveltime when this tic was generated to the server for control lag calculations.
|
||||||
|
// Only do this when in a level. Also do this after the hook, so that it can't overwrite this.
|
||||||
|
cmd->latency = (leveltime & TICCMD_LATENCYMASK);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cmd->forwardmove > MAXPLMOVE)
|
||||||
|
cmd->forwardmove = MAXPLMOVE;
|
||||||
|
else if (cmd->forwardmove < -MAXPLMOVE)
|
||||||
|
cmd->forwardmove = -MAXPLMOVE;
|
||||||
|
|
||||||
|
if (cmd->turning > KART_FULLTURN)
|
||||||
|
cmd->turning = KART_FULLTURN;
|
||||||
|
else if (cmd->turning < -KART_FULLTURN)
|
||||||
|
cmd->turning = -KART_FULLTURN;
|
||||||
|
|
||||||
|
if (cmd->throwdir > KART_FULLTURN)
|
||||||
|
cmd->throwdir = KART_FULLTURN;
|
||||||
|
else if (cmd->throwdir < -KART_FULLTURN)
|
||||||
|
cmd->throwdir = -KART_FULLTURN;
|
||||||
|
|
||||||
|
G_DoAnglePrediction(cmd, realtics, ssplayer, viewnum, player);
|
||||||
|
}
|
||||||
388
src/g_game.c
388
src/g_game.c
|
|
@ -313,12 +313,6 @@ boolean comebackshowninfo; // Have you already seen the "ATTACK OR PROTECT" mess
|
||||||
tic_t curlap; // Current lap time
|
tic_t curlap; // Current lap time
|
||||||
tic_t bestlap; // Best lap time
|
tic_t bestlap; // Best lap time
|
||||||
|
|
||||||
typedef struct joystickvector2_s
|
|
||||||
{
|
|
||||||
INT32 xaxis;
|
|
||||||
INT32 yaxis;
|
|
||||||
} joystickvector2_t;
|
|
||||||
|
|
||||||
boolean precache = true; // if true, load all graphics at start
|
boolean precache = true; // if true, load all graphics at start
|
||||||
|
|
||||||
UINT16 prevmap, nextmap;
|
UINT16 prevmap, nextmap;
|
||||||
|
|
@ -1047,64 +1041,6 @@ boolean G_PlayerInputDown(UINT8 p, INT32 gc, UINT8 menuPlayers)
|
||||||
return (G_PlayerInputAnalog(p, gc, menuPlayers) != 0);
|
return (G_PlayerInputAnalog(p, gc, menuPlayers) != 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Take a magnitude of two axes, and adjust it to take out the deadzone
|
|
||||||
// Will return a value between 0 and JOYAXISRANGE
|
|
||||||
static INT32 G_BasicDeadZoneCalculation(INT32 magnitude, fixed_t deadZone)
|
|
||||||
{
|
|
||||||
const INT32 jdeadzone = (JOYAXISRANGE * deadZone) / FRACUNIT;
|
|
||||||
INT32 deadzoneAppliedValue = 0;
|
|
||||||
INT32 adjustedMagnitude = abs(magnitude);
|
|
||||||
|
|
||||||
if (jdeadzone >= JOYAXISRANGE && adjustedMagnitude >= JOYAXISRANGE) // If the deadzone and magnitude are both 100%...
|
|
||||||
return JOYAXISRANGE; // ...return 100% input directly, to avoid dividing by 0
|
|
||||||
else if (adjustedMagnitude > jdeadzone) // Otherwise, calculate how much the magnitude exceeds the deadzone
|
|
||||||
{
|
|
||||||
adjustedMagnitude = min(adjustedMagnitude, JOYAXISRANGE);
|
|
||||||
|
|
||||||
adjustedMagnitude -= jdeadzone;
|
|
||||||
|
|
||||||
deadzoneAppliedValue = (adjustedMagnitude * JOYAXISRANGE) / (JOYAXISRANGE - jdeadzone);
|
|
||||||
}
|
|
||||||
|
|
||||||
return deadzoneAppliedValue;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get the actual sensible radial value for a joystick axis when accounting for a deadzone
|
|
||||||
static void G_HandleAxisDeadZone(UINT8 splitnum, joystickvector2_t *joystickvector)
|
|
||||||
{
|
|
||||||
INT32 gamepadStyle = Joystick[splitnum].bGamepadStyle;
|
|
||||||
fixed_t deadZone = cv_deadzone[splitnum].value;
|
|
||||||
|
|
||||||
// When gamepadstyle is "true" the values are just -1, 0, or 1. This is done in the interface code.
|
|
||||||
if (!gamepadStyle)
|
|
||||||
{
|
|
||||||
// Get the total magnitude of the 2 axes
|
|
||||||
INT32 magnitude = (joystickvector->xaxis * joystickvector->xaxis) + (joystickvector->yaxis * joystickvector->yaxis);
|
|
||||||
INT32 normalisedXAxis;
|
|
||||||
INT32 normalisedYAxis;
|
|
||||||
INT32 normalisedMagnitude;
|
|
||||||
double dMagnitude = sqrt((double)magnitude);
|
|
||||||
magnitude = (INT32)dMagnitude;
|
|
||||||
|
|
||||||
// Get the normalised xy values from the magnitude
|
|
||||||
normalisedXAxis = (joystickvector->xaxis * magnitude) / JOYAXISRANGE;
|
|
||||||
normalisedYAxis = (joystickvector->yaxis * magnitude) / JOYAXISRANGE;
|
|
||||||
|
|
||||||
// Apply the deadzone to the magnitude to give a correct value between 0 and JOYAXISRANGE
|
|
||||||
normalisedMagnitude = G_BasicDeadZoneCalculation(magnitude, deadZone);
|
|
||||||
|
|
||||||
// Apply the deadzone to the xy axes
|
|
||||||
joystickvector->xaxis = (normalisedXAxis * normalisedMagnitude) / JOYAXISRANGE;
|
|
||||||
joystickvector->yaxis = (normalisedYAxis * normalisedMagnitude) / JOYAXISRANGE;
|
|
||||||
|
|
||||||
// Cap the values so they don't go above the correct maximum
|
|
||||||
joystickvector->xaxis = min(joystickvector->xaxis, JOYAXISRANGE);
|
|
||||||
joystickvector->xaxis = max(joystickvector->xaxis, -JOYAXISRANGE);
|
|
||||||
joystickvector->yaxis = min(joystickvector->yaxis, JOYAXISRANGE);
|
|
||||||
joystickvector->yaxis = max(joystickvector->yaxis, -JOYAXISRANGE);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
//
|
||||||
// G_BuildTiccmd
|
// G_BuildTiccmd
|
||||||
// Builds a ticcmd from all of the available inputs
|
// Builds a ticcmd from all of the available inputs
|
||||||
|
|
@ -1118,330 +1054,6 @@ angle_t localangle[MAXSPLITSCREENPLAYERS];
|
||||||
|
|
||||||
INT32 localsteering[MAXSPLITSCREENPLAYERS];
|
INT32 localsteering[MAXSPLITSCREENPLAYERS];
|
||||||
|
|
||||||
// Turning was removed from G_BuildTiccmd to prevent easy client hacking.
|
|
||||||
// This brings back the camera prediction that was lost.
|
|
||||||
static void G_DoAnglePrediction(ticcmd_t *cmd, INT32 realtics, UINT8 ssplayer, UINT8 viewnum, player_t *player)
|
|
||||||
{
|
|
||||||
angle_t angleChange = 0;
|
|
||||||
|
|
||||||
// Chasecam stops in these situations, so local cam should stop too.
|
|
||||||
// Otherwise it'll jerk when it resumes.
|
|
||||||
if (player->playerstate == PST_DEAD)
|
|
||||||
return;
|
|
||||||
if (player->mo != NULL && !P_MobjWasRemoved(player->mo) && player->mo->hitlag > 0)
|
|
||||||
return;
|
|
||||||
|
|
||||||
while (realtics > 0)
|
|
||||||
{
|
|
||||||
localsteering[ssplayer - 1] = K_UpdateSteeringValue(localsteering[ssplayer - 1], cmd->turning);
|
|
||||||
angleChange = K_GetKartTurnValue(player, localsteering[ssplayer - 1]) << TICCMD_REDUCE;
|
|
||||||
|
|
||||||
realtics--;
|
|
||||||
}
|
|
||||||
|
|
||||||
#if 0
|
|
||||||
// Left here in case it needs unsealing later. This tried to replicate an old localcam function, but this behavior was unpopular in tests.
|
|
||||||
//if (player->pflags & PF_DRIFTEND)
|
|
||||||
{
|
|
||||||
localangle[ssplayer - 1] = player->mo->angle;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
#endif
|
|
||||||
{
|
|
||||||
localangle[viewnum] += angleChange;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void G_BuildTiccmd(ticcmd_t *cmd, INT32 realtics, UINT8 ssplayer)
|
|
||||||
{
|
|
||||||
const UINT8 forplayer = ssplayer-1;
|
|
||||||
const UINT8 viewnum = G_PartyPosition(g_localplayers[forplayer]);
|
|
||||||
|
|
||||||
INT32 forward;
|
|
||||||
|
|
||||||
joystickvector2_t joystickvector;
|
|
||||||
|
|
||||||
player_t *player = &players[g_localplayers[forplayer]];
|
|
||||||
//camera_t *thiscam = &camera[forplayer];
|
|
||||||
//boolean *kbl = &keyboard_look[forplayer];
|
|
||||||
//boolean *rd = &resetdown[forplayer];
|
|
||||||
//const boolean mouseaiming = player->spectator;
|
|
||||||
|
|
||||||
if (demo.playback) return;
|
|
||||||
|
|
||||||
// Is there any reason this can't just be I_BaseTiccmd?
|
|
||||||
switch (ssplayer)
|
|
||||||
{
|
|
||||||
case 2:
|
|
||||||
G_CopyTiccmd(cmd, I_BaseTiccmd2(), 1);
|
|
||||||
break;
|
|
||||||
case 3:
|
|
||||||
G_CopyTiccmd(cmd, I_BaseTiccmd3(), 1);
|
|
||||||
break;
|
|
||||||
case 4:
|
|
||||||
G_CopyTiccmd(cmd, I_BaseTiccmd4(), 1);
|
|
||||||
break;
|
|
||||||
case 1:
|
|
||||||
default:
|
|
||||||
G_CopyTiccmd(cmd, I_BaseTiccmd(), 1); // empty, or external driver
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
cmd->angle = localangle[viewnum] >> TICCMD_REDUCE;
|
|
||||||
|
|
||||||
// why build a ticcmd if we're paused?
|
|
||||||
// Or, for that matter, if we're being reborn.
|
|
||||||
if (paused || P_AutoPause() || (gamestate == GS_LEVEL && player->playerstate == PST_REBORN))
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
cmd->flags = 0;
|
|
||||||
|
|
||||||
if (menuactive || chat_on || CON_Ready())
|
|
||||||
{
|
|
||||||
cmd->flags |= TICCMD_TYPING;
|
|
||||||
|
|
||||||
if (hu_keystrokes)
|
|
||||||
{
|
|
||||||
cmd->flags |= TICCMD_KEYSTROKE;
|
|
||||||
}
|
|
||||||
|
|
||||||
goto aftercmdinput;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (G_IsPartyLocal(displayplayers[forplayer]) == false)
|
|
||||||
{
|
|
||||||
if (M_MenuButtonPressed(forplayer, MBT_A))
|
|
||||||
{
|
|
||||||
G_AdjustView(ssplayer, 1, true);
|
|
||||||
K_ToggleDirector(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (M_MenuButtonPressed(forplayer, MBT_X))
|
|
||||||
{
|
|
||||||
G_AdjustView(ssplayer, -1, true);
|
|
||||||
K_ToggleDirector(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (player->spectator == true)
|
|
||||||
{
|
|
||||||
// duplication of fire
|
|
||||||
if (G_PlayerInputDown(forplayer, gc_item, 0))
|
|
||||||
{
|
|
||||||
cmd->buttons |= BT_ATTACK;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (M_MenuButtonPressed(forplayer, MBT_R))
|
|
||||||
{
|
|
||||||
K_ToggleDirector(true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
goto aftercmdinput;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (K_PlayerUsesBotMovement(player))
|
|
||||||
{
|
|
||||||
// Bot ticcmd is generated by K_BuildBotTiccmd
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
joystickvector.xaxis = G_PlayerInputAnalog(forplayer, gc_right, 0) - G_PlayerInputAnalog(forplayer, gc_left, 0);
|
|
||||||
joystickvector.yaxis = 0;
|
|
||||||
G_HandleAxisDeadZone(forplayer, &joystickvector);
|
|
||||||
|
|
||||||
// For kart, I've turned the aim axis into a digital axis because we only
|
|
||||||
// use it for aiming to throw items forward/backward and the vote screen
|
|
||||||
// This mean that the turn axis will still be gradient but up/down will be 0
|
|
||||||
// until the stick is pushed far enough
|
|
||||||
joystickvector.yaxis = G_PlayerInputAnalog(forplayer, gc_down, 0) - G_PlayerInputAnalog(forplayer, gc_up, 0);
|
|
||||||
|
|
||||||
if (encoremode)
|
|
||||||
{
|
|
||||||
joystickvector.xaxis = -joystickvector.xaxis;
|
|
||||||
}
|
|
||||||
|
|
||||||
forward = 0;
|
|
||||||
cmd->turning = 0;
|
|
||||||
cmd->aiming = 0;
|
|
||||||
|
|
||||||
if (joystickvector.xaxis != 0)
|
|
||||||
{
|
|
||||||
cmd->turning -= (joystickvector.xaxis * KART_FULLTURN) / JOYAXISRANGE;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (player->spectator || objectplacing) // SRB2Kart: spectators need special controls
|
|
||||||
{
|
|
||||||
if (G_PlayerInputDown(forplayer, gc_accel, 0))
|
|
||||||
{
|
|
||||||
cmd->buttons |= BT_ACCELERATE;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (G_PlayerInputDown(forplayer, gc_brake, 0))
|
|
||||||
{
|
|
||||||
cmd->buttons |= BT_BRAKE;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (G_PlayerInputDown(forplayer, gc_lookback, 0))
|
|
||||||
{
|
|
||||||
cmd->aiming -= joystickvector.yaxis;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (joystickvector.yaxis < 0)
|
|
||||||
{
|
|
||||||
forward += MAXPLMOVE;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (joystickvector.yaxis > 0)
|
|
||||||
{
|
|
||||||
forward -= MAXPLMOVE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// forward with key or button // SRB2kart - we use an accel/brake instead of forward/backward.
|
|
||||||
INT32 value = G_PlayerInputAnalog(forplayer, gc_accel, 0);
|
|
||||||
if (value != 0)
|
|
||||||
{
|
|
||||||
cmd->buttons |= BT_ACCELERATE;
|
|
||||||
forward += ((value * MAXPLMOVE) / JOYAXISRANGE);
|
|
||||||
}
|
|
||||||
|
|
||||||
value = G_PlayerInputAnalog(forplayer, gc_brake, 0);
|
|
||||||
if (value != 0)
|
|
||||||
{
|
|
||||||
cmd->buttons |= BT_BRAKE;
|
|
||||||
forward -= ((value * MAXPLMOVE) / JOYAXISRANGE);
|
|
||||||
}
|
|
||||||
|
|
||||||
// But forward/backward IS used for aiming.
|
|
||||||
if (joystickvector.yaxis != 0)
|
|
||||||
{
|
|
||||||
cmd->throwdir -= (joystickvector.yaxis * KART_FULLTURN) / JOYAXISRANGE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// drift
|
|
||||||
if (G_PlayerInputDown(forplayer, gc_drift, 0))
|
|
||||||
{
|
|
||||||
cmd->buttons |= BT_DRIFT;
|
|
||||||
}
|
|
||||||
|
|
||||||
// C
|
|
||||||
if (G_PlayerInputDown(forplayer, gc_spindash, 0))
|
|
||||||
{
|
|
||||||
cmd->buttons |= BT_SPINDASHMASK;
|
|
||||||
}
|
|
||||||
|
|
||||||
// fire
|
|
||||||
if (G_PlayerInputDown(forplayer, gc_item, 0))
|
|
||||||
{
|
|
||||||
cmd->buttons |= BT_ATTACK;
|
|
||||||
}
|
|
||||||
|
|
||||||
// rear view
|
|
||||||
if (G_PlayerInputDown(forplayer, gc_lookback, 0))
|
|
||||||
{
|
|
||||||
cmd->buttons |= BT_LOOKBACK;
|
|
||||||
}
|
|
||||||
|
|
||||||
// respawn
|
|
||||||
if (G_PlayerInputDown(forplayer, gc_respawn, 0))
|
|
||||||
{
|
|
||||||
cmd->buttons |= (BT_RESPAWN | BT_EBRAKEMASK);
|
|
||||||
}
|
|
||||||
|
|
||||||
// mp general function button
|
|
||||||
if (G_PlayerInputDown(forplayer, gc_vote, 0))
|
|
||||||
{
|
|
||||||
cmd->buttons |= BT_VOTE;
|
|
||||||
}
|
|
||||||
|
|
||||||
// lua buttons a thru c
|
|
||||||
if (G_PlayerInputDown(forplayer, gc_luaa, 0)) { cmd->buttons |= BT_LUAA; }
|
|
||||||
if (G_PlayerInputDown(forplayer, gc_luab, 0)) { cmd->buttons |= BT_LUAB; }
|
|
||||||
if (G_PlayerInputDown(forplayer, gc_luac, 0)) { cmd->buttons |= BT_LUAC; }
|
|
||||||
|
|
||||||
// spectator aiming shit, ahhhh...
|
|
||||||
/*
|
|
||||||
{
|
|
||||||
INT32 player_invert = invertmouse ? -1 : 1;
|
|
||||||
INT32 screen_invert =
|
|
||||||
(player->mo && (player->mo->eflags & MFE_VERTICALFLIP)
|
|
||||||
&& (!thiscam->chase)) //because chasecam's not inverted
|
|
||||||
? -1 : 1; // set to -1 or 1 to multiply
|
|
||||||
|
|
||||||
axis = PlayerJoyAxis(ssplayer, AXISLOOK);
|
|
||||||
if (analogjoystickmove && axis != 0 && lookaxis && player->spectator)
|
|
||||||
cmd->aiming += (axis<<16) * screen_invert;
|
|
||||||
|
|
||||||
// spring back if not using keyboard neither mouselookin'
|
|
||||||
if (*kbl == false && !lookaxis && !mouseaiming)
|
|
||||||
cmd->aiming = 0;
|
|
||||||
|
|
||||||
if (player->spectator)
|
|
||||||
{
|
|
||||||
if (PlayerInputDown(ssplayer, gc_lookup) || (gamepadjoystickmove && axis < 0))
|
|
||||||
{
|
|
||||||
cmd->aiming += KB_LOOKSPEED * screen_invert;
|
|
||||||
*kbl = true;
|
|
||||||
}
|
|
||||||
else if (PlayerInputDown(ssplayer, gc_lookdown) || (gamepadjoystickmove && axis > 0))
|
|
||||||
{
|
|
||||||
cmd->aiming -= KB_LOOKSPEED * screen_invert;
|
|
||||||
*kbl = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (PlayerInputDown(ssplayer, gc_centerview)) // No need to put a spectator limit on this one though :V
|
|
||||||
cmd->aiming = 0;
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
cmd->forwardmove += (SINT8)forward;
|
|
||||||
|
|
||||||
aftercmdinput:
|
|
||||||
|
|
||||||
/* Lua: Allow this hook to overwrite ticcmd.
|
|
||||||
We check if we're actually in a level because for some reason this Hook would run in menus and on the titlescreen otherwise.
|
|
||||||
Be aware that within this hook, nothing but this player's cmd can be edited (otherwise we'd run in some pretty bad synching problems since this is clientsided, or something)
|
|
||||||
|
|
||||||
Possible usages for this are:
|
|
||||||
-Forcing the player to perform an action, which could otherwise require terrible, terrible hacking to replicate.
|
|
||||||
-Preventing the player to perform an action, which would ALSO require some weirdo hacks.
|
|
||||||
-Making some galaxy brain autopilot Lua if you're a masochist
|
|
||||||
-Making a Mario Kart 8 Deluxe tier baby mode that steers you away from walls and whatnot. You know what, do what you want!
|
|
||||||
*/
|
|
||||||
if (addedtogame && gamestate == GS_LEVEL)
|
|
||||||
{
|
|
||||||
LUA_HookTiccmd(player, cmd, HOOK(PlayerCmd));
|
|
||||||
|
|
||||||
// Send leveltime when this tic was generated to the server for control lag calculations.
|
|
||||||
// Only do this when in a level. Also do this after the hook, so that it can't overwrite this.
|
|
||||||
cmd->latency = (leveltime & TICCMD_LATENCYMASK);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (cmd->forwardmove > MAXPLMOVE)
|
|
||||||
cmd->forwardmove = MAXPLMOVE;
|
|
||||||
else if (cmd->forwardmove < -MAXPLMOVE)
|
|
||||||
cmd->forwardmove = -MAXPLMOVE;
|
|
||||||
|
|
||||||
if (cmd->turning > KART_FULLTURN)
|
|
||||||
cmd->turning = KART_FULLTURN;
|
|
||||||
else if (cmd->turning < -KART_FULLTURN)
|
|
||||||
cmd->turning = -KART_FULLTURN;
|
|
||||||
|
|
||||||
if (cmd->throwdir > KART_FULLTURN)
|
|
||||||
cmd->throwdir = KART_FULLTURN;
|
|
||||||
else if (cmd->throwdir < -KART_FULLTURN)
|
|
||||||
cmd->throwdir = -KART_FULLTURN;
|
|
||||||
|
|
||||||
G_DoAnglePrediction(cmd, realtics, ssplayer, viewnum, player);
|
|
||||||
}
|
|
||||||
|
|
||||||
ticcmd_t *G_CopyTiccmd(ticcmd_t* dest, const ticcmd_t* src, const size_t n)
|
ticcmd_t *G_CopyTiccmd(ticcmd_t* dest, const ticcmd_t* src, const size_t n)
|
||||||
{
|
{
|
||||||
return M_Memcpy(dest, src, n*sizeof(*src));
|
return M_Memcpy(dest, src, n*sizeof(*src));
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue