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