Git Repos / fte_dogmode / commit 347cc34
Commit: 347cc34a83e67b69ea1365775a58ae9991f16cb8
Parent: ebb8d538e43fa70c7719b4f30c744ac0ffebfa84
Author: Cameron Vanderzanden, 2024-07-17 11:21
Committer: Cameron Vanderzanden, 2024-07-17 11:21
Commit Message
pmove changes, smooth crouching I don't fully remember everything that changed here. (As usual). pmove_flags have changed, STARTGROUND and PRE_MOVE have been removed and ONRAMP and ONSLOPE have been added (plus more I might be forgetting). The code now tracks when a player is on a steep ramp surface that would not normally be considered ONGROUND (a slope); there's a TODO section of WalkAccelerate where custom acceleration for this state can be added. (Right now it limits the player to PM_Acceleration style movement). DanceMove (the slidemove) has been simplified a little bit. I've reworked the way it clips velocity; it now all happens within DanceMove and no longer needs an OVERCLIP value. (This is possible because I'm checking for interaction against 0 and was using an OVERCLIP of 1.0f, same as Quake 1.) I've managed to factor out one pointer and one (two?) floats as well. It should run faster now (profile_ssqc indicates that the acceleration functions are taking more time than the slidemove so those'll be the next target for optimization). The step handling in DanceMove has changed as well. It's a little volatile right now, might change again in the near future. The player should now be able to jump into the angle where stairs and a wall meet without getting caught on the stair/wall plane interaction. Unfortunately this seems to require a bunch of specialized checks (or the player will get stuck on other things or not correctly clip velocity). There's probably an elegant way to do this, I just haven't found it yet. I've also implemented smoothing for the change in view offset when crouching. (You no longer snap immediately from one view offset to another). That's all I can remember at the moment. I really need to finish implementing the V_CalcRefdef stuff (mainly cl_bob).
Change List
? | File | Add | Del |
---|---|---|---|
M | qc/Makefile | +1 | -1 |
M | qc/base_entities.qc | +2 | -33 |
M | qc/cl_entry.qc | +18 | -11 |
M | qc/defs_const.qc | +3 | -3 |
M | qc/func/door.qc | +3 | -3 |
M | qc/func/rotate.qc | +2 | -2 |
M | qc/items/backpacks.qc | -1 | |
M | qc/items/health.qc | -1 | |
M | qc/items/weapons.qc | -1 | |
M | qc/monsters/playerclient.qc | +96 | -71 |
M | qc/pmove.qc | +745 | -689 |
M | qc/sv_entry.qc | +3 | -1 |
M | qc/sv_progs.src | +1 | -1 |
M | qc/triggers/ladder.qc | +1 | -1 |
M | qc/triggers/push.qc | +1 | -1 |
M | qc/world.qc | +1 | -1 |
Diff qc/Makefile
diff --git a/qc/Makefile b/qc/Makefile
index 7bb90ba..bfbb90f 100644
--- a/qc/Makefile
+++ b/qc/Makefile
@@ -1,5 +1,5 @@
CC=fteqcc64
-CCOPTS=-Wall -O2 -Ffastarrays
+CCOPTS=-Wall -O3
client:
$(CC) $(CCOPTS) cl_progs.src
Return to the top of this page or return to the overview of this repo.
Diff qc/base_entities.qc
diff --git a/qc/base_entities.qc b/qc/base_entities.qc
index bf01003..d832f0a 100644
--- a/qc/base_entities.qc
+++ b/qc/base_entities.qc
@@ -116,9 +116,8 @@ entity damage_attacker; // set by T_Damage
.vector velocity_net; // based on the implementation in
.vector angles_net; // Nuclide -- CEV
.float flags_net;
-.float pmove_flags_net;
-.float crouchslide_timer_net;
-.float doublejump_timer_net;
+.float pm_flags_net;
+.float pm_timer_net;
#endif
//======================================================================
@@ -132,7 +131,6 @@ float() base_entity_parsemapdata;
#if defined(CSQC) || defined(SSQC)
void(entity e) base_entity_aligntoground;
void(entity e, entity p, float maxspeed) base_entity_push;
-// int(entity e, vector pos) base_entity_tracecontents;
void(entity e) base_entity_positioncontents;
#endif
#ifdef SSQC
@@ -364,28 +362,11 @@ void() noclass;
};
//--------------------------------------------------------------
- // Nuclide's PMoveCustom_Contents function -- CEV
- //--------------------------------------------------------------
- /*
- int(entity e, vector pos) base_entity_tracecontents =
- {
- local int ohitcontents = e.hitcontentsmaski;
- e.hitcontentsmaski = -1;
- traceline (pos, pos, MOVE_EVERYTHING, e);
- e.hitcontentsmaski = ohitcontents;
- return trace_endcontentsi;
- };
- */
-
- //--------------------------------------------------------------
// Set waterlevel and watertype; based on checks from purecsqc's
// pmove.qc. Called by both monsters and players. -- CEV
//--------------------------------------------------------------
void(entity e) base_entity_positioncontents =
{
- /*
- local int contents = 0;
- */
local vector v = e.origin;
#ifdef SSQC
local float oldtype = e.contype;
@@ -395,18 +376,6 @@ void() noclass;
v_z = e.origin_z + e.mins_z + 1;
e.contype = pointcontents (v);
- /*
- contents = base_entity_tracecontents (e,v);
- if (contents & CONTENTBIT_WATER)
- e.contype = CONTENT_WATER;
- else if (contents & CONTENTBIT_SLIME)
- e.contype = CONTENT_SLIME;
- else if (contents & CONTENTBIT_LAVA)
- e.contype = CONTENT_LAVA;
- else
- e.contype = CONTENT_EMPTY;
- */
-
if (e.contype < CONTENT_SOLID)
{
if (e.classtype == CT_PLAYER)
Return to the top of this page or return to the overview of this repo.
Diff qc/cl_entry.qc
diff --git a/qc/cl_entry.qc b/qc/cl_entry.qc
index ad201af..3307333 100644
--- a/qc/cl_entry.qc
+++ b/qc/cl_entry.qc
@@ -42,11 +42,6 @@ entity view_pl; // handle to the local player entity
entity viewentity; // camera -- CEV
vector view_origin; // origin for viewentity -- CEV
vector view_angles; // +x=DOWN
-float view_step;
-float view_step_adjust;
-float view_step_disable;
-float view_step_oldz;
-float view_step_time;
__used var float physics_mode = 2; // 0 = not run, 1 = DP, 2 = movetypes
#endif
@@ -325,13 +320,13 @@ void(float vwidth, float vheight, float notmenu) CSQC_UpdateView =
else
{
// punchangle code from Ironwail -- CEV
- if (autocvar(v_gunkick, 1) &&
- (view_pl.punch2 || view_pl.punch1))
+ if (autocvar(v_gunkick, 1)) {
+ if (view_punch2 || view_punch1)
{
- view_angles_x += view_pl.punch2 + bound (0,
- (time - view_pl.punch_time) / 0.1f, 1) *
- (view_pl.punch1 - view_pl.punch2);
- }
+ view_angles_x += view_punch2 + bound (0,
+ (time - view_punch_time) / 0.1f, 1) *
+ (view_punch1 - view_punch2);
+ } }
// roll code from Ironwail -- CEV
local float rollspeed = autocvar (cl_rollspeed, 200);
@@ -395,6 +390,18 @@ void(float vwidth, float vheight, float notmenu) CSQC_UpdateView =
}
#endif
+ #if 0
+ local float count = getentity (0, -1);
+ local float i;
+ for (i = 0; i < count; i++)
+ {
+ if (getentity(i, GE_ACTIVE))
+ dprint (sprintf("CSQC_UpdateView: CSQC ent num %g, "
+ "origin %v\n",
+ i, getentity (i, GE_ORIGIN)));
+ }
+ #endif
+
// Revert back to using engine HUD?
if (nocsqc > 0)
return;
Return to the top of this page or return to the overview of this repo.
Diff qc/defs_const.qc
diff --git a/qc/defs_const.qc b/qc/defs_const.qc
index de6bb9b..ac17fdd 100644
--- a/qc/defs_const.qc
+++ b/qc/defs_const.qc
@@ -166,12 +166,12 @@ const float ATTN_FEET = 2;
const float ATTN_STATIC = 3; // even more attn. (good for torches)
const float CHAN_AUTO = 0; // sound channels; 0 never overrides
-const float CHAN_WEAPON = 1; // 1-7 always override a sound on that
-const float CHAN_VOICE = 2; // channel
+const float CHAN_WEAPON = 1; //
+const float CHAN_VOICE = 2; //
const float CHAN_ITEM = 3;
const float CHAN_BODY = 4;
const float CHAN_FEET = 5; // dedicated channel for steps -- CEV
-const float CHAN_SLIDE = 6; // dedicated channel for steps -- CEV
+const float CHAN_SLIDE = 6; //
const float VOL_MAX = 1.0; // sound volume: maximum
const float VOL_HIGH = 0.9; // sound volume: high
Return to the top of this page or return to the overview of this repo.
Diff qc/func/door.qc
diff --git a/qc/func/door.qc b/qc/func/door.qc
index 5e59602..00b21e8 100644
--- a/qc/func/door.qc
+++ b/qc/func/door.qc
@@ -724,14 +724,14 @@ Key doors are always wait -1.
//--------------------------------------------------------------
void(entity e) func_door_init =
{
- local string default_noise1;
- local string default_noise2;
-
e.classname = "func_door";
e.classtype = CT_FUNC_DOOR;
base_func_init (e);
#ifdef SSQC
+ local string default_noise1;
+ local string default_noise2;
+
// this.noise3 and this.noise4 can now be overridden by
// the mapper, but will be set to default values in
// keylock_init if necessary -- iw
Return to the top of this page or return to the overview of this repo.
Diff qc/func/rotate.qc
diff --git a/qc/func/rotate.qc b/qc/func/rotate.qc
index 5c0e45c..f7526d1 100644
--- a/qc/func/rotate.qc
+++ b/qc/func/rotate.qc
@@ -1199,7 +1199,7 @@ NONBLOCKING makes the brush non-solid. This is useless if VISIBLE is set.
e.customphysics = sub_null;
local vector savemin = e.mins;
local vector savemax = e.maxs;
- setmodelindex (e, e.modelindex);
+ // setmodelindex (e, e.modelindex);
setsize (e, savemin, savemax);
setorigin (e, e.origin);
if (e.model && e.model != "")
@@ -1227,7 +1227,7 @@ NONBLOCKING makes the brush non-solid. This is useless if VISIBLE is set.
{
e.solid = SOLID_BSP;
e.blocked = func_movewall_blocked;
- // e.SendEntity = base_func_netsend;
+ e.SendEntity = base_func_netsend;
e.SendFlags = BASE_FUNC_NET_ORIGIN |
BASE_FUNC_NET_SIZE | BASE_FUNC_NET_MODEL |
BASE_FUNC_NET_SPEED;
Return to the top of this page or return to the overview of this repo.
Diff qc/items/backpacks.qc
diff --git a/qc/items/backpacks.qc b/qc/items/backpacks.qc
index 0da8475..ecf557d 100644
--- a/qc/items/backpacks.qc
+++ b/qc/items/backpacks.qc
@@ -75,7 +75,6 @@ e.g. For 'You got a bunch of rockets!' the netname key would be
local string s;
local float acount, best, old, new;
- local entity stemp;
// from Copper -- dumptruck_ds
if (other.movetype == MOVETYPE_NOCLIP)
Return to the top of this page or return to the overview of this repo.
Diff qc/items/health.qc
diff --git a/qc/items/health.qc b/qc/items/health.qc
index 3612eaa..9c59eee 100644
--- a/qc/items/health.qc
+++ b/qc/items/health.qc
@@ -105,7 +105,6 @@ float (entity e, float healamount, float ignore) T_Heal =
return;
local float amount;
- local string s;
amount = self.healamount;
if (self.healtype == HEALTH_TYPE_MEGA)
Return to the top of this page or return to the overview of this repo.
Diff qc/items/weapons.qc
diff --git a/qc/items/weapons.qc b/qc/items/weapons.qc
index 09e278a..9b3aedf 100644
--- a/qc/items/weapons.qc
+++ b/qc/items/weapons.qc
@@ -154,7 +154,6 @@ void(entity e, float old, float new) deathmatch_weapon =
void() base_item_weapon_touch =
{
local float hadammo, best, new, old;
- local entity stemp;
local float leave;
if (sub_checkvalidtouch(other) == FALSE)
Return to the top of this page or return to the overview of this repo.
Diff qc/monsters/playerclient.qc
diff --git a/qc/monsters/playerclient.qc b/qc/monsters/playerclient.qc
index c7b827c..ed1f162 100644
--- a/qc/monsters/playerclient.qc
+++ b/qc/monsters/playerclient.qc
@@ -20,6 +20,10 @@ const vector PLAYER_CORPSE_AX_MINS = '-38.72 -5.83 -50.45';
const vector PLAYER_CORPSE_AX_MAXS = '28.73 33.85 30';
#endif
+#ifdef CSQC
+const float PLAYER_CROUCH_SMOOTH = 0.1f;
+#endif
+
#if defined(CSQC) || defined(SSQC)
enumflags
{
@@ -29,8 +33,8 @@ enumflags
PLAYER_NET_SIZE, // size has changed (mins, maxs)
PLAYER_NET_ANGLES, // player angles have changed
PLAYER_NET_VELOCITY, // velocity has changed
- PLAYER_NET_FLAGS, // .flags & .pmove_flags
- PLAYER_NET_TIMERS, // .crouchslide_timer, .doublejump_timer
+ PLAYER_NET_FLAGS, // .flags & .pm_flags
+ PLAYER_NET_TIMERS, // .pm_timer
PLAYER_NET_EFFECTS, // .sveffects has changed
PLAYER_NET_SOLID, // .solid and/or .movetype have changed
PLAYER_NET_ITEMS, // .items (& others) have changed
@@ -42,6 +46,20 @@ enumflags
// globals
//======================================================================
+#ifdef CSQC
+float view_offset; // view smoothing for crouching -- CEV
+float view_offset_old;
+float view_offset_finished;
+float view_punch1; // punchangle_x -- CEV
+float view_punch2;
+float view_punch_time;
+float view_step; // view smoothing for steps -- CEV
+float view_step_adjust;
+float view_step_disable;
+float view_step_oldz;
+float view_step_time;
+#endif
+
#ifdef SSQC
float modelindex_eyes;
float modelindex_player;
@@ -99,9 +117,6 @@ float modelindex_player;
#ifdef CSQC
.float commandframe;
-.float punch1;
-.float punch2;
-.float punch_time;
#endif
//======================================================================
@@ -317,7 +332,7 @@ $frame axattd1 axattd2 axattd3 axattd4 axattd5 axattd6
self.origin_z = ReadCoord ();
}
- // we can safely infer PLAYER_NET_SIZE from .pmove_flags;
+ // we can safely infer PLAYER_NET_SIZE from .pm_flags;
// if it's necessary to transmit size (mins & maxs) in
// the future we'd do so here -- CEV
@@ -341,17 +356,14 @@ $frame axattd1 axattd2 axattd3 axattd4 axattd5 axattd6
self.flags = ReadFloat ();
newmoveflags = ReadFloat ();
}
-
- if (netflags & PLAYER_NET_TIMERS)
+ else
{
- /*
- local float cst1 = ReadShort() * 0.125;
- local float djt1 = ReadShort() * 0.125;
- */
- self.crouchslide_timer = ReadShort() * 0.125;
- self.doublejump_timer = ReadShort() * 0.125;
+ newmoveflags = self.pm_flags;
}
+ if (netflags & PLAYER_NET_TIMERS)
+ self.pm_timer = ReadFloat ();
+
if (netflags & PLAYER_NET_EFFECTS)
self.sveffects = ReadByte ();
@@ -369,33 +381,34 @@ $frame axattd1 axattd2 axattd3 axattd4 axattd5 axattd6
self.punchangle_x = ReadShort ();
// punchangle code from Ironwail -- CEV
- if (self.punch1 != self.punchangle_x)
+ if (self.entnum == player_localentnum) {
+ if (view_punch1 != self.punchangle_x)
{
- self.punch2 = self.punch1;
- self.punch1 = self.punchangle_x;
- self.punch_time = time;
- }
+ view_punch2 = view_punch1;
+ view_punch1 = self.punchangle_x;
+ view_punch_time = time;
+ } }
}
if (isnew && !(self.predraw))
{
- self.pmove_flags = newmoveflags;
+ self.pm_flags = newmoveflags;
player_init (self);
}
- else if (self.pmove_flags != newmoveflags)
+ else if (self.pm_flags != newmoveflags)
{
if (newmoveflags & PMF_CROUCHED &&
- (!(self.pmove_flags & PMF_CROUCHED)))
+ (!(self.pm_flags & PMF_CROUCHED)))
{
PM_CrouchStart ();
}
else if ((!(newmoveflags & PMF_CROUCHED)) &&
- self.pmove_flags & PMF_CROUCHED)
+ self.pm_flags & PMF_CROUCHED)
{
PM_CrouchStop ();
}
- self.pmove_flags = newmoveflags;
+ self.pm_flags = newmoveflags;
}
if (self.entnum == player_localentnum)
@@ -488,9 +501,8 @@ $frame axattd1 axattd2 axattd3 axattd4 axattd5 axattd6
e.velocity_net = e.velocity;
e.angles_net = e.angles;
e.flags_net = e.flags;
- e.pmove_flags_net = e.pmove_flags;
- e.crouchslide_timer_net = e.crouchslide_timer;
- e.doublejump_timer_net = e.doublejump_timer;
+ e.pm_flags_net = e.pm_flags;
+ e.pm_timer_net = e.pm_timer;
};
//--------------------------------------------------------------
@@ -502,9 +514,8 @@ $frame axattd1 axattd2 axattd3 axattd4 axattd5 axattd6
e.velocity = e.velocity_net;
e.angles = e.angles_net;
e.flags = e.flags_net;
- e.pmove_flags = e.pmove_flags_net;
- e.crouchslide_timer = e.crouchslide_timer_net;
- e.doublejump_timer = e.doublejump_timer_net;
+ e.pm_flags = e.pm_flags_net;
+ e.pm_timer = e.pm_timer_net;
if (e.commandframe < clientcommandframe - 128)
// avoid an infinite loop
@@ -528,7 +539,7 @@ $frame axattd1 axattd2 axattd3 axattd4 axattd5 axattd6
// step smoothing
local float view_diff = e.origin_z - view_step_oldz;
- if (view_step_disable == FALSE && e.pmove_flags & PMF_ONGROUND
+ if (view_step_disable == FALSE && e.pm_flags & PMF_ONGROUND
&& view_diff >= 4 && view_diff <= PM_STEPHEIGHT)
{
if (e.speed)
@@ -550,11 +561,30 @@ $frame axattd1 axattd2 axattd3 axattd4 axattd5 axattd6
/*
dprint (sprintf("player_prediction_preframe: "
- "pmove_step %g, step %g, step_adjust %g\n",
- view_pmove_step, view_step, view_step_adjust));
+ "pm_step %g, step %g, step_adjust %g\n",
+ view_pm_step, view_step, view_step_adjust));
*/
}
+ // smooth crouching (and other view offset Z changes) -- CEV
+ if (view_offset_finished > time)
+ {
+ if (view_offset_old != e.view_ofs_z)
+ {
+ local float z = 1 -
+ (view_offset_finished - time) /
+ PLAYER_CROUCH_SMOOTH;
+ view_offset = lerp_hermite (view_offset_old,
+ e.view_ofs_z, z);
+ }
+ }
+ else
+ {
+ if (view_offset_old != e.view_ofs_z)
+ view_offset_old = e.view_ofs_z;
+ view_offset = e.view_ofs_z;
+ }
+
view_step_oldz = e.origin_z;
view_origin = e.origin;
@@ -563,7 +593,7 @@ $frame axattd1 axattd2 axattd3 axattd4 axattd5 axattd6
view_origin_z -= (view_step_time - time) *
view_step_adjust * view_step;
- view_origin_z += e.view_ofs_z;
+ view_origin_z += view_offset;
};
//--------------------------------------------------------------
@@ -602,10 +632,10 @@ $frame axattd1 axattd2 axattd3 axattd4 axattd5 axattd6
if (f == FALSE)
// no input from client
- continue;
+ break;
if (input_timelength <= 0)
- continue;
+ break;
if (i == clientcommandframe)
CSQC_Input_Frame ();
@@ -650,7 +680,7 @@ $frame axattd1 axattd2 axattd3 axattd4 axattd5 axattd6
WriteCoord (MSG_ENTITY, self.origin_z);
}
- // we can safely infer PLAYER_NET_SIZE from .pmove_flags;
+ // we can safely infer PLAYER_NET_SIZE from .pm_flags;
// if it's necessary to transmit size (mins & maxs) in
// the future we'd do so here -- CEV
// if (netflags & PLAYER_NET_SIZE)
@@ -672,17 +702,11 @@ $frame axattd1 axattd2 axattd3 axattd4 axattd5 axattd6
if (netflags & PLAYER_NET_FLAGS)
{
WriteFloat (MSG_ENTITY, self.flags);
- WriteFloat (MSG_ENTITY, self.pmove_flags -
- (self.pmove_flags & PM_OMITFLAGS));
+ WriteFloat (MSG_ENTITY, self.pm_flags);
}
if (netflags & PLAYER_NET_TIMERS)
- {
- WriteShort (MSG_ENTITY,
- floor(self.crouchslide_timer * 8 + (1.0 / 16)));
- WriteShort (MSG_ENTITY,
- floor(self.doublejump_timer * 8 + (1.0 / 16)));
- }
+ WriteFloat (MSG_ENTITY, self.pm_timer);
if (netflags & PLAYER_NET_EFFECTS)
WriteByte (MSG_ENTITY, self.sveffects);
@@ -1212,8 +1236,8 @@ $frame axattd1 axattd2 axattd3 axattd4 axattd5 axattd6
// dir = aim (self, 100000);
makevectors (self.v_angle);
- org = self.origin + (v_forward * 10) + (v_right * 0) +
- (v_up * 8);
+ org = self.origin + (self.view_ofs - '0 0 16') +
+ (v_forward * 10) + (v_right * 0) + (v_up * 8);
dir = normalize (v_forward * BULLET_SPEED);
// 5 bullets instead of 6 -- CEV
@@ -1257,8 +1281,8 @@ $frame axattd1 axattd2 axattd3 axattd4 axattd5 axattd6
// dir = aim (self, 100000);
makevectors (self.v_angle);
- org = self.origin + (v_forward * 10) + (v_right * 0) +
- (v_up * 8);
+ org = self.origin + (self.view_ofs - '0 0 16') +
+ (v_forward * 10) + (v_right * 0) + (v_up * 8);
dir = normalize (v_forward * BULLET_SPEED);
// 12 bullets instead of 14 -- CEV
@@ -1279,6 +1303,7 @@ $frame axattd1 axattd2 axattd3 axattd4 axattd5 axattd6
void(float offset) player_fire_spikes =
{
local vector dir;
+ local vector org = self.origin + self.view_ofs;
makevectors (self.v_angle);
@@ -1307,10 +1332,9 @@ $frame axattd1 axattd2 axattd3 axattd4 axattd5 axattd6
// seven Nailgun position fix - thanks to Greenwood
// -- dumptruck_ds
- spawn_projectile_spike (self,
- self.origin + self.view_ofs + v_up * -8 +
- v_right * (offset * 0.5),
- dir, SPIKE_NORMAL_DAMAGE);
+ org += v_up * -8 + v_right * (offset * 0.5);
+
+ spawn_projectile_spike (self, org, dir, SPIKE_NORMAL_DAMAGE);
self.punchangle_x = -2;
// self.SendFlags |= PLAYER_NET_PUNCHANGLE;
@@ -1322,6 +1346,7 @@ $frame axattd1 axattd2 axattd3 axattd4 axattd5 axattd6
void() player_fire_superspikes =
{
local vector dir;
+ local vector org = self.origin + (self.view_ofs - '0 0 4');
sound (self, CHAN_WEAPON, "weapons/spike2.wav",
VOL_HIGH, ATTN_NORM);
@@ -1335,8 +1360,7 @@ $frame axattd1 axattd2 axattd3 axattd4 axattd5 axattd6
// seven Nailgun position fix - thanks to Greenwood
// -- dumptruck_ds
- spawn_projectile_spike (self, self.origin + '0 0 16',
- dir, SPIKE_SUPER_DAMAGE);
+ spawn_projectile_spike (self, org, dir, SPIKE_SUPER_DAMAGE);
self.punchangle_x = -2;
// self.SendFlags |= PLAYER_NET_PUNCHANGLE;
@@ -1348,6 +1372,7 @@ $frame axattd1 axattd2 axattd3 axattd4 axattd5 axattd6
void() player_fire_grenade =
{
local vector missile_velocity = '0 0 0';
+ local vector org = self.origin + (self.view_ofs - '0 0 8');
self.currentammo = self.ammo_rockets = self.ammo_rockets - 1;
@@ -1373,7 +1398,7 @@ $frame axattd1 axattd2 axattd3 axattd4 axattd5 axattd6
missile_velocity_z = 200;
}
- spawn_projectile_grenade (self, self.origin, missile_velocity);
+ spawn_projectile_grenade (self, org, missile_velocity);
};
//--------------------------------------------------------------
@@ -1400,6 +1425,7 @@ $frame axattd1 axattd2 axattd3 axattd4 axattd5 axattd6
//--------------------------------------------------------------
void() player_fire_rocket =
{
+ local vector org = self.origin + (self.view_ofs - '0 0 8');
local vector missile_velocity = '0 0 0';
self.currentammo = self.ammo_rockets = self.ammo_rockets - 1;
@@ -1415,9 +1441,9 @@ $frame axattd1 axattd2 axattd3 axattd4 axattd5 axattd6
missile_velocity = aim (self, 1000);
missile_velocity *= ROCKET_SPEED;
- spawn_projectile_rocket (self,
- self.origin + v_forward * 8 + '0 0 16',
- missile_velocity);
+ org += v_forward * 8;
+
+ spawn_projectile_rocket (self, org, missile_velocity);
};
//--------------------------------------------------------------
@@ -1454,8 +1480,7 @@ $frame axattd1 axattd2 axattd3 axattd4 axattd5 axattd6
self.currentammo = self.ammo_cells = self.ammo_cells - 1;
// TODO CEV
- // local vector org = self.origin;
- local vector org = self.origin + '0 0 16';
+ local vector org = self.origin + (self.view_ofs - '0 0 8');
makevectors (self.v_angle);
// set player to SOLID_BBOX, trace, then revert that change,
@@ -1727,7 +1752,7 @@ $frame axattd1 axattd2 axattd3 axattd4 axattd5 axattd6
return;
// no steps when crouching
- if (self.pmove_flags & PMF_CROUCHED)
+ if (self.pm_flags & PMF_CROUCHED)
return;
// at least 200ms between steps
@@ -2298,7 +2323,7 @@ $frame axattd1 axattd2 axattd3 axattd4 axattd5 axattd6
if (self.health < 0)
return;
- if (self.conlevel != 3)
+ if (self.conlevel != WATERLEVEL_EYES)
{
if (self.air_finished < time)
sound (self, CHAN_VOICE, "player/gasp2.wav",
@@ -2324,14 +2349,14 @@ $frame axattd1 axattd2 axattd3 axattd4 axattd5 axattd6
}
}
- if (!self.conlevel)
+ if (self.conlevel == WATERLEVEL_NONE)
{
if (self.flags & FL_INWATER)
{
// play leave water sound
- sound (self, CHAN_BODY, "misc/outwater.wav",
+ sound (self, CHAN_AUTO, "misc/outwater.wav",
VOL_HIGH, ATTN_NORM);
- self.flags = self.flags - FL_INWATER;
+ self.flags &= ~FL_INWATER;
}
return;
}
@@ -2370,16 +2395,16 @@ $frame axattd1 axattd2 axattd3 axattd4 axattd5 axattd6
{
// player enter water sound
if (self.contype == CONTENT_LAVA)
- sound (self, CHAN_BODY, "player/inlava.wav",
+ sound (self, CHAN_AUTO, "player/inlava.wav",
VOL_HIGH, ATTN_NORM);
if (self.contype == CONTENT_WATER)
- sound (self, CHAN_BODY, "player/inh2o.wav",
+ sound (self, CHAN_AUTO, "player/inh2o.wav",
VOL_HIGH, ATTN_NORM);
if (self.contype == CONTENT_SLIME)
- sound (self, CHAN_BODY, "player/slimbrn2.wav",
+ sound (self, CHAN_AUTO, "player/slimbrn2.wav",
VOL_HIGH, ATTN_NORM);
- self.flags = self.flags + FL_INWATER;
+ self.flags |= FL_INWATER;
self.damage_time = 0;
}
};
@@ -2997,7 +3022,7 @@ $frame axattd1 axattd2 axattd3 axattd4 axattd5 axattd6
e.velocity = '0 0 0';
setmodelindex (e, e.modelindex);
- if (e.pmove_flags & PMF_CROUCHED)
+ if (e.pm_flags & PMF_CROUCHED)
setsize (e, PM_CROUCH_MIN, PM_CROUCH_MAX);
else
setsize (e, PM_STAND_MIN, PM_STAND_MAX);
Return to the top of this page or return to the overview of this repo.
Diff qc/pmove.qc
diff --git a/qc/pmove.qc b/qc/pmove.qc
index 6bd0f28..9ab2f11 100644
--- a/qc/pmove.qc
+++ b/qc/pmove.qc
@@ -4,8 +4,7 @@
// TODO CEV: improved player unstick function
// TODO CEV: varied sounds (different jump sounds)
-// TODO CEV: bug where client and server disagree on vertical height
-// when stepping up onto a tall object (40 units? 42?)
+// TODO CEV: fix telejump check (teleporter time isn't networked to CSQC)
//======================================================================
// globals
@@ -28,9 +27,8 @@ vector input_movevalues; // movement requested by client
// note: timers are expensive, require synch between server and client -- CEV
// .entity groundentity; // already defined in entvars_t
.vector groundnormal;
-.float pmove_flags; // custom movement flags -- CEV
-.float crouchslide_timer; // crouchslide countdown timer
-.float doublejump_timer; // time in which a player can doublejump
+.float pm_flags; // custom movement flags -- CEV
+.float pm_timer; // crouchslide & jump timer -- CEV
.void() customphysics;
#endif
@@ -41,16 +39,16 @@ vector input_movevalues; // movement requested by client
#if defined(CSQC) || defined(SSQC)
// acceleration & friction
const float PM_AIRACCEL = 8.0f; // 10 in Q1; speed gain reduced by
-const float PM_AIRACCELSCALE = 0.25f; // multiplying by this const
-const float PM_AIRACCELQ3 = 0.8f; // 1.0 in Q3 ?; now 0.8 / 0.9
+const float PM_AIRACCELSCALE = 0.5f; // multiplying by this const
+const float PM_AIRACCELQ3 = 0.8f; // 1.0 in Q3 ?; now 0.8
const float PM_AIRACCELFWD = 0.8f; // 1 feels close to Q3 / CPM
const float PM_AIRACCELBACK = 5.0f; // Air stop speed in Q3? 5.0f?
const float PM_AIRACCELBASE = 32.0f; // PM_MAXSPEED / 10.0
const float PM_AIRACCELTURN = 250.0f; // affects +fwd turning radius; 150.0f
const float PM_GROUNDACCEL = 10.0f; // 10 is Q1, 15 is CPM
const float PM_GROUNDFRICTION = 6.0f; // 4 for Q1, 6 for Q3, 8 for (old?) CPM
-const float PM_SLIDEACCEL = 1.01f; // crouchslide accel; 10; 8? 4?
-const float PM_SLIDEFRICTION = 0.01f; // crouchslide friction; 1.0?
+const float PM_SLIDEACCEL = 1.0f; // crouchslide accel; 10; 8? 4?
+const float PM_SLIDEFRICTION = 0.25f; // crouchslide friction; 1.0?
const float PM_WATERACCEL = 10.0f; // water acceleration
const float PM_WATERFRICTION = 4.0f; // friction in water
@@ -86,20 +84,20 @@ const float PM_WALLCLIP_WINDOW = 0.15f; // 0.4 - 0.25
// misc
#define PM_MAXWISHMULT (PM_MAXWISHSPEED - PM_MAXSPEED) / PM_DOUBLEJUMP_WINDOW
+#define PM_MAXSTEPMULT PM_STEPHEIGHT / PM_DOUBLEJUMP_WINDOW
const float PM_CLIMBSCALE = 0.75; // scale XY vel by this while climbing
-const float PM_MAX_CLIP_PLANES = 4; // counting ground and self.velocity
+const float PM_MAX_CLIP_PLANES = 3; // counting ground and self.velocity
const float PM_MAXVELOCITY = 4095; // 32768 / 8.0; vel networked as short
-const float PM_OVERCLIP = 1.0f; // Q3 OVERCLIP is 1.001f, Q1 1.0f
-const float PM_ONESIDEDCLIP = -0.1f; // -0.001, -0.01, -0.1
+const float PM_OVERCLIP = 1.001f; // Q3 OVERCLIP is 1.001f, Q1 1.0f
const float PM_STEPHEIGHT = 18.0f; // 18 for Q1, 22 for later games?
-const float PM_PLANE_FLAT = 1.0f;
-const float PM_PLANE_GROUND = 0.7f;
-const float PM_PLANE_VERTICAL = 0.0f;
+const float PM_PLANE_FLAT = 1.0f; // flat horizontal
+const float PM_PLANE_GROUND = 0.7f; // above this is ONGROUND
+const float PM_PLANE_VERTICAL = 0.0f; // straight up vertical
const vector PM_TELEDROP = '0 0 -64'; // drop teleporter exit to floor if
#if defined(SSQC) // floor is within this distance
-const float PM_MOVEFLAGS = MOVE_LAGGED;
+const float PM_MOVEFLAGS = MOVE_NORMAL;
#elif defined(CSQC)
-const float PM_MOVEFLAGS = MOVE_LAGGED; // is MOVE_LAGGED supported in CSQC?
+const float PM_MOVEFLAGS = MOVE_NORMAL; // is MOVE_LAGGED supported in CSQC?
#endif
// water level
@@ -115,7 +113,7 @@ const vector PM_CROUCH_MIN = '-16 -16 -24';
const vector PM_CROUCH_MAX = '16 16 16'; // Q3 crouch MAX_z is 16 -- CEV
// Player View Offset
-// Q1 ranger's view offset is lower than Q3; is Q1 ranger canonically shorter?
+// Q1 Ranger's view offset is lower than Q3; is Q1 Ranger canonically shorter?
const vector PM_STAND_VIEWOFS = '0 0 22'; // Q3 default 0 0 26 -- CEV
const vector PM_CROUCH_VIEWOFS = '0 0 8'; // Q3 crouch 0 0 12 -- CEV
@@ -133,7 +131,8 @@ enumflags
PMF_JUMP_HELD, // player is holding the jump key
PMF_ONLADDER, // entity is on a ladder
PMF_ONGROUND, // entity is on ground
- PMF_STARTGROUND, // entity started the move on ground
+ PMF_ONRAMP, // entity is on a ramp
+ PMF_ONSLOPE, // entity is on a steep slope
PMF_CROUCH_HELD, // player is holding the crouch key
PMF_CROUCHED, // entity is crouching
PMF_CROUCHSLIDE, // entity is crouch sliding
@@ -144,7 +143,6 @@ enumflags
PMF_WATERJUMPED, // entity has waterjumped
PMF_CLIMB, // entity is climbing
PMF_PUSHED, // entity moved by a trigger_push
- PMF_PRE_MOVE, // hint that origin hasn't updated yet
PMF_SLIDE_GRAVITY, // slidemove hint to apply gravity
PMF_SLIDE_SKIM, // slidemove hint to skim/wallclip
PMF_SLIDE_STEP, // slidemove hint to traverse steps
@@ -152,9 +150,8 @@ enumflags
};
// don't transmit these flags from server to client -- CEV
-const float PM_OMITFLAGS = PMF_JUMP_HELD | PMF_STARTGROUND | PMF_CROUCH_HELD |
- PMF_PRE_MOVE | PMF_SLIDE_GRAVITY | PMF_SLIDE_SKIM |
- PMF_SLIDE_STEP | PMF_SLIDE_STICKY;
+const float PM_SLIDEFLAGS = PMF_SLIDE_GRAVITY |
+ PMF_SLIDE_SKIM | PMF_SLIDE_STEP | PMF_SLIDE_STICKY;
#endif
//======================================================================
@@ -170,25 +167,29 @@ static void(entity ent) PM_DoTouch;
vector(vector v) PM_TruncateVector;
void() PM_CheckVelocity;
float() PM_Nudge;
-vector(vector vel, vector normal) PM_ClipVelocity;
-void(entity e, vector plane, vector pos, float frac, float fl) PM_SetOnGround;
+vector(vector vel, vector normal, float overbounce) PM_ClipVelocity;
+void(float fl) PM_SetOnGround;
void() PM_DanceMove;
void() PM_CategorizePosition;
void(float friction, float move_time) PM_Friction;
void(vector dir, float wishspeed, float accel, float move_time) PM_Accelerate;
-void(vector vel, vector dir, float wishspeed, float move_time) PM_AirAccelerate;
+void(vector dir, float wishspeed, float move_time) PM_AirAccelerate;
void(vector dir, float wishspeed, float move_time) PM_AirControl;
void() PM_CrouchStart;
void() PM_CrouchStop;
void() PM_CrouchSlideStart;
void() PM_CrouchSlideStop;
void() PM_Jump;
+void(float grounddist) PM_WallClimb;
void() PM_WallJump;
+void() PM_WallJumpCheck;
float(float wishspeed) PM_GroundBoostWishSpeed;
-void(float move_time) PM_WalkAccelerate;
-void(float move_time) PM_SwimAccelerate;
-void(float scale, float move_time) PM_NoClipAccelerate;
-void(float move_time) PM_ManageTimers;
+void(vector wishvel, float move_time) PM_WalkPreMove;
+void(vector wishvel, float move_time) PM_WalkAccelerate;
+void(vector wishvel, float move_time) PM_SwimPreMove;
+void(vector wishvel, float move_time) PM_SwimAccelerate;
+void(vector wishvel, float scale, float move_time) PM_NoClipAccelerate;
+void(float move_time) PM_ManageTimer;
void(entity e) PM_Move;
#endif
@@ -239,7 +240,7 @@ static void(entity ent) PM_DoTouch =
};
//----------------------------------------------------------------------
-// PM_TruncateVector - truncate a vector to network precision
+// PM_TruncateVector - truncate a vector to network precision (short) -- CEV
//----------------------------------------------------------------------
vector(vector v) PM_TruncateVector =
{
@@ -255,19 +256,12 @@ vector(vector v) PM_TruncateVector =
//----------------------------------------------------------------------
void() PM_CheckVelocity =
{
- // could use bound here, this might be faster? -- CEV
- if (self.velocity_x > PM_MAXVELOCITY)
- self.velocity_x = PM_MAXVELOCITY;
- if (self.velocity_x < -PM_MAXVELOCITY)
- self.velocity_x = -PM_MAXVELOCITY;
- if (self.velocity_y > PM_MAXVELOCITY)
- self.velocity_y = PM_MAXVELOCITY;
- if (self.velocity_y < -PM_MAXVELOCITY)
- self.velocity_y = -PM_MAXVELOCITY;
- if (self.velocity_z > PM_MAXVELOCITY)
- self.velocity_z = PM_MAXVELOCITY;
- if (self.velocity_z < -PM_MAXVELOCITY)
- self.velocity_z = -PM_MAXVELOCITY;
+ self.velocity_x = bound (-PM_MAXVELOCITY, self.velocity_x,
+ PM_MAXVELOCITY);
+ self.velocity_y = bound (-PM_MAXVELOCITY, self.velocity_y,
+ PM_MAXVELOCITY);
+ self.velocity_z = bound (-PM_MAXVELOCITY, self.velocity_z,
+ PM_MAXVELOCITY);
}
//----------------------------------------------------------------------
@@ -277,14 +271,8 @@ void() PM_CheckVelocity =
//----------------------------------------------------------------------
float() PM_Nudge =
{
- #if defined(CSQC)
- dprint ("PM_Nudge: client player attempting to nudge out of a ");
- #elif defined(SSQC)
- dprint ("PM_Nudge: server player attempting to nudge out of a ");
- #endif
- dprint (sprintf("%s!\n", trace_ent.classname));
-
- vector test, org = self.origin;
+ vector test, org;
+ test = org = self.origin;
// check current position.
tracebox (org, self.mins, self.maxs, org, PM_MOVEFLAGS, self);
@@ -324,23 +312,15 @@ float() PM_Nudge =
//----------------------------------------------------------------------
// PM_ClipVelocity -- slide off the impacting surface -- CEV
//----------------------------------------------------------------------
-vector(vector vel, vector normal) PM_ClipVelocity =
+vector(vector vel, vector normal, float overbounce) PM_ClipVelocity =
{
- // I got tired of copy-and-pasting this. Here's hoping making
- // it a separate function won't slow things down -- CEV
+ // the same implementation used in Quake 3 -- CEV
local float backoff = vel * normal;
if (backoff < 0)
- backoff *= PM_OVERCLIP;
+ backoff *= overbounce;
else
- if (normal_z > PM_PLANE_GROUND)
- // only stick to the floor if flagged to do so -- CEV
- if (self.pmove_flags & PMF_SLIDE_STICKY)
- backoff /= PM_OVERCLIP;
- else
- backoff *= PM_ONESIDEDCLIP;
- else
- backoff /= PM_OVERCLIP;
+ backoff /= overbounce;
vel -= normal * backoff;
return vel;
@@ -351,7 +331,7 @@ vector(vector vel, vector normal) PM_ClipVelocity =
// arguments in order are: ground entity, ground plane, ground trace
// end position, ground entity num (or PMG_* flag if negative) -- CEV
//----------------------------------------------------------------------
-void(entity g, vector plane, vector pos, float frac, float fl) PM_SetOnGround =
+void(float fl) PM_SetOnGround =
{
// flagged to skip checks and clear ONGROUND -- CEV
if (fl == PMG_NOGROUND)
@@ -360,117 +340,107 @@ void(entity g, vector plane, vector pos, float frac, float fl) PM_SetOnGround =
if (fl == PMG_TRACEGROUND)
{
// do a trace to check for ground -- CEV
- if (!(self.pmove_flags & PMF_DOUBLEJUMPED))
- {
- // TODO CEV clean up this next check somehow
- if (self.pmove_flags & PMF_STEPPED ||
- self.pmove_flags & PMF_AIRSTEPPED ||
- (self.doublejump_timer > 0 &&
- self.doublejump_timer < 0.35))
- {
- // trace farther down to find a floor
- // if we're setting up to stairjump;
- // this is really aggressive -- CEV
- tracebox (self.origin, self.mins, self.maxs,
- self.origin - [0, 0, 4],
- PM_MOVEFLAGS, self);
- }
- else
- {
- goto PM_SetOnGround_SmallTrace;
- }
- }
- else
- {
- PM_SetOnGround_SmallTrace:
- // '0 0 1' works well too -- CEV
- tracebox (self.origin, self.mins, self.maxs,
- self.origin - '0 0 0.250', PM_MOVEFLAGS, self);
- }
+ tracebox (self.origin, self.mins, self.maxs,
+ self.origin - '0 0 0.25', PM_MOVEFLAGS, self);
- g = trace_ent;
- plane = trace_plane_normal;
- pos = trace_endpos;
- frac = trace_fraction;
#ifdef CSQC
fl = trace_networkentity;
#endif
}
// onground if we hit something & it faces upwards
- if (frac < 1.0f && plane_z > PM_PLANE_GROUND)
+ if (trace_fraction < 1.0f)
{
- // on ground -- CEV
-
- // ranger likes the floor. keep in mind the requested end
- // position in the tracebox at the start of this func -- CEV
- if (self.origin != pos)
+ if (trace_plane_normal_z > PM_PLANE_GROUND)
{
- if (plane_z >= PM_PLANE_FLAT)
+ // on ground -- CEV
+
+ // start crouchsliding if: we just landed, we're
+ // holding crouch, we aren't already sliding, we're
+ // not in water, and we're going faster than run
+ // speed -- CEV
+ if (!(self.pm_flags & PMF_ONGROUND)) {
+ if (self.pm_flags & PMF_CROUCH_HELD) {
+ if (!(self.pm_flags & PMF_CROUCHSLIDE)) {
+ if (self.conlevel == 0) {
+ if (self.speed > PM_MAXSPEED)
{
- #if defined(CSQC)
- if (fl <= 0)
- #elif defined(SSQC)
- if (g.velocity == '0 0 0')
- #endif
- {
- setorigin (self, pos);
- }
- }
- }
+ PM_CrouchSlideStart ();
+ } } } } }
+
+ // set groundentity and groundnormal -- CEV
+ self.groundentity = trace_ent;
+ self.groundnormal = trace_plane_normal;
- // start crouchsliding if: we just landed, we're holding
- // crouch, we aren't already sliding, we're not in water,
- // and we're going faster than run speed -- CEV
- if (!(self.pmove_flags & PMF_ONGROUND)) {
- if (self.pmove_flags & PMF_CROUCH_HELD) {
- if (!(self.pmove_flags & PMF_CROUCHSLIDE)) {
- if (self.conlevel == 0) {
- if (self.speed > PM_MAXSPEED)
+ // now manage flags -- CEV
+ self.flags |= FL_ONGROUND;
+ self.pm_flags |= PMF_ONGROUND;
+ if (self.groundnormal_z < PM_PLANE_FLAT)
+ self.pm_flags |= PMF_ONRAMP;
+ else if (self.pm_flags & PMF_ONRAMP)
+ self.pm_flags &= ~PMF_ONRAMP;
+ self.pm_flags = self.pm_flags - (self.pm_flags &
+ (PMF_ONSLOPE | PMF_CLIMB | PMF_PUSHED |
+ PMF_WALLJUMPED));
+ }
+ else if (trace_plane_normal_z > PM_PLANE_VERTICAL)
{
- PM_CrouchSlideStart ();
- } } } } }
+ // on a steep slope
- // set groundentity if it changed -- CEV
- if (self.groundentity != g)
- self.groundentity = g;
+ // set groundentity and groundnormal -- CEV
+ self.groundentity = __NULL__;
+ self.groundnormal = '0 0 0';
- // store groundnormal for later -- CEV
- self.groundnormal = plane;
+ // now do flags -- CEV
+ self.flags &= ~FL_ONGROUND;
+ self.pm_flags |= PMF_ONSLOPE;
+ self.pm_flags = self.pm_flags - (self.pm_flags &
+ (PMF_ONRAMP | PMF_ONGROUND));
+
+ // don't crouchslide on a slope -- CEV
+ if (self.pm_flags & PMF_CROUCHSLIDE)
+ {
+ if (self.pm_timer < 0)
+ self.pm_timer = 0;
+ PM_CrouchSlideStop ();
+ }
+ }
+ else
+ {
+ // we probably shouldn't end up here -- CEV
+ goto PM_SetOnGround_NoGround;
+ }
#ifdef CSQC
- // don't smooth out steps when on a networked ent -- CEV
- if (fl > 0)
+ // don't smooth out steps when on a network ent -- CEV
+ if (fl > 0 || trace_ent.velocity != '0 0 0')
view_step_disable = TRUE;
else if (view_step_disable)
view_step_disable = FALSE;
#endif
-
- // set these pmove flags if not set -- CEV
- if (!(self.flags & FL_ONGROUND))
- self.flags |= FL_ONGROUND;
- if (!(self.pmove_flags & PMF_ONGROUND))
- self.pmove_flags |= PMF_ONGROUND;
-
- // clear these pmove flags if set -- CEV
- if (self.pmove_flags & PMF_CLIMB)
- self.pmove_flags &= ~PMF_CLIMB;
- if (self.pmove_flags & PMF_PUSHED)
- self.pmove_flags &= ~PMF_PUSHED;
- if (self.pmove_flags & PMF_WALLJUMPED)
- self.pmove_flags &= ~PMF_WALLJUMPED;
}
else
{
// not on ground, clear pmove flags & fields -- CEV
PM_SetOnGround_NoGround:
- if (self.groundentity != __NULL__)
- self.groundentity = __NULL__;
- self.groundnormal = __NULL__;
- if (self.flags & FL_ONGROUND)
- self.flags &= ~FL_ONGROUND;
- if (self.pmove_flags & PMF_ONGROUND)
- self.pmove_flags &= ~PMF_ONGROUND;
+ self.groundentity = __NULL__;
+ self.groundnormal = '0 0 0';
+ self.flags &= ~FL_ONGROUND;
+ self.pm_flags = self.pm_flags - (self.pm_flags &
+ (PMF_ONSLOPE | PMF_ONRAMP | PMF_ONGROUND));
+
+ // don't crouchslide in air -- CEV
+ if (self.pm_flags & PMF_CROUCHSLIDE)
+ {
+ if (self.pm_timer < 0)
+ self.pm_timer = 0;
+ PM_CrouchSlideStop ();
+ }
+
+ #ifdef CSQC
+ if (view_step_disable)
+ view_step_disable = FALSE;
+ #endif
}
};
@@ -491,7 +461,7 @@ void() PM_DanceMove =
{
local float grav = 0;
- if (self.pmove_flags & PMF_SLIDE_GRAVITY)
+ if (self.pm_flags & PMF_SLIDE_GRAVITY)
{
if (self.gravity)
grav = self.gravity;
@@ -509,17 +479,15 @@ void() PM_DanceMove =
goto PM_DanceMove_ClearFlags;
// declare and initialize variables -- CEV
- local vector end, plane1, plane2, norm_vel, start_vel;
- local float i, j, k, maxstep, stepz, time_left;
+ local vector end, plane1, plane2, start_vel;
+ local float i, j, k, time_left;
local entity touched_ent;
local vector *jp = __NULL__;
- local vector *kp = __NULL__;
end = plane1 = plane2 = '0 0 0';
- i = j = k = maxstep = stepz = 0;
+ i = j = k = 0;
time_left = input_timelength;
start_vel = self.velocity;
- norm_vel = normalize (self.velocity);
// attempt at most 4 moves, stopping early if time_left runs out,
// clipping velocity as we go -- CEV
@@ -530,26 +498,23 @@ void() PM_DanceMove =
tracebox (self.origin, self.mins, self.maxs, end,
PM_MOVEFLAGS, self);
- if (trace_allsolid || trace_startsolid)
+ if (trace_allsolid)
{
// self is in something else; attempt to nudge out
if (PM_Nudge())
continue;
else
- #if defined(CSQC)
- break;
- #elif defined(SSQC)
setorigin (self, self.oldorigin);
- #endif
// nah, we're stuck. don't build up falling damage
// but allow sideways acceleration -- CEV
#if defined(CSQC)
- dprint ("PM_DanceMove: client player entity stuck!\n");
+ dprint ("PM_DanceMove: client player entity stuck!");
#elif defined(SSQC)
- dprint ("PM_DanceMove: server player entity stuck!\n");
- self.velocity_z = 0;
+ dprint ("PM_DanceMove: server player entity stuck!");
#endif
+ self.velocity_z = 0;
+ dprint (sprintf(" timestamp %g\n", time));
break;
}
@@ -567,16 +532,12 @@ void() PM_DanceMove =
// integrated StepSlideMove from Nuclide / CSQCTest
// only attempt to step if there's time left, stepping was
// requested, and we hit a vertical plane -- CEV
- if (self.pmove_flags & PMF_SLIDE_STEP) {
+ if (self.pm_flags & PMF_SLIDE_STEP) {
if (time_left > 0) {
- if (trace_plane_normal_z == PM_PLANE_VERTICAL)
+ if (trace_plane_normal_z <= PM_PLANE_GROUND)
{
- // store the entity and plane normal from above
- // and set up a vec to track velocity changes in
+ // store the entity and plane normal from above in
// case we need to reject the step attempt -- CEV
- #ifdef CSQC
- local float first_net = trace_networkentity;
- #endif
local vector first_plane = trace_plane_normal;
local entity first_ent = trace_ent;
j = time_left;
@@ -586,6 +547,9 @@ void() PM_DanceMove =
tracebox (self.origin, self.mins, self.maxs,
trace_endpos, PM_MOVEFLAGS, self);
+ if (trace_allsolid)
+ goto PM_DanceMove_RejectStep;
+
local vector roof_plane = trace_plane_normal;
if (trace_fraction < 1.0f)
@@ -593,93 +557,88 @@ void() PM_DanceMove =
touched_ent = trace_ent;
// second: move forward
- stepz = trace_endpos_z - self.origin_z;
+ k = trace_endpos_z - self.origin_z;
end = trace_endpos + (self.velocity * j);
end_z = trace_endpos_z;
tracebox (trace_endpos, self.mins, self.maxs, end,
PM_MOVEFLAGS, self);
- if (trace_allsolid || trace_startsolid)
- {
- // reject the step if forward move ends in a
- // solid; in practice this never hits -- CEV
+ if (trace_allsolid)
goto PM_DanceMove_RejectStep;
- }
- else if (trace_plane_normal == first_plane)
- {
- // we hit the same plane we're trying to step
- // over so reject the step attempt. we might
- // manage to step on the next iteration of
- // the loop (wallrunning up stairs) -- CEV
- goto PM_DanceMove_RejectStep;
- }
- local vector fwd_plane = trace_plane_normal;
- j -= j * trace_fraction;
+ // if we hit the same plane we're trying to step over
+ // and we made no progress in the move then reject
+ // the step attempt -- CEV
+ if (trace_plane_normal == first_plane)
+ if (self.origin_x - trace_endpos_x == 0)
+ if (self.origin_y - trace_endpos_y == 0)
+ goto PM_DanceMove_RejectStep;
if (trace_fraction < 1.0f)
+ {
+ if (trace_plane_normal_z <= PM_PLANE_GROUND) {
+ if (trace_plane_normal_z != PM_PLANE_VERTICAL)
+ {
+ goto PM_DanceMove_RejectStep;
+ } }
+
if (trace_ent && trace_ent.touch)
touched_ent = trace_ent;
+ }
+
+ local vector fwd_plane = trace_plane_normal;
+ j -= j * trace_fraction;
// third: move down
end = trace_endpos;
- end_z -= stepz + 1;
- tracebox (trace_endpos, self.mins, self.maxs,
- end, PM_MOVEFLAGS, self);
+ end_z -= k;
+ tracebox (trace_endpos, self.mins, self.maxs, end,
+ PM_MOVEFLAGS, self);
- if (trace_allsolid || trace_startsolid)
- {
- // reject the step if down move ends in
- // a solid. again, never executes -- CEV
- goto PM_DanceMove_RejectStep;
- }
- else if (trace_plane_normal_z > PM_PLANE_GROUND)
+ if (trace_plane_normal_z <= PM_PLANE_GROUND)
+ if (trace_fraction < 1.0f)
+ goto PM_DanceMove_RejectStep;
+ else if (trace_plane_normal == fwd_plane)
+ goto PM_DanceMove_RejectStep;
+
+ if (!trace_allsolid)
{
- // update time_left, stepsize, origin,
- // velocity & touched_ent -- CEV
+ // accept the stepped move. update time_left,
+ // origin, touched_ent, store any planes
+ // that interact, then update flags -- CEV
time_left = j;
- stepz = trace_endpos_z - self.origin_z;
self.origin = trace_endpos;
if (trace_ent.touch)
touched_ent = trace_ent;
- // store roof_plane and fwd_plane if we
- // might clip velocity to them later -- CEV
+ if (roof_plane != trace_plane_normal) {
if (roof_plane != plane1) {
- if (roof_plane != plane2) {
- if (self.velocity * roof_plane < 0)
+ if (roof_plane != plane2)
{
plane2 = plane1;
plane1 = roof_plane;
} } }
+ if (fwd_plane != trace_plane_normal) {
if (fwd_plane != plane1) {
- if (fwd_plane != plane2) {
- if (self.velocity * fwd_plane < 0)
+ if (fwd_plane != plane2)
{
plane2 = plane1;
plane1 = fwd_plane;
} } }
- if (maxstep < stepz)
- maxstep = stepz;
-
- self.pmove_flags |= PMF_STEPPED;
+ self.pm_flags |= PMF_STEPPED;
- if (!(self.pmove_flags & PMF_ONGROUND))
- self.pmove_flags |= PMF_AIRSTEPPED;
+ if (!(self.pm_flags & PMF_ONGROUND))
+ self.pm_flags |= PMF_AIRSTEPPED;
}
else
{
// discard the step attempt -- CEV
PM_DanceMove_RejectStep:
- #ifdef CSQC
- trace_networkentity = first_net;
- #endif
- touched_ent = trace_ent = first_ent;
trace_plane_normal = first_plane;
- stepz = 0;
+ touched_ent = trace_ent = first_ent;
}
} } }
@@ -687,63 +646,63 @@ void() PM_DanceMove =
// flags and fields. the less we do here the better;
// let PM_CategorizePosition and PM_SetOnGround handle
// the rest at the start and end of PM_Move -- CEV
- if (trace_plane_normal_z > PM_PLANE_GROUND)
+ if (trace_plane_normal_z > PM_PLANE_VERTICAL)
{
- #ifdef CSQC
- // need to update this right away for client step
- // smoothing / view interpolation -- CEV
- if (trace_networkentity)
- view_step_disable = TRUE;
- else if (view_step_disable)
- view_step_disable = FALSE;
- #endif
-
- #ifdef SSQC
- // store impact info (see player_postthink) -- CEV
- if (self.velocity_z < self.jump_flag)
- self.jump_flag = self.velocity_z;
- #endif
- }
+ if (trace_plane_normal_z > PM_PLANE_GROUND)
+ {
+ self.groundnormal = trace_plane_normal;
- // from Q3 source: "if this is the same plane we hit
- // before, nudge velocity out along it, which fixes
- // some epsilon issues with non-axial planes" -- CEV
- for (j = 0; j < PM_MAX_CLIP_PLANES; j++)
- {
- // no arrays were harmed in this loop -- CEV
- if (j == 0) { jp = &self.groundnormal; }
- else if (j == 1) { jp = &norm_vel; }
- else if (j == 2) { jp = &plane1; }
- else if (j == 3) { jp = &plane2; }
+ #ifdef SSQC
+ // impact info (see player_postthink) -- CEV
+ if (self.velocity_z < self.jump_flag)
+ self.jump_flag = self.velocity_z;
+ #endif
+ }
- if (*jp)
- if (trace_plane_normal * *jp > 0.99f)
- self.velocity += trace_plane_normal;
+ // setting the PMF_ONGROUND bit at this point will
+ // introduce a ground friction frame -- CEV
+ if (self.groundnormal_z <= PM_PLANE_GROUND)
+ {
+ self.pm_flags &= ~PMF_ONGROUND;
+ self.pm_flags &= ~PMF_ONRAMP;
+ self.pm_flags |= PMF_ONSLOPE;
+ }
+ else if (self.groundnormal_z < PM_PLANE_FLAT)
+ {
+ // self.pm_flags |= PMF_ONGROUND;
+ self.pm_flags |= PMF_ONRAMP;
+ self.pm_flags &= ~PMF_ONSLOPE;
+ }
+ else
+ {
+ // self.pm_flags |= PMF_ONGROUND;
+ self.pm_flags &= ~PMF_ONRAMP;
+ self.pm_flags &= ~PMF_ONSLOPE;
+ }
}
- // clip velocity to the plane -- CEV
- // TODO CEV
- // if (self.velocity * norm_vel > 0)
- self.velocity = PM_ClipVelocity (self.velocity,
- trace_plane_normal);
+ // clip to the plane if velocity interacts with it -- CEV
+ k = self.velocity * trace_plane_normal;
+ if (k < 0)
+ self.velocity -= trace_plane_normal * k;
// loop over stored planes clipping velocity as needed;
// this block may look familiar, it's similar to the
// strategy used in Quake3's SlideMove -- CEV
for (j = 0; j < PM_MAX_CLIP_PLANES; j++)
{
- // again, not using arrays here -- CEV
+ // no arrays were harmed in this loop -- CEV
if (j == 0) { jp = &self.groundnormal; }
- else if (j == 1) { jp = &norm_vel; }
- else if (j == 2) { jp = &plane1; }
- else if (j == 3) { jp = &plane2; }
+ else if (j == 1) { jp = &plane1; }
+ else if (j == 2) { jp = &plane2; }
// test if plane interacts & is not current plane
if (*jp == trace_plane_normal) { continue; }
- if (self.velocity * *jp >= 0) { continue; }
+ k = self.velocity * *jp;
+ if (k >= 0) { continue; }
// clip to the plane -- CEV
- self.velocity = PM_ClipVelocity (self.velocity, *jp);
+ self.velocity -= *jp * k;
// test if move goes back into the first plane -- CEV
if (self.velocity * trace_plane_normal >= 0)
@@ -757,14 +716,14 @@ void() PM_DanceMove =
// see if we enter a third plane -- CEV
for (k = 0; k < PM_MAX_CLIP_PLANES; k++)
{
- if (k == 0) { kp = &self.groundnormal; }
- else if (k == 1) { kp = &norm_vel; }
- else if (k == 2) { kp = &plane1; }
- else if (k == 3) { kp = &plane2; }
-
if (k == j) { continue; }
- if (*kp == trace_plane_normal) { continue; }
- if (self.velocity * *kp >= 0) { continue; }
+
+ if (k == 0) { jp = &self.groundnormal; }
+ else if (k == 1) { jp = &plane1; }
+ else if (k == 2) { jp = &plane2; }
+
+ if (*jp == trace_plane_normal) { continue; }
+ if (self.velocity * *jp >= 0) { continue; }
// stop when 3 planes interact -- CEV
self.velocity = '0 0 0';
@@ -775,41 +734,61 @@ void() PM_DanceMove =
}
// store current plane and plane1 for the next pass -- CEV
- plane2 = plane1;
- plane1 = trace_plane_normal;
+ if (trace_plane_normal != self.groundnormal)
+ {
+ plane2 = plane1;
+ plane1 = trace_plane_normal;
+ }
- // touch last in case doing so alters trace_plane_normal -- CEV
+ // touch last in case doing so changes trace_plane_normal -- CEV
PM_DoTouch (touched_ent);
- if (self.velocity == '0 0 0') { break; }
+ // stop if we've turned against original velocity -- CEV
+ if (self.velocity * start_vel <= 0)
+ self.velocity = '0 0 0';
+
+ // stop the loop if velocity is now zero -- CEV
+ if (self.velocity == '0 0 0')
+ break;
}
- #if 0
- if (i > 0)
- dprint (sprintf("PM_DanceMove: move complete, "
- "i %g, time_left %g, velocity_z %g\n",
- i, time_left, self.velocity_z));
- #endif
+ // the loop above doesn't clip to the ground plane; if SLIDE_STICKY
+ // is set then make sure we do (for stairjumps) -- CEV
+ if (self.pm_flags & PMF_SLIDE_STICKY) {
+ if (self.groundnormal_z > PM_PLANE_GROUND)
+ {
+ k = self.velocity * self.groundnormal;
+ self.velocity -= self.groundnormal * k;
+ } }
- // if wallclipping / wall skimming was requested and we did not
- // step during the move and we lost speed then restore velocity -- CEV
- if (self.pmove_flags & PMF_SLIDE_SKIM)
- if (maxstep == 0)
- if (vlen(start_vel) > vlen(self.velocity))
- self.velocity = start_vel;
+ // if wall clipping / skimming was requested then restore velocity
+ if (self.pm_flags & PMF_SLIDE_SKIM)
+ {
+ j = self.velocity_z;
+ k = start_vel_z;
+ self.velocity = start_vel;
+
+ if (self.pm_flags & PMF_ONSLOPE)
+ self.velocity_z = min (j, k);
+ else if (!(self.pm_flags & PMF_PUSHED))
+ if (self.pm_flags & PMF_STEPPED)
+ self.velocity_z = j;
+ }
// final gravity check here -- CEV
- if (self.pmove_flags & PMF_SLIDE_GRAVITY)
+ if (self.pm_flags & PMF_SLIDE_GRAVITY)
self.velocity_z -= grav * 0.5f;
+ #if 0
+ if (i > 0)
+ dprint (sprintf("PM_DanceMove: move complete, "
+ "i %g, time_left %g, velocity_z %g\n",
+ i, time_left, self.velocity_z));
+ #endif
+
PM_DanceMove_ClearFlags:
// clear slide hint flags -- CEV
- self.pmove_flags = self.pmove_flags - (self.pmove_flags &
- (PMF_SLIDE_GRAVITY | PMF_SLIDE_SKIM | PMF_SLIDE_STEP |
- PMF_SLIDE_STICKY));
-
- // a final call to setorigin to update links -- CEV
- setorigin (self, self.origin);
+ self.pm_flags = self.pm_flags - (self.pm_flags & PM_SLIDEFLAGS);
};
//----------------------------------------------------------------------
@@ -823,20 +802,34 @@ void() PM_CategorizePosition =
// noclip is never on ground
if (self.groundentity != __NULL__)
self.groundentity = __NULL__;
- if (self.groundnormal != __NULL__)
- self.groundnormal = __NULL__;
- if (self.pmove_flags & PMF_DOUBLEJUMPED)
- self.pmove_flags &= ~PMF_DOUBLEJUMPED;
- if (self.pmove_flags & PMF_WALLJUMPED)
- self.pmove_flags &= ~PMF_WALLJUMPED;
- if (self.pmove_flags & PMF_ONGROUND)
- self.pmove_flags &= ~PMF_ONGROUND;
+ if (self.groundnormal != '0 0 0')
+ self.groundnormal = '0 0 0';
+ if (self.pm_flags & PMF_DOUBLEJUMPED)
+ self.pm_flags &= ~PMF_DOUBLEJUMPED;
+ if (self.pm_flags & PMF_WALLJUMPED)
+ self.pm_flags &= ~PMF_WALLJUMPED;
+ if (self.pm_flags & PMF_ONGROUND)
+ self.pm_flags &= ~PMF_ONGROUND;
if (self.flags & FL_ONGROUND)
self.flags &= ~FL_ONGROUND;
- if (self.pmove_flags & PMF_PUSHED)
- self.pmove_flags &= ~PMF_PUSHED;
- if (self.pmove_flags & PMF_CLIMB)
- self.pmove_flags &= ~PMF_CLIMB;
+ if (self.pm_flags & PMF_PUSHED)
+ self.pm_flags &= ~PMF_PUSHED;
+ if (self.pm_flags & PMF_CLIMB)
+ self.pm_flags &= ~PMF_CLIMB;
+
+ self.pm_timer = 0;
+ }
+ else if (self.velocity_z > 180)
+ {
+ // if Z velocity is greater than 180 and we're not on a
+ // ramp or a steep slope then assume we're not onground
+ // (an optimization from Warsow / Warfork) -- CEV
+ if (self.pm_flags & PMF_ONRAMP)
+ PM_SetOnGround (PMG_TRACEGROUND);
+ else if (self.pm_flags & PMF_ONSLOPE)
+ PM_SetOnGround (PMG_TRACEGROUND);
+ else
+ PM_SetOnGround (PMG_NOGROUND);
}
else
{
@@ -844,23 +837,29 @@ void() PM_CategorizePosition =
// setting onground here before the acceleration functions
// turns out to be faster (in my testing) than relying on
// DanceMove to correctly track ground state -- CEV
- PM_SetOnGround (world, '0 0 0', '0 0 0', 0, PMG_TRACEGROUND);
+ PM_SetOnGround (PMG_TRACEGROUND);
}
// set waterlevel and watertype -- CEV
base_entity_positioncontents (self);
// don't crouchslide in water -- CEV
- if (self.pmove_flags & PMF_CROUCHSLIDE)
- if (self.conlevel > WATERLEVEL_NONE)
- self.pmove_flags &= ~PMF_CROUCHSLIDE;
+ if (self.pm_flags & PMF_CROUCHSLIDE) {
+ if (self.pm_flags & PMF_ONGROUND) {
+ if (self.conlevel > WATERLEVEL_NONE)
+ {
+ if (self.pm_timer < 0)
+ self.pm_timer = 0;
+ PM_CrouchSlideStop ();
+ } } }
// can't be waterjumping if we're on ground
- if (self.conlevel == WATERLEVEL_NONE || self.pmove_flags & PMF_ONGROUND)
+ if (self.pm_flags & PMF_WATERJUMPED)
{
- if (self.pmove_flags & PMF_WATERJUMPED)
+ if (self.conlevel == WATERLEVEL_NONE ||
+ self.pm_flags & PMF_ONGROUND)
{
- self.pmove_flags &= ~PMF_WATERJUMPED;
+ self.pm_flags &= ~PMF_WATERJUMPED;
self.flags &= ~FL_WATERJUMP;
}
}
@@ -914,14 +913,13 @@ void(vector dir, float wishspeed, float accel, float move_time) PM_Accelerate =
//----------------------------------------------------------------------
// PM_AirAccelerate -- Quake 1 style air acceleration -- CEV
//----------------------------------------------------------------------
-void(vector vel, vector dir, float wishspeed, float move_time)
- PM_AirAccelerate =
+void(vector dir, float wishspeed, float move_time) PM_AirAccelerate =
{
local float newspeed, speed1, zspeed;
zspeed = self.velocity_z;
- self.velocity_z = vel_z = dir_z = 0;
- newspeed = min (vlen (vel), PM_MAXAIRSPEED);
+ self.velocity_z = dir_z = 0;
+ newspeed = min (wishspeed, PM_MAXAIRSPEED);
speed1 = self.velocity * dir;
speed1 = newspeed - speed1;
@@ -984,21 +982,18 @@ void(vector dir, float wishspeed, float move_time) PM_AirControl =
void() PM_CrouchStart =
{
// crouch
- self.pmove_flags |= PMF_CROUCHED;
- // self.pmove_flags |= PMF_CROUCH_HELD;
+ self.pm_flags |= PMF_CROUCHED;
+ // self.pm_flags |= PMF_CROUCH_HELD;
setsize (self, PM_CROUCH_MIN, PM_CROUCH_MAX);
self.view_ofs = PM_CROUCH_VIEWOFS;
#ifdef CSQC
- // TODO CEV
- /*
+ // smooth crouching -- CEV
if (self.entnum == player_localentnum)
{
- view_step_oldz = self.origin_z +
- (PM_STAND_VIEWOFS_z - PM_CROUCH_VIEWOFS_z);
- view_step_time = time - 1;
+ view_offset_old = PM_STAND_VIEWOFS_z;
+ view_offset_finished = time + PLAYER_CROUCH_SMOOTH;
}
- */
#endif
};
@@ -1010,20 +1005,17 @@ void() PM_CrouchStop =
PM_MOVEFLAGS, self);
if (!trace_startsolid && !trace_allsolid)
{
- self.pmove_flags &= ~PMF_CROUCHED;
+ self.pm_flags &= ~PMF_CROUCHED;
setsize (self, PM_STAND_MIN, PM_STAND_MAX);
self.view_ofs = PM_STAND_VIEWOFS;
#ifdef CSQC
- // TODO CEV
- /*
+ // smooth crouching -- CEV
if (self.entnum == player_localentnum)
{
- view_step_oldz = self.origin_z +
- (PM_CROUCH_VIEWOFS_z - PM_STAND_VIEWOFS_z);
- view_step_time = time - 1;
+ view_offset_old = PM_CROUCH_VIEWOFS_z;
+ view_offset_finished = time + PLAYER_CROUCH_SMOOTH;
}
- */
#endif
}
};
@@ -1037,7 +1029,7 @@ void() PM_CrouchStop =
//----------------------------------------------------------------------
void() PM_CrouchSlideStart =
{
- if (self.crouchslide_timer <= 0)
+ if (self.pm_timer >= 0)
{
#ifdef SSQC
sound (self, CHAN_AUTO, "player/slidestart.ogg",
@@ -1045,14 +1037,14 @@ void() PM_CrouchSlideStart =
sound (self, CHAN_SLIDE, "player/slide.ogg",
0.2, ATTN_FEET);
#endif
- self.crouchslide_timer = PM_CROUCHSLIDE_TIME;
+ self.pm_timer = -PM_CROUCHSLIDE_TIME;
}
#ifdef SSQC
dprint (sprintf("PM_CrouchSlideStart: lesgo %g\n", self.velocity_z));
#endif
- self.pmove_flags |= PMF_CROUCHSLIDE;
+ self.pm_flags |= PMF_CROUCHSLIDE;
};
//----------------------------------------------------------------------
@@ -1060,10 +1052,11 @@ void() PM_CrouchSlideStart =
//----------------------------------------------------------------------
void() PM_CrouchSlideStop =
{
+ self.pm_flags &= ~PMF_CROUCHSLIDE;
+
#ifdef SSQC
sound (self, CHAN_SLIDE, "misc/null.wav", 0.4, ATTN_FEET);
#endif
- self.pmove_flags &= ~PMF_CROUCHSLIDE;
};
//----------------------------------------------------------------------
@@ -1072,9 +1065,9 @@ void() PM_CrouchSlideStop =
void() PM_Jump =
{
// are we already waterjumping, or is jump being held?
- if (self.pmove_flags & PMF_WATERJUMPED)
+ if (self.pm_flags & PMF_WATERJUMPED)
return;
- if (self.pmove_flags & PMF_JUMP_HELD)
+ if (self.pm_flags & PMF_JUMP_HELD)
return;
#ifdef SSQC
@@ -1084,7 +1077,7 @@ void() PM_Jump =
// make sure we get at least jumpspeed upwards from the ground
// plane by clamping it first. necessary for rampjumps. -- CEV
- if (self.groundnormal)
+ if (self.groundnormal_z > PM_PLANE_GROUND)
if (self.velocity * self.groundnormal < 0)
self.velocity -= self.groundnormal *
(self.velocity * self.groundnormal);
@@ -1093,23 +1086,28 @@ void() PM_Jump =
if (self.velocity_z < 0)
self.velocity_z = 0;
- if (self.doublejump_timer > 0)
+ if (self.pm_timer > 0)
{
// it may be useful in the future (for a tricks mode, etc)
// to distinguish between different jump types -- CEV
if (self.teleport_time > time - (PM_TELEJUMP_WINDOW + 0.2))
+ {
// a teleport jump: allow a larger (+0.2) window to
// account for time to travel thru teleporter -- CEV
// non-additive jump, though it shouldn't matter -- CEV
self.velocity_z = PM_TELEJUMPSPEED;
- else if (self.groundnormal &&
- self.groundnormal_z >= PM_PLANE_FLAT)
- // don't do additive stairjumps on flat ground -- CEV
- self.velocity_z = PM_STAIRJUMPSPEED;
- else
- // the groundnormal might be weird - some kind of
- // ramp - so we want an additive doublejump here -- CEV
+ }
+ else if (self.pm_flags & PMF_ONRAMP)
+ {
+ // the groundnormal is weird - a ramp - so we
+ // want an additive doublejump here -- CEV
self.velocity_z += PM_DOUBLEJUMPSPEED;
+ }
+ else
+ {
+ // flat ground, don't do an additive jump -- CEV
+ self.velocity_z = PM_STAIRJUMPSPEED;
+ }
#ifdef SSQC
vol = 0.9;
@@ -1117,7 +1115,7 @@ void() PM_Jump =
#endif
// set the doublejump flag -- CEV
- self.pmove_flags |= PMF_DOUBLEJUMPED;
+ self.pm_flags |= PMF_DOUBLEJUMPED;
}
else
{
@@ -1129,17 +1127,17 @@ void() PM_Jump =
#endif
// do an additive jump on non-flat ground -- CEV
- if (self.groundnormal_z >= PM_PLANE_FLAT)
- self.velocity_z = PM_JUMPSPEED;
- else
+ if (self.pm_flags & PMF_ONRAMP)
self.velocity_z += PM_JUMPSPEED;
+ else
+ self.velocity_z = PM_JUMPSPEED;
}
// manage flags -- CEV
- PM_SetOnGround (world, '0 0 0', '0 0 0', 0, PMG_NOGROUND);
- self.pmove_flags |= PMF_JUMP_HELD;
+ PM_SetOnGround (PMG_NOGROUND);
+ self.pm_flags |= PMF_JUMP_HELD;
- if (self.pmove_flags & PMF_CROUCHSLIDE)
+ if (self.pm_flags & PMF_CROUCHSLIDE)
PM_CrouchSlideStop ();
#ifdef SSQC
@@ -1150,22 +1148,97 @@ void() PM_Jump =
#endif
// timers for all jumps -- CEV
- self.doublejump_timer = PM_DOUBLEJUMP_WINDOW;
+ self.pm_timer = PM_DOUBLEJUMP_WINDOW;
};
//----------------------------------------------------------------------
-// PM_WallJump -- Wall jumping, mantling, and climbing -- CEV
+// PM_WallClimb -- climbing; checks performed in PM_WallJumpCheck -- CEV
+//----------------------------------------------------------------------
+void(float grounddist) PM_WallClimb =
+{
+ // accelerate upwards toward a vertical ledge -- CEV
+ local float zspeed = self.velocity_z;
+ if (grounddist == 0)
+ grounddist = 1;
+ self.velocity *= PM_CLIMBSCALE;
+ self.velocity_z = bound (PM_CLIMBSPEED * 0.5f,
+ zspeed + (64.0f / grounddist) * PM_CLIMBSPEED,
+ PM_CLIMBSPEED * 2.0f);
+
+ self.pm_flags |= PMF_CLIMB;
+
+ #if 0
+ dprint (sprintf("PM_WallJumpCheck: climb, vel_z %g, "
+ "grounddist %g\n", self.velocity_z, grounddist));
+ #endif
+};
+
+//----------------------------------------------------------------------
+// PM_WallJump -- Perform an actual walljump -- CEV
//----------------------------------------------------------------------
void() PM_WallJump =
{
- // are we in water, waterjumping, walljumping,
+ #ifdef SSQC
+ local float vol = 0;
+ local string wav = "";
+ #endif
+
+ // bounce off the wall plane if Z velocity is positive -- CEV
+ // if we bounce off the wall plane when Z vel is negative it
+ // introduces a scenario where a player can fall off a ledge
+ // and then (for just a frame or two) jump off the wall
+ // behind them to gain additional XY speed. You can still
+ // walljump from that floor/wall you fell from now but you
+ // won't gain horizontal speed. (found this while attempting
+ // to circlejump over the center gap in CPM22) -- CEV
+ // if (self.velocity_z > 0)
+ self.velocity += trace_plane_normal * PM_WALLJUMPFORCE;
+
+ if (self.pm_timer > 0)
+ {
+ #ifdef SSQC
+ vol = 0.9;
+ wav = "player/plyrjmp8.wav";
+ #endif
+ self.velocity_z = PM_WALLJUMPDOUBLE;
+ }
+ else
+ {
+ #ifdef SSQC
+ local float r = rint (random() * 3);
+ vol = 0.2;
+ wav = sprintf ("player/jump0%g.ogg", r + 1);
+ #endif
+ self.velocity_z = PM_WALLJUMPSPEED;
+ }
+
+ // manage flags & fields -- CEV
+ self.pm_flags |= PMF_JUMP_HELD;
+ self.pm_flags |= PMF_WALLJUMPED;
+ self.pm_timer = PM_DOUBLEJUMP_WINDOW;
+
+ // server-side stuff
+ #ifdef SSQC
+ player_footstep ();
+ if (wav != "")
+ sound (self, CHAN_BODY, wav, vol, ATTN_NORM);
+ #endif
+};
+
+//----------------------------------------------------------------------
+// PM_WallJumpCheck -- Wall jumping, mantling, and climbing -- CEV
+//----------------------------------------------------------------------
+void() PM_WallJumpCheck =
+{
+ // are we in water, waterjumping, walljumping & climbing,
// or falling too fast? -- CEV
if (self.conlevel > WATERLEVEL_NONE)
return;
- if (self.pmove_flags & PMF_WATERJUMPED)
- return;
- if (self.pmove_flags & PMF_WALLJUMPED)
+ if (self.pm_flags & PMF_WATERJUMPED)
return;
+ if (self.pm_flags & PMF_WALLJUMPED)
+ if (self.pm_flags & PMF_CLIMB)
+ return;
if (self.velocity_z < PM_WALLJUMPLIMIT)
return;
@@ -1176,23 +1249,27 @@ void() PM_WallJump =
if (grounddist <= PM_WALLJUMPGROUND)
return;
- local float i;
- local float dot = 0;
+ local float i, checks;
local vector start, end;
+ checks = (self.pm_flags & PMF_WALLJUMPED ? 1 : 4);
start = end = self.origin;
- for (i = 0; i < 4; i++)
+ for (i = 0; i < checks; i++)
{
// I've borrowed a little logic from Quake Champions Classic
// here, shoutout to RhapsodyInGeek, check out their good work
// https://github.com/Quake-Champions-Classic/mod
- // v_forward and v_right should still correspond to the
+ // v_forward and v_right should still be those set by the
// makevectors call from PM_Move -- CEV
if (i < 2)
if (input_movevalues_x == 0)
continue;
else
- end = v_forward * 10;
+ // check further when +back -- CEV
+ if (i == 0)
+ end = v_forward * 10;
+ else if (i == 1)
+ end = v_forward * 25;
if (i > 1)
if (input_movevalues_y == 0)
continue;
@@ -1211,8 +1288,8 @@ void() PM_WallJump =
MOVE_NOMONSTERS | PM_MOVEFLAGS, self);
#if 0
- dprint (sprintf("PM_WallJump: frac %g, norm_z %g, dist %g\n",
- trace_fraction, trace_plane_normal_z,
+ dprint (sprintf("PM_WallJumpCheck: frac %g, norm_z %g, dist "
+ "%g\n", trace_fraction, trace_plane_normal_z,
vlen(self.origin - trace_endpos)));
#endif
@@ -1221,16 +1298,18 @@ void() PM_WallJump =
if (trace_plane_normal_z <= PM_PLANE_GROUND) {
if (trace_plane_normal_z >= 0)
{
- dot = self.velocity * trace_plane_normal;
- if (!(self.pmove_flags & PMF_JUMP_HELD) && dot >= 0)
+ if (!(self.pm_flags & PMF_JUMP_HELD)) {
+ if (!(self.pm_flags & PMF_WALLJUMPED)) {
+ if (self.velocity * trace_plane_normal >= 0)
{
// moving away from the wall, not holding
- // jump, and haven't walljumped -- CEV
- self.pmove_flags |= PMF_WALLJUMPED;
+ // jump, and haven't walljumped -- CEV
+ PM_WallJump ();
break;
- }
- else if (i == 0) {
- if (self.pmove_flags & PMF_JUMP_HELD) {
+ } } }
+
+ if (i == 0) {
+ if (self.pm_flags & PMF_JUMP_HELD) {
if (self.speed <= PM_MAXSPEED) {
if (fabs(self.velocity_z) < 90.0f) {
if (grounddist > 42)
@@ -1258,7 +1337,7 @@ void() PM_WallJump =
if (trace_fraction >= 1.0f)
{
- // ranger's fingies can't grip a
+ // Ranger's fingies can't grip a
// vertical surface -- CEV
traceline (trace_endpos,
trace_endpos - '0 0 64',
@@ -1271,7 +1350,7 @@ void() PM_WallJump =
grounddist = trace_endpos_z -
(self.origin_z +
self.mins_z);
- self.pmove_flags |= PMF_CLIMB;
+ PM_WallClimb (grounddist);
break;
}
}
@@ -1294,7 +1373,7 @@ void() PM_WallJump =
grounddist = trace_endpos_z -
(self.origin_z +
self.mins_z);
- self.pmove_flags |= PMF_CLIMB;
+ PM_WallClimb (grounddist);
break;
}
}
@@ -1304,72 +1383,7 @@ void() PM_WallJump =
} } }
// player can't hold on to thin air -- CEV
- if (self.pmove_flags & PMF_CLIMB)
- self.pmove_flags &= ~PMF_CLIMB;
- }
-
- if (self.pmove_flags & PMF_CLIMB)
- {
- // accelerate upwards toward a vertical ledge -- CEV
- local float zspeed = self.velocity_z;
- if (grounddist == 0)
- grounddist = 1;
- self.velocity *= PM_CLIMBSCALE;
- self.velocity_z = bound (PM_CLIMBSPEED * 0.5f,
- zspeed + (64.0f / grounddist) * PM_CLIMBSPEED,
- PM_CLIMBSPEED * 2.0f);
-
- #if 0
- dprint (sprintf("PM_WallJump: climb, vel_z %g, "
- "grounddist %g\n", self.velocity_z, grounddist));
- #endif
- }
- else if (self.pmove_flags & PMF_WALLJUMPED)
- {
- #ifdef SSQC
- local float vol = 0;
- local string wav = "";
- #endif
-
- // bounce off the wall plane if Z velocity is positive -- CEV
- // if we bounce off the wall plane when Z vel is negative it
- // introduces a scenario where a player can fall off a ledge
- // and then (for just a frame or two) jump off the wall
- // behind them to gain additional XY speed. You can still
- // walljump from that floor/wall you fell from now but you
- // won't gain horizontal speed. (found this while attempting
- // to circlejump over the center gap in CPM22) -- CEV
- if (self.velocity_z > 0)
- self.velocity += trace_plane_normal * PM_WALLJUMPFORCE;
-
- if (self.doublejump_timer > 0)
- {
- #ifdef SSQC
- vol = 0.9;
- wav = "player/plyrjmp8.wav";
- #endif
- self.velocity_z = PM_WALLJUMPDOUBLE;
- }
- else
- {
- #ifdef SSQC
- local float r = rint (random() * 3);
- vol = 0.2;
- wav = sprintf ("player/jump0%g.ogg", r + 1);
- #endif
- self.velocity_z = PM_WALLJUMPSPEED;
- }
-
- // manage flags & fields; PMF_WALLJUMPED is already set -- CEV
- self.pmove_flags |= PMF_JUMP_HELD;
- self.doublejump_timer = PM_DOUBLEJUMP_WINDOW;
-
- // server-side stuff
- #ifdef SSQC
- player_footstep ();
- if (wav != "")
- sound (self, CHAN_BODY, wav, vol, ATTN_NORM);
- #endif
+ self.pm_flags &= ~PMF_CLIMB;
}
};
@@ -1382,136 +1396,121 @@ float(float wishspeed) PM_GroundBoostWishSpeed =
// broke this up into multiple lines to improve readability -- CEV
local float wishnew;
- wishnew = ((self.doublejump_timer - PM_DOUBLEJUMP_WINDOW) * -1) *
- PM_MAXWISHMULT;
+ wishnew = (PM_DOUBLEJUMP_WINDOW - self.pm_timer) * PM_MAXWISHMULT;
wishnew = bound (PM_MAXSPEED, PM_MAXSPEED + wishnew, PM_MAXWISHSPEED);
return min (wishspeed, wishnew);
};
//----------------------------------------------------------------------
-// PM_WalkAccelerate -- accel & friction for MOVETYPE_WALK -- CEV
+// PM_WalkPreMove -- Check for crouching, jumping, ladders -- CEV
//----------------------------------------------------------------------
-void(float mt) PM_WalkAccelerate =
+void(vector wishvel, float move_time) PM_WalkPreMove =
{
- // only yaw matters here -- CEV
- makevectors (input_angles_y * '0 1 0');
-
- if (self.pmove_flags & PMF_PRE_MOVE)
+ if (self.pm_flags & PMF_ONLADDER)
{
- if (self.pmove_flags & PMF_ONLADDER)
- {
- // ladder physics
- self.velocity *= PM_CLIMBSCALE;
-
- if (input_buttons & INPUT_BUTTON2 ||
- input_movevalues_z > 0)
- {
- // PlayerClimb -- johnfitz
- self.velocity_z = PM_CLIMBSPEED;
- }
- else if (input_buttons & INPUT_BUTTON8 ||
- input_movevalues_z < 0)
- {
- // PlayerClimbDown -- CEV
- // self.pmove_flags |= PMF_CROUCH_HELD;
- self.velocity_z = -PM_CLIMBSPEED;
- }
- else
- {
- self.flags |= FL_JUMPRELEASED;
- self.pmove_flags &= ~PMF_JUMP_HELD;
- self.velocity_z = 0;
- }
+ // ladder physics
+ self.velocity *= PM_CLIMBSCALE;
- self.pmove_flags &= ~PMF_ONGROUND;
+ if (input_buttons & INPUT_BUTTON2 || input_movevalues_z > 0)
+ {
+ // PlayerClimb -- johnfitz
+ self.velocity_z = PM_CLIMBSPEED;
+ }
+ else if (input_buttons & INPUT_BUTTON8 || input_movevalues_z<0)
+ {
+ // PlayerClimbDown -- CEV
+ self.velocity_z = -PM_CLIMBSPEED;
}
else
{
- if (input_buttons & INPUT_BUTTON2)
- {
- // +jump was pressed
- if (self.pmove_flags & PMF_ONGROUND)
- // normal jump
- PM_Jump ();
- else if (world_walljump)
- // walljump
- PM_WallJump ();
- }
- else
- {
- self.flags |= FL_JUMPRELEASED;
- self.pmove_flags &= ~PMF_JUMP_HELD;
- }
-
- if (input_buttons & INPUT_BUTTON8 &&
- !(self.pmove_flags & PMF_CROUCHED))
- {
- PM_CrouchStart ();
- }
- else if (!(input_buttons & INPUT_BUTTON8) &&
- self.pmove_flags & PMF_CROUCHED)
- {
- PM_CrouchStop ();
- }
+ self.flags |= FL_JUMPRELEASED;
+ self.pm_flags &= ~PMF_JUMP_HELD;
+ self.velocity_z = 0;
}
- if (self.pmove_flags & PMF_ONGROUND)
- self.pmove_flags |= PMF_STARTGROUND;
+ self.pm_flags &= ~PMF_ONGROUND;
+ }
+ else
+ {
+ if (input_buttons & INPUT_BUTTON2)
+ {
+ // +jump was pressed
+ if (self.pm_flags & PMF_ONGROUND)
+ // normal jump
+ PM_Jump ();
+ else if (world_walljump)
+ // walljump
+ PM_WallJumpCheck ();
+ }
else
- self.pmove_flags &= ~PMF_STARTGROUND;
+ {
+ self.flags |= FL_JUMPRELEASED;
+ self.pm_flags &= ~PMF_JUMP_HELD;
+ }
+
+ if (input_buttons & INPUT_BUTTON8 &&
+ !(self.pm_flags & PMF_CROUCHED))
+ {
+ PM_CrouchStart ();
+ }
+ else if (!(input_buttons & INPUT_BUTTON8) &&
+ self.pm_flags & PMF_CROUCHED)
+ {
+ PM_CrouchStop ();
+ }
}
+};
- local vector vel;
- vel = v_forward * input_movevalues_x + v_right * input_movevalues_y;
- vel_z = 0;
- local float wish = vlen (vel);
- local vector dir = normalize (vel);
+//----------------------------------------------------------------------
+// PM_WalkAccelerate -- accel & friction for MOVETYPE_WALK -- CEV
+//----------------------------------------------------------------------
+void(vector wishvel, float mt) PM_WalkAccelerate =
+{
+ local vector dir = normalize (wishvel);
+ local float wish = vlen (wishvel);
- // Test STARTGROUND (the ONGROUND status post jump) to avoid
- // a ground friction frame when chaining jumps together.
- // Probably has unintended consequences. -- CEV
- if (self.pmove_flags & PMF_STARTGROUND)
+ // Test ONGROUND after we might've called PM_Jump to avoid a ground
+ // friction frame. Probably has unintended consequences. -- CEV
+ if (self.pm_flags & PMF_ONGROUND)
{
- if (self.pmove_flags & PMF_CROUCHSLIDE && self.conlevel == 0)
+ if (self.pm_flags & PMF_CROUCHSLIDE && self.conlevel == 0)
{
+ // movement while crouchsliding -- CEV
wish = min (wish, PM_MAXSPEED);
PM_Friction (PM_SLIDEFRICTION, mt);
- if (vel != '0 0 0') {
+ if (wishvel != '0 0 0') {
if (input_movevalues_x == 0)
{
- PM_AirAccelerate (vel, dir, wish, mt);
+ PM_AirAccelerate (dir, wish, mt);
}
- else
+ else if (input_movevalues_y == 0)
{
local float a1 = 0;
- if (input_movevalues_y == 0)
- {
- if (vel * self.velocity < 0)
- a1 = PM_AIRACCELBACK;
- else
- a1 = PM_AIRACCELFWD;
- PM_Accelerate (dir, wish, a1, mt);
- PM_AirControl (dir, wish, mt);
- }
+ if (wishvel * self.velocity < 0)
+ a1 = PM_AIRACCELBACK;
else
- {
- a1 = PM_SLIDEACCEL;
- PM_Accelerate (dir, wish, a1, mt);
- }
+ a1 = PM_AIRACCELFWD;
+ PM_Accelerate (dir, wish, a1, mt);
+ PM_AirControl (dir, wish, mt);
+ }
+ else
+ {
+ PM_Accelerate (dir, wish, PM_SLIDEACCEL, mt);
} }
}
else
{
+ // movement while onground -- CEV
PM_Friction (PM_GROUNDFRICTION, mt);
- if (vel != '0 0 0')
+ if (wishvel != '0 0 0')
{
- if (self.pmove_flags & PMF_CROUCHED)
+ if (self.pm_flags & PMF_CROUCHED)
wish = min (wish, PM_CROUCHSPEED);
- else if (self.doublejump_timer > 0)
+ else if (self.pm_timer > 0)
wish = PM_GroundBoostWishSpeed (wish);
else
wish = min (wish, PM_MAXSPEED);
@@ -1520,28 +1519,39 @@ void(float mt) PM_WalkAccelerate =
}
}
}
- else if (vel != '0 0 0')
+ else if (self.pm_flags & PMF_ONSLOPE)
+ {
+ // TODO CEV steep slope acceleration (surfing?)
+ // do Q3 air accel (strafejumping) for now -- CEV
+ if (wishvel != '0 0 0')
+ {
+ wish = min (wish, PM_MAXSPEED);
+ PM_Accelerate (dir, wish, PM_AIRACCELQ3, mt);
+ }
+ }
+ else if (wishvel != '0 0 0')
{
+ // movement in the air -- CEV
wish = min (wish, PM_MAXSPEED);
if (input_movevalues_x == 0)
{
- // sideways movement in the air, so Q1 air accel -- CEV
- PM_AirAccelerate (vel, dir, wish, mt);
+ // sideways the air, so Q1 air accel -- CEV
+ PM_AirAccelerate (dir, wish, mt);
}
else if (input_movevalues_y == 0)
{
- local float a3 = 0;
+ local float a2 = 0;
// CPM / Painkiller style air control -- CEV
- if (vel * self.velocity < 0)
+ if (wishvel * self.velocity < 0)
// against original velocity; we're slowing down
- a3 = PM_AIRACCELBACK;
+ a2 = PM_AIRACCELBACK;
else
// we're with original velocity - gaining speed
- a3 = PM_AIRACCELFWD;
+ a2 = PM_AIRACCELFWD;
- PM_Accelerate (dir, wish, a3, mt);
+ PM_Accelerate (dir, wish, a2, mt);
PM_AirControl (dir, wish, mt);
}
else
@@ -1555,81 +1565,75 @@ void(float mt) PM_WalkAccelerate =
dprint (sprintf("PM_WalkAccelerate: velocity %v, speed %g, "
"wvel %v, wspeed %g\n",
self.velocity, vlen ([self.velocity_x, self.velocity_y, 0]),
- vel, wish));
+ wishvel, wish));
#endif
-
- if (!(self.pmove_flags & PMF_PRE_MOVE))
- if (self.pmove_flags & PMF_STARTGROUND)
- self.pmove_flags &= ~PMF_STARTGROUND;
};
//----------------------------------------------------------------------
-// PM_SwimAccelerate
-// Largely copied from id Software's WaterMove. Works like NoClipAccelerate.
+// PM_SwimPreMove -- Check for water jump, water wading sounds -- CEV
//----------------------------------------------------------------------
-void(float move_time) PM_SwimAccelerate =
+void(vector wishvel, float move_time) PM_SwimPreMove =
{
- local float wishspeed;
- local vector wishvel;
+ // CheckWaterJump
+ if (self.conlevel == WATERLEVEL_WAIST)
+ {
+ local vector start, end;
- makevectors (input_angles);
- wishvel = v_forward * input_movevalues_x +
- v_right * input_movevalues_y + v_up * input_movevalues_z;
+ start = self.origin;
+ start_z = start_z + 8;
+ // use wishvel instead of v_forward -- CEV
+ end = [wishvel_x, wishvel_y, 0];
+ end = normalize (end);
+ traceline (start, (start + end * 24), TRUE, self);
- if (self.pmove_flags & PMF_PRE_MOVE)
- {
- // CheckWaterJump
- if (self.conlevel == WATERLEVEL_WAIST)
+ if (trace_fraction < 1)
{
- local vector start, end;
-
- start = self.origin;
- start_z = start_z + 8;
- // use wishvel instead of v_forward -- CEV
- end = [wishvel_x, wishvel_y, 0];
- end = normalize (end);
- traceline (start, (start + end * 24), TRUE, self);
+ // solid at the waist
+ start_z = start_z + self.maxs_z - 8;
+ self.movedir = trace_plane_normal * -50;
+ traceline (start, (start + end * 24),
+ TRUE, self);
- if (trace_fraction < 1)
+ if (trace_fraction == 1)
{
- // solid at the waist
- start_z = start_z + self.maxs_z - 8;
- self.movedir = trace_plane_normal * -50;
- traceline (start, (start + end * 24),
- TRUE, self);
-
- if (trace_fraction == 1)
- {
- // open at eye level
- self.flags |= FL_WATERJUMP;
- self.pmove_flags |= PMF_WATERJUMPED;
- self.flags &= ~FL_JUMPRELEASED;
- self.pmove_flags &= ~PMF_JUMP_HELD;
- // Z velocity was 225
- self.velocity_z = PM_JUMPSPEED;
- }
+ // open at eye level
+ self.flags |= FL_WATERJUMP;
+ self.pm_flags |= PMF_WATERJUMPED;
+ self.flags &= ~FL_JUMPRELEASED;
+ self.pm_flags &= ~PMF_JUMP_HELD;
+ // Z velocity was 225
+ self.velocity_z = PM_JUMPSPEED;
}
}
-
- #ifdef SSQC
- // functionality copied into pmove from client.qc -- CEV
- if (self.conlevel >= WATERLEVEL_WAIST) {
- if (self.conlevel >= WATERLEVEL_EYES) {
- if (self.swim_time < time)
- {
- // play swimming sound
- self.swim_time = time + 1;
- if (random() < 0.5)
- sound (self, CHAN_BODY, "misc/water1.wav",
- 0.6, ATTN_NORM);
- else
- sound (self, CHAN_BODY, "misc/water2.wav",
- 0.6, ATTN_NORM);
- } } }
- #endif
}
- if (!(self.pmove_flags & PMF_WATERJUMPED))
+ #ifdef SSQC
+ // functionality copied into pmove from client.qc -- CEV
+ if (self.conlevel >= WATERLEVEL_WAIST) {
+ if (self.conlevel >= WATERLEVEL_EYES) {
+ if (self.swim_time < time)
+ {
+ // play swimming sound
+ self.swim_time = time + 1;
+ if (random() < 0.5)
+ sound (self, CHAN_BODY, "misc/water1.wav",
+ 0.6, ATTN_NORM);
+ else
+ sound (self, CHAN_BODY, "misc/water2.wav",
+ 0.6, ATTN_NORM);
+ } } }
+ #endif
+};
+
+//----------------------------------------------------------------------
+// PM_SwimAccelerate -- Largely copied from id Software's WaterMove -- CEV
+//----------------------------------------------------------------------
+void(vector wishvel, float move_time) PM_SwimAccelerate =
+{
+ local vector wishdir;
+ local float wishspeed;
+
+ if (!(self.pm_flags & PMF_WATERJUMPED))
{
if (input_buttons & INPUT_BUTTON2)
{
@@ -1639,7 +1643,7 @@ void(float move_time) PM_SwimAccelerate =
else if (input_buttons & INPUT_BUTTON8)
{
// smartcrouch
- // self.pmove_flags |= PMF_CROUCH_HELD;
+ // self.pm_flags |= PMF_CROUCH_HELD;
wishvel_z = min (-PM_MAXSPEED, wishvel_z);
}
else if (input_movevalues == '0 0 0')
@@ -1652,28 +1656,22 @@ void(float move_time) PM_SwimAccelerate =
wishspeed = vlen (wishvel);
if (wishspeed > PM_WATERMAXSPEED)
wishspeed = PM_WATERMAXSPEED;
- wishvel = normalize (wishvel);
+ wishdir = normalize (wishvel);
// water friction; reuse PM_Friction with a special constant -- CEV
- if (!(self.pmove_flags & PMF_WATERJUMPED))
+ if (!(self.pm_flags & PMF_WATERJUMPED))
PM_Friction (PM_WATERFRICTION, move_time);
// accelerate; reuse PM_Accelerate with a special constant -- CEV
- PM_Accelerate (wishvel, wishspeed, PM_WATERACCEL, move_time);
+ PM_Accelerate (wishdir, wishspeed, PM_WATERACCEL, move_time);
};
//----------------------------------------------------------------------
// PM_NoClipAccelerate -- for flying / noclip; not for swimming -- CEV
//----------------------------------------------------------------------
-void(float scale, float move_time) PM_NoClipAccelerate =
+void(vector wishvel, float scale, float move_time) PM_NoClipAccelerate =
{
local float wishspeed;
- local vector wishvel;
-
- makevectors (input_angles);
- wishvel = v_forward * input_movevalues_x;
- wishvel += v_right * input_movevalues_y;
- wishvel += v_up * input_movevalues_z;
if (input_buttons & INPUT_BUTTON2)
// smartjump
@@ -1690,32 +1688,53 @@ void(float scale, float move_time) PM_NoClipAccelerate =
};
//----------------------------------------------------------------------
-void(float move_time) PM_ManageTimers =
+// PM_ManageTimer -- pos when jumping, neg when crouchsliding -- CEV
+//----------------------------------------------------------------------
+void(float move_time) PM_ManageTimer =
{
- if (self.doublejump_timer > 0 && move_time > 0)
- self.doublejump_timer -= move_time;
- else if (self.doublejump_timer < 0)
- self.doublejump_timer = 0;
+ if (self.pm_timer)
+ {
+ if (self.pm_flags & PMF_CROUCHSLIDE)
+ {
+ self.pm_timer += move_time;
- if (self.doublejump_timer <= 0)
+ if (self.pm_timer >= 0)
+ self.pm_timer = 0;
+ }
+ else
+ {
+ self.pm_timer -= move_time;
+
+ if (self.pm_timer <= 0)
+ self.pm_timer = 0;
+ }
+ }
+
+ if (self.pm_flags & PMF_CROUCHSLIDE)
{
- if (self.pmove_flags & PMF_DOUBLEJUMPED)
- self.pmove_flags &= ~PMF_DOUBLEJUMPED;
- // TODO CEV find a better place to clear STEPPED and AIRSTEPPED
- if (self.pmove_flags & PMF_STEPPED)
- self.pmove_flags &= ~PMF_STEPPED;
- if (self.pmove_flags & PMF_AIRSTEPPED)
- self.pmove_flags &= ~PMF_AIRSTEPPED;
+ if (self.pm_timer >= 0)
+ PM_CrouchSlideStop ();
}
- if (self.crouchslide_timer > 0 && move_time > 0)
- self.crouchslide_timer -= move_time;
- else if (self.crouchslide_timer < 0)
- self.crouchslide_timer = 0;
+ if (self.pm_flags & PMF_DOUBLEJUMPED)
+ {
+ if (self.pm_timer <= 0)
+ self.pm_flags &= ~PMF_DOUBLEJUMPED;
+ }
- if (self.crouchslide_timer == 0)
- if (self.pmove_flags & PMF_CROUCHSLIDE)
- PM_CrouchSlideStop ();
+ if (self.pm_flags & PMF_AIRSTEPPED)
+ {
+ if (self.pm_timer <= 0)
+ self.pm_flags &= ~PMF_AIRSTEPPED;
+ }
+
+ /*
+ if (self.pm_flags & PMF_STEPPED)
+ {
+ if (self.pm_timer <= 0)
+ self.pm_flags &= ~PMF_STEPPED;
+ }
+ */
};
//----------------------------------------------------------------------
@@ -1744,144 +1763,180 @@ void(entity e) PM_Move =
// clear JUMP_HELD if it's set and the user isn't pressing BUTTON2
if (!(input_buttons & INPUT_BUTTON2))
- self.pmove_flags &= ~PMF_JUMP_HELD;
+ self.pm_flags &= ~PMF_JUMP_HELD;
// crouch key, crouchsliding -- CEV
if (input_buttons & INPUT_BUTTON8)
{
- self.pmove_flags |= PMF_CROUCH_HELD;
+ self.pm_flags |= PMF_CROUCH_HELD;
}
else
{
- self.pmove_flags &= ~PMF_CROUCH_HELD;
- if (self.pmove_flags & PMF_CROUCHSLIDE)
+ self.pm_flags &= ~PMF_CROUCH_HELD;
+ if (self.pm_flags & PMF_CROUCHSLIDE)
PM_CrouchSlideStop ();
}
- // figure out the properties of the player's position then clear timers
+ // figure out the properties of the player's position -- CEV
PM_CategorizePosition ();
- // PM_ManageTimers (0);
+ local vector wishvel;
local float half_time = input_timelength * 0.5;
self.speed = vlen ([self.velocity_x, self.velocity_y, 0]);
if (self.movetype == MOVETYPE_WALK)
{
- // signal acceleration functions that we're pre-move
- self.pmove_flags |= PMF_PRE_MOVE;
-
// split acceleration in two to improve responsiveness -- CEV
if (self.conlevel >= WATERLEVEL_WAIST)
{
+ makevectors (input_angles);
+ wishvel = v_forward * input_movevalues_x +
+ v_right * input_movevalues_y +
+ v_up * input_movevalues_z;
+
// swim acceleration
- PM_SwimAccelerate (half_time);
+ PM_SwimPreMove (wishvel, half_time);
+ PM_SwimAccelerate (wishvel, half_time);
}
else
{
- PM_WalkAccelerate (half_time);
-
- // WalkAccelerate calls Jump which might alter pmove
+ // only yaw matters here -- CEV
+ makevectors (input_angles_y * '0 1 0');
+ wishvel = v_forward * input_movevalues_x +
+ v_right * input_movevalues_y;
+ wishvel_z = 0;
+ PM_WalkPreMove (wishvel, half_time);
+ PM_WalkAccelerate (wishvel, half_time);
+
+ // WalkPreMove calls Jump which might change pmove
// flags so do our feature checks afterwards -- CEV
// stick to the ground if we've jumped and haven't
// yet doublejumped
- if (self.doublejump_timer > 0) {
- if (!(self.pmove_flags & PMF_CLIMB)) {
- if (!(self.pmove_flags & PMF_CROUCHSLIDE)) {
- if (!(self.pmove_flags & PMF_PUSHED)) {
- if (!(self.pmove_flags & PMF_WALLJUMPED)) {
- if (!(self.pmove_flags & PMF_DOUBLEJUMPED)) {
- self.pmove_flags |= PMF_SLIDE_STICKY;
- } } } } } }
-
- // apply gravity only when in the air, on a ramp,
- // or in the 'sticky' state -- CEV
- if (!(self.pmove_flags & PMF_ONGROUND))
- self.pmove_flags |= PMF_SLIDE_GRAVITY;
- else if (self.pmove_flags & PMF_SLIDE_STICKY)
- self.pmove_flags |= PMF_SLIDE_GRAVITY;
- else if (self.groundnormal_z < PM_PLANE_FLAT)
- self.pmove_flags |= PMF_SLIDE_GRAVITY;
+ if (!(self.pm_flags & PMF_DOUBLEJUMPED)) {
+ if (!(self.pm_flags & PMF_WALLJUMPED)) {
+ if (!(self.pm_flags & PMF_CROUCHSLIDE)) {
+ if (!(self.pm_flags & PMF_CLIMB)) {
+ if (!(self.pm_flags & PMF_PUSHED))
+ {
+ if (self.pm_flags & PMF_STEPPED)
+ {
+ // consume the step event -- CEV
+ self.pm_flags &= ~PMF_STEPPED;
+ self.pm_flags |= PMF_SLIDE_STICKY;
+ }
+ else if (self.pm_timer > 0)
+ {
+ self.pm_flags |= PMF_SLIDE_STICKY;
+ }
+ else if (input_buttons & INPUT_BUTTON2)
+ {
+ self.pm_flags |= PMF_SLIDE_STICKY;
+ }
+ } } } } }
+
+ // apply gravity when in the air or on a ramp -- CEV
+ if (!(self.pm_flags & PMF_ONGROUND))
+ self.pm_flags |= PMF_SLIDE_GRAVITY;
+ else if (self.pm_flags & PMF_ONRAMP)
+ self.pm_flags |= PMF_SLIDE_GRAVITY;
// skim / wallclipping checks -- CEV
- if (self.doublejump_timer > PM_WALLCLIP_WINDOW) {
- if (!(self.pmove_flags & PMF_STARTGROUND)) {
- if (!(self.pmove_flags & PMF_ONGROUND)) {
- if (!(self.pmove_flags & PMF_CLIMB))
+ if (!(self.pm_flags & PMF_ONGROUND)) {
+ if (!(self.pm_flags & PMF_CLIMB)) {
+ if (self.pm_timer > PM_WALLCLIP_WINDOW)
{
- self.pmove_flags |= PMF_SLIDE_SKIM;
- } } } }
+ self.pm_flags |= PMF_SLIDE_SKIM;
+ } } }
- if (self.pmove_flags & PMF_ONLADDER)
+ if (self.pm_flags & PMF_ONLADDER)
{
// feature set for ladders -- CEV
- self.pmove_flags &= ~PMF_SLIDE_GRAVITY;
- self.pmove_flags &= ~PMF_SLIDE_SKIM;
- self.pmove_flags &= ~PMF_SLIDE_STICKY;
+ self.pm_flags &= ~PMF_SLIDE_GRAVITY;
+ self.pm_flags &= ~PMF_SLIDE_SKIM;
+ self.pm_flags &= ~PMF_SLIDE_STICKY;
}
}
// timers (part 1) -- CEV
- PM_ManageTimers (half_time);
+ PM_ManageTimer (half_time);
// step if nostep is false...
if (world_nostep == FALSE)
{
// ... and either airstep is true or we're onground
if (world_airstep == TRUE)
- self.pmove_flags |= PMF_SLIDE_STEP;
- else if (self.pmove_flags & PMF_ONGROUND)
- self.pmove_flags |= PMF_SLIDE_STEP;
+ self.pm_flags |= PMF_SLIDE_STEP;
+ else if (self.pm_flags & PMF_ONGROUND)
+ self.pm_flags |= PMF_SLIDE_STEP;
}
// Do the move. Bounce, Rock, Skate, Roll -- CEV
- PM_CheckVelocity ();
- PM_DanceMove ();
+ if (self.velocity != '0 0 0')
+ PM_CheckVelocity ();
- // signal accel functions we're post-move -- CEV
- self.pmove_flags &= ~PMF_PRE_MOVE;
+ PM_DanceMove ();
- // second pass at acceleration -- CEV
+ // second pass at acceleration; note that a touch function
+ // might have changed the v_ vectors during the move -- CEV
if (self.conlevel >= WATERLEVEL_WAIST)
- PM_SwimAccelerate (half_time);
+ PM_SwimAccelerate (wishvel, half_time);
else
- PM_WalkAccelerate (half_time);
+ PM_WalkAccelerate (wishvel, half_time);
// timers (part 2) -- CEV
- PM_ManageTimers (half_time);
+ PM_ManageTimer (half_time);
// clear ladder flag -- CEV
- if (self.pmove_flags & PMF_ONLADDER)
- self.pmove_flags &= ~PMF_ONLADDER;
+ if (self.pm_flags & PMF_ONLADDER)
+ self.pm_flags &= ~PMF_ONLADDER;
}
else if (self.movetype == MOVETYPE_FLY)
{
// split acceleration in two to improve responsiveness -- CEV
- PM_NoClipAccelerate (1.0f, half_time);
+ makevectors (input_angles);
+ wishvel = v_forward * input_movevalues_x;
+ wishvel += v_right * input_movevalues_y;
+ wishvel += v_up * input_movevalues_z;
+ PM_NoClipAccelerate (wishvel, 1.0f, half_time);
// step if nostep is false...
if (world_nostep == FALSE)
{
// ... and either airstep is true or we're onground
if (world_airstep == TRUE)
- self.pmove_flags |= PMF_SLIDE_STEP;
- else if (self.pmove_flags & PMF_ONGROUND)
- self.pmove_flags |= PMF_SLIDE_STEP;
+ self.pm_flags |= PMF_SLIDE_STEP;
+ else if (self.pm_flags & PMF_ONGROUND)
+ self.pm_flags |= PMF_SLIDE_STEP;
}
+ // clear stepped flag after doing slide feature checks -- CEV
+ if (self.pm_flags & PMF_STEPPED)
+ self.pm_flags &= ~PMF_STEPPED;
+
+ if (self.velocity != '0 0 0')
+ PM_CheckVelocity ();
+
PM_DanceMove ();
- PM_NoClipAccelerate (1.0f, half_time);
+
+ // note that the v_ vectors may have changed in the move -- CEV
+ PM_NoClipAccelerate (wishvel, 1.0f, half_time);
}
else if (self.movetype == MOVETYPE_NOCLIP)
{
// noclip is a debugging feature, no need to
- // worry about acceleration consistency. -- CEV
- PM_NoClipAccelerate (1.0f, input_timelength);
+ // worry about acceleration consistency -- CEV
+ makevectors (input_angles);
+ wishvel = v_forward * input_movevalues_x;
+ wishvel += v_right * input_movevalues_y;
+ wishvel += v_up * input_movevalues_z;
+ PM_NoClipAccelerate (wishvel, 1.0f, input_timelength);
// we're noclipping so update origin directly -- CEV
self.origin += self.velocity * input_timelength;
}
- touchtriggers ();
+ if (self.movetype != MOVETYPE_NOCLIP)
+ touchtriggers ();
PM_CategorizePosition ();
@@ -1891,6 +1946,7 @@ void(entity e) PM_Move =
self.velocity = PM_TruncateVector (self.velocity);
}
+ setorigin (self, self.origin);
self.oldorigin = self.origin;
// restore self just in case -- CEV
Return to the top of this page or return to the overview of this repo.
Diff qc/sv_entry.qc
diff --git a/qc/sv_entry.qc b/qc/sv_entry.qc
index 43cf643..182f46e 100644
--- a/qc/sv_entry.qc
+++ b/qc/sv_entry.qc
@@ -56,7 +56,7 @@ void() PlayerPreThink;
void() SV_RunClientCommand;
void() PlayerPostThink;
void() StartFrame;
-void() EndFrame;
+// void() EndFrame;
// void(void() spawnfunc) CheckSpawn;
#endif
@@ -900,9 +900,11 @@ void() StartFrame =
// "Called after non-player entities have run at the end of the physics frame"
// according to fteextensions.qc
//----------------------------------------------------------------------
+/*
void() EndFrame =
{
};
+*/
/*
// placeholder in case it's necessary; based on code from Nuclide SDK -- CEV
Return to the top of this page or return to the overview of this repo.
Diff qc/sv_progs.src
diff --git a/qc/sv_progs.src b/qc/sv_progs.src
index 84917e1..a662686 100644
--- a/qc/sv_progs.src
+++ b/qc/sv_progs.src
@@ -8,7 +8,7 @@
#includelist
//----------------------------------------------------------------------
-// defs
+// server QC defs
//----------------------------------------------------------------------
defs_globals.qc // id1 globalvars_t
defs_fields.qc // id1 entvars_t
Return to the top of this page or return to the overview of this repo.
Diff qc/triggers/ladder.qc
diff --git a/qc/triggers/ladder.qc b/qc/triggers/ladder.qc
index 71b3941..5391bb6 100644
--- a/qc/triggers/ladder.qc
+++ b/qc/triggers/ladder.qc
@@ -143,7 +143,7 @@ Keys:
}
// changed to PMFLAGS -- CEV
- other.pmove_flags |= PMF_ONLADDER;
+ other.pm_flags |= PMF_ONLADDER;
};
#endif
Return to the top of this page or return to the overview of this repo.
Diff qc/triggers/push.qc
diff --git a/qc/triggers/push.qc b/qc/triggers/push.qc
index d81e013..5e14848 100644
--- a/qc/triggers/push.qc
+++ b/qc/triggers/push.qc
@@ -400,7 +400,7 @@ vector(float a, float b, float c) solve_quadratic =
{
// signal pmove that player has touched a
// push brush -- CEV
- other.pmove_flags |= PMF_PUSHED;
+ other.pm_flags |= PMF_PUSHED;
#ifdef SSQC
// carry on with normal push sound behavior
Return to the top of this page or return to the overview of this repo.
Diff qc/world.qc
diff --git a/qc/world.qc b/qc/world.qc
index 208dddf..395f845 100644
--- a/qc/world.qc
+++ b/qc/world.qc
@@ -383,7 +383,7 @@ float(entity e, vector offset) world_surface_type =
if (known_release == KNOWN_RELEASE_NOT)
return SURFACE_UNKNOWN;
- if (e.pmove_flags & PMF_WALLJUMPED)
+ if (e.pm_flags & PMF_WALLJUMPED)
return SURFACE_UNKNOWN;
local string tex = "";
Return to the top of this page or return to the overview of this repo.