]> icculus.org git repositories - divverent/nexuiz.git/blob - data/qcsrc/server/cl_physics.qc
renamed and moved all gamec/*.[ch] files to *.q[ch]
[divverent/nexuiz.git] / data / qcsrc / server / cl_physics.qc
1 float sv_accelerate;
2 float sv_friction;
3 float sv_maxspeed;
4 float sv_airaccelerate;
5 float sv_maxairspeed;
6 float sv_stopspeed;
7 float sv_gravity;
8 float sv_airaccel_sideways_friction;
9 float sv_airaccel_qw;
10 .float ladder_time;
11 .entity ladder_entity;
12 .float gravity;
13 .float swamp_slowdown;
14 .float lastflags;
15 .float lastground;
16
17 void Nixnex_GiveCurrentWeapon();
18 void SV_PlayerPhysics()
19 {
20         local vector wishvel, wishdir, v;
21         local float wishspeed, f, maxspd_mod, spd, maxairspd, airaccel, swampspd_mod;
22         string temps;
23
24         if (clienttype(self) == CLIENTTYPE_BOT)
25                 bot_think();
26
27         if (self.movetype == MOVETYPE_NONE)
28                 return;
29
30         if (self.punchangle != '0 0 0')
31         {
32                 f = vlen(self.punchangle) - 10 * frametime;
33                 if (f > 0)
34                         self.punchangle = normalize(self.punchangle) * f;
35                 else
36                         self.punchangle = '0 0 0';
37         }
38
39         if (self.punchvector != '0 0 0')
40         {
41                 f = vlen(self.punchvector) - 30 * frametime;
42                 if (f > 0)
43                         self.punchvector = normalize(self.punchvector) * f;
44                 else
45                         self.punchvector = '0 0 0';
46         }
47
48         maxspd_mod = 1;
49
50         if(cvar("g_runematch"))
51         {
52                 if(self.runes & RUNE_SPEED)
53                 {
54                         if(self.runes & CURSE_SLOW)
55                                 maxspd_mod = maxspd_mod * cvar("g_balance_rune_speed_combo_moverate");
56                         else
57                                 maxspd_mod = maxspd_mod * cvar("g_balance_rune_speed_moverate");
58                 }
59                 else if(self.runes & CURSE_SLOW)
60                 {
61                         maxspd_mod = maxspd_mod * cvar("g_balance_curse_slow_moverate");
62                 }
63         }
64
65         if(cvar("g_minstagib") && (self.items & IT_INVINCIBLE))
66         {
67                 maxspd_mod = cvar("g_balance_rune_speed_moverate");
68         }
69
70         swampspd_mod = 1;
71         if(self.in_swamp) {
72                 swampspd_mod = self.swamp_slowdown; //cvar("g_balance_swamp_moverate");
73         }
74
75
76         spd = sv_maxspeed * maxspd_mod * swampspd_mod;
77
78         if(self.speed != spd)
79         {
80                 self.speed = spd;
81                 temps = ftos(spd);
82                 stuffcmd(self, strcat("cl_forwardspeed ", temps, "\n"));
83                 stuffcmd(self, strcat("cl_backspeed ", temps, "\n"));
84                 stuffcmd(self, strcat("cl_sidespeed ", temps, "\n"));
85                 stuffcmd(self, strcat("cl_upspeed ", temps, "\n"));
86
87                 temps = ftos(sv_accelerate * maxspd_mod);
88                 stuffcmd(self, strcat("cl_movement_accelerate ", temps, "\n"));
89         }
90
91         // if dead, behave differently
92         if (self.deadflag)
93                 return;
94
95         if (!self.fixangle)
96         {
97                 self.angles_x = 0;
98                 self.angles_y = self.v_angle_y;
99                 self.angles_z = 0;
100         }
101
102         if (self.flags & FL_WATERJUMP )
103         {
104                 self.velocity_x = self.movedir_x;
105                 self.velocity_y = self.movedir_y;
106                 if (time > self.teleport_time || self.waterlevel == 0)
107                 {
108                         self.flags = self.flags - (self.flags & FL_WATERJUMP);
109                         self.teleport_time = 0;
110                 }
111         }
112         else if (self.movetype == MOVETYPE_NOCLIP || self.movetype == MOVETYPE_FLY)
113         {
114                 // noclipping or flying
115                 self.flags = self.flags - (self.flags & FL_ONGROUND);
116
117                 self.velocity = self.velocity * (1 - frametime * sv_friction);
118                 makevectors(self.v_angle);
119                 //wishvel = v_forward * self.movement_x + v_right * self.movement_y + v_up * self.movement_z;
120                 wishvel = v_forward * self.movement_x + v_right * self.movement_y + '0 0 1' * self.movement_z;
121                 // acceleration
122                 wishdir = normalize(wishvel);
123                 wishspeed = vlen(wishvel);
124                 if (wishspeed > sv_maxspeed*maxspd_mod)
125                         wishspeed = sv_maxspeed*maxspd_mod;
126                 if (time >= self.teleport_time)
127                 {
128                         f = wishspeed - (self.velocity * wishdir);
129                         if (f > 0)
130                                 self.velocity = self.velocity + wishdir * min(f, sv_accelerate*maxspd_mod * frametime * wishspeed);
131                 }
132         }
133         else if (self.waterlevel >= 2)
134         {
135                 // swimming
136                 self.flags = self.flags - (self.flags & FL_ONGROUND);
137
138                 makevectors(self.v_angle);
139                 //wishvel = v_forward * self.movement_x + v_right * self.movement_y + v_up * self.movement_z;
140                 wishvel = v_forward * self.movement_x + v_right * self.movement_y + '0 0 1' * self.movement_z;
141                 if (wishvel == '0 0 0')
142                         wishvel = '0 0 -60'; // drift towards bottom
143
144                 wishdir = normalize(wishvel);
145                 wishspeed = vlen(wishvel);
146                 if (wishspeed > sv_maxspeed*maxspd_mod)
147                         wishspeed = sv_maxspeed*maxspd_mod;
148                 wishspeed = wishspeed * 0.7;
149
150                 // water friction
151                 self.velocity = self.velocity * (1 - frametime * sv_friction);
152
153                 // water acceleration
154                 f = wishspeed - (self.velocity * wishdir);
155                 if (f > 0)
156                         self.velocity = self.velocity + wishdir * min(f, sv_accelerate*maxspd_mod * frametime * wishspeed);
157         }
158         else if (time < self.ladder_time)
159         {
160                 // on a func_ladder or swimming in func_water
161                 self.flags = self.flags - (self.flags & FL_ONGROUND);
162
163                 self.velocity = self.velocity * (1 - frametime * sv_friction);
164                 makevectors(self.v_angle);
165                 //wishvel = v_forward * self.movement_x + v_right * self.movement_y + v_up * self.movement_z;
166                 wishvel = v_forward * self.movement_x + v_right * self.movement_y + '0 0 1' * self.movement_z;
167                 if (self.gravity)
168                         self.velocity_z = self.velocity_z + self.gravity * sv_gravity * frametime;
169                 else
170                         self.velocity_z = self.velocity_z + sv_gravity * frametime;
171                 if (self.ladder_entity.classname == "func_water")
172                 {
173                         f = vlen(wishvel);
174                         if (f > self.ladder_entity.speed)
175                                 wishvel = wishvel * (self.ladder_entity.speed / f);
176
177                         self.watertype = self.ladder_entity.skin;
178                         f = self.ladder_entity.origin_z + self.ladder_entity.maxs_z;
179                         if ((self.origin_z + self.view_ofs_z) < f)
180                                 self.waterlevel = 3;
181                         else if ((self.origin_z + (self.mins_z + self.maxs_z) * 0.5) < f)
182                                 self.waterlevel = 2;
183                         else if ((self.origin_z + self.mins_z + 1) < f)
184                                 self.waterlevel = 1;
185                         else
186                         {
187                                 self.waterlevel = 0;
188                                 self.watertype = CONTENT_EMPTY;
189                         }
190                 }
191                 // acceleration
192                 wishdir = normalize(wishvel);
193                 wishspeed = vlen(wishvel);
194                 if (wishspeed > sv_maxspeed)
195                         wishspeed = sv_maxspeed;
196                 if (time >= self.teleport_time)
197                 {
198                         f = wishspeed - (self.velocity * wishdir);
199                         if (f > 0)
200                                 self.velocity = self.velocity + wishdir * min(f, sv_accelerate*maxspd_mod * frametime * wishspeed);
201                 }
202         }
203         else if (self.flags & FL_ONGROUND)
204         {
205                 // walking
206                 makevectors(self.v_angle_y * '0 1 0');
207                 wishvel = v_forward * self.movement_x + v_right * self.movement_y;
208
209                 if(!(self.lastflags & FL_ONGROUND))
210                 {
211                         if(cvar("speedmeter"))
212                                 dprint(strcat("landing velocity: ", vtos(self.velocity), " (abs: ", ftos(vlen(self.velocity)), ")\n"));
213                         if(self.lastground < time - 0.3)
214                                 self.velocity = self.velocity * (1 - cvar("sv_friction_on_land"));
215                         if(self.jumppadcount > 1)
216                                 dprint(strcat(ftos(self.jumppadcount), "x jumppad combo\n"));
217                         self.jumppadcount = 0;
218                 }
219
220                 if (self.velocity_x || self.velocity_y)
221                 if (!(self.flags & FL_JUMPRELEASED) || !self.button2)
222                 {
223                         v = self.velocity;
224                         v_z = 0;
225                         f = vlen(v);
226                         if (f < sv_stopspeed)
227                                 f = 1 - frametime * (sv_stopspeed / f) * sv_friction;
228                         else
229                                 f = 1 - frametime * sv_friction;
230                         if (f > 0)
231                                 self.velocity = self.velocity * f;
232                         else
233                                 self.velocity = '0 0 0';
234                 }
235                 // acceleration
236                 wishdir = normalize(wishvel);
237                 wishspeed = vlen(wishvel);
238                 if (wishspeed > sv_maxspeed*maxspd_mod)
239                         wishspeed = sv_maxspeed*maxspd_mod;
240                 if (self.crouch)
241                         wishspeed = wishspeed * 0.5;
242                 if (time >= self.teleport_time)
243                 {
244                         f = wishspeed - (self.velocity * wishdir);
245                         if (f > 0)
246                                 self.velocity = self.velocity + wishdir * min(f, sv_accelerate*maxspd_mod * frametime * wishspeed);
247                 }
248         }
249         else
250         {
251                 if(maxspd_mod < 1)
252                 {
253                         maxairspd = sv_maxairspeed*maxspd_mod;
254                         airaccel = sv_airaccelerate*maxspd_mod;
255                 }
256                 else
257                 {
258                         maxairspd = sv_maxairspeed;
259                         airaccel = sv_airaccelerate;
260                 }
261                 // airborn
262                 makevectors(self.v_angle_y * '0 1 0');
263                 wishvel = v_forward * self.movement_x + v_right * self.movement_y;
264                 // acceleration
265                 wishdir = normalize(wishvel);
266                 wishspeed = vlen(wishvel);
267                 if (wishspeed > maxairspd)
268                         wishspeed = maxairspd;
269                 if (self.crouch)
270                         wishspeed = wishspeed * 0.5;
271                 if (time >= self.teleport_time)
272                 {
273                         // NOTE: this does the same as the commented out old code if:
274                         //   sv_airaccel_qw 0
275                         //   sv_airaccel_sideways_friction 0
276                         
277                         float vel_straight;
278                         float vel_z;
279                         vector vel_perpend;
280                         vel_straight = self.velocity * wishdir;
281                         vel_z = self.velocity_z;
282                         vel_perpend = self.velocity - vel_straight * wishdir - vel_z * '0 0 1';
283
284                         f = wishspeed - vel_straight;
285                         if(f > 0)
286                                 vel_straight = vel_straight + min(f, airaccel * frametime * wishspeed) * sv_airaccel_qw;
287                         if(wishspeed > 0)
288                                 vel_straight = vel_straight + min(wishspeed, airaccel * frametime * wishspeed) * (1 - sv_airaccel_qw);
289
290                         // anti-sideways friction to fix QW-style bunnyhopping
291                         vel_perpend = vel_perpend * (1 - frametime * (wishspeed / maxairspd) * sv_airaccel_sideways_friction);
292
293                         self.velocity = vel_straight * wishdir + vel_z * '0 0 1' + vel_perpend;
294
295                         /*
296                         f = wishspeed;// - (self.velocity * wishdir);
297                         if (f > 0)
298                                 self.velocity = self.velocity + wishdir * min(f, airaccel * frametime * wishspeed);
299                         */
300                 }
301         }
302
303         if(self.flags & FL_ONGROUND)
304                 self.lastground = time;
305
306         self.lastflags = self.flags;
307 };