diff --git a/cvarinfo.txt b/cvarinfo.txt index 184e4160c..f6e89a23f 100644 --- a/cvarinfo.txt +++ b/cvarinfo.txt @@ -104,6 +104,7 @@ nosave bool swwm_itemsparkles = false; // visual aid for low visibility items server bool swwm_singlefirst = false; // single weapons are selected before dual ones, has to be a server cvar due to limitations nosave bool swwm_uniqstats = false; // only list stats from the same map once, rather than for each single visit nosave int swwm_filterachievements = 1; // filter for achievements at 0%: 0 - no filter, 1 - obscure text, 2 - don't show +server noarchive bool swwm_debugview = false; // debug visual aid for various things, such as actor collision, trajectories, relationships, etc. // minimap settings nosave bool swwm_mm_enable = true; // show a minimap below the score counter diff --git a/language.version b/language.version index 35f9d56b0..c82c7383c 100644 --- a/language.version +++ b/language.version @@ -1,3 +1,3 @@ [default] -SWWM_MODVER="\chSWWM \czGZ\c- \cw0.9.11b-pre r436 \cu(Sat 10 Apr 18:06:09 CEST 2021)\c-"; -SWWM_SHORTVER="\cw0.9.11b-pre r436 \cu(2021-04-10 18:06:09)\c-"; +SWWM_MODVER="\chSWWM \czGZ\c- \cw0.9.11b-pre r437 \cu(Sat 10 Apr 19:27:19 CEST 2021)\c-"; +SWWM_SHORTVER="\cw0.9.11b-pre r437 \cu(2021-04-10 19:27:19)\c-"; diff --git a/zscript.txt b/zscript.txt index c2e8436dc..ecb132bc1 100644 --- a/zscript.txt +++ b/zscript.txt @@ -30,6 +30,7 @@ version "4.5" // handler code #include "zscript/handler/swwm_handler_cheats.zsc" #include "zscript/handler/swwm_handler_damage.zsc" +#include "zscript/handler/swwm_handler_debugrender.zsc" #include "zscript/handler/swwm_handler_flash.zsc" #include "zscript/handler/swwm_handler_iwantdie.zsc" #include "zscript/handler/swwm_handler_oneliners.zsc" diff --git a/zscript/handler/swwm_handler_debugrender.zsc b/zscript/handler/swwm_handler_debugrender.zsc new file mode 100644 index 000000000..4117a404b --- /dev/null +++ b/zscript/handler/swwm_handler_debugrender.zsc @@ -0,0 +1,116 @@ +// ported and optimized from old debug test mod + +extend Class SWWMHandler +{ + ui SWWMProjectionData projdata; + + private ui void DrawWorldLine( RenderEvent e, Vector3 apos, Vector3 bpos, Color col ) + { + Vector3 a = SWWMUtility.ProjectPoint(projdata,e.viewpos+level.Vec3Diff(e.viewpos,apos)), + b = SWWMUtility.ProjectPoint(projdata,e.viewpos+level.Vec3Diff(e.viewpos,bpos)); + if ( (a.z > 1.) && (b.z > 1.) ) return; + if ( (a.z == -double.infinity) || (b.z == -double.infinity) ) return; // how the fuck??? + double da, db, s; + Vector3 p; + da = a dot (0.,0.,-1.)-1.; + db = b dot (0.,0.,-1.)-1.; + if ( da-db != 0. ) + { + s = da/(da-db); + p = (a.x+s*(b.x-a.x),a.y+s*(b.y-a.y),a.z+s*(b.z-a.z)); + if ( a.z > 1. ) a = p; + if ( b.z > 1. ) b = p; + } + Vector2 va = SWWMUtility.NDCToViewport(projdata,a); + Vector2 vb = SWWMUtility.NDCToViewport(projdata,b); + Screen.DrawLine(int(va.x),int(va.y),int(vb.x),int(vb.y),col); + } + + private ui void DrawWorldCircle( RenderEvent e, Vector3 pos, double radius, Color col ) + { + Vector3 x, y, z; + [x, y, z] = swwm_CoordUtil.GetAxes(e.viewpitch,e.viewangle,e.viewroll); + Vector3 ndc[64]; + for ( int i=0; i<64; i++ ) + { + Vector3 wpos = e.viewpos+level.Vec3Diff(e.viewpos,level.Vec3Offset(pos,y*cos(i*5.625)*radius+z*sin(i*5.625)*radius)); + ndc[i] = SWWMUtility.ProjectPoint(projdata,wpos); + } + for ( int i=0; i<64; i++ ) + { + Vector3 a = ndc[i], b = ndc[(i+1)%64]; + if ( (a.z > 1.) && (b.z > 1.) ) continue; + if ( (a.z == -double.infinity) || (b.z == -double.infinity) ) continue; // how the fuck??? + double da, db, s; + Vector3 p; + da = a dot (0.,0.,-1.)-1.; + db = b dot (0.,0.,-1.)-1.; + if ( da-db != 0. ) + { + s = da/(da-db); + p = (a.x+s*(b.x-a.x),a.y+s*(b.y-a.y),a.z+s*(b.z-a.z)); + if ( a.z > 1. ) a = p; + if ( b.z > 1. ) b = p; + } + Vector2 va = SWWMUtility.NDCToViewport(projdata,a); + Vector2 vb = SWWMUtility.NDCToViewport(projdata,b); + Screen.DrawLine(int(va.x),int(va.y),int(vb.x),int(vb.y),col); + } + } + + private ui void DrawActor( RenderEvent e, Actor a ) + { + Vector3 pos = a.prev*(1.-e.FracTic)+a.pos*e.FracTic; + if ( a is 'DynamicLight' ) DrawWorldCircle(e,pos,a.args[3]*2,Color(a.args[0],a.args[1],a.args[2])); + if ( (a.radius > 0.) && (a.height > 0.) ) + { + Vector3 b1, b2; + b1 = pos-(a.radius,a.radius,0); + b2 = pos+(a.radius,a.radius,a.height); + DrawWorldLine(e,(b1.x,b1.y,b1.z),(b1.x,b2.y,b1.z),"White"); + DrawWorldLine(e,(b1.x,b2.y,b1.z),(b2.x,b2.y,b1.z),"White"); + DrawWorldLine(e,(b2.x,b2.y,b1.z),(b2.x,b1.y,b1.z),"White"); + DrawWorldLine(e,(b2.x,b1.y,b1.z),(b1.x,b1.y,b1.z),"White"); + DrawWorldLine(e,(b1.x,b1.y,b2.z),(b1.x,b2.y,b2.z),"White"); + DrawWorldLine(e,(b1.x,b2.y,b2.z),(b2.x,b2.y,b2.z),"White"); + DrawWorldLine(e,(b2.x,b2.y,b2.z),(b2.x,b1.y,b2.z),"White"); + DrawWorldLine(e,(b2.x,b1.y,b2.z),(b1.x,b1.y,b2.z),"White"); + DrawWorldLine(e,(b1.x,b1.y,b1.z),(b1.x,b1.y,b2.z),"White"); + DrawWorldLine(e,(b2.x,b1.y,b1.z),(b2.x,b1.y,b2.z),"White"); + DrawWorldLine(e,(b1.x,b2.y,b1.z),(b1.x,b2.y,b2.z),"White"); + DrawWorldLine(e,(b2.x,b2.y,b1.z),(b2.x,b2.y,b2.z),"White"); + } + Vector3 x, y, z; + [x, y, z] = swwm_CoordUtil.GetAxes(a.pitch,a.angle,a.roll); + DrawWorldLine(e,pos,pos+x*16,"Red"); + DrawWorldLine(e,pos,pos+y*16,"Green"); + DrawWorldLine(e,pos,pos+z*16,"Blue"); + if ( a.vel != (0,0,0) ) DrawWorldLine(e,pos,pos+a.vel*GameTicRate,"Yellow"); + if ( a.target ) DrawWorldLine(e,pos,a.target.prev*(1.-e.FracTic)+a.target.pos*e.FracTic,"Gold"); + if ( a.tracer ) DrawWorldLine(e,pos,a.tracer.prev*(1.-e.FracTic)+a.tracer.pos*e.FracTic,"Orange"); + if ( a.master ) DrawWorldLine(e,pos,a.master.prev*(1.-e.FracTic)+a.master.pos*e.FracTic,"Purple"); + Vector3 ndc = SWWMUtility.ProjectPoint(projdata,e.viewpos+level.Vec3Diff(e.viewpos,pos+(0,0,a.Height/2))); + if ( ndc.z > 1. ) return; + Vector2 vpos = SWWMUtility.NDCToViewport(projdata,ndc); + String tag = a.player?a.player.GetUserName():a.GetTag(); + Screen.DrawText(NewSmallFont,Font.CR_UNTRANSLATED,vpos.x-NewSmallFont.StringWidth(tag)/2,vpos.y-NewSmallFont.GetHeight()/2,tag); + } + + private ui void DrawDebug( RenderEvent e ) + { + if ( !swwm_debugview ) return; + // prepare projection data, we're going to need this + SWWMUtility.PrepareProjData(projdata,e.ViewPos,e.ViewAngle,e.ViewPitch,e.ViewRoll,players[consoleplayer].fov); + let ti = ThinkerIterator.Create("Actor"); + Actor a; + while ( a = Actor(ti.Next()) ) + { + if ( a == players[consoleplayer].Camera ) continue; + if ( a.bINVISIBLE && !(a is 'DynamicLight') ) continue; + if ( (a is 'Inventory') && Inventory(a).Owner ) continue; + if ( a is 'SWWMShadow' ) continue; + if ( a.Distance3DSquared(e.Camera) > 1000000 ) continue; + DrawActor(e,a); + } + } +} diff --git a/zscript/swwm_blod.zsc b/zscript/swwm_blod.zsc index 6e948bfad..85cfd09fd 100644 --- a/zscript/swwm_blod.zsc +++ b/zscript/swwm_blod.zsc @@ -258,6 +258,7 @@ Class mkBloodDrop : Actor } SWWMUtility.SetToSlope(self,FRandom[Blood](0,360)); frame = Random[Blood](5,8); + vel *= 0; return; } if ( (d.HitType == TRACE_HitCeiling) || (pos.z >= ceilingz) ) @@ -291,6 +292,7 @@ Class mkBloodDrop : Actor } SWWMUtility.SetToSlope(self,FRandom[Blood](0,360),true); frame = Random[Blood](5,8); + vel *= 0; return; } if ( d.HitType == TRACE_HitWall ) diff --git a/zscript/swwm_common_fx.zsc b/zscript/swwm_common_fx.zsc index 4882e999b..a078aa4f4 100644 --- a/zscript/swwm_common_fx.zsc +++ b/zscript/swwm_common_fx.zsc @@ -1116,7 +1116,7 @@ Class InvisibleSplasher : Actor Mass 100; VSpeed -2; Radius 2; - Radius 2; + Height 2; +NOBLOCKMAP; // needed to prevent infinite loops with some 3D floor water (yes, you read that right) FloatBobPhase 0; } diff --git a/zscript/swwm_handler.zsc b/zscript/swwm_handler.zsc index a2e04eda2..5f8a08438 100644 --- a/zscript/swwm_handler.zsc +++ b/zscript/swwm_handler.zsc @@ -189,5 +189,6 @@ Class SWWMHandler : EventHandler { CheatOverlay(e); RenderShaders(e); + DrawDebug(e); } } diff --git a/zscript/utility/swwm_utility.zsc b/zscript/utility/swwm_utility.zsc index 746e7beb9..54a18e0a9 100644 --- a/zscript/utility/swwm_utility.zsc +++ b/zscript/utility/swwm_utility.zsc @@ -1109,7 +1109,22 @@ Class SWWMUtility else pp = mo.Vec3Offset(0,0,mo.CameraHeight); Vector3 sc = level.SphericalCoords(pp,a.pos,(mo.angle,mo.pitch)); if ( (abs(sc.x) > hfov) || (abs(sc.y) > vfov) ) return false; - if ( (maxdist > 0.) && (sc.z < maxdist) ) return false; + if ( (maxdist > 0.) && (sc.z > maxdist) ) return false; + return true; + } + + // ui-friendly version without CheckSight call + static clearscope bool InPlayerFOVSimple( PlayerInfo p, Actor a, double maxdist = 0. ) + { + double vfov = p.fov*.5; + double hfov = atan(Screen.GetAspectRatio()*tan(vfov)); + let mo = p.camera; + Vector3 pp; + if ( mo is 'PlayerPawn' ) pp = mo.Vec2OffsetZ(0,0,PlayerPawn(mo).player.viewz); + else pp = mo.Vec3Offset(0,0,mo.CameraHeight); + Vector3 sc = level.SphericalCoords(pp,a.pos,(mo.angle,mo.pitch)); + if ( (abs(sc.x) > hfov) || (abs(sc.y) > vfov) ) return false; + if ( (maxdist > 0.) && (sc.z > maxdist) ) return false; return true; }