Class Tier6Ammo : RandomSpawner2 replaces Cell { Default { DropItem "EClip", 255, 1; DropItem "RifleAmmo2", 255, 1; } } Class Tier6Ammo2 : RandomSpawner2 replaces CellPack { Default { DropItem "MiniAmmo", 255, 1; DropItem "RifleAmmo", 255, 1; } } Class Tier6Weapon : RandomSpawner2 replaces PlasmaRifle { Default { DropItem "Minigun", 255, 1; DropItem "SniperRifle", 255, 1; } } Class MiniAmmo : Ammo { Default { Tag "Large Bullets"; Inventory.PickupMessage "You picked up 50 bullets."; Inventory.Amount 50; Inventory.MaxAmount 200; Ammo.BackpackAmount 100; Ammo.BackpackMaxAmount 400; Ammo.DropAmount 20; } States { Spawn: MAMO A -1; Stop; } } Class MinigunLight : EnforcerLight { override void PostBeginPlay() { Super.PostBeginPlay(); args[LIGHT_INTENSITY] = Random[Minigun](120,180); } } Class MinigunTracer : Actor { Vector3 dest; Default { RenderStyle "Add"; Radius 0.1; Height 0; +NOCLIP; +NOGRAVITY; +DONTSPLASH; } override void Tick() { Super.Tick(); Vector3 dir = level.Vec3Diff(pos,dest); if ( dir.length() < 160 ) { Destroy(); return; } dir = dir.unit(); SetOrigin(Vec3Offset(dir.x*160,dir.y*160,dir.z*160),true); A_SetAngle(atan2(dir.y,dir.x),SPF_INTERPOLATE); A_SetPitch(asin(-dir.z),SPF_INTERPOLATE); A_SetRoll(roll+60,SPF_INTERPOLATE); } States { Spawn: TRAC A -1 Bright; Stop; } } Class Minigun : UTWeapon { int bcnt; action void A_FireBullet( bool alt = false ) { Weapon weap = Weapon(invoker); if ( !weap ) return; if ( weap.Ammo1.Amount <= 0 ) return; 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; invoker.bcnt = 0; if ( !weap.DepleteAmmo(weap.bAltFire,true,1) ) return; invoker.FireEffect(); UTMainHandler.DoFlash(self,Color(32,255,255,0),1); A_AlertMonsters(); if ( alt ) A_QuakeEx(3,3,3,3,0,1,"",QF_RELATIVE|QF_SCALEDOWN,rollIntensity:0.12); else A_QuakeEx(2,2,2,5,0,1,"",QF_RELATIVE|QF_SCALEDOWN,rollIntensity:0.08); let l = Spawn("MinigunLight",pos); l.target = self; if ( !alt ) MinigunLight(l).cnt--; Vector3 x, y, z, x2, y2, z2; [x, y, z] = Matrix4.GetAxes(pitch,angle,roll); Vector3 origin = pos+(0,0,player.viewheight)+10.0*x+y*4.0-z*4.0; double a = FRandom[Minigun](0,360), s = FRandom[Minigun](0,alt?0.05:0.02); [x2, y2, z2] = Matrix4.GetAxes(BulletSlope(),angle,roll); Vector3 dir = (x2+y2*cos(a)*s+z2*sin(a)*s).unit(); FLineTraceData d; LineTrace(atan2(dir.y,dir.x),10000,asin(-dir.z),TRF_ABSPOSITION,origin.z,origin.x,origin.y,d); if ( d.HitType == TRACE_HitActor ) { int dmg = Random[Minigun](12,18); // fun fact: the Minigun is one of the few weapons that has actual RNG damage in UT dmg = d.HitActor.DamageMobj(invoker,self,dmg,'shot',DMG_USEANGLE,atan2(d.HitDir.y,d.HitDir.x)); if ( d.HitActor.bNOBLOOD ) { let p = Spawn("BulletImpact",d.HitLocation); p.scale *= 0.75; 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 ) hitnormal = d.HitSector.floorplane.Normal; else if ( d.HitType == TRACE_HitCeiling ) 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 *= 0.75; 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); } if ( !Random[Minigun](0,1) ) { let t = Spawn("MinigunTracer",origin+x*20.0); t.angle = atan2(dir.y,dir.x); t.pitch = asin(-dir.z); MinigunTracer(t).dest = d.HitLocation; } origin += x*8.0+y*5.0-z*5.0; let c = Spawn("UTCasing",origin); c.vel = x*FRandom[Junk](-2,2)+y*FRandom[Junk](3,6)+z*FRandom[Junk](3,5); c.Scale *= 0.5; } action void A_MinigunRefire( statelabel flash = null, bool nounwind = false ) { Weapon weap = Weapon(invoker); if ( !weap || !player ) return; if ( weap.Ammo1.Amount <= 0 ) { if ( nounwind ) return; A_ClearRefire(); player.setpsprite(PSP_WEAPON,weap.FindState("Unwind")); return; } if ( nounwind ) { if ( player.cmd.buttons&BT_ALTATTACK ) { weap.bAltFire = true; flash = "AltFire"; } else { weap.bAltFire = false; flash = "Fire"; } } A_Refire(flash); } Default { Tag "Minigun"; Obituary "%k's Minigun turned %o into a leaky piece of meat."; Inventory.PickupMessage "You got the Minigun."; Weapon.UpSound "minigun/select"; Weapon.SlotNumber 7; Weapon.SelectionOrder 3; Weapon.AmmoType "MiniAmmo"; Weapon.AmmoUse 1; Weapon.AmmoType2 "MiniAmmo"; Weapon.AmmoUse2 1; Weapon.AmmoGive 50; } States { Spawn: MGNP A -1; Stop; MGNP B -1; Stop; Select: MGNS A 1 A_Raise(int.max); Wait; Ready: MGNS ABCDEFGHIJKLMNOPQRST 1 A_WeaponReady(WRF_NOFIRE); Idle: MGNI ABCDEFGHIJKLMNOPQRS 5 { A_CheckReload(); A_WeaponReady(); } Loop; Fire: AltFire: MGNI A 3 { invoker.bcnt = 5; } Hold: MGNF A 1 { A_PlaySound("minigun/fire",CHAN_WEAPON,1.0,true); A_FireBullet(); } MGNF B 0 A_MinigunRefire(1); Goto Unwind; MGNF B 1 A_FireBullet(); MGNF C 0 A_MinigunRefire(1); Goto Unwind; MGNF C 1 A_FireBullet(); MGNF D 0 A_MinigunRefire(1); Goto Unwind; MGNF D 1 A_FireBullet(); MGNF E 0 A_MinigunRefire(1); Goto Unwind; MGNF E 1 A_FireBullet(); MGNF F 0 A_MinigunRefire(1); Goto Unwind; MGNF F 1 A_FireBullet(); MGNF G 0 A_MinigunRefire(1); Goto Unwind; MGNF G 1 A_FireBullet(); MGNF H 0 A_MinigunRefire(1); Goto Unwind; MGNF H 1 A_FireBullet(); MGNF I 0 A_MinigunRefire(1); Goto Unwind; MGNF I 1 A_FireBullet(); MGNF J 0 A_MinigunRefire(1); Goto Unwind; MGNF J 1 A_FireBullet(); MGNF K 0 A_MinigunRefire(1); Goto Unwind; MGNF K 1 A_FireBullet(); MGNF L 0 A_MinigunRefire(1); Goto Unwind; MGNF L 1 A_FireBullet(); MGNF M 0 A_MinigunRefire(1); Goto Unwind; MGNF M 1 A_FireBullet(); MGNF N 0 A_MinigunRefire(1); Goto Unwind; MGNF N 1 A_FireBullet(); MGNF O 0 A_MinigunRefire(1); Goto Unwind; MGNF O 1 A_FireBullet(); MGNF P 0 A_MinigunRefire(1); Goto Unwind; MGNF P 1 A_FireBullet(); MGNF Q 0 A_MinigunRefire(1); Goto Unwind; MGNF Q 1 A_FireBullet(); MGNF R 0 A_MinigunRefire(1); Goto Unwind; MGNF R 1 A_FireBullet(); MGNF S 0 A_MinigunRefire(1); Goto Unwind; MGNF S 1 A_FireBullet(); MGNF A 0 { if ( invoker.bAltFire ) A_MinigunRefire(1); else A_MinigunRefire("Hold"); } Goto Unwind; AltFire2: MGNF A 1 A_FireBullet(); MGNF B 0 A_MinigunRefire(1); Goto Unwind; MGNF B 1 A_FireBullet(); MGNF C 0 A_MinigunRefire(1); Goto Unwind; MGNF C 1 A_FireBullet(); MGNF D 0 A_MinigunRefire(1); Goto Unwind; MGNF D 1 A_FireBullet(); MGNF E 0 A_MinigunRefire(1); Goto Unwind; MGNF E 1 A_FireBullet(); MGNF F 0 A_MinigunRefire(1); Goto Unwind; MGNF F 1 A_FireBullet(); MGNF G 0 A_MinigunRefire(1); Goto Unwind; MGNF G 1 A_FireBullet(); MGNF H 0 A_MinigunRefire(1); Goto Unwind; MGNF H 1 A_FireBullet(); MGNF I 0 A_MinigunRefire(1); Goto Unwind; MGNF I 1 A_FireBullet(); MGNF J 0 A_MinigunRefire(1); Goto Unwind; MGNF J 1 A_FireBullet(); MGNF K 0 A_MinigunRefire(1); Goto Unwind; MGNF K 1 A_FireBullet(); MGNF L 0 A_MinigunRefire(1); Goto Unwind; MGNF L 1 A_FireBullet(); MGNF M 0 A_MinigunRefire(1); Goto Unwind; MGNF M 1 A_FireBullet(); MGNF N 0 A_MinigunRefire(1); Goto Unwind; MGNF N 1 A_FireBullet(); MGNF O 0 A_MinigunRefire(1); Goto Unwind; MGNF O 1 A_FireBullet(); MGNF P 0 A_MinigunRefire(1); Goto Unwind; MGNF P 1 A_FireBullet(); MGNF Q 0 A_MinigunRefire(1); Goto Unwind; MGNF Q 1 A_FireBullet(); MGNF R 0 A_MinigunRefire(1); Goto Unwind; MGNF R 1 A_FireBullet(); MGNF S 0 A_MinigunRefire(1); Goto Unwind; MGNF S 1 A_FireBullet(); MGNF A 0 A_MinigunRefire(1); Goto Unwind; AltHold: MGNF A 1 { A_PlaySound("minigun/altfire",CHAN_WEAPON,1.0,true); A_FireBullet(true); } MGNF D 0 A_MinigunRefire(1); Goto Unwind; MGNF D 1 A_FireBullet(true); MGNF G 0 A_MinigunRefire(1); Goto Unwind; MGNF G 1 A_FireBullet(true); MGNF J 0 A_MinigunRefire(1); Goto Unwind; MGNF J 1 A_FireBullet(true); MGNF M 0 A_MinigunRefire(1); Goto Unwind; MGNF M 1 A_FireBullet(true); MGNF P 0 A_MinigunRefire(1); Goto Unwind; MGNF P 1 A_FireBullet(true); MGNF S 0 A_MinigunRefire(1); Goto Unwind; MGNF S 1 A_FireBullet(true); MGNF C 0 A_MinigunRefire(1); Goto Unwind; MGNF C 1 A_FireBullet(true); MGNF F 0 A_MinigunRefire(1); Goto Unwind; MGNF F 1 A_FireBullet(true); MGNF I 0 A_MinigunRefire(1); Goto Unwind; MGNF I 1 A_FireBullet(true); MGNF L 0 A_MinigunRefire(1); Goto Unwind; MGNF L 1 A_FireBullet(true); MGNF O 0 A_MinigunRefire(1); Goto Unwind; MGNF O 1 A_FireBullet(true); MGNF R 0 A_MinigunRefire(1); Goto Unwind; MGNF R 1 A_FireBullet(true); MGNF B 0 A_MinigunRefire(1); Goto Unwind; MGNF B 1 A_FireBullet(true); MGNF E 0 A_MinigunRefire(1); Goto Unwind; MGNF E 1 A_FireBullet(true); MGNF H 0 A_MinigunRefire(1); Goto Unwind; MGNF H 1 A_FireBullet(true); MGNF K 0 A_MinigunRefire(1); Goto Unwind; MGNF K 1 A_FireBullet(true); MGNF N 0 A_MinigunRefire(1); Goto Unwind; MGNF N 1 A_FireBullet(true); MGNF Q 0 A_MinigunRefire(1); Goto Unwind; MGNF Q 1 A_FireBullet(true); MGNF A 0 A_MinigunRefire("AltHold"); Goto Unwind; Unwind: MGNU A 0 A_PlaySound("minigun/unwind",CHAN_WEAPON); MGNU ABCDEFGHIJKLMNOPQRSTUVWXYZ 1 A_MinigunRefire(null,true); MGU2 ABCDEFGHIJKLM 1 A_MinigunRefire(null,true); Goto Idle; Deselect: MGND A 1 A_StopSound(CHAN_WEAPON); MGND BCDEFGHIJ 1; MGND J 1 A_Lower(int.max); Wait; MuzzleFlash: TNT1 A 0 A_Jump(256,1,2,3,4,5,6,7,8,9); Stop; MMUZ A 2 Bright; Stop; MMUZ B 2 Bright; Stop; MMUZ C 2 Bright; Stop; MMUZ D 2 Bright; Stop; MMUZ E 2 Bright; Stop; MMUZ F 2 Bright; Stop; MMUZ G 2 Bright; Stop; MMUZ H 2 Bright; Stop; MMUZ I 2 Bright; Stop; Dummy: MMUZ ABCDEFGHI -1; Stop; } }