1 float lastclientthink, sv_maxspeed, sv_friction, sv_accelerate, sv_stopspeed;
2 float sv_edgefriction, cl_rollspeed, cl_divspeed, cl_rollangle;
5 // Highly optimized port of SV_ClientThink from engine code to QuakeC.
6 // No behavior changes! This code is much shorter and probably faster than
9 // note that darkplaces engine will call this function if it finds it,
10 // so modify for your own mods and enjoy...
12 // note also, this code uses some builtin functions from dpextensions.qc
13 // (included with darkplaces engine releases)
15 void SV_PlayerPhysics() {
16 local vector wishvel, wishdir, v;
17 local float wishspeed, f;
19 if (self.movetype == MOVETYPE_NONE)
22 if (self.punchangle != '0 0 0')
24 f = vlen(self.punchangle) - 10 * frametime;
26 self.punchangle = normalize(self.punchangle) * f;
28 self.punchangle = '0 0 0';
31 // if dead, behave differently
35 if (time != lastclientthink)
37 lastclientthink = time;
38 sv_maxspeed = cvar("sv_maxspeed");
40 sv_friction = cvar("sv_friction");
41 sv_accelerate = cvar("sv_accelerate");
42 sv_stopspeed = cvar("sv_stopspeed");
43 sv_edgefriction = cvar("edgefriction");
44 // LordHavoc: this * 4 is an optimization
45 cl_rollangle = cvar("cl_rollangle") * 4;
46 // LordHavoc: this 1 / is an optimization
47 cl_divspeed = 1 / cvar("cl_rollspeed");
50 // show 1/3 the pitch angle and all the roll angle
51 self.angles_z = bound(-1, self.velocity * v_right * cl_divspeed, 1) * cl_rollangle;
54 self.angles_x = (self.v_angle_x + self.punchangle_x) * -0.333;
55 self.angles_y = self.v_angle_y + self.punchangle_y;
58 if (self.flags & FL_WATERJUMP )
60 self.velocity_x = self.movedir_x;
61 self.velocity_y = self.movedir_y;
62 if (time > self.teleport_time || self.waterlevel == 0)
64 self.flags = self.flags - (self.flags & FL_WATERJUMP);
65 self.teleport_time = 0;
70 makevectors(self.v_angle);
73 if (self.waterlevel >= 2)
74 if (self.movetype != MOVETYPE_NOCLIP)
76 if (self.movement == '0 0 0')
77 wishvel = '0 0 -60'; // drift towards bottom
79 wishvel = v_forward * self.movement_x + v_right * self.movement_y + '0 0 1' * self.movement_z;
81 wishspeed = vlen(wishvel);
82 if (wishspeed > sv_maxspeed)
83 wishspeed = sv_maxspeed * 0.7;
85 wishspeed = wishspeed * 0.7;
88 if (self.velocity != '0 0 0')
90 f = vlen(self.velocity) * (1 - frametime * sv_friction);
92 self.velocity = normalize(self.velocity) * f;
94 self.velocity = '0 0 0';
103 f = min(wishspeed - f, sv_accelerate * wishspeed * frametime);
104 self.velocity = self.velocity + normalize(wishvel) * f;
108 // hack to not let you back into teleporter
109 if (time < self.teleport_time && self.movement_x < 0)
110 wishvel = v_right * self.movement_y;
112 wishvel = v_forward * self.movement_x + v_right * self.movement_y;
114 if (self.movetype != MOVETYPE_WALK)
115 wishvel_z = self.movement_z;
119 wishdir = normalize(wishvel);
120 wishspeed = vlen(wishvel);
121 if (wishspeed > sv_maxspeed)
122 wishspeed = sv_maxspeed;
123 if (self.flags & FL_ONGROUND) {
124 wishspeed=wishspeed+wishspeed*(1);
127 if (self.movetype == MOVETYPE_NOCLIP) // noclip
128 self.velocity = wishdir * wishspeed;
129 else if (self.flags & FL_ONGROUND) // walking
132 if (self.velocity_x || self.velocity_y)
138 // if the leading edge is over a dropoff, increase friction
139 v = self.origin + normalize(v) * 16 + '0 0 1' * self.mins_z;
141 traceline(v, v + '0 0 -34', TRUE, self);
144 if (trace_fraction == 1.0)
146 if (f < sv_stopspeed)
147 f = 1 - frametime * (sv_stopspeed / f) * sv_friction * sv_edgefriction;
149 f = 1 - frametime * sv_friction * sv_edgefriction;
153 if (f < sv_stopspeed)
154 f = 1 - frametime * (sv_stopspeed / f) * sv_friction;
156 f = 1 - frametime * sv_friction;
160 self.velocity = '0 0 0';
162 self.velocity = self.velocity * f;
166 f = wishspeed - (self.velocity * wishdir);
168 self.velocity = self.velocity + wishdir * min(f, sv_accelerate * frametime * wishspeed);
173 f = wishspeed - (self.velocity * wishdir);
175 f = 30 - (self.velocity * wishdir);
177 self.velocity = self.velocity + wishdir * (min(f, sv_accelerate) * wishspeed * frametime);