Xonotic
cheats.qc
Go to the documentation of this file.
1 #include "cheats.qh"
2 
3 #include "weapons/tracing.qh"
4 #include <common/constants.qh>
6 #include <common/effects/all.qh>
7 #include <common/items/_mod.qh>
12 #include <common/monsters/_mod.qh>
14 #include <common/physics/player.qh>
16 #include <common/stats.qh>
17 #include <common/util.qh>
18 #include <common/weapons/_all.qh>
19 #include <common/weapons/_all.qh>
22 #include <lib/warpzone/common.qh>
24 #include <server/clientkill.qh>
25 #include <server/damage.qh>
26 #include <server/main.qh>
27 #include <server/mutators/_mod.qh>
28 #include <server/player.qh>
29 #include <server/race.qh>
30 #include <server/world.qh>
31 
32 #ifdef NOCHEATS
33 
34 float CheatImpulse(entity this, int imp) { return 0; }
35 float CheatCommand(entity this, int argc) { return 0; }
36 float CheatFrame(entity this) { return 0; }
37 void CheatInit() { cheatcount_total = world.cheatcount; }
38 void CheatShutdown() { }
39 void Drag_MoveDrag(entity from, entity to) { }
40 
41 #else
42 
43 .bool maycheat;
45 
46 
47 
48 void CheatInit()
49 {
51 }
52 
54 {
55 }
56 
57 float CheatsAllowed(entity this, float i, int argc, float fr) // the cheat gets passed as argument for possible future ACL checking
58 {
59  if(IS_DEAD(this))
60  return 0;
61  if(gamestart_sv_cheats < 2 && !IS_PLAYER(this))
62  return 0;
63 
64  if(i == CHIMPULSE_CLONE_MOVING.impulse || i == CHIMPULSE_CLONE_STANDING.impulse)
65  if(this.lip < autocvar_sv_clones)
66  return 1;
67 
68  // haha
69  if(this.maycheat)
70  return 1;
71 
73  return 1;
74 
75  // if we get here, player is not allowed to cheat. Log it.
76  if(i)
77  bprintf("Player %s^7 tried to use cheat 'impulse %d'\n", playername(this.netname, this.team, false), i);
78  else if(argc)
79  bprintf("Player %s^7 tried to use cheat '%s'\n", playername(this.netname, this.team, false), argv(0));
80  else if(fr)
81  bprintf("Player %s^7 tried to use cheat frame %d\n", playername(this.netname, this.team, false), fr);
82  else
83  bprintf("Player %s^7 tried to use an unknown cheat\n", playername(this.netname, this.team, false));
84 
85  return 0;
86 }
87 
88 #define BEGIN_CHEAT_FUNCTION() \
89  float cheating = 0, attempting = 0
90 #define DID_CHEAT() \
91  ++cheating
92 #define ADD_CHEATS(e,n) \
93  cheatcount_total += n; \
94  e.cheatcount += n
95 #define END_CHEAT_FUNCTION() \
96  ADD_CHEATS(this, cheating); \
97  return attempting
98 #define IS_CHEAT(ent,i,argc,fr) \
99  if((++attempting, !CheatsAllowed(ent,i,argc,fr))) \
100  break
101 
104 {
105  entity e;
106  e = find(NULL, targetname, this.target);
107  if(!e)
108  {
109  objerror(this, "Missing target. FAIL!");
110  return;
111  }
112  vector a = vectoangles(e.origin - this.origin);
113  a.x = -a.x; // don't ask
114  this.angles_x = a.x;
115  this.angles_y = a.y;
116  // we leave Rick Roll alone
117 }
118 spawnfunc(info_autoscreenshot)
119 {
120  // this one just has to exist
122  {
123  objerror(this, "Too many info_autoscreenshot entitites. FAIL!");
124  return;
125  }
126  if(this.target != "")
127  InitializeEntity(this, info_autoscreenshot_findtarget, INITPRIO_FINDTARGET);
128 }
129 
130 float CheatImpulse(entity this, int imp)
131 {
133  switch(imp)
134  {
135  entity e, e2;
136 
137  case CHIMPULSE_SPEEDRUN_INIT.impulse: // deploy personal waypoint
138  // shared with regular waypoint init, so this is not a cheat by itself
139  if(!this.personal)
140  {
141  this.personal = new(personal_wp);
142  }
143  this.personal.origin = this.origin;
144  this.personal.v_angle = this.v_angle;
145  this.personal.velocity = this.velocity;
146  SetResource(this.personal, RES_ROCKETS, GetResource(this, RES_ROCKETS));
147  SetResource(this.personal, RES_BULLETS, GetResource(this, RES_BULLETS));
148  SetResource(this.personal, RES_CELLS, GetResource(this, RES_CELLS));
149  SetResource(this.personal, RES_PLASMA, GetResource(this, RES_PLASMA));
150  SetResource(this.personal, RES_SHELLS, GetResource(this, RES_SHELLS));
151  SetResource(this.personal, RES_FUEL, GetResource(this, RES_FUEL));
153  SetResource(this.personal, RES_ARMOR, GetResource(this, RES_ARMOR));
154  STAT(WEAPONS, this.personal) = STAT(WEAPONS, this);
155  StatusEffects_copy(this.statuseffects, this.personal, 0);
156  this.personal.items = this.items;
157  this.personal.pauserotarmor_finished = this.pauserotarmor_finished;
158  this.personal.pauserothealth_finished = this.pauserothealth_finished;
159  this.personal.pauserotfuel_finished = this.pauserotfuel_finished;
160  this.personal.pauseregen_finished = this.pauseregen_finished;
161  this.personal.teleport_time = time;
162  break; // this part itself doesn't cheat, so let's not count this
163  case CHIMPULSE_CLONE_MOVING.impulse:
164  IS_CHEAT(this, imp, 0, 0);
165  makevectors (this.v_angle);
166  this.velocity = this.velocity + v_forward * 300;
167  CopyBody(this, 1);
168  this.lip += 1;
169  this.velocity = this.velocity - v_forward * 300;
170  DID_CHEAT();
171  break;
172  case CHIMPULSE_CLONE_STANDING.impulse:
173  IS_CHEAT(this, imp, 0, 0);
174  CopyBody(this, 0);
175  this.lip += 1;
176  DID_CHEAT();
177  break;
178  case CHIMPULSE_GIVE_ALL.impulse:
179  IS_CHEAT(this, imp, 0, 0);
180  CheatCommand(this, tokenize_console("give all"));
181  break; // already counted as cheat
182  case CHIMPULSE_SPEEDRUN.impulse:
184  IS_CHEAT(this, imp, 0, 0);
185  if(this.personal)
186  {
187  this.speedrunning = true;
188  tracebox(this.personal.origin, this.mins, this.maxs, this.personal.origin, MOVE_WORLDONLY, this);
189  if(trace_startsolid)
190  {
191  sprint(this, "Cannot move there, cheater - only waypoints set using g_waypointsprite_personal work\n");
192  }
193  else
194  {
195  // Abort speedrun, teleport back
196  setorigin(this, this.personal.origin);
197  this.oldvelocity = this.velocity = this.personal.velocity;
198  this.angles = this.personal.v_angle;
199  this.fixangle = true;
200 
201  MUTATOR_CALLHOOK(AbortSpeedrun, this);
202  }
203 
204  SetResource(this, RES_ROCKETS, GetResource(this.personal, RES_ROCKETS));
205  SetResource(this, RES_BULLETS, GetResource(this.personal, RES_BULLETS));
206  SetResource(this, RES_CELLS, GetResource(this.personal, RES_CELLS));
207  SetResource(this, RES_PLASMA, GetResource(this.personal, RES_PLASMA));
208  SetResource(this, RES_SHELLS, GetResource(this.personal, RES_SHELLS));
209  SetResource(this, RES_FUEL, GetResource(this.personal, RES_FUEL));
211  SetResource(this, RES_ARMOR, GetResource(this.personal, RES_ARMOR));
212  STAT(WEAPONS, this) = STAT(WEAPONS, this.personal);
213  this.items = this.personal.items;
214  this.pauserotarmor_finished = time + this.personal.pauserotarmor_finished - this.personal.teleport_time;
215  this.pauserothealth_finished = time + this.personal.pauserothealth_finished - this.personal.teleport_time;
216  this.pauserotfuel_finished = time + this.personal.pauserotfuel_finished - this.personal.teleport_time;
217  this.pauseregen_finished = time + this.personal.pauseregen_finished - this.personal.teleport_time;
218  StatusEffects_copy(this.personal, this.statuseffects, this.personal.teleport_time);
219  StatusEffects_update(this);
220 
222  DID_CHEAT();
223  break;
224  }
225  if(IS_DEAD(this))
226  sprint(this, "UR DEAD AHAHAH))\n");
227  else
228  sprint(this, "No waypoint set, cheater (use g_waypointsprite_personal to set one)\n");
229  break;
230  case CHIMPULSE_TELEPORT.impulse:
231  IS_CHEAT(this, imp, 0, 0);
232  if(this.move_movetype == MOVETYPE_NOCLIP)
233  {
234  e = find(NULL, classname, "info_autoscreenshot");
235  if(e)
236  {
237  sprint(this, "Emergency teleport used info_autoscreenshot location\n");
238  setorigin(this, e.origin);
239  this.angles = e.angles;
240  delete(e);
241  // should we? this.angles_x = -this.angles_x;
242  this.fixangle = true;
243  this.velocity = '0 0 0';
244  DID_CHEAT();
245  break;
246  }
247  }
249  {
250  sprint(this, "Emergency teleport used random location\n");
251  this.angles_x = -this.angles.x;
252  this.fixangle = true;
253  this.velocity = '0 0 0';
254  DID_CHEAT();
255  break;
256  }
257  sprint(this, "Emergency teleport could not find a good location, forget it!\n");
258  break;
259  case CHIMPULSE_R00T.impulse:
260  IS_CHEAT(this, imp, 0, 0);
262  FOREACH_CLIENT(IS_PLAYER(it) && !IS_DEAD(it) && DIFF_TEAM(it, this), { RandomSelection_AddEnt(it, 1, 1); });
265  else
266  e = this;
267 
268  Send_Effect(EFFECT_ROCKET_EXPLODE, e.origin, '0 0 0', 1);
269  sound(e, CH_SHOTS, SND_ROCKET_IMPACT, VOL_BASE, ATTEN_NORM);
270 
271  e2 = spawn();
272  setorigin(e2, e.origin);
273  RadiusDamage(e2, this, 1000, 0, 128, NULL, NULL, 500, DEATH_CHEAT.m_id, DMG_NOWEP, e);
274  delete(e2);
275 
276  LOG_INFO("404 Sportsmanship not found.");
277  DID_CHEAT();
278  break;
279  }
280 
282 }
283 
285 float CheatCommand(entity this, int argc)
286 {
288  string cmd;
289  cmd = argv(0);
290  switch(cmd)
291  {
292  float effectnum, f;
293  vector start, end;
294 
295  case "pointparticles":
296  IS_CHEAT(this, 0, argc, 0);
297  if(argc == 5)
298  {
299  f = stof(argv(2));
300  crosshair_trace(this);
301  start = (1-f) * this.origin + f * trace_endpos;
302  end = stov(argv(3));
303  f = stof(argv(4));
304  Send_Effect_(argv(1), start, end, f);
305  DID_CHEAT();
306  break;
307  }
308  sprint(this, "Usage:^3 sv_cheats 1; restart; cmd pointparticles <effectname> <position> <velocity> <countmultiplier>\n");
309  sprint(this, " Where <position> is a number from 0 to 1 representing distance on the crosshair line,\n");
310  sprint(this, " and <velocity> is a vector \"x y z\"\n");
311  break;
312  case "trailparticles":
313  IS_CHEAT(this, 0, argc, 0);
314  if(argc == 2)
315  {
316  // arguments:
317  // effectname
318  effectnum = _particleeffectnum(argv(1));
319  W_SetupShot(this, weaponentities[0], false, false, SND_Null, CH_WEAPON_A, 0, 0);
320  traceline(w_shotorg, w_shotorg + w_shotdir * max_shot_distance, MOVE_NORMAL, this);
321  __trailparticles(this, effectnum, w_shotorg, trace_endpos);
322  DID_CHEAT();
323  break;
324  }
325  sprint(this, "Usage: sv_cheats 1; restart; cmd trailparticles <effectname>\n");
326  break;
327  case "make":
328  IS_CHEAT(this, 0, argc, 0);
329  if(argc == 3)
330  {
331  f = stof(argv(2));
332  W_SetupShot(this, weaponentities[0], false, false, SND_Null, CH_WEAPON_A, 0, 0);
333  traceline(w_shotorg, w_shotorg + w_shotdir * 2048, MOVE_NORMAL, this);
335  {
336  sprint(this, "cannot make stuff there (bad surface)\n");
337  }
338  else
339  {
340  entity e = new(func_breakable);
341  e.model = strzone(argv(1));
342  e.mdl = "rocket_explode";
345  e.effects = EF_NOMODELFLAGS;
346  if(f == 1)
347  {
349  e.angles = AnglesTransform_ApplyToAngles(e.angles, '-90 0 0'); // so unrotated models work
350  }
351  func_breakable_setup(e);
352  // now, is it valid?
353  if(f == 0)
354  {
355  tracebox(e.origin, e.mins, e.maxs, e.origin, MOVE_NORMAL, e);
356  if(trace_startsolid)
357  {
358  delete(e);
359  sprint(this, "cannot make stuff there (no space)\n");
360  }
361  else
362  DID_CHEAT();
363  }
364  else
365  DID_CHEAT();
366  }
367  }
368  else
369  {
370  sprint(this, "Usage:^3 sv_cheats 1; restart; cmd make <modelname> <mode>\n");
371  sprint(this, " where <mode> can be 0, 1 or 2\n");
372  }
373  break;
374  case "penalty":
375  IS_CHEAT(this, 0, argc, 0);
376  if(argc == 3)
377  {
378  race_ImposePenaltyTime(this, stof(argv(1)), argv(2));
379  DID_CHEAT();
380  break;
381  }
382  sprint(this, "Usage:^3 sv_cheats 1; restart; cmd penalty <duration> <reason>))\n");
383  break;
384  case "dragbox_spawn": {
385  IS_CHEAT(this, 0, argc, 0);
386  entity e = new(dragbox_box);
388  e.nextthink = time;
389  e.solid = -1; // black
390  setmodel(e, MDL_Null); // network it
391  if(argc == 4)
392  e.cnt = stof(argv(1));
393  else
394  e.cnt = max(0, drag_lastcnt);
395 
396  e.aiment = new(dragbox_corner_1);
397  e.aiment.owner = e;
398  setmodel(e.aiment, MDL_MARKER);
399  e.aiment.skin = 0;
400  setsize(e.aiment, '0 0 0', '0 0 0');
401  if(argc == 4)
402  setorigin(e.aiment, stov(argv(2)));
403  else
404  {
405  crosshair_trace(this);
406  setorigin(e.aiment, trace_endpos);
407  }
408 
409  e.enemy = new(dragbox_corner_2);
410  e.enemy.owner = e;
411  setmodel(e.enemy, MDL_MARKER);
412  e.enemy.skin = 1;
413  setsize(e.enemy, '0 0 0', '0 0 0');
414  end = normalize(this.origin + this.view_ofs - e.aiment.origin);
415  end.x = (end.x > 0) * 2 - 1;
416  end.y = (end.y > 0) * 2 - 1;
417  end.z = (end.z > 0) * 2 - 1;
418  if(argc == 4)
419  setorigin(e.enemy, stov(argv(3)));
420  else
421  setorigin(e.enemy, e.aiment.origin + 32 * end);
422 
423  e.killindicator = new(drag_digit);
424  e.killindicator.owner = e;
425  setattachment(e.killindicator, e, "");
426  setorigin(e.killindicator, '0 0 -8');
427  e.killindicator.killindicator = new(drag_digit);
428  e.killindicator.killindicator.owner = e;
429  setattachment(e.killindicator.killindicator, e, "");
430  setorigin(e.killindicator.killindicator, '0 0 8');
431  DID_CHEAT();
432  break;
433  }
434  case "dragpoint_spawn": {
435  IS_CHEAT(this, 0, argc, 0);
436  entity e = new(dragpoint);
438  e.nextthink = time;
439  e.solid = 0; // nothing special
440  setmodel(e, MDL_MARKER);
441  setsize(e, STAT(PL_MIN, this), STAT(PL_MAX, this));
442  e.skin = 2;
443  if(argc == 3)
444  e.cnt = stof(argv(1));
445  else
446  e.cnt = drag_lastcnt;
447  if(argc == 3)
448  setorigin(e, stov(argv(2)));
449  else
450  {
451  crosshair_trace(this);
454  }
455 
456  e.killindicator = new(drag_digit);
457  e.killindicator.owner = e;
458  setattachment(e.killindicator, e, "");
459  setorigin(e.killindicator, '0 0 40');
460  e.killindicator.killindicator = new(drag_digit);
461  e.killindicator.killindicator.owner = e;
462  setattachment(e.killindicator.killindicator, e, "");
463  setorigin(e.killindicator.killindicator, '0 0 56');
464  DID_CHEAT();
465  break;
466  }
467  case "drag_remove":
468  IS_CHEAT(this, 0, argc, 0);
470  crosshair_trace(this);
471  for(entity e = NULL; (e = find(e, classname, "dragbox_box")); )
472  RandomSelection_AddEnt(e, 1, 1 / vlen(e.origin + (e.mins + e.maxs) * 0.5 - trace_endpos));
473  for(entity e = NULL; (e = find(e, classname, "dragpoint")); )
474  RandomSelection_AddEnt(e, 1, 1 / vlen(e.origin + (e.mins + e.maxs) * 0.5 - trace_endpos));
476  {
477  delete(RandomSelection_chosen_ent.killindicator.killindicator);
478  delete(RandomSelection_chosen_ent.killindicator);
479  if(RandomSelection_chosen_ent.aiment)
480  delete(RandomSelection_chosen_ent.aiment);
482  delete(RandomSelection_chosen_ent.enemy);
484  }
485  DID_CHEAT();
486  break;
487  case "drag_setcnt":
488  IS_CHEAT(this, 0, argc, 0);
489  if(argc == 2)
490  {
492  crosshair_trace(this);
493  for(entity e = NULL; (e = find(e, classname, "dragbox_box")); )
494  RandomSelection_AddEnt(e, 1, 1 / vlen(e.origin + (e.mins + e.maxs) * 0.5 - trace_endpos));
495  for(entity e = NULL; (e = find(e, classname, "dragpoint")); )
496  RandomSelection_AddEnt(e, 1, 1 / vlen(e.origin + (e.mins + e.maxs) * 0.5 - trace_endpos));
498  {
499  if(substring(argv(1), 0, 1) == "*")
501  else
503  }
504  DID_CHEAT();
505  break;
506  }
507  sprint(this, "Usage:^3 sv_cheats 1; restart; cmd dragbox_setcnt <cnt>\n");
508  break;
509  case "drag_save":
510  IS_CHEAT(this, 0, argc, 0);
511  if(argc == 2)
512  {
513  f = fopen(argv(1), FILE_WRITE);
514  fputs(f, "cmd drag_clear\n");
515  for(entity e = NULL; (e = find(e, classname, "dragbox_box")); )
516  {
517  fputs(f, strcat("cmd dragbox_spawn ", ftos(e.cnt), " \"", vtos(e.aiment.origin), "\" \"", vtos(e.enemy.origin), "\"\n"));
518  }
519  for(entity e = NULL; (e = find(e, classname, "dragpoint")); )
520  {
521  fputs(f, strcat("cmd dragpoint_spawn ", ftos(e.cnt), " \"", vtos(e.origin), "\"\n"));
522  }
523  fclose(f);
524  DID_CHEAT();
525  break;
526  }
527  sprint(this, "Usage:^3 sv_cheats 1; restart; cmd dragbox_save <filename>\n");
528  break;
529  case "drag_saveraceent":
530  IS_CHEAT(this, 0, argc, 0);
531  if(argc == 2)
532  {
533  f = fopen(argv(1), FILE_WRITE);
534  for(entity e = NULL; (e = find(e, classname, "dragbox_box")); )
535  {
536  fputs(f, "{\n");
537  fputs(f, "\"classname\" \"trigger_race_checkpoint\"\n");
538  fputs(f, strcat("\"origin\" \"", ftos(e.absmin.x), " ", ftos(e.absmin.y), " ", ftos(e.absmin.z), "\"\n"));
539  fputs(f, strcat("\"maxs\" \"", ftos(e.absmax.x - e.absmin.x), " ", ftos(e.absmax.y - e.absmin.y), " ", ftos(e.absmax.z - e.absmin.z), "\"\n"));
540  fputs(f, strcat("\"cnt\" \"", ftos(e.cnt), "\"\n"));
541  fputs(f, strcat("\"targetname\" \"checkpoint", ftos(e.cnt), "\"\n"));
542  fputs(f, "}\n");
543  }
544  for(entity e = NULL; (e = find(e, classname, "dragpoint")); )
545  {
546  start = '0 0 0';
547  effectnum = 0;
548  for(entity ent = NULL; (ent = find(ent, classname, "dragbox_box")); )
549  {
550  if((e.cnt <= 0 && ent.cnt == 0) || e.cnt == ent.cnt)
551  {
552  start = start + ent.origin;
553  ++effectnum;
554  }
555  }
556  start *= 1 / effectnum;
557  fputs(f, "{\n");
558  fputs(f, "\"classname\" \"info_player_race\"\n");
559  fputs(f, strcat("\"angle\" \"", ftos(vectoyaw(start - e.origin)), "\"\n"));
560  fputs(f, strcat("\"origin\" \"", ftos(e.origin.x), " ", ftos(e.origin.y), " ", ftos(e.origin.z), "\"\n"));
561  if(e.cnt == -2)
562  {
563  fputs(f, "\"target\" \"checkpoint0\"\n");
564  fputs(f, "\"race_place\" \"0\"\n");
565  }
566  else if(e.cnt == -1)
567  {
568  fputs(f, "\"target\" \"checkpoint0\"\n");
569  fputs(f, "\"race_place\" \"-1\"\n");
570  }
571  else
572  {
573  fputs(f, strcat("\"target\" \"checkpoint", ftos(e.cnt), "\"\n"));
574  if(e.cnt == 0)
575  {
576  // these need race_place
577  // counting...
578  effectnum = 1;
579  for(entity ent = NULL; (ent = find(ent, classname, "dragpoint")); )
580  if(ent.cnt == 0)
581  {
582  if(vlen2(ent.origin - start) < vlen2(e.origin - start))
583  ++effectnum;
584  else if(vlen2(ent.origin - start) == vlen2(e.origin - start) && etof(ent) < etof(e))
585  ++effectnum;
586  }
587  fputs(f, strcat("\"race_place\" \"", ftos(effectnum), "\"\n"));
588  }
589  }
590  fputs(f, "}\n");
591  }
592  fclose(f);
593  DID_CHEAT();
594  break;
595  }
596  sprint(this, "Usage:^3 sv_cheats 1; restart; cmd dragbox_save <filename>\n");
597  break;
598  case "drag_clear":
599  IS_CHEAT(this, 0, argc, 0);
600  for(entity e = NULL; (e = find(e, classname, "dragbox_box")); )
601  delete(e);
602  for(entity e = NULL; (e = find(e, classname, "dragbox_corner_1")); )
603  delete(e);
604  for(entity e = NULL; (e = find(e, classname, "dragbox_corner_2")); )
605  delete(e);
606  for(entity e = NULL; (e = find(e, classname, "dragpoint")); )
607  delete(e);
608  for(entity e = NULL; (e = find(e, classname, "drag_digit")); )
609  delete(e);
610  DID_CHEAT();
611  break;
612  case "god":
613  IS_CHEAT(this, 0, argc, 0);
615  if(this.flags & FL_GODMODE)
616  {
617  sprint(this, "godmode ON\n");
618  DID_CHEAT();
619  }
620  else
621  sprint(this, "godmode OFF\n");
622  break;
623  case "notarget":
624  IS_CHEAT(this, 0, argc, 0);
626  if(this.flags & FL_NOTARGET)
627  {
628  sprint(this, "notarget ON\n");
629  DID_CHEAT();
630  }
631  else
632  sprint(this, "notarget OFF\n");
633  break;
634  case "noclip":
635  IS_CHEAT(this, 0, argc, 0);
636  if(this.move_movetype != MOVETYPE_NOCLIP)
637  {
639  sprint(this, "noclip ON\n");
640  DID_CHEAT();
641  }
642  else
643  {
645  sprint(this, "noclip OFF\n");
646  }
647  break;
648  case "fly":
649  IS_CHEAT(this, 0, argc, 0);
650  if(this.move_movetype != MOVETYPE_FLY)
651  {
652  set_movetype(this, MOVETYPE_FLY);
653  sprint(this, "flymode ON\n");
654  DID_CHEAT();
655  }
656  else
657  {
659  sprint(this, "flymode OFF\n");
660  }
661  break;
662  case "give":
663  IS_CHEAT(this, 0, argc, 0);
664  if(GiveItems(this, 1, argc))
665  DID_CHEAT();
666  break;
667  case "usetarget":
668  IS_CHEAT(this, 0, argc, 0);
669  entity e = spawn();
670  e.target = argv(1);
671  SUB_UseTargets(e, this, NULL);
672  delete(e);
673  DID_CHEAT();
674  break;
675  case "killtarget":
676  IS_CHEAT(this, 0, argc, 0);
677  entity e2 = spawn();
678  e2.killtarget = argv(1);
679  SUB_UseTargets(e2, this, NULL);
680  delete(e2);
681  DID_CHEAT();
682  break;
683  case "teleporttotarget":
684  IS_CHEAT(this, 0, argc, 0);
685  entity ent = new(cheattriggerteleport);
686  setorigin(ent, ent.origin);
687  ent.target = argv(1);
688  teleport_findtarget(ent);
689  if(!wasfreed(ent))
690  {
691  Simple_TeleportPlayer(ent, this);
692  delete(ent);
693  DID_CHEAT();
694  }
695  break;
696  }
697 
699 }
700 
701 .entity dragentity;
702 
703 float CheatFrame(entity this)
704 {
706 
707  // Dragging can be used as either a cheat, or a function for some objects. If sv_cheats is active,
708  // the cheat dragging is used (unlimited pickup range and any entity can be carried). If sv_cheats
709  // is disabled, normal dragging is used (limited pickup range and only dragable objects can be carried),
710  // grabbing itself no longer being accounted as cheating.
711 
712  switch(0)
713  {
714  default:
716  {
717  // use cheat dragging if cheats are enabled
718  //if(Drag_IsDragging(this))
719  //crosshair_trace_plusvisibletriggers(this);
720  Drag(this, true, true);
721  }
722  else
723  {
724  Drag(this, false, false); // execute dragging
725  }
726  break;
727  }
728 
730 }
731 
732 
733 
734 
735 
736 // ENTITY DRAGGING
737 
738 // on dragger:
739 .float draggravity;
740 .float dragspeed; // speed of mouse wheel action
741 .float dragdistance; // distance of dragentity's draglocalvector from view_ofs
742 .vector draglocalvector; // local attachment vector of the dragentity
744 // on draggee:
745 .entity draggedby;
747 
748 float Drag(entity this, float force_allow_pick, float ischeat)
749 {
751 
752  // returns true when an entity has been picked up
753  // If pick is true, the object can also be picked up if it's not being held already
754  // If pick is false, only keep dragging the object if it's already being held
755 
756  switch(0)
757  {
758  default:
759  if(Drag_IsDragging(this))
760  {
761  if(PHYS_INPUT_BUTTON_DRAG(this))
762  {
763  if(CS(this).impulse == 10 || CS(this).impulse == 15 || CS(this).impulse == 18)
764  {
765  Drag_MoveForward(this);
766  CS(this).impulse = 0;
767  }
768  else if(CS(this).impulse == 12 || CS(this).impulse == 16 || CS(this).impulse == 19)
769  {
770  Drag_MoveBackward(this);
771  CS(this).impulse = 0;
772  }
773  else if(CS(this).impulse >= 1 && CS(this).impulse <= 9)
774  {
775  Drag_SetSpeed(this, CS(this).impulse - 1);
776  }
777  else if(CS(this).impulse == 14)
778  {
779  Drag_SetSpeed(this, 9);
780  }
781 
782  if(frametime)
783  Drag_Update(this);
784  }
785  else
786  {
787  Drag_Finish(this);
788  }
789  }
790  else if(Drag_CanDrag(this) && PHYS_INPUT_BUTTON_DRAG(this))
791  {
793  entity e = trace_ent;
794  float pick = force_allow_pick;
795  if (e && !pick && vdist(this.origin - e.origin, <=, autocvar_g_grab_range))
796  {
797  // pick is true if the object can be picked up. While an object is being carried, the Drag() function
798  // must execute for it either way, otherwise it would cause bugs if it went out of the player's trace.
799  // This also makes sure that an object can only pe picked up if in range, but does not get dropped if
800  // it goes out of range while slinging it around.
801 
802  switch(e.grab)
803  {
804  case 0: // can't grab
805  break;
806  case 1: // owner can grab
807  if(e.owner == this || e.realowner == this)
808  pick = true;
809  break;
810  case 2: // owner and team mates can grab
811  if(SAME_TEAM(e.owner, this) || SAME_TEAM(e.realowner, this) || e.team == this.team)
812  pick = true;
813  break;
814  case 3: // anyone can grab
815  pick = true;
816  break;
817  default:
818  break;
819  }
820  }
821  // Find e and pick
822  if(e && pick && Drag_IsDraggable(e, this))
823  {
824  if(ischeat)
825  IS_CHEAT(this, 0, 0, CHRAME_DRAG);
826  if(e.draggedby)
827  Drag_Finish(e.draggedby);
828  if(e.tag_entity)
829  detach_sameorigin(e);
830  Drag_Begin(this, e, trace_endpos);
831  if(ischeat)
832  DID_CHEAT();
833  return true;
834  }
835  }
836  break;
837  }
838  return false;
839 }
840 
841 void Drag_Begin(entity dragger, entity draggee, vector touchpoint)
842 {
843  float tagscale;
844 
845  draggee.dragmovetype = draggee.move_movetype;
846  draggee.draggravity = draggee.gravity;
847  set_movetype(draggee, MOVETYPE_WALK);
848  draggee.gravity = 0.00001;
849  UNSET_ONGROUND(draggee);
850  draggee.draggedby = dragger;
851 
852  dragger.dragentity = draggee;
853 
854  dragger.dragdistance = vlen(touchpoint - dragger.origin - dragger.view_ofs);
855  dragger.draglocalangle = draggee.angles.y - dragger.v_angle.y;
856  touchpoint = touchpoint - gettaginfo(draggee, 0);
857  tagscale = (vlen(v_forward) ** -2);
858  dragger.draglocalvector_x = touchpoint * v_forward * tagscale;
859  dragger.draglocalvector_y = touchpoint * v_right * tagscale;
860  dragger.draglocalvector_z = touchpoint * v_up * tagscale;
861 
862  dragger.dragspeed = 64;
863 }
864 
865 void Drag_Finish(entity dragger)
866 {
867  entity draggee;
868  draggee = dragger.dragentity;
869  if(dragger)
870  dragger.dragentity = NULL;
871  draggee.draggedby = NULL;
872  set_movetype(draggee, draggee.dragmovetype);
873  draggee.gravity = draggee.draggravity;
874 
875  switch(draggee.move_movetype)
876  {
877  case MOVETYPE_TOSS:
878  case MOVETYPE_WALK:
879  case MOVETYPE_STEP:
880  case MOVETYPE_FLYMISSILE:
881  case MOVETYPE_BOUNCE:
883  case MOVETYPE_PHYSICS:
884  break;
885  default:
886  draggee.velocity = '0 0 0';
887  break;
888  }
889 
890  if((draggee.flags & FL_ITEM) && (vdist(draggee.velocity, <, 32)))
891  {
892  draggee.velocity = '0 0 0';
893  SET_ONGROUND(draggee); // floating items are FUN
894  }
895 }
896 
897 bool drag_undraggable(entity draggee, entity dragger)
898 {
899  // stuff probably shouldn't need this, we should figure out why they do!
900  // exceptions of course are observers and weapon entities, where things mess up
901  return false;
902 }
903 
904 float Drag_IsDraggable(entity draggee, entity dragger)
905 {
906  // TODO add more checks for bad stuff here
907  if(draggee == NULL)
908  return false;
909  if(draggee.classname == "door") // FIXME find out why these must be excluded, or work around the problem (trying to drag these causes like 4 fps)
910  return false; // probably due to BSP collision
911  //if(draggee.model == "")
912  // return false;
913 
914  return ((draggee.draggable) ? draggee.draggable(draggee, dragger) : true);
915 }
916 
918 {
919  // TODO add more checks for bad stuff here
920  if(substring(draggee.model, 0, 1) == "*")
921  return false;
922  return true;
923 }
924 
926 {
927  dragger.dragdistance += dragger.dragspeed;
928 }
929 
930 void Drag_SetSpeed(entity dragger, float s)
931 {
932  dragger.dragspeed = (2 ** s);
933 }
934 
936 {
937  dragger.dragdistance = max(0, dragger.dragdistance - dragger.dragspeed);
938 }
939 
940 void Drag_Update(entity dragger)
941 {
942  vector curorigin, neworigin, goodvelocity;
943  float f;
944  entity draggee;
945 
946  draggee = dragger.dragentity;
947  UNSET_ONGROUND(draggee);
948 
949  curorigin = gettaginfo(draggee, 0);
950  curorigin = curorigin + v_forward * dragger.draglocalvector.x + v_right * dragger.draglocalvector.y + v_up * dragger.draglocalvector.z;
951  makevectors(dragger.v_angle);
952  neworigin = dragger.origin + dragger.view_ofs + v_forward * dragger.dragdistance;
953  goodvelocity = (neworigin - curorigin) * (1 / frametime);
954 
955  while(draggee.angles.y - dragger.v_angle.y - dragger.draglocalangle > 180)
956  dragger.draglocalangle += 360;
957  while(draggee.angles.y - dragger.v_angle.y - dragger.draglocalangle <= -180)
958  dragger.draglocalangle -= 360;
959 
960  f = min(frametime * 10, 1);
961  draggee.velocity = draggee.velocity * (1 - f) + goodvelocity * f;
962 
963  if(Drag_MayChangeAngles(draggee))
964  draggee.angles_y = draggee.angles.y * (1 - f) + (dragger.v_angle.y + dragger.draglocalangle) * f;
965 
966  draggee.ltime = max(servertime + serverframetime, draggee.ltime); // fixes func_train breakage
967 
968  vector vecs = '0 0 0';
969  .entity weaponentity = weaponentities[0]; // TODO: unhardcode
970  if(dragger.(weaponentity).movedir.x > 0)
971  vecs = dragger.(weaponentity).movedir;
972 
973  vector dv = v_right * -vecs_y + v_up * vecs_z;
974 
975  te_lightning1(draggee, dragger.origin + dragger.view_ofs + dv, curorigin);
976 }
977 
978 float Drag_CanDrag(entity dragger)
979 {
980  return (!IS_DEAD(dragger)) || (IS_PLAYER(dragger));
981 }
982 
983 float Drag_IsDragging(entity dragger)
984 {
985  if(!dragger.dragentity)
986  return false;
987  if(wasfreed(dragger.dragentity) || dragger.dragentity.draggedby != dragger)
988  {
989  dragger.dragentity = NULL;
990  return false;
991  }
992  if(!Drag_CanDrag(dragger) || !Drag_IsDraggable(dragger.dragentity, dragger))
993  {
994  Drag_Finish(dragger);
995  return false;
996  }
997  return true;
998 }
999 
1001 {
1002  if(from.draggedby)
1003  {
1004  to.draggedby = from.draggedby;
1005  to.draggedby.dragentity = to;
1006  from.draggedby = NULL;
1007  }
1008 }
1009 
1011 {
1012  if(this.aiment && this.enemy)
1013  {
1014  this.origin_x = (this.aiment.origin.x + this.enemy.origin.x) * 0.5;
1015  this.origin_y = (this.aiment.origin.y + this.enemy.origin.y) * 0.5;
1016  this.origin_z = (this.aiment.origin.z + this.enemy.origin.z) * 0.5;
1017  this.maxs_x = fabs(this.aiment.origin.x - this.enemy.origin.x) * 0.5;
1018  this.maxs_y = fabs(this.aiment.origin.y - this.enemy.origin.y) * 0.5;
1019  this.maxs_z = fabs(this.aiment.origin.z - this.enemy.origin.z) * 0.5;
1020  this.mins = -1 * this.maxs;
1021  setorigin(this, this.origin);
1022  setsize(this, this.mins, this.maxs); // link edict
1023  }
1024 
1025  if(this.cnt == -1) // actually race_place -1
1026  {
1027  // show "10 10" for qualifying spawns
1028  setmodel(this.killindicator, MDL_NUM(10));
1029  setmodel(this.killindicator.killindicator, MDL_NUM(10));
1030  }
1031  else if(this.cnt == -2) // actually race_place 0
1032  {
1033  // show "10 0" for loser spawns
1034  setmodel(this.killindicator, MDL_NUM(10));
1035  setmodel(this.killindicator.killindicator, MDL_NUM(0));
1036  }
1037  else
1038  {
1039  setmodel(this.killindicator, MDL_NUM(this.cnt % 10));
1040  setmodel(this.killindicator.killindicator, MDL_NUM(floor(this.cnt / 10)));
1041  }
1042 
1043  this.nextthink = time;
1044 }
1045 
1046 #endif
int int int imp
Definition: impulse.qc:90
float MOVETYPE_WALK
Definition: progsdefs.qc:249
entity world
Definition: csprogsdefs.qc:15
void Drag_Finish(entity dragger)
Definition: cheats.qc:865
#define PHYS_INPUT_BUTTON_DRAG(s)
Definition: player.qh:153
vector w_shotorg
Definition: tracing.qh:18
vector view_ofs
Definition: progsdefs.qc:151
bool SetResourceExplicit(entity e, Resource res_type, float amount)
Sets the resource amount of an entity without calling any hooks.
Definition: cl_resources.qc:15
void teleport_findtarget(entity this)
Definition: teleporters.qc:237
float trace_dphitq3surfaceflags
const float MOVETYPE_PHYSICS
Header file that describes the resource system.
float MOVETYPE_STEP
Definition: progsdefs.qc:250
int team
Definition: main.qh:157
float MOVETYPE_TOSS
Definition: progsdefs.qc:252
ERASEABLE void RandomSelection_Init()
Definition: random.qc:4
const float CHRAME_DRAG
Definition: cheats.qh:18
entity() spawn
float CheatImpulse(entity this, int imp)
Definition: cheats.qc:130
int autocvar_g_max_info_autoscreenshot
Definition: cheats.qh:7
const float MOVE_NORMAL
Definition: csprogsdefs.qc:252
ClientState CS(Client this)
Definition: state.qh:47
bool speedrunning
Definition: cheats.qh:21
#define FOREACH_CLIENT(cond, body)
Definition: utils.qh:49
float MOVETYPE_BOUNCEMISSILE
Definition: progsdefs.qc:257
vector v_angle
Definition: progsdefs.qc:161
vector maxs
Definition: csprogsdefs.qc:113
float DPCONTENTS_SKY
void SUB_UseTargets(entity this, entity actor, entity trigger)
Definition: triggers.qc:366
float CheatsAllowed(entity this, float i, int argc, float fr)
Definition: cheats.qc:57
string netname
Definition: powerups.qc:20
spawnfunc(info_autoscreenshot)
Definition: cheats.qc:118
void Drag_MoveForward(entity dragger)
Definition: cheats.qc:925
vector w_shotdir
Definition: tracing.qh:19
float MoveToRandomMapLocation(entity e, float goodcontents, float badcontents, float badsurfaceflags, float attempts, float maxaboveground, float minviewdistance)
Definition: world.qc:1157
float DPCONTENTS_PLAYERCLIP
entity to
Definition: self.qh:96
origin
Definition: ent_cs.qc:114
float FL_GODMODE
Definition: progsdefs.qc:237
#define gettaginfo
Definition: post.qh:32
string classname
Definition: csprogsdefs.qc:107
vector oldvelocity
Definition: main.qh:38
float MOVETYPE_BOUNCE
Definition: progsdefs.qc:256
#define DIFF_TEAM(a, b)
Definition: teams.qh:240
float FL_ITEM
Definition: progsdefs.qc:239
#define UNSET_ONGROUND(s)
Definition: movetypes.qh:18
float drag_lastcnt
Definition: cheats.qc:284
#define bprintf(...)
Definition: util.qh:192
float impulse
Definition: progsdefs.qc:158
#define move_out_of_solid(e)
Definition: common.qh:110
#define DMG_NOWEP
Definition: damage.qh:126
float Drag_MayChangeAngles(entity draggee)
Definition: cheats.qc:917
float move_movetype
Definition: movetypes.qh:76
#define BEGIN_CHEAT_FUNCTION()
Definition: cheats.qc:88
void Drag_MoveBackward(entity dragger)
Definition: cheats.qc:935
void race_ImposePenaltyTime(entity pl, float penalty, string reason)
Definition: race.qc:1225
void crosshair_trace(entity pl)
Definition: tracing.qc:508
entity trace_ent
Definition: csprogsdefs.qc:40
bool maycheat
Definition: cheats.qc:43
#define DID_CHEAT()
Definition: cheats.qc:90
#define setmodel(this, m)
Definition: model.qh:26
float Drag_IsDraggable(entity draggee, entity dragger)
Definition: cheats.qc:904
RES_HEALTH
Definition: ent_cs.qc:126
#define RandomSelection_AddEnt(e, weight, priority)
Definition: random.qh:14
#define END_CHEAT_FUNCTION()
Definition: cheats.qc:95
void CheatShutdown()
Definition: cheats.qc:53
void Drag_SetSpeed(entity dragger, float s)
Definition: cheats.qc:930
Model MDL_NUM(int i)
Definition: all.inc:351
void DragBox_Think(entity this)
Definition: cheats.qc:1010
entity Simple_TeleportPlayer(entity teleporter, entity player)
Definition: teleporters.qc:180
entity personal
Definition: cheats.qh:23
float draggravity
Definition: cheats.qc:739
entity enemy
Definition: sv_ctf.qh:143
float Q3SURFACEFLAG_SKY
vector mins
Definition: csprogsdefs.qc:113
#define vlen2(v)
Definition: vector.qh:4
float cnt
Definition: powerups.qc:24
const int CH_WEAPON_A
Definition: sound.qh:7
void SetResource(entity e, Resource res_type, float amount)
Sets the current amount of resource the given entity will have.
Definition: cl_resources.qc:26
float draglocalangle
Definition: cheats.qc:743
vector v_up
Definition: csprogsdefs.qc:31
float serverframetime
Definition: main.qh:36
spree_cen s1 spree_cen s1 spree_cen s1 spree_cen s1 spree_cen s1 spree_cen s1 spree_cen s1 f1 s1 strcat(_("Level %s: "), "^BG%s\3\, _("^BGPress ^F2%s^BG to enter the game"))
bool autocvar_g_allow_checkpoints
Definition: race.qh:3
float gamestart_sv_cheats
Definition: cheats.qc:44
float pauserothealth_finished
Definition: client.qh:343
entity RandomSelection_chosen_ent
Definition: random.qh:5
float CheatFrame(entity this)
Definition: cheats.qc:703
float cheatcount_total
Definition: cheats.qh:10
float fixangle
Definition: progsdefs.qc:160
float EF_NOMODELFLAGS
float pauserotfuel_finished
Definition: client.qh:345
#define NULL
Definition: post.qh:17
float frametime
Definition: csprogsdefs.qc:17
#define LOG_INFO(...)
Definition: log.qh:70
float DPCONTENTS_SOLID
const float VOL_BASE
Definition: sound.qh:36
float pauserotarmor_finished
Definition: client.qh:344
int autocvar_sv_clones
Definition: cheats.qh:8
vector trace_endpos
Definition: csprogsdefs.qc:37
vector AnglesTransform_ApplyToAngles(vector transform, vector v)
#define SAME_TEAM(a, b)
Definition: teams.qh:239
#define W_SetupShot(ent, wepent, antilag, recoil, snd, chan, maxdamage, deathtype)
Definition: tracing.qh:33
float Q3SURFACEFLAG_NOIMPACT
#define IS_DEAD(s)
Definition: utils.qh:26
int autocvar_sv_cheats
Definition: cheats.qh:5
const float ATTEN_NORM
Definition: sound.qh:30
float nextthink
Definition: csprogsdefs.qc:121
float num_autoscreenshot
Definition: cheats.qc:102
const int CH_SHOTS
Definition: sound.qh:14
void Drag_Update(entity dragger)
Definition: cheats.qc:940
float dragspeed
Definition: cheats.qc:740
float Drag_CanDrag(entity dragger)
Definition: cheats.qc:978
vector(float skel, float bonenum) _skel_get_boneabs_hidden
#define tokenize_console
Definition: dpextensions.qh:24
float MOVETYPE_FLYMISSILE
Definition: progsdefs.qc:255
const float FILE_WRITE
Definition: csprogsdefs.qc:233
entity killindicator
Definition: clientkill.qh:7
float MOVETYPE_NOCLIP
Definition: progsdefs.qc:254
float GetResource(entity e, Resource res_type)
Returns the current amount of resource the given entity has.
Definition: cl_resources.qc:10
float DPCONTENTS_BODY
float flags
Definition: csprogsdefs.qc:129
void InitializeEntity(entity e, void(entity this) func, int order)
Definition: world.qc:2146
#define SET_ONGROUND(s)
Definition: movetypes.qh:17
#define vdist(v, cmp, f)
Vector distance comparison, avoids sqrt()
Definition: vector.qh:8
float lip
Definition: subs.qh:40
float autocvar_g_grab_range
Definition: cheats.qh:6
float items
Definition: progsdefs.qc:145
float RadiusDamage(entity inflictor, entity attacker, float coredamage, float edgedamage, float rad, entity cantbe, entity mustbe, float forceintensity, int deathtype,.entity weaponentity, entity directhitentity)
Definition: damage.qc:1057
float dragdistance
Definition: cheats.qc:741
entity draggedby
Definition: cheats.qc:745
string targetname
Definition: progsdefs.qc:194
vector v_right
Definition: csprogsdefs.qc:31
#define MUTATOR_CALLHOOK(id,...)
Definition: base.qh:140
bool drag_undraggable(entity draggee, entity dragger)
Definition: cheats.qc:897
entity aiment
Definition: movetypes.qh:90
entity weaponentities[MAX_WEAPONSLOTS]
Definition: weapon.qh:14
setorigin(ent, v)
float pauseregen_finished
Definition: client.qh:342
#define setthink(e, f)
vector trace_plane_normal
Definition: csprogsdefs.qc:38
float DPCONTENTS_SLIME
float GiveItems(entity e, float beginarg, float endarg)
Definition: items.qc:1504
#define IS_CHEAT(ent, i, argc, fr)
Definition: cheats.qc:98
vector angles
Definition: csprogsdefs.qc:104
void crosshair_trace_plusvisibletriggers(entity pl)
Definition: tracing.qc:513
float dragmovetype
Definition: cheats.qc:746
float trace_startsolid
Definition: csprogsdefs.qc:35
void Drag_MoveDrag(entity from, entity to)
Definition: cheats.qc:1000
float servertime
Definition: main.qh:36
void CheatInit()
Definition: cheats.qc:48
float FL_NOTARGET
Definition: progsdefs.qc:238
string target
Definition: progsdefs.qc:193
#define sound(e, c, s, v, a)
Definition: sound.qh:52
#define BITXOR_ASSIGN(a, b)
Definition: common.qh:107
float CheatCommand(entity this, int argc)
Definition: cheats.qc:285
void CopyBody(entity this, float keepvelocity)
Definition: player.qc:64
float DPCONTENTS_DONOTENTER
float MOVE_WORLDONLY
float time
Definition: csprogsdefs.qc:16
vector velocity
Definition: csprogsdefs.qc:103
#define makevectors
Definition: post.qh:21
entity dragentity
Definition: cheats.qc:701
float trace_fraction
Definition: csprogsdefs.qc:36
float Drag_IsDragging(entity dragger)
Definition: cheats.qc:983
void set_movetype(entity this, int mt)
void info_autoscreenshot_findtarget(entity this)
Definition: cheats.qc:103
vector draglocalvector
Definition: cheats.qc:742
float MOVETYPE_FLY
Definition: progsdefs.qc:251
#define IS_PLAYER(v)
Definition: utils.qh:9
#define fixedvectoangles2(a, b)
void Drag_Begin(entity dragger, entity draggee, vector touchpoint)
Definition: cheats.qc:841
float DPCONTENTS_CORPSE
vector v_forward
Definition: csprogsdefs.qc:31
float DPCONTENTS_LAVA
float Drag(entity this, float force_allow_pick, float ischeat)
Definition: cheats.qc:748