+float trace_dphitcontents;
+.float dphitcontents;
+
void WarpZone_Accumulator_Clear(entity acc)
{
acc.warpzone_transform = '0 0 0';
{
float f, s;
- if not(e.modelindex)
+ if(!e.modelindex || e.warpzone_isboxy)
return 1;
s = e.solid;
{
// if we are near any warpzone planes - MOVE AWAY (work around nearclip)
entity e;
+ if(!warpzone_warpzones_exist)
+ return world;
for(e = world; (e = find(e, classname, "trigger_warpzone")); )
if(WarpZoneLib_BoxTouchesBrush(mi, ma, e, world))
return e;
void WarpZone_MakeAllSolid()
{
entity e;
+ if(!warpzone_warpzones_exist)
+ return;
for(e = world; (e = find(e, classname, "trigger_warpzone")); )
e.solid = SOLID_BSP;
}
void WarpZone_MakeAllOther()
{
entity e;
+ if(!warpzone_warpzones_exist)
+ return;
for(e = world; (e = find(e, classname, "trigger_warpzone")); )
e.solid = SOLID_TRIGGER;
}
void WarpZone_TraceBox_ThroughZone(vector org, vector mi, vector ma, vector end, float nomonsters, entity forent, entity zone, WarpZone_trace_callback_t cb)
{
+ float nomonsters_adjusted;
float frac, sol, i;
+ float contentshack;
vector o0, e0;
entity wz;
vector vf, vr, vu;
+
+ WarpZone_Trace_InitTransform();
+ if(!warpzone_warpzones_exist)
+ {
+ if(nomonsters == MOVE_NOTHING)
+ {
+ trace_endpos = end;
+ trace_fraction = 1;
+ if(cb)
+ cb(org, trace_endpos, end);
+ return;
+ }
+ else
+ {
+ tracebox(org, mi, ma, end, nomonsters, forent);
+ if(cb)
+ cb(org, trace_endpos, end);
+ return;
+ }
+ }
+
vf = v_forward;
vr = v_right;
vu = v_up;
o0 = org;
e0 = end;
- WarpZone_Trace_InitTransform();
+
+ switch(nomonsters)
+ {
+ case MOVE_WORLDONLY:
+ case MOVE_NOTHING:
+ nomonsters_adjusted = MOVE_NOMONSTERS;
+ break;
+ default:
+ nomonsters_adjusted = nomonsters;
+ break;
+ }
+ if((contentshack = (forent.dphitcontentsmask && !(forent.dphitcontentsmask & DPCONTENTS_SOLID))))
+ forent.dphitcontentsmask |= DPCONTENTS_SOLID;
+
// if starting in warpzone, first transform
wz = WarpZone_Find(org + mi, org + ma);
if(wz)
goto fail;
}
WarpZone_Trace_AddTransform(wz);
- org = WarpZone_TransformOrigin(wz, trace_endpos);
+ org = WarpZone_TransformOrigin(wz, org);
end = WarpZone_TransformOrigin(wz, end);
}
WarpZone_MakeAllSolid();
if(--i < 1)
{
dprint("Too many warpzones in sequence, aborting trace.\n");
+ trace_ent = world;
break;
}
- tracebox(org, mi, ma, end, nomonsters, forent);
+ tracebox(org, mi, ma, end, nomonsters_adjusted, forent);
if(cb)
cb(org, trace_endpos, end);
if(sol < 0)
if(trace_fraction >= 1)
break;
if(trace_ent.classname != "trigger_warpzone")
+ {
+ if((nomonsters == MOVE_NOTHING) || ((nomonsters == MOVE_WORLDONLY) && trace_ent) || (contentshack && (trace_dphitcontents & forent.dphitcontentsmask) == DPCONTENTS_SOLID))
+ {
+ // continue the trace, ignoring this hit (we only care for warpzones)
+ org = trace_endpos + normalize(end - org);
+ continue;
+ // we cannot do an inverted trace here, as we do care for further warpzones inside that "solid" to be found
+ // otherwise, players could block entrances that way
+ }
break;
+ }
if(trace_ent == wz)
{
dprint("I transformed into the same zone again, wtf, aborting the trace\n");
+ trace_ent = world;
break;
}
wz = trace_ent;
}
WarpZone_MakeAllOther();
:fail
+ if(contentshack)
+ forent.dphitcontentsmask &~= DPCONTENTS_SOLID;
trace_startsolid = sol;
v_forward = vf;
v_right = vr;
vector vf, vr, vu, v0, o0;
entity wz;
- vf = v_forward;
- vr = v_right;
- vu = v_up;
o0 = e.origin;
v0 = e.velocity;
+
WarpZone_Trace_InitTransform();
+ WarpZone_tracetoss_time = 0;
+ if(!warpzone_warpzones_exist)
+ {
+ tracetoss(e, forent);
+ if(cb)
+ cb(e.origin, trace_endpos, trace_endpos);
+ dt = vlen(e.origin - o0) / vlen(e.velocity);
+ WarpZone_tracetoss_time += dt;
+ e.velocity_z -= dt * g;
+ WarpZone_tracetoss_velocity = e.velocity;
+ e.velocity = v0;
+ return;
+ }
+
+ vf = v_forward;
+ vr = v_right;
+ vu = v_up;
+
// if starting in warpzone, first transform
wz = WarpZone_Find(e.origin + e.mins, e.origin + e.maxs);
if(wz)
}
WarpZone_MakeAllSolid();
g = cvar("sv_gravity") * e.gravity;
- WarpZone_tracetoss_time = 0;
i = 16;
for(;;)
{
if(--i < 1)
{
dprint("Too many warpzones in sequence, aborting trace.\n");
+ trace_ent = world;
break;
}
tracetoss(e, forent);
if(cb)
cb(e.origin, trace_endpos, trace_endpos);
e.origin = trace_endpos;
- e.velocity_z -= WarpZone_tracetoss_time * g;
dt = vlen(e.origin - o0) / vlen(e.velocity);
WarpZone_tracetoss_time += dt;
+ e.velocity_z -= dt * g;
if(trace_fraction >= 1)
break;
if(trace_ent.classname != "trigger_warpzone")
if(trace_ent == wz)
{
dprint("I transformed into the same zone again, wtf, aborting the trace\n");
+ trace_ent = world;
break;
}
wz = trace_ent;