.float ltime;
.void() blocked;
-void _Movetype_VectorAngles_FLU(vector myangles)
+void _Movetype_AngleVectorsFLU(vector myangles) // AngleVectorsFLU
{
float angle, sr, sp, sy, cr, cp, cy;
a = -moveangle;
// sets v_forward, v_right and v_up
- _Movetype_VectorAngles_FLU(a);
+ _Movetype_AngleVectorsFLU(a);
pushorig = self.move_origin;
pushang = self.move_angles;
}
// destructible walls that can be used to trigger target_objective_decrease
-void spawnfunc_func_breakable() {
+void spawnfunc_func_breakable()
+{
float n, i;
if(!self.health)
self.health = 100;
--- /dev/null
+#ifndef TRIGGERS_FUNC_BREAKABLE_H
+#define TRIGGERS_FUNC_BREAKABLE_H
+
+#ifdef SVQC
+void spawnfunc_func_breakable();
+#endif
+
+#endif
WriteByte(MSG_ENTITY, ENT_CLIENT_LADDER);
WriteString(MSG_ENTITY, self.classname);
- WriteByte(MSG_ENTITY, self.warpzone_isboxy);
WriteByte(MSG_ENTITY, self.skin);
WriteByte(MSG_ENTITY, self.speed);
- WriteByte(MSG_ENTITY, self.scale);
- WriteCoord(MSG_ENTITY, self.origin_x);
- WriteCoord(MSG_ENTITY, self.origin_y);
- WriteCoord(MSG_ENTITY, self.origin_z);
- WriteCoord(MSG_ENTITY, self.mins_x);
- WriteCoord(MSG_ENTITY, self.mins_y);
- WriteCoord(MSG_ENTITY, self.mins_z);
- WriteCoord(MSG_ENTITY, self.maxs_x);
- WriteCoord(MSG_ENTITY, self.maxs_y);
- WriteCoord(MSG_ENTITY, self.maxs_z);
-
- WriteCoord(MSG_ENTITY, self.movedir_x);
- WriteCoord(MSG_ENTITY, self.movedir_y);
- WriteCoord(MSG_ENTITY, self.movedir_z);
-
- WriteCoord(MSG_ENTITY, self.angles_x);
- WriteCoord(MSG_ENTITY, self.angles_y);
- WriteCoord(MSG_ENTITY, self.angles_z);
+ trigger_common_write(false);
return true;
}
void ent_func_ladder()
{
self.classname = strzone(ReadString());
- self.warpzone_isboxy = ReadByte();
self.skin = ReadByte();
self.speed = ReadByte();
- self.scale = ReadByte();
- self.origin_x = ReadCoord();
- self.origin_y = ReadCoord();
- self.origin_z = ReadCoord();
- setorigin(self, self.origin);
- self.mins_x = ReadCoord();
- self.mins_y = ReadCoord();
- self.mins_z = ReadCoord();
- self.maxs_x = ReadCoord();
- self.maxs_y = ReadCoord();
- self.maxs_z = ReadCoord();
- setsize(self, self.mins, self.maxs);
- self.movedir_x = ReadCoord();
- self.movedir_y = ReadCoord();
- self.movedir_z = ReadCoord();
- self.angles_x = ReadCoord();
- self.angles_y = ReadCoord();
- self.angles_z = ReadCoord();
+
+ trigger_common_read(false);
self.solid = SOLID_TRIGGER;
self.draw = trigger_draw_generic;
self.trigger_touch = func_ladder_touch;
self.drawmask = MASK_NORMAL;
self.move_time = time;
+ self.entremove = trigger_remove_generic;
}
#endif
#ifdef SVQC
void plat_delayedinit()
{
- plat_spawn_inside_trigger (); // the "start moving" trigger
+ plat_spawn_inside_trigger(); // the "start moving" trigger
}
float plat_send(entity to, float sf)
if(sf & SF_TRIGGER_INIT)
{
WriteShort(MSG_ENTITY, num_for_edict(self));
- WriteString(MSG_ENTITY, self.target);
- WriteString(MSG_ENTITY, self.target2);
- WriteString(MSG_ENTITY, self.target3);
- WriteString(MSG_ENTITY, self.target4);
- WriteString(MSG_ENTITY, self.targetname);
WriteByte(MSG_ENTITY, self.platmovetype_start);
WriteByte(MSG_ENTITY, self.platmovetype_turn);
WriteByte(MSG_ENTITY, self.platmovetype_end);
- WriteCoord(MSG_ENTITY, self.origin_x);
- WriteCoord(MSG_ENTITY, self.origin_y);
- WriteCoord(MSG_ENTITY, self.origin_z);
-
WriteString(MSG_ENTITY, self.model);
- WriteCoord(MSG_ENTITY, self.mins_x);
- WriteCoord(MSG_ENTITY, self.mins_y);
- WriteCoord(MSG_ENTITY, self.mins_z);
- WriteCoord(MSG_ENTITY, self.maxs_x);
- WriteCoord(MSG_ENTITY, self.maxs_y);
- WriteCoord(MSG_ENTITY, self.maxs_z);
+ trigger_common_write(true);
WriteCoord(MSG_ENTITY, self.pos1_x);
WriteCoord(MSG_ENTITY, self.pos1_y);
WriteCoord(MSG_ENTITY, self.size_y);
WriteCoord(MSG_ENTITY, self.size_z);
- WriteAngle(MSG_ENTITY, self.angles_x);
- WriteAngle(MSG_ENTITY, self.angles_y);
- WriteAngle(MSG_ENTITY, self.angles_z);
-
WriteAngle(MSG_ENTITY, self.mangle_x);
WriteAngle(MSG_ENTITY, self.mangle_y);
WriteAngle(MSG_ENTITY, self.mangle_z);
if(sf & SF_TRIGGER_INIT)
{
self.sv_entnum = ReadShort();
- self.target = strzone(ReadString());
- self.target2 = strzone(ReadString());
- self.target3 = strzone(ReadString());
- self.target4 = strzone(ReadString());
- self.targetname = strzone(ReadString());
self.platmovetype_start = ReadByte();
self.platmovetype_turn = ReadByte();
self.platmovetype_end = ReadByte();
- self.origin_x = ReadCoord();
- self.origin_y = ReadCoord();
- self.origin_z = ReadCoord();
- setorigin(self, self.origin);
-
self.model = strzone(ReadString());
setmodel(self, self.model);
- self.mins_x = ReadCoord();
- self.mins_y = ReadCoord();
- self.mins_z = ReadCoord();
- self.maxs_x = ReadCoord();
- self.maxs_y = ReadCoord();
- self.maxs_z = ReadCoord();
- setsize(self, self.mins, self.maxs);
+ trigger_common_read(true);
self.pos1_x = ReadCoord();
self.pos1_y = ReadCoord();
self.size_y = ReadCoord();
self.size_z = ReadCoord();
- self.angles_x = ReadAngle();
- self.angles_y = ReadAngle();
- self.angles_z = ReadAngle();
-
self.mangle_x = ReadAngle();
self.mangle_y = ReadAngle();
self.mangle_z = ReadAngle();
self.drawmask = MASK_NORMAL;
self.draw = plat_draw;
self.use = plat_use;
+ self.entremove = trigger_remove_generic;
plat_reset(); // also called here
+
+ self.move_origin = self.origin;
+ self.move_angles = self.angles;
+ self.move_time = time;
}
if(sf & SF_TRIGGER_RESET)
{
plat_reset();
+
+ self.move_origin = self.origin;
+ self.move_angles = self.angles;
+ self.move_time = time;
}
}
#endif
#include "subs.qc"
#include "triggers.qc"
#include "platforms.qc"
+#include "teleporters.qc"
// func
#include "func/include.qc"
#include "triggers.qh"
#include "subs.qh"
#include "platforms.qh"
+#include "teleporters.qh"
// func
#include "func/include.qh"
#include "corner.qc"
#include "follow.qc"
#include "laser.qc"
+#include "teleport_dest.qc"
--- /dev/null
+#ifdef SVQC
+
+void spawnfunc_info_teleport_destination (void)
+{
+ self.classname = "info_teleport_destination";
+
+ self.mangle = self.angles;
+ self.angles = '0 0 0';
+
+ //setorigin (self, self.origin + '0 0 27'); // To fix a mappers' habit as old as Quake
+ setorigin (self, self.origin);
+
+ IFTARGETED
+ {
+ }
+ else
+ objerror ("^3Teleport destination without a targetname");
+}
+
+void spawnfunc_misc_teleporter_dest (void)
+{
+ spawnfunc_info_teleport_destination();
+}
+
+void spawnfunc_target_teleporter (void)
+{
+ spawnfunc_info_teleport_destination();
+}
+
+#endif
#include "include.qh"
#include "changelevel.qc"
+#include "location.qc"
#include "music.qc"
#include "spawn.qc"
#include "speaker.qc"
--- /dev/null
+#ifdef SVQC
+void spawnfunc_target_location()
+{
+ self.classname = "target_location";
+ // location name in netname
+ // eventually support: count, teamgame selectors, line of sight?
+}
+
+void spawnfunc_info_location()
+{
+ self.classname = "target_location";
+ self.message = self.netname;
+}
+#endif
--- /dev/null
+#include "teleporters.qh"
+
+#if defined(CSQC)
+#elif defined(MENUQC)
+#elif defined(SVQC)
+ #include "../../warpzonelib/common.qh"
+ #include "../../warpzonelib/util_server.qh"
+ #include "../../warpzonelib/server.qh"
+ #include "../constants.qh"
+ #include "../triggers/subs.qh"
+ #include "../util.qh"
+ #include "../../server/weapons/csqcprojectile.qh"
+ #include "../../server/autocvars.qh"
+ #include "../../server/constants.qh"
+ #include "../../server/defs.qh"
+ #include "../deathtypes.qh"
+ #include "../../server/tturrets/include/turrets_early.qh"
+ #include "../../server/vehicles/vehicles_def.qh"
+ #include "../mapinfo.qh"
+ #include "../../server/anticheat.qh"
+#endif
+
+#ifdef SVQC
+
+float check_tdeath(entity player, vector org, vector telefragmin, vector telefragmax)
+{
+ if (IS_PLAYER(player) && player.health >= 1)
+ {
+ TDEATHLOOP(org)
+ {
+ if (!(teamplay && autocvar_g_telefrags_teamplay && head.team == player.team))
+ if(IS_PLAYER(head))
+ if(head.health >= 1)
+ return 1;
+ }
+ }
+ return 0;
+}
+
+void tdeath(entity player, entity teleporter, entity telefragger, vector telefragmin, vector telefragmax)
+{
+ TDEATHLOOP(player.origin)
+ {
+ if (IS_PLAYER(player) && player.health >= 1)
+ {
+ if (!(teamplay && autocvar_g_telefrags_teamplay && head.team == player.team))
+ {
+ if(IS_PLAYER(head))
+ if(head.health >= 1)
+ ++tdeath_hit;
+ Damage (head, teleporter, telefragger, 10000, DEATH_TELEFRAG, head.origin, '0 0 0');
+ }
+ }
+ else // dead bodies and monsters gib themselves instead of telefragging
+ Damage (telefragger, teleporter, telefragger, 10000, DEATH_TELEFRAG, telefragger.origin, '0 0 0');
+ }
+}
+
+void spawn_tdeath(vector v0, entity e, vector v)
+{
+ tdeath(e, e, e, '0 0 0', '0 0 0');
+}
+
+void TeleportPlayer(entity teleporter, entity player, vector to, vector to_angles, vector to_velocity, vector telefragmin, vector telefragmax, float tflags)
+{
+ entity telefragger;
+ vector from;
+
+ if(teleporter.owner)
+ telefragger = teleporter.owner;
+ else
+ telefragger = player;
+
+ makevectors (to_angles);
+
+ if(player.teleportable == TELEPORT_NORMAL) // don't play sounds or show particles for anything that isn't a player, maybe change later to block only observers
+ {
+ if(self.pushltime < time) // only show one teleport effect per teleporter per 0.2 seconds, for better fps
+ {
+ if(tflags & TELEPORT_FLAG_SOUND)
+ sound (player, CH_TRIGGER, "misc/teleport.wav", VOL_BASE, ATTEN_NORM);
+ if(tflags & TELEPORT_FLAG_PARTICLES)
+ {
+ pointparticles(particleeffectnum("teleport"), player.origin, '0 0 0', 1);
+ pointparticles(particleeffectnum("teleport"), to + v_forward * 32, '0 0 0', 1);
+ }
+ self.pushltime = time + 0.2;
+ }
+ }
+
+ // Relocate the player
+ // assuming to allows PL_MIN to PL_MAX box and some more
+ from = player.origin;
+ setorigin (player, to);
+ player.oldorigin = to; // don't undo the teleport by unsticking
+ player.angles = to_angles;
+ player.fixangle = true;
+ player.velocity = to_velocity;
+ BITXOR_ASSIGN(player.effects, EF_TELEPORT_BIT);
+
+ makevectors(player.angles);
+ Reset_ArcBeam(player, v_forward);
+ UpdateCSQCProjectileAfterTeleport(player);
+
+ if(IS_PLAYER(player))
+ {
+ if(tflags & TELEPORT_FLAG_TDEATH)
+ if(player.takedamage && player.deadflag == DEAD_NO && !g_race && !g_cts && (autocvar_g_telefrags || (tflags & TELEPORT_FLAG_FORCE_TDEATH)))
+ tdeath(player, teleporter, telefragger, telefragmin, telefragmax);
+
+ // player no longer is on ground
+ player.flags &= ~FL_ONGROUND;
+
+ // reset tracking of oldvelocity for impact damage (sudden velocity changes)
+ player.oldvelocity = player.velocity;
+
+ // reset tracking of who pushed you into a hazard (for kill credit)
+ if(teleporter.owner)
+ {
+ player.pusher = teleporter.owner;
+ player.pushltime = time + autocvar_g_maxpushtime;
+ player.istypefrag = player.BUTTON_CHAT;
+ }
+ else
+ {
+ player.pushltime = 0;
+ player.istypefrag = 0;
+ }
+
+ player.lastteleporttime = time;
+ }
+}
+
+entity Simple_TeleportPlayer(entity teleporter, entity player)
+{
+ vector locout;
+ entity e;
+ float p;
+
+ // Find the output teleporter
+ if(teleporter.enemy)
+ {
+ e = teleporter.enemy;
+ }
+ else
+ {
+ RandomSelection_Init();
+ for(e = world; (e = find(e, targetname, teleporter.target)); )
+ {
+ p = 1;
+ if(autocvar_g_telefrags_avoid)
+ {
+ locout = e.origin + '0 0 1' * (1 - player.mins.z - 24);
+ if(check_tdeath(player, locout, '0 0 0', '0 0 0'))
+ p = 0;
+ }
+ RandomSelection_Add(e, 0, string_null, (e.cnt ? e.cnt : 1), p);
+ }
+ e = RandomSelection_chosen_ent;
+ }
+
+ if(!e) { sprint(player, "Teleport destination vanished. Sorry... please complain to the mapper.\n"); }
+
+ makevectors(e.mangle);
+
+ if(e.speed)
+ if(vlen(player.velocity) > e.speed)
+ player.velocity = normalize(player.velocity) * max(0, e.speed);
+
+ if(autocvar_g_teleport_maxspeed)
+ if(vlen(player.velocity) > autocvar_g_teleport_maxspeed)
+ player.velocity = normalize(player.velocity) * max(0, autocvar_g_teleport_maxspeed);
+
+ locout = e.origin + '0 0 1' * (1 - player.mins.z - 24);
+ TeleportPlayer(teleporter, player, locout, e.mangle, v_forward * vlen(player.velocity), '0 0 0', '0 0 0', TELEPORT_FLAGS_TELEPORTER);
+
+ return e;
+}
+
+void teleport_findtarget (void)
+{
+ entity e;
+ float n;
+
+ n = 0;
+ for(e = world; (e = find(e, targetname, self.target)); )
+ {
+ ++n;
+ if(e.movetype == MOVETYPE_NONE)
+ waypoint_spawnforteleporter(self, e.origin, 0);
+ if(e.classname != "info_teleport_destination")
+ print("^3MAPPER ERROR: teleporter does target an invalid teleport destination entity. Angles will not work.\n");
+ }
+
+ if(n == 0)
+ {
+ // no dest!
+ objerror ("Teleporter with nonexistant target");
+ return;
+ }
+ else if(n == 1)
+ {
+ // exactly one dest - bots love that
+ self.enemy = find(e, targetname, self.target);
+ }
+ else
+ {
+ // have to use random selection every single time
+ self.enemy = world;
+ }
+
+ // now enable touch
+ self.touch = Teleport_Touch;
+}
+
+entity Teleport_Find(vector mi, vector ma)
+{
+ entity e;
+ for(e = world; (e = find(e, classname, "trigger_teleport")); )
+ if(WarpZoneLib_BoxTouchesBrush(mi, ma, e, world))
+ return e;
+ return world;
+}
+
+void WarpZone_PostTeleportPlayer_Callback(entity pl)
+{
+ makevectors(pl.angles);
+ Reset_ArcBeam(pl, v_forward);
+ UpdateCSQCProjectileAfterTeleport(pl);
+ {
+ entity oldself = self;
+ self = pl;
+ anticheat_fixangle();
+ self = oldself;
+ }
+ // "disown" projectiles after teleport
+ if(pl.owner)
+ if(pl.owner == pl.realowner)
+ {
+ if(!(pl.flags & FL_PROJECTILE))
+ print("A non-projectile got through a warpzone and its owner cleared. It's a ", pl.classname, ".\n");
+ pl.owner = world;
+ }
+ if(IS_PLAYER(pl))
+ {
+ // reset tracking of oldvelocity for impact damage (sudden velocity changes)
+ pl.oldvelocity = pl.velocity;
+ // reset teleport time tracking too (or multijump can cause insane speeds)
+ pl.lastteleporttime = time;
+ }
+}
+#endif
--- /dev/null
+#ifndef T_TELEPORTERS_H
+#define T_TELEPORTERS_H
+
+#ifdef SVQC
+
+void trigger_teleport_use();
+
+#define TDEATHLOOP(o) \
+ entity head; \
+ vector deathmin; \
+ vector deathmax; \
+ float deathradius; \
+ deathmin = (o) + player.mins; \
+ deathmax = (o) + player.maxs; \
+ if(telefragmin != telefragmax) \
+ { \
+ if(deathmin.x > telefragmin.x) deathmin.x = telefragmin.x; \
+ if(deathmin.y > telefragmin.y) deathmin.y = telefragmin.y; \
+ if(deathmin.z > telefragmin.z) deathmin.z = telefragmin.z; \
+ if(deathmax.x < telefragmax.x) deathmax.x = telefragmax.x; \
+ if(deathmax.y < telefragmax.y) deathmax.y = telefragmax.y; \
+ if(deathmax.z < telefragmax.z) deathmax.z = telefragmax.z; \
+ } \
+ deathradius = max(vlen(deathmin), vlen(deathmax)); \
+ for(head = findradius(o, deathradius); head; head = head.chain) \
+ if(head != player) \
+ if(head.takedamage) \
+ if(boxesoverlap(deathmin, deathmax, head.absmin, head.absmax))
+
+
+float check_tdeath(entity player, vector org, vector telefragmin, vector telefragmax);
+float tdeath_hit;
+void tdeath(entity player, entity teleporter, entity telefragger, vector telefragmin, vector telefragmax);
+
+void spawn_tdeath(vector v0, entity e, vector v);
+
+.entity pusher;
+const float TELEPORT_FLAG_SOUND = 1;
+const float TELEPORT_FLAG_PARTICLES = 2;
+const float TELEPORT_FLAG_TDEATH = 4;
+const float TELEPORT_FLAG_FORCE_TDEATH = 8;
+
+#define TELEPORT_FLAGS_WARPZONE 0
+#define TELEPORT_FLAGS_PORTAL (TELEPORT_FLAG_SOUND | TELEPORT_FLAG_PARTICLES | TELEPORT_FLAG_TDEATH | TELEPORT_FLAG_FORCE_TDEATH)
+#define TELEPORT_FLAGS_TELEPORTER (TELEPORT_FLAG_SOUND | TELEPORT_FLAG_PARTICLES | TELEPORT_FLAG_TDEATH)
+
+// types for .teleportable entity setting
+const float TELEPORT_NORMAL = 1; // play sounds/effects etc
+const float TELEPORT_SIMPLE = 2; // only do teleport, nothing special
+
+void Reset_ArcBeam(entity player, vector forward);
+void TeleportPlayer(entity teleporter, entity player, vector to, vector to_angles, vector to_velocity, vector telefragmin, vector telefragmax, float tflags);
+
+entity Simple_TeleportPlayer(entity teleporter, entity player);
+
+void Teleport_Touch (void);
+
+void teleport_findtarget (void);
+
+entity Teleport_Find(vector mi, vector ma);
+
+entity teleport_first;
+.entity teleport_next;
+
+void WarpZone_PostTeleportPlayer_Callback(entity pl);
+#endif
+
+#endif
#include "relay_teamcheck.qc"
#include "secret.qc"
#include "swamp.qc"
+#include "teleport.qc"
if(sf & 1)
{
- WriteString(MSG_ENTITY, self.target);
WriteByte(MSG_ENTITY, self.team);
WriteInt24_t(MSG_ENTITY, self.spawnflags);
WriteByte(MSG_ENTITY, self.active);
- WriteByte(MSG_ENTITY, self.warpzone_isboxy);
WriteByte(MSG_ENTITY, self.height);
- WriteByte(MSG_ENTITY, self.scale);
- WriteCoord(MSG_ENTITY, self.origin_x);
- WriteCoord(MSG_ENTITY, self.origin_y);
- WriteCoord(MSG_ENTITY, self.origin_z);
-
- WriteCoord(MSG_ENTITY, self.mins_x);
- WriteCoord(MSG_ENTITY, self.mins_y);
- WriteCoord(MSG_ENTITY, self.mins_z);
- WriteCoord(MSG_ENTITY, self.maxs_x);
- WriteCoord(MSG_ENTITY, self.maxs_y);
- WriteCoord(MSG_ENTITY, self.maxs_z);
-
- WriteCoord(MSG_ENTITY, self.movedir_x);
- WriteCoord(MSG_ENTITY, self.movedir_y);
- WriteCoord(MSG_ENTITY, self.movedir_z);
+
+ trigger_common_write(true);
}
if(sf & 2)
#endif
#ifdef CSQC
-void trigger_push_remove()
-{
- if(self.target)
- strunzone(self.target);
- self.target = string_null;
-}
+
void ent_trigger_push()
{
float sf = ReadByte();
if(sf & 1)
{
self.classname = "jumppad";
- self.target = strzone(ReadString());
int mytm = ReadByte(); if(mytm) { self.team = mytm - 1; }
self.spawnflags = ReadInt24_t();
self.active = ReadByte();
- self.warpzone_isboxy = ReadByte();
self.height = ReadByte();
- self.scale = ReadByte();
-
- self.origin_x = ReadCoord();
- self.origin_y = ReadCoord();
- self.origin_z = ReadCoord();
- setorigin(self, self.origin);
-
- self.mins_x = ReadCoord();
- self.mins_y = ReadCoord();
- self.mins_z = ReadCoord();
- self.maxs_x = ReadCoord();
- self.maxs_y = ReadCoord();
- self.maxs_z = ReadCoord();
- setsize(self, self.mins, self.maxs);
-
- self.movedir_x = ReadCoord();
- self.movedir_y = ReadCoord();
- self.movedir_z = ReadCoord();
-
- self.entremove = trigger_push_remove;
+
+ trigger_common_read(true);
+
+ self.entremove = trigger_remove_generic;
self.solid = SOLID_TRIGGER;
self.draw = trigger_draw_generic;
self.trigger_touch = trigger_push_touch;
{
WriteByte(MSG_ENTITY, ENT_CLIENT_KEYLOCK);
- WriteString(MSG_ENTITY, self.target);
- WriteString(MSG_ENTITY, self.target2);
- WriteString(MSG_ENTITY, self.target3);
- WriteString(MSG_ENTITY, self.target4);
- WriteString(MSG_ENTITY, self.killtarget);
- WriteString(MSG_ENTITY, self.targetname);
-
WriteInt24_t(MSG_ENTITY, self.itemkeys);
- WriteByte(MSG_ENTITY, self.warpzone_isboxy);
WriteByte(MSG_ENTITY, self.height);
- WriteByte(MSG_ENTITY, self.scale);
-
- WriteCoord(MSG_ENTITY, self.origin_x);
- WriteCoord(MSG_ENTITY, self.origin_y);
- WriteCoord(MSG_ENTITY, self.origin_z);
-
- WriteCoord(MSG_ENTITY, self.mins_x);
- WriteCoord(MSG_ENTITY, self.mins_y);
- WriteCoord(MSG_ENTITY, self.mins_z);
- WriteCoord(MSG_ENTITY, self.maxs_x);
- WriteCoord(MSG_ENTITY, self.maxs_y);
- WriteCoord(MSG_ENTITY, self.maxs_z);
- WriteCoord(MSG_ENTITY, self.movedir_x);
- WriteCoord(MSG_ENTITY, self.movedir_y);
- WriteCoord(MSG_ENTITY, self.movedir_z);
+ trigger_common_write(true);
return true;
}
void ent_keylock()
{
- self.target = strzone(ReadString());
- self.target2 = strzone(ReadString());
- self.target3 = strzone(ReadString());
- self.target4 = strzone(ReadString());
- self.killtarget = strzone(ReadString());
- self.targetname = strzone(ReadString());
-
self.itemkeys = ReadInt24_t();
- self.warpzone_isboxy = ReadByte();
self.height = ReadByte();
- self.scale = ReadByte();
-
- self.origin_x = ReadCoord();
- self.origin_y = ReadCoord();
- self.origin_z = ReadCoord();
-
- self.mins_x = ReadCoord();
- self.mins_y = ReadCoord();
- self.mins_z = ReadCoord();
- self.maxs_x = ReadCoord();
- self.maxs_y = ReadCoord();
- self.maxs_z = ReadCoord();
-
- self.movedir_x = ReadCoord();
- self.movedir_y = ReadCoord();
- self.movedir_z = ReadCoord();
+
+ trigger_common_read(true);
self.classname = "trigger_keylock";
self.drawmask = MASK_NORMAL;
#if defined(CSQC)
#elif defined(MENUQC)
#elif defined(SVQC)
- #include "../../..//dpdefs/progsdefs.qh"
+ #include "../../../dpdefs/progsdefs.qh"
#include "../../util.qh"
#include "../../../server/defs.qh"
#include "secret.qh"
{
WriteByte(MSG_ENTITY, ENT_CLIENT_LADDER);
- WriteByte(MSG_ENTITY, self.warpzone_isboxy);
- WriteByte(MSG_ENTITY, self.scale);
WriteByte(MSG_ENTITY, self.dmg); // can probably get away with using a single byte here
WriteByte(MSG_ENTITY, self.swamp_slowdown);
WriteByte(MSG_ENTITY, self.swamp_interval);
- WriteCoord(MSG_ENTITY, self.origin_x);
- WriteCoord(MSG_ENTITY, self.origin_y);
- WriteCoord(MSG_ENTITY, self.origin_z);
- WriteCoord(MSG_ENTITY, self.mins_x);
- WriteCoord(MSG_ENTITY, self.mins_y);
- WriteCoord(MSG_ENTITY, self.mins_z);
- WriteCoord(MSG_ENTITY, self.maxs_x);
- WriteCoord(MSG_ENTITY, self.maxs_y);
- WriteCoord(MSG_ENTITY, self.maxs_z);
-
- WriteCoord(MSG_ENTITY, self.movedir_x);
- WriteCoord(MSG_ENTITY, self.movedir_y);
- WriteCoord(MSG_ENTITY, self.movedir_z);
-
- WriteAngle(MSG_ENTITY, self.angles_x);
- WriteAngle(MSG_ENTITY, self.angles_y);
- WriteAngle(MSG_ENTITY, self.angles_z);
+ trigger_common_write(false);
return true;
}
void ent_swamp()
{
- self.warpzone_isboxy = ReadByte();
- self.scale = ReadByte();
self.dmg = ReadByte();
self.swamp_slowdown = ReadByte();
self.swamp_interval = ReadByte();
- self.origin_x = ReadCoord();
- self.origin_y = ReadCoord();
- self.origin_z = ReadCoord();
- setorigin(self, self.origin);
-
- self.mins_x = ReadCoord();
- self.mins_y = ReadCoord();
- self.mins_z = ReadCoord();
- self.maxs_x = ReadCoord();
- self.maxs_y = ReadCoord();
- self.maxs_z = ReadCoord();
- setsize(self, self.mins, self.maxs);
-
- self.movedir_x = ReadCoord();
- self.movedir_y = ReadCoord();
- self.movedir_z = ReadCoord();
-
- self.angles_x = ReadAngle();
- self.angles_y = ReadAngle();
- self.angles_z = ReadAngle();
+ trigger_common_read(false);
self.classname = "trigger_swamp";
self.solid = SOLID_TRIGGER;
self.trigger_touch = swamp_touch;
self.drawmask = MASK_NORMAL;
self.move_time = time;
+ self.entremove = trigger_remove_generic;
}
#endif
--- /dev/null
+#ifdef SVQC
+void trigger_teleport_use()
+{
+ if(teamplay)
+ self.team = activator.team;
+#ifdef SVQC
+ self.SendFlags |= SF_TRIGGER_UPDATE;
+#endif
+}
+
+void Teleport_Touch (void)
+{
+ entity oldself;
+ string s;
+
+ if (self.active != ACTIVE_ACTIVE)
+ return;
+
+ if (!other.teleportable)
+ return;
+
+ if(other.vehicle)
+ if(!other.vehicle.teleportable)
+ return;
+
+ if(other.turrcaps_flags & TFL_TURRCAPS_ISTURRET)
+ return;
+
+ if(other.deadflag != DEAD_NO)
+ return;
+
+ if(self.team)
+ if(((self.spawnflags & 4) == 0) == (self.team != other.team))
+ return;
+
+ EXACTTRIGGER_TOUCH;
+
+ if(IS_PLAYER(other))
+ RemoveGrapplingHook(other);
+
+ entity e;
+ e = Simple_TeleportPlayer(self, other);
+
+ activator = other;
+ s = self.target; self.target = string_null;
+ SUB_UseTargets();
+ if (!self.target) self.target = s;
+
+ oldself = self;
+ self = e;
+ SUB_UseTargets();
+ self = oldself;
+}
+
+void spawnfunc_trigger_teleport()
+{
+ self.angles = '0 0 0';
+
+ EXACTTRIGGER_INIT;
+
+ self.active = ACTIVE_ACTIVE;
+
+ self.use = trigger_teleport_use;
+
+ // this must be called to spawn the teleport waypoints for bots
+ InitializeEntity(self, teleport_findtarget, INITPRIO_FINDTARGET);
+
+ if (self.target == "")
+ {
+ objerror ("Teleporter with no target");
+ return;
+ }
+
+ self.teleport_next = teleport_first;
+ teleport_first = self;
+}
+#endif
#endif
}
+#ifdef SVQC
+void trigger_common_write(bool withtarget)
+{
+ WriteByte(MSG_ENTITY, self.warpzone_isboxy);
+ WriteByte(MSG_ENTITY, self.scale);
+
+ if(withtarget)
+ {
+ WriteString(MSG_ENTITY, self.target);
+ WriteString(MSG_ENTITY, self.target2);
+ WriteString(MSG_ENTITY, self.target3);
+ WriteString(MSG_ENTITY, self.target4);
+ WriteString(MSG_ENTITY, self.targetname);
+ WriteString(MSG_ENTITY, self.killtarget);
+ }
+
+ WriteCoord(MSG_ENTITY, self.origin_x);
+ WriteCoord(MSG_ENTITY, self.origin_y);
+ WriteCoord(MSG_ENTITY, self.origin_z);
+
+ WriteCoord(MSG_ENTITY, self.mins_x);
+ WriteCoord(MSG_ENTITY, self.mins_y);
+ WriteCoord(MSG_ENTITY, self.mins_z);
+
+ WriteCoord(MSG_ENTITY, self.movedir_x);
+ WriteCoord(MSG_ENTITY, self.movedir_y);
+ WriteCoord(MSG_ENTITY, self.movedir_z);
+
+ WriteCoord(MSG_ENTITY, self.angles_x);
+ WriteCoord(MSG_ENTITY, self.angles_y);
+ WriteCoord(MSG_ENTITY, self.angles_z);
+}
+
+#elif defined(CSQC)
+
+void trigger_common_read(bool withtarget)
+{
+ self.warpzone_isboxy = ReadByte();
+ self.scale = ReadByte();
+
+ if(withtarget)
+ {
+ self.target = strzone(ReadString());
+ self.target2 = strzone(ReadString());
+ self.target3 = strzone(ReadString());
+ self.target4 = strzone(ReadString());
+ self.targetname = strzone(ReadString());
+ self.killtarget = strzone(ReadString());
+ }
+
+ self.origin_x = ReadCoord();
+ self.origin_y = ReadCoord();
+ self.origin_z = ReadCoord();
+ setorigin(self, self.origin);
+
+ self.mins_x = ReadCoord();
+ self.mins_y = ReadCoord();
+ self.mins_z = ReadCoord();
+ self.maxs_x = ReadCoord();
+ self.maxs_y = ReadCoord();
+ self.maxs_z = ReadCoord();
+ setsize(self, self.mins, self.maxs);
+
+ self.movedir_x = ReadCoord();
+ self.movedir_y = ReadCoord();
+ self.movedir_z = ReadCoord();
+
+ self.angles_x = ReadCoord();
+ self.angles_y = ReadCoord();
+ self.angles_z = ReadCoord();
+}
+
+void trigger_remove_generic()
+{
+ if(self.target) { strunzone(self.target); }
+ self.target = string_null;
+
+ if(self.target2) { strunzone(self.target2); }
+ self.target2 = string_null;
+
+ if(self.target3) { strunzone(self.target3); }
+ self.target3 = string_null;
+
+ if(self.target4) { strunzone(self.target4); }
+ self.target4 = string_null;
+
+ if(self.targetname) { strunzone(self.targetname); }
+ self.target = string_null;
+
+ if(self.killtarget) { strunzone(self.killtarget); }
+ self.killtarget = string_null;
+}
+#endif
+
/*
==============================
SUB_UseTargets
// used elsewhere (will fix)
#ifdef SVQC
+void trigger_common_write(bool withtarget);
+
void spawnfunc_trigger_once();
string trigger_magicear_processmessage_forallears(entity source, float teamsay, entity privatesay, string msgin);
.vector dest;
#ifdef CSQC
+void trigger_common_read(bool withtarget);
+void trigger_remove_generic();
+
float WarpZoneLib_ExactTrigger_Touch();
#define EXACTTRIGGER_TOUCH if(WarpZoneLib_ExactTrigger_Touch()) return
#include "cheats.qh"
#include "g_damage.qh"
#include "race.qh"
-#include "t_teleporters.qh"
+#include "../common/triggers/teleporters.qh"
#if defined(CSQC)
#elif defined(MENUQC)
#include "../warpzonelib/util_server.qh"
#include "../common/constants.qh"
#include "../common/util.qh"
+ #include "../common/triggers/func/breakable.qh"
#include "../common/monsters/monsters.qh"
#include "../common/weapons/weapons.qh"
#include "weapons/tracing.qh"
#include "defs.qh"
#include "../common/deathtypes.qh"
#include "../common/triggers/subs.qh"
+ #include "../common/triggers/func/breakable.qh"
#include "mutators/mutators_include.qh"
#include "../csqcmodellib/sv_model.qh"
#endif
return nearest_entity[0];
}
-void spawnfunc_target_location()
-{
- self.classname = "target_location";
- // location name in netname
- // eventually support: count, teamgame selectors, line of sight?
-}
-
-void spawnfunc_info_location()
-{
- self.classname = "target_location";
- self.message = self.netname;
-}
-
string NearestLocation(vector p)
{
entity loc;
const float SP_ASSAULT_OBJECTIVES = 4;
// predefined spawnfuncs
-void spawnfunc_func_breakable();
void target_objective_decrease_activate();
#endif
t_items.qc
t_quake3.qc
t_quake.qc
-t_teleporters.qc
waypointsprites.qc
bot/bot.qc
+++ /dev/null
-#include "t_teleporters.qh"
-
-#if defined(CSQC)
-#elif defined(MENUQC)
-#elif defined(SVQC)
- #include "../warpzonelib/common.qh"
- #include "../warpzonelib/util_server.qh"
- #include "../warpzonelib/server.qh"
- #include "../common/constants.qh"
- #include "../common/triggers/subs.qh"
- #include "../common/util.qh"
- #include "weapons/csqcprojectile.qh"
- #include "autocvars.qh"
- #include "constants.qh"
- #include "defs.qh"
- #include "../common/deathtypes.qh"
- #include "tturrets/include/turrets_early.qh"
- #include "vehicles/vehicles_def.qh"
- #include "../common/mapinfo.qh"
- #include "anticheat.qh"
-#endif
-
-void trigger_teleport_use()
-{
- if(teamplay)
- self.team = activator.team;
-}
-
-float check_tdeath(entity player, vector org, vector telefragmin, vector telefragmax)
-{
- if (IS_PLAYER(player) && player.health >= 1)
- {
- TDEATHLOOP(org)
- {
- if (!(teamplay && autocvar_g_telefrags_teamplay && head.team == player.team))
- if(IS_PLAYER(head))
- if(head.health >= 1)
- return 1;
- }
- }
- return 0;
-}
-
-void tdeath(entity player, entity teleporter, entity telefragger, vector telefragmin, vector telefragmax)
-{
- TDEATHLOOP(player.origin)
- {
- if (IS_PLAYER(player) && player.health >= 1)
- {
- if (!(teamplay && autocvar_g_telefrags_teamplay && head.team == player.team))
- {
- if(IS_PLAYER(head))
- if(head.health >= 1)
- ++tdeath_hit;
- Damage (head, teleporter, telefragger, 10000, DEATH_TELEFRAG, head.origin, '0 0 0');
- }
- }
- else // dead bodies and monsters gib themselves instead of telefragging
- Damage (telefragger, teleporter, telefragger, 10000, DEATH_TELEFRAG, telefragger.origin, '0 0 0');
- }
-}
-
-void spawn_tdeath(vector v0, entity e, vector v)
-{
- tdeath(e, e, e, '0 0 0', '0 0 0');
-}
-
-void TeleportPlayer(entity teleporter, entity player, vector to, vector to_angles, vector to_velocity, vector telefragmin, vector telefragmax, float tflags)
-{
- entity telefragger;
- vector from;
-
- if(teleporter.owner)
- telefragger = teleporter.owner;
- else
- telefragger = player;
-
- makevectors (to_angles);
-
- if(player.teleportable == TELEPORT_NORMAL) // don't play sounds or show particles for anything that isn't a player, maybe change later to block only observers
- {
- if(self.pushltime < time) // only show one teleport effect per teleporter per 0.2 seconds, for better fps
- {
- if(tflags & TELEPORT_FLAG_SOUND)
- sound (player, CH_TRIGGER, "misc/teleport.wav", VOL_BASE, ATTEN_NORM);
- if(tflags & TELEPORT_FLAG_PARTICLES)
- {
- pointparticles(particleeffectnum("teleport"), player.origin, '0 0 0', 1);
- pointparticles(particleeffectnum("teleport"), to + v_forward * 32, '0 0 0', 1);
- }
- self.pushltime = time + 0.2;
- }
- }
-
- // Relocate the player
- // assuming to allows PL_MIN to PL_MAX box and some more
- from = player.origin;
- setorigin (player, to);
- player.oldorigin = to; // don't undo the teleport by unsticking
- player.angles = to_angles;
- player.fixangle = true;
- player.velocity = to_velocity;
- BITXOR_ASSIGN(player.effects, EF_TELEPORT_BIT);
-
- makevectors(player.angles);
- Reset_ArcBeam(player, v_forward);
- UpdateCSQCProjectileAfterTeleport(player);
-
- if(IS_PLAYER(player))
- {
- if(tflags & TELEPORT_FLAG_TDEATH)
- if(player.takedamage && player.deadflag == DEAD_NO && !g_race && !g_cts && (autocvar_g_telefrags || (tflags & TELEPORT_FLAG_FORCE_TDEATH)))
- tdeath(player, teleporter, telefragger, telefragmin, telefragmax);
-
- // player no longer is on ground
- player.flags &= ~FL_ONGROUND;
-
- // reset tracking of oldvelocity for impact damage (sudden velocity changes)
- player.oldvelocity = player.velocity;
-
- // reset tracking of who pushed you into a hazard (for kill credit)
- if(teleporter.owner)
- {
- player.pusher = teleporter.owner;
- player.pushltime = time + autocvar_g_maxpushtime;
- player.istypefrag = player.BUTTON_CHAT;
- }
- else
- {
- player.pushltime = 0;
- player.istypefrag = 0;
- }
-
- player.lastteleporttime = time;
- }
-}
-
-entity Simple_TeleportPlayer(entity teleporter, entity player)
-{
- vector locout;
- entity e;
- float p;
-
- // Find the output teleporter
- if(teleporter.enemy)
- {
- e = teleporter.enemy;
- }
- else
- {
- RandomSelection_Init();
- for(e = world; (e = find(e, targetname, teleporter.target)); )
- {
- p = 1;
- if(autocvar_g_telefrags_avoid)
- {
- locout = e.origin + '0 0 1' * (1 - player.mins.z - 24);
- if(check_tdeath(player, locout, '0 0 0', '0 0 0'))
- p = 0;
- }
- RandomSelection_Add(e, 0, string_null, (e.cnt ? e.cnt : 1), p);
- }
- e = RandomSelection_chosen_ent;
- }
-
- if(!e) { sprint(player, "Teleport destination vanished. Sorry... please complain to the mapper.\n"); }
-
- makevectors(e.mangle);
-
- if(e.speed)
- if(vlen(player.velocity) > e.speed)
- player.velocity = normalize(player.velocity) * max(0, e.speed);
-
- if(autocvar_g_teleport_maxspeed)
- if(vlen(player.velocity) > autocvar_g_teleport_maxspeed)
- player.velocity = normalize(player.velocity) * max(0, autocvar_g_teleport_maxspeed);
-
- locout = e.origin + '0 0 1' * (1 - player.mins.z - 24);
- TeleportPlayer(teleporter, player, locout, e.mangle, v_forward * vlen(player.velocity), '0 0 0', '0 0 0', TELEPORT_FLAGS_TELEPORTER);
-
- return e;
-}
-
-void Teleport_Touch (void)
-{
- entity oldself;
- string s;
-
- if (self.active != ACTIVE_ACTIVE)
- return;
-
- if (!other.teleportable)
- return;
-
- if(other.vehicle)
- if(!other.vehicle.teleportable)
- return;
-
- if(other.turrcaps_flags & TFL_TURRCAPS_ISTURRET)
- return;
-
- if(other.deadflag != DEAD_NO)
- return;
-
- if(self.team)
- if(((self.spawnflags & 4) == 0) == (self.team != other.team))
- return;
-
- EXACTTRIGGER_TOUCH;
-
- if(IS_PLAYER(other))
- RemoveGrapplingHook(other);
-
- entity e;
- e = Simple_TeleportPlayer(self, other);
-
- activator = other;
- s = self.target; self.target = string_null;
- SUB_UseTargets();
- if (!self.target) self.target = s;
-
- oldself = self;
- self = e;
- SUB_UseTargets();
- self = oldself;
-}
-
-void spawnfunc_info_teleport_destination (void)
-{
- self.classname = "info_teleport_destination";
-
- self.mangle = self.angles;
- self.angles = '0 0 0';
-
- //setorigin (self, self.origin + '0 0 27'); // To fix a mappers' habit as old as Quake
- setorigin (self, self.origin);
-
- IFTARGETED
- {
- }
- else
- objerror ("^3Teleport destination without a targetname");
-}
-
-void spawnfunc_misc_teleporter_dest (void)
-{
- spawnfunc_info_teleport_destination();
-}
-
-void spawnfunc_target_teleporter (void)
-{
- spawnfunc_info_teleport_destination();
-}
-
-void teleport_findtarget (void)
-{
- entity e;
- float n;
-
- n = 0;
- for(e = world; (e = find(e, targetname, self.target)); )
- {
- ++n;
- if(e.movetype == MOVETYPE_NONE)
- waypoint_spawnforteleporter(self, e.origin, 0);
- if(e.classname != "info_teleport_destination")
- print("^3MAPPER ERROR: teleporter does target an invalid teleport destination entity. Angles will not work.\n");
- }
-
- if(n == 0)
- {
- // no dest!
- objerror ("Teleporter with nonexistant target");
- return;
- }
- else if(n == 1)
- {
- // exactly one dest - bots love that
- self.enemy = find(e, targetname, self.target);
- }
- else
- {
- // have to use random selection every single time
- self.enemy = world;
- }
-
- // now enable touch
- self.touch = Teleport_Touch;
-}
-
-entity Teleport_Find(vector mi, vector ma)
-{
- entity e;
- for(e = world; (e = find(e, classname, "trigger_teleport")); )
- if(WarpZoneLib_BoxTouchesBrush(mi, ma, e, world))
- return e;
- return world;
-}
-
-void spawnfunc_trigger_teleport (void)
-{
- self.angles = '0 0 0';
-
- EXACTTRIGGER_INIT;
-
- self.active = ACTIVE_ACTIVE;
-
- self.use = trigger_teleport_use;
-
- // this must be called to spawn the teleport waypoints for bots
- InitializeEntity(self, teleport_findtarget, INITPRIO_FINDTARGET);
-
- if (self.target == "")
- {
- objerror ("Teleporter with no target");
- return;
- }
-
- self.teleport_next = teleport_first;
- teleport_first = self;
-}
-
-void WarpZone_PostTeleportPlayer_Callback(entity pl)
-{
- makevectors(pl.angles);
- Reset_ArcBeam(pl, v_forward);
- UpdateCSQCProjectileAfterTeleport(pl);
- {
- entity oldself = self;
- self = pl;
- anticheat_fixangle();
- self = oldself;
- }
- // "disown" projectiles after teleport
- if(pl.owner)
- if(pl.owner == pl.realowner)
- {
- if(!(pl.flags & FL_PROJECTILE))
- print("A non-projectile got through a warpzone and its owner cleared. It's a ", pl.classname, ".\n");
- pl.owner = world;
- }
- if(IS_PLAYER(pl))
- {
- // reset tracking of oldvelocity for impact damage (sudden velocity changes)
- pl.oldvelocity = pl.velocity;
- // reset teleport time tracking too (or multijump can cause insane speeds)
- pl.lastteleporttime = time;
- }
-}
+++ /dev/null
-#ifndef T_TELEPORTERS_H
-#define T_TELEPORTERS_H
-
-void trigger_teleport_use();
-
-#define TDEATHLOOP(o) \
- entity head; \
- vector deathmin; \
- vector deathmax; \
- float deathradius; \
- deathmin = (o) + player.mins; \
- deathmax = (o) + player.maxs; \
- if(telefragmin != telefragmax) \
- { \
- if(deathmin.x > telefragmin.x) deathmin.x = telefragmin.x; \
- if(deathmin.y > telefragmin.y) deathmin.y = telefragmin.y; \
- if(deathmin.z > telefragmin.z) deathmin.z = telefragmin.z; \
- if(deathmax.x < telefragmax.x) deathmax.x = telefragmax.x; \
- if(deathmax.y < telefragmax.y) deathmax.y = telefragmax.y; \
- if(deathmax.z < telefragmax.z) deathmax.z = telefragmax.z; \
- } \
- deathradius = max(vlen(deathmin), vlen(deathmax)); \
- for(head = findradius(o, deathradius); head; head = head.chain) \
- if(head != player) \
- if(head.takedamage) \
- if(boxesoverlap(deathmin, deathmax, head.absmin, head.absmax))
-
-
-float check_tdeath(entity player, vector org, vector telefragmin, vector telefragmax);
-float tdeath_hit;
-void tdeath(entity player, entity teleporter, entity telefragger, vector telefragmin, vector telefragmax);
-
-void spawn_tdeath(vector v0, entity e, vector v);
-
-.entity pusher;
-const float TELEPORT_FLAG_SOUND = 1;
-const float TELEPORT_FLAG_PARTICLES = 2;
-const float TELEPORT_FLAG_TDEATH = 4;
-const float TELEPORT_FLAG_FORCE_TDEATH = 8;
-
-#define TELEPORT_FLAGS_WARPZONE 0
-#define TELEPORT_FLAGS_PORTAL (TELEPORT_FLAG_SOUND | TELEPORT_FLAG_PARTICLES | TELEPORT_FLAG_TDEATH | TELEPORT_FLAG_FORCE_TDEATH)
-#define TELEPORT_FLAGS_TELEPORTER (TELEPORT_FLAG_SOUND | TELEPORT_FLAG_PARTICLES | TELEPORT_FLAG_TDEATH)
-
-// types for .teleportable entity setting
-const float TELEPORT_NORMAL = 1; // play sounds/effects etc
-const float TELEPORT_SIMPLE = 2; // only do teleport, nothing special
-
-void Reset_ArcBeam(entity player, vector forward);
-void TeleportPlayer(entity teleporter, entity player, vector to, vector to_angles, vector to_velocity, vector telefragmin, vector telefragmax, float tflags);
-
-entity Simple_TeleportPlayer(entity teleporter, entity player);
-
-void Teleport_Touch (void);
-
-void spawnfunc_info_teleport_destination (void);
-
-void spawnfunc_misc_teleporter_dest (void);
-
-void spawnfunc_target_teleporter (void);
-
-void teleport_findtarget (void);
-
-entity Teleport_Find(vector mi, vector ma);
-
-entity teleport_first;
-.entity teleport_next;
-void spawnfunc_trigger_teleport (void);
-
-void WarpZone_PostTeleportPlayer_Callback(entity pl);
-#endif