Class PeaceAmmo : Ammo { Default { Inventory.Icon "I_Peace"; Inventory.Amount 1; Inventory.MaxAmount 1; Ammo.BackpackAmount 0; Ammo.BackpackMaxAmount 2; } override bool TryPickup( in out Actor toucher ) { if ( !sting_proto ) return false; // not allowed return Super.TryPickup(toucher); } override void Tick() { Super.Tick(); if ( sting_proto ) return; if ( Owner ) Owner.RemoveInventory(self); Destroy(); } } Class PeaceLight : RocketLight { Default { Args 255,128,112,32; } } Class PeaceTrail : Actor { Default { RenderStyle "Add"; Radius 0.1; Height 0; +NOBLOCKMAP; +NOGRAVITY; +DONTSPLASH; +FORCEXYBILLBOARD; +NOTELEPORT; Scale 0.25; } override void PostBeginPlay() { Super.PostBeginPlay(); let l = Spawn("PeaceLight",pos); l.target = self; } override void Tick() { Super.Tick(); if ( !target || !target.bMISSILE ) { Destroy(); return; } Vector3 dir = (cos(target.angle)*cos(target.pitch),sin(target.angle)*cos(target.pitch),-sin(target.pitch)); SetOrigin(level.Vec3Offset(target.pos,-dir*3),true); } States { Spawn: PFLA A -1 Bright; Stop; } } Class PeaceRocket : Actor { Vector3 Acceleration; int ticcnt; Default { Obituary "$O_PEACE"; DamageType 'PeaceDeath'; Radius 2; Height 2; Speed 3.5; PROJECTILE; +SKYEXPLODE; +EXPLODEONWATER; +SEEKERMISSILE; +FORCERADIUSDMG; +NODAMAGETHRUST; +INTERPOLATEANGLES; +HITOWNER; ReactionTime 9; } override void PostBeginPlay() { Super.PostBeginPlay(); let l = Spawn("PeaceTrail",pos); l.target = self; A_PlaySound("peace/fly",CHAN_VOICE,1.0,true,2.5,pitch:0.8); Acceleration = vel*1.67; } action void A_CheckForTargets() { let bi = BlockThingsIterator.Create(self,500); double mindist = double.infinity; while ( bi.Next() ) { if ( !bi.Thing || (!bi.Thing.bISMONSTER && !bi.Thing.player) || (bi.Thing.Health <= 0) || (Distance3D(bi.Thing) > 500) || !CheckSight(bi.Thing) ) continue; if ( sting_peacehome && ((bi.Thing == target) || (target && target.IsFriend(bi.Thing))) ) continue; double dist = Distance3D(bi.Thing); if ( dist > mindist ) break; tracer = bi.Thing; mindist = dist; } } action void A_SeekTargets() { if ( !tracer || (tracer.Health <= 0) ) return; double mag = vel.length(); vel = mag*(level.Vec3Diff(pos,tracer.Vec3Offset(0,0,tracer.height/2)).unit()*mag*6./TICRATE+vel).unit(); } action void A_PeaceExplode() { bFORCEXYBILLBOARD = true; A_SetRenderStyle(1.0,STYLE_Add); A_SprayDecal("RocketBlast",50); A_NoGravity(); A_SetScale(1.1); UTMainHandler.DoBlast(self,200,70000); A_Explode(100,200); A_QuakeEx(3,3,3,8,0,250,"",QF_RELATIVE|QF_SCALEDOWN,falloff:200,rollIntensity:0.2); A_PlaySound("utrl/explode",CHAN_VOICE); A_AlertMonsters(); Spawn("RocketExplLight",pos); int numpt = Random[Peace](15,30); for ( int i=0; i 0. ) { Vector3 dir = vel/mag; if ( mag > 16 ) vel = vel.unit()*16; angle = atan2(dir.y,dir.x); pitch = asin(-dir.z); mag = Acceleration.length(); Acceleration = dir*mag; } for ( int i=0; i<3; i++ ) { let s = Spawn("UTSmoke",pos); s.vel = (FRandom[Peace](-0.2,0.2),FRandom[Peace](-0.2,0.2),FRandom[Peace](-0.2,0.2)); s.vel += vel*0.1; s.SetShade(Color(1,1,1)*Random[Peace](32,48)); } special1++; if ( special1 > 35 ) { special1 = 0; A_CheckForTargets(); A_CountDown(); } // early check if ( GetAge() == 5 ) A_CheckForTargets(); } Wait; Death: TNT1 A 0 A_PeaceExplode(); SSMX ABCDEFGHIJ 2 Bright; Stop; } } Class PeaceFragment : SentryFragment { Default { Scale 0.5; } } Class PeaceBarrel : Actor { action void A_AlignSelf() { // find closest 3d floor for its normal F3DFloor ff = null; for ( int i=0; i 20 ) { invoker.special2++; if ( invoker.special2 <= 9 ) { A_PlaySound("peace/set",CHAN_ITEM,.4); player.FindPSprite(PSP_WEAPON).frame = invoker.special2; } invoker.special1 = 0; } if ( (invoker.special2 >= 10) || !(player.cmd.buttons&(BT_ATTACK|BT_ALTATTACK)) ) { invoker.special2 = min(9,invoker.special2); player.SetPSprite(PSP_WEAPON,invoker.FindState(next)); } } Default { Tag "$T_PEACE"; Inventory.PickupMessage "$I_PEACE"; Weapon.UpSound "peace/select"; Weapon.SlotNumber 8; Weapon.SelectionOrder 1050; Weapon.SlotPriority 0.9; Weapon.AmmoType "PeaceAmmo"; Weapon.AmmoUse 1; Weapon.AmmoType2 "PeaceAmmo"; Weapon.AmmoUse2 1; Weapon.AmmoGive 1; UTWeapon.DropAmmo 1; } States { Spawn: PEAP A -1; Stop; PEAP B -1; Stop; Select: PEAS A 1 A_Raise(int.max); Wait; Ready: PEAS ABCDEFGHIJ 2 A_WeaponReady(WRF_NOFIRE); PEAS K 0 A_PlaySound("peace/up",CHAN_ITEM,.4); PEAS KLMNOPQRST 2 A_WeaponReady(WRF_NOFIRE); Idle: PEAI A 1 { A_CheckReload(); A_WeaponReady(); } Wait; EmptyIdle: TNT1 A 1 { let weap = Weapon(invoker); if ( weap.Ammo1.Amount > 0 ) return ResolveState("Ready"); A_CheckReload(); A_WeaponReady(WRF_NOFIRE); return ResolveState(null); } Wait; Fire: PEAC A 1 A_StartCount(); PEAC # 1 A_CountUp(1); Wait; PEAF ABCD 2; PEAF E 0 { A_PlaySound("peace/down",CHAN_ITEM,.4); UTMainHandler.DoSwing(self,(FRandom[Peace](-0.1,-0.04),FRandom[Peace](0.4,0.6)),3,0,7,SWING_Spring,3,0.8); } PEAF EFG 2; PEAF H 0 { UTMainHandler.DoSwing(self,(FRandom[Peace](0.08,0.12),FRandom[Peace](-1.2,-0.9)),4,0,6,SWING_Spring,3,1.5); } PEAF HI 2; // hello PEAF I -1 A_PeacemakerThrow(); Stop; AltFire: PEAC A 1 A_StartCount(); PEAC # 1 A_CountUp(1); Wait; PEAF ABCD 2; PEAF E 0 { A_PlaySound("peace/down",CHAN_ITEM,.4); UTMainHandler.DoSwing(self,(FRandom[Peace](-0.1,-0.04),FRandom[Peace](0.4,0.6)),3,0,7,SWING_Spring,3,0.8); } PEAF EFG 2; PEAF H 0 { UTMainHandler.DoSwing(self,(FRandom[Peace](0.08,0.12),FRandom[Peace](-1.2,-0.9)),4,0,6,SWING_Spring,3,1.5); } PEAF HI 2; // howdy PEAF I -1 A_PeacemakerThrow(true); Stop; Deselect: PEAD A 0 A_JumpIfNoAmmo("EmptyDeselect"); PEAD ABCDEFGHI 1; PEAD J 1 A_Lower(int.max); EmptyDeselect: TNT1 A 1 A_Lower(int.max); Wait; } }