- CORRECTPIXELSTRETCH where needed on models. - Replace CoordUtil.GetAxes with quaternion version.
342 lines
9.8 KiB
Text
342 lines
9.8 KiB
Text
Class URifleAmmo : Ammo
|
|
{
|
|
Default
|
|
{
|
|
Tag "$T_RIFLEAMMO";
|
|
Inventory.Icon "I_RifleA";
|
|
Inventory.PickupMessage "";
|
|
Inventory.Amount 8;
|
|
Inventory.MaxAmount 50;
|
|
Ammo.BackpackAmount 4;
|
|
Ammo.BackpackMaxAmount 100;
|
|
Ammo.DropAmount 8;
|
|
+INVENTORY.IGNORESKILL;
|
|
}
|
|
override String PickupMessage()
|
|
{
|
|
if ( PickupMsg.Length() > 0 ) return Super.PickupMessage();
|
|
return String.Format("%s%d%s",StringTable.Localize("$I_RIFLEAMMOL"),Amount,StringTable.Localize("$I_RIFLEAMMOR"));
|
|
}
|
|
States
|
|
{
|
|
Spawn:
|
|
SBOX A -1;
|
|
Stop;
|
|
}
|
|
}
|
|
|
|
Class URifleAmmo2 : URifleAmmo
|
|
{
|
|
Default
|
|
{
|
|
Tag "$T_RIFLEAMMO2";
|
|
Inventory.PickupMessage "$I_RIFLEAMMO2";
|
|
Inventory.Amount 1;
|
|
Ammo.DropAmount 1;
|
|
+INVENTORY.IGNORESKILL;
|
|
}
|
|
States
|
|
{
|
|
Spawn:
|
|
SRND A -1;
|
|
Stop;
|
|
}
|
|
}
|
|
|
|
Class URifle : UnrealWeapon
|
|
{
|
|
double sniperzoom;
|
|
ui TextureID reticle;
|
|
transient ui Font zfont;
|
|
bool bLightOn;
|
|
UFlashLight1 lt[2];
|
|
|
|
override void PreRender( double lbottom )
|
|
{
|
|
if ( sniperzoom <= 1. ) return;
|
|
if ( reticle.IsNull() ) reticle = TexMan.CheckForTexture("UReticle",Texman.Type_Any);
|
|
Screen.DrawTexture(reticle,false,320,320,DTA_VirtualWidth,640,DTA_VirtualHeight,640,DTA_LegacyRenderStyle,STYLE_Stencil,DTA_FillColor,Color(255,0,0));
|
|
if ( !zfont ) zfont = Font.GetFont('UTFont40');
|
|
Screen.DrawText(zfont,Font.CR_UNTRANSLATED,700,700,String.Format("X%.1f",sniperzoom),DTA_VirtualWidth,1280,DTA_VirtualHeight,960,DTA_LegacyRenderStyle,STYLE_Stencil,DTA_FillColor,Color(255,0,0));
|
|
}
|
|
override void DetachFromOwner()
|
|
{
|
|
Super.DetachFromOwner();
|
|
PlayerInfo p = players[consoleplayer];
|
|
if ( p.Camera == Owner ) PPShader.SetEnabled("URifleScope",false);
|
|
bLightOn = false;
|
|
if ( lt[0] ) lt[0].Destroy();
|
|
if ( lt[1] ) lt[1].Destroy();
|
|
}
|
|
override void RenderOverlay( RenderEvent e )
|
|
{
|
|
PlayerInfo p = players[consoleplayer];
|
|
if ( (p.Camera != Owner) || (sniperzoom <= 1.) ) PPShader.SetEnabled("URifleScope",false);
|
|
else PPShader.SetEnabled("URifleScope",sting_zoomshader);
|
|
}
|
|
override void DoEffect()
|
|
{
|
|
Super.DoEffect();
|
|
bALT_AMMO_OPTIONAL = !sting_rifle;
|
|
if ( sniperzoom > 1.0 ) crosshair = 99;
|
|
else crosshair = 0;
|
|
}
|
|
action void A_ToggleLight()
|
|
{
|
|
invoker.bLightOn = !invoker.bLightOn;
|
|
A_StartSound(invoker.bLightOn?"lite/pickup":"lite/off",CHAN_ITEM);
|
|
if ( invoker.bLightOn )
|
|
{
|
|
if ( !invoker.lt[0] ) invoker.lt[0] = UFlashLight1(Spawn("UFlashLight1",pos));
|
|
invoker.lt[0].target = self;
|
|
invoker.lt[0].master = invoker;
|
|
invoker.lt[0].basecolor[0] = 255;
|
|
invoker.lt[0].basecolor[1] = 224;
|
|
invoker.lt[0].basecolor[2] = 192;
|
|
invoker.lt[0].args[3] = 480;
|
|
invoker.lt[0].SpotInnerAngle = 2;
|
|
invoker.lt[0].SpotOuterAngle = 9;
|
|
if ( !invoker.lt[1] ) invoker.lt[1] = UFlashLight1(Spawn("UFlashLight2",pos));
|
|
invoker.lt[1].target = self;
|
|
invoker.lt[1].master = invoker;
|
|
invoker.lt[1].basecolor[0] = 128;
|
|
invoker.lt[1].basecolor[1] = 112;
|
|
invoker.lt[1].basecolor[2] = 96;
|
|
invoker.lt[1].args[3] = 500;
|
|
invoker.lt[1].SpotOuterAngle = 15;
|
|
}
|
|
else
|
|
{
|
|
if ( invoker.lt[0] ) invoker.lt[0].Destroy();
|
|
if ( invoker.lt[1] ) invoker.lt[1].Destroy();
|
|
}
|
|
}
|
|
action void A_RifleFire( bool zoomed = false, bool alt = false )
|
|
{
|
|
Weapon weap = Weapon(invoker);
|
|
if ( !weap ) return;
|
|
if ( weap.Ammo1.Amount <= 0 ) return;
|
|
if ( !weap.DepleteAmmo(weap.bAltFire,true,1) ) return;
|
|
if ( self is 'UTPlayer' )
|
|
UTPlayer(self).PlayAttacking3();
|
|
invoker.FireEffect();
|
|
UTMainHandler.DoFlash(self,Color(32,0,0,255),1);
|
|
if ( alt ) A_StartSound("rifle/fire",CHAN_WEAPON,CHANF_OVERLAP,Dampener.Active(self)?.3:1.,pitch:FRandom[Sniper](0.9,1.1));
|
|
else A_StartSound("rifle/fire",CHAN_WEAPON,CHANF_OVERLAP,Dampener.Active(self)?.3:1.);
|
|
if ( !Dampener.Active(self) ) A_AlertMonsters();
|
|
if ( zoomed ) A_QuakeEx(1,1,1,2,0,1,"",QF_RELATIVE|QF_SCALEDOWN,rollIntensity:0.09);
|
|
else
|
|
{
|
|
A_QuakeEx(2,2,2,3,0,1,"",QF_RELATIVE|QF_SCALEDOWN,rollIntensity:0.12);
|
|
A_Overlay(-2,"MuzzleFlash");
|
|
A_OverlayFlags(-2,PSPF_RENDERSTYLE|PSPF_FORCESTYLE,true);
|
|
A_OverlayRenderstyle(-2,STYLE_Add);
|
|
}
|
|
let l = Spawn("SniperLight",pos);
|
|
l.target = self;
|
|
Vector3 x, y, z, x2, y2, z2, dir;
|
|
[x, y, z] = dt_Utility.GetAxes(angle,pitch,roll);
|
|
Vector3 origin = level.Vec3Offset(Vec2OffsetZ(0,0,player.viewz),10*x);
|
|
if ( !zoomed ) origin = level.Vec3Offset(origin,-y*3-z*2);
|
|
FLineTraceData d;
|
|
[x2, y2, z2] = dt_Utility.GetAxes(angle,BulletSlope(),roll);
|
|
if ( alt ) dir = dt_Utility.ConeSpread(x2,y2,z2,FRandom[Rifle](0,360),FRandom[Rifle](0.,.25));
|
|
else dir = x2;
|
|
LineTrace(atan2(dir.y,dir.x),10000,asin(-dir.z),TRF_ABSPOSITION,origin.z,origin.x,origin.y,d);
|
|
UTBulletTrail.DoTrail(self,origin,dir,10000,alt?3:1);
|
|
if ( d.HitType == TRACE_HitActor )
|
|
{
|
|
int dmg = 45;
|
|
if ( d.HitLocation.z >= (d.HitActor.pos.z+d.HitActor.height*0.81) )
|
|
{
|
|
dmg = d.HitActor.DamageMobj(invoker,self,100,'Decapitated',DMG_USEANGLE|DMG_THRUSTLESS,atan2(d.HitDir.y,d.HitDir.x));
|
|
UTMainHandler.DoKnockback(d.HitActor,d.HitDir,35000);
|
|
}
|
|
else
|
|
{
|
|
dmg = d.HitActor.DamageMobj(invoker,self,dmg,'shot',DMG_USEANGLE|DMG_THRUSTLESS,atan2(d.HitDir.y,d.HitDir.x));
|
|
UTMainHandler.DoKnockback(d.HitActor,d.HitDir,30000);
|
|
}
|
|
if ( d.HitActor.bNOBLOOD )
|
|
{
|
|
let p = Spawn("BulletImpact",d.HitLocation);
|
|
p.scale *= 1.5;
|
|
p.angle = atan2(d.HitDir.y,d.HitDir.x)+180;
|
|
p.pitch = asin(d.HitDir.z);
|
|
}
|
|
else
|
|
{
|
|
d.HitActor.TraceBleed(dmg,self);
|
|
d.HitActor.SpawnBlood(d.HitLocation,atan2(d.HitDir.y,d.HitDir.x)+180,dmg);
|
|
}
|
|
}
|
|
else if ( d.HitType != TRACE_HitNone )
|
|
{
|
|
Vector3 hitnormal = -d.HitDir;
|
|
if ( d.HitType == TRACE_HitFloor )
|
|
{
|
|
if ( d.Hit3DFloor ) hitnormal = -d.Hit3DFloor.top.Normal;
|
|
else hitnormal = d.HitSector.floorplane.Normal;
|
|
}
|
|
else if ( d.HitType == TRACE_HitCeiling )
|
|
{
|
|
if ( d.Hit3DFloor ) hitnormal = -d.Hit3DFloor.bottom.Normal;
|
|
else hitnormal = d.HitSector.ceilingplane.Normal;
|
|
}
|
|
else if ( d.HitType == TRACE_HitWall )
|
|
{
|
|
hitnormal = (-d.HitLine.delta.y,d.HitLine.delta.x,0).unit();
|
|
if ( !d.LineSide ) hitnormal *= -1;
|
|
}
|
|
let p = Spawn("BulletImpact",d.HitLocation+hitnormal*0.01);
|
|
p.scale *= 1.5;
|
|
p.angle = atan2(hitnormal.y,hitnormal.x);
|
|
p.pitch = asin(-hitnormal.z);
|
|
if ( d.HitLine ) d.HitLine.RemoteActivate(self,d.LineSide,SPAC_Impact,d.HitLocation);
|
|
}
|
|
for ( int i=0; i<24; i++ )
|
|
{
|
|
let s = Spawn("UTStaticViewSmoke",origin);
|
|
UTViewSmoke(s).ofs = (10,-3,-2);
|
|
UTViewSmoke(s).vvel += (FRandom[Sniper](-0.05,0.15),FRandom[Sniper](-1.2,1.2),FRandom[Sniper](-0.1,0.1));
|
|
s.target = self;
|
|
s.scale *= 1.8;
|
|
s.alpha *= 0.3;
|
|
}
|
|
origin = level.Vec3Offset(origin,x*4-y*6-z*10);
|
|
let c = Spawn("UCasing",origin);
|
|
c.scale *= 1.25;
|
|
c.angle = angle;
|
|
c.pitch = pitch;
|
|
c.vel = x*FRandom[Junk](-1.5,1.5)+y*FRandom[Junk](2,4)+z*FRandom[Junk](2,3);
|
|
}
|
|
override String GetObituary( Actor victim, Actor inflictor, Name mod, bool playerattack )
|
|
{
|
|
if ( mod == 'Decapitated' ) return StringTable.Localize("$O_SNIPERDECAP");
|
|
return Obituary;
|
|
}
|
|
Default
|
|
{
|
|
Tag "$T_RIFLE";
|
|
Obituary "$O_SNIPER";
|
|
Inventory.PickupMessage "$I_RIFLE";
|
|
Weapon.UpSound "rifle/select";
|
|
Weapon.SlotNumber 9;
|
|
Weapon.SelectionOrder 900;
|
|
Weapon.SlotPriority 1;
|
|
Weapon.AmmoType "URifleAmmo";
|
|
Weapon.AmmoUse 1;
|
|
Weapon.AmmoType2 "URifleAmmo";
|
|
Weapon.AmmoUse2 1;
|
|
Weapon.AmmoGive 8;
|
|
Weapon.Kickback 250;
|
|
UTWeapon.DropAmmo 4;
|
|
+NOEXTREMEDEATH;
|
|
}
|
|
States
|
|
{
|
|
Spawn:
|
|
SRFP A -1;
|
|
Stop;
|
|
SRFP B -1;
|
|
Stop;
|
|
Select:
|
|
SRFS A 1 A_Raise(int.max);
|
|
Wait;
|
|
Ready:
|
|
SRFS A 0 A_ZoomFactor(invoker.sniperzoom=1.0,ZOOM_INSTANT);
|
|
SRFS ABCDEFGHIJKLMNOPQRST 1 A_WeaponReady(WRF_NOFIRE);
|
|
Idle:
|
|
SRFI A 1
|
|
{
|
|
A_CheckReload();
|
|
A_WeaponReady(sting_riflel?(WRF_ALLOWZOOM|WRF_ALLOWRELOAD):WRF_ALLOWZOOM);
|
|
}
|
|
Wait;
|
|
ZoomedIdle:
|
|
TNT1 A 1
|
|
{
|
|
A_CheckReload();
|
|
A_WeaponReady(sting_riflel?(WRF_ALLOWZOOM|WRF_ALLOWRELOAD):WRF_ALLOWZOOM);
|
|
}
|
|
Wait;
|
|
Fire:
|
|
SRFF A 0 A_JumpIf(invoker.sniperzoom>1.0,"ZoomedFire");
|
|
SRFF A 0 A_RifleFire();
|
|
SRFF ABCDEFGHIJ 2;
|
|
Goto Idle;
|
|
ZoomedFire:
|
|
TNT1 A 20 A_RifleFire(true);
|
|
Goto ZoomedIdle;
|
|
AltFire:
|
|
SRFF A 0 A_JumpIf(!sting_rifle,"Zoom");
|
|
SRFF A 0 A_JumpIf(invoker.sniperzoom>1.0,"ZoomedAltFire");
|
|
SRFF A 0 A_RifleFire(false,true);
|
|
SRFF ABCDEFG 1;
|
|
SRFF A 0 A_JumpIfNoAmmo("AltFireEnd");
|
|
SRFF A 0 A_RifleFire(false,true);
|
|
SRFF ABCDEFG 1;
|
|
SRFF A 0 A_JumpIfNoAmmo("AltFireEnd");
|
|
SRFF A 0 A_RifleFire(false,true);
|
|
SRFF ABCDEFG 1;
|
|
AltFireEnd:
|
|
SRFF HIJ 1;
|
|
SRFI A 3;
|
|
Goto Idle;
|
|
ZoomedAltFire:
|
|
TNT1 A 7 A_RifleFire(true,true);
|
|
TNT1 A 0 A_JumpIfNoAmmo("ZoomedAltFireEnd");
|
|
TNT1 A 7 A_RifleFire(true,true);
|
|
TNT1 A 0 A_JumpIfNoAmmo("ZoomedAltFireEnd");
|
|
TNT1 A 7 A_RifleFire(true,true);
|
|
ZoomedAltFireEnd:
|
|
TNT1 A 6;
|
|
Goto ZoomedIdle;
|
|
Reload:
|
|
SRFI A 0 A_JumpIf(invoker.sniperzoom>1.0,"ZoomedReload");
|
|
SRFI A 8 A_ToggleLight();
|
|
Goto Idle;
|
|
ZoomedReload:
|
|
TNT1 A 8 A_ToggleLight();
|
|
Goto Idle;
|
|
Zoom:
|
|
SRSU A 0 A_JumpIf(invoker.sniperzoom>1.0,"ZoomOut");
|
|
SRSU A 0 A_StartSound("rifle/scopeon",CHAN_WEAPONMISC,volume:.5);
|
|
SRSU ABCDEFGHIJKLMN 1;
|
|
SRSI A 0;
|
|
Goto ZoomHold;
|
|
ZoomHold:
|
|
TNT1 A 1
|
|
{
|
|
if ( invoker.sniperzoom <= 8.0 )
|
|
A_ZoomFactor(invoker.sniperzoom*=1.1);
|
|
invoker.sniperzoom = min(invoker.sniperzoom,8.1);
|
|
}
|
|
TNT1 A 0 A_JumpIf(player.cmd.buttons&(BT_ALTATTACK|BT_ZOOM),"ZoomHold");
|
|
Goto ZoomedIdle;
|
|
ZoomOut:
|
|
SRSD A 0 A_ZoomFactor(invoker.sniperzoom=1.0,ZOOM_INSTANT);
|
|
SRSD A 0 A_StartSound("rifle/scopeoff",CHAN_WEAPONMISC,volume:.5);
|
|
SRSI A 1;
|
|
SRSD ABCDEFGHIJKLMNO 1;
|
|
Goto Idle;
|
|
Deselect:
|
|
SRFD A 0 A_JumpIf(invoker.sniperzoom<=1.0,"Deselect2");
|
|
SRSD A 0 A_ZoomFactor(invoker.sniperzoom=1.0,ZOOM_INSTANT);
|
|
SRSD A 0 A_StartSound("rifle/scopeoff",CHAN_WEAPONMISC,volume:.5);
|
|
SRSI A 1;
|
|
SRSD ABCDEFGHIJKLMNO 1;
|
|
Deselect2:
|
|
SRFD A 0
|
|
{
|
|
A_ZoomFactor(invoker.sniperzoom=1.0,ZOOM_INSTANT);
|
|
if ( invoker.bLightOn ) A_ToggleLight();
|
|
}
|
|
SRFD ABCDEFG 1;
|
|
SRFD H 1 A_Lower(int.max);
|
|
Wait;
|
|
MuzzleFlash:
|
|
SMUZ A 3 Bright;
|
|
Stop;
|
|
}
|
|
}
|