Decouple precise crosshairs from weapons. 100% smoother now.
This commit is contained in:
parent
edbc19ce64
commit
84fb9c036f
21 changed files with 194 additions and 269 deletions
|
|
@ -1,3 +1,3 @@
|
|||
[default]
|
||||
SWWM_MODVER="\cyDEMOLITIONIST \cw1.3pre r502 \cu(Sat 24 Sep 14:56:35 CEST 2022)\c-";
|
||||
SWWM_SHORTVER="\cw1.3pre r502 \cu(2022-09-24 14:56:35)\c-";
|
||||
SWWM_MODVER="\cyDEMOLITIONIST \cw1.3pre r503 \cu(Sat 24 Sep 21:33:48 CEST 2022)\c-";
|
||||
SWWM_SHORTVER="\cw1.3pre r503 \cu(2022-09-24 21:33:48)\c-";
|
||||
|
|
|
|||
|
|
@ -29,6 +29,7 @@ version "4.9"
|
|||
#include "zscript/swwm_blod.zsc"
|
||||
// handler code
|
||||
#include "zscript/handler/swwm_handler_cheats.zsc"
|
||||
#include "zscript/handler/swwm_handler_crosshair.zsc"
|
||||
#include "zscript/handler/swwm_handler_damage.zsc"
|
||||
#include "zscript/handler/swwm_handler_debugrender.zsc"
|
||||
#include "zscript/handler/swwm_handler_flash.zsc"
|
||||
|
|
|
|||
|
|
@ -44,6 +44,7 @@ Class DualPlasmaBlast : SWWMWeapon
|
|||
Obituary "$O_PLASMABLAST";
|
||||
SWWMWeapon.Tooltip "$TT_PLASMABLAST2";
|
||||
SWWMWeapon.GetLine "getplasmablast2";
|
||||
SWWMWeapon.NumCrosshairs 2;
|
||||
Weapon.SlotNumber 2;
|
||||
Weapon.SlotPriority 4.;
|
||||
Weapon.SelectionOrder 1050;
|
||||
|
|
|
|||
|
|
@ -45,7 +45,7 @@ Class HeavyMahSheenGun : SWWMWeapon
|
|||
c.vel += vel*.5;
|
||||
}
|
||||
|
||||
override Vector3 GetTraceOffset()
|
||||
override Vector3 GetTraceOffset( int index )
|
||||
{
|
||||
return (10,0,-4);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -200,7 +200,7 @@ Class MisterRifle : SWWMWeapon
|
|||
lastfiremode = firemode+1;
|
||||
}
|
||||
|
||||
override Vector3 GetTraceOffset()
|
||||
override Vector3 GetTraceOffset( int index )
|
||||
{
|
||||
return (10,2.8,-2.4);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -35,7 +35,7 @@ Class Quadravol : SWWMWeapon
|
|||
else origin.A_StartSound(UpSound,CHAN_WEAPON,CHANF_OVERLAP);
|
||||
}
|
||||
|
||||
override Vector3 GetTraceOffset()
|
||||
override Vector3 GetTraceOffset( int index )
|
||||
{
|
||||
return onehand?(10,3.5,-2):(10,3,-2.5);
|
||||
}
|
||||
|
|
|
|||
154
zscript/handler/swwm_handler_crosshair.zsc
Normal file
154
zscript/handler/swwm_handler_crosshair.zsc
Normal file
|
|
@ -0,0 +1,154 @@
|
|||
// precise crosshair (now fully independent from weapons)
|
||||
|
||||
const MAX_CROSSHAIRS = 25;
|
||||
|
||||
Class SWWMCrosshairTracer : LineTracer
|
||||
{
|
||||
Actor ignoreme;
|
||||
|
||||
override ETraceStatus TraceCallback()
|
||||
{
|
||||
if ( Results.HitType == TRACE_HitActor )
|
||||
{
|
||||
if ( Results.HitActor == ignoreme ) return TRACE_Skip;
|
||||
if ( Results.HitActor.bSHOOTABLE ) return TRACE_Stop;
|
||||
return TRACE_Skip;
|
||||
}
|
||||
else if ( (Results.HitType == TRACE_HitWall) && (Results.Tier == TIER_Middle) )
|
||||
{
|
||||
if ( !Results.HitLine.sidedef[1] || (Results.HitLine.Flags&(Line.ML_BlockHitscan|Line.ML_BlockEverything)) )
|
||||
return TRACE_Stop;
|
||||
return TRACE_Skip;
|
||||
}
|
||||
return TRACE_Stop;
|
||||
}
|
||||
}
|
||||
|
||||
extend Class SWWMHandler
|
||||
{
|
||||
transient ui SWWMCrosshairTracer ctr; // very simple crosshair tracer
|
||||
transient ui int numcrosshairs; // how many crosshairs the current weapon has
|
||||
transient ui Vector3 tpos[MAX_CROSSHAIRS]; // current trace positions in world space
|
||||
transient ui Color tcol[MAX_CROSSHAIRS]; // current crosshair colors
|
||||
transient ui SWWMProjectionData tprojdata; // cached Gutamatics projection data
|
||||
transient ui Vector3 lagtndc[MAX_CROSSHAIRS]; // "lagged" NDC for crosshairs
|
||||
transient ui Weapon lasttw; // last player weapon, to "reset" crosshair positions
|
||||
transient ui double prevframe; // previous frame timestamp
|
||||
|
||||
private ui void TraceCrosshairs( RenderEvent e )
|
||||
{
|
||||
// trace precise crosshair(s)
|
||||
Vector3 traceofs[MAX_CROSSHAIRS];
|
||||
let sw = SWWMWeapon(players[consoleplayer].ReadyWeapon);
|
||||
if ( !sw )
|
||||
{
|
||||
numcrosshairs = 1;
|
||||
traceofs[0] = (0,0,0);
|
||||
}
|
||||
else
|
||||
{
|
||||
numcrosshairs = sw.NumCrosshairs;
|
||||
for ( int i=0; i<numcrosshairs; i++ )
|
||||
traceofs[i] = sw.GetTraceOffset(i);
|
||||
}
|
||||
let mo = players[consoleplayer].mo;
|
||||
if ( !ctr ) ctr = new("SWWMCrosshairTracer");
|
||||
ctr.ignoreme = mo;
|
||||
Vector3 x, y, z, ofs, origin;
|
||||
Color col;
|
||||
[x, y, z] = swwm_CoordUtil.GetAxes(e.ViewPitch,e.ViewAngle,e.ViewRoll);
|
||||
int chp = crosshairhealth;
|
||||
for ( int i=0; i<numcrosshairs; i++ )
|
||||
{
|
||||
origin = level.Vec3Offset(e.ViewPos,traceofs[i].x*x+traceofs[i].y*y+traceofs[i].z*z);
|
||||
ctr.Trace(origin,level.PointInSector(origin.xy),x,10000.,0);
|
||||
if ( chp >= 2 )
|
||||
{
|
||||
int hp = Clamp(mo.Health,0,200);
|
||||
double sat = (hp<150)?1.:(1.-(hp-150)/100.);
|
||||
Vector3 rgb = SWWMUtility.HSVtoRGB((hp/300.,sat,1.));
|
||||
col = Color(int(rgb.x*255),int(rgb.y*255),int(rgb.z*255));
|
||||
}
|
||||
else if ( chp == 1 )
|
||||
{
|
||||
double hp = Clamp(mo.Health,0,100)/100.;
|
||||
if ( hp <= 0 ) col = Color(255,0,0);
|
||||
else if ( hp < .3 ) col = Color(255,int(hp*255/.3),0);
|
||||
else if ( hp < .85 ) col = Color(int((.6-hp)*255/.3),255,0);
|
||||
else col = Color(0,255,0);
|
||||
}
|
||||
else if ( (ctr.Results.HitType == TRACE_HitActor) && ctr.Results.HitActor.bSHOOTABLE )
|
||||
{
|
||||
// show target health, rather than our own
|
||||
double hp = ctr.Results.HitActor.Health/double(ctr.Results.HitActor.GetSpawnHealth());
|
||||
if ( hp <= 0 ) col = Color(255,0,0);
|
||||
else if ( hp < .3 ) col = Color(255,int(hp*255/.3),0);
|
||||
else if ( hp < .85 ) col = Color(int((.6-hp)*255/.3),255,0);
|
||||
else col = Color(0,255,0);
|
||||
}
|
||||
else col = crosshaircolor;
|
||||
if ( ctr.Results.HitType == TRACE_HitNone ) tpos[i] = level.Vec3Offset(origin,x*10000.);
|
||||
else tpos[i] = ctr.Results.HitPos;
|
||||
tcol[i] = col;
|
||||
}
|
||||
// copy over used slots to unused slots, so transition between weapons is smoother
|
||||
int j = 0;
|
||||
for ( int i=numcrosshairs; i<MAX_CROSSHAIRS; i++ )
|
||||
{
|
||||
tpos[i] = tpos[j];
|
||||
tcol[i] = tcol[j];
|
||||
j = (j+1)%numcrosshairs;
|
||||
}
|
||||
}
|
||||
|
||||
private ui void RenderCrosshairs( RenderEvent e )
|
||||
{
|
||||
double frametime = (MSTimeF()-prevframe)/1000.;
|
||||
double theta = clamp(15.*frametime,0.,.5); // naive, but whatever
|
||||
// draw precise crosshair(s)
|
||||
if ( automapactive || !(players[consoleplayer].Camera is 'PlayerPawn') ) return;
|
||||
if ( !swwm_precisecrosshair ) return;
|
||||
if ( crosshairforce ) return;
|
||||
if ( !crosshairon && (swwm_precisecrosshair <= 1) ) return;
|
||||
int cnum = abs(CVar.FindCVar('crosshair').GetInt());
|
||||
if ( !cnum ) return;
|
||||
String tn = String.Format("XHAIR%s%d",(Screen.GetWidth()<640)?"S":"B",cnum);
|
||||
TextureID ctex = TexMan.CheckForTexture(tn,TexMan.Type_MiscPatch);
|
||||
if ( !ctex.IsValid() ) ctex = TexMan.CheckForTexture(String.Format("XHAIR%s1",(Screen.GetWidth()<640)?"S":"B"),TexMan.Type_MiscPatch);
|
||||
if ( !ctex.IsValid() ) ctex = TexMan.CheckForTexture("XHAIRS1",TexMan.Type_MiscPatch);
|
||||
Vector2 ts = TexMan.GetScaledSize(ctex);
|
||||
double cs = crosshairscale;
|
||||
double sz = 1.;
|
||||
if ( cs > 0. ) sz = Screen.GetHeight()*cs/200.;
|
||||
if ( crosshairgrow ) sz *= StatusBar.CrosshairSize;
|
||||
SWWMUtility.PrepareProjData(tprojdata,e.ViewPos,e.ViewAngle,e.ViewPitch,e.ViewRoll,players[consoleplayer].fov);
|
||||
let w = players[consoleplayer].ReadyWeapon;
|
||||
for ( int i=0; i<numcrosshairs; i++ )
|
||||
{
|
||||
Vector3 cpos = tpos[i];
|
||||
Color ccol = tcol[i];
|
||||
Vector3 tdir = level.Vec3Diff(e.ViewPos,cpos);
|
||||
// project
|
||||
Vector3 ndc = SWWMUtility.ProjectPoint(tprojdata,e.ViewPos+tdir);
|
||||
if ( ndc.z >= 1. ) continue;
|
||||
Vector2 vpos = SWWMUtility.NDCToViewport(tprojdata,ndc);
|
||||
if ( !prevframe ) lagtndc[i] = ndc;
|
||||
if ( lagtndc[i].z >= 1. ) continue;
|
||||
Vector2 oldvpos = SWWMUtility.NDCToViewport(tprojdata,lagtndc[i]);
|
||||
lagtndc[i] = SWWMUtility.LerpVector3(lagtndc[i],ndc,theta);
|
||||
if ( lagtndc[i].z >= 1. ) continue;
|
||||
Vector2 lagvpos = SWWMUtility.NDCToViewport(tprojdata,lagtndc[i]);
|
||||
int streak = int(max(abs(oldvpos.x-lagvpos.x),abs(oldvpos.y-lagvpos.y)));
|
||||
for ( int i=0; i<streak; i++ ) Screen.DrawTexture(ctex,false,int(SWWMUtility.lerp(oldvpos.x,lagvpos.x,i/double(streak))),int(SWWMUtility.lerp(oldvpos.y,lagvpos.y,i/double(streak))),DTA_DestWidthF,ts.x*sz,DTA_DestHeightF,ts.y*sz,DTA_AlphaChannel,true,DTA_FillColor,ccol,DTA_Alpha,(i*.5)/streak);
|
||||
Screen.DrawTexture(ctex,false,int(lagvpos.x),int(lagvpos.y),DTA_DestWidthF,ts.x*sz,DTA_DestHeightF,ts.y*sz,DTA_AlphaChannel,true,DTA_FillColor,ccol);
|
||||
}
|
||||
// copy over used slots to unused slots, so transition between weapons is smoother
|
||||
int j = 0;
|
||||
for ( int i=numcrosshairs; i<MAX_CROSSHAIRS; i++ )
|
||||
{
|
||||
lagtndc[i] = lagtndc[j];
|
||||
j = (j+1)%numcrosshairs;
|
||||
}
|
||||
prevframe = MSTimeF();
|
||||
}
|
||||
}
|
||||
|
|
@ -45,16 +45,6 @@ Class SWWMGesture : SWWMWeapon
|
|||
{
|
||||
return false;
|
||||
}
|
||||
override void RenderUnderlay( RenderEvent e )
|
||||
{
|
||||
Super.RenderUnderlay(e);
|
||||
// avoid jumpy switching
|
||||
if ( formerweapon is 'SWWMWeapon' )
|
||||
{
|
||||
SWWMWeapon(formerweapon).lagvpos = lagvpos;
|
||||
SWWMWeapon(formerweapon).prevframe = prevframe;
|
||||
}
|
||||
}
|
||||
override void DoEffect()
|
||||
{
|
||||
Super.DoEffect();
|
||||
|
|
@ -666,16 +656,6 @@ Class SWWMItemGesture : SWWMWeapon abstract
|
|||
{
|
||||
return false;
|
||||
}
|
||||
override void RenderUnderlay( RenderEvent e )
|
||||
{
|
||||
Super.RenderUnderlay(e);
|
||||
// avoid jumpy switching
|
||||
if ( gest && (gest.formerweapon is 'SWWMWeapon') )
|
||||
{
|
||||
SWWMWeapon(gest.formerweapon).lagvpos = lagvpos;
|
||||
SWWMWeapon(gest.formerweapon).prevframe = prevframe;
|
||||
}
|
||||
}
|
||||
override void DoEffect()
|
||||
{
|
||||
Super.DoEffect();
|
||||
|
|
|
|||
|
|
@ -311,6 +311,8 @@ Class SWWMHandler : EventHandler
|
|||
sw.RenderUnderlay(e);
|
||||
if ( sw.bHASSCRTEX ) sw.RenderTexture(e);
|
||||
}
|
||||
TraceCrosshairs(e);
|
||||
RenderCrosshairs(e);
|
||||
if ( !statusbar || !(statusbar is 'SWWMStatusBar') ) return;
|
||||
SWWMStatusBar(statusbar).viewpos = e.viewpos;
|
||||
SWWMStatusBar(statusbar).viewrot = (e.viewangle,e.viewpitch,e.viewroll);
|
||||
|
|
|
|||
|
|
@ -432,6 +432,10 @@ Class SWWMWeapon : Weapon abstract
|
|||
virtual ui void DrawWeapon( double TicFrac, double bx, double by, double hs, Vector2 ss )
|
||||
{
|
||||
}
|
||||
// extra drawing, usually scopes
|
||||
virtual ui void RenderUnderlay( RenderEvent e )
|
||||
{
|
||||
}
|
||||
// HUD-side ticking
|
||||
virtual ui void HudTick()
|
||||
{
|
||||
|
|
|
|||
|
|
@ -1,32 +1,15 @@
|
|||
// precise crosshair
|
||||
|
||||
Class SWWMCrosshairTracer : LineTracer
|
||||
{
|
||||
Actor ignoreme;
|
||||
|
||||
override ETraceStatus TraceCallback()
|
||||
{
|
||||
if ( Results.HitType == TRACE_HitActor )
|
||||
{
|
||||
if ( Results.HitActor == ignoreme ) return TRACE_Skip;
|
||||
if ( Results.HitActor.bSHOOTABLE ) return TRACE_Stop;
|
||||
return TRACE_Skip;
|
||||
}
|
||||
else if ( (Results.HitType == TRACE_HitWall) && (Results.Tier == TIER_Middle) )
|
||||
{
|
||||
if ( !Results.HitLine.sidedef[1] || (Results.HitLine.Flags&(Line.ML_BlockHitscan|Line.ML_BlockEverything)) )
|
||||
return TRACE_Stop;
|
||||
return TRACE_Skip;
|
||||
}
|
||||
return TRACE_Stop;
|
||||
}
|
||||
}
|
||||
|
||||
extend Class SWWMWeapon
|
||||
{
|
||||
ui SWWMCrosshairTracer ctr;
|
||||
ui Vector2 lagvpos;
|
||||
transient ui double prevframe;
|
||||
int NumCrosshairs; // how many crosshairs this weapon has (for multi-barrel weapons, or dual-wielding)
|
||||
|
||||
Property NumCrosshairs : NumCrosshairs;
|
||||
|
||||
Default
|
||||
{
|
||||
SWWMWeapon.NumCrosshairs 1;
|
||||
}
|
||||
|
||||
override void DoEffect()
|
||||
{
|
||||
|
|
@ -36,93 +19,8 @@ extend Class SWWMWeapon
|
|||
else crosshair = 0;
|
||||
}
|
||||
|
||||
// extra drawing, usually scopes
|
||||
virtual ui void RenderUnderlay( RenderEvent e )
|
||||
{
|
||||
Vector3 cpos;
|
||||
Color ccol;
|
||||
[cpos, ccol] = TraceForCrosshair();
|
||||
// avoid jumpy switching
|
||||
if ( (Owner.player.PendingWeapon is 'SWWMWeapon') && (Owner.player.PendingWeapon != SisterWeapon) )
|
||||
{
|
||||
SWWMWeapon(Owner.player.PendingWeapon).lagvpos = lagvpos;
|
||||
SWWMWeapon(Owner.player.PendingWeapon).prevframe = prevframe;
|
||||
}
|
||||
// draw custom crosshair
|
||||
if ( automapactive || !(players[consoleplayer].Camera is 'PlayerPawn') ) return;
|
||||
if ( !swwm_precisecrosshair ) return;
|
||||
if ( crosshairforce ) return;
|
||||
if ( !crosshairon && (swwm_precisecrosshair <= 1) ) return;
|
||||
let sb = SWWMStatusBar(StatusBar);
|
||||
if ( !sb ) return;
|
||||
SWWMUtility.PrepareProjData(sb.projdata,e.ViewPos,e.ViewAngle,e.ViewPitch,e.ViewRoll,players[consoleplayer].fov);
|
||||
Vector3 tdir = level.Vec3Diff(e.ViewPos,cpos);
|
||||
// project
|
||||
Vector3 ndc = SWWMUtility.ProjectPoint(sb.projdata,e.ViewPos+tdir);
|
||||
if ( ndc.z >= 1. ) return;
|
||||
Vector2 vpos = SWWMUtility.NDCToViewport(sb.projdata,ndc);
|
||||
double frametime = (MSTimeF()-prevframe)/1000.;
|
||||
double theta = clamp(15.*frametime,0.,.5); // naive, but whatever
|
||||
Vector2 oldvpos = lagvpos;
|
||||
if ( !prevframe || (lagvpos == (0,0)) ) oldvpos = lagvpos = vpos;
|
||||
else lagvpos = SWWMUtility.LerpVector2(lagvpos,vpos,theta);
|
||||
prevframe = MSTimeF();
|
||||
int cnum = abs(CVar.FindCVar('crosshair').GetInt());
|
||||
if ( !cnum ) return;
|
||||
String tn = String.Format("XHAIR%s%d",(Screen.GetWidth()<640)?"S":"B",cnum);
|
||||
TextureID ctex = TexMan.CheckForTexture(tn,TexMan.Type_MiscPatch);
|
||||
if ( !ctex.IsValid() ) ctex = TexMan.CheckForTexture(String.Format("XHAIR%s1",(Screen.GetWidth()<640)?"S":"B"),TexMan.Type_MiscPatch);
|
||||
if ( !ctex.IsValid() ) ctex = TexMan.CheckForTexture("XHAIRS1",TexMan.Type_MiscPatch);
|
||||
Vector2 ts = TexMan.GetScaledSize(ctex);
|
||||
double cs = crosshairscale;
|
||||
double sz = 1.;
|
||||
if ( cs > 0. ) sz = Screen.GetHeight()*cs/200.;
|
||||
if ( crosshairgrow ) sz *= sb.CrosshairSize;
|
||||
int streak = int(max(abs(oldvpos.x-lagvpos.x),abs(oldvpos.y-lagvpos.y)));
|
||||
for ( int i=0; i<streak; i++ ) Screen.DrawTexture(ctex,false,int(SWWMUtility.lerp(oldvpos.x,lagvpos.x,i/double(streak))),int(SWWMUtility.lerp(oldvpos.y,lagvpos.y,i/double(streak))),DTA_DestWidthF,ts.x*sz,DTA_DestHeightF,ts.y*sz,DTA_AlphaChannel,true,DTA_FillColor,ccol,DTA_Alpha,(i*.5)/streak);
|
||||
Screen.DrawTexture(ctex,false,int(lagvpos.x),int(lagvpos.y),DTA_DestWidthF,ts.x*sz,DTA_DestHeightF,ts.y*sz,DTA_AlphaChannel,true,DTA_FillColor,ccol);
|
||||
}
|
||||
ui Vector3, Color TraceForCrosshair()
|
||||
{
|
||||
if ( !ctr ) ctr = new("SWWMCrosshairTracer");
|
||||
ctr.ignoreme = Owner;
|
||||
Vector3 x, y, z, ofs;
|
||||
double s;
|
||||
[x, y, z] = swwm_CoordUtil.GetAxes(Owner.pitch,Owner.angle,Owner.roll);
|
||||
ofs = GetTraceOffset();
|
||||
Vector3 origin = level.Vec3Offset(Owner.Vec2OffsetZ(0,0,Owner.player.viewz),ofs.x*x+ofs.y*y+ofs.z*z);
|
||||
ctr.Trace(origin,level.PointInSector(origin.xy),x,10000.,0);
|
||||
Color col = crosshaircolor;
|
||||
int chp = crosshairhealth;
|
||||
if ( chp >= 2 )
|
||||
{
|
||||
int hp = Clamp(Owner.Health,0,200);
|
||||
double sat = (hp<150)?1.:(1.-(hp-150)/100.);
|
||||
Vector3 rgb = SWWMUtility.HSVtoRGB((hp/300.,sat,1.));
|
||||
col = Color(int(rgb.x*255),int(rgb.y*255),int(rgb.z*255));
|
||||
}
|
||||
else if ( chp == 1 )
|
||||
{
|
||||
double hp = Clamp(Owner.Health,0,100)/100.;
|
||||
if ( hp <= 0 ) col = Color(255,0,0);
|
||||
else if ( hp < .3 ) col = Color(255,int(hp*255/.3),0);
|
||||
else if ( hp < .85 ) col = Color(int((.6-hp)*255/.3),255,0);
|
||||
else col = Color(0,255,0);
|
||||
}
|
||||
else if ( (ctr.Results.HitType == TRACE_HitActor) && ctr.Results.HitActor.bSHOOTABLE )
|
||||
{
|
||||
// show target health, rather than our own
|
||||
double hp = ctr.Results.HitActor.Health/double(ctr.Results.HitActor.GetSpawnHealth());
|
||||
if ( hp <= 0 ) col = Color(255,0,0);
|
||||
else if ( hp < .3 ) col = Color(255,int(hp*255/.3),0);
|
||||
else if ( hp < .85 ) col = Color(int((.6-hp)*255/.3),255,0);
|
||||
else col = Color(0,255,0);
|
||||
}
|
||||
if ( ctr.Results.HitType == TRACE_HitNone ) return level.Vec3Offset(origin,x*10000.), col;
|
||||
else return ctr.Results.HitPos, col;
|
||||
}
|
||||
// where the trace is coming from relative to eyes
|
||||
virtual clearscope Vector3 GetTraceOffset() const
|
||||
virtual clearscope Vector3 GetTraceOffset( int index ) const
|
||||
{
|
||||
return (0.,0.,0.);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -155,7 +155,7 @@ Class Hellblazer : SWWMWeapon
|
|||
lastammo = nextammo;
|
||||
}
|
||||
|
||||
override Vector3 GetTraceOffset()
|
||||
override Vector3 GetTraceOffset( int index )
|
||||
{
|
||||
return (10.,3.5,-5.);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -15,8 +15,6 @@ Class Wallbuster : SWWMWeapon
|
|||
|
||||
Class<Ammo> curobt;
|
||||
|
||||
ui Vector2 lagvpos25[25];
|
||||
|
||||
override String GetObituary( Actor victim, Actor inflictor, Name mod, bool playerattack )
|
||||
{
|
||||
if ( curobt is 'RedShell' ) return StringTable.Localize("$O_WALLBUSTER_RED");
|
||||
|
|
@ -40,118 +38,6 @@ Class Wallbuster : SWWMWeapon
|
|||
SelectionOrder = 1400;
|
||||
}
|
||||
|
||||
override void RenderUnderlay( RenderEvent e )
|
||||
{
|
||||
Vector3 cpos;
|
||||
Color ccol;
|
||||
[cpos, ccol] = TraceForCrosshair();
|
||||
// avoid jumpy switching
|
||||
if ( Owner.player.PendingWeapon is 'SWWMWeapon' )
|
||||
{
|
||||
SWWMWeapon(Owner.player.PendingWeapon).lagvpos = lagvpos;
|
||||
SWWMWeapon(Owner.player.PendingWeapon).prevframe = prevframe;
|
||||
}
|
||||
Vector3 cpos25[25];
|
||||
Color ccol25[25];
|
||||
// 25-trace
|
||||
for ( int i=0; i<25; i++ )
|
||||
[cpos25[i], ccol25[i]] = TraceForCrosshair25(i);
|
||||
// draw custom crosshair
|
||||
if ( automapactive || !(players[consoleplayer].Camera is 'PlayerPawn') ) return;
|
||||
if ( !swwm_precisecrosshair ) return;
|
||||
if ( crosshairforce ) return;
|
||||
if ( !crosshairon && (swwm_precisecrosshair <= 1) ) return;
|
||||
let sb = SWWMStatusBar(StatusBar);
|
||||
if ( !sb ) return;
|
||||
SWWMUtility.PrepareProjData(sb.projdata,e.ViewPos,e.ViewAngle,e.ViewPitch,e.ViewRoll,players[consoleplayer].fov);
|
||||
int cnum = abs(CVar.FindCVar('crosshair').GetInt());
|
||||
if ( !cnum ) return;
|
||||
String tn = String.Format("XHAIR%s%d",(Screen.GetWidth()<640)?"S":"B",cnum);
|
||||
TextureID ctex = TexMan.CheckForTexture(tn,TexMan.Type_MiscPatch);
|
||||
if ( !ctex.IsValid() ) ctex = TexMan.CheckForTexture(String.Format("XHAIR%s1",(Screen.GetWidth()<640)?"S":"B"),TexMan.Type_MiscPatch);
|
||||
if ( !ctex.IsValid() ) ctex = TexMan.CheckForTexture("XHAIRS1",TexMan.Type_MiscPatch);
|
||||
Vector2 ts = TexMan.GetScaledSize(ctex);
|
||||
double cs = crosshairscale;
|
||||
double sz = 1.;
|
||||
if ( cs > 0. ) sz = Screen.GetHeight()*cs/200.;
|
||||
if ( crosshairgrow ) sz *= sb.CrosshairSize;
|
||||
Vector3 tdir = level.Vec3Diff(e.ViewPos,cpos);
|
||||
// project
|
||||
Vector3 ndc = SWWMUtility.ProjectPoint(sb.projdata,e.ViewPos+tdir);
|
||||
if ( ndc.z >= 1. ) return;
|
||||
Vector2 vpos = SWWMUtility.NDCToViewport(sb.projdata,ndc);
|
||||
double frametime = (MSTimeF()-prevframe)/1000.;
|
||||
double theta = clamp(15.*frametime,0.,1.); // naive, but whatever
|
||||
if ( !prevframe || (lagvpos == (0,0)) ) lagvpos = vpos;
|
||||
else lagvpos = SWWMUtility.LerpVector2(lagvpos,vpos,theta);
|
||||
Vector2 oldvpos;
|
||||
for ( int i=0; i<25; i++ )
|
||||
{
|
||||
tdir = level.Vec3Diff(e.ViewPos,cpos25[i]);
|
||||
// project
|
||||
ndc = SWWMUtility.ProjectPoint(sb.projdata,e.ViewPos+tdir);
|
||||
if ( ndc.z >= 1. ) continue;
|
||||
vpos = SWWMUtility.NDCToViewport(sb.projdata,ndc);
|
||||
oldvpos = lagvpos25[i];
|
||||
if ( !prevframe || (lagvpos25[i] == (0,0)) ) oldvpos = lagvpos25[i] = vpos;
|
||||
else lagvpos25[i] = SWWMUtility.LerpVector2(lagvpos25[i],vpos,theta);
|
||||
int streak = int(max(abs(oldvpos.x-lagvpos25[i].x),abs(oldvpos.y-lagvpos25[i].y)));
|
||||
for ( int j=0; j<streak; j++ ) Screen.DrawTexture(ctex,false,int(SWWMUtility.lerp(oldvpos.x,lagvpos25[i].x,j/double(streak))),int(SWWMUtility.lerp(oldvpos.y,lagvpos25[i].y,j/double(streak))),DTA_DestWidthF,ts.x*sz,DTA_DestHeightF,ts.y*sz,DTA_AlphaChannel,true,DTA_FillColor,ccol,DTA_Alpha,(j*.5)/streak);
|
||||
Screen.DrawTexture(ctex,false,int(lagvpos25[i].x),int(lagvpos25[i].y),DTA_DestWidthF,ts.x*sz,DTA_DestHeightF,ts.y*sz,DTA_AlphaChannel,true,DTA_FillColor,ccol25[i]);
|
||||
}
|
||||
prevframe = MSTimeF();
|
||||
}
|
||||
|
||||
ui Vector3, Color TraceForCrosshair25( int i )
|
||||
{
|
||||
if ( !ctr ) ctr = new("SWWMCrosshairTracer");
|
||||
ctr.ignoreme = Owner;
|
||||
Vector3 x, y, z, ofs;
|
||||
double s;
|
||||
[x, y, z] = swwm_CoordUtil.GetAxes(Owner.pitch,Owner.angle,Owner.roll);
|
||||
ofs = GetTraceOffset25(i);
|
||||
Vector3 origin = level.Vec3Offset(Owner.Vec2OffsetZ(0,0,Owner.player.viewz),ofs.x*x+ofs.y*y+ofs.z*z);
|
||||
ctr.Trace(origin,level.PointInSector(origin.xy),x,10000.,0);
|
||||
Color col = crosshaircolor;
|
||||
int chp = crosshairhealth;
|
||||
if ( chp >= 2 )
|
||||
{
|
||||
int hp = Clamp(Owner.Health,0,200);
|
||||
double sat = (hp<150)?1.:(1.-(hp-150)/100.);
|
||||
Vector3 rgb = SWWMUtility.HSVtoRGB((hp/300.,sat,1.));
|
||||
col = Color(int(rgb.x*255),int(rgb.y*255),int(rgb.z*255));
|
||||
}
|
||||
else if ( chp == 1 )
|
||||
{
|
||||
double hp = Clamp(Owner.Health,0,100)/100.;
|
||||
if ( hp <= 0 ) col = Color(255,0,0);
|
||||
else if ( hp < .3 ) col = Color(255,int(hp*255/.3),0);
|
||||
else if ( hp < .85 ) col = Color(int((.6-hp)*255/.3),255,0);
|
||||
else col = Color(0,255,0);
|
||||
}
|
||||
else if ( (ctr.Results.HitType == TRACE_HitActor) && ctr.Results.HitActor.bSHOOTABLE )
|
||||
{
|
||||
// show target health, rather than our own
|
||||
double hp = ctr.Results.HitActor.Health/double(ctr.Results.HitActor.GetSpawnHealth());
|
||||
if ( hp <= 0 ) col = Color(255,0,0);
|
||||
else if ( hp < .3 ) col = Color(255,int(hp*255/.3),0);
|
||||
else if ( hp < .85 ) col = Color(int((.6-hp)*255/.3),255,0);
|
||||
else col = Color(0,255,0);
|
||||
}
|
||||
if ( ctr.Results.HitType == TRACE_HitNone ) return level.Vec3Offset(origin,x*10000.), col;
|
||||
else return ctr.Results.HitPos, col;
|
||||
}
|
||||
|
||||
clearscope Vector3 GetTraceOffset25( int i ) const
|
||||
{
|
||||
double t1 = 90-int(i%5)*72;
|
||||
double t2 = 360-int(i/5)*72;
|
||||
Vector2 b = AngleToVector(t1,1.2);
|
||||
b.y += 3.;
|
||||
Vector2 n = RotateVector(b,t2);
|
||||
return (10.,3.5+n.x,-6.+n.y);
|
||||
}
|
||||
|
||||
override bool UsesAmmo( Class<Ammo> kind )
|
||||
{
|
||||
static const Class<Ammo> types[] = {"RedShell","GreenShell","BlueShell","PurpleShell"};
|
||||
|
|
@ -283,9 +169,14 @@ Class Wallbuster : SWWMWeapon
|
|||
if ( t.Results.HitType == TRACE_HitFloor ) p.CheckSplash(40);
|
||||
}
|
||||
}
|
||||
override Vector3 GetTraceOffset()
|
||||
override Vector3 GetTraceOffset( int index )
|
||||
{
|
||||
return (10.,3.5,-6.);
|
||||
double t1 = 90-int(index%5)*72;
|
||||
double t2 = 360-int(index/5)*72;
|
||||
Vector2 b = AngleToVector(t1,1.2);
|
||||
b.y += 3.;
|
||||
Vector2 n = RotateVector(b,t2);
|
||||
return (10.,3.5+n.x,-6.+n.y);
|
||||
}
|
||||
action void A_FireShells( int num = 1 )
|
||||
{
|
||||
|
|
@ -764,6 +655,7 @@ Class Wallbuster : SWWMWeapon
|
|||
Obituary "$O_WALLBUSTER_RED";
|
||||
SWWMWeapon.Tooltip "$TT_WALLBUSTER";
|
||||
SWWMWeapon.GetLine "getwallbuster";
|
||||
SWWMWeapon.NumCrosshairs 25;
|
||||
Weapon.SlotNumber 4;
|
||||
Weapon.SelectionOrder 400;
|
||||
Weapon.UpSound "wallbuster/select";
|
||||
|
|
|
|||
|
|
@ -77,7 +77,7 @@ Class Eviscerator : SWWMWeapon
|
|||
invoker.loadtics = -delay;
|
||||
}
|
||||
|
||||
override Vector3 GetTraceOffset()
|
||||
override Vector3 GetTraceOffset( int index )
|
||||
{
|
||||
return (10.,4.,-5.);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -71,7 +71,7 @@ Class Ynykron : SWWMWeapon
|
|||
}
|
||||
}
|
||||
|
||||
override Vector3 GetTraceOffset()
|
||||
override Vector3 GetTraceOffset( int index )
|
||||
{
|
||||
return (15.,4.,-1.);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -85,7 +85,7 @@ Class DeepImpact : SWWMWeapon
|
|||
}
|
||||
}
|
||||
|
||||
override Vector3 GetTraceOffset()
|
||||
override Vector3 GetTraceOffset( int index )
|
||||
{
|
||||
return (10.,2.,-3.);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -356,7 +356,7 @@ Class Spreadgun : SWWMWeapon
|
|||
}
|
||||
}
|
||||
|
||||
override Vector3 GetTraceOffset()
|
||||
override Vector3 GetTraceOffset( int index )
|
||||
{
|
||||
return (10.,2.,-2.);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -24,7 +24,7 @@ Class Sparkster : SWWMWeapon
|
|||
return Super.ReportHUDAmmo();
|
||||
}
|
||||
|
||||
override Vector3 GetTraceOffset()
|
||||
override Vector3 GetTraceOffset( int index )
|
||||
{
|
||||
return (10.,4.5,-5.);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -12,9 +12,8 @@ Class ExplodiumGun : SWWMWeapon
|
|||
|
||||
Property ClipCount : ClipCount;
|
||||
|
||||
override Vector3 GetTraceOffset()
|
||||
override Vector3 GetTraceOffset( int index )
|
||||
{
|
||||
if ( Owner.player.ReadyWeapon == SisterWeapon ) return (10.,3.5,-2.);
|
||||
return (10.,3.,-2.);
|
||||
}
|
||||
|
||||
|
|
@ -575,16 +574,9 @@ Class DualExplodiumGun : SWWMWeapon
|
|||
|
||||
Property ClipCount : ClipCount;
|
||||
|
||||
override void RenderUnderlay( RenderEvent e )
|
||||
override Vector3 GetTraceOffset( int index )
|
||||
{
|
||||
Super.RenderUnderlay(e);
|
||||
// draw both crosshairs
|
||||
SWWMWeapon(SisterWeapon).RenderUnderlay(e);
|
||||
}
|
||||
|
||||
override Vector3 GetTraceOffset()
|
||||
{
|
||||
if ( Owner.player.ReadyWeapon == SisterWeapon ) return (10.,-3.,-2.);
|
||||
if ( index == 1 ) return (10.,3.5,-2.);
|
||||
return (10.,-3.5,-2.);
|
||||
}
|
||||
|
||||
|
|
@ -777,6 +769,7 @@ Class DualExplodiumGun : SWWMWeapon
|
|||
Obituary "$O_EXPLODIUM";
|
||||
SWWMWeapon.Tooltip "$TT_EXPLODIUM2";
|
||||
SWWMWeapon.GetLine "getexplodiumgun2";
|
||||
SWWMWeapon.NumCrosshairs 2;
|
||||
Weapon.UpSound "explodium/select";
|
||||
Weapon.SisterWeapon "ExplodiumGun";
|
||||
Weapon.SlotNumber 2;
|
||||
|
|
|
|||
|
|
@ -113,7 +113,7 @@ Class CandyGun : SWWMWeapon
|
|||
return gotstuff, gotspares;
|
||||
}
|
||||
|
||||
override Vector3 GetTraceOffset()
|
||||
override Vector3 GetTraceOffset( int index )
|
||||
{
|
||||
return (10.,3,-2.);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -614,7 +614,7 @@ Class SilverBullet : SWWMWeapon
|
|||
s.Explode();
|
||||
}
|
||||
}
|
||||
override Vector3 GetTraceOffset()
|
||||
override Vector3 GetTraceOffset( int index )
|
||||
{
|
||||
if ( zoomed ) return (0.,0.,0.);
|
||||
return (10.,1,-1.);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue