1 float lastclientthink, sv_maxspeed, sv_friction, sv_accelerate, sv_stopspeed;
2 float sv_edgefriction, cl_rollspeed, cl_divspeed, cl_rollangle;
7 // Highly optimized port of SV_ClientThink from engine code to QuakeC.
8 // No behavior changes! This code is much shorter and probably faster than
11 // note that darkplaces engine will call this function if it finds it,
12 // so modify for your own mods and enjoy...
14 // note also, this code uses some builtin functions from dpextensions.qc
15 // (included with darkplaces engine releases)
17 void SV_PlayerPhysics() {
18 local vector wishvel, wishdir, v;
19 local float wishspeed, f;
21 if (self.movetype == MOVETYPE_NONE)
24 if (self.punchangle != '0 0 0')
26 f = vlen(self.punchangle) - 10 * frametime;
28 self.punchangle = normalize(self.punchangle) * f;
30 self.punchangle = '0 0 0';
33 // if dead, behave differently
37 if (time != lastclientthink)
39 lastclientthink = time;
40 sv_maxspeed = cvar("sv_maxspeed");
42 sv_friction = cvar("sv_friction");
43 sv_accelerate = cvar("sv_accelerate");
44 sv_stopspeed = cvar("sv_stopspeed");
45 sv_edgefriction = cvar("edgefriction");
46 // LordHavoc: this * 4 is an optimization
47 cl_rollangle = cvar("cl_rollangle") * 4;
48 // LordHavoc: this 1 / is an optimization
49 cl_divspeed = 1 / cvar("cl_rollspeed");
52 // show 1/3 the pitch angle and all the roll angle
53 self.angles_z = bound(-1, self.velocity * v_right * cl_divspeed, 1) * cl_rollangle;
54 /* if (!self.fixangle)
56 self.angles_x = (self.v_angle_x + self.punchangle_x) * -0.333;
57 self.angles_y = self.v_angle_y + self.punchangle_y;
60 if (self.crouch) self.movement = self.movement * 0.5; /* Quick try by diGGer */
62 if (self.flags & FL_WATERJUMP )
64 self.velocity_x = self.movedir_x;
65 self.velocity_y = self.movedir_y;
66 if (time > self.teleport_time || self.waterlevel == 0)
68 self.flags = self.flags - (self.flags & FL_WATERJUMP);
69 self.teleport_time = 0;
74 makevectors(self.v_angle);
77 if (self.waterlevel >= 2)
78 if (self.movetype != MOVETYPE_NOCLIP)
80 if (self.movement == '0 0 0')
81 wishvel = '0 0 -30'; // drift towards bottom
83 wishvel = v_forward * self.movement_x + v_right * self.movement_y + '0 0 1' * self.movement_z;
85 wishspeed = vlen(wishvel);
86 if (wishspeed > sv_maxspeed)
87 wishspeed = sv_maxspeed * 1.4;
89 wishspeed = wishspeed * 1.4;
92 if (self.velocity != '0 0 0')
94 f = vlen(self.velocity) * (1 - frametime * sv_friction);
96 self.velocity = normalize(self.velocity) * f;
98 self.velocity = '0 0 0';
103 // water acceleration
107 f = min(wishspeed - f, sv_accelerate * wishspeed * frametime);
108 self.velocity = self.velocity + normalize(wishvel) * f;
112 // hack to not let you back into teleporter
113 if (time < self.teleport_time && self.movement_x < 0)
114 wishvel = v_right * self.movement_y;
116 wishvel = v_forward * self.movement_x + v_right * self.movement_y;
118 if (self.movetype != MOVETYPE_WALK)
119 wishvel_z = self.movement_z;
123 wishdir = normalize(wishvel);
124 wishspeed = vlen(wishvel);
125 if (wishspeed > sv_maxspeed)
126 wishspeed = sv_maxspeed;
127 if (self.flags & FL_ONGROUND) {
128 wishspeed=wishspeed+wishspeed*(1);
131 else if (time < self.ladder_time)
133 // on a func_ladder or swimming in func_water
134 self.velocity = self.velocity * (1 - frametime * sv_friction);
135 makevectors(self.v_angle);
136 //wishvel = v_forward * self.movement_x + v_right * self.movement_y + v_up * self.movement_z;
137 wishvel = v_forward * self.movement_x + v_right * self.movement_y + '0 0 1' * self.movement_z;
139 self.velocity_z = self.velocity_z + self.gravity * sv_gravity * frametime;
141 self.velocity_z = self.velocity_z + sv_gravity * frametime;
142 if (self.ladder_entity.classname == "func_water")
145 if (f > self.ladder_entity.speed)
146 wishvel = wishvel * (self.ladder_entity.speed / f);
148 self.watertype = self.ladder_entity.skin;
149 f = self.ladder_entity.origin_z + self.ladder_entity.maxs_z;
150 if ((self.origin_z + self.view_ofs_z) < f)
152 else if ((self.origin_z + (self.mins_z + self.maxs_z) * 0.5) < f)
154 else if ((self.origin_z + self.mins_z + 1) < f)
159 self.watertype = CONTENT_EMPTY;
163 if (self.movetype == MOVETYPE_NOCLIP) // noclip
164 self.velocity = wishdir * wishspeed;
165 else if (self.flags & FL_ONGROUND) // walking
168 if (self.velocity_x || self.velocity_y)
174 // if the leading edge is over a dropoff, increase friction
175 v = self.origin + normalize(v) * 16 + '0 0 1' * self.mins_z;
177 traceline(v, v + '0 0 -34', TRUE, self);
180 if (trace_fraction == 1.0)
182 if (f < sv_stopspeed)
183 f = 1 - frametime * (sv_stopspeed / f) * sv_friction * sv_edgefriction;
185 f = 1 - frametime * sv_friction * sv_edgefriction;
189 if (f < sv_stopspeed)
190 f = 1 - frametime * (sv_stopspeed / f) * sv_friction;
192 f = 1 - frametime * sv_friction;
196 self.velocity = '0 0 0';
198 self.velocity = self.velocity * f;
203 f = wishspeed - (self.velocity * wishdir);
205 self.velocity = self.velocity + wishdir * min(f, sv_accelerate * frametime * wishspeed);
207 else if (!(game & GAME_NO_AIR_CONTROL))
210 f = wishspeed - (self.velocity * wishdir);
212 f = 80 - (self.velocity * wishdir);
214 self.velocity = self.velocity + wishdir * (min(f, sv_accelerate) * wishspeed * frametime);