]> icculus.org git repositories - divverent/nexuiz.git/blob - qcsrc/sv_user.nc
*** empty log message ***
[divverent/nexuiz.git] / qcsrc / sv_user.nc
1 float lastclientthink, sv_maxspeed, sv_friction, sv_accelerate, sv_stopspeed;
2 float sv_edgefriction, cl_rollspeed, cl_divspeed, cl_rollangle;
3
4 // LordHavoc:
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
7 // the engine code :)
8
9 // note that darkplaces engine will call this function if it finds it,
10 // so modify for your own mods and enjoy...
11
12 // note also, this code uses some builtin functions from dpextensions.qc
13 // (included with darkplaces engine releases)
14
15 void SV_PlayerPhysics() {
16         local vector wishvel, wishdir, v;
17         local float wishspeed, f;
18
19         if (self.movetype == MOVETYPE_NONE)
20                 return;
21
22         if (self.punchangle != '0 0 0')
23         {
24                 f = vlen(self.punchangle) - 10 * frametime;
25                 if (f > 0)
26                         self.punchangle = normalize(self.punchangle) * f;
27                 else
28                         self.punchangle = '0 0 0';
29         }
30
31         // if dead, behave differently
32         if (self.health <= 0)
33                 return;
34
35         if (time != lastclientthink)
36         {
37                 lastclientthink = time;
38                 sv_maxspeed = cvar("sv_maxspeed");
39                 sv_friction = cvar("sv_friction");
40                 sv_accelerate = cvar("sv_accelerate");
41                 sv_stopspeed = cvar("sv_stopspeed");
42                 sv_edgefriction = cvar("edgefriction");
43                 // LordHavoc: this * 4 is an optimization
44                 cl_rollangle = cvar("cl_rollangle") * 4;
45                 // LordHavoc: this 1 / is an optimization
46                 cl_divspeed = 1 / cvar("cl_rollspeed");
47         }
48
49         // show 1/3 the pitch angle and all the roll angle
50         self.angles_z = bound(-1, self.velocity * v_right * cl_divspeed, 1) * cl_rollangle;
51         if (!self.fixangle)
52         {
53                 self.angles_x = (self.v_angle_x + self.punchangle_x) * -0.333;
54                 self.angles_y = self.v_angle_y + self.punchangle_y;
55         }
56
57         if (self.flags & FL_WATERJUMP )
58         {
59                 self.velocity_x = self.movedir_x;
60                 self.velocity_y = self.movedir_y;
61                 if (time > self.teleport_time || self.waterlevel == 0)
62                 {
63                         self.flags = self.flags - (self.flags & FL_WATERJUMP);
64                         self.teleport_time = 0;
65                 }
66                 return;
67         }
68
69         makevectors(self.v_angle);
70
71         // swim
72         if (self.waterlevel >= 2)
73         if (self.movetype != MOVETYPE_NOCLIP)
74         {
75                 if (self.movement == '0 0 0')
76                         wishvel = '0 0 -60'; // drift towards bottom
77                 else
78                         wishvel = v_forward * self.movement_x + v_right * self.movement_y + v_up * self.movement_z;
79
80                 wishspeed = vlen(wishvel);
81                 if (wishspeed > sv_maxspeed)
82                         wishspeed = sv_maxspeed * 0.7;
83                 else
84                         wishspeed = wishspeed * 0.7;
85
86                 // water friction
87                 if (self.velocity != '0 0 0')
88                 {
89                         f = vlen(self.velocity) * (1 - frametime * sv_friction);
90                         if (f > 0)
91                                 self.velocity = normalize(self.velocity) * f;
92                         else
93                                 self.velocity = '0 0 0';
94                 }
95                 else
96                         f = 0;
97
98                 // water acceleration
99                 if (wishspeed <= f)
100                         return;
101
102                 f = min(wishspeed - f, sv_accelerate * wishspeed * frametime);
103                 self.velocity = self.velocity + normalize(wishvel) * f;
104                 return;
105         }
106
107         // hack to not let you back into teleporter
108         if (time < self.teleport_time && self.movement_x < 0)
109                 wishvel = v_right * self.movement_y;
110         else
111                 wishvel = v_forward * self.movement_x + v_right * self.movement_y;
112
113         if (self.movetype != MOVETYPE_WALK)
114                 wishvel_z = self.movement_z;
115         else
116                 wishvel_z = 0;
117
118         wishdir = normalize(wishvel);
119         wishspeed = vlen(wishvel);
120         if (wishspeed > sv_maxspeed)
121                 wishspeed = sv_maxspeed;
122         if (self.flags & FL_ONGROUND) {
123                 wishspeed=wishspeed+wishspeed*(1);
124         }
125
126         if (self.movetype == MOVETYPE_NOCLIP) // noclip
127                 self.velocity = wishdir * wishspeed;
128         else if (self.flags & FL_ONGROUND) // walking
129         {
130                 // friction
131                 if (self.velocity_x || self.velocity_y)
132                 {
133                         v = self.velocity;
134                         v_z = 0;
135                         f = vlen(v);
136
137                         // if the leading edge is over a dropoff, increase friction
138                         v = self.origin + normalize(v) * 16 + '0 0 1' * self.mins_z;
139
140                         traceline(v, v + '0 0 -34', TRUE, self);
141
142                         // apply friction
143                         if (trace_fraction == 1.0)
144                         {
145                                 if (f < sv_stopspeed)
146                                         f = 1 - frametime * (sv_stopspeed / f) * sv_friction * sv_edgefriction;
147                                 else
148                                         f = 1 - frametime * sv_friction * sv_edgefriction;
149                         }
150                         else
151                         {
152                                 if (f < sv_stopspeed)
153                                         f = 1 - frametime * (sv_stopspeed / f) * sv_friction;
154                                 else
155                                         f = 1 - frametime * sv_friction;
156                         }
157
158                         if (f < 0)
159                                 self.velocity = '0 0 0';
160                         else
161                                 self.velocity = self.velocity * f;
162                 }
163
164                 // acceleration
165                 f = wishspeed - (self.velocity * wishdir);
166                 if (f > 0)
167                         self.velocity = self.velocity + wishdir * min(f, sv_accelerate * frametime * wishspeed);
168         }
169         else // airborne
170         {
171                 if (wishspeed < 30)
172                         f = wishspeed - (self.velocity * wishdir);
173                 else
174                         f = 30 - (self.velocity * wishdir);
175                 if (f > 0)
176                         self.velocity = self.velocity + wishdir * (min(f, sv_accelerate) * wishspeed * frametime);
177         }
178 }