From 011d15f2cf0d2fe859534a29f87ba3e0c8695424 Mon Sep 17 00:00:00 2001 From: Mario Date: Thu, 3 Dec 2015 19:54:36 +1000 Subject: [PATCH] Predict warpzones --- qcsrc/client/progs.inc | 1 + qcsrc/common/physics.qh | 1 + qcsrc/common/triggers/teleporters.qc | 10 +++- qcsrc/common/triggers/teleporters.qh | 6 +- qcsrc/lib/warpzone/client.qc | 3 + qcsrc/lib/warpzone/server.qc | 83 +++++++++++++++++++++++++--- qcsrc/lib/warpzone/server.qh | 3 + 7 files changed, 96 insertions(+), 11 deletions(-) diff --git a/qcsrc/client/progs.inc b/qcsrc/client/progs.inc index 8c443568e..775e03148 100644 --- a/qcsrc/client/progs.inc +++ b/qcsrc/client/progs.inc @@ -63,6 +63,7 @@ #include "../lib/warpzone/anglestransform.qc" #include "../lib/warpzone/client.qc" #include "../lib/warpzone/common.qc" +#include "../lib/warpzone/server.qc" #include "../lib/warpzone/util_server.qc" #if BUILD_MOD diff --git a/qcsrc/common/physics.qh b/qcsrc/common/physics.qh index 0169011c0..01a8770a5 100644 --- a/qcsrc/common/physics.qh +++ b/qcsrc/common/physics.qh @@ -106,6 +106,7 @@ bool IsFlying(entity a); // TODO #define IS_CLIENT(s) (s).isplayermodel #define IS_PLAYER(s) (s).isplayermodel + #define IS_NOT_A_CLIENT(s) !(s).isplayermodel #define isPushable(s) (s).isplayermodel //float player_multijump; diff --git a/qcsrc/common/triggers/teleporters.qc b/qcsrc/common/triggers/teleporters.qc index f990cd1d5..1f4d0a664 100644 --- a/qcsrc/common/triggers/teleporters.qc +++ b/qcsrc/common/triggers/teleporters.qc @@ -280,29 +280,35 @@ entity Teleport_Find(vector mi, vector ma) return world; } -#ifdef SVQC void WarpZone_PostTeleportPlayer_Callback(entity pl) {SELFPARAM(); +#ifdef SVQC makevectors(pl.angles); Reset_ArcBeam(pl, v_forward); UpdateCSQCProjectileAfterTeleport(pl); { 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)) + #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 diff --git a/qcsrc/common/triggers/teleporters.qh b/qcsrc/common/triggers/teleporters.qh index fb31785e7..0e9e23572 100644 --- a/qcsrc/common/triggers/teleporters.qh +++ b/qcsrc/common/triggers/teleporters.qh @@ -62,10 +62,14 @@ void spawn_tdeath(vector v0, entity e, vector v); void Reset_ArcBeam(entity player, vector forward); -void WarpZone_PostTeleportPlayer_Callback(entity pl); #endif +void WarpZone_PostTeleportPlayer_Callback(entity pl); + #ifdef CSQC +.entity realowner; +.float lastteleporttime; + #define TDEATHLOOP(o) \ entity head; \ vector deathmin; \ diff --git a/qcsrc/lib/warpzone/client.qc b/qcsrc/lib/warpzone/client.qc index dd2b5cc9a..3eaba332a 100644 --- a/qcsrc/lib/warpzone/client.qc +++ b/qcsrc/lib/warpzone/client.qc @@ -25,6 +25,7 @@ void WarpZone_Fade_PreDraw() self.drawmask = MASK_NORMAL; } +void WarpZone_Touch (); NET_HANDLE(ENT_CLIENT_WARPZONE, bool isnew) { warpzone_warpzones_exist = 1; @@ -87,6 +88,8 @@ NET_HANDLE(ENT_CLIENT_WARPZONE, bool isnew) // how to draw // engine currently wants this self.predraw = WarpZone_Fade_PreDraw; + + self.move_touch = WarpZone_Touch; return true; } diff --git a/qcsrc/lib/warpzone/server.qc b/qcsrc/lib/warpzone/server.qc index 342bc0c5a..4540dab4f 100644 --- a/qcsrc/lib/warpzone/server.qc +++ b/qcsrc/lib/warpzone/server.qc @@ -30,27 +30,44 @@ void WarpZone_StoreProjectileData(entity e) { +#ifdef SVQC e.warpzone_oldorigin = e.origin; e.warpzone_oldvelocity = e.velocity; e.warpzone_oldangles = e.angles; +#elif defined(CSQC) + e.warpzone_oldorigin = e.move_origin; + e.warpzone_oldvelocity = e.move_velocity; + e.warpzone_oldangles = e.move_angles; +#endif } void WarpZone_TeleportPlayer(entity teleporter, entity player, vector to, vector to_angles, vector to_velocity) { +#ifdef SVQC setorigin (player, to); // NOTE: this also aborts the move, when this is called by touch player.oldorigin = to; // for DP's unsticking player.angles = to_angles; player.fixangle = true; player.velocity = to_velocity; +#elif defined(CSQC) + player.move_origin = to; + player.move_angles = to_angles; + player.move_velocity = to_velocity; +#endif BITXOR_ASSIGN(player.effects, EF_TELEPORT_BIT); if(IS_PLAYER(player)) +#ifdef SVQC BITCLR_ASSIGN(player.flags, FL_ONGROUND); +#elif defined(CSQC) + BITCLR_ASSIGN(player.move_flags, FL_ONGROUND); +#endif WarpZone_PostTeleportPlayer_Callback(player); } +#ifdef SVQC bool WarpZone_Teleported_Send(entity to, int sf) {SELFPARAM(); WriteHeader(MSG_ENTITY, ENT_CLIENT_WARPZONE_TELEPORTED); @@ -59,14 +76,21 @@ bool WarpZone_Teleported_Send(entity to, int sf) WriteCoord(MSG_ENTITY, self.angles.z); return true; } +#endif float WarpZone_Teleport(entity wz, entity player, float f0, float f1) { vector o0, a0, v0, o1, a1, v1, o10; +#ifdef SVQC o0 = player.origin + player.view_ofs; v0 = player.velocity; a0 = player.angles; +#elif defined(CSQC) + o0 = player.move_origin + player.view_ofs; + v0 = player.move_velocity; + a0 = player.move_angles; +#endif o10 = o1 = WarpZone_TransformOrigin(wz, o0); v1 = WarpZone_TransformVelocity(wz, v0); @@ -124,12 +148,15 @@ float WarpZone_Teleport(entity wz, entity player, float f0, float f1) player.warpzone_teleport_finishtime = time; player.warpzone_teleport_zone = wz; +#ifdef SVQC // prevent further teleports back float dt = (o1 - o10) * v1 * (1 / (v1 * v1)); - if(dt < sys_frametime) - player.warpzone_teleport_finishtime += sys_frametime - dt; + if(dt < PHYS_INPUT_FRAMETIME) + player.warpzone_teleport_finishtime += PHYS_INPUT_FRAMETIME - dt; +#endif #ifndef WARPZONE_USE_FIXANGLE + #ifdef SVQC if(IS_VEHICLE(player) && player.owner) player = player.owner; // hax if(IS_PLAYER(player)) @@ -149,6 +176,11 @@ float WarpZone_Teleport(entity wz, entity player, float f0, float f1) ts.effects = EF_NODEPTHTEST; ts.angles = wz.warpzone_transform; } + #elif defined(CSQC) + setproperty(VF_CL_VIEWANGLES, WarpZone_TransformVAngles(wz, getpropertyvec(VF_CL_VIEWANGLES))); + if(checkextension("DP_CSQC_ROTATEMOVES")) + CL_RotateMoves(wz.warpzone_transform); + #endif #endif return 1; @@ -163,13 +195,21 @@ void WarpZone_Touch () return; // FIXME needs a better check to know what is safe to teleport and what not +#ifdef SVQC if(other.movetype == MOVETYPE_NONE || other.movetype == MOVETYPE_FOLLOW || other.tag_entity) +#elif defined(CSQC) + if(other.move_movetype == MOVETYPE_NONE || other.move_movetype == MOVETYPE_FOLLOW || other.tag_networkentity) +#endif return; if(WarpZoneLib_ExactTrigger_Touch()) return; +#ifdef SVQC if(WarpZone_PlaneDist(self, other.origin + other.view_ofs) >= 0) // wrong side of the trigger_warpzone (don't teleport yet) +#elif defined(CSQC) + if(WarpZone_PlaneDist(self, other.move_origin + other.view_ofs) >= 0) // wrong side of the trigger_warpzone (don't teleport yet) +#endif return; float f; @@ -186,11 +226,16 @@ void WarpZone_Touch () float d; d = 24 + max(vlen(other.mins), vlen(other.maxs)); if(IS_NOT_A_CLIENT(other)) + #ifdef SVQC f = -d / bound(frametime * d * 1, frametime * vlen(other.velocity), d); + #elif defined(CSQC) + f = -d / bound(frametime * d * 1, frametime * vlen(other.move_velocity), d); + #endif else f = -1; if(WarpZone_Teleport(self, other, f, 0)) { +#ifdef SVQC string save1, save2; activator = other; @@ -207,6 +252,7 @@ void WarpZone_Touch () if (!self.target) self.target = save1; if (!self.target2) self.target2 = save2; setself(this); +#endif } else { @@ -214,6 +260,7 @@ void WarpZone_Touch () } } +#ifdef SVQC bool WarpZone_Send(entity to, int sendflags) {SELFPARAM(); WriteHeader(MSG_ENTITY, ENT_CLIENT_WARPZONE); @@ -318,8 +365,17 @@ float WarpZone_CheckProjectileImpact(entity player) {SELFPARAM(); vector o0, v0; - o0 = player.origin + player.view_ofs; - v0 = player.velocity; + .vector orgvec, velvec; +#ifdef SVQC + orgvec = origin; + velvec = velocity; +#elif defined(CSQC) + orgvec = move_origin; + velvec = move_velocity; +#endif + + o0 = player.orgvec + player.view_ofs; + v0 = player.velvec; // if we teleported shortly before, abort if(time <= player.warpzone_teleport_finishtime + 0.1) @@ -337,15 +393,19 @@ float WarpZone_CheckProjectileImpact(entity player) LOG_INFO("impactfilter found something - and it even gets handled correctly - please tell divVerent that this code apparently gets triggered again\n"); #endif LOG_INFO("Entity type: ", player.classname, "\n"); - LOG_INFO("Origin: ", vtos(player.origin), "\n"); - LOG_INFO("Velocity: ", vtos(player.velocity), "\n"); + LOG_INFO("Origin: ", vtos(player.orgvec), "\n"); + LOG_INFO("Velocity: ", vtos(player.velvec), "\n"); #ifdef WARPZONELIB_REMOVEHACK return 0; #else // retry previous move +#ifdef SVQC setorigin(player, player.warpzone_oldorigin); - player.velocity = player.warpzone_oldvelocity; +#elif defined(CSQC) + player.move_origin = player.warpzone_oldorigin; +#endif + player.velvec = player.warpzone_oldvelocity; if(WarpZone_Teleport(wz, player, 0, 1)) { entity oldself; @@ -373,13 +433,14 @@ float WarpZone_CheckProjectileImpact(entity player) else { setorigin(player, o0 - player.view_ofs); - player.velocity = v0; + player.velvec = v0; } return +1; #endif } #endif +#endif float WarpZone_Projectile_Touch() {SELFPARAM(); @@ -395,6 +456,7 @@ float WarpZone_Projectile_Touch() if(time == self.warpzone_teleport_time) return true; +#ifdef SVQC #ifdef WARPZONELIB_KEEPDEBUG // this SEEMS to not happen at the moment, but if it did, it would be more reliable { @@ -445,10 +507,13 @@ float WarpZone_Projectile_Touch() if(WarpZone_Projectile_Touch_ImpactFilter_Callback()) return true; +#endif return false; } +#ifdef SVQC + void WarpZone_InitStep_FindOriginTarget() {SELFPARAM(); if(self.killtarget != "") @@ -892,3 +957,5 @@ void WarpZone_PlayerPhysics_FixVAngle() } #endif } + +#endif diff --git a/qcsrc/lib/warpzone/server.qh b/qcsrc/lib/warpzone/server.qh index b96b7b336..0e0594a1b 100644 --- a/qcsrc/lib/warpzone/server.qh +++ b/qcsrc/lib/warpzone/server.qh @@ -1,6 +1,7 @@ #ifndef LIB_WARPZONE_SERVER_H #define LIB_WARPZONE_SERVER_H +#ifdef SVQC void WarpZone_StartFrame(); float WarpZone_Projectile_Touch(); @@ -16,3 +17,5 @@ void WarpZone_PlayerPhysics_FixVAngle(); void WarpZone_PostInitialize_Callback(); #endif + +#endif -- 2.39.2