Compare commits

..

3 commits

Author SHA1 Message Date
Sergei Shubin
41d0815f42 gitignore update 2026-03-20 17:25:54 +08:00
53dae1453a Build system fixes, rename to quake3live, disable hw gamma
- Rename output binary to quake3live.exe (all configurations)
- Set TargetName in vcxproj to match OutputFile for AfterBuild copy
- Default fs_game to "missionpack" in FS_Startup
- Add AfterBuild copy for ui project to workdir/missionpack
- Enable q3_ui build for non-TA configs only (TA uses ui project)
- Guard hardware gamma with ENABLE_HW_GAMMA macro (disabled by default)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-20 13:20:42 +08:00
ba2dbb803e Implant QL pmove system into Q3 Team Arena
Replace Q3TA player movement with Quake Live's pmove system,
decompiled from qagamex64.so via Ghidra MCP.

Struct changes:
- playerState_t: +12 bytes (field_08c, field_094, field_09c,
  lastJumpTime, jumped, crouchSlideTimer, forwardmove/rightmove/upmove)
- usercmd_t: +4 bytes (field_15, field_16 between weapon and forwardmove)
- pmove_t: +16 bytes (field_0dc/0e0/0e4/0f8, removed framecount)
- pml_t: +12 bytes (isJumppad, wallContact, isStepJump)
- pm_flags: remapped to QL values (21 flags, several moved/new)

New physics systems:
- Dual VQ3/PQL physics (PMF_PROMODE)
- Double jump, crouch slide, chain/ramp/step jump
- Wall contact movement, grapple hook physics
- 34 server-tunable pmove_* cvars with cgame prediction sync

Network protocol updated for new struct fields and usercmd bytes.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-20 02:57:53 +08:00
16 changed files with 4631 additions and 3692 deletions

25
.gitignore vendored
View file

@ -6,6 +6,9 @@
*.ncb *.ncb
*.sdf *.sdf
*.opensdf *.opensdf
*.pdb
*.ilk
*.exp
*.idb *.idb
UpgradeLog*.htm UpgradeLog*.htm
_UpgradeReport_Files/ _UpgradeReport_Files/
@ -13,15 +16,10 @@ Backup/
# Build output directories # Build output directories
Debug/ Debug/
Debug_TA/
Debug TA/
Release/ Release/
Release_TA/ Release_TA/
Release TA/
x64/ x64/
*___Win32_*/ *___Win32_*/
ReleaseAXP/
DebugAxp/
# Intermediate build files # Intermediate build files
*.obj *.obj
@ -29,9 +27,18 @@ DebugAxp/
*.res *.res
*.sbr *.sbr
*.bsc *.bsc
*.pdb
*.ilk
*.exp
# Working directory (game runtime + copied build outputs) # Compiled outputs
*.exe
*.dll
*.lib
*.map
# Working directory (build outputs + game data)
workdir/ workdir/
code/botlib/Debug_TA
code/cgame/Debug_TA
code/Debug_TA
code/ui/Debug_TA
code/game/Debug_TA
code/renderer/Debug_TA

View file

@ -1156,6 +1156,40 @@ extern vmCvar_t cg_smoothClients;
extern vmCvar_t pmove_fixed; extern vmCvar_t pmove_fixed;
extern vmCvar_t pmove_msec; extern vmCvar_t pmove_msec;
//extern vmCvar_t cg_pmove_fixed; //extern vmCvar_t cg_pmove_fixed;
extern vmCvar_t pmove_JumpVelocity;
extern vmCvar_t pmove_JumpVelocityMax;
extern vmCvar_t pmove_JumpVelocityScaleAdd;
extern vmCvar_t pmove_JumpVelocityTimeThreshold;
extern vmCvar_t pmove_JumpVelocityTimeThresholdOffset;
extern vmCvar_t pmove_JumpTimeDeltaMin;
extern vmCvar_t pmove_ChainJump;
extern vmCvar_t pmove_ChainJumpVelocity;
extern vmCvar_t pmove_StepJumpVelocity;
extern vmCvar_t pmove_RampJumpScale;
extern vmCvar_t pmove_StepHeight;
extern vmCvar_t pmove_WalkAccel;
extern vmCvar_t pmove_WalkFriction;
extern vmCvar_t pmove_StrafeAccel;
extern vmCvar_t pmove_CircleStrafeFriction;
extern vmCvar_t pmove_CrouchSlideFriction;
extern vmCvar_t pmove_CrouchSlideTime;
extern vmCvar_t pmove_WaterSwimScale;
extern vmCvar_t pmove_WaterWadeScale;
extern vmCvar_t pmove_WeaponDropTime;
extern vmCvar_t pmove_WeaponRaiseTime;
extern vmCvar_t pmove_WishSpeed;
extern vmCvar_t pmove_AirSteps;
extern vmCvar_t pmove_AirAccel;
extern vmCvar_t pmove_AirStopAccel;
extern vmCvar_t pmove_AirControl;
extern vmCvar_t pmove_AutoHop;
extern vmCvar_t pmove_BunnyHop;
extern vmCvar_t pmove_StepJump;
extern vmCvar_t pmove_CrouchStepJump;
extern vmCvar_t pmove_RampJump;
extern vmCvar_t pmove_DoubleJump;
extern vmCvar_t pmove_CrouchSlide;
extern vmCvar_t pmove_noPlayerClip;
extern vmCvar_t cg_cameraOrbit; extern vmCvar_t cg_cameraOrbit;
extern vmCvar_t cg_cameraOrbitDelay; extern vmCvar_t cg_cameraOrbitDelay;
extern vmCvar_t cg_timescaleFadeEnd; extern vmCvar_t cg_timescaleFadeEnd;

View file

@ -168,6 +168,42 @@ vmCvar_t pmove_fixed;
//vmCvar_t cg_pmove_fixed; //vmCvar_t cg_pmove_fixed;
vmCvar_t pmove_msec; vmCvar_t pmove_msec;
vmCvar_t cg_pmove_msec; vmCvar_t cg_pmove_msec;
// QL pmove cvars (synced from server)
vmCvar_t pmove_JumpVelocity;
vmCvar_t pmove_JumpVelocityMax;
vmCvar_t pmove_JumpVelocityScaleAdd;
vmCvar_t pmove_JumpVelocityTimeThreshold;
vmCvar_t pmove_JumpVelocityTimeThresholdOffset;
vmCvar_t pmove_JumpTimeDeltaMin;
vmCvar_t pmove_ChainJump;
vmCvar_t pmove_ChainJumpVelocity;
vmCvar_t pmove_StepJumpVelocity;
vmCvar_t pmove_RampJumpScale;
vmCvar_t pmove_StepHeight;
vmCvar_t pmove_WalkAccel;
vmCvar_t pmove_WalkFriction;
vmCvar_t pmove_StrafeAccel;
vmCvar_t pmove_CircleStrafeFriction;
vmCvar_t pmove_CrouchSlideFriction;
vmCvar_t pmove_CrouchSlideTime;
vmCvar_t pmove_WaterSwimScale;
vmCvar_t pmove_WaterWadeScale;
vmCvar_t pmove_WeaponDropTime;
vmCvar_t pmove_WeaponRaiseTime;
vmCvar_t pmove_WishSpeed;
vmCvar_t pmove_AirSteps;
vmCvar_t pmove_AirAccel;
vmCvar_t pmove_AirStopAccel;
vmCvar_t pmove_AirControl;
vmCvar_t pmove_AutoHop;
vmCvar_t pmove_BunnyHop;
vmCvar_t pmove_StepJump;
vmCvar_t pmove_CrouchStepJump;
vmCvar_t pmove_RampJump;
vmCvar_t pmove_DoubleJump;
vmCvar_t pmove_CrouchSlide;
vmCvar_t pmove_noPlayerClip;
vmCvar_t cg_cameraMode; vmCvar_t cg_cameraMode;
vmCvar_t cg_cameraOrbit; vmCvar_t cg_cameraOrbit;
vmCvar_t cg_cameraOrbitDelay; vmCvar_t cg_cameraOrbitDelay;
@ -307,6 +343,41 @@ static cvarTable_t cvarTable[] = { // bk001129
{ &pmove_fixed, "pmove_fixed", "0", 0}, { &pmove_fixed, "pmove_fixed", "0", 0},
{ &pmove_msec, "pmove_msec", "8", 0}, { &pmove_msec, "pmove_msec", "8", 0},
// QL pmove cvars
{ &pmove_JumpVelocity, "pmove_JumpVelocity", "270", 0 },
{ &pmove_JumpVelocityMax, "pmove_JumpVelocityMax", "700", 0 },
{ &pmove_JumpVelocityScaleAdd, "pmove_JumpVelocityScaleAdd", "0", 0 },
{ &pmove_JumpVelocityTimeThreshold, "pmove_JumpVelocityTimeThreshold", "500", 0 },
{ &pmove_JumpVelocityTimeThresholdOffset, "pmove_JumpVelocityTimeThresholdOffset", "0.5", 0 },
{ &pmove_JumpTimeDeltaMin, "pmove_JumpTimeDeltaMin", "100", 0 },
{ &pmove_ChainJump, "pmove_ChainJump", "1", 0 },
{ &pmove_ChainJumpVelocity, "pmove_ChainJumpVelocity", "110", 0 },
{ &pmove_StepJumpVelocity, "pmove_StepJumpVelocity", "48", 0 },
{ &pmove_RampJumpScale, "pmove_RampJumpScale", "1", 0 },
{ &pmove_StepHeight, "pmove_StepHeight", "22", 0 },
{ &pmove_WalkAccel, "pmove_WalkAccel", "10", 0 },
{ &pmove_WalkFriction, "pmove_WalkFriction", "6", 0 },
{ &pmove_StrafeAccel, "pmove_StrafeAccel", "1", 0 },
{ &pmove_CircleStrafeFriction, "pmove_CircleStrafeFriction", "6", 0 },
{ &pmove_CrouchSlideFriction, "pmove_CrouchSlideFriction", "0.5", 0 },
{ &pmove_CrouchSlideTime, "pmove_CrouchSlideTime", "2", 0 },
{ &pmove_WaterSwimScale, "pmove_WaterSwimScale", "0.5", 0 },
{ &pmove_WaterWadeScale, "pmove_WaterWadeScale", "0.7", 0 },
{ &pmove_WeaponDropTime, "pmove_WeaponDropTime", "200", 0 },
{ &pmove_WeaponRaiseTime, "pmove_WeaponRaiseTime", "250", 0 },
{ &pmove_WishSpeed, "pmove_WishSpeed", "400", 0 },
{ &pmove_AirSteps, "pmove_AirSteps", "1", 0 },
{ &pmove_AirAccel, "pmove_AirAccel", "1", 0 },
{ &pmove_AirStopAccel, "pmove_AirStopAccel", "1", 0 },
{ &pmove_AirControl, "pmove_AirControl", "0", 0 },
{ &pmove_AutoHop, "pmove_AutoHop", "1", 0 },
{ &pmove_BunnyHop, "pmove_BunnyHop", "1", 0 },
{ &pmove_StepJump, "pmove_StepJump", "1", 0 },
{ &pmove_CrouchStepJump, "pmove_CrouchStepJump", "1", 0 },
{ &pmove_RampJump, "pmove_RampJump", "0", 0 },
{ &pmove_DoubleJump, "pmove_DoubleJump", "1", 0 },
{ &pmove_CrouchSlide, "pmove_CrouchSlide", "0", 0 },
{ &pmove_noPlayerClip, "pmove_noPlayerClip", "0", 0 },
{ &cg_noTaunt, "cg_noTaunt", "0", CVAR_ARCHIVE}, { &cg_noTaunt, "cg_noTaunt", "0", CVAR_ARCHIVE},
{ &cg_noProjectileTrail, "cg_noProjectileTrail", "0", CVAR_ARCHIVE}, { &cg_noProjectileTrail, "cg_noProjectileTrail", "0", CVAR_ARCHIVE},
{ &cg_smallFont, "ui_smallFont", "0.25", CVAR_ARCHIVE}, { &cg_smallFont, "ui_smallFont", "0.25", CVAR_ARCHIVE},

View file

@ -26,6 +26,7 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
// It also handles local physics interaction, like fragments bouncing off walls // It also handles local physics interaction, like fragments bouncing off walls
#include "cg_local.h" #include "cg_local.h"
#include "../game/bg_local.h"
static pmove_t cg_pmove; static pmove_t cg_pmove;
@ -499,6 +500,42 @@ void CG_PredictPlayerState( void ) {
cg_pmove.pmove_fixed = pmove_fixed.integer;// | cg_pmove_fixed.integer; cg_pmove.pmove_fixed = pmove_fixed.integer;// | cg_pmove_fixed.integer;
cg_pmove.pmove_msec = pmove_msec.integer; cg_pmove.pmove_msec = pmove_msec.integer;
// sync QL pmove globals for client prediction
pm_jumpVelocity = pmove_JumpVelocity.value;
pm_jumpVelocityMax = pmove_JumpVelocityMax.value;
pm_jumpVelocityScaleAdd = pmove_JumpVelocityScaleAdd.value;
pm_jumpVelocityTimeThreshold = pmove_JumpVelocityTimeThreshold.value;
pm_jumpVelocityTimeThresholdOffset = pmove_JumpVelocityTimeThresholdOffset.value;
pm_jumpTimeDeltaMin = pmove_JumpTimeDeltaMin.value;
pm_chainJump = pmove_ChainJump.integer;
pm_chainJumpVelocity = pmove_ChainJumpVelocity.value;
pm_stepJumpVelocity = pmove_StepJumpVelocity.value;
pm_rampJumpScale = pmove_RampJumpScale.value;
pm_stepHeight = pmove_StepHeight.value;
pm_walkAccel = pmove_WalkAccel.value;
pm_walkFriction = pmove_WalkFriction.value;
pm_strafeAccel = pmove_StrafeAccel.value;
pm_circleStrafeFriction = pmove_CircleStrafeFriction.value;
pm_crouchSlideFriction = pmove_CrouchSlideFriction.value;
pm_crouchSlideTime = pmove_CrouchSlideTime.integer;
pm_waterSwimScale = pmove_WaterSwimScale.value;
pm_waterWadeScale = pmove_WaterWadeScale.value;
pm_weaponDropTime = pmove_WeaponDropTime.integer;
pm_weaponRaiseTime = pmove_WeaponRaiseTime.integer;
pm_wishSpeed = pmove_WishSpeed.value;
pm_airSteps = pmove_AirSteps.integer;
pm_airAccel = pmove_AirAccel.value;
pm_airStopAccel = pmove_AirStopAccel.value;
pm_airControl = pmove_AirControl.value;
pm_autoHopEnabled = pmove_AutoHop.integer;
pm_bunnyHop = pmove_BunnyHop.integer;
pm_stepJumpEnabled = pmove_StepJump.integer;
pm_crouchStepJump = pmove_CrouchStepJump.integer;
pm_rampJumpEnabled = pmove_RampJump.integer;
pm_noPlayerClip = pmove_noPlayerClip.integer;
pmove_rampJumpFlag = pmove_RampJump.integer;
pmove_stepJumpFlag = pmove_StepJump.integer;
// run cmds // run cmds
moved = qfalse; moved = qfalse;
for ( cmdNum = current - CMD_BACKUP + 1 ; cmdNum <= current ; cmdNum++ ) { for ( cmdNum = current - CMD_BACKUP + 1 ; cmdNum <= current ; cmdNum++ ) {

View file

@ -1,83 +1,159 @@
/* /*
=========================================================================== ===========================================================================
Copyright (C) 1999-2005 Id Software, Inc. Copyright (C) 1999-2005 Id Software, Inc.
This file is part of Quake III Arena source code. This file is part of Quake III Arena source code.
Quake III Arena source code is free software; you can redistribute it Quake III Arena source code is free software; you can redistribute it
and/or modify it under the terms of the GNU General Public License as and/or modify it under the terms of the GNU General Public License as
published by the Free Software Foundation; either version 2 of the License, published by the Free Software Foundation; either version 2 of the License,
or (at your option) any later version. or (at your option) any later version.
Quake III Arena source code is distributed in the hope that it will be Quake III Arena source code is distributed in the hope that it will be
useful, but WITHOUT ANY WARRANTY; without even the implied warranty of useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details. GNU General Public License for more details.
You should have received a copy of the GNU General Public License You should have received a copy of the GNU General Public License
along with Foobar; if not, write to the Free Software along with Foobar; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
=========================================================================== ===========================================================================
*/ */
// //
// bg_local.h -- local definitions for the bg (both games) files // bg_local.h -- local definitions for the bg (both games) files
#define MIN_WALK_NORMAL 0.7f // can't walk on very steep slopes #define MIN_WALK_NORMAL 0.7f // can't walk on very steep slopes
#define STEPSIZE 18 #define STEPSIZE 18
#define JUMP_VELOCITY 270 #define JUMP_VELOCITY 270
#define TIMER_LAND 130 #define TIMER_LAND 130
#define TIMER_GESTURE (34*66+50) #define TIMER_GESTURE (34*66+50)
#define OVERCLIP 1.001f #define OVERCLIP 1.001f
// all of the locals will be zeroed before each // all of the locals will be zeroed before each
// pmove, just to make damn sure we don't have // pmove, just to make damn sure we don't have
// any differences when running on client or server // any differences when running on client or server
typedef struct { typedef struct {
vec3_t forward, right, up; vec3_t forward, right, up;
float frametime; float frametime;
int msec; int msec;
qboolean walking; qboolean walking;
qboolean groundPlane; qboolean groundPlane;
trace_t groundTrace; trace_t groundTrace;
float impactSpeed; // QL additions between groundTrace and impactSpeed
int isJumppad; // set during crouch step jump
vec3_t previous_origin; int wallContact; // PM_CheckWallContact result
vec3_t previous_velocity; int isStepJump; // set during normal step jump
int previous_waterlevel;
} pml_t; float impactSpeed;
extern pmove_t *pm; vec3_t previous_origin;
extern pml_t pml; vec3_t previous_velocity;
int previous_waterlevel;
// movement parameters } pml_t;
extern float pm_stopspeed;
extern float pm_duckScale; extern pmove_t *pm;
extern float pm_swimScale; extern pml_t pml;
extern float pm_wadeScale;
// movement parameters
extern float pm_accelerate; extern float pm_stopspeed;
extern float pm_airaccelerate; extern float pm_duckScale;
extern float pm_wateraccelerate; extern float pm_swimScale;
extern float pm_flyaccelerate; extern float pm_wadeScale;
extern float pm_friction; extern float pm_accelerate;
extern float pm_waterfriction; extern float pm_airaccelerate;
extern float pm_flightfriction; extern float pm_wateraccelerate;
extern float pm_flyaccelerate;
extern int c_pmove;
extern float pm_friction;
void PM_ClipVelocity( vec3_t in, vec3_t normal, vec3_t out, float overbounce ); extern float pm_waterfriction;
void PM_AddTouchEnt( int entityNum ); extern float pm_flightfriction;
void PM_AddEvent( int newEvent ); extern float pm_spectatorfriction;
qboolean PM_SlideMove( qboolean gravity ); extern int c_pmove;
void PM_StepSlideMove( qboolean gravity );
// QL cached cvar globals
extern float pm_jumpVelocity;
extern float pm_jumpVelocityMax;
extern float pm_jumpVelocityScaleAdd;
extern float pm_jumpVelocityTimeThreshold;
extern float pm_jumpVelocityTimeThresholdOffset;
extern float pm_jumpTimeDeltaMin;
extern int pm_chainJump;
extern float pm_chainJumpVelocity;
extern float pm_stepJumpVelocity;
extern float pm_rampJumpScale;
extern float pm_stepHeight;
extern float pm_walkAccel;
extern float pm_walkFriction;
extern float pm_strafeAccel;
extern float pm_circleStrafeFriction;
extern float pm_crouchSlideFriction;
extern int pm_crouchSlideTime;
extern float pm_waterSwimScale;
extern float pm_waterWadeScale;
extern int pm_weaponDropTime;
extern int pm_weaponRaiseTime;
extern float pm_wishSpeed;
extern int pm_airSteps;
extern float pm_airStepFriction;
extern float pm_airAccel;
extern float pm_airStopAccel;
extern float pm_airControl;
extern int pm_autoHopEnabled;
extern int pm_bunnyHop;
extern int pm_stepJumpEnabled;
extern int pm_crouchStepJump;
extern int pm_rampJumpEnabled;
extern int pm_noPlayerClip;
extern float pm_velocityGh;
// QL extern flags
extern int pmove_globalFlag;
extern int pmove_rampJumpFlag;
extern int pmove_stepJumpFlag;
extern float _DAT_003cfe90;
extern int DAT_003cfe30;
// pmove functions
void PM_ClipVelocity( vec3_t in, vec3_t normal, vec3_t out, float overbounce );
void PM_AddTouchEnt( int entityNum );
void PM_AddEvent( int newEvent );
qboolean PM_SlideMove( qboolean gravity );
void PM_StepSlideMove( qboolean gravity );
// QL new functions
void PM_SetupPhysicsOverrides( void );
void PM_CheckWallContact( void );
void PM_CheckDuck( void );
void PM_DropTimers( void );
void PM_SetWaterLevel( void );
void PM_SetMovementDir( void );
void PM_Friction( void );
void PM_Accelerate( float wishspeed, float accel, vec3_t wishdir );
void PM_CmdScale( usercmd_t *cmd, float *scale );
int PM_BuildWishVelocity( usercmd_t *cmd, float *wishspeed, vec3_t wishdir );
void PM_Jump( void );
int PM_CheckJump( int checkDoubleJump );
int PM_CheckGrapple( void );
void PM_GrappleMove( void );
void PM_WaterJumpMove( void );
void PM_WaterMove( void );
void PM_AirMove( void );
void PM_AirControl( void );
void PM_FlyMove( void );
void PM_GroundTrace( void );
void PM_CrashLand( void );
int PM_FootstepForSurface( void );
void PM_ContinueLegsAnim( int anim );
void PM_ForceLegsAnim( int anim );
int PM_CanJump( void );
int PM_CanEdgeGrab( void );

File diff suppressed because it is too large Load diff

View file

@ -139,22 +139,35 @@ typedef enum {
WEAPON_FIRING WEAPON_FIRING
} weaponstate_t; } weaponstate_t;
// pmove->pm_flags // pmove->pm_flags (QL remapped values — NOT the same as Q3/Q3TA!)
#define PMF_DUCKED 1 #define PMF_DUCKED 0x0001
#define PMF_JUMP_HELD 2 #define PMF_JUMP_HELD 0x0002
#define PMF_BACKWARDS_JUMP 8 // go into backwards land #define PMF_ATTACK_HELD 0x0004 // QL: blocks weapon fire (warmup/transition)
#define PMF_BACKWARDS_RUN 16 // coast down to backwards run #define PMF_BACKWARDS_JUMP 0x0008
#define PMF_TIME_LAND 32 // pm_time is time before rejump #define PMF_BACKWARDS_RUN 0x0010
#define PMF_TIME_KNOCKBACK 64 // pm_time is an air-accelerate only time #define PMF_TIME_KNOCKBACK 0x0020 // pm_time is knockback stun
#define PMF_TIME_WATERJUMP 256 // pm_time is waterjump #define PMF_TIME_WATERJUMP 0x0040 // pm_time is waterjump
#define PMF_RESPAWNED 512 // clear after attack and jump buttons come up #define PMF_TIME_WATERJUMP_INIT 0x0080 // QL: waterjump initiation
#define PMF_USE_ITEM_HELD 1024 #define PMF_USE_ITEM_HELD 0x0100 // freezes player (intermission)
#define PMF_GRAPPLE_PULL 2048 // pull towards grapple location #define PMF_RESPAWNED 0x0200 // clear after attack and jump buttons come up
#define PMF_FOLLOW 4096 // spectate following another player #define PMF_GRAPPLE_PULL 0x0400 // grapple hook active
#define PMF_SCOREBOARD 8192 // spectate as a scoreboard #define PMF_GRAPPLE_ACTIVE 0x0800 // QL: grapple point tracking
#define PMF_INVULEXPAND 16384 // invulnerability sphere set to full size #define PMF_FOLLOW_SPECTATE 0x1000 // spectate following another player
#define PMF_GRAPPLE_TARGET 0x2000 // QL: player is grappled by another
#define PMF_INVUL_EXPAND 0x4000 // invulnerability sphere set to full size
#define PMF_GRAPPLE_RELEASED 0x8000 // QL: grapple just released (blocks fire)
#define PMF_PROMODE 0x10000 // QL: PQL air control / promode physics
#define PMF_DOUBLE_JUMP 0x20000 // QL: double jump enabled
#define PMF_AUTOHOP_HELD 0x40000 // QL: per-player autohop disabled (inverted)
#define PMF_CA_TEAM1 0x80000 // QL: Clan Arena team 1
#define PMF_CROUCH_SLIDE 0x100000 // QL: crouch slide mechanic enabled
#define PMF_ALL_TIMES (PMF_TIME_WATERJUMP|PMF_TIME_LAND|PMF_TIME_KNOCKBACK) #define PMF_ALL_TIMES (PMF_TIME_WATERJUMP|PMF_TIME_KNOCKBACK|PMF_TIME_WATERJUMP_INIT)
// Q3TA compatibility aliases
#define PMF_FOLLOW PMF_FOLLOW_SPECTATE
#define PMF_INVULEXPAND PMF_INVUL_EXPAND
#define PMF_SCOREBOARD PMF_FOLLOW_SPECTATE // Q3TA used separate bit; QL merged into FOLLOW
#define MAXTOUCH 32 #define MAXTOUCH 32
typedef struct { typedef struct {
@ -166,9 +179,7 @@ typedef struct {
int tracemask; // collide against these types of surfaces int tracemask; // collide against these types of surfaces
int debugLevel; // if set, diagnostic output will be printed int debugLevel; // if set, diagnostic output will be printed
qboolean noFootsteps; // if the game is setup for no footsteps by the server qboolean noFootsteps; // if the game is setup for no footsteps by the server
qboolean gauntletHit; // true if a gauntlet attack would actually hit something qboolean gauntletHit; // Q3TA compat: true if a gauntlet attack would actually hit something
int framecount;
// results (out) // results (out)
int numtouch; int numtouch;
@ -181,14 +192,22 @@ typedef struct {
float xyspeed; float xyspeed;
// for fixed msec Pmove // QL additions after xyspeed
int pmove_fixed; float field_0dc; // step height delta
int pmove_msec; int field_0e0; // cmd.serverTime of step event
int field_0e4; // unconfirmed
// callbacks to test the world // callbacks to test the world
// these will be different functions during game and cgame // these will be different functions during game and cgame
void (*trace)( trace_t *results, const vec3_t start, const vec3_t mins, const vec3_t maxs, const vec3_t end, int passEntityNum, int contentMask ); void (*trace)( trace_t *results, const vec3_t start, const vec3_t mins, const vec3_t maxs, const vec3_t end, int passEntityNum, int contentMask );
int (*pointcontents)( const vec3_t point, int passEntityNum ); int (*pointcontents)( const vec3_t point, int passEntityNum );
int field_0f8; // QL: linked entity boolean
int pad_0fc;
// Q3TA compat fields (not in QL pmove_t but used by game code)
int pmove_fixed;
int pmove_msec;
} pmove_t; } pmove_t;
// if a full pmove isn't done on the client, you can just update the angles // if a full pmove isn't done on the client, you can just update the angles

View file

@ -1,325 +1,397 @@
/* /*
=========================================================================== ===========================================================================
Copyright (C) 1999-2005 Id Software, Inc. Copyright (C) 1999-2005 Id Software, Inc.
This file is part of Quake III Arena source code. This file is part of Quake III Arena source code.
Quake III Arena source code is free software; you can redistribute it Quake III Arena source code is free software; you can redistribute it
and/or modify it under the terms of the GNU General Public License as and/or modify it under the terms of the GNU General Public License as
published by the Free Software Foundation; either version 2 of the License, published by the Free Software Foundation; either version 2 of the License,
or (at your option) any later version. or (at your option) any later version.
Quake III Arena source code is distributed in the hope that it will be Quake III Arena source code is distributed in the hope that it will be
useful, but WITHOUT ANY WARRANTY; without even the implied warranty of useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details. GNU General Public License for more details.
You should have received a copy of the GNU General Public License You should have received a copy of the GNU General Public License
along with Foobar; if not, write to the Free Software along with Foobar; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
=========================================================================== ===========================================================================
*/ */
// //
// bg_slidemove.c -- part of bg_pmove functionality // bg_slidemove.c -- part of bg_pmove functionality
//
#include "q_shared.h" // Reconstructed from Quake Live x86_64 binary.
#include "bg_public.h" // PM_SlideMove at 0x00155ed0, PM_StepSlideMove at 0x00156850.
#include "bg_local.h"
#include "q_shared.h"
/* #include "bg_public.h"
#include "bg_local.h"
input: origin, velocity, bounds, groundPlane, trace function
extern float _DAT_003cfe90; // velocity damping factor for step-up
output: origin, velocity, impacts, stairup boolean extern int DAT_003cfe30; // edge grab enabled
extern int pmove_stepJumpFlag; // step jump enabled
*/
/*
/* ==================
================== PM_SlideMove
PM_SlideMove
Returns qtrue if the velocity was clipped in some way
Returns qtrue if the velocity was clipped in some way ==================
================== */
*/ #define MAX_CLIP_PLANES 5
#define MAX_CLIP_PLANES 5 qboolean PM_SlideMove( qboolean gravity ) {
qboolean PM_SlideMove( qboolean gravity ) { int bumpcount;
int bumpcount, numbumps; int numplanes;
vec3_t dir; vec3_t planes[MAX_CLIP_PLANES];
float d; vec3_t clipVelocity;
int numplanes; vec3_t endClipVelocity;
vec3_t planes[MAX_CLIP_PLANES]; vec3_t endVelocity;
vec3_t primal_velocity; vec3_t end;
vec3_t clipVelocity; vec3_t dir;
int i, j, k; trace_t trace;
trace_t trace; float primal_vel_x, primal_vel_y, primal_vel_z;
vec3_t end; float time_left;
float time_left; float into;
float into; float d;
vec3_t endVelocity; int i, j, k;
vec3_t endClipVelocity;
primal_vel_x = pm->ps->velocity[0];
numbumps = 4; primal_vel_y = pm->ps->velocity[1];
primal_vel_z = pm->ps->velocity[2];
VectorCopy (pm->ps->velocity, primal_velocity);
if ( !gravity ) {
if ( gravity ) { endVelocity[0] = 0.0f;
VectorCopy( pm->ps->velocity, endVelocity ); endVelocity[1] = 0.0f;
endVelocity[2] -= pm->ps->gravity * pml.frametime; endVelocity[2] = 0.0f;
pm->ps->velocity[2] = ( pm->ps->velocity[2] + endVelocity[2] ) * 0.5; } else {
primal_velocity[2] = endVelocity[2]; endVelocity[0] = primal_vel_x;
if ( pml.groundPlane ) { endVelocity[1] = pm->ps->velocity[1];
// slide along the ground plane primal_vel_z = pm->ps->velocity[2] - (float)pm->ps->gravity * pml.frametime;
PM_ClipVelocity (pm->ps->velocity, pml.groundTrace.plane.normal, pm->ps->velocity[2] = (pm->ps->velocity[2] + primal_vel_z) * 0.5f;
pm->ps->velocity, OVERCLIP ); endVelocity[2] = primal_vel_z;
} if ( pml.groundPlane ) {
} // slide along the ground plane
PM_ClipVelocity( pm->ps->velocity, pml.groundTrace.plane.normal,
time_left = pml.frametime; pm->ps->velocity, OVERCLIP );
}
// never turn against the ground plane }
if ( pml.groundPlane ) {
numplanes = 1; time_left = pml.frametime;
VectorCopy( pml.groundTrace.plane.normal, planes[0] );
} else { // never turn against the ground plane
numplanes = 0; if ( pml.groundPlane ) {
} numplanes = 2;
VectorCopy( pml.groundTrace.plane.normal, planes[0] );
// never turn against original velocity VectorNormalize2( pm->ps->velocity, planes[1] );
VectorNormalize2( pm->ps->velocity, planes[numplanes] ); } else {
numplanes++; numplanes = 1;
VectorNormalize2( pm->ps->velocity, planes[0] );
for ( bumpcount=0 ; bumpcount < numbumps ; bumpcount++ ) { }
// calculate position we are trying to move to for ( bumpcount = 0; bumpcount < 4; bumpcount++ ) {
VectorMA( pm->ps->origin, time_left, pm->ps->velocity, end );
// calculate position we are trying to move to
// see if we can make it there VectorMA( pm->ps->origin, time_left, pm->ps->velocity, end );
pm->trace ( &trace, pm->ps->origin, pm->mins, pm->maxs, end, pm->ps->clientNum, pm->tracemask);
// see if we can make it there
if (trace.allsolid) { pm->trace( &trace, pm->ps->origin, pm->mins, pm->maxs, end,
// entity is completely trapped in another solid pm->ps->clientNum, pm->tracemask );
pm->ps->velocity[2] = 0; // don't build up falling damage, but allow sideways acceleration
return qtrue; if ( trace.allsolid ) {
} // entity is completely trapped in another solid
pm->ps->velocity[2] = 0.0f;
if (trace.fraction > 0) { return qtrue;
// actually covered some distance }
VectorCopy (trace.endpos, pm->ps->origin);
} if ( trace.fraction > 0.0f ) {
// actually covered some distance
if (trace.fraction == 1) { VectorCopy( trace.endpos, pm->ps->origin );
break; // moved the entire distance }
}
if ( trace.fraction == 1.0f ) {
// save entity for contact break; // moved the entire distance
PM_AddTouchEnt( trace.entityNum ); }
time_left -= time_left * trace.fraction; // save entity for contact
PM_AddTouchEnt( trace.entityNum );
if (numplanes >= MAX_CLIP_PLANES) {
// this shouldn't really happen time_left -= time_left * trace.fraction;
VectorClear( pm->ps->velocity );
return qtrue; if ( numplanes >= MAX_CLIP_PLANES ) {
} // this shouldn't really happen
VectorClear( pm->ps->velocity );
// return qtrue;
// if this is the same plane we hit before, nudge velocity }
// out along it, which fixes some epsilon issues with
// non-axial planes //
// // if this is the same plane we hit before, nudge velocity
for ( i = 0 ; i < numplanes ; i++ ) { // out along it, which fixes some epsilon issues with
if ( DotProduct( trace.plane.normal, planes[i] ) > 0.99 ) { // non-axial planes
VectorAdd( trace.plane.normal, pm->ps->velocity, pm->ps->velocity ); //
break; for ( i = 0; i < numplanes; i++ ) {
} if ( (double)DotProduct( trace.plane.normal, planes[i] ) > 0.99 ) {
} VectorAdd( trace.plane.normal, pm->ps->velocity, pm->ps->velocity );
if ( i < numplanes ) { break;
continue; }
} }
VectorCopy (trace.plane.normal, planes[numplanes]); if ( i < numplanes ) {
numplanes++; continue;
}
// VectorCopy( trace.plane.normal, planes[numplanes] );
// modify velocity so it parallels all of the clip planes numplanes++;
//
//
// find a plane that it enters // modify velocity so it parallels all of the clip planes
for ( i = 0 ; i < numplanes ; i++ ) { //
into = DotProduct( pm->ps->velocity, planes[i] );
if ( into >= 0.1 ) { // find a plane that it enters
continue; // move doesn't interact with the plane for ( i = 0; i < numplanes; i++ ) {
} into = DotProduct( pm->ps->velocity, planes[i] );
if ( (double)into >= 0.1 ) {
// see how hard we are hitting things continue; // move doesn't interact with the plane
if ( -into > pml.impactSpeed ) { }
pml.impactSpeed = -into;
} // see how hard we are hitting things
if ( -into > pml.impactSpeed ) {
// slide along the plane pml.impactSpeed = -into;
PM_ClipVelocity (pm->ps->velocity, planes[i], clipVelocity, OVERCLIP ); }
// slide along the plane // slide along the plane
PM_ClipVelocity (endVelocity, planes[i], endClipVelocity, OVERCLIP ); PM_ClipVelocity( pm->ps->velocity, planes[i], clipVelocity, OVERCLIP );
// see if there is a second plane that the new move enters // slide along the plane
for ( j = 0 ; j < numplanes ; j++ ) { PM_ClipVelocity( endVelocity, planes[i], endClipVelocity, OVERCLIP );
if ( j == i ) {
continue; // see if there is a second plane that the new move enters
} for ( j = 0; j < numplanes; j++ ) {
if ( DotProduct( clipVelocity, planes[j] ) >= 0.1 ) { if ( j == i ) {
continue; // move doesn't interact with the plane continue;
} }
if ( (double)DotProduct( clipVelocity, planes[j] ) >= 0.1 ) {
// try clipping the move to the plane continue; // move doesn't interact with the plane
PM_ClipVelocity( clipVelocity, planes[j], clipVelocity, OVERCLIP ); }
PM_ClipVelocity( endClipVelocity, planes[j], endClipVelocity, OVERCLIP );
// try clipping the move to the plane
// see if it goes back into the first clip plane PM_ClipVelocity( clipVelocity, planes[j], clipVelocity, OVERCLIP );
if ( DotProduct( clipVelocity, planes[i] ) >= 0 ) { PM_ClipVelocity( endClipVelocity, planes[j], endClipVelocity, OVERCLIP );
continue;
} // see if it goes back into the first clip plane
if ( DotProduct( clipVelocity, planes[i] ) >= 0.0f ) {
// slide the original velocity along the crease continue;
CrossProduct (planes[i], planes[j], dir); }
VectorNormalize( dir );
d = DotProduct( dir, pm->ps->velocity ); // slide the original velocity along the crease
VectorScale( dir, d, clipVelocity ); CrossProduct( planes[i], planes[j], dir );
VectorNormalize( dir );
CrossProduct (planes[i], planes[j], dir); d = DotProduct( dir, pm->ps->velocity );
VectorNormalize( dir ); VectorScale( dir, d, clipVelocity );
d = DotProduct( dir, endVelocity );
VectorScale( dir, d, endClipVelocity ); CrossProduct( planes[i], planes[j], dir );
VectorNormalize( dir );
// see if there is a third plane the the new move enters d = DotProduct( dir, endVelocity );
for ( k = 0 ; k < numplanes ; k++ ) { VectorScale( dir, d, endClipVelocity );
if ( k == i || k == j ) {
continue; // see if there is a third plane the new move enters
} for ( k = 0; k < numplanes; k++ ) {
if ( DotProduct( clipVelocity, planes[k] ) >= 0.1 ) { if ( k == i || k == j ) {
continue; // move doesn't interact with the plane continue;
} }
if ( (double)DotProduct( clipVelocity, planes[k] ) >= 0.1 ) {
// stop dead at a tripple plane interaction continue; // move doesn't interact with the plane
VectorClear( pm->ps->velocity ); }
return qtrue;
} // stop dead at a triple plane interaction
} VectorClear( pm->ps->velocity );
return qtrue;
// if we have fixed all interactions, try another move }
VectorCopy( clipVelocity, pm->ps->velocity ); }
VectorCopy( endClipVelocity, endVelocity );
break; // if we have fixed all interactions, try another move
} VectorCopy( clipVelocity, pm->ps->velocity );
} VectorCopy( endClipVelocity, endVelocity );
break;
if ( gravity ) { }
VectorCopy( endVelocity, pm->ps->velocity ); }
}
if ( gravity ) {
// don't change velocity if in a timer (FIXME: is this correct?) VectorCopy( endVelocity, pm->ps->velocity );
if ( pm->ps->pm_time ) { }
VectorCopy( primal_velocity, pm->ps->velocity );
} // don't change velocity if in a timer (FIXME: is this correct?)
if ( pm->ps->pm_time ) {
return ( bumpcount != 0 ); pm->ps->velocity[0] = primal_vel_x;
} pm->ps->velocity[1] = primal_vel_y;
pm->ps->velocity[2] = primal_vel_z;
/* }
==================
PM_StepSlideMove return ( bumpcount != 0 );
}
==================
*/ /*
void PM_StepSlideMove( qboolean gravity ) { ==================
vec3_t start_o, start_v; PM_StepSlideMove
vec3_t down_o, down_v;
trace_t trace; QL version: significantly expanded from Q3 with air-step support,
// float down_dist, up_dist; step-jump logic, edge grab, and velocity damping on step-ups.
// vec3_t delta, delta2; ==================
vec3_t up, down; */
float stepSize; void PM_StepSlideMove( qboolean gravity ) {
vec3_t start_o;
VectorCopy (pm->ps->origin, start_o); float start_vx, start_vy, start_vz;
VectorCopy (pm->ps->velocity, start_v); vec3_t up, down;
vec3_t projected;
if ( PM_SlideMove( gravity ) == 0 ) { vec3_t stepStart, stepEnd;
return; // we got exactly where we wanted to go first try vec3_t edgeMins, edgeMaxs, edgeEnd;
} trace_t trace;
float stepSize;
VectorCopy(start_o, down); float delta;
down[2] -= STEPSIZE; float dotNV;
pm->trace (&trace, start_o, pm->mins, pm->maxs, down, pm->ps->clientNum, pm->tracemask);
VectorSet(up, 0, 0, 1); VectorCopy( pm->ps->origin, start_o );
// never step up when you still have up velocity start_vx = pm->ps->velocity[0];
if ( pm->ps->velocity[2] > 0 && (trace.fraction == 1.0 || start_vy = pm->ps->velocity[1];
DotProduct(trace.plane.normal, up) < 0.7)) { start_vz = pm->ps->velocity[2];
return;
} if ( PM_SlideMove( gravity ) == 0 ) {
return; // we got exactly where we wanted to go first try
VectorCopy (pm->ps->origin, down_o); }
VectorCopy (pm->ps->velocity, down_v);
// project where we would have gone without obstruction
VectorCopy (start_o, up); projected[0] = start_vx * pml.frametime + start_o[0];
up[2] += STEPSIZE; projected[1] = start_vy * pml.frametime + start_o[1];
projected[2] = pml.frametime * start_vz + start_o[2];
// test the player position if they were a stepheight higher
pm->trace (&trace, start_o, pm->mins, pm->maxs, up, pm->ps->clientNum, pm->tracemask); if ( pm_airSteps == 0 ) {
if ( trace.allsolid ) { // trace forward to projected position, then down to check for ground
if ( pm->debugLevel ) { pm->trace( &trace, start_o, pm->mins, pm->maxs, projected,
Com_Printf("%i:bend can't step\n", c_pmove); pm->ps->clientNum, pm->tracemask );
} VectorCopy( trace.endpos, projected );
return; // can't step up down[0] = trace.endpos[0];
} down[1] = trace.endpos[1];
down[2] = trace.endpos[2] - (float)pm_stepHeight;
stepSize = trace.endpos[2] - start_o[2]; pm->trace( &trace, projected, pm->mins, pm->maxs, down,
// try slidemove from this position pm->ps->clientNum, pm->tracemask );
VectorCopy (trace.endpos, pm->ps->origin); // never step up when you still have up velocity
VectorCopy (start_v, pm->ps->velocity); if ( start_vz > 0.0f ) {
if ( trace.fraction == 1.0f ) {
PM_SlideMove( gravity ); return;
}
// push down the final amount if ( trace.plane.normal[2] < MIN_WALK_NORMAL ) {
VectorCopy (pm->ps->origin, down); return;
down[2] -= stepSize; }
pm->trace (&trace, pm->ps->origin, pm->mins, pm->maxs, down, pm->ps->clientNum, pm->tracemask); }
if ( !trace.allsolid ) { }
VectorCopy (trace.endpos, pm->ps->origin);
} // try stepping up
if ( trace.fraction < 1.0 ) { up[0] = start_o[0];
PM_ClipVelocity( pm->ps->velocity, trace.plane.normal, pm->ps->velocity, OVERCLIP ); up[1] = start_o[1];
} up[2] = start_o[2] + (float)pm_stepHeight;
#if 0 // test the player position if they were a stepheight higher
// if the down trace can trace back to the original position directly, don't step pm->trace( &trace, start_o, pm->mins, pm->maxs, up,
pm->trace( &trace, pm->ps->origin, pm->mins, pm->maxs, start_o, pm->ps->clientNum, pm->tracemask); pm->ps->clientNum, pm->tracemask );
if ( trace.fraction == 1.0 ) { if ( trace.allsolid ) {
// use the original move if ( pm->debugLevel ) {
VectorCopy (down_o, pm->ps->origin); Com_Printf( "%i:bend can't step\n", c_pmove );
VectorCopy (down_v, pm->ps->velocity); }
if ( pm->debugLevel ) { return; // can't step up
Com_Printf("%i:bend\n", c_pmove); }
}
} else stepSize = trace.endpos[2] - start_o[2];
#endif // try slidemove from this position
{ VectorCopy( trace.endpos, pm->ps->origin );
// use the step move pm->ps->velocity[0] = start_vx;
float delta; pm->ps->velocity[1] = start_vy;
pm->ps->velocity[2] = start_vz;
delta = pm->ps->origin[2] - start_o[2];
if ( delta > 2 ) { PM_SlideMove( gravity );
if ( delta < 7 ) {
PM_AddEvent( EV_STEP_4 ); // push down the final amount
} else if ( delta < 11 ) { VectorCopy( pm->ps->origin, down );
PM_AddEvent( EV_STEP_8 ); down[2] -= stepSize;
} else if ( delta < 15 ) { pm->trace( &trace, pm->ps->origin, pm->mins, pm->maxs, down,
PM_AddEvent( EV_STEP_12 ); pm->ps->clientNum, pm->tracemask );
} else { if ( !trace.allsolid ) {
PM_AddEvent( EV_STEP_16 ); VectorCopy( trace.endpos, pm->ps->origin );
} }
} if ( trace.fraction < 1.0f ) {
if ( pm->debugLevel ) { dotNV = DotProduct( trace.plane.normal, pm->ps->velocity );
Com_Printf("%i:stepped\n", c_pmove); if ( dotNV >= 0.0f && fabs( dotNV ) >= 0.001f ) {
} // velocity is moving away from the surface, skip clipping
} goto skipClip;
} }
PM_ClipVelocity( pm->ps->velocity, trace.plane.normal,
pm->ps->velocity, OVERCLIP );
}
skipClip:
// trace from start to final position to check if we actually stepped
pm->trace( &trace, start_o, pm->mins, pm->maxs, pm->ps->origin,
pm->ps->clientNum, pm->tracemask );
if ( trace.fraction < 1.0f ) {
// didn't make it all the way -- use the step move result
delta = pm->ps->origin[2] - start_o[2];
if ( delta > 2.0f ) {
pm->field_0dc = delta;
pm->field_0e0 = pm->cmd.serverTime;
}
// apply velocity damping when stepping up while airborne
if ( !pml.groundPlane && delta > 0.0f && start_vz > 0.0f ) {
float dampFactor = 1.0f - _DAT_003cfe90;
pm->ps->velocity[0] *= dampFactor;
pm->ps->velocity[1] *= dampFactor;
}
// step jump / edge grab logic
if ( pmove_stepJumpFlag && pm->ps->pm_type == PM_NORMAL
&& delta > 0.0f && (int)pm->waterlevel < 2 ) {
if ( PM_CanJump() || ( DAT_003cfe30 && PM_CanEdgeGrab() ) ) {
// check if there is walkable ground at the projected position
stepStart[0] = projected[0];
stepStart[1] = projected[1];
stepStart[2] = projected[2] + (float)pm_stepHeight;
stepEnd[0] = projected[0];
stepEnd[1] = projected[1];
stepEnd[2] = projected[2] - (float)pm_stepHeight;
pm->trace( &trace, stepStart, pm->mins, pm->maxs, stepEnd,
pm->ps->clientNum, pm->tracemask );
if ( !trace.startsolid && !trace.allsolid
&& trace.plane.normal[2] >= MIN_WALK_NORMAL ) {
if ( PM_CanJump() ) {
// normal step jump
pml.isStepJump = 1;
PM_Jump();
pml.isStepJump = 0;
} else if ( DAT_003cfe30 && PM_CanEdgeGrab() ) {
// edge grab: check for open air below with shrunk bbox
edgeMins[0] = pm->mins[0] + 1.0f;
edgeMins[1] = pm->mins[1] + 1.0f;
edgeMins[2] = pm->mins[2];
edgeMaxs[0] = pm->maxs[0] - 1.0f;
edgeMaxs[1] = pm->maxs[1] - 1.0f;
edgeMaxs[2] = pm->maxs[2];
edgeEnd[0] = pm->ps->origin[0];
edgeEnd[1] = pm->ps->origin[1];
edgeEnd[2] = pm->ps->origin[2] - 64.0f;
pm->trace( &trace, pm->ps->origin, edgeMins, edgeMaxs, edgeEnd,
pm->ps->clientNum, pm->tracemask );
if ( trace.fraction == 1.0f ) {
// over an edge -- do a crouch step jump
pml.isJumppad = 1;
PM_Jump();
pml.isJumppad = 0;
}
}
}
}
}
if ( pm->debugLevel ) {
Com_Printf( "%i:stepped %f\n", c_pmove, delta );
}
}
}

View file

@ -22,6 +22,7 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
// //
#include "g_local.h" #include "g_local.h"
#include "bg_local.h"
level_locals_t level; level_locals_t level;
@ -95,6 +96,42 @@ vmCvar_t g_enableBreath;
vmCvar_t g_proxMineTimeout; vmCvar_t g_proxMineTimeout;
#endif #endif
// QL pmove cvars
vmCvar_t pmove_JumpVelocity;
vmCvar_t pmove_JumpVelocityMax;
vmCvar_t pmove_JumpVelocityScaleAdd;
vmCvar_t pmove_JumpVelocityTimeThreshold;
vmCvar_t pmove_JumpVelocityTimeThresholdOffset;
vmCvar_t pmove_JumpTimeDeltaMin;
vmCvar_t pmove_ChainJump;
vmCvar_t pmove_ChainJumpVelocity;
vmCvar_t pmove_StepJumpVelocity;
vmCvar_t pmove_RampJumpScale;
vmCvar_t pmove_StepHeight;
vmCvar_t pmove_WalkAccel;
vmCvar_t pmove_WalkFriction;
vmCvar_t pmove_StrafeAccel;
vmCvar_t pmove_CircleStrafeFriction;
vmCvar_t pmove_CrouchSlideFriction;
vmCvar_t pmove_CrouchSlideTime;
vmCvar_t pmove_WaterSwimScale;
vmCvar_t pmove_WaterWadeScale;
vmCvar_t pmove_WeaponDropTime;
vmCvar_t pmove_WeaponRaiseTime;
vmCvar_t pmove_WishSpeed;
vmCvar_t pmove_AirSteps;
vmCvar_t pmove_AirAccel;
vmCvar_t pmove_AirStopAccel;
vmCvar_t pmove_AirControl;
vmCvar_t pmove_AutoHop;
vmCvar_t pmove_BunnyHop;
vmCvar_t pmove_StepJump;
vmCvar_t pmove_CrouchStepJump;
vmCvar_t pmove_RampJump;
vmCvar_t pmove_DoubleJump;
vmCvar_t pmove_CrouchSlide;
vmCvar_t pmove_noPlayerClip;
// bk001129 - made static to avoid aliasing // bk001129 - made static to avoid aliasing
static cvarTable_t gameCvarTable[] = { static cvarTable_t gameCvarTable[] = {
// don't override the cheat state set by the system // don't override the cheat state set by the system
@ -178,8 +215,43 @@ static cvarTable_t gameCvarTable[] = {
{ &pmove_fixed, "pmove_fixed", "0", CVAR_SYSTEMINFO, 0, qfalse}, { &pmove_fixed, "pmove_fixed", "0", CVAR_SYSTEMINFO, 0, qfalse},
{ &pmove_msec, "pmove_msec", "8", CVAR_SYSTEMINFO, 0, qfalse}, { &pmove_msec, "pmove_msec", "8", CVAR_SYSTEMINFO, 0, qfalse},
{ &g_rankings, "g_rankings", "0", 0, 0, qfalse} { &g_rankings, "g_rankings", "0", 0, 0, qfalse},
// QL pmove cvars
{ &pmove_JumpVelocity, "pmove_JumpVelocity", "270", 0, 0, qfalse },
{ &pmove_JumpVelocityMax, "pmove_JumpVelocityMax", "700", 0, 0, qfalse },
{ &pmove_JumpVelocityScaleAdd, "pmove_JumpVelocityScaleAdd", "0", 0, 0, qfalse },
{ &pmove_JumpVelocityTimeThreshold, "pmove_JumpVelocityTimeThreshold", "500", 0, 0, qfalse },
{ &pmove_JumpVelocityTimeThresholdOffset, "pmove_JumpVelocityTimeThresholdOffset", "0.5", 0, 0, qfalse },
{ &pmove_JumpTimeDeltaMin, "pmove_JumpTimeDeltaMin", "100", 0, 0, qfalse },
{ &pmove_ChainJump, "pmove_ChainJump", "1", 0, 0, qfalse },
{ &pmove_ChainJumpVelocity, "pmove_ChainJumpVelocity", "110", 0, 0, qfalse },
{ &pmove_StepJumpVelocity, "pmove_StepJumpVelocity", "48", 0, 0, qfalse },
{ &pmove_RampJumpScale, "pmove_RampJumpScale", "1", 0, 0, qfalse },
{ &pmove_StepHeight, "pmove_StepHeight", "22", 0, 0, qfalse },
{ &pmove_WalkAccel, "pmove_WalkAccel", "10", 0, 0, qfalse },
{ &pmove_WalkFriction, "pmove_WalkFriction", "6", 0, 0, qfalse },
{ &pmove_StrafeAccel, "pmove_StrafeAccel", "1", 0, 0, qfalse },
{ &pmove_CircleStrafeFriction, "pmove_CircleStrafeFriction", "6", 0, 0, qfalse },
{ &pmove_CrouchSlideFriction, "pmove_CrouchSlideFriction", "0.5", 0, 0, qfalse },
{ &pmove_CrouchSlideTime, "pmove_CrouchSlideTime", "2", 0, 0, qfalse },
{ &pmove_WaterSwimScale, "pmove_WaterSwimScale", "0.5", 0, 0, qfalse },
{ &pmove_WaterWadeScale, "pmove_WaterWadeScale", "0.7", 0, 0, qfalse },
{ &pmove_WeaponDropTime, "pmove_WeaponDropTime", "200", 0, 0, qfalse },
{ &pmove_WeaponRaiseTime, "pmove_WeaponRaiseTime", "250", 0, 0, qfalse },
{ &pmove_WishSpeed, "pmove_WishSpeed", "400", 0, 0, qfalse },
{ &pmove_AirSteps, "pmove_AirSteps", "1", 0, 0, qfalse },
{ &pmove_AirAccel, "pmove_AirAccel", "1", 0, 0, qfalse },
{ &pmove_AirStopAccel, "pmove_AirStopAccel", "1", 0, 0, qfalse },
{ &pmove_AirControl, "pmove_AirControl", "0", 0, 0, qfalse },
{ &pmove_AutoHop, "pmove_AutoHop", "1", 0, 0, qfalse },
{ &pmove_BunnyHop, "pmove_BunnyHop", "1", 0, 0, qfalse },
{ &pmove_StepJump, "pmove_StepJump", "1", 0, 0, qfalse },
{ &pmove_CrouchStepJump, "pmove_CrouchStepJump", "1", 0, 0, qfalse },
{ &pmove_RampJump, "pmove_RampJump", "0", 0, 0, qfalse },
{ &pmove_DoubleJump, "pmove_DoubleJump", "1", 0, 0, qfalse },
{ &pmove_CrouchSlide, "pmove_CrouchSlide", "0", 0, 0, qfalse },
{ &pmove_noPlayerClip, "pmove_noPlayerClip", "0", 0, 0, qfalse },
}; };
// bk001129 - made static to avoid aliasing // bk001129 - made static to avoid aliasing
@ -397,6 +469,42 @@ void G_UpdateCvars( void ) {
if (remapped) { if (remapped) {
G_RemapTeamShaders(); G_RemapTeamShaders();
} }
// sync pmove cvar globals
pm_jumpVelocity = pmove_JumpVelocity.value;
pm_jumpVelocityMax = pmove_JumpVelocityMax.value;
pm_jumpVelocityScaleAdd = pmove_JumpVelocityScaleAdd.value;
pm_jumpVelocityTimeThreshold = pmove_JumpVelocityTimeThreshold.value;
pm_jumpVelocityTimeThresholdOffset = pmove_JumpVelocityTimeThresholdOffset.value;
pm_jumpTimeDeltaMin = pmove_JumpTimeDeltaMin.value;
pm_chainJump = pmove_ChainJump.integer;
pm_chainJumpVelocity = pmove_ChainJumpVelocity.value;
pm_stepJumpVelocity = pmove_StepJumpVelocity.value;
pm_rampJumpScale = pmove_RampJumpScale.value;
pm_stepHeight = pmove_StepHeight.value;
pm_walkAccel = pmove_WalkAccel.value;
pm_walkFriction = pmove_WalkFriction.value;
pm_strafeAccel = pmove_StrafeAccel.value;
pm_circleStrafeFriction = pmove_CircleStrafeFriction.value;
pm_crouchSlideFriction = pmove_CrouchSlideFriction.value;
pm_crouchSlideTime = pmove_CrouchSlideTime.integer;
pm_waterSwimScale = pmove_WaterSwimScale.value;
pm_waterWadeScale = pmove_WaterWadeScale.value;
pm_weaponDropTime = pmove_WeaponDropTime.integer;
pm_weaponRaiseTime = pmove_WeaponRaiseTime.integer;
pm_wishSpeed = pmove_WishSpeed.value;
pm_airSteps = pmove_AirSteps.integer;
pm_airAccel = pmove_AirAccel.value;
pm_airStopAccel = pmove_AirStopAccel.value;
pm_airControl = pmove_AirControl.value;
pm_autoHopEnabled = pmove_AutoHop.integer;
pm_bunnyHop = pmove_BunnyHop.integer;
pm_stepJumpEnabled = pmove_StepJump.integer;
pm_crouchStepJump = pmove_CrouchStepJump.integer;
pm_rampJumpEnabled = pmove_RampJump.integer;
pm_noPlayerClip = pmove_noPlayerClip.integer;
pmove_rampJumpFlag = pmove_RampJump.integer;
pmove_stepJumpFlag = pmove_StepJump.integer;
} }
/* /*

View file

@ -1186,8 +1186,14 @@ typedef struct playerState_s {
int externalEventTime; int externalEventTime;
int clientNum; // ranges from 0 to MAX_CLIENTS-1 int clientNum; // ranges from 0 to MAX_CLIENTS-1
// QL additions: 3 new fields inserted here (shifts weapon onward +12 bytes)
int field_08c; // team entity reference (team gametypes only)
int weapon; // copied to entityState_t->weapon int weapon; // copied to entityState_t->weapon
int field_094; // cmd.field_15 copy (weapon-like index, 1-14)
int weaponstate; int weaponstate;
int field_09c; // cmd.field_16 copy (index, 10-136)
vec3_t viewangles; // for fixed views vec3_t viewangles; // for fixed views
int viewheight; int viewheight;
@ -1207,7 +1213,17 @@ typedef struct playerState_s {
int loopSound; int loopSound;
int jumppad_ent; // jumppad entity hit this frame int jumppad_ent; // jumppad entity hit this frame
int lastJumpTime; // QL: last jump timestamp for chain jump timing
int jumped; // QL: double jump consumed flag
int field_1d4; // QL: crouch start time
int crouchSlideTimer; // QL: crouch slide charge/decay timer
// not communicated over the net at all // not communicated over the net at all
signed char forwardmove; // QL: copied from cmd each frame
signed char rightmove;
signed char upmove;
byte pad_1df;
int ping; // server to game info for scoreboard int ping; // server to game info for scoreboard
int pmove_framecount; // FIXME: don't transmit over the network int pmove_framecount; // FIXME: don't transmit over the network
int jumppad_frame; int jumppad_frame;
@ -1249,8 +1265,12 @@ typedef struct usercmd_s {
int serverTime; int serverTime;
int angles[3]; int angles[3];
int buttons; int buttons;
byte weapon; // weapon byte weapon;
signed char forwardmove, rightmove, upmove; byte field_15; // QL: weapon-like index (1-14), copied to ps->field_094
byte field_16; // QL: index (10-136), copied to ps->field_09c
signed char forwardmove, rightmove, upmove;
byte pad_1a;
byte pad_1b;
} usercmd_t; } usercmd_t;
//=================================================================== //===================================================================

View file

@ -46,7 +46,7 @@ int demo_protocols[] =
#define DEF_COMZONEMEGS "24" #define DEF_COMZONEMEGS "24"
#else #else
#define DEF_COMHUNKMEGS "512" #define DEF_COMHUNKMEGS "512"
#define DEF_COMZONEMEGS "384" #define DEF_COMZONEMEGS "256"
#endif #endif
int com_argc; int com_argc;

View file

@ -655,6 +655,8 @@ void MSG_WriteDeltaUsercmd( msg_t *msg, usercmd_t *from, usercmd_t *to ) {
MSG_WriteDelta( msg, from->upmove, to->upmove, 8 ); MSG_WriteDelta( msg, from->upmove, to->upmove, 8 );
MSG_WriteDelta( msg, from->buttons, to->buttons, 16 ); MSG_WriteDelta( msg, from->buttons, to->buttons, 16 );
MSG_WriteDelta( msg, from->weapon, to->weapon, 8 ); MSG_WriteDelta( msg, from->weapon, to->weapon, 8 );
MSG_WriteDelta( msg, from->field_15, to->field_15, 8 );
MSG_WriteDelta( msg, from->field_16, to->field_16, 8 );
} }
@ -677,6 +679,8 @@ void MSG_ReadDeltaUsercmd( msg_t *msg, usercmd_t *from, usercmd_t *to ) {
to->upmove = MSG_ReadDelta( msg, from->upmove, 8); to->upmove = MSG_ReadDelta( msg, from->upmove, 8);
to->buttons = MSG_ReadDelta( msg, from->buttons, 16); to->buttons = MSG_ReadDelta( msg, from->buttons, 16);
to->weapon = MSG_ReadDelta( msg, from->weapon, 8); to->weapon = MSG_ReadDelta( msg, from->weapon, 8);
to->field_15 = MSG_ReadDelta( msg, from->field_15, 8);
to->field_16 = MSG_ReadDelta( msg, from->field_16, 8);
} }
/* /*
@ -699,7 +703,9 @@ void MSG_WriteDeltaUsercmdKey( msg_t *msg, int key, usercmd_t *from, usercmd_t *
from->rightmove == to->rightmove && from->rightmove == to->rightmove &&
from->upmove == to->upmove && from->upmove == to->upmove &&
from->buttons == to->buttons && from->buttons == to->buttons &&
from->weapon == to->weapon) { from->weapon == to->weapon &&
from->field_15 == to->field_15 &&
from->field_16 == to->field_16) {
MSG_WriteBits( msg, 0, 1 ); // no change MSG_WriteBits( msg, 0, 1 ); // no change
oldsize += 7; oldsize += 7;
return; return;
@ -714,6 +720,8 @@ void MSG_WriteDeltaUsercmdKey( msg_t *msg, int key, usercmd_t *from, usercmd_t *
MSG_WriteDeltaKey( msg, key, from->upmove, to->upmove, 8 ); MSG_WriteDeltaKey( msg, key, from->upmove, to->upmove, 8 );
MSG_WriteDeltaKey( msg, key, from->buttons, to->buttons, 16 ); MSG_WriteDeltaKey( msg, key, from->buttons, to->buttons, 16 );
MSG_WriteDeltaKey( msg, key, from->weapon, to->weapon, 8 ); MSG_WriteDeltaKey( msg, key, from->weapon, to->weapon, 8 );
MSG_WriteDeltaKey( msg, key, from->field_15, to->field_15, 8 );
MSG_WriteDeltaKey( msg, key, from->field_16, to->field_16, 8 );
} }
@ -738,6 +746,8 @@ void MSG_ReadDeltaUsercmdKey( msg_t *msg, int key, usercmd_t *from, usercmd_t *t
to->upmove = MSG_ReadDeltaKey( msg, key, from->upmove, 8); to->upmove = MSG_ReadDeltaKey( msg, key, from->upmove, 8);
to->buttons = MSG_ReadDeltaKey( msg, key, from->buttons, 16); to->buttons = MSG_ReadDeltaKey( msg, key, from->buttons, 16);
to->weapon = MSG_ReadDeltaKey( msg, key, from->weapon, 8); to->weapon = MSG_ReadDeltaKey( msg, key, from->weapon, 8);
to->field_15 = MSG_ReadDeltaKey( msg, key, from->field_15, 8);
to->field_16 = MSG_ReadDeltaKey( msg, key, from->field_16, 8);
} else { } else {
to->angles[0] = from->angles[0]; to->angles[0] = from->angles[0];
to->angles[1] = from->angles[1]; to->angles[1] = from->angles[1];
@ -747,6 +757,8 @@ void MSG_ReadDeltaUsercmdKey( msg_t *msg, int key, usercmd_t *from, usercmd_t *t
to->upmove = from->upmove; to->upmove = from->upmove;
to->buttons = from->buttons; to->buttons = from->buttons;
to->weapon = from->weapon; to->weapon = from->weapon;
to->field_15 = from->field_15;
to->field_16 = from->field_16;
} }
} }
@ -1119,7 +1131,7 @@ netField_t playerStateFields[] =
{ PSF(events[0]), 8 }, { PSF(events[0]), 8 },
{ PSF(legsAnim), 8 }, { PSF(legsAnim), 8 },
{ PSF(events[1]), 8 }, { PSF(events[1]), 8 },
{ PSF(pm_flags), 16 }, { PSF(pm_flags), 21 },
{ PSF(groundEntityNum), GENTITYNUM_BITS }, { PSF(groundEntityNum), GENTITYNUM_BITS },
{ PSF(weaponstate), 4 }, { PSF(weaponstate), 4 },
{ PSF(eFlags), 16 }, { PSF(eFlags), 16 },
@ -1147,7 +1159,18 @@ netField_t playerStateFields[] =
{ PSF(grapplePoint[1]), 0 }, { PSF(grapplePoint[1]), 0 },
{ PSF(grapplePoint[2]), 0 }, { PSF(grapplePoint[2]), 0 },
{ PSF(jumppad_ent), 10 }, { PSF(jumppad_ent), 10 },
{ PSF(loopSound), 16 } { PSF(loopSound), 16 },
// QL additions
{ PSF(field_08c), 32 },
{ PSF(field_094), 8 },
{ PSF(field_09c), 8 },
{ PSF(lastJumpTime), 32 },
{ PSF(jumped), 1 },
{ PSF(field_1d4), 32 },
{ PSF(crouchSlideTimer), 32 },
{ PSF(forwardmove), 8 },
{ PSF(rightmove), 8 },
{ PSF(upmove), 8 },
}; };
/* /*

View file

@ -10,6 +10,8 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "cgame", "cgame\cgame.vcxpro
EndProject EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "game", "game\game.vcxproj", "{F9EE10DA-2404-4154-B904-F93C936C040A}" Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "game", "game\game.vcxproj", "{F9EE10DA-2404-4154-B904-F93C936C040A}"
EndProject EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "q3_ui", "q3_ui\q3_ui.vcxproj", "{D454C4C7-7765-4149-ABAD-05FDEB9D94F8}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "quake3", "quake3.vcxproj", "{81CB51C4-B434-4E12-B69B-BAEE102F2852}" Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "quake3", "quake3.vcxproj", "{81CB51C4-B434-4E12-B69B-BAEE102F2852}"
EndProject EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "renderer", "renderer\renderer.vcxproj", "{AB424155-FBED-4D8D-B007-5B6CF93EA395}" Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "renderer", "renderer\renderer.vcxproj", "{AB424155-FBED-4D8D-B007-5B6CF93EA395}"
@ -56,6 +58,12 @@ Global
{F9EE10DA-2404-4154-B904-F93C936C040A}.Release TA|x86.Build.0 = Release TA|Win32 {F9EE10DA-2404-4154-B904-F93C936C040A}.Release TA|x86.Build.0 = Release TA|Win32
{F9EE10DA-2404-4154-B904-F93C936C040A}.Release|x86.ActiveCfg = Release|Win32 {F9EE10DA-2404-4154-B904-F93C936C040A}.Release|x86.ActiveCfg = Release|Win32
{F9EE10DA-2404-4154-B904-F93C936C040A}.Release|x86.Build.0 = Release|Win32 {F9EE10DA-2404-4154-B904-F93C936C040A}.Release|x86.Build.0 = Release|Win32
{D454C4C7-7765-4149-ABAD-05FDEB9D94F8}.Debug TA|x86.ActiveCfg = Debug|Win32
{D454C4C7-7765-4149-ABAD-05FDEB9D94F8}.Debug|x86.ActiveCfg = Debug|Win32
{D454C4C7-7765-4149-ABAD-05FDEB9D94F8}.Debug|x86.Build.0 = Debug|Win32
{D454C4C7-7765-4149-ABAD-05FDEB9D94F8}.Release TA|x86.ActiveCfg = Release|Win32
{D454C4C7-7765-4149-ABAD-05FDEB9D94F8}.Release|x86.ActiveCfg = Release|Win32
{D454C4C7-7765-4149-ABAD-05FDEB9D94F8}.Release|x86.Build.0 = Release|Win32
{81CB51C4-B434-4E12-B69B-BAEE102F2852}.Debug TA|x86.ActiveCfg = Debug TA|Win32 {81CB51C4-B434-4E12-B69B-BAEE102F2852}.Debug TA|x86.ActiveCfg = Debug TA|Win32
{81CB51C4-B434-4E12-B69B-BAEE102F2852}.Debug TA|x86.Build.0 = Debug TA|Win32 {81CB51C4-B434-4E12-B69B-BAEE102F2852}.Debug TA|x86.Build.0 = Debug TA|Win32
{81CB51C4-B434-4E12-B69B-BAEE102F2852}.Debug|x86.ActiveCfg = Debug|Win32 {81CB51C4-B434-4E12-B69B-BAEE102F2852}.Debug|x86.ActiveCfg = Debug|Win32

File diff suppressed because it is too large Load diff

View file

@ -560,18 +560,10 @@
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" /> <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets"> <ImportGroup Label="ExtensionTargets">
</ImportGroup> </ImportGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<_CopyOutputFile>$(SolutionDir)Debug\uix86_new.dll</_CopyOutputFile>
<_CopyOutputDir>$(SolutionDir)..\workdir\baseq3\</_CopyOutputDir>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug TA|Win32'"> <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug TA|Win32'">
<_CopyOutputFile>$(SolutionDir)Debug_TA\uix86.dll</_CopyOutputFile> <_CopyOutputFile>$(SolutionDir)Debug_TA\uix86.dll</_CopyOutputFile>
<_CopyOutputDir>$(SolutionDir)..\workdir\missionpack\</_CopyOutputDir> <_CopyOutputDir>$(SolutionDir)..\workdir\missionpack\</_CopyOutputDir>
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<_CopyOutputFile>$(SolutionDir)Release\uix86_new.dll</_CopyOutputFile>
<_CopyOutputDir>$(SolutionDir)..\workdir\baseq3\</_CopyOutputDir>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release TA|Win32'"> <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release TA|Win32'">
<_CopyOutputFile>$(SolutionDir)Release_TA\uix86.dll</_CopyOutputFile> <_CopyOutputFile>$(SolutionDir)Release_TA\uix86.dll</_CopyOutputFile>
<_CopyOutputDir>$(SolutionDir)..\workdir\missionpack\</_CopyOutputDir> <_CopyOutputDir>$(SolutionDir)..\workdir\missionpack\</_CopyOutputDir>

View file

@ -37,6 +37,10 @@ static unsigned short s_oldHardwareGamma[3][256];
*/ */
void WG_CheckHardwareGamma( void ) void WG_CheckHardwareGamma( void )
{ {
#ifndef ENABLE_HW_GAMMA
glConfig.deviceSupportsGamma = qfalse;
return;
#else
HDC hDC; HDC hDC;
glConfig.deviceSupportsGamma = qfalse; glConfig.deviceSupportsGamma = qfalse;
@ -96,6 +100,7 @@ void WG_CheckHardwareGamma( void )
} }
} }
} }
#endif // ENABLE_HW_GAMMA
} }
/* /*
@ -131,6 +136,9 @@ void mapGammaMax( void ) {
** This routine should only be called if glConfig.deviceSupportsGamma is TRUE ** This routine should only be called if glConfig.deviceSupportsGamma is TRUE
*/ */
void GLimp_SetGamma( unsigned char red[256], unsigned char green[256], unsigned char blue[256] ) { void GLimp_SetGamma( unsigned char red[256], unsigned char green[256], unsigned char blue[256] ) {
#ifndef ENABLE_HW_GAMMA
return;
#else
unsigned short table[3][256]; unsigned short table[3][256];
int i, j; int i, j;
int ret; int ret;
@ -188,6 +196,7 @@ void GLimp_SetGamma( unsigned char red[256], unsigned char green[256], unsigned
Com_Printf( "SetDeviceGammaRamp failed.\n" ); Com_Printf( "SetDeviceGammaRamp failed.\n" );
} }
} }
#endif // ENABLE_HW_GAMMA
} }
/* /*
@ -195,6 +204,9 @@ void GLimp_SetGamma( unsigned char red[256], unsigned char green[256], unsigned
*/ */
void WG_RestoreGamma( void ) void WG_RestoreGamma( void )
{ {
#ifndef ENABLE_HW_GAMMA
return;
#else
if ( glConfig.deviceSupportsGamma ) if ( glConfig.deviceSupportsGamma )
{ {
if ( qwglSetDeviceGammaRamp3DFX ) if ( qwglSetDeviceGammaRamp3DFX )
@ -210,5 +222,6 @@ void WG_RestoreGamma( void )
ReleaseDC( GetDesktopWindow(), hDC ); ReleaseDC( GetDesktopWindow(), hDC );
} }
} }
#endif // ENABLE_HW_GAMMA
} }