#elif defined(SVQC)
#include <common/constants.qh>
#include <common/net_linked.qh>
- #include <common/triggers/subs.qh>
+ #include <common/mapobjects/subs.qh>
#include <common/util.qh>
#include <server/constants.qh>
#include <server/defs.qh>
+ #include <server/utils.qh>
+#endif
+
+#ifdef SVQC
+bool autocvar_sv_warpzone_allow_selftarget;
#endif
#ifdef WARPZONELIB_KEEPDEBUG
.float warpzone_teleport_finishtime;
.entity warpzone_teleport_zone;
-#define WarpZone_StoreProjectileData(e_) MACRO_BEGIN { \
+#define WarpZone_StoreProjectileData(e_) MACRO_BEGIN \
entity e = e_; \
e.warpzone_oldorigin = e.origin; \
e.warpzone_oldvelocity = e.velocity; \
e.warpzone_oldangles = e.angles; \
- } MACRO_END
+ MACRO_END
void WarpZone_TeleportPlayer(entity teleporter, entity player, vector to, vector to_angles, vector to_velocity)
{
+#ifdef SVQC
+ player.lastteleport_origin = player.origin;
+ player.lastteleporttime = time;
+#endif
setorigin(player, to); // NOTE: this also aborts the move, when this is called by touch
+ player.angles = to_angles;
#ifdef SVQC
player.oldorigin = to; // for DP's unsticking
player.fixangle = true;
+ if (IS_BOT_CLIENT(player))
+ {
+ // FIXME find a way to smooth view's angles change for bots too
+ player.v_angle = player.angles;
+ bot_aim_reset(player);
+ }
#endif
- player.angles = to_angles;
player.velocity = to_velocity;
BITXOR_ASSIGN(player.effects, EF_TELEPORT_BIT);
bool WarpZone_Teleported_Send(entity this, entity to, int sf)
{
WriteHeader(MSG_ENTITY, ENT_CLIENT_WARPZONE_TELEPORTED);
- WriteCoord(MSG_ENTITY, this.angles.x);
- WriteCoord(MSG_ENTITY, this.angles.y);
- WriteCoord(MSG_ENTITY, this.angles.z);
+ WriteVector(MSG_ENTITY, this.angles);
return true;
}
#endif
return;
// FIXME needs a better check to know what is safe to teleport and what not
- if((toucher.move_movetype == MOVETYPE_NONE && toucher.move_movetype == MOVETYPE_NONE) || toucher.move_movetype == MOVETYPE_FOLLOW || toucher.move_movetype == MOVETYPE_FOLLOW || toucher.tag_entity
-#ifdef CSQC
- || tag_networkentity
-#endif
- )
+ if(toucher.move_movetype == MOVETYPE_NONE || toucher.move_movetype == MOVETYPE_FOLLOW || toucher.tag_entity)
return;
if(WarpZoneLib_ExactTrigger_Touch(this, toucher))
if(WarpZone_Teleport(this, toucher, f, 0))
{
#ifdef SVQC
- string save1, save2;
-
- save1 = this.target; this.target = string_null;
- save2 = this.target3; this.target3 = string_null;
- SUB_UseTargets(this, toucher, toucher); // use toucher too?
- if (!this.target) this.target = save1;
- if (!this.target3) this.target3 = save2;
-
- save1 = this.target; this.target = string_null;
- save2 = this.target2; this.target2 = string_null;
- SUB_UseTargets(this.enemy, toucher, toucher); // use toucher too?
- if (!this.target) this.target = save1;
- if (!this.target2) this.target2 = save2;
+ SUB_UseTargets_SkipTargets(this, toucher, toucher, BIT(1) | BIT(3)); // use toucher too?
+ SUB_UseTargets_SkipTargets(this.enemy, toucher, toucher, BIT(1) | BIT(2)); // use toucher too?
#endif
}
else
player.velocity = player.warpzone_oldvelocity;
if(WarpZone_Teleport(wz, player, 0, 1))
{
- string save1, save2;
-
- save1 = wz.target; wz.target = string_null;
- save2 = wz.target3; wz.target3 = string_null;
- SUB_UseTargets(wz, player, player);
- if (!wz.target) wz.target = save1;
- if (!wz.target3) wz.target3 = save2;
-
- save1 = wz.enemy.target; wz.enemy.target = string_null;
- save2 = wz.enemy.target2; wz.enemy.target2 = string_null;
- SUB_UseTargets(wz.enemy, player, player);
- if (!wz.enemy.target) wz.enemy.target = save1;
- if (!wz.enemy.target2) wz.enemy.target2 = save2;
+ SUB_UseTargets_SkipTargets(wz, player, player, BIT(1) | BIT(3));
+ SUB_UseTargets_SkipTargets(wz.enemy, player, player, BIT(1) | BIT(2));
}
else
{
if(area > 0)
{
org = org - ((org - point) * norm) * norm; // project to plane
- makevectors(ang);
- if(norm * v_forward < 0)
+ vector forward, right, up;
+ MAKE_VECTORS(ang, forward, right, up);
+ if(norm * forward < 0)
{
LOG_INFO("Position target of trigger_warpzone near ", vtos(this.aiment.origin), " points into trigger_warpzone. BEWARE.");
norm = -1 * norm;
}
- ang = vectoangles2(norm, v_up); // keep rotation, but turn exactly against plane
+ ang = vectoangles2(norm, up); // keep rotation, but turn exactly against plane
ang.x = -ang.x;
- if(norm * v_forward < 0.99)
+ if(norm * forward < 0.99)
LOG_INFO("trigger_warpzone near ", vtos(this.aiment.origin), " has been turned to match plane orientation (", vtos(this.aiment.angles), " -> ", vtos(ang));
if(vdist(org - this.aiment.origin, >, 0.5))
LOG_INFO("trigger_warpzone near ", vtos(this.aiment.origin), " has been moved to match the plane (", vtos(this.aiment.origin), " -> ", vtos(org), ").");
// this way only one of the two ents needs to target
if(this.target != "")
{
- this.enemy = this; // so the if(!e.enemy) check also skips this, saves one IF
+ if(!autocvar_sv_warpzone_allow_selftarget)
+ this.enemy = this; // so the if(!e.enemy) check also skips this, saves one IF
e2 = NULL;
for(e = NULL, i = 0; (e = find(e, targetname, this.target)); )