1 void WarpZone_SetUp(entity e, vector my_org, vector my_ang, vector other_org, vector other_ang)
3 e.warpzone_transform = AnglesTransform_Divide(other_ang, AnglesTransform_TurnDirectionFR(my_ang));
4 e.warpzone_origin = my_org;
5 e.warpzone_targetorigin = other_org;
6 e.warpzone_angles = my_ang;
7 e.warpzone_targetangles = other_ang;
8 fixedmakevectors(my_ang); e.warpzone_forward = v_forward;
9 fixedmakevectors(other_ang); e.warpzone_targetforward = v_forward;
14 vector WarpZoneLib_BoxTouchesBrush_mins;
15 vector WarpZoneLib_BoxTouchesBrush_maxs;
16 entity WarpZoneLib_BoxTouchesBrush_ent;
17 entity WarpZoneLib_BoxTouchesBrush_ignore;
18 float WarpZoneLib_BoxTouchesBrush_Recurse()
24 tracebox('0 0 0', WarpZoneLib_BoxTouchesBrush_mins, WarpZoneLib_BoxTouchesBrush_maxs, '0 0 0', MOVE_NOMONSTERS, WarpZoneLib_BoxTouchesBrush_ignore);
26 if (trace_networkentity)
28 dprint("hit a network ent, cannot continue WarpZoneLib_BoxTouchesBrush\n");
29 // we cannot continue, as a player blocks us...
36 if (trace_ent == WarpZoneLib_BoxTouchesBrush_ent)
44 f = WarpZoneLib_BoxTouchesBrush_Recurse();
50 float WarpZoneLib_BoxTouchesBrush(vector mi, vector ma, entity e, entity ig)
59 WarpZoneLib_BoxTouchesBrush_mins = mi;
60 WarpZoneLib_BoxTouchesBrush_maxs = ma;
61 WarpZoneLib_BoxTouchesBrush_ent = e;
62 WarpZoneLib_BoxTouchesBrush_ignore = ig;
63 f = WarpZoneLib_BoxTouchesBrush_Recurse();
69 entity WarpZone_Find(vector mi, vector ma)
71 // if we are near any warpzone planes - MOVE AWAY (work around nearclip)
73 for(e = world; (e = find(e, classname, "trigger_warpzone")); )
74 if(WarpZoneLib_BoxTouchesBrush(mi, ma, e, world))
79 void WarpZone_MakeAllSolid()
82 for(e = world; (e = find(e, classname, "trigger_warpzone")); )
86 void WarpZone_MakeAllOther()
89 for(e = world; (e = find(e, classname, "trigger_warpzone")); )
90 e.solid = SOLID_TRIGGER;
93 void WarpZone_TraceBox(vector org, vector mi, vector ma, vector end, float nomonsters, entity forent)
102 WarpZone_MakeAllSolid();
110 tracebox(org, mi, ma, end, nomonsters, forent);
111 if(WarpZone_trace_callback)
112 WarpZone_trace_callback();
114 sol = trace_startsolid;
115 if(trace_fraction >= 1)
117 frac = trace_fraction = frac + (1 - frac) * trace_fraction;
118 if(trace_ent.classname != "trigger_warpzone")
120 // we hit a warpzone... so, let's perform the trace after the warp again
121 org = WarpZone_TransformOrigin(trace_ent, trace_endpos);
122 end = WarpZone_TransformOrigin(trace_ent, end);
123 WarpZone_trace_velocity = WarpZone_TransformVelocity(trace_ent, WarpZone_trace_velocity);
124 WarpZone_trace_angles = WarpZone_TransformAngles(trace_ent, WarpZone_trace_angles);
125 WarpZone_trace_v_angle = WarpZone_TransformVAngles(trace_ent, WarpZone_trace_v_angle);
128 dprint("I transformed into the same zone again, wtf, aborting the trace\n");
133 WarpZone_MakeAllOther();
134 trace_startsolid = sol;
135 WarpZone_trace_endpos = o0 + (e0 - o0) * trace_fraction;
141 void WarpZone_TraceLine(vector org, vector end, float nomonsters, entity forent)
143 WarpZone_TraceBox(org, '0 0 0', '0 0 0', end, nomonsters, forent);
146 void WarpZone_TraceToss(entity e, entity forent)
149 vector vf, vr, vu, v0, o0;
153 WarpZone_MakeAllSolid();
154 g = cvar("sv_gravity") * e.gravity;
155 WarpZone_tracetoss_time = 0;
160 tracetoss(e, forent);
161 if(WarpZone_trace_callback)
162 WarpZone_trace_callback();
163 e.origin = trace_endpos;
164 dt = vlen(e.origin - o0) / vlen(e.velocity);
165 WarpZone_tracetoss_time += dt;
166 e.velocity_z -= WarpZone_tracetoss_time * g;
167 if(trace_fraction >= 1)
169 if(trace_ent.classname != "trigger_warpzone")
171 // we hit a warpzone... so, let's perform the trace after the warp again
172 e.origin = WarpZone_TransformOrigin(trace_ent, e.origin);
173 e.velocity = WarpZone_TransformVelocity(trace_ent, e.velocity);
175 WarpZone_MakeAllOther();
179 WarpZone_tracetoss_velocity = e.velocity;
182 WarpZone_trace_endpos = e.origin + e.velocity * WarpZone_tracetoss_time;
183 WarpZone_trace_endpos_z -= 0.5 * g * WarpZone_tracetoss_time * WarpZone_tracetoss_time;
186 void WarpZone_TrailParticles(entity own, float eff, vector org, vector end)
193 WarpZone_MakeAllSolid();
197 traceline(org, end, MOVE_NOMONSTERS, world);
198 //print(vtos(org), " to ", vtos(trace_endpos), "\n");
199 trailparticles(own, eff, org, trace_endpos);
200 if(trace_fraction >= 1)
202 if(trace_ent.classname != "trigger_warpzone")
204 // we hit a warpzone... so, let's perform the trace after the warp again
205 org = WarpZone_TransformOrigin(trace_ent, trace_endpos);
206 end = WarpZone_TransformOrigin(trace_ent, end);
208 WarpZone_MakeAllOther();
214 float WarpZone_PlaneDist(entity wz, vector v)
216 return (v - wz.warpzone_origin) * wz.warpzone_forward;
219 float WarpZone_TargetPlaneDist(entity wz, vector v)
221 return (v - wz.warpzone_targetorigin) * wz.warpzone_targetforward;
224 vector WarpZone_TransformOrigin(entity wz, vector v)
226 return wz.warpzone_targetorigin + AnglesTransform_Apply(wz.warpzone_transform, v - wz.warpzone_origin);
229 vector WarpZone_TransformVelocity(entity wz, vector v)
231 return AnglesTransform_Apply(wz.warpzone_transform, v);
234 vector WarpZone_TransformAngles(entity wz, vector v)
236 return AnglesTransform_ApplyToAngles(wz.warpzone_transform, v);
239 vector WarpZone_TransformVAngles(entity wz, vector ang)
246 ang = AnglesTransform_ApplyToVAngles(wz.warpzone_transform, ang);
247 ang = AnglesTransform_Normalize(ang, TRUE);
248 ang = AnglesTransform_CancelRoll(ang);
254 vector WarpZone_UnTransformOrigin(entity wz, vector v)
256 return wz.warpzone_origin + AnglesTransform_Apply(AnglesTransform_Invert(wz.warpzone_transform), v - wz.warpzone_targetorigin);
259 vector WarpZone_UnTransformVelocity(entity wz, vector v)
261 return AnglesTransform_Apply(AnglesTransform_Invert(wz.warpzone_transform), v);
264 vector WarpZone_UnTransformAngles(entity wz, vector v)
266 return AnglesTransform_ApplyToAngles(AnglesTransform_Invert(wz.warpzone_transform), v);
269 vector WarpZone_UnTransformVAngles(entity wz, vector ang)
276 ang = AnglesTransform_ApplyToVAngles(AnglesTransform_Invert(wz.warpzone_transform), ang);
277 ang = AnglesTransform_Normalize(ang, TRUE);
278 ang = AnglesTransform_CancelRoll(ang);
284 vector WarpZoneLib_NearestPointOnBox(vector mi, vector ma, vector org)
287 nearest_x = bound(mi_x, org_x, ma_x);
288 nearest_y = bound(mi_y, org_y, ma_y);
289 nearest_z = bound(mi_z, org_z, ma_z);
293 .float WarpZone_findradius_hit;
294 .entity WarpZone_findradius_next;
295 void WarpZone_FindRadius_Recurse(vector org, float rad, vector org0, vector shift0, vector transform, vector shift1, float needlineofsight)
296 // blast origin of current search original blast origin how to untransform (victim to blast system)
300 vector shift0_new, transform_new, shift1_new;
301 vector transform_second;
307 e0 = findradius(org, rad);
310 for(e = e0; e; e = e.chain)
312 p = WarpZoneLib_NearestPointOnBox(e.origin + e.mins, e.origin + e.maxs, org0);
315 traceline(org, p, MOVE_NOMONSTERS, e);
316 if(trace_fraction < 1)
319 if(!e.WarpZone_findradius_hit || vlen(e.WarpZone_findradius_dist) > vlen(org0 - p))
321 e.WarpZone_findradius_nearest = p;
322 e.WarpZone_findradius_dist = org0 - p;
323 e.WarpZone_findradius_findorigin = org;
324 e.WarpZone_findradius_findradius = rad;
325 if(e.classname == "trigger_warpzone")
327 e.WarpZone_findradius_next = wz;
330 e.WarpZone_findradius_hit = 1;
331 e.enemy.WarpZone_findradius_dist = '0 0 0'; // we don't want to go through this zone ever again
332 e.enemy.WarpZone_findradius_hit = 1;
336 e.warpzone_transform = transform;
337 e.warpzone_origin = shift0;
338 e.warpzone_targetorigin = shift1;
340 e.WarpZone_findradius_hit = 1;
344 for(e = wz; e; e = e.WarpZone_findradius_next)
346 org0_new = WarpZone_TransformOrigin(e, org);
347 traceline(e.warpzone_targetorigin, org0_new, MOVE_NOMONSTERS, e);
348 org_new = trace_endpos;
350 transform_second = AnglesTransform_Invert(e.warpzone_transform);
351 transform_new = AnglesTransform_Multiply(transform, transform_second);
352 shift0_new = AnglesTransform_Multiply_GetPreShift(shift0, transform, shift1, e.warpzone_targetorigin, transform_second, e.warpzone_origin);
353 shift1_new = AnglesTransform_Multiply_GetPostShift(shift0, transform, shift1, e.warpzone_targetorigin, transform_second, e.warpzone_origin);
354 WarpZone_FindRadius_Recurse(
356 bound(0, rad - vlen(org_new - org0_new), rad - 8),
358 shift0_new, transform_new, shift1_new,
360 e.WarpZone_findradius_hit = 0;
361 e.enemy.WarpZone_findradius_hit = 0;
364 entity WarpZone_FindRadius(vector org, float rad, float needlineofsight)
367 WarpZone_FindRadius_Recurse(org, rad, org, '0 0 0', '0 0 0', '0 0 0', needlineofsight);
368 e0 = findchainfloat(WarpZone_findradius_hit, 1);
369 for(e = e0; e; e = e.chain)
370 e.WarpZone_findradius_hit = 0;
374 void WarpZone_Accumulator_Clear(entity acc)
376 acc.warpzone_transform = '0 0 0';
377 acc.warpzone_origin = '0 0 0';
378 acc.warpzone_targetorigin = '0 0 0';
380 void WarpZone_Accumulator_Add(entity acc, entity wz)
383 sf = AnglesTransform_Multiply_GetPreShift(wz.warpzone_origin, wz.warpzone_transform, wz.warpzone_targetorigin, acc.warpzone_origin, acc.warpzone_transform, acc.warpzone_targetorigin);
384 t = AnglesTransform_Multiply(wz.warpzone_transform, acc.warpzone_transform);
385 st = AnglesTransform_Multiply_GetPostShift(wz.warpzone_origin, wz.warpzone_transform, wz.warpzone_targetorigin, acc.warpzone_origin, acc.warpzone_transform, acc.warpzone_targetorigin);
386 acc.warpzone_origin = sf;
387 acc.warpzone_transform = t;
388 acc.warpzone_targetorigin = st;
391 .entity WarpZone_refsys;
392 void WarpZone_RefSys_GC()
394 // garbage collect unused reference systems
395 self.nextthink = time + 1;
396 if(self.owner.WarpZone_refsys != self)
399 void WarpZone_RefSys_Add(entity me, entity wz)
401 if(me.WarpZone_refsys.owner != me)
403 me.WarpZone_refsys = spawn();
404 me.WarpZone_refsys.classname = "warpzone_refsys";
405 me.WarpZone_refsys.owner = me;
406 me.WarpZone_refsys.think = WarpZone_RefSys_GC;
407 me.WarpZone_refsys.nextthink = time + 1;
408 WarpZone_Accumulator_Clear(me.WarpZone_refsys);
411 WarpZone_Accumulator_Add(me.WarpZone_refsys, wz);
413 vector WarpZone_RefSys_TransformOrigin(entity from, entity to, vector org)
415 if(from.WarpZone_refsys)
416 org = WarpZone_UnTransformOrigin(from.WarpZone_refsys, org);
417 if(to.WarpZone_refsys)
418 org = WarpZone_TransformOrigin(to.WarpZone_refsys, org);
421 vector WarpZone_RefSys_TransformVelocity(entity from, entity to, vector vel)
423 if(from.WarpZone_refsys)
424 vel = WarpZone_UnTransformVelocity(from.WarpZone_refsys, vel);
425 if(to.WarpZone_refsys)
426 vel = WarpZone_TransformVelocity(to.WarpZone_refsys, vel);
429 vector WarpZone_RefSys_TransformAngles(entity from, entity to, vector ang)
431 if(from.WarpZone_refsys)
432 ang = WarpZone_UnTransformAngles(from.WarpZone_refsys, ang);
433 if(to.WarpZone_refsys)
434 ang = WarpZone_TransformAngles(to.WarpZone_refsys, ang);
437 vector WarpZone_RefSys_TransformVAngles(entity from, entity to, vector ang)
439 if(from.WarpZone_refsys)
440 ang = WarpZone_UnTransformVAngles(from.WarpZone_refsys, ang);
441 if(to.WarpZone_refsys)
442 ang = WarpZone_TransformVAngles(to.WarpZone_refsys, ang);
445 entity WarpZone_RefSys_SpawnSameRefSys(entity me)
449 if(me.WarpZone_refsys)
450 WarpZone_RefSys_Add(e, me.WarpZone_refsys);