X-Git-Url: http://de.git.xonotic.org/?p=xonotic%2Fxonotic-data.pk3dir.git;a=blobdiff_plain;f=qcsrc%2Fcommon%2Ftriggers%2Fteleporters.qc;h=eae31ead021891d6b9f8e8803175a4bbda5363b1;hp=89a5fa20df1cef803ab61357d98e06e06d3ffd24;hb=068324d293df795dbc41de75f38256b8c6c35607;hpb=08e6497842b33529d0c1b0caa431b49ca98d79da diff --git a/qcsrc/common/triggers/teleporters.qc b/qcsrc/common/triggers/teleporters.qc index 89a5fa20d..eae31ead0 100644 --- a/qcsrc/common/triggers/teleporters.qc +++ b/qcsrc/common/triggers/teleporters.qc @@ -3,41 +3,44 @@ #if defined(CSQC) #elif defined(MENUQC) #elif defined(SVQC) - #include "../../server/_all.qh" - #include "../../warpzonelib/common.qh" - #include "../../warpzonelib/util_server.qh" - #include "../../warpzonelib/server.qh" + #include + #include + #include #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 + #include + #include + #include + #include "../deathtypes/all.qh" #include "../turrets/sv_turrets.qh" #include "../vehicles/all.qh" #include "../mapinfo.qh" - #include "../../server/anticheat.qh" + #include #endif -#ifdef SVQC - float check_tdeath(entity player, vector org, vector telefragmin, vector telefragmax) { - if (IS_PLAYER(player) && player.health >= 1) + if (IS_PLAYER(player) && !IS_DEAD(player)) { TDEATHLOOP(org) { + #ifdef SVQC if (!(teamplay && autocvar_g_telefrags_teamplay && head.team == player.team)) + #endif if(IS_PLAYER(head)) - if(head.health >= 1) + if(!IS_DEAD(head)) return 1; } } return 0; } +#ifdef SVQC + +void trigger_teleport_link(entity this); + void tdeath(entity player, entity teleporter, entity telefragger, vector telefragmin, vector telefragmax) { TDEATHLOOP(player.origin) @@ -49,11 +52,11 @@ void tdeath(entity player, entity teleporter, entity telefragger, vector telefra if(IS_PLAYER(head)) if(head.health >= 1) ++tdeath_hit; - Damage (head, teleporter, telefragger, 10000, DEATH_TELEFRAG, head.origin, '0 0 0'); + Damage (head, teleporter, telefragger, 10000, DEATH_TELEFRAG.m_id, 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'); + Damage (telefragger, teleporter, telefragger, 10000, DEATH_TELEFRAG.m_id, telefragger.origin, '0 0 0'); } } @@ -62,8 +65,10 @@ void spawn_tdeath(vector v0, entity e, vector v) tdeath(e, e, e, '0 0 0', '0 0 0'); } +#endif + void TeleportPlayer(entity teleporter, entity player, vector to, vector to_angles, vector to_velocity, vector telefragmin, vector telefragmax, float tflags) -{ +{SELFPARAM(); entity telefragger; vector from; @@ -74,23 +79,38 @@ void TeleportPlayer(entity teleporter, entity player, vector to, vector to_angle makevectors (to_angles); +#ifdef SVQC 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); + { + string thesound = SND(TELEPORT); + if(teleporter.noise != "") + { + RandomSelection_Init(); + FOREACH_WORD(teleporter.noise, true, + { + RandomSelection_Add(NULL, 0, it, 1, 1); + }); + thesound = RandomSelection_chosen_string; + } + _sound (player, CH_TRIGGER, thesound, VOL_BASE, ATTEN_NORM); + } if(tflags & TELEPORT_FLAG_PARTICLES) { - Send_Effect("teleport", player.origin, '0 0 0', 1); - Send_Effect("teleport", to + v_forward * 32, '0 0 0', 1); + Send_Effect(EFFECT_TELEPORT, player.origin, '0 0 0', 1); + Send_Effect(EFFECT_TELEPORT, to + v_forward * 32, '0 0 0', 1); } self.pushltime = time + 0.2; } } +#endif // Relocate the player // assuming to allows PL_MIN to PL_MAX box and some more +#ifdef SVQC from = player.origin; setorigin (player, to); player.oldorigin = to; // don't undo the teleport by unsticking @@ -102,15 +122,35 @@ void TeleportPlayer(entity teleporter, entity player, vector to, vector to_angle makevectors(player.angles); Reset_ArcBeam(player, v_forward); UpdateCSQCProjectileAfterTeleport(player); + UpdateItemAfterTeleport(player); +#elif defined(CSQC) + from = player.move_origin; + player.move_origin = to; + player.move_angles = to_angles; + player.move_velocity = to_velocity; + player.move_flags &= ~FL_ONGROUND; + player.iflags |= IFLAG_TELEPORTED | IFLAG_V_ANGLE | IFLAG_ANGLES; + player.csqcmodel_teleported = 1; + player.v_angle = to_angles; + + if(player.isplayermodel) // not for anything but the main player + { + setproperty(VF_ANGLES, player.move_angles); + setproperty(VF_CL_VIEWANGLES, player.move_angles); + } + makevectors(player.move_angles); +#endif + +#ifdef SVQC 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))) + if(player.takedamage && !IS_DEAD(player) && !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; + UNSET_ONGROUND(player); // reset tracking of oldvelocity for impact damage (sudden velocity changes) player.oldvelocity = player.velocity; @@ -130,6 +170,7 @@ void TeleportPlayer(entity teleporter, entity player, vector to, vector to_angle player.lastteleporttime = time; } +#endif } entity Simple_TeleportPlayer(entity teleporter, entity player) @@ -149,9 +190,13 @@ entity Simple_TeleportPlayer(entity teleporter, entity player) for(e = world; (e = find(e, targetname, teleporter.target)); ) { p = 1; - if(autocvar_g_telefrags_avoid) + if(STAT(TELEPORT_TELEFRAG_AVOID, player)) { + #ifdef SVQC + locout = e.origin + '0 0 1' * (1 - player.mins.z - 24); + #elif defined(CSQC) locout = e.origin + '0 0 1' * (1 - player.mins.z - 24); + #endif if(check_tdeath(player, locout, '0 0 0', '0 0 0')) p = 0; } @@ -160,37 +205,60 @@ entity Simple_TeleportPlayer(entity teleporter, entity player) e = RandomSelection_chosen_ent; } +#ifdef SVQC if(!e) { sprint(player, "Teleport destination vanished. Sorry... please complain to the mapper.\n"); } +#elif defined(CSQC) + if(!e) { LOG_INFO("Teleport destination could not be found from CSQC.\n"); } +#endif makevectors(e.mangle); +#ifdef SVQC if(e.speed) - if(vlen(player.velocity) > e.speed) + if(vdist(player.velocity, >, e.speed)) player.velocity = normalize(player.velocity) * max(0, e.speed); +#elif defined(CSQC) + if(e.speed) + if(vdist(player.move_velocity, >, e.speed)) + player.move_velocity = normalize(player.move_velocity) * max(0, e.speed); +#endif - if(autocvar_g_teleport_maxspeed) - if(vlen(player.velocity) > autocvar_g_teleport_maxspeed) - player.velocity = normalize(player.velocity) * max(0, autocvar_g_teleport_maxspeed); +#ifdef SVQC + if(STAT(TELEPORT_MAXSPEED, player)) + if(vdist(player.velocity, >, STAT(TELEPORT_MAXSPEED, player))) + player.velocity = normalize(player.velocity) * max(0, STAT(TELEPORT_MAXSPEED, player)); +#elif defined(CSQC) + if(STAT(TELEPORT_MAXSPEED, player)) + if(vdist(player.move_velocity, >, STAT(TELEPORT_MAXSPEED, player))) + player.move_velocity = normalize(player.move_velocity) * max(0, STAT(TELEPORT_MAXSPEED, player)); +#endif +#ifdef SVQC 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); +#elif defined(CSQC) + locout = e.origin + '0 0 1' * (1 - player.mins.z - 24); + + TeleportPlayer(teleporter, player, locout, e.mangle, v_forward * vlen(player.move_velocity), '0 0 0', '0 0 0', TELEPORT_FLAGS_TELEPORTER); +#endif return e; } -void teleport_findtarget (void) +void teleport_findtarget() { + int n = 0; entity e; - float n; - - n = 0; for(e = world; (e = find(e, targetname, self.target)); ) { ++n; +#ifdef SVQC 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"); + LOG_INFO("^3MAPPER ERROR: teleporter does target an invalid teleport destination entity. Angles will not work.\n"); +#endif } if(n == 0) @@ -211,7 +279,13 @@ void teleport_findtarget (void) } // now enable touch +#ifdef SVQC self.touch = Teleport_Touch; + + trigger_teleport_link(self); +#elif defined(CSQC) + self.move_touch = Teleport_Touch; +#endif } entity Teleport_Find(vector mi, vector ma) @@ -224,30 +298,35 @@ entity Teleport_Find(vector mi, vector ma) } void WarpZone_PostTeleportPlayer_Callback(entity pl) -{ +{SELFPARAM(); +#ifdef SVQC makevectors(pl.angles); Reset_ArcBeam(pl, v_forward); UpdateCSQCProjectileAfterTeleport(pl); + UpdateItemAfterTeleport(pl); { - entity oldself = self; - self = pl; - anticheat_fixangle(); - self = oldself; + WITH(entity, self, pl, anticheat_fixangle()); } +#endif // "disown" projectiles after teleport if(pl.owner) if(pl.owner == pl.realowner) { + #ifdef SVQC if(!(pl.flags & FL_PROJECTILE)) - print("A non-projectile got through a warpzone and its owner cleared. It's a ", pl.classname, ".\n"); + #elif defined(CSQC) + if(!(pl.move_flags & BIT(15))) // FL_PROJECTILE + #endif + LOG_INFO("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) + #ifdef SVQC pl.oldvelocity = pl.velocity; + #endif // reset teleport time tracking too (or multijump can cause insane speeds) pl.lastteleporttime = time; } } -#endif