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;
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
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
111float 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);
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);
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);
214 SetResourceExplicit(teleporter.enemy, RES_HEALTH, autocvar_g_balance_portal_health);
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
239float 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
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
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))
316 return; // cannot go through someone else's portal
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 = (toucher.effects & ~EF_RED) | EF_BLUE;
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
381void 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
389void 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 setorigin(teleporter, teleporter.origin); // link it to the area grid
408}
409
410void Portal_Remove(entity portal, float killed)
411{
412 entity e;
413 e = portal.enemy;
414
415 if(e)
416 {
417 Portal_Disconnect(portal, e);
418 Portal_Remove(e, killed);
419 }
420
421 if(portal == portal.aiment.portal_in)
422 portal.aiment.portal_in = NULL;
423 if(portal == portal.aiment.portal_out)
424 portal.aiment.portal_out = NULL;
425 //portal.aiment = NULL;
426
427 // makes the portal vanish
428 if(killed)
429 {
430 fixedmakevectors(portal.mangle);
431 sound(portal, CH_SHOTS, SND_PORTO_EXPLODE, VOL_BASE, ATTEN_NORM);
432 Send_Effect(EFFECT_ROCKET_EXPLODE, portal.origin + v_forward * 16, v_forward * 1024, 4);
433 delete(portal);
434 }
435 else
436 {
438 sound(portal, CH_SHOTS, SND_PORTO_EXPIRE, VOL_BASE, ATTEN_NORM);
439 SUB_SetFade(portal, time, 0.5);
440 }
441}
442
443void Portal_Damage(entity this, entity inflictor, entity attacker, float damage, int deathtype, .entity weaponentity, vector hitloc, vector force)
444{
445 if(deathtype == DEATH_TELEFRAG.m_id)
446 return;
447 if(attacker != this.aiment)
449 return;
450 TakeResource(this, RES_HEALTH, damage);
451 if(GetResource(this, RES_HEALTH) < 0)
452 Portal_Remove(this, 1);
453}
454
456{
457 if(!Portal_WillHitPlane(e.origin, e.mins, e.maxs, e.velocity + g, this.origin, v_forward, this.maxs.x))
458 return;
459
460 // if e would hit the portal in a frame...
461 // already teleport him
462 tracebox(e.origin, e.mins, e.maxs, e.origin + e.velocity * 2 * frametime, MOVE_NORMAL, e);
463 if(trace_ent == this)
464 Portal_TeleportPlayer(this, e, portal_owner);
465}
466
468{
469 entity o;
470 vector g;
471
472#ifdef PORTALS_ARE_NOT_SOLID
473 // portal is being removed?
474 if(this.solid != SOLID_TRIGGER)
475 return; // possibly engine bug
476
477 if(!this.enemy)
478 error("Portal_Think called for a broken portal\n");
479
480 o = this.aiment;
481 this.solid = SOLID_BBOX;
482 this.aiment = NULL;
483
484 g = frametime * '0 0 -1' * autocvar_sv_gravity;
485
487
489 if(it != o)
491 continue; // cannot go through someone else's portal
492
493 if(it != o || time >= this.portal_activatetime)
494 Portal_Think_TryTeleportPlayer(this, it, g, o);
495
496 for(int slot = 0; slot < MAX_WEAPONSLOTS; ++slot)
497 {
498 .entity weaponentity = weaponentities[slot];
499 if(it.(weaponentity).hook)
500 Portal_Think_TryTeleportPlayer(this, it.(weaponentity).hook, g, o);
501 }
502 });
503 this.solid = SOLID_TRIGGER;
504 this.aiment = o;
505#endif
506
507 this.nextthink = time;
508
509 if(this.fade_time && time > this.fade_time)
510 Portal_Remove(this, 0);
511}
512
514{
515 if(IS_SPEC(client))
516 client = client.enemy;
517 if(client == this.aiment)
518 {
519 this.modelindex = this.savemodelindex;
520 }
521 else if(IS_INDEPENDENT_PLAYER(client) || IS_INDEPENDENT_PLAYER(this.aiment))
522 {
523 this.modelindex = 0;
524 }
525 else
526 {
527 this.modelindex = this.savemodelindex;
528 }
529 return true;
530}
531
532// cleanup:
533// when creating in-portal:
534// disconnect
535// clear existing in-portal
536// set as in-portal
537// connect
538// when creating out-portal:
539// disconnect
540// clear existing out-portal
541// set as out-portal
542// when player dies:
543// disconnect portals
544// clear both portals
545// after timeout of in-portal:
546// disconnect portals
547// clear both portals
548// TODO: ensure only one portal shot at once
550{
551 if(own.portal_in)
552 {
553 if(own.portal_out)
554 Portal_Disconnect(own.portal_in, own.portal_out);
555 Portal_Remove(own.portal_in, 0);
556 }
557 own.portal_in = portal;
558 if(own.portal_out)
559 {
560 own.portal_out.portal_id = portal.portal_id;
561 Portal_Connect(own.portal_in, own.portal_out);
562 }
563 return 2;
564}
566{
567 if(own.portal_out)
568 {
569 if(own.portal_in)
570 Portal_Disconnect(own.portal_in, own.portal_out);
571 Portal_Remove(own.portal_out, 0);
572 }
573 own.portal_out = portal;
574 if(own.portal_in)
575 {
576 own.portal_in.portal_id = portal.portal_id;
577 Portal_Connect(own.portal_in, own.portal_out);
578 }
579 return 1;
580}
582{
583 if(own.portal_in)
584 Portal_Remove(own.portal_in, 0);
585 if(own.portal_out)
586 Portal_Remove(own.portal_out, 0);
587}
589{
591 W_Porto_Remove(own);
592}
594{
595 Portal_Remove(this, this.cnt);
596}
597void Portal_RemoveLater(entity portal, float kill)
598{
600 portal.cnt = kill;
602 portal.nextthink = time;
603}
605{
606 if(own.portal_in)
607 Portal_RemoveLater(own.portal_in, 0);
608 if(own.portal_out)
609 Portal_RemoveLater(own.portal_out, 0);
610}
616void Portal_ClearWithID(entity own, float id)
617{
618 if(own.portal_in)
619 if(own.portal_in.portal_id == id)
620 {
621 if(own.portal_out)
622 Portal_Disconnect(own.portal_in, own.portal_out);
623 Portal_Remove(own.portal_in, 0);
624 }
625 if(own.portal_out)
626 if(own.portal_out.portal_id == id)
627 {
628 if(own.portal_in)
629 Portal_Disconnect(own.portal_in, own.portal_out);
630 Portal_Remove(own.portal_out, 0);
631 }
632}
633
635{
636 entity portal;
637
639 if(!CheckWireframeBox(own, org - 48 * v_right - 48 * v_up + 16 * v_forward, 96 * v_right, 96 * v_up, 96 * v_forward))
640 return NULL;
641
642 portal = new(portal);
643 portal.aiment = own;
644 setorigin(portal, org);
645 portal.mangle = ang;
646 portal.angles = ang;
647 portal.angles_x = -portal.angles.x; // is a bmodel
648 setthink(portal, Portal_Think);
649 portal.nextthink = 0;
650 portal.portal_activatetime = time + 0.1;
651 portal.takedamage = DAMAGE_AIM;
652 portal.event_damage = Portal_Damage;
655 setmodel(portal, MDL_PORTAL);
656 portal.savemodelindex = portal.modelindex;
657 setcefc(portal, Portal_Customize);
658
659 if(!Portal_FindSafeOrigin(portal))
660 {
661 delete(portal);
662 return NULL;
663 }
664
665 setsize(portal, '-48 -48 -48', '48 48 48');
667
668 return portal;
669}
670
671float Portal_SpawnInPortalAtTrace(entity own, vector dir, float portal_id_val)
672{
673 entity portal;
674 vector ang;
675 vector org;
676
680
681 portal = Portal_Spawn(own, org, ang);
682 if(!portal)
683 return 0;
684
685 portal.portal_id = portal_id_val;
686 Portal_SetInPortal(own, portal);
687
688 return 1;
689}
690
691float Portal_SpawnOutPortalAtTrace(entity own, vector dir, float portal_id_val)
692{
693 entity portal;
694 vector ang;
695 vector org;
696
700
701 portal = Portal_Spawn(own, org, ang);
702 if(!portal)
703 return 0;
704
705 portal.portal_id = portal_id_val;
706 Portal_SetOutPortal(own, portal);
707
708 return 1;
709}
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:159
#define IS_PLAYER(s)
Definition player.qh:243
#define autocvar_sv_gravity
Definition stats.qh:421
float CheckWireframeBox(entity forent, vector v0, vector dvx, vector dvy, vector dvz)
Definition util.qc:582
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:124
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)
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:467
float Portal_WillHitPlane(vector eorg, vector emins, vector emaxs, vector evel, vector porg, vector pnorm, float psize)
Definition portals.qc:239
void Portal_Remove(entity portal, float killed)
Definition portals.qc:410
float savemodelindex
Definition portals.qc:35
float Portal_TeleportPlayer(entity teleporter, entity player, entity portal_owner)
Definition portals.qc:111
float Portal_SetInPortal(entity own, entity portal)
Definition portals.qc:549
float portal_wants_to_vanish
Definition portals.qc:33
void Portal_ClearAllLater(entity own)
Definition portals.qc:611
entity Portal_Spawn(entity own, vector org, vector ang)
Definition portals.qc:634
void Portal_Disconnect(entity teleporter, entity destination)
Definition portals.qc:381
void Portal_MakeOutPortal(entity portal)
Definition portals.qc:370
float Portal_SpawnOutPortalAtTrace(entity own, vector dir, float portal_id_val)
Definition portals.qc:691
float Portal_FindSafeOrigin(entity portal)
Definition portals.qc:219
float PlayerEdgeDistance(entity p, vector v)
Definition portals.qc:37
void Portal_ClearAll(entity own)
Definition portals.qc:588
void Portal_Damage(entity this, entity inflictor, entity attacker, float damage, int deathtype,.entity weaponentity, vector hitloc, vector force)
Definition portals.qc:443
void Portal_MakeInPortal(entity portal)
Definition portals.qc:359
void Portal_ClearWithID(entity own, float id)
Definition portals.qc:616
void Portal_Think_TryTeleportPlayer(entity this, entity e, vector g, entity portal_owner)
Definition portals.qc:455
float portal_activatetime
Definition portals.qc:34
void Portal_MakeWaitingPortal(entity portal)
Definition portals.qc:348
void Portal_Connect(entity teleporter, entity destination)
Definition portals.qc:389
void Portal_ClearAll_PortalsOnly(entity own)
Definition portals.qc:581
float Portal_SpawnInPortalAtTrace(entity own, vector dir, float portal_id_val)
Definition portals.qc:671
bool Portal_Customize(entity this, entity client)
Definition portals.qc:513
void Portal_MakeBrokenPortal(entity portal)
Definition portals.qc:337
vector portal_transform
Definition portals.qc:31
void Portal_RemoveLater(entity portal, float kill)
Definition portals.qc:597
const vector SAFENUDGE
Definition portals.qc:28
const vector SAFERNUDGE
Definition portals.qc:29
void Portal_ClearAllLater_PortalsOnly(entity own)
Definition portals.qc:604
void Portal_RemoveLater_Think(entity this)
Definition portals.qc:593
void Portal_Touch(entity this, entity toucher)
Definition portals.qc:264
float Portal_SetOutPortal(entity own, entity portal)
Definition portals.qc:565
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:146
vector right_vector
Definition porto.qh:64
#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:50
#define IS_VEHICLE(v)
Definition utils.qh:22
#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