Xonotic
portals.qc
Go to the documentation of this file.
1 #include "portals.qh"
2 
3 #include <common/constants.qh>
5 #include <common/effects/all.qh>
10 #include <common/util.qh>
13 #include <common/weapons/_all.qh>
17 #include <lib/warpzone/common.qh>
19 #include <server/client.qh>
20 #include <server/damage.qh>
21 #include <server/hook.qh>
22 #include <server/mutators/_mod.qh>
23 #include <server/player.qh>
24 #include <server/weapons/common.qh>
25 
26 #define PORTALS_ARE_NOT_SOLID
27 
28 const vector SAFENUDGE = '1 1 1';
29 const vector SAFERNUDGE = '8 8 8';
30 
36 
38 {
39  vector vbest = vec3(
40  ((v.x < 0) ? p.mins.x : p.maxs.x),
41  ((v.y < 0) ? p.mins.y : p.maxs.y),
42  ((v.z < 0) ? p.mins.z : p.maxs.z));
43 
44  return vbest * v;
45 }
46 
48 {
49  vector old_forward, old_up;
50  vector old_yawforward;
51  vector new_forward, new_up;
52  vector new_yawforward;
53 
54  vector ang;
55  ang = vangle;
56  /*
57  ang_x = bound(-89, mod(-ang_x + 180, 360) - 180, 89);
58  ang = AnglesTransform_ApplyToVAngles(transform, ang);
59  */
60 
61  // PLAYERS use different math
62 #if !(POSITIVE_PITCH_IS_DOWN)
63  ang.x = -ang.x;
64 #endif
65 
66  //print("reference: ", vtos(AnglesTransform_ApplyToVAngles(transform, ang)), "\n");
67 
68  fixedmakevectors(ang);
69  old_forward = v_forward;
70  old_up = v_up;
71  fixedmakevectors(ang.y * '0 1 0');
72  old_yawforward = v_forward;
73 
74  // their aiming directions are portalled...
75  new_forward = AnglesTransform_Apply(transform, old_forward);
76  new_up = AnglesTransform_Apply(transform, old_up);
77  new_yawforward = AnglesTransform_Apply(transform, old_yawforward);
78 
79  // but now find a new sense of direction
80  // this is NOT easy!
81  // assume new_forward points straight up.
82  // What is our yaw?
83  //
84  // new_up could now point forward OR backward... which direction to choose?
85 
86  if(new_forward.z > 0.7 || new_forward.z < -0.7) // far up; in this case, the "up" vector points backwards
87  {
88  // new_yawforward and new_yawup define the new aiming half-circle
89  // we "just" need to find out whether new_up or -new_up is in that half circle
90  ang = fixedvectoangles(new_forward); // this still gets us a nice pitch value...
91  if(new_up * new_yawforward < 0)
92  new_up = -1 * new_up;
93  ang.y = vectoyaw(new_up); // this vector is the yaw we want
94  //print("UP/DOWN path: ", vtos(ang), "\n");
95  }
96  else
97  {
98  // good angles; here, "forward" suffices
99  ang = fixedvectoangles(new_forward);
100  //print("GOOD path: ", vtos(ang), "\n");
101  }
102 
103 #if !(POSITIVE_PITCH_IS_DOWN)
104  ang.x = -ang.x;
105 #endif
106  ang.z = vangle.z;
107  return ang;
108 }
109 
110 .vector right_vector;
111 float Portal_TeleportPlayer(entity teleporter, entity player, entity portal_owner)
112 {
113  vector from, to, safe, step, transform, ang, newvel;
114  float planeshift, s, t;
115 
116  if (!teleporter.enemy)
117  {
118  backtrace("Portal_TeleportPlayer called without other portal being set. Stop.");
119  return 0;
120  }
121 
122  from = teleporter.origin;
123  transform = teleporter.portal_transform;
124 
125  to = teleporter.enemy.origin;
126  to = to + AnglesTransform_Apply(teleporter.portal_transform, player.origin - from);
127  newvel = AnglesTransform_Apply(transform, player.velocity);
128  // this now is INSIDE the plane... can't use that
129 
130  // shift it out
131  fixedmakevectors(teleporter.enemy.mangle);
132 
133  // first shift it ON the plane if needed
134  planeshift = ((teleporter.enemy.origin - to) * v_forward) + PlayerEdgeDistance(player, v_forward) + 1;
135  /*
136  if(planeshift > 0 && (newvel * v_forward) > vlen(newvel) * 0.01)
137  // if we can't, let us not do the planeshift and do somewhat incorrect transformation in the end
138  to += newvel * (planeshift / (newvel * v_forward));
139  else
140  */
141  to += v_forward * planeshift;
142 
143  s = (to - teleporter.enemy.origin) * v_right;
144  t = (to - teleporter.enemy.origin) * v_up;
145  s = bound(-48, s, 48);
146  t = bound(-48, t, 48);
147  to = teleporter.enemy.origin
148  + ((to - teleporter.enemy.origin) * v_forward) * v_forward
149  + s * v_right
150  + t * v_up;
151 
152  safe = teleporter.enemy.portal_safe_origin; // a valid player origin
153  step = to + ((safe - to) * v_forward) * v_forward;
154  tracebox(safe, player.mins - SAFENUDGE, player.maxs + SAFENUDGE, step, MOVE_NOMONSTERS, player);
155  if(trace_startsolid)
156  {
157  LOG_INFO("'safe' teleport location is not safe!");
158  // FAIL TODO why does this happen?
159  return 0;
160  }
161  safe = trace_endpos + normalize(safe - trace_endpos) * 0;
162  tracebox(safe, player.mins - SAFENUDGE, player.maxs + SAFENUDGE, to, MOVE_NOMONSTERS, player);
163  if(trace_startsolid)
164  {
165  LOG_INFO("trace_endpos in solid, this can't be!");
166  // FAIL TODO why does this happen? (reported by MrBougo)
167  return 0;
168  }
169  to = trace_endpos + normalize(safe - trace_endpos) * 0;
170  //print(vtos(to), "\n");
171 
172  // ang_x stuff works around weird quake angles
173  if(IS_PLAYER(player))
174  ang = Portal_ApplyTransformToPlayerAngle(transform, player.v_angle);
175  else
176  ang = AnglesTransform_ApplyToAngles(transform, player.angles);
177 
178  // factor -1 allows chaining portals, but may be weird
179  player.right_vector = -1 * AnglesTransform_Apply(transform, player.right_vector);
180 
181  MUTATOR_CALLHOOK(PortalTeleport, player);
182 
183  if (!teleporter.enemy)
184  {
185  backtrace("Portal_TeleportPlayer ended up without other portal being set BEFORE TeleportPlayer. Stop.");
186  return 0;
187  }
188 
189  tdeath_hit = 0;
190  TeleportPlayer(teleporter, player, to, ang, newvel, teleporter.enemy.absmin, teleporter.enemy.absmax, TELEPORT_FLAGS_PORTAL);
191  if(tdeath_hit)
192  {
193  // telefrag within 1 second of portal creation = amazing
194  if(time < teleporter.teleport_time + 1)
195  Send_Notification(NOTIF_ONE, player, MSG_ANNCE, ANNCE_ACHIEVEMENT_AMAZING);
196  }
197  else if(player != portal_owner && IS_PLAYER(portal_owner) && IS_PLAYER(player))
198  {
199  player.pusher = portal_owner;
200  player.pushltime = time + autocvar_g_maxpushtime;
201  player.istypefrag = PHYS_INPUT_BUTTON_CHAT(player);
202  }
203 
204  if (!teleporter.enemy)
205  {
206  backtrace("Portal_TeleportPlayer ended up without other portal being set AFTER TeleportPlayer. Stop.");
207  return 0;
208  }
209 
210  // reset fade counter
211  teleporter.portal_wants_to_vanish = 0;
212  teleporter.fade_time = ((autocvar_g_balance_portal_lifetime >= 0) ? time + autocvar_g_balance_portal_lifetime : 0);
215 
216  return 1;
217 }
218 
220 {
221  vector o;
222  o = portal.origin;
223  portal.mins = PL_MIN_CONST - SAFERNUDGE;
224  portal.maxs = PL_MAX_CONST + SAFERNUDGE;
225  fixedmakevectors(portal.mangle);
226  portal.origin += 16 * v_forward;
227  if(!move_out_of_solid(portal))
228  {
229 #ifdef DEBUG
230  LOG_INFO("NO SAFE ORIGIN");
231 #endif
232  return 0;
233  }
234  portal.portal_safe_origin = portal.origin;
235  setorigin(portal, o);
236  return 1;
237 }
238 
239 float Portal_WillHitPlane(vector eorg, vector emins, vector emaxs, vector evel, vector porg, vector pnorm, float psize)
240 {
241  float dist, distpersec, delta;
242  vector v;
243 
244  dist = (eorg - porg) * pnorm;
245  dist += min(emins.x * pnorm.x, emaxs.x * pnorm.x);
246  dist += min(emins.y * pnorm.y, emaxs.y * pnorm.y);
247  dist += min(emins.z * pnorm.z, emaxs.z * pnorm.z);
248  if(dist < -1) // other side?
249  return 0;
250 #ifdef PORTALS_ARE_NOT_SOLID
251  distpersec = evel * pnorm;
252  if(distpersec >= 0) // going away from the portal?
253  return 0;
254  // we don't need this check with solid portals, them being SOLID_BSP should suffice
255  delta = dist / distpersec;
256  v = eorg - evel * delta - porg;
257  v = v - pnorm * (pnorm * v);
258  return vlen(v) < psize;
259 #else
260  return 1;
261 #endif
262 }
263 
264 void Portal_Touch(entity this, entity toucher)
265 {
266  vector g;
267 
268 #ifdef PORTALS_ARE_NOT_SOLID
269  // portal is being removed?
270  if(this.solid != SOLID_TRIGGER)
271  return; // possibly engine bug
272 
273  if(IS_PLAYER(toucher))
274  return; // handled by think
275 #endif
276 
277  if(toucher.classname == "item_flag_team")
278  return; // never portal these
279 
280  if(toucher.classname == "grapplinghook")
281  return; // handled by think
282 
283  if(!autocvar_g_vehicles_teleportable)
284  if(IS_VEHICLE(toucher))
285  return; // no teleporting vehicles?
286 
287  if(!this.enemy)
288  error("Portal_Touch called for a broken portal\n");
289 
290 #ifdef PORTALS_ARE_NOT_SOLID
291  if(trace_fraction < 1)
292  return; // only handle TouchAreaGrid ones (only these can teleport)
293 #else
294  if(trace_fraction >= 1)
295  return; // only handle impacts
296 #endif
297 
298  if(toucher.classname == "porto")
299  {
300  if(toucher.portal_id == this.portal_id)
301  return;
302  }
303  if(time < this.portal_activatetime)
304  if(toucher == this.aiment)
305  {
306  this.portal_activatetime = time + 0.1;
307  return;
308  }
309  if(toucher != this.aiment)
310  if(IS_PLAYER(toucher))
312  return; // cannot go through someone else's portal
313  if(toucher.aiment != this.aiment)
314  if(IS_PLAYER(toucher.aiment))
315  if(IS_INDEPENDENT_PLAYER(toucher.aiment) || IS_INDEPENDENT_PLAYER(this.aiment))
316  return; // cannot go through someone else's portal
317  fixedmakevectors(this.mangle);
318  g = frametime * '0 0 -1' * autocvar_sv_gravity;
319  if(!Portal_WillHitPlane(toucher.origin, toucher.mins, toucher.maxs, toucher.velocity + g, this.origin, v_forward, this.maxs.x))
320  return;
321 
322  /*
323  if(toucher.mins_x < PL_MIN.x || toucher.mins_y < PL_MIN.y || toucher.mins_z < PL_MIN.z
324  || toucher.maxs_x > PL_MAX.x || toucher.maxs_y > PL_MAX.y || toucher.maxs_z > PL_MAX.z)
325  {
326  // can't teleport this
327  return;
328  }
329  */
330 
331  if(Portal_TeleportPlayer(this, toucher, this.aiment))
332  if(toucher.classname == "porto")
333  if(toucher.effects & EF_RED)
334  toucher.effects += EF_BLUE - EF_RED;
335 }
336 
338 {
339  portal.skin = 2;
340  portal.solid = SOLID_NOT;
341  settouch(portal, func_null);
342  setthink(portal, func_null);
343  portal.effects = 0;
344  portal.nextthink = 0;
345  portal.takedamage = DAMAGE_NO;
346 }
347 
349 {
350  portal.skin = 2;
351  portal.solid = SOLID_NOT;
352  settouch(portal, func_null);
353  setthink(portal, func_null);
354  portal.effects = EF_ADDITIVE;
355  portal.nextthink = 0;
356  portal.takedamage = DAMAGE_YES;
357 }
358 
360 {
361  portal.skin = 0;
362  portal.solid = SOLID_NOT; // this is done when connecting them!
363  settouch(portal, Portal_Touch);
364  setthink(portal, Portal_Think);
365  portal.effects = EF_RED;
366  portal.nextthink = time;
367  portal.takedamage = DAMAGE_NO;
368 }
369 
371 {
372  portal.skin = 1;
373  portal.solid = SOLID_NOT;
374  settouch(portal, func_null);
375  setthink(portal, func_null);
376  portal.effects = EF_STARDUST | EF_BLUE;
377  portal.nextthink = 0;
378  portal.takedamage = DAMAGE_YES;
379 }
380 
381 void Portal_Disconnect(entity teleporter, entity destination)
382 {
383  teleporter.enemy = NULL;
384  destination.enemy = NULL;
385  Portal_MakeBrokenPortal(teleporter);
386  Portal_MakeBrokenPortal(destination);
387 }
388 
389 void Portal_Connect(entity teleporter, entity destination)
390 {
391  teleporter.portal_transform = AnglesTransform_RightDivide(AnglesTransform_TurnDirectionFR(destination.mangle), teleporter.mangle);
392 
393  teleporter.enemy = destination;
394  destination.enemy = teleporter;
395  Portal_MakeInPortal(teleporter);
396  Portal_MakeOutPortal(destination);
397  teleporter.fade_time = ((autocvar_g_balance_portal_lifetime >= 0) ? time + autocvar_g_balance_portal_lifetime : 0);
398  destination.fade_time = teleporter.fade_time;
399  teleporter.portal_wants_to_vanish = 0;
400  destination.portal_wants_to_vanish = 0;
401  teleporter.teleport_time = time;
402 #ifdef PORTALS_ARE_NOT_SOLID
403  teleporter.solid = SOLID_TRIGGER;
404 #else
405  teleporter.solid = SOLID_BSP;
406 #endif
407 }
408 
409 void Portal_Remove(entity portal, float killed)
410 {
411  entity e;
412  e = portal.enemy;
413 
414  if(e)
415  {
416  Portal_Disconnect(portal, e);
417  Portal_Remove(e, killed);
418  }
419 
420  if(portal == portal.aiment.portal_in)
421  portal.aiment.portal_in = NULL;
422  if(portal == portal.aiment.portal_out)
423  portal.aiment.portal_out = NULL;
424  //portal.aiment = NULL;
425 
426  // makes the portal vanish
427  if(killed)
428  {
429  fixedmakevectors(portal.mangle);
430  sound(portal, CH_SHOTS, SND_PORTO_EXPLODE, VOL_BASE, ATTEN_NORM);
431  Send_Effect(EFFECT_ROCKET_EXPLODE, portal.origin + v_forward * 16, v_forward * 1024, 4);
432  delete(portal);
433  }
434  else
435  {
436  Portal_MakeBrokenPortal(portal);
437  sound(portal, CH_SHOTS, SND_PORTO_EXPIRE, VOL_BASE, ATTEN_NORM);
438  SUB_SetFade(portal, time, 0.5);
439  }
440 }
441 
442 void Portal_Damage(entity this, entity inflictor, entity attacker, float damage, int deathtype, .entity weaponentity, vector hitloc, vector force)
443 {
444  if(deathtype == DEATH_TELEFRAG.m_id)
445  return;
446  if(attacker != this.aiment)
447  if(IS_INDEPENDENT_PLAYER(attacker) || IS_INDEPENDENT_PLAYER(this.aiment))
448  return;
449  TakeResource(this, RES_HEALTH, damage);
450  if(GetResource(this, RES_HEALTH) < 0)
451  Portal_Remove(this, 1);
452 }
453 
455 {
456  if(!Portal_WillHitPlane(e.origin, e.mins, e.maxs, e.velocity + g, this.origin, v_forward, this.maxs.x))
457  return;
458 
459  // if e would hit the portal in a frame...
460  // already teleport him
461  tracebox(e.origin, e.mins, e.maxs, e.origin + e.velocity * 2 * frametime, MOVE_NORMAL, e);
462  if(trace_ent == this)
463  Portal_TeleportPlayer(this, e, portal_owner);
464 }
465 
467 {
468  entity o;
469  vector g;
470 
471 #ifdef PORTALS_ARE_NOT_SOLID
472  // portal is being removed?
473  if(this.solid != SOLID_TRIGGER)
474  return; // possibly engine bug
475 
476  if(!this.enemy)
477  error("Portal_Think called for a broken portal\n");
478 
479  o = this.aiment;
480  this.solid = SOLID_BBOX;
481  this.aiment = NULL;
482 
483  g = frametime * '0 0 -1' * autocvar_sv_gravity;
484 
485  fixedmakevectors(this.mangle);
486 
488  if(it != o)
490  continue; // cannot go through someone else's portal
491 
492  if(it != o || time >= this.portal_activatetime)
493  Portal_Think_TryTeleportPlayer(this, it, g, o);
494 
495  for(int slot = 0; slot < MAX_WEAPONSLOTS; ++slot)
496  {
497  .entity weaponentity = weaponentities[slot];
498  if(it.(weaponentity).hook)
499  Portal_Think_TryTeleportPlayer(this, it.(weaponentity).hook, g, o);
500  }
501  });
502  this.solid = SOLID_TRIGGER;
503  this.aiment = o;
504 #endif
505 
506  this.nextthink = time;
507 
508  if(this.fade_time && time > this.fade_time)
509  Portal_Remove(this, 0);
510 }
511 
512 bool Portal_Customize(entity this, entity client)
513 {
514  if(IS_SPEC(client))
515  client = client.enemy;
516  if(client == this.aiment)
517  {
518  this.modelindex = this.savemodelindex;
519  }
520  else if(IS_INDEPENDENT_PLAYER(client) || IS_INDEPENDENT_PLAYER(this.aiment))
521  {
522  this.modelindex = 0;
523  }
524  else
525  {
526  this.modelindex = this.savemodelindex;
527  }
528  return true;
529 }
530 
531 // cleanup:
532 // when creating in-portal:
533 // disconnect
534 // clear existing in-portal
535 // set as in-portal
536 // connect
537 // when creating out-portal:
538 // disconnect
539 // clear existing out-portal
540 // set as out-portal
541 // when player dies:
542 // disconnect portals
543 // clear both portals
544 // after timeout of in-portal:
545 // disconnect portals
546 // clear both portals
547 // TODO: ensure only one portal shot at once
548 float Portal_SetInPortal(entity own, entity portal)
549 {
550  if(own.portal_in)
551  {
552  if(own.portal_out)
553  Portal_Disconnect(own.portal_in, own.portal_out);
554  Portal_Remove(own.portal_in, 0);
555  }
556  own.portal_in = portal;
557  if(own.portal_out)
558  {
559  own.portal_out.portal_id = portal.portal_id;
560  Portal_Connect(own.portal_in, own.portal_out);
561  }
562  return 2;
563 }
565 {
566  if(own.portal_out)
567  {
568  if(own.portal_in)
569  Portal_Disconnect(own.portal_in, own.portal_out);
570  Portal_Remove(own.portal_out, 0);
571  }
572  own.portal_out = portal;
573  if(own.portal_in)
574  {
575  own.portal_in.portal_id = portal.portal_id;
576  Portal_Connect(own.portal_in, own.portal_out);
577  }
578  return 1;
579 }
581 {
582  if(own.portal_in)
583  Portal_Remove(own.portal_in, 0);
584  if(own.portal_out)
585  Portal_Remove(own.portal_out, 0);
586 }
588 {
590  W_Porto_Remove(own);
591 }
593 {
594  Portal_Remove(this, this.cnt);
595 }
596 void Portal_RemoveLater(entity portal, float kill)
597 {
598  Portal_MakeBrokenPortal(portal);
599  portal.cnt = kill;
601  portal.nextthink = time;
602 }
604 {
605  if(own.portal_in)
606  Portal_RemoveLater(own.portal_in, 0);
607  if(own.portal_out)
608  Portal_RemoveLater(own.portal_out, 0);
609 }
611 {
613  W_Porto_Remove(own);
614 }
615 void Portal_ClearWithID(entity own, float id)
616 {
617  if(own.portal_in)
618  if(own.portal_in.portal_id == id)
619  {
620  if(own.portal_out)
621  Portal_Disconnect(own.portal_in, own.portal_out);
622  Portal_Remove(own.portal_in, 0);
623  }
624  if(own.portal_out)
625  if(own.portal_out.portal_id == id)
626  {
627  if(own.portal_in)
628  Portal_Disconnect(own.portal_in, own.portal_out);
629  Portal_Remove(own.portal_out, 0);
630  }
631 }
632 
634 {
635  entity portal;
636 
637  fixedmakevectors(ang);
638  if(!CheckWireframeBox(own, org - 48 * v_right - 48 * v_up + 16 * v_forward, 96 * v_right, 96 * v_up, 96 * v_forward))
639  return NULL;
640 
641  portal = new(portal);
642  portal.aiment = own;
643  setorigin(portal, org);
644  portal.mangle = ang;
645  portal.angles = ang;
646  portal.angles_x = -portal.angles.x; // is a bmodel
647  setthink(portal, Portal_Think);
648  portal.nextthink = 0;
649  portal.portal_activatetime = time + 0.1;
650  portal.takedamage = DAMAGE_AIM;
651  portal.event_damage = Portal_Damage;
654  setmodel(portal, MDL_PORTAL);
655  portal.savemodelindex = portal.modelindex;
656  setcefc(portal, Portal_Customize);
657 
658  if(!Portal_FindSafeOrigin(portal))
659  {
660  delete(portal);
661  return NULL;
662  }
663 
664  setsize(portal, '-48 -48 -48', '48 48 48');
665  Portal_MakeWaitingPortal(portal);
666 
667  return portal;
668 }
669 
670 float Portal_SpawnInPortalAtTrace(entity own, vector dir, float portal_id_val)
671 {
672  entity portal;
673  vector ang;
674  vector org;
675 
676  org = trace_endpos;
678  fixedmakevectors(ang);
679 
680  portal = Portal_Spawn(own, org, ang);
681  if(!portal)
682  return 0;
683 
684  portal.portal_id = portal_id_val;
685  Portal_SetInPortal(own, portal);
686 
687  return 1;
688 }
689 
690 float Portal_SpawnOutPortalAtTrace(entity own, vector dir, float portal_id_val)
691 {
692  entity portal;
693  vector ang;
694  vector org;
695 
696  org = trace_endpos;
698  fixedmakevectors(ang);
699 
700  portal = Portal_Spawn(own, org, ang);
701  if(!portal)
702  return 0;
703 
704  portal.portal_id = portal_id_val;
705  Portal_SetOutPortal(own, portal);
706 
707  return 1;
708 }
const float SOLID_NOT
Definition: csprogsdefs.qc:244
void Portal_MakeWaitingPortal(entity portal)
Definition: portals.qc:348
void Portal_MakeInPortal(entity portal)
Definition: portals.qc:359
#define PHYS_INPUT_BUTTON_CHAT(s)
Definition: player.qh:155
float Portal_WillHitPlane(vector eorg, vector emins, vector emaxs, vector evel, vector porg, vector pnorm, float psize)
Definition: portals.qc:239
#define fixedvectoangles(a)
void Portal_ClearAllLater(entity own)
Definition: portals.qc:610
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
bool Portal_Customize(entity this, entity client)
Definition: portals.qc:512
float portal_wants_to_vanish
Definition: portals.qc:33
float modelindex
Definition: csprogsdefs.qc:91
float Portal_FindSafeOrigin(entity portal)
Definition: portals.qc:219
#define IS_INDEPENDENT_PLAYER(e)
Definition: client.qh:314
entity() spawn
float DAMAGE_AIM
Definition: progsdefs.qc:284
#define vec3(_x, _y, _z)
Definition: vector.qh:95
const float MOVE_NORMAL
Definition: csprogsdefs.qc:252
#define FOREACH_CLIENT(cond, body)
Definition: utils.qh:49
float autocvar_g_balance_portal_health
Definition: portals.qh:3
float Portal_TeleportPlayer(entity teleporter, entity player, entity portal_owner)
Definition: portals.qc:111
float PlayerEdgeDistance(entity p, vector v)
Definition: portals.qc:37
void Portal_Disconnect(entity teleporter, entity destination)
Definition: portals.qc:381
void Portal_MakeBrokenPortal(entity portal)
Definition: portals.qc:337
entity to
Definition: self.qh:96
void Portal_Think_TryTeleportPlayer(entity this, entity e, vector g, entity portal_owner)
Definition: portals.qc:454
#define move_out_of_solid(e)
Definition: common.qh:110
float autocvar_g_maxpushtime
Definition: damage.qh:17
vector AnglesTransform_RightDivide(vector to_transform, vector from_transform)
entity trace_ent
Definition: csprogsdefs.qc:40
void TakeResource(entity receiver, Resource res_type, float amount)
Takes an entity some resource.
Definition: cl_resources.qc:31
const float EF_ADDITIVE
Definition: csprogsdefs.qc:300
#define setmodel(this, m)
Definition: model.qh:26
vector portal_transform
Definition: portals.qc:31
RES_HEALTH
Definition: ent_cs.qc:126
void Portal_Remove(entity portal, float killed)
Definition: portals.qc:409
#define IS_SPEC(v)
Definition: utils.qh:10
void Portal_Connect(entity teleporter, entity destination)
Definition: portals.qc:389
vector AnglesTransform_TurnDirectionFR(vector transform)
entity enemy
Definition: sv_ctf.qh:143
void Portal_MakeOutPortal(entity portal)
Definition: portals.qc:370
const float MOVE_NOMONSTERS
Definition: csprogsdefs.qc:253
float cnt
Definition: powerups.qc:24
void Portal_ClearAll(entity own)
Definition: portals.qc:587
const float EF_BLUE
Definition: csprogsdefs.qc:301
vector v_up
Definition: csprogsdefs.qc:31
const int MAX_WEAPONSLOTS
Definition: weapon.qh:13
void Portal_Touch(entity this, entity toucher)
Definition: portals.qc:264
#define NULL
Definition: post.qh:17
float frametime
Definition: csprogsdefs.qc:17
#define LOG_INFO(...)
Definition: log.qh:70
void Portal_ClearWithID(entity own, float id)
Definition: portals.qc:615
void Portal_RemoveLater(entity portal, float kill)
Definition: portals.qc:596
#define backtrace(msg)
Definition: log.qh:105
const float VOL_BASE
Definition: sound.qh:36
void Portal_ClearAllLater_PortalsOnly(entity own)
Definition: portals.qc:603
vector portal_safe_origin
Definition: portals.qc:32
void Portal_Damage(entity this, entity inflictor, entity attacker, float damage, int deathtype,.entity weaponentity, vector hitloc, vector force)
Definition: portals.qc:442
vector trace_endpos
Definition: csprogsdefs.qc:37
vector AnglesTransform_ApplyToAngles(vector transform, vector v)
float Portal_SetOutPortal(entity own, entity portal)
Definition: portals.qc:564
const float ATTEN_NORM
Definition: sound.qh:30
float nextthink
Definition: csprogsdefs.qc:121
vector Portal_ApplyTransformToPlayerAngle(vector transform, vector vangle)
Definition: portals.qc:47
const int CH_SHOTS
Definition: sound.qh:14
entity Portal_Spawn(entity own, vector org, vector ang)
Definition: portals.qc:633
vector(float skel, float bonenum) _skel_get_boneabs_hidden
#define IS_VEHICLE(v)
Definition: utils.qh:22
float Portal_SpawnOutPortalAtTrace(entity own, vector dir, float portal_id_val)
Definition: portals.qc:690
const float EF_RED
Definition: csprogsdefs.qc:307
vector v
Definition: ent_cs.qc:116
float GetResource(entity e, Resource res_type)
Returns the current amount of resource the given entity has.
Definition: cl_resources.qc:10
const float SOLID_BSP
Definition: csprogsdefs.qc:248
void Portal_RemoveLater_Think(entity this)
Definition: portals.qc:592
float Portal_SetInPortal(entity own, entity portal)
Definition: portals.qc:548
float fade_time
Definition: common.qh:22
const vector SAFERNUDGE
Definition: portals.qc:29
const float SOLID_TRIGGER
Definition: csprogsdefs.qc:245
vector v_right
Definition: csprogsdefs.qc:31
#define MUTATOR_CALLHOOK(id,...)
Definition: base.qh:140
entity aiment
Definition: movetypes.qh:90
const float SOLID_BBOX
Definition: csprogsdefs.qc:246
entity weaponentities[MAX_WEAPONSLOTS]
Definition: weapon.qh:14
vector mangle
Definition: subs.qh:51
setorigin(ent, v)
float autocvar_g_balance_portal_lifetime
Definition: portals.qh:4
#define setthink(e, f)
void Portal_ClearAll_PortalsOnly(entity own)
Definition: portals.qc:580
vector trace_plane_normal
Definition: csprogsdefs.qc:38
const vector SAFENUDGE
Definition: portals.qc:28
void SUB_SetFade(entity ent, float vanish_time, float fading_time)
Definition: subs.qc:77
float trace_startsolid
Definition: csprogsdefs.qc:35
#define TELEPORT_FLAGS_PORTAL
Definition: teleporters.qh:21
void Portal_Think(entity this)
Definition: portals.qc:466
#define sound(e, c, s, v, a)
Definition: sound.qh:52
vector AnglesTransform_Apply(vector transform, vector v)
float time
Definition: csprogsdefs.qc:16
float Portal_SpawnInPortalAtTrace(entity own, vector dir, float portal_id_val)
Definition: portals.qc:670
vector right_vector
Definition: portals.qc:110
float portal_activatetime
Definition: portals.qc:34
int dir
Definition: impulse.qc:89
void TeleportPlayer(entity teleporter, entity player, vector to, vector to_angles, vector to_velocity, vector telefragmin, vector telefragmax, float tflags)
Definition: teleporters.qc:67
float trace_fraction
Definition: csprogsdefs.qc:36
float DAMAGE_NO
Definition: progsdefs.qc:282
#define fixedmakevectors
float savemodelindex
Definition: portals.qc:35
#define IS_PLAYER(v)
Definition: utils.qh:9
const float EF_STARDUST
Definition: csprogsdefs.qc:308
var void func_null()
#define fixedvectoangles2(a, b)
vector v_forward
Definition: csprogsdefs.qc:31
float solid
Definition: csprogsdefs.qc:99
float DAMAGE_YES
Definition: progsdefs.qc:283