]> icculus.org git repositories - divverent/nexuiz.git/blob - data/qcsrc/server/cl_impulse.qc
document weapon impulse order; load weapon priority from client
[divverent/nexuiz.git] / data / qcsrc / server / cl_impulse.qc
1 .vector personal_v_angle; // view angles to restore on impulse 77
2 .vector personal_velocity; // velocity to restore on impulse 77
3
4 void CopyBody(float keepvelocity);
5
6 // changes by LordHavoc on 03/30/04
7 // cleaned up dummy code
8 // dummies are now removed eventually after being gibbed (norespawn = TRUE)
9 // dummy impulse now checks sv_cheats to prevent players from overwhelming server with dummies
10 // dummies now use player code where possible
11
12 void player_anim (void);
13 void DummyThink(void)
14 {
15         self.think = DummyThink;
16         self.nextthink = time;
17         SV_PlayerPhysics();
18         PlayerPreThink();
19         //player_anim();
20         PlayerPostThink();
21 }
22
23 // from dpmod
24 void printsurfaceinfo(entity e, vector v)
25 {
26         local float surfnum, numpoints, vnum;
27         local string s;
28         local vector n;
29         surfnum = getsurfacenearpoint(e, v);
30         if (surfnum >= 0)
31         {
32                 sprint(self, "texture: ");
33                 s = getsurfacetexture(e, surfnum);
34                 sprint(self, s);
35                 sprint(self, " normal: ");
36                 n = getsurfacenormal(e, surfnum);
37                 sprint(self, vtos(n));
38                 sprint(self, " ");
39                 numpoints = getsurfacenumpoints(e, surfnum);
40                 sprint(self, ftos(numpoints));
41                 sprint(self, " verts:");
42                 vnum = 0;
43                 while (vnum < numpoints)
44                 {
45                         sprint(self, " ");
46                         n = getsurfacepoint(e, surfnum, vnum);
47                         sprint(self, vtos(n));
48                         vnum = vnum + 1;
49                 }
50                 sprint(self, " point tested: ");
51                 sprint(self, vtos(v));
52                 sprint(self, " nearest point on surface: ");
53                 n = getsurfaceclippedpoint(e, surfnum, v);
54                 sprint(self, vtos(n));
55                 sprint(self, "\n");
56         }
57 };
58
59 /*
60  * Impulse map:
61  *
62  * 0 reserved (no input)
63  * 1 to 9: weapon shortcuts
64  * 10: next weapon
65  * 11: most recently used weapon
66  * 12: previous weapon
67  * 13: moving clone
68  * 14: fixed clone
69  * 17: throw weapon
70  * 19: printsurfaceinfo
71  * 20: distance
72  * 30 to 39: create waypoints
73  * 47: clear personal waypoints
74  * 48: clear team waypoints
75  * 49: turn base waypoints on/off
76  * 77: ctf speedrun
77  * 99: loaded
78  * 143: emergency teleport
79  *
80  * TODO:
81  * 200 to 219: individual weapons
82  * 220 to 229: next weapon shortcuts
83  * 230 to 239: prev weapon shortcuts
84  * 240 to 249: best weapon shortcuts
85  */
86
87 void ImpulseCommands (void)
88 {
89         local float imp;
90         imp = self.impulse;
91         if (!imp || gameover)
92                 return;
93         self.impulse = 0;
94
95         if (timeoutStatus == 2) //don't allow any impulses while the game is paused
96                 return;
97
98         if (imp >= 1 && imp <= 12)
99         {
100                 // weapon switching impulses
101                 if(self.deadflag == DEAD_NO)
102                 {
103                         if (imp <= 9)
104                                 W_SwitchWeapon (imp);
105                         else if (imp == 10)
106                                 W_NextWeapon ();
107                         else if (imp == 12)
108                                 W_PreviousWeapon ();
109                         else if (imp == 11) // last weapon
110                                 W_SwitchWeapon (self.cnt);
111                 }
112                 else
113                         self.impulse = imp; // retry in next frame
114         }
115         // throw weapon
116         else if (imp == 17)
117         {
118                 if(self.deadflag == DEAD_NO)
119                 if (!g_minstagib)
120                         W_ThrowWeapon(W_CalculateProjectileVelocity(self.velocity, v_forward * 750), '0 0 0', TRUE);
121         }
122         // deploy waypoints
123         else if (imp >= 30 && imp <= 49)
124         {
125                 if(imp == 30)
126                 {
127                         WaypointSprite_DeployPersonal("waypoint", self.origin);
128                         self.personal_v_angle = self.v_angle;
129                         self.personal_velocity = self.velocity;
130                         sprint(self, "personal waypoint spawned at location\n");
131                 }
132                 else if(imp == 31)
133                 {
134                         WaypointSprite_DeployPersonal("waypoint", self.cursor_trace_endpos);
135                         self.personal_v_angle = self.v_angle;
136                         self.personal_velocity = '0 0 0';
137                         sprint(self, "personal waypoint spawned at crosshair\n");
138                 }
139                 else if(imp == 32 && vlen(self.death_origin))
140                 {
141                         WaypointSprite_DeployPersonal("waypoint", self.death_origin);
142                         self.personal_v_angle = self.v_angle;
143                         self.personal_velocity = '0 0 0';
144                         sprint(self, "personal waypoint spawned at death location\n");
145                 }
146                 else if(imp == 33 && self.deadflag == DEAD_NO && teams_matter)
147                 {
148                         WaypointSprite_Attach("helpme", TRUE);
149                         sprint(self, "HELP ME attached\n");
150                 }
151                 else if(imp == 34)
152                 {
153                         WaypointSprite_DeployFixed("here", FALSE, self.origin);
154                         sprint(self, "HERE spawned at location\n");
155                 }
156                 else if(imp == 35)
157                 {
158                         WaypointSprite_DeployFixed("here", FALSE, self.cursor_trace_endpos);
159                         sprint(self, "HERE spawned at crosshair\n");
160                 }
161                 else if(imp == 36 && vlen(self.death_origin))
162                 {
163                         WaypointSprite_DeployFixed("here", FALSE, self.death_origin);
164                         sprint(self, "HERE spawned at death location\n");
165                 }
166                 else if(imp == 37)
167                 {
168                         WaypointSprite_DeployFixed("danger", FALSE, self.origin);
169                         sprint(self, "DANGER spawned at location\n");
170                 }
171                 else if(imp == 38)
172                 {
173                         WaypointSprite_DeployFixed("danger", FALSE, self.cursor_trace_endpos);
174                         sprint(self, "DANGER spawned at crosshair\n");
175                 }
176                 else if(imp == 39 && vlen(self.death_origin))
177                 {
178                         WaypointSprite_DeployFixed("danger", FALSE, self.death_origin);
179                         sprint(self, "DANGER spawned at death location\n");
180                 }
181                 else if(imp == 47)
182                 {
183                         WaypointSprite_ClearPersonal();
184                         sprint(self, "personal waypoint cleared\n");
185                 }
186                 else if(imp == 48)
187                 {
188                         WaypointSprite_ClearOwned();
189                         sprint(self, "all waypoints cleared\n");
190                 }
191                 else if(imp == 49)
192                 {
193                         self.cvar_cl_hidewaypoints = !(self.cvar_cl_hidewaypoints);
194                         sprint(self, "fixed waypoints now ");
195                         if(self.cvar_cl_hidewaypoints)
196                                 sprint(self, "OFF\n");
197                         else
198                                 sprint(self, "ON\n");
199                 }
200         }
201         else
202         {
203                 if (sv_cheats)
204                 {
205                         if(imp == 19)
206                         {
207                                 makevectors(self.v_angle);
208                                 traceline(self.origin + self.view_ofs, self.origin + self.view_ofs + v_forward * MAX_SHOT_DISTANCE, FALSE, self);
209                                 if (trace_fraction < 1)
210                                         printsurfaceinfo(trace_ent, trace_endpos);
211                         }
212                         else if(imp == 20)
213                         {
214                                 makevectors(self.v_angle);
215                                 traceline(self.origin + self.view_ofs, self.origin + self.view_ofs + v_forward * 65536, FALSE, self);
216                                 sprint(self, strcat("distance: ", ftos(fabs(vlen(trace_endpos - (self.origin + self.view_ofs)))), "\n"));
217                         }
218                         else if(self.deadflag == DEAD_NO)
219                         {
220                                 if(imp == 77)
221                                 {
222                                         if(self.waypointsprite_deployed_personal)
223                                         {
224                                                 self.speedrunning = TRUE;
225                                                 tracebox(self.waypointsprite_deployed_personal.origin, self.mins, self.maxs, self.waypointsprite_deployed_personal.origin, MOVE_WORLDONLY, self);
226                                                 if(trace_startsolid)
227                                                 {
228                                                         sprint(self, "Cannot move there, cheater - only waypoints set using g_waypointsprite_personal work\n");
229                                                 }
230                                                 else
231                                                 {
232                                                         // Abort speedrun, teleport back
233                                                         setorigin(self, self.waypointsprite_deployed_personal.origin);
234                                                         self.oldvelocity = self.velocity = self.personal_velocity;
235                                                         self.angles = self.personal_v_angle;
236                                                         self.fixangle = TRUE;
237                                                         if(self.flagcarried)
238                                                         {
239                                                                 bprint("The ", self.flagcarried.netname, " was returned to base by its carrier\n");
240                                                                 ReturnFlag(self.flagcarried);
241                                                         }
242                                                 }
243                                                 self.ammo_rockets = 999;
244                                                 self.ammo_nails = 999;
245                                                 self.ammo_cells = 999;
246                                                 self.ammo_shells = 999;
247                                                 self.health = start_health;
248                                                 self.armorvalue = start_armorvalue;
249                                                 self.items |= itemsInMap & (IT_LASER | IT_SHOTGUN | IT_UZI | IT_GRENADE_LAUNCHER | IT_ELECTRO | IT_CRYLINK | IT_NEX | IT_HAGAR | IT_ROCKET_LAUNCHER);
250                                                 self.pauserotarmor_finished = time + cvar("g_balance_pause_armor_rot_spawn");
251                                                 self.pauserothealth_finished = time + cvar("g_balance_pause_health_rot_spawn");
252                                                 self.pauseregen_finished = time + cvar("g_balance_pause_health_regen_spawn");
253                                         }
254                                         else
255                                                 sprint(self, "No waypoint set, cheater (use g_waypointsprite_personal to set one)\n");
256                                 }
257                                 else if(imp == 99)
258                                 {
259                                         self.items |= (IT_LASER | IT_UZI | IT_SHOTGUN | IT_GRENADE_LAUNCHER | IT_ELECTRO | IT_CRYLINK | IT_NEX | IT_HAGAR | IT_ROCKET_LAUNCHER);
260                                         self.ammo_shells = g_pickup_shells_max;
261                                         self.ammo_nails = g_pickup_nails_max;
262                                         self.ammo_rockets = g_pickup_rockets_max;
263                                         self.ammo_cells = g_pickup_cells_max;
264                                         self.health = g_pickup_healthsmall_max;
265                                         self.armorvalue = g_pickup_armorsmall_max;
266                                         self.pauserotarmor_finished = time + cvar("g_balance_pause_armor_rot_spawn");
267                                         self.pauserothealth_finished = time + cvar("g_balance_pause_health_rot_spawn");
268                                         self.pauseregen_finished = time + cvar("g_balance_pause_health_regen_spawn");
269                                         // precache weapon models/sounds
270                                         local float wep;
271                                         wep = WEP_FIRST;
272                                         while (wep <= WEP_LAST)
273                                         {
274                                                 weapon_action(wep, WR_PRECACHE);
275                                                 wep = wep + 1;
276                                         }
277                                 }
278                                 else if (imp == 13)
279                                 {
280                                         makevectors (self.v_angle);
281                                         self.velocity = self.velocity + v_forward * 300;
282                                         CopyBody(1);
283                                         self.lip += 1;
284                                         self.velocity = self.velocity - v_forward * 300;
285                                 }
286                                 else if (imp == 14)
287                                 {
288                                         CopyBody(0);
289                                         self.lip += 1;
290                                 }
291                                 else if (imp == 143) // actually: impulse 911
292                                 {
293                                         vector start, end, enddown;
294                                         float i;
295                                         float m;
296                                         float good, evil, evilsurf;
297                                         float maxattempts;
298                                         vector org, delta;
299
300                                         good = DPCONTENTS_SOLID | DPCONTENTS_CORPSE | DPCONTENTS_PLAYERCLIP;
301                                         evil = DPCONTENTS_SLIME | DPCONTENTS_LAVA | DPCONTENTS_SKY | DPCONTENTS_BODY | DPCONTENTS_DONOTENTER;
302                                         evilsurf = Q3SURFACEFLAG_SKY;
303
304                                         m = self.dphitcontentsmask;
305                                         self.dphitcontentsmask = good | evil;
306
307                                         org = world.mins;
308                                         delta = world.maxs - world.mins;
309
310                                         maxattempts = ((sv_cheats >= 2) ? 100000 : 100);
311
312                                         for(i = 0; i < maxattempts; ++i)
313                                         {
314                                                 start_x = org_x + random() * delta_x;
315                                                 start_y = org_y + random() * delta_y;
316                                                 start_z = org_z + random() * delta_z;
317
318                                                 // rule 1: start inside world bounds, and outside
319                                                 // solid, and don't start from somewhere where you can
320                                                 // fall down to evil
321                                                 tracebox(start, self.mins, self.maxs, start - '0 0 1' * delta_z, MOVE_NORMAL, self);
322                                                 if(trace_fraction >= 1)
323                                                         continue;
324                                                 if(trace_startsolid)
325                                                         continue;
326                                                 dprint("hit contents ", ftos(trace_dphitcontents), "\n");
327                                                 if(trace_dphitcontents & evil)
328                                                         continue;
329                                                 if(trace_dphitq3surfaceflags & evilsurf)
330                                                         continue;
331
332                                                 // rule 2: if we are too high, lower the point
333                                                 if(trace_fraction * delta_z > 1024)
334                                                         start = trace_endpos + '0 0 1024';
335                                                 enddown = trace_endpos;
336
337                                                 // these can be traceLINES as we already verified the starting box
338                                                 traceline(start, start + '1 0 0' * delta_x, MOVE_NORMAL, self);
339                                                 if(trace_fraction >= 1)
340                                                         continue;
341                                                 traceline(start, start - '1 0 0' * delta_x, MOVE_NORMAL, self);
342                                                 if(trace_fraction >= 1)
343                                                         continue;
344                                                 traceline(start, start + '0 1 0' * delta_y, MOVE_NORMAL, self);
345                                                 if(trace_fraction >= 1)
346                                                         continue;
347                                                 traceline(start, start - '0 1 0' * delta_y, MOVE_NORMAL, self);
348                                                 if(trace_fraction >= 1)
349                                                         continue;
350                                                 traceline(start, start + '0 0 1' * delta_z, MOVE_NORMAL, self);
351                                                 if(trace_fraction >= 1)
352                                                         continue;
353
354                                                 end_x = org_x + random() * delta_x;
355                                                 end_y = org_y + random() * delta_y;
356                                                 end_z = org_z + random() * delta_z;
357                                                 end = start + normalize(end - start) * vlen(delta);
358
359                                                 // rule 3: start TO end must not be too short
360                                                 tracebox(start, self.mins, self.maxs, end, MOVE_NORMAL, self);
361                                                 if(trace_startsolid)
362                                                         continue;
363                                                 if(trace_fraction < 256 / vlen(delta))
364                                                         continue;
365
366                                                 // rule 4: don't want to look at sky
367                                                 if(trace_dphitq3surfaceflags & Q3SURFACEFLAG_SKY)
368                                                         continue;
369
370                                                 // rule 5: we must not end up in trigger_hurt
371                                                 if(tracebox_hits_trigger_hurt(start, self.mins, self.maxs, enddown))
372                                                 {
373                                                         dprint("trigger_hurt! ouch! and nothing else could find it!\n");
374                                                         continue;
375                                                 }
376
377                                                 break;
378                                         }
379
380                                         if(i < maxattempts)
381                                         {
382                                                 self.origin = start;
383                                                 self.angles = vectoangles(end - start);
384                                                 self.angles_x = -self.angles_x;
385                                                 self.fixangle = TRUE;
386                                                 self.velocity = '0 0 0';
387                                                 dprint("Needed ", ftos(i + 1), " attempts\n");
388                                         }
389                                         else
390                                                 sprint(self, "Emergency teleport could not find a good location, forget it!\n");
391
392                                         self.dphitcontentsmask = m;
393                                 }
394                         }
395                 }
396         }
397
398         if (cvar("g_waypointeditor"))
399         {
400                 local entity e;
401                 if (imp == 103) waypoint_schedulerelink(waypoint_spawn(self.origin, self.origin, 0));
402                 else if (imp == 104) {e = navigation_findnearestwaypoint(self, FALSE);if (e) waypoint_remove(e);}
403                 else if (imp == 105) waypoint_schedulerelinkall();
404                 else if (imp == 106) waypoint_saveall();
405         }
406
407         //TetrisImpulses(imp);
408 }