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