19 bool autocvar_sv_warpzone_allow_selftarget;
22 #ifdef WARPZONELIB_KEEPDEBUG 23 #define WARPZONELIB_REMOVEHACK 38 #define WarpZone_StoreProjectileData(e_) MACRO_BEGIN \ 40 e.warpzone_oldorigin = e.origin; \ 41 e.warpzone_oldvelocity = e.velocity; \ 42 e.warpzone_oldangles = e.angles; \ 48 player.lastteleport_origin = player.origin;
49 player.lastteleporttime =
time;
52 player.angles = to_angles;
54 player.oldorigin =
to;
55 player.fixangle =
true;
59 player.v_angle = player.angles;
63 player.velocity = to_velocity;
76 WriteHeader(MSG_ENTITY, ENT_CLIENT_WARPZONE_TELEPORTED);
77 WriteVector(MSG_ENTITY, this.
angles);
84 vector o0, a0, v0, o1, a1, v1, o10;
86 o0 = player.origin + player.view_ofs;
97 if(f0 != 0 || f1 != 0)
117 o1 = o1 - v1 * (d / dv);
121 tracebox(o1 - player.view_ofs, player.mins, player.maxs, o1 - player.view_ofs,
MOVE_NOMONSTERS, player);
127 o1 = player.origin + player.view_ofs;
132 LOG_INFO(
"would have to put player in solid, won't do that");
142 player.warpzone_teleport_time =
time;
143 player.warpzone_teleport_finishtime =
time;
144 player.warpzone_teleport_zone = wz;
148 float dt = (o1 - o10) * v1 * (1 / (v1 * v1));
149 if(dt < PHYS_INPUT_FRAMETIME)
150 player.warpzone_teleport_finishtime += PHYS_INPUT_FRAMETIME - dt;
153 #ifndef WARPZONE_USE_FIXANGLE 156 player = player.owner;
160 player.fixangle =
false;
162 entity ts =
new(warpzone_teleported);
165 ts.SendFlags = 0xFFFFFF;
166 ts.drawonlytoclient = player;
168 ts.nextthink =
time + 1;
172 ts.angles = wz.warpzone_transform;
186 if(toucher.classname ==
"trigger_warpzone")
189 if(
time <= toucher.warpzone_teleport_finishtime)
214 d = 24 +
max(
vlen(toucher.mins),
vlen(toucher.maxs));
235 WriteHeader(MSG_ENTITY, ENT_CLIENT_WARPZONE);
243 if(this.
origin !=
'0 0 0')
290 WriteHeader(MSG_ENTITY, ENT_CLIENT_WARPZONE_CAMERA);
294 if(this.
origin !=
'0 0 0')
332 #ifdef WARPZONELIB_KEEPDEBUG 333 float WarpZone_CheckProjectileImpact(
entity player)
337 o0 = player.origin + player.view_ofs;
338 v0 = player.velocity;
341 if(
time <= player.warpzone_teleport_finishtime + 0.1)
350 #ifdef WARPZONELIB_REMOVEHACK 351 LOG_INFO(
"impactfilter found something - and it no longer gets handled correctly - please tell divVerent whether anything behaves broken now");
353 LOG_INFO(
"impactfilter found something - and it even gets handled correctly - please tell divVerent that this code apparently gets triggered again");
355 LOG_INFO(
"Entity type: ", player.classname);
359 #ifdef WARPZONELIB_REMOVEHACK 363 setorigin(player, player.warpzone_oldorigin);
364 player.velocity = player.warpzone_oldvelocity;
373 player.velocity = v0;
384 if(toucher.classname ==
"trigger_warpzone")
397 #ifdef WARPZONELIB_KEEPDEBUG 400 float save_dpstartcontents;
401 float save_dphitcontents;
402 float save_dphitq3surfaceflags;
403 string save_dphittexturename;
405 float save_startsolid;
409 float save_plane_dist;
426 float f = WarpZone_CheckProjectileImpact(
this);
427 if (f)
return (f > 0);
453 void WarpZone_InitStep_FindOriginTarget(
entity this)
460 error(
"Warp zone with nonexisting killtarget");
467 void WarpZonePosition_InitStep_FindTarget(
entity this)
471 error(
"Warp zone position with no target");
477 error(
"Warp zone position with nonexisting target");
480 if(this.
enemy.aiment)
483 error(
"Warp zone position targeting already oriented warpzone");
486 this.
enemy.aiment =
this;
489 void WarpZoneCamera_Think(
entity this)
494 ||
this.warpzone_save_eangles !=
this.enemy.angles)
505 void WarpZoneCamera_InitStep_FindTarget(
entity this)
511 error(
"Camera with no target");
520 error(
"Camera with nonexisting target");
525 this.SendFlags = 0xFFFFFF;
528 setthink(
this, WarpZoneCamera_Think);
535 void WarpZone_InitStep_UpdateTransform(
entity this)
537 vector org, ang, norm, point;
545 org = 0.5 * (this.
mins + this.
maxs);
547 norm = point =
'0 0 0';
549 for(i_s = 0; ; ++i_s)
551 tex = getsurfacetexture(
this, i_s);
554 if(tex ==
"textures/common/trigger" || tex ==
"trigger")
556 n_t = getsurfacenumtriangles(
this, i_s);
557 for(i_t = 0; i_t < n_t; ++i_t)
559 tri = getsurfacetriangle(
this, i_s, i_t);
560 a = getsurfacepoint(
this, i_s, tri.x);
561 b = getsurfacepoint(
this, i_s, tri.y);
562 c = getsurfacepoint(
this, i_s, tri.z);
563 n =
cross(c - a, b - a);
564 area = area +
vlen(n);
566 point = point +
vlen(n) * (a + b + c);
571 norm = norm * (1 / area);
572 point = point * (1 / (3 * area));
573 if(
vdist(norm, <, 0.99))
575 LOG_INFO(
"trigger_warpzone near ",
vtos(this.
aiment.origin),
" is nonplanar. BEWARE.");
588 org = org - ((org - point) * norm) * norm;
589 vector forward, right, up;
590 MAKE_VECTORS(ang, forward, right, up);
591 if(norm * forward < 0)
593 LOG_INFO(
"Position target of trigger_warpzone near ",
vtos(this.
aiment.origin),
" points into trigger_warpzone. BEWARE.");
596 ang = vectoangles2(norm, up);
598 if(norm * forward < 0.99)
611 error(
"cannot infer origin/angles for this warpzone, please use a killtarget or a trigger_warpzone_position");
617 void WarpZone_InitStep_ClearTarget(
entity this)
624 void WarpZone_InitStep_FindTarget(
entity this)
635 if(!autocvar_sv_warpzone_allow_selftarget)
641 if(e.classname ==
this.classname)
647 error(
"Warpzone with non-existing target");
655 void WarpZone_Think(
entity this);
656 void WarpZone_InitStep_FinalizeTransform(
entity this)
660 error(
"Invalid warp zone detected. Killed.");
667 this.SendFlags = 0xFFFFFF;
677 float warpzone_initialized;
679 entity warpzone_position_first;
680 entity warpzone_camera_first;
681 .entity warpzone_next;
685 this.warpzone_next = warpzone_position_first;
686 warpzone_position_first =
this;
690 spawnfunc_misc_warpzone_position(
this);
716 setsize(
this, this.
mins * this.
scale, this.
maxs * this.scale);
718 setsize(
this, this.
mins, this.
maxs);
720 this.SendFlags = 0xFFFFFF;
722 this.warpzone_next = warpzone_first;
723 warpzone_first =
this;
735 precache_model(this.
model);
736 _setmodel(
this, this.
model);
740 setsize(
this, this.
mins * this.
scale, this.
maxs * this.scale);
742 setsize(
this, this.
mins, this.
maxs);
745 else if(this.
solid < 0)
748 this.SendFlags = 0xFFFFFF;
749 this.warpzone_next = warpzone_camera_first;
750 warpzone_camera_first =
this;
752 void WarpZones_Reconnect()
754 for(
entity e = warpzone_first; e; e = e.warpzone_next)
755 WarpZone_InitStep_ClearTarget(e);
756 for(
entity e = warpzone_first; e; e = e.warpzone_next)
757 WarpZone_InitStep_FindTarget(e);
758 for(
entity e = warpzone_camera_first; e; e = e.warpzone_next)
759 WarpZoneCamera_InitStep_FindTarget(e);
760 for(
entity e = warpzone_first; e; e = e.warpzone_next)
761 WarpZone_InitStep_FinalizeTransform(e);
764 void WarpZone_Think(
entity this)
769 ||
this.warpzone_save_eangles !=
this.enemy.angles)
771 WarpZone_InitStep_UpdateTransform(
this);
772 WarpZone_InitStep_UpdateTransform(this.
enemy);
773 WarpZone_InitStep_FinalizeTransform(
this);
774 WarpZone_InitStep_FinalizeTransform(this.
enemy);
783 void WarpZone_StartFrame()
785 if (!warpzone_initialized)
787 warpzone_initialized =
true;
788 for(
entity e = warpzone_first; e; e = e.warpzone_next)
789 WarpZone_InitStep_FindOriginTarget(e);
790 for(
entity e = warpzone_position_first; e; e = e.warpzone_next)
791 WarpZonePosition_InitStep_FindTarget(e);
792 for(
entity e = warpzone_first; e; e = e.warpzone_next)
793 WarpZone_InitStep_UpdateTransform(e);
794 WarpZones_Reconnect();
836 .float warpzone_reconnecting;
837 bool visible_to_some_client(
entity ent)
849 for(
entity e = warpzone_first; e; e = e.warpzone_next)
850 e.warpzone_reconnecting = ((
this.target ==
"" || e.target ==
this.target) && !((
this.spawnflags & 1) && (visible_to_some_client(e) || visible_to_some_client(e.enemy))));
851 for(
entity e = warpzone_camera_first; e; e = e.warpzone_next)
852 e.warpzone_reconnecting = ((
this.target ==
"" || e.target ==
this.target) && !((
this.spawnflags & 1) && visible_to_some_client(e)));
853 for(
entity e = warpzone_first; e; e = e.warpzone_next)
854 if(e.warpzone_reconnecting)
855 WarpZone_InitStep_ClearTarget(e);
856 for(
entity e = warpzone_first; e; e = e.warpzone_next)
857 if(e.warpzone_reconnecting)
858 WarpZone_InitStep_FindTarget(e);
859 for(
entity e = warpzone_camera_first; e; e = e.warpzone_next)
860 if(e.warpzone_reconnecting)
861 WarpZoneCamera_InitStep_FindTarget(e);
862 for(
entity e = warpzone_first; e; e = e.warpzone_next)
863 if(e.warpzone_reconnecting || e.enemy.warpzone_reconnecting)
864 WarpZone_InitStep_FinalizeTransform(e);
869 this.
use = trigger_warpzone_reconnect_use;
874 spawnfunc_trigger_warpzone_reconnect(
this);
877 void WarpZone_PlayerPhysics_FixVAngle(
entity this)
879 #ifndef WARPZONE_DONT_FIX_VANGLE 885 this.v_angle_z += 720;
#define IL_EACH(this, cond, body)
vector warpzone_save_eorigin
float trace_dphitq3surfaceflags
float WarpZone_Teleport(entity wz, entity player, float f0, float f1)
const float VF_CL_VIEWANGLES
void WarpZoneLib_ExactTrigger_Init(entity this)
void bot_aim_reset(entity this)
bool WarpZoneLib_MoveOutOfSolid(entity e)
bool WarpZoneLib_ExactTrigger_Touch(entity this, entity toucher)
float trace_dphitcontents
vector WarpZone_TransformOrigin(entity wz, vector v)
void SUB_UseTargets_SkipTargets(entity this, entity actor, entity trigger, int skiptargets)
ClientState CS(Client this)
#define FOREACH_CLIENT(cond, body)
float checkpvs(vector viewpos, entity viewee)
entity Teleport_Find(vector mi, vector ma)
vector warpzone_oldorigin
spawnfunc(info_player_attacker)
#define WarpZone_StoreProjectileData(e_)
bool WarpZone_Projectile_Touch_ImpactFilter_Callback(entity this, entity toucher)
const float EF_NODEPTHTEST
float warpzone_warpzones_exist
entity warpzone_teleport_zone
void WarpZone_PostInitialize_Callback()
vector warpzone_targetangles
float WarpZone_PlaneDist(entity wz, vector v)
#define BITSET_ASSIGN(a, b)
spree_cen s1 spree_cen s1 spree_cen s1 spree_cen s1 spree_cen s1 spree_cen s1 spree_cen s1 f1
#define IS_REAL_CLIENT(v)
const int EF_TELEPORT_BIT
vector warpzone_save_origin
vector warpzone_oldangles
#define setmodel(this, m)
string trace_dphittexturename
void WarpZone_TeleportPlayer(entity teleporter, entity player, vector to, vector to_angles, vector to_velocity)
entity Simple_TeleportPlayer(entity teleporter, entity player)
#define BIT(n)
Only ever assign into the first 24 bits in QC (so max is BIT(23)).
#define BITCLR_ASSIGN(a, b)
const float MOVE_NOMONSTERS
ERASEABLE entity IL_PUSH(IntrusiveList this, entity it)
Push to tail.
vector WarpZone_TransformAngles(entity wz, vector v)
void WarpZone_SetUp(entity e, vector my_org, vector my_ang, vector other_org, vector other_ang)
vector WarpZone_TransformVAngles(entity wz, vector ang)
float warpzone_teleport_finishtime
float warpzone_teleport_time
entity WarpZone_Find(vector mi, vector ma)
void WarpZone_RefSys_Add(entity me, entity wz)
#define setSendEntity(e, f)
float trace_dpstartcontents
vector warpzone_save_eangles
float WarpZone_TargetPlaneDist(entity wz, vector v)
#define IS_NOT_A_CLIENT(v)
was: (clienttype(v) == CLIENTTYPE_NOTACLIENT)
vector warpzone_targetorigin
vector warpzone_oldvelocity
vector WarpZone_TransformVelocity(entity wz, vector v)
vector(float skel, float bonenum) _skel_get_boneabs_hidden
IntrusiveList g_projectiles
void WarpZone_Camera_SetUp(entity e, vector my_org, vector my_ang)
IntrusiveList g_warpzones
#define vdist(v, cmp, f)
Vector distance comparison, avoids sqrt()
void WarpZone_PostTeleportPlayer_Callback(entity pl)
#define IS_BOT_CLIENT(v)
want: (IS_CLIENT(v) && !IS_REAL_CLIENT(v))
float warpzone_cameras_exist
vector trace_plane_normal
float WarpZone_Projectile_Touch(entity this, entity toucher)
void WarpZone_Touch(entity this, entity toucher)
vector warpzone_save_angles
#define BITXOR_ASSIGN(a, b)