djcev.com

//

Git Repos / fte_dogmode / commit c91b0a0

Commit: c91b0a03e51febbe3ae9af98b63ad8c03f6fce02
Parent: fcbb9b7c8d5ad7002dcc085040bd1a21516d2a7a
Author: Cameron Vanderzanden, 2024-06-26 03:47
Committer: Cameron Vanderzanden, 2024-06-26 03:47

Commit Message

pmove fixes, GL now a faux tribolt, wall climbing

I can't think of a reason not to commit this right now so here it
is. There's a few things in-progress, some of it may be incomplete.

Several changes to the pmove code. I gave up on copy-and-pasting
ClipVelocity and broke that out into its own function. (Where it
should've been all along, I don't think I was saving many operations
by manually inlining it). I also reworked the stepping code in
PM_DanceMove (it's better now, but still not perfect).

Also in pmove, I've added mantling / wall climbing code inspired
by a recent playthrough of Deus Ex Invisible War. I already had a
blank spot in PM_WallJump where I knew the implementation would
go, and now it's there. From a player's perspective it works by
holding jump while off the ground and moving into a wall. You'll
climb (silently and without animation for now) until you can
step up and over the wall. You won't grab if you're rising or
falling too fast. From standing on flat ground the maximum height
of a ledge you can grab is somewhere between 100 and 128 units
high (I haven't figured out the exact value yet). None of this
is final of course and may change whenever.

Third change in pmove: I've removed PM_DanceMoveQ3. It's been
rotting away for a while and wasn't usable in its current state.
Given the choice between testing/updating it and removing it, I've
removed it. I'm optimistic I can get PM_DanceMove working well
enough without relying on an array of plane normals (which was
the reason I was testing Q3's slidemove, to play around with
such an array).

The step smoothing code has changed (again), more about this
later as I decide what to do with SOLID_BSP MOVETYPE_PUSH
entities & movement prediction etc. .

I've also implemented a faux tribolt, currently weapon 6,
replacing the grenade launcher. I have no assets for it so it's
currently using the standard GL model and mervup.mdl (from one
of the expansions) for its projectile. Works more or less like
the QC weapon, firing three MOVETYPE_BOUNCE bolts in quick
succession (0.125f apart) each with a lifetime of 0.8 (up from
QC's 0.6) and a speed of 1200ups (down from QC's 1600). Works a
treat. Ogres now fire this same weapon rather than grenades;
something to play with, see if it's any fun or not. (I was
getting tired of Ogres firing 100 damage grenades).

I've also made a first attempt at making Ogres choose different
weapons based on range. Obviously they'll melee if you're close
enough, but now at medium range they'll fire flak, and at long
range they'll fire tribolts. The current range function seems
unreliable for this; either that function needs improving or
it needs to be called more often.

There are other changes in progress which I'll detail when I
decide whether to keep them or not. For now I'm committing so
I don't lose any of these pmove changes.

Change List

Diff qc/Makefile

diff --git a/qc/Makefile b/qc/Makefile
index 1164a10..7bb90ba 100644
--- a/qc/Makefile
+++ b/qc/Makefile
@@ -1,5 +1,5 @@
CC=fteqcc64
-CCOPTS=-Wall -O2
+CCOPTS=-Wall -O2 -Ffastarrays

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 59502f5..af21e8e 100644
--- a/qc/base_entities.qc
+++ b/qc/base_entities.qc
@@ -45,6 +45,7 @@ entity damage_attacker; // set by T_Damage
.float is_waiting; // wait until activated before trigger?
.float lefty; // used by monsters and func_bob
.float light_lev; // not used ingame, parsed by light util
+.float scale; // resizes model. 1=normal, 2=double
.float speed;
.float speed2;
.float state; // plats / doors / buttons
@@ -131,6 +132,8 @@ float(entity src, entity dest) can_damage;
void(entity targ, entity inflictor, entity attacker, vector dir) killed;
void(entity inflictor, entity attacker, float damage, entity ignore)
t_radiusdamage2;
+void(entity inflictor, entity attacker, float damage, float radius,
+ float mindamage, entity ignore) t_radiusdamage3;
void(entity attacker, float damage) t_beamdamage2;
void(entity targ, entity inflictor, entity attacker, float damage) t_damage2;
#endif
@@ -597,6 +600,56 @@ void() noclass;
};

//--------------------------------------------------------------
+ void(entity inflictor, entity attacker, float damage, float radius,
+ float mindamage, entity ignore) t_radiusdamage3 =
+ {
+ local float points;
+ local entity head;
+ local vector org;
+
+ head = findradius (inflictor.origin, radius + 40);
+
+ while (head)
+ {
+ if (head == ignore || !head.takedamage)
+ {
+ head = head.chain;
+ continue;
+ }
+
+ org = head.origin + (head.mins + head.maxs) * 0.5;
+ points = max (0, 0.5 * vlen (inflictor.origin - org));
+ points = damage - points;
+ if (head == attacker)
+ points = points * 0.5;
+
+ if (mindamage > 0)
+ points = max (points, mindamage);
+
+ if (points > 0)
+ {
+ if (can_damage(inflictor, head))
+ {
+ // shambler takes half damage from
+ // all explosions
+ if (head.classtype ==
+ CT_MONSTER_SHAMBLER)
+ {
+ t_damage2 (head, inflictor,
+ attacker, points * 0.5);
+ }
+ else
+ {
+ t_damage2 (head, inflictor,
+ attacker, points);
+ }
+ }
+ }
+ head = head.chain;
+ }
+ };
+
+ //--------------------------------------------------------------
// T_BeamDamage
//--------------------------------------------------------------
void(entity attacker, float damage) t_beamdamage2 =
@@ -693,6 +746,16 @@ void() noclass;
if (attacker.damage_mod)
damage = damage * attacker.damage_mod;

+ // TODO CEV this is a quick hack
+ if ((inflictor.classgroup & CG_PROJECTILE &&
+ inflictor.aflag & PROJECTILE_EXPLOSIVE) &&
+ (targ.classtype == CT_MONSTER_ZOMBIE ||
+ targ.classgroup & CG_CORPSE))
+ {
+ // let even weak explosions gib zombies and corpses
+ damage = damage * 3;
+ }
+
// don't deplete armor if drowning/burning, or
// protected by biosuit/pentagram/godmode (note:
// in ID1 // pentagram/godmode doesn't actually
@@ -755,18 +818,27 @@ void() noclass;
// figure momentum direction
dir = targ.origin -
(inflictor.absmin + inflictor.absmax) * 0.5;
- dir_z = dir_z * 0.7;
+ // only a fraction of dir_z -- CEV
+ dir_z = dir_z * 0.5;
dir = normalize (dir);

- if (targ.flags & FL_MONSTER && targ.flags & FL_ONGROUND)
+ if (targ.flags & FL_MONSTER &&
+ targ.flags & FL_ONGROUND &&
+ targ.movetype == MOVETYPE_STEP)
+ {
targ.flags &= ~FL_ONGROUND;
+ }

if (attacker.classtype == CT_PLAYER && attacker == targ)
// standard knockback for self-damage -- CEV
targ.velocity += dir * damage * 8;
else
// decreased knockback otherwise -- CEV
- targ.velocity += dir * damage * 4;
+ if (attacker.super_damage_finished > time)
+ // negate Quad
+ targ.velocity += dir * damage;
+ else
+ targ.velocity += dir * damage * 4;

/*
dprint (sprintf("t_damage2: inflictor %s adds "

Return to the top of this page or return to the overview of this repo.

Diff qc/base_monster.qc

diff --git a/qc/base_monster.qc b/qc/base_monster.qc
index 46a7bd1..e673415 100644
--- a/qc/base_monster.qc
+++ b/qc/base_monster.qc
@@ -101,6 +101,7 @@ void(float n) monster_update_total;
void(vector org, float projspeed) base_monster_fire_flak;
void(vector org, float direct, float splash, float elevation)
base_monster_fire_grenade;
+void() base_monster_fire_tribolt;
void(vector org, vector dir, float off) base_monster_fire_hknightspell;
void(vector org, vector dir) base_monster_fire_laser;
void(vector org, vector dir, float projspeed) base_monster_fire_lavaball;
@@ -250,7 +251,7 @@ void(float n) monster_update_total =
crandom() * v_right +
crandom() * v_up;
dir = normalize (dir);
- // f*cking hack...is self a v_forward problem?
+ // f*cking hack...is this a v_forward problem?
dir_z *= -1;
// SetSpeed -- CEV
dir *= min (projspeed * (self.proj_speed_mod ?
@@ -294,6 +295,17 @@ void(float n) monster_update_total =
};

//--------------------------------------------------------------
+ void() base_monster_fire_tribolt =
+ {
+ sound (self, CHAN_WEAPON, "weapons/grenade.wav",
+ VOL_HIGH, ATTN_NORM);
+
+ spawn_projectile_bolt (self, 0);
+ spawn_projectile_bolt (self, BOLT_FIRING_DELAY);
+ spawn_projectile_bolt (self, BOLT_FIRING_DELAY * 2.0f);
+ };
+
+ //--------------------------------------------------------------
// hknight_shot
//--------------------------------------------------------------
void(vector org, vector dir, float off) base_monster_fire_hknightspell =

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 fd0e5a3..8019589 100644
--- a/qc/cl_entry.qc
+++ b/qc/cl_entry.qc
@@ -36,7 +36,7 @@ float servercommandframe;

// Reports which ssqc entnum was hit when a csqc traceline impacts an
// ssqc-based brush entity.
-// float trace_networkentity;
+float trace_networkentity;

entity view_pl; // handle to the local player entity
entity viewentity; // camera -- CEV
@@ -44,6 +44,7 @@ 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;

@@ -244,8 +245,6 @@ void(float vwidth, float vheight, float notmenu) CSQC_UpdateView =

if (view_pl)
{
- // call the preframe function for every entity with one.
- // used for movement prediction & smoothing -- CEV
player_prediction_preframe (view_pl);

// read our smoothed & predicted view origin
@@ -312,8 +311,6 @@ void(float vwidth, float vheight, float notmenu) CSQC_UpdateView =
addentities (DRAWMASK_ENGINE | DRAWMASK_NORMAL);
renderscene ();

- // call postframe for every entity with one; used for
- // prediction rollback -- CEV
player_prediction_postframe (view_pl);
}
else

Return to the top of this page or return to the overview of this repo.

Diff qc/cl_hud.qc

diff --git a/qc/cl_hud.qc b/qc/cl_hud.qc
index d3ef595..0b280d5 100644
--- a/qc/cl_hud.qc
+++ b/qc/cl_hud.qc
@@ -858,8 +858,7 @@ void(vector virtmin, vector virtsize) Hud_Intermission =
//----------------------------------------------------------------------
void(vector pos) Hud_InputMonitor =
{
- // TODO CEV
- // getinputstate (servercommandframe);
+ getinputstate (servercommandframe);

if (input_movevalues_x)
if (input_movevalues_x < 0)

Return to the top of this page or return to the overview of this repo.

Diff qc/defs_builtins.qc

diff --git a/qc/defs_builtins.qc b/qc/defs_builtins.qc
index 95ed7c5..b17448e 100644
--- a/qc/defs_builtins.qc
+++ b/qc/defs_builtins.qc
@@ -347,35 +347,11 @@ void(entity e) setspawnparms = #78;
#ifdef SSQC
//----------------------------------------------------------------------
// Centerprint
-//
-// The following function definitions allow the engine's builtin
-// centerprint function (builtin #73) to be called with different
-// numbers of string arguments. The string that will be printed is the
-// concatenation of the string arguments.
-//
-// These definitions work because builtin #73 is implemented in such a
-// way that it can accept multiple string arguments in this manner, even
-// though the original QuakeC code didn't take advantage of this fact.
-// A maximum of seven string arguments can be passed because a function
-// is limited to a total of eight arguments (and the first argument is
-// the client). Note that in the original engine, all of the strings
-// for a centerprint message are concatenated into a single 256-char
-// buffer, therefore excessively long messages should be avoided. -- iw
//----------------------------------------------------------------------

.float suppressCenterPrint;

void(entity client, string s1) centerprint_builtin = #73;
-void(entity client, string s1, string s2) centerprint_builtin2 = #73;
-void(entity client, string s1, string s2, string s3) centerprint_builtin3 = #73;
-void(entity client, string s1, string s2, string s3, string s4)
- centerprint_builtin4 = #73;
-void(entity client, string s1, string s2, string s3, string s4, string s5)
- centerprint_builtin5 = #73;
-void(entity client, string s1, string s2, string s3, string s4, string s5,
- string s6) centerprint_builtin6 = #73;
-void(entity client, string s1, string s2, string s3, string s4, string s5,
- string s6, string s7) centerprint_builtin7 = #73;

void(entity client, string s1) centerprint =
{
@@ -392,23 +368,6 @@ void(entity client, string s1) centerprint =
sprint(client, "\n");
}
};
-
-void(entity client, string s1, string s2) centerprint2 =
-{
- // Is the centerprint message being used by something else?
- if (!client.suppressCenterPrint)
- {
- centerprint_builtin2(client, s1, s2);
- }
- else
- {
- // Send message to client console instead
- sprint(client, "(centerprint) ");
- sprint(client, s1);
- sprint(client, s2);
- sprint(client, "\n");
- }
-};
#endif

//======================================================================

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 6c73c04..58d8b6c 100644
--- a/qc/defs_const.qc
+++ b/qc/defs_const.qc
@@ -222,6 +222,7 @@ const float MOVE_MISSILE = 2; // bbox of +/- 15 against FL_MONSTER
const float MOVE_HITMODEL = 4; // impact mesh instead of bbox
const float MOVE_TRIGGERS = 16; // impact only triggers
const float MOVE_EVERYTHING = 32; // solids & triggers & non-solid ents
+const float MOVE_LAGGED = 64; // antilag based on player's latency

const float DEAD_NO = 0; // .deadflag values
const float DEAD_DYING = 1;

Return to the top of this page or return to the overview of this repo.

Diff qc/defs_ctypes.qc

diff --git a/qc/defs_ctypes.qc b/qc/defs_ctypes.qc
index 7982cc5..6eb81a6 100644
--- a/qc/defs_ctypes.qc
+++ b/qc/defs_ctypes.qc
@@ -207,6 +207,7 @@ enum
CT_PATH_ROTATE, // Hipnotic rotation

// projectiles
+ CT_PROJECTILE_BOLT, // QC tribolt bolts
CT_PROJECTILE_BULLET, // id1 shotgun pellets
CT_PROJECTILE_FIREBALL, // created by misc_fireball
CT_PROJECTILE_FLAK, // pd3 flak projectile

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 7e8e385..5e59602 100644
--- a/qc/func/door.qc
+++ b/qc/func/door.qc
@@ -880,7 +880,7 @@ Key doors are always wait -1.
}

// network func_door to the CSQC client -- CEV
- 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;
#endif

Return to the top of this page or return to the overview of this repo.

Diff qc/func/new_plat.qc

diff --git a/qc/func/new_plat.qc b/qc/func/new_plat.qc
index ebf20af..6b971e8 100644
--- a/qc/func/new_plat.qc
+++ b/qc/func/new_plat.qc
@@ -881,7 +881,7 @@ Set "sounds" to one of the following:
e.trigger_field = spawn_temp_new_plat_trigger (e);
}

- 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;
#endif

Return to the top of this page or return to the overview of this repo.

Diff qc/func/plat.qc

diff --git a/qc/func/plat.qc b/qc/func/plat.qc
index 28cc1a1..c74f4dc 100644
--- a/qc/func/plat.qc
+++ b/qc/func/plat.qc
@@ -309,16 +309,18 @@ Set "sounds" to one of the following:
e.angles = '0 0 0';
#endif

- setorigin (e, e.origin);
// SOLID_BSP and MOVETYPE_PUSH on both client and server -- CEV
e.solid = SOLID_BSP;
e.movetype = MOVETYPE_PUSH;
+ setorigin (e, e.origin);
+
#if defined(SSQC)
setmodel (e, e.model);
#elif defined(CSQC)
self.oldorigin = self.origin;
setmodelindex (e, e.modelindex);
#endif
+
setsize (e, e.mins, e.maxs);

#ifdef SSQC
@@ -353,7 +355,7 @@ Set "sounds" to one of the following:
}

// network func_plat to the CSQC client -- CEV
- 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;
#endif

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 0f96eee..5c0e45c 100644
--- a/qc/func/rotate.qc
+++ b/qc/func/rotate.qc
@@ -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/func/train.qc

diff --git a/qc/func/train.qc b/qc/func/train.qc
index 085f156..222a8d9 100644
--- a/qc/func/train.qc
+++ b/qc/func/train.qc
@@ -184,9 +184,8 @@ void() func_train;
// state: stopped
self.state = 0;

- self.SendFlags |= BASE_FUNC_NET_SPEED |
- BASE_FUNC_NET_ORIGIN |
- BASE_FUNC_NET_VELOCITY;
+ self.SendFlags |= BASE_FUNC_NET_ORIGIN |
+ BASE_FUNC_NET_VELOCITY | BASE_FUNC_NET_SPEED;

// oof -- CEV
if (self.classtype == CT_MISC_MODELTRAIN)
@@ -241,9 +240,8 @@ void() func_train;
// state: stopped
self.state = 0;

- self.SendFlags |= BASE_FUNC_NET_SPEED |
- BASE_FUNC_NET_ORIGIN |
- BASE_FUNC_NET_VELOCITY;
+ self.SendFlags |= BASE_FUNC_NET_ORIGIN |
+ BASE_FUNC_NET_VELOCITY | BASE_FUNC_NET_SPEED;

// oof -- CEV
if (self.classtype == CT_MISC_MODELTRAIN)
@@ -359,8 +357,8 @@ void() func_train;
sub_calcmove (self, targ.origin - (displ * do_displace),
self.speed2, base_func_train_wait);

- self.SendFlags |= BASE_FUNC_NET_SPEED |
- BASE_FUNC_NET_ORIGIN | BASE_FUNC_NET_VELOCITY;
+ self.SendFlags |= BASE_FUNC_NET_ORIGIN |
+ BASE_FUNC_NET_VELOCITY | BASE_FUNC_NET_SPEED;
};

//--------------------------------------------------------------
@@ -395,7 +393,8 @@ void() func_train;

// If you set SendFlags here it will cause a movement error
// on the client; let the next think take care of it -- CEV
- self.SendFlags |= BASE_FUNC_NET_ORIGIN;
+ self.SendFlags |= BASE_FUNC_NET_ORIGIN |
+ BASE_FUNC_NET_VELOCITY | BASE_FUNC_NET_SPEED;

if (targ.speed)
// uses speed from the 1st path corner if set
@@ -497,9 +496,9 @@ void() func_train;
else
e.nextthink = time + 0.1;

- if (e.solid == SOLID_BSP)
+ if (e.solid == SOLID_BSP && e.classtype == CT_FUNC_TRAIN)
{
- 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/keylock.qc

diff --git a/qc/keylock.qc b/qc/keylock.qc
index 3fdd1f1..ea5bb57 100644
--- a/qc/keylock.qc
+++ b/qc/keylock.qc
@@ -197,7 +197,8 @@ void(entity client, string custom_message,
if (custom_message != "")
centerprint (client, custom_message);
else
- centerprint2 (client, "You need the ", self.netname);
+ centerprint (client,
+ sprintf("You need the %s", self.netname));
sound (self, CHAN_VOICE, self.noise3, VOL_HIGH, ATTN_NORM);
return;
}

Return to the top of this page or return to the overview of this repo.

Diff qc/math.qc

diff --git a/qc/math.qc b/qc/math.qc
index c2f5830..e902a12 100644
--- a/qc/math.qc
+++ b/qc/math.qc
@@ -34,7 +34,8 @@ float(float v) anglemod;
#ifdef SSQC
float(float theta) preach_tan;
float(float y, float x) preach_atan2;
-float(float theta, vector source, vector dest) preach_iterate_elevation;
+float(float theta, float spd, vector source, vector dest)
+ preach_iterate_elevation;
#endif

//------------------------------------------------------------------------------
@@ -278,7 +279,8 @@ float(float y, float x) preach_atan2 =
return vectoyaw (ang);
};

-float(float theta, vector source, vector dest) preach_iterate_elevation =
+float(float theta, float spd, vector source, vector dest)
+ preach_iterate_elevation =
{
// constants in the equation to be solved
local float a, b, c;
@@ -296,7 +298,7 @@ float(float theta, vector source, vector dest) preach_iterate_elevation =
y = vlen (ofs);

// find the coefficients of the quadratic in tan(theta)
- a = 0.5 * world_gravity * y * y / (GRENADE_SPEED * GRENADE_SPEED);
+ a = 0.5 * world_gravity * y * y / (spd * spd);
b = -y;
c = a + z;

Return to the top of this page or return to the overview of this repo.

Diff qc/monsters/enforcer.qc

diff --git a/qc/monsters/enforcer.qc b/qc/monsters/enforcer.qc
index 89755d9..8a49545 100644
--- a/qc/monsters/enforcer.qc
+++ b/qc/monsters/enforcer.qc
@@ -486,19 +486,22 @@ damage_mod(float) : "USE WITH CAUTION! Multiply all damage from this monster by
{
ai_face ();
self.attack_elevation = preach_iterate_elevation (
- OGRE_DEFAULT_ELEVATION, self.origin, self.enemy.origin);
+ OGRE_DEFAULT_ELEVATION, GRENADE_SPEED,
+ self.origin, self.enemy.origin);
};
void() enf_tur_atk4 = [$attack4, enf_tur_atk5]
{
ai_face ();
self.attack_elevation = preach_iterate_elevation (
- self.attack_elevation, self.origin, self.enemy.origin);
+ self.attack_elevation, GRENADE_SPEED,
+ self.origin, self.enemy.origin);
};
void() enf_tur_atk5 = [$attack5, enf_tur_atk6]
{
ai_face ();
self.attack_elevation = preach_iterate_elevation (
- self.attack_elevation, self.origin, self.enemy.origin);
+ self.attack_elevation, GRENADE_SPEED,
+ self.origin, self.enemy.origin);
};
void() enf_tur_atk6 = [$attack6, enf_tur_atk7]
{
@@ -508,19 +511,22 @@ damage_mod(float) : "USE WITH CAUTION! Multiply all damage from this monster by
{
ai_face ();
self.attack_elevation = preach_iterate_elevation (
- OGRE_DEFAULT_ELEVATION, self.origin, self.enemy.origin);
+ self.attack_elevation, GRENADE_SPEED,
+ self.origin, self.enemy.origin);
};
void() enf_tur_atk8 = [$attack8, enf_tur_atk9]
{
ai_face ();
self.attack_elevation = preach_iterate_elevation (
- self.attack_elevation, self.origin, self.enemy.origin);
+ self.attack_elevation, GRENADE_SPEED,
+ self.origin, self.enemy.origin);
};
void() enf_tur_atk9 = [$attack5, enf_tur_atk10]
{
ai_face ();
self.attack_elevation = preach_iterate_elevation (
- self.attack_elevation, self.origin, self.enemy.origin);
+ self.attack_elevation, GRENADE_SPEED,
+ self.origin, self.enemy.origin);
};
void() enf_tur_atk10 = [$attack6, enf_tur_atk11]
{

Return to the top of this page or return to the overview of this repo.

Diff qc/monsters/ogre.qc

diff --git a/qc/monsters/ogre.qc b/qc/monsters/ogre.qc
index 5a9d9db..2249e0a 100644
--- a/qc/monsters/ogre.qc
+++ b/qc/monsters/ogre.qc
@@ -357,8 +357,12 @@ damage_mod(float) : "USE WITH CAUTION! Multiply all damage from this monster by
switch (self.style)
{
case 0:
- base_monster_fire_grenade (
- self.origin, 40, 40, 0);
+ // default ogre firing behavior -- CEV
+ if (enemy_range < RANGE_MID)
+ base_monster_fire_flak (
+ self.origin + '0 0 16', 800);
+ else
+ base_monster_fire_tribolt ();
break;
case 1:
base_monster_fire_flak (
@@ -601,9 +605,27 @@ damage_mod(float) : "USE WITH CAUTION! Multiply all damage from this monster by
//--------------------------------------------------------------
// Ogre Projectile Attack
//--------------------------------------------------------------
- void() ogre_nail1 = [$shoot1, ogre_nail2] { ai_face (); };
- void() ogre_nail2 = [$shoot2, ogre_nail3] { ai_face (); };
- void() ogre_nail3 = [$shoot2, ogre_nail4] { ai_face (); };
+ void() ogre_nail1 = [$shoot1, ogre_nail2]
+ {
+ ai_face ();
+ self.attack_elevation = preach_iterate_elevation (
+ OGRE_DEFAULT_ELEVATION, BOLT_SPEED,
+ self.origin, self.enemy.origin);
+ };
+ void() ogre_nail2 = [$shoot2, ogre_nail3]
+ {
+ ai_face ();
+ self.attack_elevation = preach_iterate_elevation (
+ self.attack_elevation, BOLT_SPEED,
+ self.origin, self.enemy.origin);
+ };
+ void() ogre_nail3 = [$shoot2, ogre_nail4]
+ {
+ ai_face ();
+ self.attack_elevation = preach_iterate_elevation (
+ self.attack_elevation, BOLT_SPEED,
+ self.origin, self.enemy.origin);
+ };
void() ogre_nail4 = [$shoot3, ogre_nail5]
{
ai_face ();
@@ -620,9 +642,27 @@ damage_mod(float) : "USE WITH CAUTION! Multiply all damage from this monster by
//--------------------------------------------------------------
// Ogre Turret Attack
//--------------------------------------------------------------
- void() ogre_tur_atk1 = [$shoot1, ogre_tur_atk2] { ai_face (); };
- void() ogre_tur_atk2 = [$shoot2, ogre_tur_atk3] { ai_face (); };
- void() ogre_tur_atk3 = [$shoot2, ogre_tur_atk4] { ai_face (); };
+ void() ogre_tur_atk1 = [$shoot1, ogre_tur_atk2]
+ {
+ ai_face ();
+ self.attack_elevation = preach_iterate_elevation (
+ OGRE_DEFAULT_ELEVATION, BOLT_SPEED,
+ self.origin, self.enemy.origin);
+ };
+ void() ogre_tur_atk2 = [$shoot2, ogre_tur_atk3]
+ {
+ ai_face ();
+ self.attack_elevation = preach_iterate_elevation (
+ self.attack_elevation, BOLT_SPEED,
+ self.origin, self.enemy.origin);
+ };
+ void() ogre_tur_atk3 = [$shoot2, ogre_tur_atk4]
+ {
+ ai_face ();
+ self.attack_elevation = preach_iterate_elevation (
+ self.attack_elevation, BOLT_SPEED,
+ self.origin, self.enemy.origin);
+ };
void() ogre_tur_atk4 = [$shoot3, ogre_tur_atk5]
{
ai_face ();
@@ -1125,19 +1165,22 @@ damage_mod(float) : "USE WITH CAUTION! Multiply all damage from this monster by
{
ai_face ();
self.attack_elevation = preach_iterate_elevation (
- OGRE_DEFAULT_ELEVATION, self.origin, self.enemy.origin);
+ OGRE_DEFAULT_ELEVATION, GRENADE_SPEED,
+ self.origin, self.enemy.origin);
};
void() ogre_mm_nail2 = [$shoot2, ogre_mm_nail3]
{
ai_face ();
self.attack_elevation = preach_iterate_elevation (
- self.attack_elevation, self.origin, self.enemy.origin);
+ self.attack_elevation, GRENADE_SPEED,
+ self.origin, self.enemy.origin);
};
void() ogre_mm_nail3 = [$shoot2, ogre_mm_nail4]
{
ai_face ();
self.attack_elevation = preach_iterate_elevation (
- self.attack_elevation, self.origin, self.enemy.origin);
+ self.attack_elevation, GRENADE_SPEED,
+ self.origin, self.enemy.origin);
};
void() ogre_mm_nail4 = [$shoot3, ogre_nail5]
{
@@ -1155,19 +1198,22 @@ damage_mod(float) : "USE WITH CAUTION! Multiply all damage from this monster by
{
ai_face ();
self.attack_elevation = preach_iterate_elevation (
- OGRE_DEFAULT_ELEVATION, self.origin, self.enemy.origin);
+ OGRE_DEFAULT_ELEVATION, GRENADE_SPEED,
+ self.origin, self.enemy.origin);
};
void() ogre_mm_t_atk2 = [$shoot2, ogre_mm_t_atk3]
{
ai_face ();
self.attack_elevation = preach_iterate_elevation (
- self.attack_elevation, self.origin, self.enemy.origin);
+ self.attack_elevation, GRENADE_SPEED,
+ self.origin, self.enemy.origin);
};
void() ogre_mm_t_atk3 = [$shoot2, ogre_mm_t_atk4]
{
ai_face ();
self.attack_elevation = preach_iterate_elevation (
- self.attack_elevation, self.origin, self.enemy.origin);
+ self.attack_elevation, GRENADE_SPEED,
+ self.origin, self.enemy.origin);
};
void() ogre_mm_t_atk4 = [$shoot3, ogre_mm_t_atk5]
{

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 6e11a4e..fd23160 100644
--- a/qc/monsters/playerclient.qc
+++ b/qc/monsters/playerclient.qc
@@ -116,8 +116,8 @@ static void() player_remove;
void(entity e) player_prediction_save;
void(entity e) player_prediction_reset;
void(entity e) player_prediction_preframe;
-void(entity e) player_prediction_postframe;
void(entity e, float endframe) player_prediction;
+void(entity e) player_prediction_postframe;
#endif
#ifdef SSQC
float(entity to, float netflags) player_netsend;
@@ -138,6 +138,7 @@ void() player_fire_supershotgun;
void(float offset) player_fire_spikes;
void() player_fire_superspikes;
void() player_fire_grenade;
+void() player_fire_tribolt;
void() player_fire_rocket;
void() player_fire_lightning;
void() player_attack;
@@ -189,8 +190,6 @@ void() pl_diee5; void() pl_diee6; void() pl_diee7; void() pl_diee8;
void() pl_diee9;
void() player_death_think;
void() player_prethink_watermove;
-void() player_prethink_waterjump;
-void() player_prethink_jump;
void() player_prethink;
void() player_postthink_powerups;
void() player_postthink;
@@ -400,26 +399,8 @@ $frame axattd1 axattd2 axattd3 axattd4 axattd5 axattd6
if (self.entnum == player_localentnum)
{
view_pl = self;
-
- if (isnew)
- {
- // we've just spawned in
- self.commandframe = servercommandframe;
- player_prediction_save (self);
- }
- else
- {
- // reconcile any movement desynch by processing
- // movement from servercommandframe up to the
- // most recently completed client frame
- self.commandframe = servercommandframe;
- player_prediction (self, clientcommandframe-1);
-
- // now set our commandframe and save results
- // for later extrapolation/prediction -- CEV
- self.commandframe = clientcommandframe - 1;
- player_prediction_save (self);
- }
+ self.commandframe = servercommandframe;
+ player_prediction_save (self);
}

// TODO CEV movement interpolation for other players
@@ -543,37 +524,18 @@ $frame axattd1 axattd2 axattd3 axattd4 axattd5 axattd6
// player_prediction_save (e);
player_prediction (e, clientcommandframe);

- // step smoothing (and vertical motion on MOVETYPE_PUSH)
- local float zspeed = 0;
-
- if (e.groundentity.velocity_z > 0)
- {
- zspeed = e.groundentity.velocity_z;
- if (view_step_adjust < 16)
- view_step = 0;
- view_step_adjust = bound (8, zspeed * 0.11, 64);
- }
- /*
- else if (e.pmove_flags & PMF_CROUCHED &&
- e.origin_z - view_step_oldz < 0)
- {
- zspeed = 1;
- view_step_adjust = 6;
- }
- */
- else if (e.origin_z - view_step_oldz >= 4 &&
- e.origin_z - view_step_oldz <= PM_STEPHEIGHT &&
- e.pmove_flags & PMF_ONGROUND)
+ // step smoothing
+ local float view_diff = e.origin_z - view_step_oldz;
+ if (view_step_disable == FALSE && e.pmove_flags & PMF_ONGROUND
+ && view_diff >= 4 && view_diff <= PM_STEPHEIGHT)
{
if (e.speed)
- zspeed = e.speed;
+ view_step_adjust = e.speed * 0.018;
else
- zspeed = PM_MAXSPEED;
- view_step_adjust = bound (4, zspeed * 0.018, 16);
- }
+ view_step_adjust = PM_MAXSPEED * 0.018;
+
+ view_step_adjust = bound (4, view_step_adjust, 16);

- if (zspeed)
- {
// evaluate out the remaining old step
if (view_step_time - time > 0)
view_step = (view_step_time - time) *
@@ -581,15 +543,13 @@ $frame axattd1 axattd2 axattd3 axattd4 axattd5 axattd6
else
view_step = 0;

- view_step += (e.origin_z - view_step_oldz);
-
+ view_step += view_diff;
view_step_time = time + (1 / view_step_adjust);

/*
dprint (sprintf("player_prediction_preframe: "
- "groundent %s, zspeed %g, step_adjust %g\n",
- self.groundentity.classname, zspeed,
- view_step_adjust));
+ "pmove_step %g, step %g, step_adjust %g\n",
+ view_pmove_step, view_step, view_step_adjust));
*/
}

@@ -605,14 +565,6 @@ $frame axattd1 axattd2 axattd3 axattd4 axattd5 axattd6
};

//--------------------------------------------------------------
- void(entity e) player_prediction_postframe =
- {
- player_prediction_reset (e);
- setsize (e, e.mins, e.maxs);
- setorigin (e, e.origin);
- };
-
- //--------------------------------------------------------------
// was Pred_RunMovement in CSQCTest cs/prediction.qc
//--------------------------------------------------------------
void(entity e, float endframe) player_prediction =
@@ -650,21 +602,25 @@ $frame axattd1 axattd2 axattd3 axattd4 axattd5 axattd6
// no input from client
continue;

- if (input_timelength == 0)
- break;
+ if (input_timelength <= 0)
+ continue;

- if (world_standardphysics)
- // for testing
- runstandardplayerphysics (e);
- else
- // for real
- PM_Move (e);
+ // see pmove.qc -- CEV
+ PM_Move (e);
}

// add anything that was applied after (for low packet
// rate protocols)
input_angles = view_angles;
};
+
+ //--------------------------------------------------------------
+ void(entity e) player_prediction_postframe =
+ {
+ player_prediction_reset (e);
+ setsize (e, e.mins, e.maxs);
+ setorigin (e, e.origin);
+ };
#endif

#ifdef SSQC
@@ -1095,63 +1051,57 @@ $frame axattd1 axattd2 axattd3 axattd4 axattd5 axattd6
{
self.currentammo = 0;
self.weaponmodel = "progs/v_axe.mdl";
- self.weaponframe = 0;
}
else if (self.weapon == IT_SHOTGUN)
{
self.currentammo = self.ammo_shells;
self.weaponmodel = "progs/v_shot.mdl";
- self.weaponframe = 0;
self.items = self.items | IT_SHELLS;
}
else if (self.weapon == IT_SUPER_SHOTGUN)
{
self.currentammo = self.ammo_shells;
self.weaponmodel = "progs/v_shot2.mdl";
- self.weaponframe = 0;
self.items = self.items | IT_SHELLS;
}
else if (self.weapon == IT_NAILGUN)
{
self.currentammo = self.ammo_nails;
self.weaponmodel = "progs/v_nail.mdl";
- self.weaponframe = 0;
self.items = self.items | IT_NAILS;
}
else if (self.weapon == IT_SUPER_NAILGUN)
{
self.currentammo = self.ammo_nails;
self.weaponmodel = "progs/v_nail2.mdl";
- self.weaponframe = 0;
self.items = self.items | IT_NAILS;
}
else if (self.weapon == IT_GRENADE_LAUNCHER)
{
self.currentammo = self.ammo_rockets;
self.weaponmodel = "progs/v_rock.mdl";
- self.weaponframe = 0;
self.items = self.items | IT_ROCKETS;
}
else if (self.weapon == IT_ROCKET_LAUNCHER)
{
self.currentammo = self.ammo_rockets;
self.weaponmodel = "progs/v_rock2.mdl";
- self.weaponframe = 0;
self.items = self.items | IT_ROCKETS;
}
else if (self.weapon == IT_LIGHTNING)
{
self.currentammo = self.ammo_cells;
self.weaponmodel = "progs/v_light.mdl";
- self.weaponframe = 0;
self.items = self.items | IT_CELLS;
}
else
{
self.currentammo = 0;
self.weaponmodel = "";
- self.weaponframe = 0;
}
+
+ // TODO CEV
+ self.weaponframe = 0;
};

//--------------------------------------------------------------
@@ -1419,6 +1369,25 @@ $frame axattd1 axattd2 axattd3 axattd4 axattd5 axattd6
};

//--------------------------------------------------------------
+ void() player_fire_tribolt =
+ {
+ local vector missile_vel = '0 0 0';
+
+ self.currentammo = self.ammo_rockets = self.ammo_rockets - 1;
+
+ sound (self, CHAN_WEAPON, "weapons/grenade.wav",
+ VOL_HIGH, ATTN_NORM);
+
+ self.punchangle_x = -2;
+ // self.SendFlags |= PLAYER_NET_PUNCHANGLE;
+
+ // called a tribolt 'cause there's three of 'em -- CEV
+ spawn_projectile_bolt (self, 0);
+ spawn_projectile_bolt (self, BOLT_FIRING_DELAY);
+ spawn_projectile_bolt (self, BOLT_FIRING_DELAY * 2.0f);
+ };
+
+ //--------------------------------------------------------------
// Weapon 7: W_FireRocket
//--------------------------------------------------------------
void() player_fire_rocket =
@@ -1555,8 +1524,11 @@ $frame axattd1 axattd2 axattd3 axattd4 axattd5 axattd6
else if (self.weapon == IT_GRENADE_LAUNCHER)
{
pl_rocket1 ();
- player_fire_grenade ();
- self.attack_finished = time + 0.6;
+ // TODO CEV
+ // player_fire_grenade ();
+ player_fire_tribolt ();
+ // self.attack_finished = time + 0.6;
+ self.attack_finished = time + 1.3;
}
else if (self.weapon == IT_ROCKET_LAUNCHER)
{
@@ -2411,101 +2383,6 @@ $frame axattd1 axattd2 axattd3 axattd4 axattd5 axattd6
};

//--------------------------------------------------------------
- // CheckWaterJump -- the legacy standard id1 (?) waterjump
- //--------------------------------------------------------------
- void() player_prethink_waterjump =
- {
- // from Copper -- dumptruck_ds
- if (self.movetype == MOVETYPE_NOCLIP)
- return;
-
- local vector start, end;
-
- // check for a jump-out-of-water
- makevectors (self.angles);
- start = self.origin;
- start_z = start_z + 8;
- v_forward_z = 0;
- normalize (v_forward);
- end = start + v_forward * 24;
- traceline (start, end, TRUE, self);
- if (trace_fraction < 1)
- {
- // solid at waist
- start_z = start_z + self.maxs_z - 8;
- end = start + v_forward * 24;
- self.movedir = trace_plane_normal * -50;
- traceline (start, end, TRUE, self);
- if (trace_fraction == 1)
- {
- // open at eye level
- self.flags = self.flags | FL_WATERJUMP;
- self.velocity_z = 225;
- self.flags -= self.flags & FL_JUMPRELEASED;
- // safety net
- self.teleport_time = time + 2;
- return;
- }
- }
- };
-
- //--------------------------------------------------------------
- // PlayerJump -- standard legacy id1 jump logic
- //--------------------------------------------------------------
- void() player_prethink_jump =
- {
- if (self.flags & FL_WATERJUMP)
- return;
-
- if (self.conlevel >= WATERLEVEL_WAIST)
- {
- if (self.contype == CONTENT_WATER)
- self.velocity_z = 100;
- else if (self.contype == CONTENT_SLIME)
- self.velocity_z = 80;
- else
- self.velocity_z = 50;
-
- // play swiming sound
- if (self.conlevel >= WATERLEVEL_EYES &&
- self.swim_time < time)
- {
- self.swim_time = time + 1;
- if (random() < 0.5)
- sound (self, CHAN_BODY,
- "misc/water1.wav",
- VOL_HIGH, ATTN_NORM);
- else
- sound (self, CHAN_BODY,
- "misc/water2.wav",
- VOL_HIGH, ATTN_NORM);
- }
- return;
- }
-
- // refactoring from Copper -- dumptruck_ds
- if (self.movetype != MOVETYPE_NOCLIP)
- {
- if (!(self.flags & FL_ONGROUND))
- return;
- // don't pogo stick
- if ( !(self.flags & FL_JUMPRELEASED) )
- return;
- // player jumping sound (h00rt)
- sound (self, CHAN_BODY, "player/plyrjmp8.wav",
- VOL_HIGH, ATTN_NORM);
- }
-
- self.flags = self.flags - (self.flags & FL_JUMPRELEASED);
-
- // don't stairwalk
- self.flags = self.flags - FL_ONGROUND;
-
- self.button2 = 0;
- self.velocity_z = self.velocity_z + 270;
- };
-
- //--------------------------------------------------------------
// Called by PlayerPreThink in entrypoints.qc -- CEV
//--------------------------------------------------------------
void() player_prethink =
@@ -2517,87 +2394,9 @@ $frame axattd1 axattd2 axattd3 axattd4 axattd5 axattd6
if (clean_up_client_stuff)
fog_set_from_ent (self, self);

- // note that this code block is here, before the tests
- // which check whether the player is dead, so that the
- // player's gravity will be correctly updated even if
- // they e.g. fell off a ladder because they died -- iw
- if (world_standardphysics)
- {
- if (self.pmove_flags & PMF_ONLADDER)
- {
- do_ladder_physics = TRUE;
- // not zero, because zero means "default"
- self.gravity = 0.0000001;
- self.pmove_flags &= ~PMF_ONLADDER;
- }
- else
- {
- do_ladder_physics = FALSE;
- self.gravity = self.wantedgravity;
- }
-
- // from copper -- dumptruck_ds
- if (self.movetype == MOVETYPE_NOCLIP)
- self.flags |= FL_FLY;
-
- player_prethink_watermove ();
-
- if (self.conlevel == WATERLEVEL_WAIST)
- player_prethink_waterjump ();
-
- // johnfitz ladder conditions, added from
- // Rubicon2 -- dumptruck_ds
- if (do_ladder_physics)
- {
- if (self.button2)
- {
- // PlayerClimb -- johnfitz
- self.velocity = '0 0 160';
- /*
- // no ladder footsteps for now
- if (time > self.ladder_step_finished)
- {
- // TODO CEV oof
- r = random();
- if (r > 0.66)
- sound (self, CHAN_BODY,
- "ladder/metal1.wav",
- VOL_MID, ATTN_NORM);
- else if (r > 0.33)
- sound (self, CHAN_BODY,
- "ladder/metal2.wav",
- VOL_MID, ATTN_NORM);
- else
- sound (self, CHAN_BODY,
- "ladder/metal3.wav",
- VOL_MID, ATTN_NORM);
- self.ladder_step_finished =
- time + 0.3;
- }
- */
- }
- else
- {
- self.flags |= FL_JUMPRELEASED;
- self.velocity = 0.9 * self.velocity;
- self.velocity_z = 0;
- }
- }
- else
- {
- if (self.button2)
- player_prethink_jump ();
- else
- self.flags |= FL_JUMPRELEASED;
- }
- }
- else
- {
- self.gravity = self.wantedgravity;
+ self.gravity = self.wantedgravity;

- // WaterMove - needs to run even if doing mod physics
- player_prethink_watermove ();
- }
+ player_prethink_watermove ();

if (self.deadflag >= DEAD_DEAD)
{
@@ -2884,14 +2683,6 @@ $frame axattd1 axattd2 axattd3 axattd4 axattd5 axattd6
}

player_postthink_powerups ();
-
- // from Copper -- dumptruck_ds
- if (world_standardphysics && self.movetype != MOVETYPE_NOCLIP)
- self.flags &= ~FL_FLY;
-
- // set oldorigin here so we can detect if the engine modifies
- // player origin (useful for setting SendFlags above) -- CEV
- self.oldorigin = self.origin;
};

//==============================================================

Return to the top of this page or return to the overview of this repo.

Diff qc/monsters/soldier.qc

diff --git a/qc/monsters/soldier.qc b/qc/monsters/soldier.qc
index f9e96d1..85dd198 100644
--- a/qc/monsters/soldier.qc
+++ b/qc/monsters/soldier.qc
@@ -544,19 +544,22 @@ damage_mod(float) : "USE WITH CAUTION! Multiply all damage from this monster by
{
ai_face ();
self.attack_elevation = preach_iterate_elevation (
- OGRE_DEFAULT_ELEVATION, self.origin, self.enemy.origin);
+ OGRE_DEFAULT_ELEVATION, GRENADE_SPEED,
+ self.origin, self.enemy.origin);
};
void() army_tur_atk3 = [$shoot3, army_tur_atk4]
{
ai_face ();
self.attack_elevation = preach_iterate_elevation (
- self.attack_elevation, self.origin, self.enemy.origin);
+ self.attack_elevation, GRENADE_SPEED,
+ self.origin, self.enemy.origin);
};
void() army_tur_atk4 = [$shoot4, army_tur_atk5]
{
ai_face ();
self.attack_elevation = preach_iterate_elevation (
- self.attack_elevation, self.origin, self.enemy.origin);
+ self.attack_elevation, GRENADE_SPEED,
+ self.origin, self.enemy.origin);
};
void() army_tur_atk5 =
{

Return to the top of this page or return to the overview of this repo.

Diff qc/monsters/zombie.qc

diff --git a/qc/monsters/zombie.qc b/qc/monsters/zombie.qc
index e53e337..9c5dbbc 100644
--- a/qc/monsters/zombie.qc
+++ b/qc/monsters/zombie.qc
@@ -519,19 +519,22 @@ spawnflags(Flags) =
{
ai_face ();
self.attack_elevation = preach_iterate_elevation (
- OGRE_DEFAULT_ELEVATION, self.origin, self.enemy.origin);
+ OGRE_DEFAULT_ELEVATION, ZCHUNK_SPEED,
+ self.origin, self.enemy.origin);
};
void() zom_tur_atka11 = [$atta11, zom_tur_atka12]
{
ai_face ();
self.attack_elevation = preach_iterate_elevation (
- self.attack_elevation, self.origin, self.enemy.origin);
+ self.attack_elevation, ZCHUNK_SPEED,
+ self.origin, self.enemy.origin);
};
void() zom_tur_atka12 = [$atta12, zom_tur_atka13]
{
ai_face ();
self.attack_elevation = preach_iterate_elevation (
- self.attack_elevation, self.origin, self.enemy.origin);
+ self.attack_elevation, ZCHUNK_SPEED,
+ self.origin, self.enemy.origin);
};
void() zom_tur_atka13 = [$atta13, zom_alt_seek1]
{
@@ -560,19 +563,22 @@ spawnflags(Flags) =
{
ai_face ();
self.attack_elevation = preach_iterate_elevation (
- OGRE_DEFAULT_ELEVATION, self.origin, self.enemy.origin);
+ OGRE_DEFAULT_ELEVATION, ZCHUNK_SPEED,
+ self.origin, self.enemy.origin);
};
void() zom_tur_atkb12 = [$attb12, zom_tur_atkb13]
{
ai_face ();
self.attack_elevation = preach_iterate_elevation (
- self.attack_elevation, self.origin, self.enemy.origin);
+ self.attack_elevation, ZCHUNK_SPEED,
+ self.origin, self.enemy.origin);
};
void() zom_tur_atkb13 = [$attb13, zom_tur_atkb14]
{
ai_face ();
self.attack_elevation = preach_iterate_elevation (
- self.attack_elevation, self.origin, self.enemy.origin);
+ self.attack_elevation, ZCHUNK_SPEED,
+ self.origin, self.enemy.origin);
};
void() zom_tur_atkb14 = [$attb13, zom_alt_seek1]
{
@@ -599,19 +605,22 @@ spawnflags(Flags) =
{
ai_face ();
self.attack_elevation = preach_iterate_elevation (
- OGRE_DEFAULT_ELEVATION, self.origin, self.enemy.origin);
+ OGRE_DEFAULT_ELEVATION, ZCHUNK_SPEED,
+ self.origin, self.enemy.origin);
};
void() zom_tur_atkc10 = [$attc10, zom_tur_atkc11]
{
ai_face ();
self.attack_elevation = preach_iterate_elevation (
- self.attack_elevation, self.origin, self.enemy.origin);
+ self.attack_elevation, ZCHUNK_SPEED,
+ self.origin, self.enemy.origin);
};
void() zom_tur_atkc11 = [$attc11, zom_tur_atkc12]
{
ai_face ();
self.attack_elevation = preach_iterate_elevation (
- self.attack_elevation, self.origin, self.enemy.origin);
+ self.attack_elevation, ZCHUNK_SPEED,
+ self.origin, self.enemy.origin);
};
void() zom_tur_atkc12 = [$attc12, zom_alt_seek1]
{

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 960d13a..d5b93d6 100644
--- a/qc/pmove.qc
+++ b/qc/pmove.qc
@@ -26,6 +26,7 @@ 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 grounddistance; // distance from ground
.float pmove_flags; // custom movement flags -- CEV
.float crouchslide_timer; // crouchslide countdown timer
.float doublejump_timer; // time in which a player can doublejump
@@ -38,15 +39,15 @@ vector input_movevalues; // movement requested by client

#if defined(CSQC) || defined (SSQC)
// acceleration & friction
-const float PM_AIRACCEL = 8.0f; // 10 in Q1; halved on acceleration
-const float PM_AIRACCELQ3 = 0.9f; // 1.0 in Q3 ?; now 0.75 or 0.8
-const float PM_AIRACCELFWD = 0.8f; // 1 feels close to Q3 / CPM
+const float PM_AIRACCEL = 7.5f; // 10 in Q1; speed gain reduced by
+const float PM_AIRACCELSCALE = 0.3f; // multiplying by this const
+const float PM_AIRACCELQ3 = 1.0f; // 1.0 in Q3 ?; now 0.8
+const float PM_AIRACCELFWD = 1.0f; // 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 vector PM_GROUNDDIST_V = '0 0 1'; // distance for ground check
const float PM_SLIDEACCEL = 1.01f; // crouchslide accel; 10; 8? 4?
const float PM_SLIDEFRICTION = 0.01f; // crouchslide friction; 1.0?
const float PM_WATERACCEL = 10.0f; // water acceleration
@@ -66,6 +67,7 @@ const float PM_WATERSINKSPEED = 60.0f;

// vertical speeds (mostly)
const float PM_GRAVITY = 800.0f; // superseded by world_gravity global
+const float PM_CLIMBSPEED = 120.0f; // ladder & wall climbing
const float PM_JUMPSPEED = 270.0f; // standard jump Z velocity; 90 * 3
const float PM_DOUBLEJUMPSPEED = 270.0f;// 270 * 1.5 in CPM
const float PM_SHORTJUMPSPEED = 180.0f; // 180 = 90 * 2
@@ -86,12 +88,18 @@ const float PM_WALLJUMP_WINDOW = 0.3f; // dj timer < this to walljump
const float PM_WALLCLIP_WINDOW = 0.25f; //

// misc
+const float PM_CLIMBSCALE = 0.75; // scale XY vel by this while climbing
const float PM_MAX_CLIP_PLANES = 5;
const float PM_OVERCLIP = 1.0f; // Quake3's OVERCLIP is 1.001f
const float PM_ONESIDEDCLIP = -0.1f; // -0.001, -0.01, -0.1
const float PM_STEPHEIGHT = 18.0f; // 18 for Q1, 22 for later games?
const vector PM_TELEDROP = '0 0 -64'; // drop teleporter exit to floor if
- // floor is within this distance
+#if defined(SSQC) // floor is within this distance
+const float PM_MOVEFLAGS = MOVE_LAGGED;
+#elif defined(CSQC)
+const float PM_MOVEFLAGS = MOVE_LAGGED; // is MOVE_LAGGED supported in CSQC?
+#endif
+
// water level
const float WATERLEVEL_NONE = 0;
const float WATERLEVEL_FEET = 1;
@@ -112,6 +120,7 @@ const vector PM_CROUCH_VIEWOFS = '0 0 8'; // Q3 crouch 0 0 12 -- CEV
// pmove_flags is used by the engine; FTE defines two constants:
// PMF_JUMP_HELD = 1, PMF_LADDER = 2. So those two constants should
// be first (and in that order) in our enum below. -- CEV
+// this is currently 19 flags; max flags for a float is 23 -- CEV
enumflags
{
PMF_JUMP_HELD, // player is holding the jump key
@@ -123,6 +132,8 @@ enumflags
PMF_CROUCHSLIDE, // entity is crouch sliding
PMF_DOUBLEJUMPED, // entity has doublejumped
PMF_WALLJUMPED, // entity has walljumped
+ PMF_CLIMB1, // entity is climbing (state 1)
+ PMF_CLIMB2, // entity is climbing (state 2)
PMF_WATERJUMPED, // entity has waterjumped
PMF_PRE_MOVE, // hint that origin hasn't updated yet
PMF_SLIDE_GRAVITY, // slidemove hint to apply gravity
@@ -145,8 +156,8 @@ float(float maxspeed, float a, float c, float t) PM_MaxCircleGroundSpeed;
#if defined(CSQC) || defined (SSQC)
static void(entity ent) PM_DoTouch;
float() PM_Nudge;
+vector(vector vel, vector normal) PM_ClipVelocity;
void() PM_DanceMove;
-void(float dogravity, float sticky, float dostep, float doskim) PM_DanceMoveQ3;
void() PM_CategorizePosition;
void(float friction, float move_time) PM_Friction;
void(vector wishdir, float wishspeed, float accel, float move_time)
@@ -227,7 +238,7 @@ float() PM_Nudge =
vector test, org = self.origin;

// check current position.
- tracebox (org, self.mins, self.maxs, org, FALSE, self);
+ tracebox (org, self.mins, self.maxs, org, PM_MOVEFLAGS, self);
if (!trace_startsolid)
return TRUE;

@@ -249,7 +260,7 @@ float() PM_Nudge =
{
test.x = org.x + offsets[x];
tracebox (test, self.mins, self.maxs, test,
- FALSE, self);
+ PM_MOVEFLAGS, self);
if (!trace_startsolid)
{
// okay, that'll do
@@ -264,13 +275,37 @@ float() PM_Nudge =
};

//----------------------------------------------------------------------
+// PM_ClipVelocity -- slide off the impacting surface
+//----------------------------------------------------------------------
+vector(vector vel, vector normal) PM_ClipVelocity =
+{
+ // I got tired of copy-and-pasting this. Here's hoping making
+ // it a separate function won't slow things down -- CEV
+ local float backoff = vel * normal;
+
+ if (backoff < 0)
+ backoff *= PM_OVERCLIP;
+ else
+ if (normal_z > 0.7)
+ // 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;
+
+ vel -= normal * backoff;
+ return vel;
+};
+
+//----------------------------------------------------------------------
// PM_DanceMove
//
// Updates origin according to velocity, moves the player through the world.
// Same as Q3 SlideMove and Q1 FlyMove. This version handles steps, applies
// gravity, and restores velocity based on a timer check (those latter two
-// are features of Q3's SlideMove). I've inlined ClipVelocity to hopefully
-// improve performance.
+// are features of Q3's SlideMove).
//
// Based on code from the Nuclide SDK (presumably by Eukara), specifically
// the function PMoveCustom_Move found in the file pmove_custom.qc. That
@@ -279,12 +314,12 @@ float() PM_Nudge =
//----------------------------------------------------------------------
void() PM_DanceMove =
{
- vector end, prev_plane, prev_plane2, start_vel;
- float f, grav, i, stepsize, time_left;
- entity touched_ent;
+ local vector end, plane1, plane2, start_vel;
+ local float f, grav, i, stepsize, time_left;
+ local entity touched_ent;

// silence some FTEQCC warnings -- CEV
- end = prev_plane = prev_plane2 = '0 0 0';
+ end = plane1 = plane2 = '0 0 0';
f = grav = i = stepsize = 0;
time_left = input_timelength;

@@ -294,8 +329,7 @@ void() PM_DanceMove =
grav = self.gravity;
else
grav = 1.0;
- // world_gravity is set in world () (on the server)
- // or PlayerUpdate (client) -- CEV
+ // world_gravity is set in worldspawn() -- CEV
grav *= world_gravity * time_left;
// Half now, half later. Apparently affects framerate
// dependence. -- CEV
@@ -321,26 +355,18 @@ void() PM_DanceMove =
{
// set our destination & test the move -- CEV
end = self.origin + (self.velocity * time_left);
- tracebox (self.origin, self.mins, self.maxs, end, FALSE, self);
+ tracebox (self.origin, self.mins, self.maxs, end,
+ PM_MOVEFLAGS, self);

if (trace_allsolid || trace_startsolid)
{
- #ifdef CSQC
- if (trace_ent.velocity)
- {
- self.velocity += trace_ent.velocity;
- }
- else
- {
- if (PM_Nudge())
- continue;
- }
- #endif
-
- #ifdef SSQC
// self is in something else; attempt to nudge out
if (PM_Nudge())
continue;
+ #if defined(CSQC)
+ else
+ break;
+ #elif defined(SSQC)
else
setorigin (self, self.oldorigin);

@@ -359,9 +385,7 @@ void() PM_DanceMove =
// no obstructions, made the whole move -- CEV
break;

- // zero out stepsize, then save the touched ent for later,
- // then reduce time_left -- CEV
- stepsize = 0;
+ // save the trace ent for later then reduce time_left -- CEV
touched_ent = trace_ent;
time_left -= time_left * trace_fraction;

@@ -371,9 +395,9 @@ void() PM_DanceMove =
if (self.pmove_flags & PMF_SLIDE_STEP && time_left > 0 &&
trace_plane_normal_z == 0)
{
- // store the entity and plane normal from our
- // first move attempt, setup a vec to track
- // velocity changes -- CEV
+ // store the entity and plane normal from above
+ // and set up a vec to track velocity changes in
+ // case we need to reject the step attempt -- CEV
local entity first_ent = trace_ent;
local vector first_plane = trace_plane_normal;
local vector new_vel = self.velocity;
@@ -382,15 +406,15 @@ void() PM_DanceMove =
// first: move up
trace_endpos_z += PM_STEPHEIGHT;
tracebox (self.origin, self.mins, self.maxs,
- trace_endpos, FALSE, self);
+ trace_endpos, PM_MOVEFLAGS, self);

if (trace_fraction < 1.0f)
{
- // do a simple clipvel to the roof plane
- // right now -- CEV
- f -= f * trace_fraction;
- new_vel -= trace_plane_normal *
- (new_vel * trace_plane_normal);
+ // clip velocity to the roof plane but
+ // don't reduce time_left (f) by the
+ // roof fraction -- CEV
+ new_vel = PM_ClipVelocity (new_vel,
+ trace_plane_normal);

if (trace_ent && trace_ent.touch)
touched_ent = trace_ent;
@@ -401,81 +425,72 @@ void() PM_DanceMove =
end = trace_endpos + (new_vel * f);
end_z = trace_endpos_z;
tracebox (trace_endpos, self.mins, self.maxs, end,
- FALSE, self);
+ PM_MOVEFLAGS, self);
+
+ // reject the step if forward move ends in a solid
+ // in practice this never executes -- CEV
+ if (trace_allsolid || trace_startsolid)
+ goto PM_DanceMove_RejectStep;
+
+ local vector fwd_plane = trace_plane_normal;
+ f -= f * trace_fraction;

- if (trace_fraction >= 1.0f)
+ if (trace_fraction < 1.0f)
+ if (trace_ent && trace_ent.touch)
+ touched_ent = trace_ent;
+
+ // third: move down
+ end = trace_endpos;
+ end_z -= (stepsize + 1);
+ tracebox (trace_endpos, self.mins, self.maxs,
+ end, PM_MOVEFLAGS, self);
+
+ if (trace_allsolid || trace_startsolid)
{
- // forward move didn't hit anything
- // third: move down
- end = trace_endpos;
- end_z -= stepsize;
- tracebox (trace_endpos, self.mins, self.maxs,
- end, FALSE, self);
-
- if (trace_allsolid || trace_startsolid)
- {
- // reject the move
- #ifdef SSQC
- dprint ("PM_DanceMove: down solid\n");
- #endif
- goto PM_DanceMove_RejectStep;
- }
- else if (trace_fraction < 1.0f &&
- trace_plane_normal_z > 0.7f)
+ // reject the step if down move ends in
+ // a solid. again, never executes -- CEV
+ goto PM_DanceMove_RejectStep;
+ }
+ else if (trace_endpos_z - self.origin_z <= 0)
+ {
+ // what am I even doing with this check -- CEV
+ if (fwd_plane != first_plane &&
+ self.velocity * fwd_plane < 0)
{
- // Update time_left, stepsize, origin,
- // velocity & touched_ent (if need);
- // the later inline ClipVel will
- // handle the plane -- CEV
- time_left = f - (f * trace_fraction);
- stepsize = trace_endpos_z -
- self.origin_z;
- /*
- #ifdef CSQC
- // save off stepsize for view smoothing
- if (self.entnum == player_localentnum)
- pmove_step = stepsize;
- #endif
- */
- self.origin = trace_endpos;
-
- if (new_vel != self.velocity)
- self.velocity = new_vel;
-
- if (trace_ent && trace_ent.touch)
- touched_ent = trace_ent;
-
- // don't attempt to step again
- // self.pmove_flags &= ~PMF_SLIDE_STEP;
+ plane2 = plane1;
+ plane1 = fwd_plane;
}
- else
+ goto PM_DanceMove_RejectStep;
+ }
+ else if (trace_fraction < 1.0f &&
+ trace_plane_normal_z > 0.7f)
+ {
+ // we're clear to update time_left, stepsize,
+ // origin, velocity & touched_ent -- CEV
+ time_left = f;
+ stepsize = trace_endpos_z - self.origin_z;
+ self.origin = trace_endpos;
+
+ // the ClipVelocity calls below will handle
+ // trace_plane_normal and fwd_plane -- CEV
+ if (new_vel * fwd_plane < 0)
{
- // reject the move
- goto PM_DanceMove_RejectStep;
+ plane2 = plane1;
+ plane1 = fwd_plane;
}
+
+ self.velocity = new_vel;
+
+ if (trace_ent && trace_ent.touch)
+ touched_ent = trace_ent;
}
else
{
- // forward move hit something
- if (trace_plane_normal != first_plane &&
- trace_plane_normal_z == 0)
- {
- // hit something different than the
- // first move; note that we're not
- // restoring the first plane normal
- if (trace_ent && trace_ent.touch)
- touched_ent = trace_ent;
- time_left -= time_left * trace_fraction;
- stepsize = 0;
- }
- else
- {
- // revert to move before step attempt
- PM_DanceMove_RejectStep:
- touched_ent = trace_ent = first_ent;
- trace_plane_normal = first_plane;
- stepsize = 0;
- }
+ // discard the step attempt
+ PM_DanceMove_RejectStep:
+ touched_ent = trace_ent = first_ent;
+ trace_plane_normal = first_plane;
+ stepsize = 0;
}
}

@@ -505,137 +520,88 @@ void() PM_DanceMove =
self.pmove_flags &= ~PMF_ONGROUND;
}

- // clip velocity to the plane -- CEV
- f = self.velocity * 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
+ if (plane1 && trace_plane_normal * plane1 > 0.99)
+ self.velocity += trace_plane_normal;

- if (f < 0)
- f *= PM_OVERCLIP;
- else
- if (trace_plane_normal_z > 0.7)
- if (self.pmove_flags & PMF_SLIDE_STICKY)
- f /= PM_OVERCLIP;
- else
- f *= PM_ONESIDEDCLIP;
- else
- f /= PM_OVERCLIP;
+ if (plane2 && trace_plane_normal * plane2 > 0.99)
+ self.velocity += trace_plane_normal;

- self.velocity -= trace_plane_normal * f;
+ // clip velocity to the plane -- CEV
+ self.velocity = PM_ClipVelocity (self.velocity,
+ trace_plane_normal);

- // if velocity interacts with prev_plane then clip to it.
- // I'm duplicating a little code here (PM_ClipVelocity),
- // hopefully the audience will forgive me. -- CEV
- if (prev_plane && prev_plane != trace_plane_normal &&
- self.velocity * prev_plane < 0)
+ // if velocity interacts with plane1 then clip to it.
+ if (plane1 != trace_plane_normal && self.velocity * plane1 < 0)
{
- f = self.velocity * prev_plane;
+ self.velocity = PM_ClipVelocity (self.velocity, plane1);

- if (f < 0)
- f *= PM_OVERCLIP;
- else
- if (prev_plane_z > 0.7)
- if (self.pmove_flags & PMF_SLIDE_STICKY)
- f /= PM_OVERCLIP;
- else
- f *= PM_ONESIDEDCLIP;
- else
- f /= PM_OVERCLIP;
-
- self.velocity -= prev_plane * f;
-
- // Slide along the crease of previous plane and
- // current plane if the two still interact -- CEV
+ // slide along the crease if necessary -- CEV
if (self.velocity * trace_plane_normal < 0)
{
- end = crossproduct (prev_plane,
- trace_plane_normal);
+ end = crossproduct (plane1, trace_plane_normal);
end = normalize (end);
self.velocity = end * (end * self.velocity);
}

- // An optimization from Quake 3 -- CEV
- if (prev_plane2 && prev_plane2 != trace_plane_normal &&
- prev_plane2 != prev_plane &&
- self.velocity * prev_plane2 < 0)
+ // an optimization from Quake 3 -- CEV
+ if (plane2 && plane2 != trace_plane_normal &&
+ plane2 != plane1 && self.velocity * plane2 < 0)
{
- // Stop if we interact with three planes -- CEV
- #ifdef SSQC
- dprint ("PM_DanceMove: triple plane stop\n");
- #endif
- self.velocity = '0 0 0';
- PM_DoTouch (touched_ent);
-
- break;
+ // stop if we interact with three planes -- CEV
+ dprint ("PM_DanceMove: position A1\n");
+ goto PM_DanceMove_Stop;
}
}

- // Duplicating the block above here but checking prev_plane2
- // instead of prev_plane. This rarely executes but if we're
- // storing two previous planes we might as well check both.
- // Again this is inlined instead of broken out into multiple
- // functions in the hope that it'll run faster that way -- CEV
- if (prev_plane2 && prev_plane2 != trace_plane_normal &&
- self.velocity * prev_plane2 < 0)
+ // uplicating the block above but checking plane2 instead
+ // of plane1. We're storing two planes so we might as well
+ // check both -- CEV
+ if (plane2 != trace_plane_normal && self.velocity * plane2 < 0)
{
- #ifdef SSQC
- dprint ("PM_DanceMove: interacts with prev_plane2\n");
- #endif
- f = self.velocity * prev_plane2;
-
- if (f < 0)
- f *= PM_OVERCLIP;
- else
- if (prev_plane2_z > 0.7)
- if (self.pmove_flags & PMF_SLIDE_STICKY)
- f /= PM_OVERCLIP;
- else
- f *= PM_ONESIDEDCLIP;
- else
- f /= PM_OVERCLIP;
-
- self.velocity -= prev_plane2 * f;
+ self.velocity = PM_ClipVelocity (self.velocity, plane2);

if (self.velocity * trace_plane_normal < 0)
{
- end = crossproduct (prev_plane2,
- trace_plane_normal);
+ end = crossproduct (plane2, trace_plane_normal);
end = normalize (end);
self.velocity = end * (end * self.velocity);
}

- if (prev_plane && prev_plane != trace_plane_normal &&
- prev_plane2 != prev_plane &&
- self.velocity * prev_plane < 0)
+ if (plane1 && plane1 != trace_plane_normal &&
+ plane2 != plane1 && self.velocity * plane1 < 0)
{
- // Stop if we interact with three planes -- CEV
- #ifdef SSQC
- dprint ("PM_DanceMove: triple plane stop 2\n");
- #endif
- self.velocity = '0 0 0';
- PM_DoTouch (touched_ent);
-
- break;
+ dprint ("PM_DanceMove: position B1\n");
+ goto PM_DanceMove_Stop;
}
}

- // an optimization from Quake 1; is this necessary? -- CEV
+ // an optimization from Quake 1 -- CEV
if (self.velocity * start_vel <= 0)
{
// we've turned against original velocity so zero
// out vel, touch any ents, and stop the loop
+ dprint ("PM_DanceMove: position Z\n");
+ PM_DanceMove_Stop:
self.velocity = '0 0 0';
PM_DoTouch (touched_ent);
break;
}

- // store current plane and prev_plane for later -- CEV
- prev_plane2 = prev_plane;
- prev_plane = trace_plane_normal;
+ // store current plane and plane1 for subsequent loops -- CEV
+ plane2 = plane1;
+ plane1 = trace_plane_normal;

// touch the saved entity last in case doing so overwrites
// trace_plane_normal -- CEV
PM_DoTouch (touched_ent);
}

+ // a final call to setorigin to update links -- CEV
+ setorigin (self, self.origin);
+
// wallclip / wall skim timer check
// if doskim is true and velocity is non-zero and we lost speed
// during the move then restore velocity -- CEV
@@ -677,38 +643,40 @@ void() PM_DanceMove =
if (self.pmove_flags & PMF_SLIDE_GRAVITY)
self.velocity_z -= grav * 0.5;

- // if stepsize is nonzero and we changed from inair to onground then
- // we've airstepped. -- CEV
- if (stepsize > 0 && !(self.pmove_flags & PMF_STARTGROUND) &&
- self.pmove_flags & PMF_ONGROUND)
+ if (self.pmove_flags & PMF_ONGROUND &&
+ self.pmove_flags & PMF_SLIDE_STEP)
{
- // improve stairjumps by mercilessly gluing the player to
- // the floor when their z vel is positive, the jump timer
- // isn't running, the ground is flat horizontal, and we
- // weren't recently pushed -- CEV
- if (self.velocity_z > 0 && self.doublejump_timer == 0 &&
- self.groundnormal_z == 1 &&
- !(self.pmove_flags & PMF_PUSHED) &&
- !(self.pmove_flags & PMF_WATERJUMPED))
+ if (stepsize == 0)
+ stepsize = self.origin_z - self.oldorigin_z;
+
+ // if stepsize is nonzero and we changed from inair to
+ // onground then we've airstepped. -- CEV
+ if (stepsize > 0)
{
- self.velocity_z = 0;
- }
+ if (!(self.pmove_flags & PMF_STARTGROUND))
+ {
+ // improve stairjumps by mercilessly gluing
+ // the player to the floor when their z vel
+ // is positive, the jump timer isn't running,
+ // the ground is flat horizontal, and we
+ // weren't recently pushed -- CEV
+ if (self.velocity_z > 0 &&
+ self.doublejump_timer == 0 &&
+ self.groundnormal_z == 1 &&
+ !(self.pmove_flags & PMF_PUSHED) &&
+ !(self.pmove_flags & PMF_WATERJUMPED))
+ {
+ self.velocity_z = 0;
+ }

- #ifdef SSQC
- // flag to be handled later (see player_postthink) -- CEV
- self.pmove_flags |= PMF_AIRSTEPPED;
- #endif
+ #ifdef SSQC
+ // for later (see player_postthink) -- CEV
+ self.pmove_flags |= PMF_AIRSTEPPED;
+ #endif
+ }
+ }
}

- /*
- #ifdef CSQC
- // prepare step smoothing; inspired by Quake 3 cg_event.c -- CEV
- if (stepsize > 0 && self.entnum == player_localentnum)
- if (player_steptime - time <= 0)
- pmove_step = stepsize;
- #endif
- */
-
// clear slide hint flags -- CEV
self.pmove_flags = self.pmove_flags - (self.pmove_flags &
(PMF_SLIDE_GRAVITY | PMF_SLIDE_SKIM | PMF_SLIDE_STEP |
@@ -717,352 +685,6 @@ void() PM_DanceMove =
// clear push brush flag -- CEV
if (self.groundentity && self.pmove_flags & PMF_PUSHED)
self.pmove_flags &= ~PMF_PUSHED;
-
- // a final call to setorigin to update links -- CEV
- setorigin (self, self.origin);
-};
-
-//----------------------------------------------------------------------
-// PM_DanceMoveQ3
-//
-// An alternate SlideMove based more closely on Q3's SlideMove. This
-// solves all interactions correctly by using an array of planes and a
-// lot of loops. Unfortunately it's slow and greatly affects the way
-// movement feels - heavier, slower - and sometimes seems to affect
-// framerate. Included here (in a working form) so I can experiment
-// with it. -- CEV
-//----------------------------------------------------------------------
-void(float dogravity, float sticky, float dostep, float doskim) PM_DanceMoveQ3 =
-{
- vector plane[PM_MAX_CLIP_PLANES], end, start_v, new_v;
- float backoff, grav, h, i, j, k, np, stepsize, time_left;
- entity touched_ent;
-
- // silence some FTEQCC warnings -- CEV
- backoff = grav = h = i = j = k = np = stepsize = time_left = 0;
-
- if (dogravity)
- {
- if (self.gravity)
- grav = self.gravity;
- else
- grav = 1.0;
- // world_gravity is set in world () (on the server)
- // or PlayerUpdate (client) -- CEV
- grav = grav * world_gravity * input_timelength;
- // Half now, half later. Apparently affects framerate
- // dependence. -- CEV
- self.velocity_z -= grav * 0.5;
- }
-
- new_v = start_v = self.velocity;
-
- if (!(world_airstep) && !(self.pmove_flags & PMF_ONGROUND))
- dostep = FALSE;
-
- if (world_nostep)
- dostep = FALSE;
-
- for (h = 5, time_left = input_timelength; time_left > 0 && h; h--)
- {
- // set our destination & test the move -- CEV
- end = self.origin + (self.velocity * time_left);
- tracebox (self.origin, self.mins, self.maxs, end, FALSE, self);
-
- if (trace_allsolid || trace_startsolid)
- {
- // entity is trapped in a solid; attempt to nudge out
- if (PM_Nudge())
- continue;
-
- // nah, we're stuck. don't build up falling damage
- // but allow sideways acceleration -- CEV
- self.velocity_z = 0;
- break;
- }
-
- // accept the move -- CEV
- self.origin = trace_endpos;
-
- if (trace_fraction >= 1.0f)
- // no obstructions, made the whole move -- CEV
- break;
-
- if (np >= PM_MAX_CLIP_PLANES)
- {
- dprint (sprintf("PM_DanceMoveQ3: no more plane storage,"
- " numbumps: %g\n", fabs(h - 5)));
- self.velocity = '0 0 0';
- break;
- }
-
- // duplicate plane check from Quake3 -- CEV
- /*
- for (i = 0; i < np; i++)
- {
- if (trace_plane_normal * plane[i] > 0.99)
- {
- #ifdef SSQC
- dprint ("PM_DanceMoveQ3: non-axial plane\n");
- #endif
- self.velocity += trace_plane_normal;
- break;
- }
- }
-
- if (i < np)
- continue;
- */
-
- // zero out stepsize, then store the plane normal and touched
- // ent for later, then reduce time_left -- CEV
- stepsize = 0;
- touched_ent = trace_ent;
- plane[np] = trace_plane_normal;
- np++;
- time_left -= time_left * trace_fraction;
-
- // integrated StepSlideMove from Nuclide / CSQCTest -- CEV
- if (dostep && time_left && trace_plane_normal_z == 0)
- {
- i = time_left;
- new_v = self.velocity;
-
- // first: move up
- trace_endpos_z += PM_STEPHEIGHT;
- tracebox (self.origin, self.mins, self.maxs,
- trace_endpos, FALSE, self);
-
- if (trace_fraction < 1.0f)
- {
- // do a simple clipvel to the
- // roof plane right now -- CEV
- i -= i * trace_fraction;
- new_v -= trace_plane_normal *
- (new_v * trace_plane_normal);
- }
-
- // second: move forward
- stepsize = trace_endpos_z - self.origin_z;
- end = trace_endpos + (new_v * i);
- end_z = trace_endpos_z;
- tracebox (trace_endpos, self.mins, self.maxs, end,
- FALSE, self);
-
- // save trace_ent if it has a touch function
- if (trace_ent && trace_ent.touch != __NULL__)
- touched_ent = trace_ent;
-
- if (trace_allsolid || trace_startsolid)
- {
- // reject the move immediately -- CEV
- #ifdef SSQC
- dprint ("PM_DanceMoveQ3: fwd move solid\n");
- #endif
- stepsize = 0;
- self.velocity = '0 0 0';
- break;
- }
- else if (trace_fraction >= 1.0f)
- {
- // forward move didn't hit anything
- // third: move down
- end = trace_endpos;
- end_z -= stepsize + 1;
- tracebox (trace_endpos, self.mins, self.maxs,
- end, FALSE, self);
-
- if (trace_allsolid || trace_startsolid)
- {
- // again reject the move -- CEV
- #ifdef SSQC
- dprint ("PM_DanceMoveQ3: down move "
- "solid\n");
- #endif
- stepsize = 0;
- self.velocity = '0 0 0';
- break;
- }
- else if (trace_fraction < 1.0f &&
- trace_plane_normal_z > 0.7f)
- {
- // we'll let our proper ClipVel loop
- // below take care of this -- CEV
- plane[np - 1] = trace_plane_normal;
- time_left = i - (i * trace_fraction);
- stepsize = trace_endpos_z -
- self.origin_z;
- self.origin = trace_endpos;
-
- if (new_v != self.velocity)
- // hit a roof on the way
- self.velocity = new_v;
-
- touched_ent = trace_ent;
-
- // don't attempt to step again
- dostep = FALSE;
- }
- else
- {
- // down move didn't hit and/or it hit
- // a plane too steep to be ground.
- // reset & continue on -- CEV
- trace_plane_normal = plane[np - 1];
- stepsize = 0;
- }
- }
- else
- {
- // forward move hit something. reset
- // and move on. -- CEV
- trace_plane_normal = plane[np - 1];
- stepsize = 0;
- }
- }
-
- // need to do the ground check & touch the saved ent before
- // we might stop the loop early -- CEV
- if (trace_plane_normal_z > 0.7)
- {
- if (touched_ent.solid == SOLID_BSP)
- {
- self.groundentity = touched_ent;
- self.groundnormal = trace_plane_normal;
- self.flags |= FL_ONGROUND;
- self.pmove_flags |= PMF_ONGROUND;
- }
- }
- else
- {
- self.groundentity = __NULL__;
- self.groundnormal = __NULL__;
- self.flags &= ~FL_ONGROUND;
- self.pmove_flags &= ~PMF_ONGROUND;
- }
-
- // touch the saved entity -- CEV
- PM_DoTouch (touched_ent);
-
- // Quake 3's plane interaction and velocity clipping scheme.
- // Solves more interactions than Q1's FlyMove and Nuclide's
- // Pmove_Custom. Probably the slowest of the three mentioned.
- // -- CEV
- for (i = 0; i < np; i++)
- {
- if (plane[i] != self.groundnormal)
- if (self.velocity * plane[i] >= 0.1)
- continue;
-
- // Inline ClipVelocity / PM_Rebound
- backoff = self.velocity * plane[i];
-
- if (backoff < 0)
- backoff *= PM_OVERCLIP;
- else
- if (sticky)
- backoff /= PM_OVERCLIP;
- else
- backoff *= PM_ONESIDEDCLIP;
-
- new_v = self.velocity - (plane[i] * backoff);
-
- // new_v -= plane[i] * (new_v * plane[i]);
-
- for (j = 0; j < np; j++)
- {
- if (j == i)
- continue;
-
- if (plane[j] != self.groundnormal)
- if (new_v * plane[j] >= 0.1)
- continue;
-
- // duplicating code here to avoid a function
- // call -- CEV
- backoff = new_v * plane[j];
-
- if (backoff < 0)
- backoff *= PM_OVERCLIP;
- else
- if (sticky)
- backoff /= PM_OVERCLIP;
- else
- backoff *= PM_ONESIDEDCLIP;
-
- new_v -= plane[j] * backoff;
-
- // new_v -= plane[j] * (new_v * plane[j]);
-
- // see if we still interact with the first
- // clip plane (an optimization from Q3)
- if (new_v * plane[i] >= 0)
- continue;
-
- if (sticky)
- continue;
-
- // slide along the crease
- end = crossproduct (plane[i], plane[j]);
- end = normalize (end);
- new_v = end * (end * new_v);
-
- // see if the move enters a third plane
- for (k = 0; k < np; k++)
- {
- if (k == i || k == j)
- continue;
-
- if (new_v * plane[k] >= 0.1)
- // no interaction
- continue;
-
- #ifdef SSQC
- dprint ("PM_DanceMoveQ3: 3x stop\n");
- #endif
- self.velocity = '0 0 0';
-
- // break out of all the loops now
- // by skipping directly to the end
- goto dancemove_end;
- }
- }
-
- // try another move
- self.velocity = new_v;
- break;
- }
-
- // an optimization from Quake 1; is this necessary? -- CEV
- if (self.velocity * start_v <= 0)
- {
- // we've turned against original velocity so
- // clear vel and stop the loop
- self.velocity = '0 0 0';
- break;
- }
- }
-
- dancemove_end:
-
- // wallclip / wall skim timer check
- // if doskim is true and velocity is non-zero and we lost speed
- // during the move then restore velocity -- CEV
- if (doskim && self.velocity && (vlen(start_v) > vlen(self.velocity)))
- {
- if (sticky)
- self.velocity = [start_v_x, start_v_y,
- min (start_v_z, self.velocity_z)];
- else
- self.velocity = start_v;
- }
-
- // final gravity check here -- CEV
- if (dogravity)
- self.velocity_z -= grav * 0.5;
-
- // a final call to setorigin to update links -- CEV
- setorigin (self, self.origin);
};

//----------------------------------------------------------------------
@@ -1077,6 +699,8 @@ void() PM_CategorizePosition =
if (self.groundentity != __NULL__)
self.groundentity = __NULL__;
self.groundnormal = __NULL__;
+ // use a large value for distance when no groundentity -- CEV
+ self.grounddistance = 32767;
if (self.pmove_flags & PMF_DOUBLEJUMPED)
self.pmove_flags &= ~PMF_DOUBLEJUMPED;
if (self.pmove_flags & PMF_WALLJUMPED)
@@ -1087,18 +711,21 @@ void() PM_CategorizePosition =
self.flags &= ~FL_ONGROUND;
if (self.pmove_flags & PMF_PUSHED)
self.pmove_flags &= ~PMF_PUSHED;
+ if (self.pmove_flags & PMF_CLIMB1)
+ self.pmove_flags &= ~PMF_CLIMB1;
+ if (self.pmove_flags & PMF_CLIMB2)
+ self.pmove_flags &= ~PMF_CLIMB2;
}
else
{
- // TODO CEV there must be a way to optimize out this
- // tracebox ground check some of the time
-
// do a trace to check for ground
tracebox (self.origin, self.mins, self.maxs,
- self.origin - PM_GROUNDDIST_V, FALSE, self);
+ self.origin - '0 0 1024', PM_MOVEFLAGS, self);

- // only onground if we hit it & it faces upwards
- if (trace_fraction < 1.0f && trace_plane_normal_z > 0.7f)
+ self.grounddistance = self.origin_z - trace_endpos_z;
+
+ // only onground if we're within one unit & it faces upwards
+ if (self.grounddistance <= 1 && trace_plane_normal_z > 0.7f)
{
// on ground
if (!(self.pmove_flags & PMF_ONGROUND) &&
@@ -1125,30 +752,39 @@ void() PM_CategorizePosition =

self.groundnormal = trace_plane_normal;

+ #ifdef CSQC
+ // don't smooth out steps when on a networked ent -- CEV
+ if (trace_networkentity)
+ view_step_disable = TRUE;
+ else if (view_step_disable)
+ view_step_disable = FALSE;
+ #endif
+
if (!(self.flags & FL_ONGROUND))
self.flags |= FL_ONGROUND;
if (!(self.pmove_flags & PMF_ONGROUND))
self.pmove_flags |= PMF_ONGROUND;

- // TODO CEV
- // for MOVETYPE_PUSH entities
- #if 0
- if (trace_ent.velocity_z > 0)
- self.velocity_z += trace_ent.velocity_z;
- #endif
-
if (self.pmove_flags & PMF_WALLJUMPED)
self.pmove_flags &= ~PMF_WALLJUMPED;

if (self.pmove_flags & PMF_PUSHED)
self.pmove_flags &= ~PMF_PUSHED;
+
+ if (self.pmove_flags & PMF_CLIMB1)
+ self.pmove_flags &= ~PMF_CLIMB1;
+ if (self.pmove_flags & PMF_CLIMB2)
+ self.pmove_flags &= ~PMF_CLIMB2;
}
else
{
// not on ground
if (self.groundentity != __NULL__)
self.groundentity = __NULL__;
- self.groundnormal = __NULL__;
+ if (self.groundnormal)
+ self.groundnormal = __NULL__;
+ if (self.grounddistance < 32767)
+ self.grounddistance = 32767;
if (self.flags & FL_ONGROUND)
self.flags &= ~FL_ONGROUND;
if (self.pmove_flags & PMF_ONGROUND)
@@ -1314,7 +950,7 @@ void() PM_CrouchStop =
{
// uncrouch if we're clear to stand
tracebox (self.origin, PM_STAND_MIN, PM_STAND_MAX, self.origin,
- FALSE, self);
+ PM_MOVEFLAGS, self);
if (!trace_startsolid && !trace_allsolid)
{
self.pmove_flags &= ~PMF_CROUCHED;
@@ -1430,26 +1066,26 @@ void(vector wishdir) PM_Jump =
// set the doublejump flag -- CEV
self.pmove_flags |= PMF_DOUBLEJUMPED;
}
- // Commented out for now -- TODO CEV
- /*
else if (input_movevalues_y && input_movevalues_x == 0 &&
- vlen (self.velocity) <= PM_SHORTJUMPTHRESH)
+ self.speed <= PM_SHORTJUMPTHRESH)
{
- // short jump with added sideways velocity - a dodge
- self.velocity_z = 0;
- self.velocity = wishdir * PM_BOOSTWISHSPEED;
- // self.velocity = normalize (self.velocity);
- // self.velocity *= 400;
+ // short fast sideways jump - a dodge -- CEV
+ #ifdef SSQC
+ local float r1 = rint (random() * 3);
+ vol = 0.2;
+ wav = sprintf ("player/jump0%g.ogg", r1 + 1);
+ #endif
+
+ self.velocity = wishdir * 400;
self.velocity_z = PM_SHORTJUMPSPEED;
}
- */
else
{
// normal jump
#ifdef SSQC
- local float r = rint (random() * 3);
+ local float r2 = rint (random() * 3);
vol = 0.1;
- wav = sprintf ("player/jump0%g.ogg", r + 1);
+ wav = sprintf ("player/jump0%g.ogg", r2 + 1);
#endif

// do an additive jump on non-flat ground -- CEV
@@ -1467,7 +1103,6 @@ void(vector wishdir) PM_Jump =
self.pmove_flags &= ~PMF_ONGROUND;
self.flags &= ~FL_ONGROUND;
self.pmove_flags |= PMF_JUMP_HELD;
- self.button2 = 0;

if (self.pmove_flags & PMF_CROUCHSLIDE)
PM_CrouchSlideStop ();
@@ -1484,7 +1119,7 @@ void(vector wishdir) PM_Jump =
};

//----------------------------------------------------------------------
-// PM_WallJump
+// PM_WallJump -- Wall jumping, mantling, and climbing -- CEV
//----------------------------------------------------------------------
void() PM_WallJump =
{
@@ -1492,40 +1127,31 @@ void() PM_WallJump =
// or is jump being held?
if (self.conlevel > WATERLEVEL_NONE ||
self.pmove_flags & PMF_WATERJUMPED ||
- self.pmove_flags & PMF_JUMP_HELD ||
self.pmove_flags & PMF_WALLJUMPED)
{
return;
}

- // mandatory interval between jump and walljump
- // if (self.doublejump_timer <= PM_WALLJUMP_WINDOW)
- // return;
-
if (self.velocity_z < PM_WALLJUMPLIMIT)
- {
- // falling too fast to walljump
- // TODO CEV it would be a good idea to include a sound here.
- /*
- #ifdef SSQC
- dprint ("PM_WallJump: falling too fast, returning\n");
- #endif
- */
+ // falling too fast to walljump -- CEV
return;
- }

- // start at STEPHEIGHT + 1 to try and clear any steps -- CEV
- local float f = 0;
- local vector start = self.origin;
- // start_z += PM_STEPHEIGHT + 1;
- start_z = start_z + 12;
- local vector end = start;
+ // ground distance is set in PM_CategorizePosition -- CEV
+ if (self.grounddistance <= 32)
+ // within 32 units of the floor, abort -- CEV
+ return;

- for (float i = 0; i < 4; i++)
+ local float i;
+ local float dot = 0;
+ local float dist = 0;
+ local vector start, end;
+ start = end = self.origin;
+
+ for (i = 0; i < 4; i++)
{
// I've borrowed a little logic from Quake Champions Classic
// here, shoutout to RhapsodyInGeek, check out their good work
- // https://github.com/RhapsodyInGeek/Quake-Champions-Classic
+ // https://github.com/Quake-Champions-Classic/mod
// v_forward and v_right should still correspond to the
// makevectors call from PM_Move -- CEV
if (i < 2)
@@ -1544,52 +1170,151 @@ void() PM_WallJump =
end = start + end;

// this ends up firing *a lot* when hopping through a map
- // normally, unfortunately. traceline may be better here -- CEV
- tracebox (start, PM_CROUCH_MIN, PM_CROUCH_MAX, end, TRUE, self);
+ // normally (specifically when releasing jump button after
+ // a jump has registered). traceline would be better here
+ // except it complicates wall climbing. -- CEV
+ tracebox (start, PM_CROUCH_MIN, PM_CROUCH_MAX, end,
+ 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,
+ vlen(self.origin - trace_endpos)));
+ #endif

// in order: we hit something, that something is vaguely
// vertical, and that something is within 20 (units?) -- CEV
if (trace_fraction < 1.0f &&
trace_plane_normal_z <= 0.7f &&
- trace_plane_normal_z >= 0 &&
- vlen(self.origin - trace_endpos) <= 20)
+ trace_plane_normal_z >= 0)
+ // vlen(self.origin - trace_endpos) <= 20)
{
- // If self.velocity * trace_plane_normal is less than
- // zero that means the user is directing their movement
- // *into* the wall instead of away from it. Could be
- // useful later for vaulting or climbing. -- CEV
- f = self.velocity * trace_plane_normal;
- if (f >= 0)
+ dot = self.velocity * trace_plane_normal;
+ if (dot >= 0 && (!(self.pmove_flags & PMF_JUMP_HELD)))
{
- // moving away from the wall
+ // moving away from the wall -- CEV
self.pmove_flags |= PMF_WALLJUMPED;
break;
}
- #ifdef SSQC
- else
+ else if (i == 0 && self.pmove_flags & PMF_JUMP_HELD &&
+ self.speed <= PM_MAXSPEED &&
+ fabs(self.velocity_z) < 90.0f &&
+ self.grounddistance > 42)
{
- dprint (sprintf("PM_WallJump: wallclimb "
- "normalspeed %f\n", f));
+ // holding jump and moving *into* the wall
+ // at a rate below MAXSPEED with a low Z
+ // velocity and at least 43 units away from
+ // the ground; attempt to climb -- CEV
+
+ local vector tpn_ang;
+ tpn_ang = vectoangles (trace_plane_normal);
+
+ // must be facing the impacted surface -- CEV
+ if (angledif(input_angles_y, tpn_ang_y) <= 150)
+ continue;
+
+ // we're looking for empty space, for a trace
+ // to not hit anything, so use tracelines
+ // below -- CEV
+
+ // horizontal forward at least 64u off floor
+ start_z += 22;
+ traceline (start, start + v_forward * 30,
+ MOVE_NOMONSTERS | PM_MOVEFLAGS, self);
+
+ if (trace_fraction >= 1.0f)
+ {
+ // ranger's fingies can't grip a
+ // vertical surface -- CEV
+ traceline (trace_endpos,
+ trace_endpos - '0 0 64',
+ MOVE_NOMONSTERS | PM_MOVEFLAGS,
+ self);
+
+ if (trace_plane_normal_z > 0.7f)
+ {
+ dist = trace_endpos_z -
+ (self.origin_z +
+ self.mins_z);
+ self.pmove_flags |= PMF_CLIMB1;
+ self.pmove_flags &= ~PMF_CLIMB2;
+ break;
+ }
+ }
+
+ // horizontal forward at least 96u off floor
+ start_z += 32;
+ traceline (start, start + v_forward * 30,
+ MOVE_NOMONSTERS | PM_MOVEFLAGS, self);
+
+ if (trace_fraction >= 1.0f)
+ {
+ traceline (trace_endpos,
+ trace_endpos - '0 0 64',
+ MOVE_NOMONSTERS | PM_MOVEFLAGS,
+ self);
+
+ if (trace_plane_normal_z > 0.7f)
+ {
+ dist = trace_endpos_z -
+ (self.origin_z +
+ self.mins_z);
+ self.pmove_flags &= ~PMF_CLIMB1;
+ self.pmove_flags |= PMF_CLIMB2;
+ break;
+ }
+ }
+
+ start = self.origin;
}
- #endif
}
+
+ // player can't hold on to thin air -- CEV
+ if (self.pmove_flags & PMF_CLIMB1)
+ self.pmove_flags &= ~PMF_CLIMB1;
+ if (self.pmove_flags & PMF_CLIMB2)
+ self.pmove_flags &= ~PMF_CLIMB2;
}

- if (self.pmove_flags & PMF_WALLJUMPED)
+ if (self.pmove_flags & PMF_CLIMB1)
+ {
+ // climb up to a near edge
+ local float zspeed = self.velocity_z;
+ self.velocity *= PM_CLIMBSCALE;
+ self.velocity_z = bound (PM_CLIMBSPEED,
+ zspeed + PM_CLIMBSPEED, PM_CLIMBSPEED * 2);
+ #ifdef SSQC
+ dprint (sprintf("PM_WallJump: climb offset 1, i %g, vel_z %g, "
+ "dist %g\n", i, self.velocity_z, dist));
+ #endif
+ }
+ else if (self.pmove_flags & PMF_CLIMB2)
+ {
+ // climb to an edge farther away
+ local float zspeed2 = self.velocity_z;
+ self.velocity *= PM_CLIMBSCALE;
+ self.velocity_z = bound (PM_CLIMBSPEED * 0.5,
+ zspeed2 + PM_CLIMBSPEED, PM_CLIMBSPEED);
+ #ifdef SSQC
+ dprint (sprintf("PM_WallJump: climb offset 2, i %g, vel_z %g, "
+ "dist %g\n", i, self.velocity_z, dist));
+ #endif
+ }
+ else if (self.pmove_flags & PMF_WALLJUMPED)
{
#ifdef SSQC
local float vol = 0;
local string wav = "";
#endif

- // bounce off the wall plane -- CEV
- self.velocity_x += trace_plane_normal_x * PM_WALLJUMPFORCE;
- self.velocity_y += trace_plane_normal_y * PM_WALLJUMPFORCE;
+ // walljump; bounce off the wall plane -- CEV
+ self.velocity_z = 0;
+ self.velocity += trace_plane_normal * PM_WALLJUMPFORCE;

if (self.doublejump_timer > 0)
{
#ifdef SSQC
- dprint ("PM_WallJump: wall double ");
+ // dprint ("PM_WallJump: wall double ");
vol = 0.9;
wav = "player/plyrjmp8.wav";
#endif
@@ -1598,7 +1323,7 @@ void() PM_WallJump =
else
{
#ifdef SSQC
- dprint ("PM_WallJump: walljump ");
+ // dprint ("PM_WallJump: walljump ");
local float r = rint (random() * 3);
vol = 0.2;
wav = sprintf ("player/jump0%g.ogg", r + 1);
@@ -1612,9 +1337,7 @@ void() PM_WallJump =

// server-side stuff
#ifdef SSQC
- dprint (sprintf("dist %g, normalspeed %g\n",
- vlen(self.origin - trace_endpos), f));
- self.button2 = 0;
+ // dprint (sprintf("i %g, normalspeed %g\n", i, dot));
player_footstep ();
if (wav != "")
sound (self, CHAN_BODY, wav, vol, ATTN_NORM);
@@ -1641,20 +1364,20 @@ void(vector wishvel, float move_time) PM_WalkAccelerate =
if (self.pmove_flags & PMF_ONLADDER)
{
// ladder physics
- self.velocity *= 0.75;
+ self.velocity *= PM_CLIMBSCALE;

- if (input_buttons & INPUT_BUTTON2 || self.button2 > 0 ||
+ if (input_buttons & INPUT_BUTTON2 ||
input_movevalues_z > 0)
{
// PlayerClimb -- johnfitz
- self.velocity_z = 160;
+ 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 = -160;
+ self.velocity_z = -PM_CLIMBSPEED;
}
else
{
@@ -1667,8 +1390,7 @@ void(vector wishvel, float move_time) PM_WalkAccelerate =
}
else
{
- if (input_buttons & INPUT_BUTTON2 || self.button2 > 0 ||
- input_movevalues_z > 0)
+ if (input_buttons & INPUT_BUTTON2)
{
// +jump was pressed
if (self.pmove_flags & PMF_ONGROUND)
@@ -1681,6 +1403,7 @@ void(vector wishvel, float move_time) PM_WalkAccelerate =
else
{
self.flags |= FL_JUMPRELEASED;
+ self.pmove_flags &= ~PMF_JUMP_HELD;
}

if (input_buttons & INPUT_BUTTON8 &&
@@ -1923,8 +1646,6 @@ void(vector wishvel, float move_time) PM_WalkAccelerate =
if (newspeed > speed1)
newspeed = speed1;

- // self.velocity += newspeed * wishdir;
-
// below is an attempt to separate turning radius
// from acceleration. -- CEV

@@ -1936,7 +1657,8 @@ void(vector wishvel, float move_time) PM_WalkAccelerate =
if (newspeed > speed1)
{
// we've gained speed; reduce -- CEV
- newspeed = (newspeed - speed1) * 0.4;
+ newspeed = (newspeed - speed1) *
+ PM_AIRACCELSCALE;
newspeed += speed1;
// now apply the new speed -- CEV
self.velocity = normalize (wishdir);
@@ -2108,9 +1830,12 @@ void(vector wishvel, float scale, float move_time) PM_NoClipAccelerate =
{
local float wishspeed;

- // smartjump
- if (input_buttons & 2)
+ if (input_buttons & INPUT_BUTTON2)
+ // smartjump
wishvel_z = max (PM_MAXSPEED, wishvel_z);
+ else if (input_buttons & INPUT_BUTTON8)
+ // smartcrouch
+ wishvel_z = min (-PM_MAXSPEED, wishvel_z);

wishspeed = vlen (wishvel) * scale;
wishvel = normalize (wishvel);
@@ -2144,10 +1869,6 @@ void(float move_time) PM_ManageTimers =
//----------------------------------------------------------------------
void(entity e) PM_Move =
{
- if (input_timelength <= 0)
- // don't process partial frames -- CEV
- return;
-
// 'self' in this context is not reliable; it should be set to
// the entity passed to this function -- CEV
local entity oself = self;
@@ -2208,7 +1929,7 @@ void(entity e) PM_Move =
}
}

- // TODO CEV this is the wrong place to clear PMF_JUMP_HELD
+ // 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;

@@ -2228,6 +1949,8 @@ void(entity e) PM_Move =
PM_CategorizePosition ();
PM_ManageTimers (0);

+ self.speed = vlen ([self.velocity_x, self.velocity_y, 0]);
+
switch (self.movetype)
{
case MOVETYPE_WALK:
@@ -2312,13 +2035,20 @@ void(entity e) PM_Move =
// signal accel functions we're post-move
self.pmove_flags &= ~PMF_PRE_MOVE;

- // second pass at acceleration
+ // second pass at acceleration, making sure
+ // our v_ vectors are correct
if (self.conlevel >= WATERLEVEL_WAIST)
+ {
+ makevectors (input_angles);
PM_SwimAccelerate (wishvel,
input_timelength * 0.5f);
+ }
else
+ {
+ makevectors ([0, input_angles_y, 0]);
PM_WalkAccelerate (wishvel,
input_timelength * 0.5f);
+ }

// timers (part 2) -- CEV
PM_ManageTimers (input_timelength * 0.5f);
@@ -2361,11 +2091,7 @@ void(entity e) PM_Move =
break;
}

- #ifdef CSQC
- // oldorigin is saved in player_postthink on the server -- CEV
self.oldorigin = self.origin;
- #endif
-
self.speed = vlen ([self.velocity_x, self.velocity_y, 0]);

// make sure we've touched the ground entity (it might've slipped

Return to the top of this page or return to the overview of this repo.

Diff qc/projectiles/bolt.qc

diff --git a/qc/projectiles/bolt.qc b/qc/projectiles/bolt.qc
new file mode 100644
index 0000000..edba774
--- /dev/null
+++ b/qc/projectiles/bolt.qc
@@ -0,0 +1,221 @@
+//==============================================================================
+// Tribolt projectile -- using DOE minigrenade assets -- CEV
+//==============================================================================
+
+//======================================================================
+// constants
+//======================================================================
+const float BOLT_SPEED = 1200; // 1600ups in QC
+const float BOLT_DIRECT_DAMAGE = 35; // 35 in QC
+const float BOLT_SPLASH_DAMAGE = 35; // 35 damage per bolt in QC
+const float BOLT_SPLASH_MINIMUM = 10; // minimum splash damage per bolt
+const float BOLT_SPLASH_RADIUS = 100; // same as grenade
+const float BOLT_FIRING_DELAY = 0.125f; // 0.125 in QC
+const float BOLT_LIFETIME = 0.8; // 0.6 in QC; 0.8 * 1200 = 960
+
+const vector BOLT_MINS = '0 0 0'; // zero size for mininades
+const vector BOLT_MAXS = '0 0 0';
+
+//======================================================================
+// forward declarations
+//======================================================================
+
+// projectile_bolt
+void() projectile_bolt_think;
+void() projectile_bolt_think_delay;
+void() projectile_bolt_touch;
+entity(entity src, float d) spawn_projectile_bolt;
+void(entity e) projectile_bolt_init_velocity;
+void(entity e) projectile_bolt_init;
+strip void() projectile_bolt;
+
+//------------------------------------------------------------------------------
+
+//----------------------------------------------------------------------
+// class projectile_bolt: base_projectile
+// {
+ //--------------------------------------------------------------
+ void() projectile_bolt_explode =
+ {
+ if (self.takedamage)
+ self.takedamage = DAMAGE_NO;
+
+ t_radiusdamage3 (self, self.owner, self.splash_damage,
+ 100, BOLT_SPLASH_MINIMUM, other);
+
+ // BecomeExplosion
+ pointparticles (particleeffectnum("te_explosion2_230_5"),
+ self.origin);
+ sound (self, CHAN_WEAPON, "cev/tribolt/boltexpl.ogg",
+ 1.0, ATTN_NORM);
+ become_base_explosion (self);
+ };
+
+ //--------------------------------------------------------------
+ void() projectile_bolt_think =
+ {
+ projectile_bolt_explode ();
+ };
+
+ //--------------------------------------------------------------
+ void() projectile_bolt_think_delay =
+ {
+ if (self.owner && self.owner.health > 0)
+ {
+ self.origin = self.owner.origin;
+ if (self.owner.classgroup & CG_MONSTER)
+ self.owner.effects |= EF_MUZZLEFLASH;
+ projectile_bolt_init_velocity (self);
+ projectile_bolt_init (self);
+ }
+ else
+ {
+ // remove on next tick -- CEV
+ self.think = sub_remove;
+ self.nextthink = time + 0.1;
+ }
+ };
+
+ //--------------------------------------------------------------
+ void() projectile_bolt_touch =
+ {
+ if (base_projectile_check_touch())
+ return;
+
+ if (other.takedamage == DAMAGE_AIM)
+ {
+ t_damage2 (other, self, self.owner,
+ self.direct_damage);
+ projectile_bolt_explode ();
+ return;
+ }
+
+ // stop dead at whatever point we hit -- CEV
+ sound (self, CHAN_WEAPON, "weapons/bounce.wav",
+ VOL_HIGH, ATTN_NORM);
+ self.movetype = MOVETYPE_NONE;
+ self.velocity = '0 0 0';
+ self.avelocity = '0 0 0';
+ };
+
+ //--------------------------------------------------------------
+ // arguments are source entity, origin, velocity, and delay -- CEV
+ //--------------------------------------------------------------
+ entity(entity src, float d) spawn_projectile_bolt =
+ {
+ local entity e = spawn ();
+ e.owner = src;
+ e.origin = src.origin;
+ // damage
+ e.direct_damage = BOLT_DIRECT_DAMAGE;
+ e.splash_damage = BOLT_SPLASH_DAMAGE;
+ // model, skin, & sounds
+ e.mdl_proj = src.mdl_proj;
+ e.skin_proj = src.skin_proj;
+ e.snd_hit = src.snd_hit;
+
+ if (d)
+ {
+ // delay spawning
+ e.think = projectile_bolt_think_delay;
+ e.nextthink = time + d;
+ }
+ else
+ {
+ // spawn now
+ if (e.owner.classgroup & CG_MONSTER)
+ e.owner.effects |= EF_MUZZLEFLASH;
+ projectile_bolt_init_velocity (e);
+ projectile_bolt_init (e);
+ }
+
+ return e;
+ };
+
+ //--------------------------------------------------------------
+ void(entity e) projectile_bolt_init_velocity =
+ {
+ if (e.owner && e.owner.health > 0)
+ {
+ if (e.owner.classgroup & CG_MONSTER)
+ {
+ if (e.owner.attack_elevation)
+ {
+ local vector ang = e.owner.angles;
+ ang_x = -e.owner.attack_elevation;
+ makevectors (ang);
+ e.velocity = v_forward * BOLT_SPEED +
+ crandom() * v_right * 10 +
+ crandom() * v_up * 10;
+ }
+ else
+ {
+ e.velocity = normalize (
+ e.enemy.origin - e.origin);
+ e.velocity *= BOLT_SPEED;
+ e.velocity_z = 200;
+ }
+ }
+ else if (e.owner.v_angle_x)
+ {
+ makevectors (e.owner.v_angle);
+ e.velocity = v_forward * BOLT_SPEED +
+ v_up * 200 +
+ crandom() * v_right * 10 +
+ crandom() * v_up * 10;
+ }
+ else
+ {
+ e.velocity = aim (e.owner, 10000);
+ e.velocity *= BOLT_SPEED;
+ e.velocity_z = 200;
+ }
+ }
+ else
+ {
+ // remove on next tick -- CEV
+ e.think = sub_remove;
+ e.nextthink = time + 0.1;
+ }
+ }
+
+ //--------------------------------------------------------------
+ void(entity e) projectile_bolt_init =
+ {
+ base_projectile_init (e);
+
+ e.classname = "projectile_bolt";
+ e.classtype = CT_PROJECTILE_BOLT;
+ e.movetype = MOVETYPE_BOUNCE;
+ e.solid = SOLID_BBOX;
+ e.think = projectile_bolt_think;
+ e.touch = projectile_bolt_touch;
+ e.aflag |= PROJECTILE_EXPLOSIVE;
+ e.angles = vectoangles (e.velocity);
+
+ if (!e.avelocity)
+ e.avelocity = '300 300 300';
+
+ if (!e.splash_damage)
+ e.splash_damage = BOLT_SPLASH_DAMAGE;
+
+ // DOE multi grenade model but at half the size -- CEV
+ setmodel (e, "progs/mervup.mdl");
+ e.skin = 0;
+ e.scale = 0.5;
+
+ setsize (e, BOLT_MINS, BOLT_MAXS);
+ setorigin (e, e.origin);
+
+ // set missile duration
+ e.nextthink = time + BOLT_LIFETIME;
+ };
+
+ //--------------------------------------------------------------
+ strip void() projectile_bolt =
+ {
+ projectile_bolt_init (self);
+ };
+// };
+
+

Return to the top of this page or return to the overview of this repo.

Diff qc/projectiles/flak.qc

diff --git a/qc/projectiles/flak.qc b/qc/projectiles/flak.qc
index 48f9aeb..4ee1b75 100644
--- a/qc/projectiles/flak.qc
+++ b/qc/projectiles/flak.qc
@@ -7,7 +7,7 @@
//======================================================================
// constants
//======================================================================
-const float FLAK_DIRECT_DAMAGE = 4; // default direct damage
+const float FLAK_DIRECT_DAMAGE = 8; // default direct damage; was 4
// flak doesn't splash
const float FLAK_SPEED = 800; // speed of BDW's OgreFireFlak

@@ -66,9 +66,6 @@ strip void() projectile_flak;
{
spawn_touchblood (self.direct_damage);

- sound (self, CHAN_VOICE, "fish/bite.wav",
- VOL_HIGH, ATTN_NORM);
-
if (other.spikecount)
{
// not the first one
@@ -77,6 +74,9 @@ strip void() projectile_flak;
return;
}

+ sound (self, CHAN_VOICE, "fish/bite.wav",
+ VOL_HIGH, ATTN_NORM);
+
// the first one...
other.spikecount = self.direct_damage;

Return to the top of this page or return to the overview of this repo.

Diff qc/projectiles/wizardspell.qc

diff --git a/qc/projectiles/wizardspell.qc b/qc/projectiles/wizardspell.qc
index 6a0d63c..1709a43 100644
--- a/qc/projectiles/wizardspell.qc
+++ b/qc/projectiles/wizardspell.qc
@@ -179,15 +179,8 @@ strip void() projectile_wizardspell;
//--------------------------------------------------------------
void() projectile_wizardspell_think =
{
- // make sure owner still exists -- CEV
- if (!self.owner)
- {
- remove (self);
- return;
- }
-
// make sure owner is still alive
- if (self.owner.health > 0)
+ if (self.owner && self.owner.health > 0)
{
self.owner.effects |= EF_MUZZLEFLASH;

@@ -203,7 +196,8 @@ strip void() projectile_wizardspell;
self.owner, self.origin, dir);
}

- remove (self);
+ self.think = sub_remove;
+ self.nextthink = time + 0.1;
};

//--------------------------------------------------------------

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 4737968..43cf643 100644
--- a/qc/sv_entry.qc
+++ b/qc/sv_entry.qc
@@ -832,13 +832,8 @@ void() PlayerPreThink =
//----------------------------------------------------------------------
void() SV_RunClientCommand =
{
- // should match the one used by csqc.
- if (world_standardphysics)
- // for testing -- CEV
- runstandardplayerphysics (self);
- else
- // for real. See pmove.qc -- CEV
- PM_Move (self);
+ // see pmove.qc -- CEV
+ PM_Move (self);
};

//----------------------------------------------------------------------
@@ -880,6 +875,7 @@ void() StartFrame =
gamestarted = TRUE;
}

+ /*
// aid clientside prediction by updating any networked SOLID_BSP
// MOVETYPE_PUSH entities that are in motion. I hate looping
// through all entities like this. -- CEV
@@ -892,11 +888,12 @@ void() StartFrame =
if (e.classgroup & CG_FUNC)
// only ents in motion with a SendEntity func
if (e.velocity && e.SendEntity)
- // transmit origin, vel, state, speed
+ // transmit origin and velocity
e.SendFlags |= BASE_FUNC_NET_ORIGIN |
BASE_FUNC_NET_VELOCITY |
BASE_FUNC_NET_SPEED;
}
+ */
};

//----------------------------------------------------------------------

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 40cee89..84917e1 100644
--- a/qc/sv_progs.src
+++ b/qc/sv_progs.src
@@ -20,7 +20,6 @@ defs_ctypes.qc // global class list
// utility & helper functions
//----------------------------------------------------------------------
math.qc // Code by Joshua Skelton + misc
-utility.qc
newflags.qc // new spawnflags for all entities
cshift.qc // background color shift controller
keylock.qc // common code for entities unlockable with keys
@@ -54,6 +53,7 @@ info/teleport_destination.qc // teleporter endpoints
//----------------------------------------------------------------------
// projectiles - these were all previously in weapons.qc
//----------------------------------------------------------------------
+projectiles/bolt.qc // Quake Champions-like tribolt projectiles
projectiles/bullet.qc // id1 shotguns
projectiles/fireball.qc // id1 fireball (spawned by misc_fireball)
projectiles/flak.qc // pd3 flak

Return to the top of this page or return to the overview of this repo.

Diff qc/triggers/fog.qc

diff --git a/qc/triggers/fog.qc b/qc/triggers/fog.qc
index fa4d795..5b858b9 100644
--- a/qc/triggers/fog.qc
+++ b/qc/triggers/fog.qc
@@ -44,6 +44,13 @@ const float FOGBLEND_BLENDTO = 8;
//======================================================================

#ifdef SSQC
+float(float in) zeroconvert;
+float(float in, float def) zeroconvertdefault;
+float(vector v, vector s) bounds_angle_size;
+void(entity client, float f) stuffcmd_digit;
+void(entity client, float f, float numdigits) stuffcmd_int;
+void(entity client, float f) stuffcmd_float;
+
void(entity client, float density, vector color) fog_save;
void(entity client) fog_save_to_previous;
void(entity client, float density) skyfog_save;
@@ -97,6 +104,157 @@ void() trigger_fog;
//------------------------------------------------------------------------------

#ifdef SSQC
+//======================================================================
+// Sourced from utility.qc from smej2
+//======================================================================
+
+//----------------------------------------------------------------------
+// shorthand for turning -1 to 0 for keyvalues for which 0 is a
+// valid non-default selection
+//----------------------------------------------------------------------
+float(float in) zeroconvert =
+{
+ if (in == -1)
+ return 0;
+ return in;
+};
+
+//----------------------------------------------------------------------
+float(float in, float def) zeroconvertdefault =
+{
+ if (in == -1)
+ return 0;
+ if (in == 0)
+ return def;
+ return in;
+}
+
+//----------------------------------------------------------------------
+// for measuring how large an entity is along an arbitrary vector
+// FIXME: this is trash and it returns trash
+//----------------------------------------------------------------------
+float(vector v, vector s) bounds_angle_size =
+{
+ v_x = fabs (v_x);
+ v_y = fabs (v_y);
+ v_z = fabs (v_z);
+
+ // size is always + + + but this is in case I switch the
+ // parameters somewhere
+ s_x = fabs (s_x);
+ s_y = fabs (s_y);
+ s_z = fabs (s_z);
+
+ return v * s;
+};
+
+//======================================================================
+// wonderful stuffcmd code from Honey by czg
+//======================================================================
+
+//----------------------------------------------------------------------
+// stuffcmd_float
+// This is a horrible hack that I am ashamed of!
+//----------------------------------------------------------------------
+void(entity client, float f) stuffcmd_digit =
+{
+ local float d;
+ d = floor (f);
+ d = mod (d, 10);
+
+ // CLOSE YOUR EYES, HONEY! DON'T LOOK!
+ switch (d)
+ {
+ case 0: stuffcmd (client, "0"); break;
+ case 1: stuffcmd (client, "1"); break;
+ case 2: stuffcmd (client, "2"); break;
+ case 3: stuffcmd (client, "3"); break;
+ case 4: stuffcmd (client, "4"); break;
+ case 5: stuffcmd (client, "5"); break;
+ case 6: stuffcmd (client, "6"); break;
+ case 7: stuffcmd (client, "7"); break;
+ case 8: stuffcmd (client, "8"); break;
+ case 9: stuffcmd (client, "9"); break;
+ }
+};
+
+//----------------------------------------------------------------------
+void(entity client, float f, float numdigits) stuffcmd_int =
+{
+ local float tmp;
+
+ if (f == 0)
+ {
+ stuffcmd (client, "0");
+ return;
+ }
+
+ if (f < 0)
+ {
+ // Yeah sure.
+ stuffcmd (client, "-");
+ f = fabs (f);
+ }
+
+ if (numdigits <= 0)
+ {
+ tmp = f;
+ numdigits = 1;
+ while (tmp >= 1)
+ {
+ tmp = tmp / 10;
+ numdigits = numdigits * 10;
+ }
+ }
+
+ // I don't know what I'm thinking here...
+ // I need to do this to get zero-padding to work.
+
+ while (numdigits > 1)
+ {
+ numdigits = numdigits / 10;
+ tmp = f / numdigits;
+ stuffcmd_digit (client, tmp);
+ }
+};
+
+//----------------------------------------------------------------------
+void(entity client, float f) stuffcmd_float =
+{
+ local float intpart, decpart, isNegative;
+
+ isNegative = FALSE;
+
+ if (f == 0)
+ {
+ stuffcmd (client, "0");
+ return;
+ }
+
+ if (f < 0)
+ {
+ // easier this way
+ isNegative = TRUE;
+ f = fabs (f);
+ }
+
+ // 1: stuff the integer part.
+ intpart = floor (f);
+ if (isNegative)
+ stuffcmd (client, "-");
+ stuffcmd_int (client, intpart, 0);
+
+ // 2: stuff the decimal point.
+ stuffcmd (client, ".");
+
+ // 3: stuff the decimal part.
+ decpart = mod (f, 1);
+ decpart = decpart * 10000;
+ stuffcmd_int (client, decpart, 10000);
+};
+
+//======================================================================
+
//----------------------------------------------------------------------
// fog_save
//----------------------------------------------------------------------

Return to the top of this page or return to the overview of this repo.

Diff qc/triggers/take_weapon.qc

diff --git a/qc/triggers/take_weapon.qc b/qc/triggers/take_weapon.qc
index 640a235..9f6656b 100644
--- a/qc/triggers/take_weapon.qc
+++ b/qc/triggers/take_weapon.qc
@@ -48,8 +48,8 @@ Removes shotgun upon touch. You can also set "reset_items" in the worldspawn ent

if (other.classtype == CT_PLAYER)
{
- player_set_current_ammo ();
- player_best_weapon ();
+ sub_runfloatas (other, player_best_weapon);
+ sub_runvoidas (other, player_set_current_ammo);
}
};

Return to the top of this page or return to the overview of this repo.

Diff qc/utility.qc

diff --git a/qc/utility.qc b/qc/utility.qc
deleted file mode 100644
index e672c27..0000000
--- a/qc/utility.qc
+++ /dev/null
@@ -1,210 +0,0 @@
-//==============================================================================
-// utility.qc
-//==============================================================================
-
-//======================================================================
-// forward declarations
-//======================================================================
-
-float(float in) bprint_int;
-float(float in) zeroconvert;
-float(float in, float def) zeroconvertdefault;
-
-float(vector v, vector s) bounds_angle_size;
-
-void(entity client, float f) stuffcmd_digit;
-void(entity client, float f, float numdigits) stuffcmd_int;
-void(entity client, float f) stuffcmd_float;
-
-//------------------------------------------------------------------------------
-
-//======================================================================
-// Sourced from utility.qc from smej2
-//======================================================================
-
-//----------------------------------------------------------------------
-float(float in) bprint_int =
-{
- in = floor (in);
- if (in <= 0)
- return 0;
-
- local float digit;
- digit = in - bprint_int (in / 10);
-
- switch (digit)
- {
- case 9: bprint("9"); break;
- case 8: bprint("8"); break;
- case 7: bprint("7"); break;
- case 6: bprint("6"); break;
- case 5: bprint("5"); break;
- case 4: bprint("4"); break;
- case 3: bprint("3"); break;
- case 2: bprint("2"); break;
- case 1: bprint("1"); break;
- case 0: bprint("0"); break;
- }
-
- return in * 10;
-};
-
-//----------------------------------------------------------------------
-// shorthand for turning -1 to 0 for keyvalues for which 0 is a
-// valid non-default selection
-//----------------------------------------------------------------------
-float(float in) zeroconvert =
-{
- if (in == -1)
- return 0;
- return in;
-};
-
-//----------------------------------------------------------------------
-float(float in, float def) zeroconvertdefault =
-{
- if (in == -1)
- return 0;
- if (in == 0)
- return def;
- return in;
-}
-
-//----------------------------------------------------------------------
-// for measuring how large an entity is along an arbitrary vector
-// FIXME: this is trash and it returns trash
-//----------------------------------------------------------------------
-float(vector v, vector s) bounds_angle_size =
-{
- v_x = fabs (v_x);
- v_y = fabs (v_y);
- v_z = fabs (v_z);
-
- // size is always + + + but this is in case I switch the
- // parameters somewhere
- s_x = fabs (s_x);
- s_y = fabs (s_y);
- s_z = fabs (s_z);
-
- return v * s;
-};
-
-//----------------------------------------------------------------------
-// count -4 = numclients in coop
-//----------------------------------------------------------------------
-/*
-void(.float fld) playercount_convert =
-{
- if (self.fld != -4)
- return;
- if (!coop)
- self.fld = 1;
- else
- self.fld = clients;
-};
-*/
-
-//======================================================================
-// wonderful stuffcmd code from Honey by czg
-//======================================================================
-
-//----------------------------------------------------------------------
-// stuffcmd_float
-// This is a horrible hack that I am ashamed of!
-//----------------------------------------------------------------------
-void(entity client, float f) stuffcmd_digit =
-{
- local float d;
- d = floor (f);
- d = mod (d, 10);
-
- // CLOSE YOUR EYES, HONEY! DON'T LOOK!
- switch (d)
- {
- case 0: stuffcmd (client, "0"); break;
- case 1: stuffcmd (client, "1"); break;
- case 2: stuffcmd (client, "2"); break;
- case 3: stuffcmd (client, "3"); break;
- case 4: stuffcmd (client, "4"); break;
- case 5: stuffcmd (client, "5"); break;
- case 6: stuffcmd (client, "6"); break;
- case 7: stuffcmd (client, "7"); break;
- case 8: stuffcmd (client, "8"); break;
- case 9: stuffcmd (client, "9"); break;
- }
-};
-
-//----------------------------------------------------------------------
-void(entity client, float f, float numdigits) stuffcmd_int =
-{
- local float tmp;
-
- if (f == 0)
- {
- stuffcmd (client, "0");
- return;
- }
-
- if (f < 0)
- {
- // Yeah sure.
- stuffcmd (client, "-");
- f = fabs (f);
- }
-
- if (numdigits <= 0)
- {
- tmp = f;
- numdigits = 1;
- while (tmp >= 1)
- {
- tmp = tmp / 10;
- numdigits = numdigits * 10;
- }
- }
-
- // I don't know what I'm thinking here...
- // I need to do this to get zero-padding to work.
-
- while (numdigits > 1)
- {
- numdigits = numdigits / 10;
- tmp = f / numdigits;
- stuffcmd_digit (client, tmp);
- }
-};
-
-//----------------------------------------------------------------------
-void(entity client, float f) stuffcmd_float =
-{
- local float intpart, decpart, isNegative;
-
- isNegative = FALSE;
-
- if (f == 0)
- {
- stuffcmd (client, "0");
- return;
- }
-
- if (f < 0)
- {
- // easier this way
- isNegative = TRUE;
- f = fabs (f);
- }
-
- // 1: stuff the integer part.
- intpart = floor (f);
- if (isNegative)
- stuffcmd (client, "-");
- stuffcmd_int (client, intpart, 0);
-
- // 2: stuff the decimal point.
- stuffcmd (client, ".");
-
- // 3: stuff the decimal part.
- decpart = mod (f, 1);
- decpart = decpart * 10000;
- stuffcmd_int (client, decpart, 10000);
-};

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 b7df6e5..208dddf 100644
--- a/qc/world.qc
+++ b/qc/world.qc
@@ -40,7 +40,6 @@ float world_clrun;
float world_gravity;
float world_maxvelocity;
float world_nostep;
-float world_standardphysics;
float world_walljump;
float world_clforwardspeed;
float world_clsidespeed;
@@ -90,7 +89,6 @@ void() world_latched_cvars =
world_gravity = autocvar (sv_gravity, 800.0);
world_maxvelocity = autocvar (sv_maxvelocity, 10000.0);
world_nostep = autocvar (pm_nostep, FALSE);
- world_standardphysics = autocvar (pm_standardphysics, FALSE);
world_walljump = autocvar (pm_walljump, TRUE);

world_clforwardspeed = autocvar (cl_forwardspeed, PM_RUNSPEED);
@@ -117,6 +115,9 @@ void() world_weapon_precache =
precache_sound ("weapons/bounce.wav"); // grenade bounce
precache_sound ("weapons/shotgn2.wav"); // super shotgun

+ // cev custom weapons precaches START
+ precache_sound ("cev/tribolt/boltexpl.ogg");
+
// dumptruck_ds mobot.qc precaches START
precache_model ("progs/ogre.mdl");
precache_model ("progs/h_ogre.mdl");
@@ -388,7 +389,7 @@ float(entity e, vector offset) world_surface_type =
local string tex = "";
local float surfnum = 0;

- if (world_standardphysics || e.classtype != CT_PLAYER)
+ if (e.classtype != CT_PLAYER)
{
// trace to the ground entity, get the surface
// number we're standing on, then get the texture

Return to the top of this page or return to the overview of this repo.