From: Mario Date: Thu, 19 Feb 2015 05:35:16 +0000 (+1100) Subject: Move more stuff around X-Git-Tag: xonotic-v0.8.1~38^2~32 X-Git-Url: https://git.rm.cloudns.org/?a=commitdiff_plain;h=52c8d9ce236f80561b3963a67da390ff19b82a81;p=xonotic%2Fxonotic-data.pk3dir.git Move more stuff around --- diff --git a/qcsrc/client/movetypes.qc b/qcsrc/client/movetypes.qc index 19a5d41e8..2a46de112 100644 --- a/qcsrc/client/movetypes.qc +++ b/qcsrc/client/movetypes.qc @@ -287,7 +287,7 @@ float _Movetype_PushEntity(vector push, float failonstartsolid) // SV_PushEntity .float ltime; .void() blocked; -void _Movetype_VectorAngles_FLU(vector myangles) +void _Movetype_AngleVectorsFLU(vector myangles) // AngleVectorsFLU { float angle, sr, sp, sy, cr, cp, cy; @@ -401,7 +401,7 @@ void _Movetype_PushMove(float dt) // SV_PushMove 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; diff --git a/qcsrc/common/triggers/func/breakable.qc b/qcsrc/common/triggers/func/breakable.qc index eac14a4ea..5ce34b5f4 100644 --- a/qcsrc/common/triggers/func/breakable.qc +++ b/qcsrc/common/triggers/func/breakable.qc @@ -229,7 +229,8 @@ void func_breakable_reset() } // 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; diff --git a/qcsrc/common/triggers/func/breakable.qh b/qcsrc/common/triggers/func/breakable.qh new file mode 100644 index 000000000..b641d9446 --- /dev/null +++ b/qcsrc/common/triggers/func/breakable.qh @@ -0,0 +1,8 @@ +#ifndef TRIGGERS_FUNC_BREAKABLE_H +#define TRIGGERS_FUNC_BREAKABLE_H + +#ifdef SVQC +void spawnfunc_func_breakable(); +#endif + +#endif diff --git a/qcsrc/common/triggers/func/ladder.qc b/qcsrc/common/triggers/func/ladder.qc index 483fef80c..8b093f7ad 100644 --- a/qcsrc/common/triggers/func/ladder.qc +++ b/qcsrc/common/triggers/func/ladder.qc @@ -23,28 +23,10 @@ float func_ladder_send(entity to, float sf) 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; } @@ -76,32 +58,16 @@ void spawnfunc_func_water() 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 diff --git a/qcsrc/common/triggers/func/plat.qc b/qcsrc/common/triggers/func/plat.qc index ce4e3e2e4..4c4e5049d 100644 --- a/qcsrc/common/triggers/func/plat.qc +++ b/qcsrc/common/triggers/func/plat.qc @@ -1,7 +1,7 @@ #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) @@ -12,28 +12,14 @@ 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); @@ -46,10 +32,6 @@ float plat_send(entity to, float sf) 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); @@ -157,31 +139,15 @@ void ent_plat() 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(); @@ -194,10 +160,6 @@ void ent_plat() 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(); @@ -214,13 +176,22 @@ void ent_plat() 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 diff --git a/qcsrc/common/triggers/include.qc b/qcsrc/common/triggers/include.qc index 8189d3b72..59da1f217 100644 --- a/qcsrc/common/triggers/include.qc +++ b/qcsrc/common/triggers/include.qc @@ -4,6 +4,7 @@ #include "subs.qc" #include "triggers.qc" #include "platforms.qc" +#include "teleporters.qc" // func #include "func/include.qc" diff --git a/qcsrc/common/triggers/include.qh b/qcsrc/common/triggers/include.qh index 1cd37db5b..138d26786 100644 --- a/qcsrc/common/triggers/include.qh +++ b/qcsrc/common/triggers/include.qh @@ -8,6 +8,7 @@ #include "triggers.qh" #include "subs.qh" #include "platforms.qh" +#include "teleporters.qh" // func #include "func/include.qh" diff --git a/qcsrc/common/triggers/misc/include.qc b/qcsrc/common/triggers/misc/include.qc index 8c5678f96..c05f8c376 100644 --- a/qcsrc/common/triggers/misc/include.qc +++ b/qcsrc/common/triggers/misc/include.qc @@ -3,3 +3,4 @@ #include "corner.qc" #include "follow.qc" #include "laser.qc" +#include "teleport_dest.qc" diff --git a/qcsrc/common/triggers/misc/teleport_dest.qc b/qcsrc/common/triggers/misc/teleport_dest.qc new file mode 100644 index 000000000..b80ce827d --- /dev/null +++ b/qcsrc/common/triggers/misc/teleport_dest.qc @@ -0,0 +1,30 @@ +#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 diff --git a/qcsrc/common/triggers/target/include.qc b/qcsrc/common/triggers/target/include.qc index 3b8e02442..c53ea6d17 100644 --- a/qcsrc/common/triggers/target/include.qc +++ b/qcsrc/common/triggers/target/include.qc @@ -1,6 +1,7 @@ #include "include.qh" #include "changelevel.qc" +#include "location.qc" #include "music.qc" #include "spawn.qc" #include "speaker.qc" diff --git a/qcsrc/common/triggers/target/location.qc b/qcsrc/common/triggers/target/location.qc new file mode 100644 index 000000000..1430cabd8 --- /dev/null +++ b/qcsrc/common/triggers/target/location.qc @@ -0,0 +1,14 @@ +#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 diff --git a/qcsrc/common/triggers/teleporters.qc b/qcsrc/common/triggers/teleporters.qc new file mode 100644 index 000000000..5e91d7607 --- /dev/null +++ b/qcsrc/common/triggers/teleporters.qc @@ -0,0 +1,252 @@ +#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 diff --git a/qcsrc/common/triggers/teleporters.qh b/qcsrc/common/triggers/teleporters.qh new file mode 100644 index 000000000..bdd24ddef --- /dev/null +++ b/qcsrc/common/triggers/teleporters.qh @@ -0,0 +1,68 @@ +#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 diff --git a/qcsrc/common/triggers/trigger/include.qc b/qcsrc/common/triggers/trigger/include.qc index 2a92f7349..14986348f 100644 --- a/qcsrc/common/triggers/trigger/include.qc +++ b/qcsrc/common/triggers/trigger/include.qc @@ -21,3 +21,4 @@ #include "relay_teamcheck.qc" #include "secret.qc" #include "swamp.qc" +#include "teleport.qc" diff --git a/qcsrc/common/triggers/trigger/jumppads.qc b/qcsrc/common/triggers/trigger/jumppads.qc index dc269bdd5..e852ff4e8 100644 --- a/qcsrc/common/triggers/trigger/jumppads.qc +++ b/qcsrc/common/triggers/trigger/jumppads.qc @@ -320,27 +320,12 @@ float trigger_push_send(entity to, float sf) 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) @@ -425,12 +410,7 @@ void spawnfunc_target_position() { target_push_link(); } #endif #ifdef CSQC -void trigger_push_remove() -{ - if(self.target) - strunzone(self.target); - self.target = string_null; -} + void ent_trigger_push() { float sf = ReadByte(); @@ -438,32 +418,14 @@ void ent_trigger_push() 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; diff --git a/qcsrc/common/triggers/trigger/keylock.qc b/qcsrc/common/triggers/trigger/keylock.qc index 729b83a08..ec27d4b77 100644 --- a/qcsrc/common/triggers/trigger/keylock.qc +++ b/qcsrc/common/triggers/trigger/keylock.qc @@ -100,32 +100,10 @@ bool trigger_keylock_send(entity to, int sf) { 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; } @@ -220,32 +198,10 @@ void keylock_remove() 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; diff --git a/qcsrc/common/triggers/trigger/secret.qc b/qcsrc/common/triggers/trigger/secret.qc index 267c69a8c..1902b7e7d 100644 --- a/qcsrc/common/triggers/trigger/secret.qc +++ b/qcsrc/common/triggers/trigger/secret.qc @@ -1,7 +1,7 @@ #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" diff --git a/qcsrc/common/triggers/trigger/swamp.qc b/qcsrc/common/triggers/trigger/swamp.qc index 474eb2467..8013f3b17 100644 --- a/qcsrc/common/triggers/trigger/swamp.qc +++ b/qcsrc/common/triggers/trigger/swamp.qc @@ -98,29 +98,11 @@ float swamp_send(entity to, float sf) { 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; } @@ -155,32 +137,11 @@ void spawnfunc_trigger_swamp(void) 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; @@ -188,5 +149,6 @@ void ent_swamp() self.trigger_touch = swamp_touch; self.drawmask = MASK_NORMAL; self.move_time = time; + self.entremove = trigger_remove_generic; } #endif diff --git a/qcsrc/common/triggers/trigger/teleport.qc b/qcsrc/common/triggers/trigger/teleport.qc new file mode 100644 index 000000000..5ff5fcf33 --- /dev/null +++ b/qcsrc/common/triggers/trigger/teleport.qc @@ -0,0 +1,77 @@ +#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 diff --git a/qcsrc/common/triggers/triggers.qc b/qcsrc/common/triggers/triggers.qc index 8e94b5170..62306a603 100644 --- a/qcsrc/common/triggers/triggers.qc +++ b/qcsrc/common/triggers/triggers.qc @@ -29,6 +29,100 @@ void trigger_setnextthink(entity e, float dtime) #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 diff --git a/qcsrc/common/triggers/triggers.qh b/qcsrc/common/triggers/triggers.qh index 20e9369d2..ead4e90cd 100644 --- a/qcsrc/common/triggers/triggers.qh +++ b/qcsrc/common/triggers/triggers.qh @@ -27,6 +27,8 @@ void trigger_setnextthink(entity e, float dtime); // 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); @@ -39,6 +41,9 @@ void target_voicescript_clear(entity pl); .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 diff --git a/qcsrc/server/cheats.qc b/qcsrc/server/cheats.qc index 3119182a6..b8eaf6e42 100644 --- a/qcsrc/server/cheats.qc +++ b/qcsrc/server/cheats.qc @@ -1,7 +1,7 @@ #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) @@ -12,6 +12,7 @@ #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" @@ -19,6 +20,7 @@ #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 diff --git a/qcsrc/server/miscfunctions.qc b/qcsrc/server/miscfunctions.qc index 1655d3954..2ce05407b 100644 --- a/qcsrc/server/miscfunctions.qc +++ b/qcsrc/server/miscfunctions.qc @@ -227,19 +227,6 @@ entity findnearest(vector point, .string field, string value, vector axismod) 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; diff --git a/qcsrc/server/mutators/gamemode_assault.qh b/qcsrc/server/mutators/gamemode_assault.qh index 330707e67..1266492ca 100644 --- a/qcsrc/server/mutators/gamemode_assault.qh +++ b/qcsrc/server/mutators/gamemode_assault.qh @@ -29,6 +29,5 @@ const float ST_ASSAULT_OBJECTIVES = 1; const float SP_ASSAULT_OBJECTIVES = 4; // predefined spawnfuncs -void spawnfunc_func_breakable(); void target_objective_decrease_activate(); #endif diff --git a/qcsrc/server/progs.src b/qcsrc/server/progs.src index c45e3cb6a..cd62a169f 100644 --- a/qcsrc/server/progs.src +++ b/qcsrc/server/progs.src @@ -48,7 +48,6 @@ t_halflife.qc t_items.qc t_quake3.qc t_quake.qc -t_teleporters.qc waypointsprites.qc bot/bot.qc diff --git a/qcsrc/server/t_teleporters.qc b/qcsrc/server/t_teleporters.qc deleted file mode 100644 index 38d35bb03..000000000 --- a/qcsrc/server/t_teleporters.qc +++ /dev/null @@ -1,349 +0,0 @@ -#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; - } -} diff --git a/qcsrc/server/t_teleporters.qh b/qcsrc/server/t_teleporters.qh deleted file mode 100644 index 03e3c3f29..000000000 --- a/qcsrc/server/t_teleporters.qh +++ /dev/null @@ -1,71 +0,0 @@ -#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