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' * PHYS_GRAVITY(toucher);
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
485
487 {
488 if(it != o)
490 continue; // cannot go through someone else's portal
491
492 g = frametime * '0 0 -1' * PHYS_GRAVITY(it);
493
494 if(it != o || time >= this.portal_activatetime)
495 Portal_Think_TryTeleportPlayer(this, it, g, o);
496
497 for(int slot = 0; slot < MAX_WEAPONSLOTS; ++slot)
498 {
499 .entity weaponentity = weaponentities[slot];
500 if(it.(weaponentity).hook)
501 Portal_Think_TryTeleportPlayer(this, it.(weaponentity).hook, g, o);
502 }
503 });
504 this.solid = SOLID_TRIGGER;
505 this.aiment = o;
506#endif
507
508 this.nextthink = time;
509
510 if(this.fade_time && time > this.fade_time)
511 Portal_Remove(this, 0);
512}
513
515{
516 if(IS_SPEC(client))
517 client = client.enemy;
518 if(client == this.aiment)
519 {
520 this.modelindex = this.savemodelindex;
521 }
522 else if(IS_INDEPENDENT_PLAYER(client) || IS_INDEPENDENT_PLAYER(this.aiment))
523 {
524 this.modelindex = 0;
525 }
526 else
527 {
528 this.modelindex = this.savemodelindex;
529 }
530 return true;
531}
532
533// cleanup:
534// when creating in-portal:
535// disconnect
536// clear existing in-portal
537// set as in-portal
538// connect
539// when creating out-portal:
540// disconnect
541// clear existing out-portal
542// set as out-portal
543// when player dies:
544// disconnect portals
545// clear both portals
546// after timeout of in-portal:
547// disconnect portals
548// clear both portals
549// TODO: ensure only one portal shot at once
551{
552 if(own.portal_in)
553 {
554 if(own.portal_out)
555 Portal_Disconnect(own.portal_in, own.portal_out);
556 Portal_Remove(own.portal_in, 0);
557 }
558 own.portal_in = portal;
559 if(own.portal_out)
560 {
561 own.portal_out.portal_id = portal.portal_id;
562 Portal_Connect(own.portal_in, own.portal_out);
563 }
564 return 2;
565}
567{
568 if(own.portal_out)
569 {
570 if(own.portal_in)
571 Portal_Disconnect(own.portal_in, own.portal_out);
572 Portal_Remove(own.portal_out, 0);
573 }
574 own.portal_out = portal;
575 if(own.portal_in)
576 {
577 own.portal_in.portal_id = portal.portal_id;
578 Portal_Connect(own.portal_in, own.portal_out);
579 }
580 return 1;
581}
583{
584 if(own.portal_in)
585 Portal_Remove(own.portal_in, 0);
586 if(own.portal_out)
587 Portal_Remove(own.portal_out, 0);
588}
590{
592 W_Porto_Remove(own);
593}
595{
596 Portal_Remove(this, this.cnt);
597}
598void Portal_RemoveLater(entity portal, float kill)
599{
601 portal.cnt = kill;
603 portal.nextthink = time;
604}
606{
607 if(own.portal_in)
608 Portal_RemoveLater(own.portal_in, 0);
609 if(own.portal_out)
610 Portal_RemoveLater(own.portal_out, 0);
611}
617void Portal_ClearWithID(entity own, float id)
618{
619 if(own.portal_in)
620 if(own.portal_in.portal_id == id)
621 {
622 if(own.portal_out)
623 Portal_Disconnect(own.portal_in, own.portal_out);
624 Portal_Remove(own.portal_in, 0);
625 }
626 if(own.portal_out)
627 if(own.portal_out.portal_id == id)
628 {
629 if(own.portal_in)
630 Portal_Disconnect(own.portal_in, own.portal_out);
631 Portal_Remove(own.portal_out, 0);
632 }
633}
634
636{
637 entity portal;
638
640 if(!CheckWireframeBox(own, org - 48 * v_right - 48 * v_up + 16 * v_forward, 96 * v_right, 96 * v_up, 96 * v_forward))
641 return NULL;
642
643 portal = new(portal);
644 portal.aiment = own;
645 setorigin(portal, org);
646 portal.mangle = ang;
647 portal.angles = ang;
648 portal.angles_x = -portal.angles.x; // is a bmodel
649 setthink(portal, Portal_Think);
650 portal.nextthink = 0;
651 portal.portal_activatetime = time + 0.1;
652 portal.takedamage = DAMAGE_AIM;
653 portal.event_damage = Portal_Damage;
656 setmodel(portal, MDL_PORTAL);
657 portal.savemodelindex = portal.modelindex;
658 setcefc(portal, Portal_Customize);
659
660 if(!Portal_FindSafeOrigin(portal))
661 {
662 delete(portal);
663 return NULL;
664 }
665
666 setsize(portal, '-48 -48 -48', '48 48 48');
668
669 return portal;
670}
671
672float Portal_SpawnInPortalAtTrace(entity own, vector dir, float portal_id_val)
673{
674 entity portal;
675 vector ang;
676 vector org;
677
681
682 portal = Portal_Spawn(own, org, ang);
683 if(!portal)
684 return 0;
685
686 portal.portal_id = portal_id_val;
687 Portal_SetInPortal(own, portal);
688
689 return 1;
690}
691
692float Portal_SpawnOutPortalAtTrace(entity own, vector dir, float portal_id_val)
693{
694 entity portal;
695 vector ang;
696 vector org;
697
701
702 portal = Portal_Spawn(own, org, ang);
703 if(!portal)
704 return 0;
705
706 portal.portal_id = portal_id_val;
707 Portal_SetOutPortal(own, portal);
708
709 return 1;
710}
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: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)
#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: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:550
float portal_wants_to_vanish
Definition portals.qc:33
void Portal_ClearAllLater(entity own)
Definition portals.qc:612
entity Portal_Spawn(entity own, vector org, vector ang)
Definition portals.qc:635
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:692
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:589
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:617
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:582
float Portal_SpawnInPortalAtTrace(entity own, vector dir, float portal_id_val)
Definition portals.qc:672
bool Portal_Customize(entity this, entity client)
Definition portals.qc:514
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:598
const vector SAFENUDGE
Definition portals.qc:28
const vector SAFERNUDGE
Definition portals.qc:29
void Portal_ClearAllLater_PortalsOnly(entity own)
Definition portals.qc:605
void Portal_RemoveLater_Think(entity this)
Definition portals.qc:594
void Portal_Touch(entity this, entity toucher)
Definition portals.qc:264
float Portal_SetOutPortal(entity own, entity portal)
Definition portals.qc:566
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: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