centerprints now are managed independently per line
[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         if(self.flags & FL_NOTARGET)
76                 spd = sv_maxspeed * cvar("sv_spectator_speed_multiplier");
77         else
78                 spd = sv_maxspeed * maxspd_mod * swampspd_mod;
79
80         if(self.speed != spd)
81         {
82                 self.speed = spd;
83                 temps = ftos(spd);
84                 stuffcmd(self, strcat("cl_forwardspeed ", temps, "\n"));
85                 stuffcmd(self, strcat("cl_backspeed ", temps, "\n"));
86                 stuffcmd(self, strcat("cl_sidespeed ", temps, "\n"));
87                 stuffcmd(self, strcat("cl_upspeed ", temps, "\n"));
88
89                 temps = ftos(sv_accelerate * maxspd_mod);
90                 stuffcmd(self, strcat("cl_movement_accelerate ", temps, "\n"));
91         }
92
93         // if dead, behave differently
94         if (self.deadflag)
95                 return;
96
97         if (!self.fixangle)
98         {
99                 self.angles_x = 0;
100                 self.angles_y = self.v_angle_y;
101                 self.angles_z = 0;
102         }
103
104         if (self.flags & FL_WATERJUMP )
105         {
106                 self.velocity_x = self.movedir_x;
107                 self.velocity_y = self.movedir_y;
108                 if (time > self.teleport_time || self.waterlevel == 0)
109                 {
110                         self.flags = self.flags - (self.flags & FL_WATERJUMP);
111                         self.teleport_time = 0;
112                 }
113         }
114         else if (self.movetype == MOVETYPE_NOCLIP || self.movetype == MOVETYPE_FLY)
115         {
116                 // noclipping or flying
117                 self.flags = self.flags - (self.flags & FL_ONGROUND);
118
119                 self.velocity = self.velocity * (1 - frametime * sv_friction);
120                 makevectors(self.v_angle);
121                 //wishvel = v_forward * self.movement_x + v_right * self.movement_y + v_up * self.movement_z;
122                 wishvel = v_forward * self.movement_x + v_right * self.movement_y + '0 0 1' * self.movement_z;
123                 // acceleration
124                 wishdir = normalize(wishvel);
125                 wishspeed = vlen(wishvel);
126                 if (wishspeed > sv_maxspeed*maxspd_mod)
127                         wishspeed = sv_maxspeed*maxspd_mod;
128                 if (time >= self.teleport_time)
129                 {
130                         f = wishspeed - (self.velocity * wishdir);
131                         if (f > 0)
132                                 self.velocity = self.velocity + wishdir * min(f, sv_accelerate*maxspd_mod * frametime * wishspeed);
133                 }
134         }
135         else if (self.waterlevel >= 2)
136         {
137                 // swimming
138                 self.flags = self.flags - (self.flags & FL_ONGROUND);
139
140                 makevectors(self.v_angle);
141                 //wishvel = v_forward * self.movement_x + v_right * self.movement_y + v_up * self.movement_z;
142                 wishvel = v_forward * self.movement_x + v_right * self.movement_y + '0 0 1' * self.movement_z;
143                 if (wishvel == '0 0 0')
144                         wishvel = '0 0 -60'; // drift towards bottom
145
146                 wishdir = normalize(wishvel);
147                 wishspeed = vlen(wishvel);
148                 if (wishspeed > sv_maxspeed*maxspd_mod)
149                         wishspeed = sv_maxspeed*maxspd_mod;
150                 wishspeed = wishspeed * 0.7;
151
152                 // water friction
153                 self.velocity = self.velocity * (1 - frametime * sv_friction);
154
155                 // water acceleration
156                 f = wishspeed - (self.velocity * wishdir);
157                 if (f > 0)
158                         self.velocity = self.velocity + wishdir * min(f, sv_accelerate*maxspd_mod * frametime * wishspeed);
159         }
160         else if (time < self.ladder_time)
161         {
162                 // on a func_ladder or swimming in func_water
163                 self.flags = self.flags - (self.flags & FL_ONGROUND);
164
165                 self.velocity = self.velocity * (1 - frametime * sv_friction);
166                 makevectors(self.v_angle);
167                 //wishvel = v_forward * self.movement_x + v_right * self.movement_y + v_up * self.movement_z;
168                 wishvel = v_forward * self.movement_x + v_right * self.movement_y + '0 0 1' * self.movement_z;
169                 if (self.gravity)
170                         self.velocity_z = self.velocity_z + self.gravity * sv_gravity * frametime;
171                 else
172                         self.velocity_z = self.velocity_z + sv_gravity * frametime;
173                 if (self.ladder_entity.classname == "func_water")
174                 {
175                         f = vlen(wishvel);
176                         if (f > self.ladder_entity.speed)
177                                 wishvel = wishvel * (self.ladder_entity.speed / f);
178
179                         self.watertype = self.ladder_entity.skin;
180                         f = self.ladder_entity.origin_z + self.ladder_entity.maxs_z;
181                         if ((self.origin_z + self.view_ofs_z) < f)
182                                 self.waterlevel = 3;
183                         else if ((self.origin_z + (self.mins_z + self.maxs_z) * 0.5) < f)
184                                 self.waterlevel = 2;
185                         else if ((self.origin_z + self.mins_z + 1) < f)
186                                 self.waterlevel = 1;
187                         else
188                         {
189                                 self.waterlevel = 0;
190                                 self.watertype = CONTENT_EMPTY;
191                         }
192                 }
193                 // acceleration
194                 wishdir = normalize(wishvel);
195                 wishspeed = vlen(wishvel);
196                 if (wishspeed > sv_maxspeed)
197                         wishspeed = sv_maxspeed;
198                 if (time >= self.teleport_time)
199                 {
200                         f = wishspeed - (self.velocity * wishdir);
201                         if (f > 0)
202                                 self.velocity = self.velocity + wishdir * min(f, sv_accelerate*maxspd_mod * frametime * wishspeed);
203                 }
204         }
205         else if (self.flags & FL_ONGROUND)
206         {
207                 // walking
208                 makevectors(self.v_angle_y * '0 1 0');
209                 wishvel = v_forward * self.movement_x + v_right * self.movement_y;
210
211                 if(!(self.lastflags & FL_ONGROUND))
212                 {
213                         if(cvar("speedmeter"))
214                                 dprint(strcat("landing velocity: ", vtos(self.velocity), " (abs: ", ftos(vlen(self.velocity)), ")\n"));
215                         if(self.lastground < time - 0.3)
216                                 self.velocity = self.velocity * (1 - cvar("sv_friction_on_land"));
217                         if(self.jumppadcount > 1)
218                                 dprint(strcat(ftos(self.jumppadcount), "x jumppad combo\n"));
219                         self.jumppadcount = 0;
220                 }
221
222                 if (self.velocity_x || self.velocity_y)
223                 if (!(self.flags & FL_JUMPRELEASED) || !self.button2)
224                 {
225                         v = self.velocity;
226                         v_z = 0;
227                         f = vlen(v);
228                         if (f < sv_stopspeed)
229                                 f = 1 - frametime * (sv_stopspeed / f) * sv_friction;
230                         else
231                                 f = 1 - frametime * sv_friction;
232                         if (f > 0)
233                                 self.velocity = self.velocity * f;
234                         else
235                                 self.velocity = '0 0 0';
236                 }
237                 // acceleration
238                 wishdir = normalize(wishvel);
239                 wishspeed = vlen(wishvel);
240                 if (wishspeed > sv_maxspeed*maxspd_mod)
241                         wishspeed = sv_maxspeed*maxspd_mod;
242                 if (self.crouch)
243                         wishspeed = wishspeed * 0.5;
244                 if (time >= self.teleport_time)
245                 {
246                         f = wishspeed - (self.velocity * wishdir);
247                         if (f > 0)
248                                 self.velocity = self.velocity + wishdir * min(f, sv_accelerate*maxspd_mod * frametime * wishspeed);
249                 }
250         }
251         else
252         {
253                 if(maxspd_mod < 1)
254                 {
255                         maxairspd = sv_maxairspeed*maxspd_mod;
256                         airaccel = sv_airaccelerate*maxspd_mod;
257                 }
258                 else
259                 {
260                         maxairspd = sv_maxairspeed;
261                         airaccel = sv_airaccelerate;
262                 }
263                 // airborn
264                 makevectors(self.v_angle_y * '0 1 0');
265                 wishvel = v_forward * self.movement_x + v_right * self.movement_y;
266                 // acceleration
267                 wishdir = normalize(wishvel);
268                 wishspeed = vlen(wishvel);
269                 if (wishspeed > maxairspd)
270                         wishspeed = maxairspd;
271                 if (self.crouch)
272                         wishspeed = wishspeed * 0.5;
273                 if (time >= self.teleport_time)
274                 {
275                         // NOTE: this does the same as the commented out old code if:
276                         //   sv_airaccel_qw 0
277                         //   sv_airaccel_sideways_friction 0
278                         
279                         float vel_straight;
280                         float vel_z;
281                         vector vel_perpend;
282                         vel_straight = self.velocity * wishdir;
283                         vel_z = self.velocity_z;
284                         vel_perpend = self.velocity - vel_straight * wishdir - vel_z * '0 0 1';
285
286                         f = wishspeed - vel_straight;
287                         if(f > 0)
288                                 vel_straight = vel_straight + min(f, airaccel * frametime * wishspeed) * sv_airaccel_qw;
289                         if(wishspeed > 0)
290                                 vel_straight = vel_straight + min(wishspeed, airaccel * frametime * wishspeed) * (1 - sv_airaccel_qw);
291
292                         // anti-sideways friction to fix QW-style bunnyhopping
293                         vel_perpend = vel_perpend * (1 - frametime * (wishspeed / maxairspd) * sv_airaccel_sideways_friction);
294
295                         self.velocity = vel_straight * wishdir + vel_z * '0 0 1' + vel_perpend;
296
297                         /*
298                         f = wishspeed;// - (self.velocity * wishdir);
299                         if (f > 0)
300                                 self.velocity = self.velocity + wishdir * min(f, airaccel * frametime * wishspeed);
301                         */
302                 }
303         }
304
305         if(self.flags & FL_ONGROUND)
306                 self.lastground = time;
307
308         self.lastflags = self.flags;
309 };