From a99c38fd75caeb3b314a119aa758e9b355528ac2 Mon Sep 17 00:00:00 2001 From: Marisa Kirisame Date: Sat, 18 Aug 2018 20:42:28 +0200 Subject: [PATCH] Various improvements, fixes and rebalances that I'm too tired to list through. --- maps/titlemap.wad | Bin 1867 -> 1867 bytes modeldef.flak | 4 +- sndinfo.txt | 1 + zscript/eightball.zsc | 30 ++++- zscript/flakcannon.zsc | 12 +- zscript/healitems.zsc | 1 - zscript/minigun.zsc | 8 +- zscript/powerups.zsc | 14 +- zscript/ripper.zsc | 5 +- zscript/shockrifle.zsc | 6 +- zscript/sniperrifle.zsc | 1 + zscript/utcommon.zsc | 250 ++++++++++++++++++++++++++++-------- zscript/warheadlauncher.zsc | 2 + 13 files changed, 260 insertions(+), 74 deletions(-) diff --git a/maps/titlemap.wad b/maps/titlemap.wad index 5a633588cd8c1499d091855037fbb8df66cc16ba..d1db4cba53649689f7855f288796870db319c8a6 100644 GIT binary patch delta 16 XcmX@jcbacQ6f?7tsp;le=6B2hFx3TP delta 16 XcmX@jcbacQ6f?7-k;Ud%=6B2hFv 0 ) + { + double MagnitudeVel = Vel.length(); + SeekingDir = (SeekingDir*0.5*MagnitudeVel+Vel).unit(); + Vel = MagnitudeVel * SeekingDir; + invoker.Acceleration = 25 * SeekingDir; + } + } + } States { Spawn: RCKT B 1 { A_SetRoll(roll+30,SPF_INTERPOLATE); + if ( invoker.ticcnt++ > 3 ) + { + invoker.ticcnt = 0; + A_RocketSeek(); + } + vel += invoker.Acceleration/TICRATE; + if ( vel.length() > 45. ) vel = Vel.unit()*45.; Vector3 dir = vel.unit(); if ( waterlevel <= 0 ) vel = dir*min(vel.length()+1,32); A_SetAngle(atan2(dir.y,dir.x),SPF_INTERPOLATE); A_SetPitch(asin(-dir.z),SPF_INTERPOLATE); - if ( tracer ) A_SeekerMissile(0,2,SMF_PRECISE); for ( int i=0; i<3; i++ ) { let s = Spawn("UTSmoke",pos); diff --git a/zscript/flakcannon.zsc b/zscript/flakcannon.zsc index 890f509..35ea6eb 100644 --- a/zscript/flakcannon.zsc +++ b/zscript/flakcannon.zsc @@ -29,13 +29,17 @@ Class FlakAmmo : Ammo Default { Tag "Flak Shells"; - Inventory.PickupMessage "You picked up 10 Flak Shells."; + Inventory.PickupMessage "You picked up %d Flak Shells."; Inventory.Amount 10; Inventory.MaxAmount 50; Ammo.BackpackAmount 20; Ammo.BackpackMaxAmount 100; Ammo.DropAmount 5; } + override String PickupMessage() + { + return String.Format(pickupmsg,Amount); + } States { Spawn: @@ -52,6 +56,7 @@ Class FlakAmmo2 : FlakAmmo Inventory.PickupMessage "You picked up a Flak Shell."; Inventory.Amount 1; Ammo.DropAmount 1; + +INVENTORY.IGNORESKILL; } States { @@ -143,10 +148,10 @@ Class FlakChunk : Actor DamageType 'Shredded'; BounceType "Doom"; BounceFactor 0.8; + WallBounceFactor 0.8; PROJECTILE; +USEBOUNCESTATE; -BOUNCEAUTOOFF; - +BOUNCEAUTOOFFFLOORONLY; +CANBOUNCEWATER; +SKYEXPLODE; Scale 0.3; @@ -224,9 +229,10 @@ Class FlakChunk : Actor invoker.rollvel = FRandom[Flak](50,100)*RandomPick[Flak](-1,1)*(vel.length()/speed); invoker.pitchvel = FRandom[Flak](50,100)*RandomPick[Flak](-1,1)*(vel.length()/speed); invoker.yawvel = FRandom[Flak](50,100)*RandomPick[Flak](-1,1)*(vel.length()/speed); - vel = (vel.unit()+(FRandom[Flak](-0.4,0.4),FRandom[Flak](-0.4,0.4),FRandom[Flak](-0.4,0.4))).unit()*vel.length(); + vel = (vel.unit()+(FRandom[Flak](-0.2,0.2),FRandom[Flak](-0.2,0.2),FRandom[Flak](-0.2,0.2))).unit()*vel.length(); A_PlaySound("flak/bounce",volume:0.3); A_AlertMonsters(); + bBOUNCEAUTOOFFFLOORONLY = true; if ( vel.length() < 4.0 ) ExplodeMissile(); } override int DoSpecialDamage( Actor target, int damage, Name damagetype ) diff --git a/zscript/healitems.zsc b/zscript/healitems.zsc index 08df1b9..ab7369d 100644 --- a/zscript/healitems.zsc +++ b/zscript/healitems.zsc @@ -28,7 +28,6 @@ Class UTHealthBox : Health replaces Medikit Tag "Health Box"; Inventory.Amount 50; Inventory.PickupMessage "You picked up a Health Box."; - Health.LowMessage 25,"You picked up a Health Box that you REALLY need!"; Inventory.PickupSound "misc/ut_heal"; } States diff --git a/zscript/minigun.zsc b/zscript/minigun.zsc index 8be71a9..1bb5340 100644 --- a/zscript/minigun.zsc +++ b/zscript/minigun.zsc @@ -30,13 +30,17 @@ Class MiniAmmo : Ammo Default { Tag "Large Bullets"; - Inventory.PickupMessage "You picked up 50 bullets."; + Inventory.PickupMessage "You picked up %d bullets."; Inventory.Amount 50; Inventory.MaxAmount 200; Ammo.BackpackAmount 100; Ammo.BackpackMaxAmount 400; Ammo.DropAmount 20; } + override String PickupMessage() + { + return String.Format(pickupmsg,Amount); + } States { Spawn: @@ -102,7 +106,7 @@ Class Minigun : UTWeapon A_Overlay(-2,"MuzzleFlash",true); A_OverlayFlags(-2,PSPF_RENDERSTYLE|PSPF_FORCESTYLE,true); A_OverlayRenderstyle(-2,STYLE_Add); - if ( (alt && (invoker.bcnt++ < 3)) || (invoker.bcnt++ < 5) ) return; + if ( (alt && (invoker.bcnt++ < 2)) || (invoker.bcnt++ < 4) ) return; invoker.bcnt = 0; if ( !weap.DepleteAmmo(weap.bAltFire,true,1) ) return; invoker.FireEffect(); diff --git a/zscript/powerups.zsc b/zscript/powerups.zsc index cc366eb..f22ee84 100644 --- a/zscript/powerups.zsc +++ b/zscript/powerups.zsc @@ -52,13 +52,18 @@ Class DamageAmplifier : Powerup Powerup.Color "EE00FF", 0.15; } + override void BeginPlay() + { + Super.BeginPlay(); + if ( deathmatch ) EffectTics /= 2; + } + override void InitEffect() { Super.InitEffect(); l = Spawn("DamageAmpLight",Owner.pos); l.target = Owner; l.master = self; - if ( deathmatch ) EffectTics /= 2; } override void DoEffect() @@ -197,11 +202,16 @@ Class PowerUTInvisibility : PowerInvisibility { Default { - Powerup.Duration -80; + Powerup.Duration -100; Powerup.Strength 90; Powerup.Mode "Additive"; Powerup.Color "FFFFFF", 0.1; } + override void BeginPlay() + { + Super.BeginPlay(); + if ( deathmatch ) EffectTics /= 2; + } override void EndEffect() { Super.EndEffect(); diff --git a/zscript/ripper.zsc b/zscript/ripper.zsc index 3ee7cfc..658ce94 100644 --- a/zscript/ripper.zsc +++ b/zscript/ripper.zsc @@ -58,7 +58,7 @@ Class Razor2 : Actor Radius 2; Height 2; Speed 40; // should be 26 but it looks way too slow - DamageFunction Random[Ripper](30,40); + DamageFunction (Random[Ripper](30,40)*((DamageType=='Decapitated')?3.5:1.0)); DamageType 'Ripper'; Obituary "%k ripped a chunk of meat out of %o with the Ripper."; BounceType "Doom"; @@ -84,12 +84,11 @@ Class Razor2 : Actor } override int SpecialMissileHit( Actor victim ) { - if ( pos.z > victim.pos.z+victim.height*0.8 ) DamageType = 'Decapitated'; + if ( pos.z > victim.pos.z+victim.height*0.75 ) DamageType = 'Decapitated'; return -1; } override int DoSpecialDamage( Actor target, int damage, Name damagetype ) { - if ( pos.z > target.pos.z+target.height*0.8 ) damage *= 2; if ( !target.bNOBLOOD ) { target.SpawnBlood(pos,AngleTo(target),damage); diff --git a/zscript/shockrifle.zsc b/zscript/shockrifle.zsc index 968c428..a188da8 100644 --- a/zscript/shockrifle.zsc +++ b/zscript/shockrifle.zsc @@ -1115,9 +1115,9 @@ Class EnhancedShockAmmo : Ammo { int ticcnt; - override void PostBeginPlay() + override void BeginPlay() { - Super.PostBeginPlay(); + Super.BeginPlay(); if ( deathmatch ) { MaxAmount /= 2; @@ -1167,7 +1167,6 @@ Class EnhancedShockRifle : UTWeapon replaces InvulnerabilitySphere override void PostBeginPlay() { Super.PostBeginPlay(); - if ( deathmatch ) AmmoGive1 /= 2; } action void A_SShockFire() { @@ -1266,6 +1265,7 @@ Class EnhancedShockRifle : UTWeapon replaces InvulnerabilitySphere +WEAPON.AMMO_OPTIONAL; +WEAPON.ALT_AMMO_OPTIONAL; +WEAPON.CHEATNOTWEAPON; + +INVENTORY.IGNORESKILL; } States { diff --git a/zscript/sniperrifle.zsc b/zscript/sniperrifle.zsc index c1e2abe..bf529c9 100644 --- a/zscript/sniperrifle.zsc +++ b/zscript/sniperrifle.zsc @@ -26,6 +26,7 @@ Class RifleAmmo2 : RifleAmmo Inventory.PickupMessage "You got a Rifle Round."; Inventory.Amount 1; Ammo.DropAmount 1; + +INVENTORY.IGNORESKILL; } States { diff --git a/zscript/utcommon.zsc b/zscript/utcommon.zsc index e4a51a3..ab3b73d 100644 --- a/zscript/utcommon.zsc +++ b/zscript/utcommon.zsc @@ -5,14 +5,18 @@ Class UTPlayer : DoomPlayer transient CVar footsteps, utmovement, doomspeed, doomaircontrol, nowalkdrop; Vector2 acceleration; Vector3 acceleration3; - int last_fm_tap, last_sm_tap; int last_fm, last_sm; + int last_fm_tap, last_sm_tap; + int last_tap_fm, last_tap_sm; + int last_jump_held; const groundspeed = 400.; const accelrate = 2048.; const walkfactor = 0.3; const utaircontrol = 0.35; const groundspeed_doomish = 600.; + const fluidfriction = 1.2; + const terminalvelocity = 2500.; Default { @@ -184,6 +188,7 @@ Class UTPlayer : DoomPlayer bool forcefootstep = false; if ( player.onground && !bNoGravity && !lastground && (waterlevel < 3) ) { + player.jumptics = 0; if ( lastvelz < -4 ) { double vol = clamp((-lastvelz-4)*0.05,0.01,1.0); @@ -240,38 +245,83 @@ Class UTPlayer : DoomPlayer else fs *= max(abs(cmd.forwardmove/12800.),abs(cmd.sidemove/10240.)); if ( CanCrouch() && (player.crouchfactor != -1) ) fs *= player.crouchfactor; acceleration = rotatevector((cmd.forwardmove,-cmd.sidemove),angle); + Vector2 dodge = (0,0); + int fm = cmd.forwardmove; + int sm = cmd.sidemove; + if ( fm ) + { + int clk = abs(gametic-last_fm_tap); + if ( (clk < 8) && (last_fm*fm == 0) && (last_tap_fm*fm>0) ) + dodge += RotateVector((fm,0),angle).unit(); + if ( !last_fm && (last_jump_held < gametic-1) ) + { + last_fm_tap = gametic; + last_tap_fm = fm; + } + } + last_fm = fm; + if ( sm ) + { + int clk = abs(gametic-last_sm_tap); + if ( (clk < 8) && (last_sm*sm == 0) && (last_tap_sm*sm>0) ) + dodge += RotateVector((0,-sm),angle).unit(); + if ( !last_sm && (last_jump_held < gametic-1) ) + { + last_sm_tap = gametic; + last_tap_sm = sm; + } + } + last_sm = sm; if ( player.onground ) { - if ( nowalkdrop.GetBool() ) - bNODROPOFF = ((acceleration.length() > double.epsilon) && (cmd.buttons&BT_SPEED)); - // Hook in Unreal physics - Vector2 dir = (0,0); - if ( vel.xy.length() > double.epsilon ) dir = vel.xy.unit(); - if ( acceleration.length() <= double.epsilon ) + if ( !bNoGravity && !waterlevel && (dodge.length() > 0) ) { - Vector2 oldvel = vel.xy; - vel.xy = vel.xy - (2 * dir) * vel.xy.length() * friction/TICRATE; - if ( oldvel dot vel.xy < 0.0 ) vel.xy *= 0; + if ( doomspeed.GetBool() ) vel += dodge.unit()*(groundspeed_doomish*1.5)/TICRATE; + else vel += dodge.unit()*(groundspeed*1.5)/TICRATE; + vel.z += jumpz*0.5; + bOnMobj = false; + if ( !(player.cheats&CF_PREDICTING) ) + A_PlaySound("*jump",CHAN_BODY); + if ( player.cheats & CF_REVERTPLEASE ) + { + player.cheats &= ~CF_REVERTPLEASE; + player.camera = player.mo; + } + player.vel *= 0; } else { - Vector2 acceldir = acceleration.unit(); - acceleration = acceldir * Min(acceleration.length(), accelrate/TICRATE); - vel.xy = vel.xy - (dir - acceldir) * vel.xy.length() * friction/TICRATE; + if ( nowalkdrop.GetBool() ) + bNODROPOFF = ((acceleration.length() > double.epsilon) && (cmd.buttons&BT_SPEED)); + // Hook in Unreal physics + Vector2 dir = (0,0); + if ( vel.xy.length() > double.epsilon ) dir = vel.xy.unit(); + if ( acceleration.length() <= double.epsilon ) + { + Vector2 oldvel = vel.xy; + vel.xy = vel.xy - (2 * dir) * vel.xy.length() * friction/TICRATE; + if ( oldvel dot vel.xy < 0.0 ) vel.xy *= 0; + } + else + { + Vector2 acceldir = acceleration.unit(); + acceleration = acceldir * Min(acceleration.length(), accelrate/TICRATE); + vel.xy = vel.xy - (dir - acceldir) * vel.xy.length() * friction/TICRATE; + } + vel.xy = vel.xy + acceleration/TICRATE; + double maxvel; + if ( doomspeed.GetBool() ) maxvel = (groundspeed_doomish*fs)/TICRATE; + else maxvel = (groundspeed*fs)/TICRATE; + double doomfriction = clamp(GetFriction()/ORIG_FRICTION,0.0,1.0); + maxvel *= doomfriction; + if ( vel.xy.length() > maxvel ) vel.xy = vel.xy.unit()*maxvel; + if ( !(player.cheats & CF_PREDICTING) ) + { + if ( acceleration.length() <= double.epsilon ) PlayIdle(); + else PlayRunning(); + } + player.vel = vel.xy; } - vel.xy = vel.xy + acceleration * (1./TICRATE); - double maxvel; - if ( doomspeed.GetBool() ) maxvel = (groundspeed_doomish*fs)/TICRATE; - else maxvel = (groundspeed*fs)/TICRATE; - double doomfriction = clamp(GetFriction()/ORIG_FRICTION,0.0,1.0); - maxvel *= doomfriction; - if ( vel.xy.length() > maxvel ) vel.xy = vel.xy.unit()*maxvel; - if ( !(player.cheats & CF_PREDICTING) ) - { - if ( acceleration.length() <= double.epsilon ) PlayIdle(); - else PlayRunning(); - } - player.vel = vel.xy; } else if ( !bNoGravity && !waterlevel ) { @@ -281,8 +331,23 @@ Class UTPlayer : DoomPlayer maxaccel += (40.-vel.xy.length())/TICRATE; if ( acceleration.length() > maxaccel ) acceleration = acceleration.unit()*maxaccel; - acceleration *= doomaircontrol.GetBool()?level.aircontrol:0.35; - vel.xy += acceleration/TICRATE; + Vector2 dir = (0,0); + if ( vel.xy.length() > double.epsilon ) dir = vel.xy.unit(); + if ( acceleration.length() <= double.epsilon ) + { + Vector2 oldvel = vel.xy; + vel.xy = vel.xy - (2 * dir) * vel.xy.length() * fluidfriction/TICRATE; + if ( oldvel dot vel.xy < 0.0 ) vel.xy *= 0; + } + else + { + Vector2 acceldir = acceleration.unit(); + acceleration = acceldir * Min(acceleration.length(), accelrate/TICRATE); + vel.xy = vel.xy - (dir - acceldir) * vel.xy.length() * fluidfriction/TICRATE; + } + acceleration *= doomaircontrol.GetBool()?level.aircontrol:utaircontrol; + vel.xy = vel.xy + acceleration/TICRATE; + if ( vel.length() > terminalvelocity/TICRATE ) vel = vel.unit()*(terminalvelocity/TICRATE); player.vel *= 0; } else @@ -327,44 +392,41 @@ Class UTPlayer : DoomPlayer player.camera = player.mo; } } - override void CheckJump() { if ( !utmovement ) utmovement = CVar.GetCVar('flak_utmovement'); - if ( !doomspeed ) doomspeed = CVar.GetCVar('flak_doomspeed'); - if ( utmovement.GetBool() && player.onground && !bNoGravity && !waterlevel && (player.jumptics == 0) && (player.cmd.forwardmove || player.cmd.sidemove) ) + if ( !utmovement.GetBool() ) { - int fm = player.cmd.forwardmove; - int sm = player.cmd.sidemove; - Vector2 dodge = (0,0); - if ( fm ) + Super.CheckJump(); + return; + } + if ( player.cmd.buttons&BT_JUMP ) + { + if ( player.crouchoffset ) player.crouching = 1; + else if ( waterlevel >= 2 ) Vel.z = 4*Speed; + else if ( bNoGravity ) Vel.z = 3.; + else if ( level.IsJumpingAllowed() && player.onground && (player.jumpTics == 0) && (last_jump_held < gametic-1) ) { - int clk = abs(gametic-last_fm_tap); - if ( (clk < 5) && (clk > 1) && (last_fm*fm>0) ) - dodge += RotateVector((fm,0),angle).unit(); - last_fm_tap = gametic; - last_fm = fm; - } - if ( sm ) - { - int clk = abs(gametic-last_sm_tap); - if ( (clk < 5) && (clk > 1) && (last_sm*sm>0) ) - dodge += RotateVector((0,-sm),angle).unit(); - last_sm_tap = gametic; - last_sm = sm; - } - if ( dodge.length() > 0 ) - { - if ( doomspeed.GetBool() ) vel += dodge.unit()*(groundspeed_doomish*1.5)/TICRATE; - else vel += dodge.unit()*(groundspeed*1.5)/TICRATE; - vel.z += jumpz*0.5; + double jumpvelz = JumpZ; + double jumpfac = 0; + for ( let p = Inv; p != null; p = p.Inv ) + { + let pp = PowerHighJump(p); + if ( !pp ) continue; + double f = pp.Strength; + if ( f > jumpfac ) jumpfac = f; + } + if ( jumpfac > 0 ) jumpvelz *= jumpfac; + Vel.z += jumpvelz; bOnMobj = false; player.jumpTics = -1; if ( !(player.cheats&CF_PREDICTING) ) A_PlaySound("*jump",CHAN_BODY); } + last_jump_held = gametic; } - Super.CheckJump(); + if ( !player.onground || player.jumptics ) + last_jump_held = gametic; } } @@ -388,6 +450,7 @@ Class RandomSpawner2 : RandomSpawner Class UTWeapon : Weapon { int DropAmmo; + bool bExtraPickup; Property DropAmmo: DropAmmo; @@ -434,6 +497,79 @@ Class UTWeapon : Weapon A_ClearRefire(); } + override bool HandlePickup( Inventory item ) + { + if (item.GetClass() == GetClass()) + { + if ( Weapon(item).PickupForAmmo(self) ) + item.bPickupGood = true; + if ( (MaxAmount > 1) || bALWAYSPICKUP ) + return Inventory.HandlePickup(item); + return true; + } + return false; + } + override bool ShouldStay() + { + if ( ((multiplayer && (!deathmatch && !alwaysapplydmflags)) || sv_weaponstay) && !bDropped ) + return (!bExtraPickup && !bALWAYSPICKUP); + return false; + } + override bool TryPickup( in out Actor toucher ) + { + if ( !bExtraPickup ) bExtraPickup = ((MaxAmount > 1) && (toucher.CountInv(GetClass()) < MaxAmount)); + return Super.TryPickup(toucher); + } + + // Whole chain of function rewrites because of some stupid hardcoded deathmatch ammo multiplier + override bool TryPickupRestricted( in out Actor toucher ) + { + if ( ShouldStay() ) return false; + bExtraPickup = false; + bool gaveSome = !!(NonIdioticAddAmmo(toucher,AmmoType1,AmmoGive1)); + gaveSome |= !!(NonIdioticAddAmmo(toucher,AmmoType2,AmmoGive2)); + if ( gaveSome ) GoAwayAndDie(); + return gaveSome; + } + override void AttachToOwner( Actor other ) + { + bExtraPickup = false; + Inventory.AttachToOwner(other); + Ammo1 = NonIdioticAddAmmo(Owner,AmmoType1,AmmoGive1); + Ammo2 = NonIdioticAddAmmo(Owner,AmmoType2,AmmoGive2); + SisterWeapon = AddWeapon(SisterWeaponType); + if ( Owner.player ) + { + if ( !Owner.player.GetNeverSwitch() && !bNo_Auto_Switch ) + Owner.player.PendingWeapon = self; + if ( Owner.player.mo == players[consoleplayer].camera ) + StatusBar.ReceivedWeapon(self); + } + GivenAsMorphWeapon = false; + } + + // rewrite of AddAmmo without stupid hardcoded 2.5x ammo multiplier + protected Ammo NonIdioticAddAmmo( Actor other, Class ammotype, int amount ) + { + if ( !ammotype ) return null; + Ammo ammoitem; + if ( !bIgnoreSkill ) amount = int(amount*G_SkillPropertyFloat(SKILLP_AmmoFactor)); + ammoitem = Ammo(other.FindInventory(ammotype)); + if ( !ammoitem ) + { + ammoitem = Ammo(Spawn(ammotype)); + ammoitem.Amount = min(amount,ammoitem.MaxAmount); + ammoitem.AttachToOwner(other); + } + else if ( ammoitem.Amount < ammoitem.MaxAmount ) + { + ammoitem.Amount += amount; + if ( ammoitem.Amount > ammoitem.MaxAmount ) + ammoitem.Amount = ammoitem.MaxAmount; + } + return ammoitem; + } + Default { Weapon.BobStyle "Smooth"; @@ -1022,7 +1158,9 @@ Class UTMainHandler : StaticEventHandler ui void StartMenu() { - int proto = CVar.GetCVar('flak_protomenu',players[consoleplayer]).GetInt(); + CVar protomenu = CVar.GetCVar('flak_protomenu',players[consoleplayer]); + if ( !protomenu ) return; // this can happen + int proto = protomenu.GetInt(); if ( proto ) { tex = TexMan.CheckForTexture("protobg",TexMan.Type_Any); diff --git a/zscript/warheadlauncher.zsc b/zscript/warheadlauncher.zsc index 4a0c89d..76d9f09 100644 --- a/zscript/warheadlauncher.zsc +++ b/zscript/warheadlauncher.zsc @@ -11,6 +11,7 @@ Class WarheadAmmo : Ammo Ammo.BackpackMaxAmount 3; Ammo.DropAmount 1; Inventory.RespawnTics 2100; + +INVENTORY.IGNORESKILL; } States { @@ -710,6 +711,7 @@ Class WarheadLauncher : UTWeapon replaces BFG9000 Weapon.AmmoGive 1; Inventory.RespawnTics 2100; +INVENTORY.ALWAYSPICKUP; + +INVENTORY.IGNORESKILL; +WEAPON.NOAUTOFIRE; UTWeapon.DropAmmo 1; }