]> icculus.org git repositories - divverent/nexuiz.git/blob - data/qcsrc/server/cl_impulse.qc
do less audio spam for triggers that don't even respond to players
[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, 14: weapon shortcuts
64  * 10: next weapon according to linear list
65  * 11: most recently used weapon
66  * 12: previous weapon according to linear list
67  * 13: best weapon according to priority list
68  * 15: next weapon according to priority list
69  * 16: previous weapon according to priority list
70  * 17: throw weapon
71  * 18: next weapon according to sbar_hudselector 1 list
72  * 19: previous weapon according to sbar_hudselector 1 list
73  * 20: reload if needed
74  *
75  * 30 to 39: create waypoints
76  * 47: clear personal waypoints
77  * 48: clear team waypoints
78  *
79  * 99: loaded
80  *
81  * 140: moving clone
82  * 141: ctf speedrun
83  * 142: fixed clone
84  * 143: emergency teleport
85  * 144: printsurfaceinfo
86  * 145: distance
87  *
88  * TODO:
89  * 200 to 209: prev weapon shortcuts
90  * 210 to 219: best weapon shortcuts
91  * 220 to 229: next weapon shortcuts
92  * 230 to 253: individual weapons (up to 24)
93  */
94
95 void ImpulseCommands (void)
96 {
97         local float imp;
98         vector start, end, enddown;
99         float i;
100         float m;
101         float good, evil, evilsurf;
102         float maxattempts;
103         vector org, delta;
104         float wep;
105         entity e;
106
107         imp = self.impulse;
108         if (!imp || gameover)
109                 return;
110         self.impulse = 0;
111
112         if (timeoutStatus == 2) //don't allow any impulses while the game is paused
113                 return;
114
115         if (imp >= 1 && imp <= 9)
116         {
117                 // weapon switching impulses
118                 if(self.deadflag == DEAD_NO)
119                         W_NextWeaponOnImpulse(imp);
120                 else
121                         self.impulse = imp; // retry in next frame
122         }
123         else if(imp >= 10 && imp <= 20)
124         {
125                 if(self.deadflag == DEAD_NO)
126                 {
127                         switch(imp)
128                         {
129                                 case 10:
130                                         W_NextWeapon (0);
131                                         break;
132                                 case 11:
133                                         W_SwitchWeapon (self.cnt); // previously used
134                                         break;
135                                 case 12:
136                                         W_PreviousWeapon (0);
137                                         break;
138                                 case 13:
139                                         W_SwitchWeapon (w_getbestweapon(self));
140                                         break;
141                                 case 14:
142                                         W_NextWeaponOnImpulse(0);
143                                         break;
144                                 case 15:
145                                         W_NextWeapon (2);
146                                         break;
147                                 case 16:
148                                         W_PreviousWeapon (2);
149                                         break;
150                                 case 17:
151                                         if (!g_minstagib)
152                                                 W_ThrowWeapon(W_CalculateProjectileVelocity(self.velocity, v_forward * 750), '0 0 0', TRUE);
153                                         break;
154                                 case 18:
155                                         W_NextWeapon (1);
156                                         break;
157                                 case 19:
158                                         W_PreviousWeapon (1);
159                                         break;
160                                 case 20:
161                                         W_Reload ();
162                                         break;
163                         }
164                 }
165                 else
166                         self.impulse = imp; // retry in next frame
167         }
168         else if(imp >= 200 && imp <= 229)
169         {
170                 if(self.deadflag == DEAD_NO)
171                 {
172                         // custom order weapon cycling
173                         i = mod(imp, 10);
174                         m = (imp - (210 + i)); // <0 for prev, =0 for best, >0 for next
175                         W_CycleWeapon(self.(cvar_cl_weaponpriorities[i]), m);
176                 }
177                 else
178                         self.impulse = imp; // retry in next frame
179         }
180         else if(imp >= 230 && imp <= 253)
181         {
182                 if(self.deadflag == DEAD_NO)
183                         W_SwitchWeapon (imp - 230 + WEP_FIRST);
184                 else
185                         self.impulse = imp; // retry in next frame
186         }
187         // deploy waypoints
188         else if (imp >= 30 && imp <= 49)
189         {
190                 entity wp;
191                 switch(imp)
192                 {
193                         case 30:
194                                 wp = WaypointSprite_DeployPersonal("waypoint", self.origin);
195                                 if(wp)
196                                 {
197                                         WaypointSprite_UpdateTeamRadar(wp, RADARICON_WAYPOINT, '0 1 1');
198                                         WaypointSprite_Ping(wp);
199                                 }
200                                 self.personal_v_angle = self.v_angle;
201                                 self.personal_velocity = self.velocity;
202                                 sprint(self, "personal waypoint spawned at location\n");
203                                 break;
204                         case 31:
205                                 wp = WaypointSprite_DeployPersonal("waypoint", self.cursor_trace_endpos);
206                                 if(wp)
207                                 {
208                                         WaypointSprite_UpdateTeamRadar(wp, RADARICON_WAYPOINT, '0 1 1');
209                                         WaypointSprite_Ping(wp);
210                                 }
211                                 self.personal_v_angle = self.v_angle;
212                                 self.personal_velocity = '0 0 0';
213                                 sprint(self, "personal waypoint spawned at crosshair\n");
214                                 break;
215                         case 32:
216                                 if(vlen(self.death_origin))
217                                 {
218                                         wp = WaypointSprite_DeployPersonal("waypoint", self.death_origin);
219                                         if(wp)
220                                         {
221                                                 WaypointSprite_UpdateTeamRadar(wp, RADARICON_WAYPOINT, '0 1 1');
222                                                 WaypointSprite_Ping(wp);
223                                         }
224                                         self.personal_v_angle = self.v_angle;
225                                         self.personal_velocity = '0 0 0';
226                                         sprint(self, "personal waypoint spawned at death location\n");
227                                 }
228                                 break;
229                         case 33:
230                                 if(self.deadflag == DEAD_NO && teams_matter)
231                                 {
232                                         wp = WaypointSprite_Attach("helpme", TRUE);
233                                         if(wp)
234                                                 WaypointSprite_UpdateTeamRadar(wp, RADARICON_HELPME, '1 0.5 0'); // TODO choose better color
235                                         if(!wp)
236                                                 wp = self.waypointsprite_attachedforcarrier; // flag sprite?
237                                         if(wp)
238                                                 WaypointSprite_Ping(wp);
239                                         sprint(self, "HELP ME attached\n");
240                                 }
241                                 break;
242                         case 34:
243                                 wp = WaypointSprite_DeployFixed("here", FALSE, self.origin);
244                                 if(wp)
245                                 {
246                                         WaypointSprite_UpdateTeamRadar(wp, RADARICON_HERE, '0 1 0');
247                                         WaypointSprite_Ping(wp);
248                                 }
249                                 sprint(self, "HERE spawned at location\n");
250                                 break;
251                         case 35:
252                                 wp = WaypointSprite_DeployFixed("here", FALSE, self.cursor_trace_endpos);
253                                 if(wp)
254                                 {
255                                         WaypointSprite_UpdateTeamRadar(wp, RADARICON_HERE, '0 1 0');
256                                         WaypointSprite_Ping(wp);
257                                 }
258                                 sprint(self, "HERE spawned at crosshair\n");
259                                 break;
260                         case 36:
261                                 if(vlen(self.death_origin))
262                                 {
263                                         wp = WaypointSprite_DeployFixed("here", FALSE, self.death_origin);
264                                         if(wp)
265                                         {
266                                                 WaypointSprite_UpdateTeamRadar(wp, RADARICON_HERE, '0 1 0');
267                                                 WaypointSprite_Ping(wp);
268                                         }
269                                         sprint(self, "HERE spawned at death location\n");
270                                 }
271                                 break;
272                         case 37:
273                                 wp = WaypointSprite_DeployFixed("danger", FALSE, self.origin);
274                                 if(wp)
275                                 {
276                                         WaypointSprite_UpdateTeamRadar(wp, RADARICON_DANGER, '1 0.5 0');
277                                         WaypointSprite_Ping(wp);
278                                 }
279                                 sprint(self, "DANGER spawned at location\n");
280                                 break;
281                         case 38:
282                                 wp = WaypointSprite_DeployFixed("danger", FALSE, self.cursor_trace_endpos);
283                                 if(wp)
284                                 {
285                                         WaypointSprite_UpdateTeamRadar(wp, RADARICON_DANGER, '1 0.5 0');
286                                         WaypointSprite_Ping(wp);
287                                 }
288                                 sprint(self, "DANGER spawned at crosshair\n");
289                                 break;
290                         case 39:
291                                 if(vlen(self.death_origin))
292                                 {
293                                         wp = WaypointSprite_DeployFixed("danger", FALSE, self.death_origin);
294                                         if(wp)
295                                         {
296                                                 WaypointSprite_UpdateTeamRadar(wp, RADARICON_DANGER, '1 0.5 0');
297                                                 WaypointSprite_Ping(wp);
298                                         }
299                                         sprint(self, "DANGER spawned at death location\n");
300                                 }
301                                 break;
302                         case 47:
303                                 WaypointSprite_ClearPersonal();
304                                 sprint(self, "personal waypoint cleared\n");
305                                 break;
306                         case 48:
307                                 WaypointSprite_ClearOwned();
308                                 sprint(self, "all waypoints cleared\n");
309                                 break;
310                 }
311         }
312         else if(imp >= 140 && imp <= 149 || imp == 99) // 10 cheats ought to be enough for anyone
313         {
314                 if(self.deadflag == DEAD_NO)
315                 {
316                         if(sv_cheats || (self.lip < sv_clones))
317                         {
318                                 switch(imp)
319                                 {       
320                                          case 140:
321                                                 makevectors (self.v_angle);
322                                                 self.velocity = self.velocity + v_forward * 300;
323                                                 CopyBody(1);
324                                                 self.lip += 1;
325                                                 self.velocity = self.velocity - v_forward * 300;
326                                                 break;
327                                         case 142:
328                                                 CopyBody(0);
329                                                 self.lip += 1;
330                                                 break;
331                                  }
332                         }
333
334                         if(sv_cheats)
335                         {
336                                 switch(imp)
337                                 {
338                                         case 99:
339                                                 self.weapons |= WEPBIT_ALL;
340                                                 self.items |= IT_UNLIMITED_AMMO;
341                                                 self.ammo_shells = g_pickup_shells_max;
342                                                 self.ammo_nails = g_pickup_nails_max;
343                                                 self.ammo_rockets = g_pickup_rockets_max;
344                                                 self.ammo_cells = g_pickup_cells_max;
345                                                 self.health = g_pickup_healthsmall_max;
346                                                 self.armorvalue = g_pickup_armorsmall_max;
347                                                 self.pauserotarmor_finished = time + cvar("g_balance_pause_armor_rot_spawn");
348                                                 self.pauserothealth_finished = time + cvar("g_balance_pause_health_rot_spawn");
349                                                 self.pauseregen_finished = time + cvar("g_balance_pause_health_regen_spawn");
350                                                 // precache weapon models/sounds
351                                                 wep = WEP_FIRST;
352                                                 while (wep <= WEP_LAST)
353                                                 {
354                                                         weapon_action(wep, WR_PRECACHE);
355                                                         wep = wep + 1;
356                                                 }
357                                                 break;
358                                         case 141:
359                                                 if(self.waypointsprite_deployed_personal)
360                                                 {
361                                                         self.speedrunning = TRUE;
362                                                         tracebox(self.waypointsprite_deployed_personal.origin, self.mins, self.maxs, self.waypointsprite_deployed_personal.origin, MOVE_WORLDONLY, self);
363                                                         if(trace_startsolid)
364                                                         {
365                                                                 sprint(self, "Cannot move there, cheater - only waypoints set using g_waypointsprite_personal work\n");
366                                                         }
367                                                         else
368                                                         {
369                                                                 // Abort speedrun, teleport back
370                                                                 setorigin(self, self.waypointsprite_deployed_personal.origin);
371                                                                 self.oldvelocity = self.velocity = self.personal_velocity;
372                                                                 self.angles = self.personal_v_angle;
373                                                                 self.fixangle = TRUE;
374                                                                 if(self.flagcarried)
375                                                                 {
376                                                                         bprint("The ", self.flagcarried.netname, " was returned to base by its carrier\n");
377                                                                         ReturnFlag(self.flagcarried);
378                                                                 }
379                                                         }
380                                                         self.ammo_rockets = 999;
381                                                         self.ammo_nails = 999;
382                                                         self.ammo_cells = 999;
383                                                         self.ammo_shells = 999;
384                                                         self.health = start_health;
385                                                         self.armorvalue = start_armorvalue;
386                                                         self.weapons |= weaponsInMap;
387                                                         self.pauserotarmor_finished = time + cvar("g_balance_pause_armor_rot_spawn");
388                                                         self.pauserothealth_finished = time + cvar("g_balance_pause_health_rot_spawn");
389                                                         self.pauseregen_finished = time + cvar("g_balance_pause_health_regen_spawn");
390                                                 }
391                                                 else if(self.deadflag != DEAD_NO)
392                                                         sprint(self, "UR DEAD AHAHAH))\n");
393                                                 else
394                                                         sprint(self, "No waypoint set, cheater (use g_waypointsprite_personal to set one)\n");
395                                                 break;
396                                         case 143:
397                                                 good = DPCONTENTS_SOLID | DPCONTENTS_CORPSE | DPCONTENTS_PLAYERCLIP;
398                                                 evil = DPCONTENTS_SLIME | DPCONTENTS_LAVA | DPCONTENTS_SKY | DPCONTENTS_BODY | DPCONTENTS_DONOTENTER;
399                                                 evilsurf = Q3SURFACEFLAG_SKY;
400
401                                                 m = self.dphitcontentsmask;
402                                                 self.dphitcontentsmask = good | evil;
403
404                                                 org = world.mins;
405                                                 delta = world.maxs - world.mins;
406
407                                                 maxattempts = ((sv_cheats >= 2) ? 100000 : 100);
408
409                                                 for(i = 0; i < maxattempts; ++i)
410                                                 {
411                                                         start_x = org_x + random() * delta_x;
412                                                         start_y = org_y + random() * delta_y;
413                                                         start_z = org_z + random() * delta_z;
414
415                                                         // rule 1: start inside world bounds, and outside
416                                                         // solid, and don't start from somewhere where you can
417                                                         // fall down to evil
418                                                         tracebox(start, self.mins, self.maxs, start - '0 0 1' * delta_z, MOVE_NORMAL, self);
419                                                         if(trace_fraction >= 1)
420                                                                 continue;
421                                                         if(trace_startsolid)
422                                                                 continue;
423                                                         dprint("hit contents ", ftos(trace_dphitcontents), "\n");
424                                                         if(trace_dphitcontents & evil)
425                                                                 continue;
426                                                         if(trace_dphitq3surfaceflags & evilsurf)
427                                                                 continue;
428
429                                                         // rule 2: if we are too high, lower the point
430                                                         if(trace_fraction * delta_z > 1024)
431                                                                 start = trace_endpos + '0 0 1024';
432                                                         enddown = trace_endpos;
433
434                                                         // these can be traceLINES as we already verified the starting box
435                                                         traceline(start, start + '1 0 0' * delta_x, MOVE_NORMAL, self);
436                                                         if(trace_fraction >= 1)
437                                                                 continue;
438                                                         traceline(start, start - '1 0 0' * delta_x, MOVE_NORMAL, self);
439                                                         if(trace_fraction >= 1)
440                                                                 continue;
441                                                         traceline(start, start + '0 1 0' * delta_y, MOVE_NORMAL, self);
442                                                         if(trace_fraction >= 1)
443                                                                 continue;
444                                                         traceline(start, start - '0 1 0' * delta_y, MOVE_NORMAL, self);
445                                                         if(trace_fraction >= 1)
446                                                                 continue;
447                                                         traceline(start, start + '0 0 1' * delta_z, MOVE_NORMAL, self);
448                                                         if(trace_fraction >= 1)
449                                                                 continue;
450
451                                                         end_x = org_x + random() * delta_x;
452                                                         end_y = org_y + random() * delta_y;
453                                                         end_z = org_z + random() * delta_z;
454                                                         end = start + normalize(end - start) * vlen(delta);
455
456                                                         // rule 3: start TO end must not be too short
457                                                         tracebox(start, self.mins, self.maxs, end, MOVE_NORMAL, self);
458                                                         if(trace_startsolid)
459                                                                 continue;
460                                                         if(trace_fraction < 256 / vlen(delta))
461                                                                 continue;
462
463                                                         // rule 4: don't want to look at sky
464                                                         if(trace_dphitq3surfaceflags & Q3SURFACEFLAG_SKY)
465                                                                 continue;
466
467                                                         // rule 5: we must not end up in trigger_hurt
468                                                         if(tracebox_hits_trigger_hurt(start, self.mins, self.maxs, enddown))
469                                                         {
470                                                                 dprint("trigger_hurt! ouch! and nothing else could find it!\n");
471                                                                 continue;
472                                                         }
473
474                                                         break;
475                                                 }
476
477                                                 if(i < maxattempts)
478                                                 {
479                                                         self.origin = start;
480                                                         self.angles = vectoangles(end - start);
481                                                         self.angles_x = -self.angles_x;
482                                                         self.fixangle = TRUE;
483                                                         self.velocity = '0 0 0';
484                                                         dprint("Needed ", ftos(i + 1), " attempts\n");
485                                                 }
486                                                 else
487                                                         sprint(self, "Emergency teleport could not find a good location, forget it!\n");
488
489                                                 self.dphitcontentsmask = m;
490                                                 break;
491                                         case 144:
492                                                 makevectors(self.v_angle);
493                                                 traceline(self.origin + self.view_ofs, self.origin + self.view_ofs + v_forward * MAX_SHOT_DISTANCE, FALSE, self);
494                                                 if (trace_fraction < 1)
495                                                         printsurfaceinfo(trace_ent, trace_endpos);
496                                                 break;
497                                         case 145:
498                                                 makevectors(self.v_angle);
499                                                 traceline(self.origin + self.view_ofs, self.origin + self.view_ofs + v_forward * 65536, FALSE, self);
500                                                 sprint(self, strcat("distance: ", ftos(fabs(vlen(trace_endpos - (self.origin + self.view_ofs)))), "\n"));
501                                                 break;
502                                 }
503                         }
504                 }
505         }
506         else if(imp >= 103 && imp <= 106)
507         {
508                 if(cvar("g_waypointeditor"))
509                 {
510                         switch(imp)
511                         {
512                                 case 103:
513                                         waypoint_schedulerelink(waypoint_spawn(self.origin, self.origin, 0));
514                                         break;
515                                 case 104:
516                                         e = navigation_findnearestwaypoint(self, FALSE);
517                                         if (e)
518                                                 waypoint_remove(e);
519                                         break;
520                                 case 105:
521                                         waypoint_schedulerelinkall();
522                                         break;
523                                 case 106:
524                                         waypoint_saveall();
525                                         break;
526                         }
527                 }
528         }
529
530         //TetrisImpulses(imp);
531 }