diff --git a/language.txt b/language.txt index f9fb012..1c24293 100644 --- a/language.txt +++ b/language.txt @@ -190,6 +190,7 @@ M_SENTRYDOWN = "Your Sentry has been destroyed."; M_SENTRYDRY = "Your Sentry has run out of ammo."; M_SENTRYHIJACK = "Your Sentry has been hijacked."; M_MSNOROOM = "No room to deploy Sentry."; +M_NSTOOFAR = "Cannot recall Sentry from this distance."; M_FFNOROOM = "No room to activate Force Field."; S_MINHUD = "Health %d Score %d Ammo %d"; S_MINHUD2 = "Health %d Score %d Ammo %d/%d"; @@ -409,6 +410,7 @@ M_SENTRYDOWN = "Tu Torreta ha sido destruida."; M_SENTRYDRY = "Tu Torreta se ha quedado sin munición."; M_SENTRYHIJACK = "Tu Torreta ha sido hackeada."; M_MSNOROOM = "No hay espacio para colocar la Torreta."; +M_NSTOOFAR = "No se puede retirar la Torreta desde esta distancia."; M_FFNOROOM = "No hay espacio para activar el Campo de Fuerza."; S_MINHUD = "Salud %d Puntuación %d Munición %d"; S_MINHUD2 = "Salud %d Puntuación %d Munición %d/%d"; diff --git a/modeldef.umisc b/modeldef.umisc index e707e6a..48e6685 100644 --- a/modeldef.umisc +++ b/modeldef.umisc @@ -565,6 +565,23 @@ Model "MinigunSentryX" FrameIndex SENF P 0 47 // shoot } +Model "SentryFragment" +{ + Path "models" + Model 0 "sfrag_d.3d" + Skin 0 "Minigun.png" + Scale 0.1 0.1 0.12 + USEACTORPITCH + USEACTORROLL + + FrameIndex CHIP A 0 0 + FrameIndex CHIP B 0 1 + FrameIndex CHIP C 0 2 + FrameIndex CHIP D 0 3 + FrameIndex CHIP E 0 4 + FrameIndex CHIP F 0 5 +} + Model "MinigunSentryBase" { Path "models" diff --git a/models/sfrag_a.3d b/models/sfrag_a.3d new file mode 100644 index 0000000..dfd5dbe Binary files /dev/null and b/models/sfrag_a.3d differ diff --git a/models/sfrag_d.3d b/models/sfrag_d.3d new file mode 100644 index 0000000..cc3657c Binary files /dev/null and b/models/sfrag_d.3d differ diff --git a/sndinfo.txt b/sndinfo.txt index e08ca02..e75da72 100644 --- a/sndinfo.txt +++ b/sndinfo.txt @@ -225,3 +225,8 @@ sentry/raise sentup sentry/wind sentwind sentry/fire sentfire sentry/unwind sentuwnd +sentry/explode cannonex + +vfrag/bounce1 glasstk1 +vfrag/bounce2 glasstk2 +$random vfrag/bounce { vfrag/bounce1 vfrag/bounce2 } diff --git a/sounds/CannonEx.ogg b/sounds/CannonEx.ogg new file mode 100644 index 0000000..a76ae2e Binary files /dev/null and b/sounds/CannonEx.ogg differ diff --git a/sounds/GlassTk1.ogg b/sounds/GlassTk1.ogg new file mode 100644 index 0000000..1d3545b Binary files /dev/null and b/sounds/GlassTk1.ogg differ diff --git a/sounds/GlassTk2.ogg b/sounds/GlassTk2.ogg new file mode 100644 index 0000000..1d011a0 Binary files /dev/null and b/sounds/GlassTk2.ogg differ diff --git a/zscript/asmd.zsc b/zscript/asmd.zsc index 1adf27b..e2833ce 100644 --- a/zscript/asmd.zsc +++ b/zscript/asmd.zsc @@ -532,7 +532,7 @@ Class ASMDBeam : Actor Actor r; if ( t.Results.HitActor is 'ASMDHitbox' ) { - BeamExplode(true); + BeamExplode(mult>1.5); if ( target ) { target.TakeInventory('ASMDAmmo',2); diff --git a/zscript/miscitems.zsc b/zscript/miscitems.zsc index 80dd54a..78b4dd3 100644 --- a/zscript/miscitems.zsc +++ b/zscript/miscitems.zsc @@ -431,6 +431,28 @@ Class VoiceBoxActive : Actor bMOVEWITHSECTOR = false; bFORCEXYBILLBOARD = true; A_SetScale(FRandomPick[ExploS](-1.5,1.5),FRandomPick[ExploS](-1.5,1.5)); + int numpt = Random[ExploS](15,30); + for ( int i=0; i 80 ) + { + if ( Owner.CheckLocalView() ) Console.Printf(StringTable.Localize("$M_NSTOOFAR")); + return false; + } + tracer.SetStateLabel("PackUp"); return false; } + Vector3 origin = Owner.Vec2OffsetZ(0,0,Owner.player.viewz); + FLineTraceData d; + Owner.LineTrace(Owner.angle,90,Owner.pitch,TRF_ABSPOSITION,origin.z,origin.x,origin.y,data:d); + if ( d.HitType != TRACE_HitNone ) origin = d.HitLocation-d.HitDir*20; + else origin = d.HitLocation; + Owner.LineTrace(0,56,90,TRF_ABSPOSITION,origin.z,origin.x,origin.y,data:d); + origin = d.HitLocation; let a = Spawn("MinigunSentryBase",origin); if ( !a.TestMobjLocation() ) { @@ -1416,7 +1509,8 @@ Class SentryItem : UnrealInventory return; } Charge = tracer.Health; - if ( Charge <= 0 ) DepleteOrDestroy(); + special1 = tracer.special1; + if ( Charge <= 0 ) Destroy(); } override void Travelled() { @@ -1425,7 +1519,7 @@ Class SentryItem : UnrealInventory { bUNTOSSABLE = false; bUNDROPPABLE = false; - DepleteOrDestroy(); + Destroy(); } } States @@ -1481,8 +1575,8 @@ Class MinigunSentryX : Actor // The "head" of the sentry, attaches to the body Class MinigunSentry : Actor { - const maxangle = 60; - const maxpitch = 30; + const maxangle = 80; + const maxpitch = 40; Default { @@ -1545,7 +1639,7 @@ Class MinigunSentry : Actor } void A_SentryAttack() { - special1 = max(0,special1-1); + master.special1 = special1 = max(0,special1-1); if ( (special1 <= 0) && master.master && master.master.CheckLocalView() ) Console.Printf(StringTable.Localize("$M_SENTRYDRY")); A_SentryFaceTarget(); master.A_AlertMonsters(0,AMF_TARGETEMITTER); @@ -1553,7 +1647,7 @@ Class MinigunSentry : Actor Vector3 x, y, z, origin; [x, y, z] = dt_CoordUtil.GetAxes(pitch,angle,roll); origin = level.Vec3Offset(pos,x*24+z*8); - double a = FRandom[Sentry](0,360), s = FRandom[Sentry](0,0.15); + double a = FRandom[Sentry](0,360), s = FRandom[Sentry](0,0.04); Vector3 dir = (x+y*cos(a)*s+z*sin(a)*s).unit(); FLineTraceData d; master.LineTrace(atan2(dir.y,dir.x),10000,asin(-dir.z),TRF_ABSPOSITION,origin.z,origin.x,origin.y,d); @@ -1692,7 +1786,7 @@ Class MinigunSentry : Actor SENU A 0 { A_LookEx(LOF_NOSOUNDCHECK|LOF_NOJUMP); - if ( TargetVisible() ) return ResolveState("MissileLoop"); + if ( TargetVisible() && (special1>0) ) return ResolveState("MissileLoop"); A_PlaySound("sentry/unwind"); master.SetStateLabel("MissileEnd"); return ResolveState(null); @@ -1716,21 +1810,180 @@ Class MinigunSentry : Actor Class SentryFragment : Actor { + int deadtimer; + double rollvel, anglevel, pitchvel; + double heat; + + Default + { + Radius 2; + Height 2; + +NOBLOCKMAP; + +MISSILE; + +MOVEWITHSECTOR; + +THRUACTORS; + +NOTELEPORT; + +DONTSPLASH; + +INTERPOLATEANGLES; + +USEBOUNCESTATE; + BounceType "Doom"; + BounceFactor 0.3; + Gravity 0.35; + } + override void PostBeginPlay() + { + Super.PostBeginPlay(); + deadtimer = 0; + anglevel = FRandom[Junk](10,30)*RandomPick[Junk](-1,1); + pitchvel = FRandom[Junk](10,30)*RandomPick[Junk](-1,1); + rollvel = FRandom[Junk](10,30)*RandomPick[Junk](-1,1); + frame = Random[Junk](0,5); + scale *= Frandom[Junk](0.8,1.2); + heat = 1.5; + } + override void Tick() + { + Super.Tick(); + if ( isFrozen() ) return; + if ( heat > 0 ) + { + heat -= FRandom[Junk](0.003,0.006); + let s = Spawn("UTSmoke",pos); + s.alpha *= min(1.,heat)*0.6*alpha; + } + if ( InStateSequence(CurState,ResolveState("Death")) ) + { + deadtimer++; + if ( deadtimer > 300 ) A_FadeOut(0.05); + return; + } + } + States + { + Spawn: + CHIP # 1 + { + angle += anglevel; + pitch += pitchvel; + roll += rollvel; + } + Loop; + Bounce: + CHIP # 0 + { + anglevel = FRandom[Junk](10,30)*RandomPick[Junk](-1,1); + pitchvel = FRandom[Junk](10,30)*RandomPick[Junk](-1,1); + rollvel = FRandom[Junk](10,30)*RandomPick[Junk](-1,1); + vel = (vel.unit()+(FRandom[Junk](-.2,.2),FRandom[Junk](-.2,.2),FRandom[Junk](-.2,.2))).unit()*vel.length(); + A_PlaySound("vfrag/bounce",CHAN_BODY,min(1.,vel.length()*0.1),pitch:FRandom[Junk](0.6,1.4)); + } + Goto Spawn; + Death: + CHIP # -1 + { + pitch = int(pitch/180)*180; + roll = int(roll/180)*180; + } + Stop; + Dummy: + CHIP ABCDEF -1; + Stop; + } +} + +Class SentryXLight : PaletteLight +{ + Default + { + ReactionTime 30; + Args 0,0,0,120; + } } Class SentryBoom : Actor { + Default + { + RenderStyle "Add"; + Scale 3.2; + +NOGRAVITY; + +NOBLOCKMAP; + +NODAMAGETHRUST; + +FORCERADIUSDMG; + +FORCEXYBILLBOARD; + } + override void PostBeginPlay() + { + Super.PostBeginPlay(); + A_Explode(80,250); + A_PlaySound("sentry/explode"); + UTMainHandler.DoBlast(self,250,70000); + double ang, pt; + for ( int i=0; i<16; i++ ) + { + let f = Spawn("SentryFragment",Vec3Offset(FRandom[EFrag](-8,8),FRandom[EFrag](-8,8),FRandom[EFrag](4,40))); + ang = FRandom[EFrag](0,360); + pt = FRandom[EFrag](-90,90); + f.vel = (cos(ang)*cos(pt),sin(ang)*cos(pt),-sin(pt))*FRandom[EFrag](8,15); + } + Scale.x *= RandomPick[EFrag](-1,1); + Scale.y *= RandomPick[EFrag](-1,1); + int numpt = Random[ExploS](20,25); + for ( int i=0; i= sentryammo) ) return; A_PlaySound("misc/i_pkup",CHAN_ITEM); int xammo = min(sentryammo-tracer.special1,amo.Amount); - tracer.special1 += xammo; + special1 = tracer.special1 += xammo; amo.Amount -= xammo; } override int DamageMobj( Actor inflictor, Actor source, int damage, Name mod, int flags, double angle ) @@ -1841,10 +2075,6 @@ Class MinigunSentryBase : Actor if ( tracer && !tracer.target ) tracer.target = target; return dmg; } - override void Die( Actor source, Actor inflictor, int dmgflags, Name MeansOfDeath ) - { - Super.Die(source,inflictor,dmgflags,MeansOfDeath); - } States { Spawn: @@ -1866,6 +2096,7 @@ Class MinigunSentryBase : Actor PackUp: SENI A -1 { + bSPECIAL = false; tracer.SetStateLabel("PackUp"); } Stop; @@ -1891,7 +2122,7 @@ Class MinigunSentryBase : Actor } Stop; Death: - TNT1 A 1 Spawn("SentryBoom",pos); + TNT1 A 1 Spawn("SentryBoom",Vec3Offset(0,0,height/2)); Stop; } } diff --git a/zscript/ueightball.zsc b/zscript/ueightball.zsc index 3b9a02c..a09aad0 100644 --- a/zscript/ueightball.zsc +++ b/zscript/ueightball.zsc @@ -516,10 +516,10 @@ Class Eightball : UnrealWeapon EBLS ABCDEFGHIJKLMNO 1 A_WeaponReady(WRF_NOFIRE); Ready2: EBLS O 0 A_CheckReload(); - EBLL A 0 A_PlaySound("utrl/load",CHAN_ITEM,Dampener.Active(self)?.1:1.); - EBLL ABCDEFGHIJK 2; + EBLL A 0 A_PlaySound("utrl/load",CHAN_6,Dampener.Active(self)?.1:1.); + EBLL ABCDEFGHIJK 1 A_WeaponReady(WRF_NOFIRE); EBLL L 0 A_PlaySound("utrl/rotate",CHAN_ITEM,Dampener.Active(self)?.01:.1); - EBLL LMNOPQRSTUVWXYZ[ 1; + EBLL LMNOPQRSTUVWXYZ[ 1 A_WeaponReady(WRF_NOFIRE); EBLL Z 0; // force no tweening EBLI A 0; Goto Idle; @@ -571,8 +571,8 @@ Class Eightball : UnrealWeapon Loading: EBLI A 0; EBLL A 0 A_LoadRocket(); - EBLL A 0 A_PlaySound("utrl/load",CHAN_ITEM,Dampener.Active(self)?.1:1.); - EBLL ABCDEFGHIJK 2; + EBLL A 0 A_PlaySound("utrl/load",CHAN_6,Dampener.Active(self)?.1:1.); + EBLL ABCDEFGHIJK 1; EBLL L 0 A_PlaySound("utrl/rotate",CHAN_ITEM,Dampener.Active(self)?.01:.1); EBLL LMNOPQRSTUVWXYZ[ 1; EBLL Z 0; diff --git a/zscript/uflakcannon.zsc b/zscript/uflakcannon.zsc index ba735dd..18a9f33 100644 --- a/zscript/uflakcannon.zsc +++ b/zscript/uflakcannon.zsc @@ -117,7 +117,7 @@ Class UFlakSlug : FlakSlug A_SetRenderStyle(1.0,STYLE_Add); A_SprayDecal("RocketBlast",50); A_NoGravity(); - A_SetScale(1.2); + A_SetScale(2.2); UTMainHandler.DoBlast(self,120,75000); A_Explode(70,120); A_QuakeEx(4,4,4,8,0,170,"",QF_RELATIVE|QF_SCALEDOWN,falloff:120,rollIntensity:0.2); diff --git a/zscript/unrealcommon.zsc b/zscript/unrealcommon.zsc index 2a87226..ef9e456 100644 --- a/zscript/unrealcommon.zsc +++ b/zscript/unrealcommon.zsc @@ -592,9 +592,12 @@ Class UnrealInventory : Inventory bool bActive; // is currently activated int Charge; // for timed items int DefaultCharge; + private int UItemFlags; Property Charge : DefaultCharge; + FlagDef DrawSpecial : UItemFlags, 0; // hud draws special1 as amount + // Drawstuffs under HUD virtual ui void PreRender( double lbottom ) {} // Drawstuffs over HUD diff --git a/zscript/unrealhud.zsc b/zscript/unrealhud.zsc index fd0ec22..279c18b 100644 --- a/zscript/unrealhud.zsc +++ b/zscript/unrealhud.zsc @@ -190,9 +190,9 @@ Class UnrealHUD : BaseStatusBar private void DrawNumberOf( Inventory i, double x, double y ) { - if ( i.Amount <= 1 ) return; + if ( (i.Amount <= 1) && !((i is 'UnrealInventory') || !UnrealInventory(i).bDRAWSPECIAL) ) return; double TempX = CurX, TempY = CurY; - string itxt = String.Format("%d",i.Amount); + string itxt = String.Format("%d",((i is 'UnrealInventory')&&UnrealInventory(i).bDRAWSPECIAL)?i.special1:i.Amount); CurX += 30; CurY += 23; CurX -= TinyRedFont.StringWidth(itxt); @@ -377,7 +377,7 @@ Class UnrealHUD : BaseStatusBar { bRed = ((Prev is 'UnrealInventory') && UnrealInventory(Prev).bActive) || (Prev is 'Powerup') || ((Prev is 'UTranslator') && ((bTranslatorActive) || (bFlashTranslator && ((gametic%8)<4)))); DrawHudIcon(x,y,Prev,bRed); - if ( Prev.MaxAmount > 1 ) DrawNumberOf(Prev,x,y); + if ( (Prev.MaxAmount > 1) || ((Prev is 'UnrealInventory') && UnrealInventory(Prev).bDRAWSPECIAL) ) DrawNumberOf(Prev,x,y); } bRed = ((SelectedItem is 'UnrealInventory') && UnrealInventory(SelectedItem).bActive) || (SelectedItem is 'Powerup') || ((SelectedItem is 'UTranslator') && ((bTranslatorActive) || (bFlashTranslator && ((gametic%8)<4)))); if ( !Next && !Prev && !bDrawOne ) DrawHudIcon(x+64,y,SelectedItem,bRed); @@ -386,12 +386,12 @@ Class UnrealHUD : BaseStatusBar if ( !Next && !Prev && !bDrawOne ) CurX = x+64; CurY = y; Screen.DrawTexture(IconSel,false,CurX,CurY,DTA_VirtualWidthF,ClipX,DTA_VirtualHeightF,ClipY,DTA_KeepRatio,true,DTA_Alpha,0.5); - if ( SelectedItem.MaxAmount > 1 ) DrawNumberOf(SelectedItem,CurX,y); + if ( (SelectedItem.MaxAmount > 1) || ((SelectedItem is 'UnrealInventory') && UnrealInventory(SelectedItem).bDRAWSPECIAL) ) DrawNumberOf(SelectedItem,CurX,y); if ( Next ) { bRed = ((Next is 'UnrealInventory') && UnrealInventory(Next).bActive) || (Next is 'Powerup') || ((Next is 'UTranslator') && ((bTranslatorActive) || (bFlashTranslator && ((gametic%8)<4)))); DrawHudIcon(x+64,y,Next,bRed); - if ( Next.MaxAmount > 1 ) DrawNumberOf(Next,x+64,y); + if ( (Next.MaxAmount > 1) || ((Next is 'UnrealInventory') && UnrealInventory(Next).bDRAWSPECIAL) ) DrawNumberOf(Next,x+64,y); } }