X-Git-Url: http://de.git.xonotic.org/?a=blobdiff_plain;f=qcsrc%2Fwarpzonelib%2Fcommon.qc;h=8536bd3d2c464bf575b32356ce60599432cd6190;hb=9041fcca280badb5dfb2a574023f12e374b46f28;hp=3f6bb10a2ebe872b77bc88e45f44558beced4bb1;hpb=b334d049e62088e7544b2d1453b5a95a4245813c;p=xonotic%2Fxonotic-data.pk3dir.git diff --git a/qcsrc/warpzonelib/common.qc b/qcsrc/warpzonelib/common.qc index 3f6bb10a2..8536bd3d2 100644 --- a/qcsrc/warpzonelib/common.qc +++ b/qcsrc/warpzonelib/common.qc @@ -1,3 +1,6 @@ +float trace_dphitcontents; +.float dphitcontents; + void WarpZone_Accumulator_Clear(entity acc) { acc.warpzone_transform = '0 0 0'; @@ -55,6 +58,21 @@ void WarpZone_SetUp(entity e, vector my_org, vector my_ang, vector other_org, ve e.camera_transform = WarpZone_camera_transform; } +vector WarpZone_Camera_camera_transform(vector org, vector ang) +{ + // a fixed camera view + trace_endpos = self.warpzone_origin; + makevectors(self.warpzone_angles); + return self.warpzone_origin; +} + +void WarpZone_Camera_SetUp(entity e, vector my_org, vector my_ang) // we assume that e.oldorigin and e.avelocity point to view origin and direction +{ + e.warpzone_origin = my_org; + e.warpzone_angles = my_ang; + e.camera_transform = WarpZone_Camera_camera_transform; +} + .entity enemy; vector WarpZoneLib_BoxTouchesBrush_mins; @@ -95,7 +113,7 @@ float WarpZoneLib_BoxTouchesBrush(vector mi, vector ma, entity e, entity ig) { float f, s; - if not(e.modelindex) + if(!e.modelindex || e.warpzone_isboxy) return 1; s = e.solid; @@ -114,6 +132,8 @@ entity WarpZone_Find(vector mi, vector ma) { // 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; @@ -123,6 +143,8 @@ entity WarpZone_Find(vector mi, vector ma) void WarpZone_MakeAllSolid() { entity e; + if(!warpzone_warpzones_exist) + return; for(e = world; (e = find(e, classname, "trigger_warpzone")); ) e.solid = SOLID_BSP; } @@ -130,6 +152,8 @@ void WarpZone_MakeAllSolid() void WarpZone_MakeAllOther() { entity e; + if(!warpzone_warpzones_exist) + return; for(e = world; (e = find(e, classname, "trigger_warpzone")); ) e.solid = SOLID_TRIGGER; } @@ -150,16 +174,52 @@ void WarpZone_Trace_AddTransform(entity wz) 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) @@ -173,7 +233,7 @@ void WarpZone_TraceBox_ThroughZone(vector org, vector mi, vector ma, vector end, goto fail; } WarpZone_Trace_AddTransform(wz); - org = WarpZone_TransformOrigin(wz, trace_endpos); + org = WarpZone_TransformOrigin(wz, org); end = WarpZone_TransformOrigin(wz, end); } WarpZone_MakeAllSolid(); @@ -185,9 +245,10 @@ void WarpZone_TraceBox_ThroughZone(vector org, vector mi, vector ma, vector end, 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) @@ -197,10 +258,21 @@ void WarpZone_TraceBox_ThroughZone(vector org, vector mi, vector ma, vector end, 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; @@ -213,6 +285,8 @@ void WarpZone_TraceBox_ThroughZone(vector org, vector mi, vector ma, vector end, } WarpZone_MakeAllOther(); :fail + if(contentshack) + forent.dphitcontentsmask &~= DPCONTENTS_SOLID; trace_startsolid = sol; v_forward = vf; v_right = vr; @@ -235,12 +309,28 @@ void WarpZone_TraceToss_ThroughZone(entity e, entity forent, entity zone, WarpZo 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) @@ -259,22 +349,22 @@ void WarpZone_TraceToss_ThroughZone(entity e, entity forent, entity zone, WarpZo } 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") @@ -282,6 +372,7 @@ void WarpZone_TraceToss_ThroughZone(entity e, entity forent, entity zone, WarpZo if(trace_ent == wz) { dprint("I transformed into the same zone again, wtf, aborting the trace\n"); + trace_ent = world; break; } wz = trace_ent;