Class UDamage : PowerupGiver replaces Berserk { Default { Tag "Damage Amplifier"; Inventory.PickupMessage "You got the Damage Amplifier!"; +COUNTITEM; +INVENTORY.AUTOACTIVATE; +INVENTORY.ALWAYSPICKUP; +INVENTORY.BIGPOWERUP; Inventory.MaxAmount 0; Powerup.Type "DamageAmplifier"; Inventory.PickupSound "udamage/pickup"; Inventory.RespawnTics 4200; } States { Spawn: UDAM A -1; Stop; } } Class DamageAmpLight : DynamicLight { Default { DynamicLight.Type "Point"; Args 238,0,255,80; } override void Tick() { Super.Tick(); if ( !target || !master ) { Destroy(); return; } SetOrigin(target.pos,true); args[LIGHT_INTENSITY] = Random[ASMD](10,12)*8; bDORMANT = Powerup(master).isBlinking(); } } Class DamageAmplifier : Powerup { Actor l; Default { Powerup.Duration -60; Powerup.Color "EE00FF", 0.15; } override void InitEffect() { Super.InitEffect(); l = Spawn("DamageAmpLight",Owner.pos); l.target = Owner; l.master = self; } override void DoEffect() { Super.DoEffect(); if ( (EffectTics == 175) || (EffectTics == 140) || (EffectTics == 105) || (EffectTics == 70) || (EffectTics == 35) ) Owner.A_PlaySound("udamage/drain",CHAN_7,1.0,false,0.25); } override void EndEffect() { Super.EndEffect(); PrintPickupMessage(true,"Damage Amplifier has worn off."); } override bool isBlinking() { return ((EffectTics <= 175) && (EffectTics%35 >= 30)); } void FireEffect() { if ( EffectTics < 350 ) Owner.A_PlaySound("udamage/fire2",CHAN_7,1.0,false,0.25); else Owner.A_PlaySound("udamage/fire1",CHAN_7,1.0,false,0.25); UTMainHandler.DoFlash(Owner,Color(96,238,0,255),10); } override void ModifyDamage( int damage, Name damageType, out int newdamage, bool passive ) { if ( passive || (damage <= 0) ) return; newdamage = max(1,ApplyDamageFactors(GetClass(),damageType,damage,damage*3)); if ( !(Owner.player.ReadyWeapon is 'UTWeapon') ) FireEffect(); } } // Backpack that only gives ammo for valid weapons Class UTBackpack : BackpackItem replaces Backpack { override Inventory CreateCopy( Actor other ) { // Find every unique type of ammoitem. Give it to the player if // he doesn't have it already, and double its maximum capacity. for ( int i=0; i)(AllActorClasses[i]); if ( !type || (type.GetParentClass() != 'Ammo') ) continue; // check that it's for a valid weapon bool isvalid = false; for ( int j=0; j)(AllActorClasses[j]); if ( !type2 ) continue; let rep = GetReplacement(type2); if ( (rep != type2) && !(rep is "DehackedPickup") ) continue; readonly weap = GetDefaultByType(type2); if ( !other.player || !other.player.weapons.LocateWeapon(type2) || weap.bCheatNotWeapon ) continue; if ( (weap.AmmoType1 == type) || (weap.AmmoType2 == type) ) { isvalid = true; break; } } if ( !isvalid ) continue; let ammoitem = Ammo(other.FindInventory(type)); int amount = GetDefaultByType(type).BackpackAmount; // extra ammo in baby mode and nightmare mode if ( !bIgnoreSkill ) amount = int(amount*G_SkillPropertyFloat(SKILLP_AmmoFactor)); if ( amount < 0 ) amount = 0; if ( !ammoitem ) { // The player did not have the ammoitem. Add it. ammoitem = Ammo(Spawn(type)); ammoitem.Amount = bDepleted?0:amount; if ( ammoitem.BackpackMaxAmount > ammoitem.MaxAmount ) ammoitem.MaxAmount = ammoitem.BackpackMaxAmount; if ( ammoitem.Amount > ammoitem.MaxAmount ) ammoitem.Amount = ammoitem.MaxAmount; ammoitem.AttachToOwner(other); } else { // The player had the ammoitem. Give some more. if ( ammoitem.MaxAmount < ammoitem.BackpackMaxAmount ) ammoitem.MaxAmount = ammoitem.BackpackMaxAmount; if ( !bDepleted && (ammoitem.Amount < ammoitem.MaxAmount) ) { ammoitem.Amount += amount; if ( ammoitem.Amount > ammoitem.MaxAmount ) ammoitem.Amount = ammoitem.MaxAmount; } } } return Inventory.CreateCopy(other); } override bool HandlePickup (Inventory item) { // Since you already have a backpack, that means you already have every // kind of ammo in your inventory, so we don't need to look at the // entire PClass list to discover what kinds of ammo exist, and we don't // have to alter the MaxAmount either. if ( item is 'BackpackItem' ) { for ( let probe = Owner.Inv; probe; probe = probe.Inv ) { if ( probe.GetParentClass() != 'Ammo' ) continue; if ( probe.Amount >= probe.MaxAmount && !sv_unlimited_pickup ) continue; int amount = Ammo(probe).Default.BackpackAmount; // extra ammo in baby mode and nightmare mode if ( !bIgnoreSkill ) amount = int(amount*G_SkillPropertyFloat(SKILLP_AmmoFactor)); probe.Amount += amount; if ( (probe.Amount > probe.MaxAmount) && !sv_unlimited_pickup ) probe.Amount = probe.MaxAmount; } // The pickup always succeeds, even if you didn't get anything item.bPickupGood = true; return true; } return false; } Default { Tag "Backpack"; Inventory.PickupMessage "You got a Backpack."; Inventory.RespawnTics 2100; } States { Spawn: BPAK A -1; Stop; } } Class PowerUTInvisibility : PowerInvisibility { Default { Powerup.Duration -80; Powerup.Strength 90; Powerup.Mode "Additive"; Powerup.Color "FFFFFF", 0.1; } override void EndEffect() { Super.EndEffect(); PrintPickupMessage(true,"Invisibility has worn off."); } } Class UTInvisibility : PowerupGiver replaces BlurSphere { Default { Tag "Invisibility"; +COUNTITEM; +INVENTORY.AUTOACTIVATE; +INVENTORY.ALWAYSPICKUP; +INVENTORY.BIGPOWERUP; Inventory.MaxAmount 0; Powerup.Type "PowerUTInvisibility"; Inventory.PickupMessage "You have Invisibility."; Inventory.PickupSound "invis/pickup"; Inventory.RespawnTics 4200; } override void PostBeginPlay() { Super.PostBeginPlay(); tracer = Spawn("UTInvisibilityX",pos); tracer.angle = angle; tracer.target = self; } States { Spawn: INVS A -1 Bright; Stop; } } Class UTInvisibilityX : Actor { Default { RenderStyle "Add"; +NOGRAVITY; +NOCLIP; +DONTSPLASH; Radius 0.1; Height 0; } override void Tick() { Super.Tick(); if ( !target ) { Destroy(); return; } SetOrigin(target.pos,true); A_SetAngle(target.angle,SPF_INTERPOLATE); bInvisible = target.bInvisible; } States { Spawn: INVS A -1 Bright; Stop; } } Class UTMapRevealer : MapRevealer replaces Allmap { Default { +COUNTITEM; +INVENTORY.FANCYPICKUPSOUND; +INVENTORY.ALWAYSPICKUP; Inventory.MaxAmount 0; Inventory.PickupSound "trans/pickup"; Inventory.PickupMessage "You got the Computer Map."; } States { Spawn: TRNS A -1; Stop; } } Class UTJumpBoots : Inventory replaces RadSuit { Default { Tag "AntiGrav Boots"; +INVENTORY.AUTOACTIVATE; +INVENTORY.ALWAYSPICKUP; Inventory.Amount 2100; Inventory.MaxAmount 2100; Inventory.InterHubAmount 2100; Inventory.PickupMessage "You picked up the AntiGrav boots."; Inventory.PickupSound "boot/pickup"; Inventory.RespawnTics 1050; } override bool Use( bool pickup ) { if ( pickup ) { Owner.GiveInventory("PowerJumpBoots_HighJump",1); Owner.GiveInventory("PowerJumpBoots_IronFeet",1); } return false; } override void Tick() { Super.Tick(); if ( !Owner || !Owner.player ) return; amount--; if ( (amount > 0) && (owner.player.jumptics == -1) ) { Amount = max(0,Amount-700); Owner.A_PlaySound("boot/jump",CHAN_BODY); } else if ( (Amount <= 0) && owner.player.onground ) { PrintPickupMessage(true,"The AntiGrav Boots have drained."); DepleteOrDestroy(); } } override void DetachFromOwner() { Super.DetachFromOwner(); Owner.TakeInventory("PowerJumpBoots_HighJump",1); Owner.TakeInventory("PowerJumpBoots_IronFeet",1); } override void OwnerDied() { Super.OwnerDied(); DepleteOrDestroy(); } States { Spawn: JBUT A -1; Stop; } } Class PowerJumpBoots_HighJump : PowerHighJump { Default { Powerup.Strength 3; Powerup.Duration int.max; +INVENTORY.PERSISTENTPOWER; } } Class PowerJumpBoots_IronFeet : PowerIronFeet { Default { Powerup.Duration int.max; Powerup.Color "00 00 00", 0.0; +INVENTORY.PERSISTENTPOWER; } override void AbsorbDamage( int damage, Name damageType, out int newdamage ) { } override void DoEffect() { Powerup.DoEffect(); } } Class Searchlight : Inventory replaces Infrared { Actor lt[3]; int ticcnt; Default { Tag "Searchligh"; +COUNTITEM; +INVENTORY.UNTOSSABLE; +INVENTORY.FANCYPICKUPSOUND; +INVENTORY.AUTOACTIVATE; +INVENTORY.ALWAYSPICKUP; Inventory.Amount 200; Inventory.MaxAmount 200; Inventory.InterHubAmount 0; Inventory.PickupMessage "You picked up the Searchlight."; } override bool Use( bool pickup ) { if ( !lt[0] ) lt[0] = Spawn("mkLight"); lt[0].target = owner; lt[0].master = self; if ( !lt[1] ) lt[1] = Spawn("mkLight2"); lt[1].target = owner; lt[1].master = self; if ( !lt[2] ) lt[2] = Spawn("mkLight3"); lt[2].target = owner; lt[2].master = self; return Super.Use(pickup); } override void DetachFromOwner() { Super.DetachFromOwner(); if ( lt[0] ) lt[0].Destroy(); if ( lt[1] ) lt[1].Destroy(); if ( lt[2] ) lt[2].Destroy(); } override void DoEffect() { Super.DoEffect(); if ( !Owner ) return; if ( ticcnt++ < TICRATE ) return; ticcnt = 0; if ( --Amount <= 0 ) { PrintPickupMessage(true,"Searchlight batteries have died."); DepleteOrDestroy(); } } States { Spawn: SLIT A -1; Stop; } } /* hello, Soundless Mound copypasted lights */ Class mkLight : DynamicLight { int basecolor[3]; Default { DynamicLight.Type "Point"; +DynamicLight.SPOT; +DynamicLight.ATTENUATE; +DynamicLight.DONTLIGHTSELF; args 255,224,160,300; DynamicLight.SpotInnerAngle 20; DynamicLight.SpotOuterAngle 35; } override void PostBeginPlay() { Super.PostBeginPlay(); basecolor[0] = args[LIGHT_RED]; basecolor[1] = args[LIGHT_GREEN]; basecolor[2] = args[LIGHT_BLUE]; } override void Tick() { Super.Tick(); if ( !target || !Inventory(master) ) { Destroy(); return; } if ( target.player ) SetOrigin((target.pos.x,target.pos.y,target.player.viewz),true); else SetOrigin(target.vec3Offset(0,0,target.height*0.75),true); A_SetAngle(target.angle,SPF_INTERPOLATE); A_SetPitch(target.pitch,SPF_INTERPOLATE); args[LIGHT_RED] = int(basecolor[0]*clamp(Inventory(master).amount/40.,0.,1.)); args[LIGHT_GREEN] = int(basecolor[1]*clamp(Inventory(master).amount/40.,0.,1.)); args[LIGHT_BLUE] = int(basecolor[2]*clamp(Inventory(master).amount/40.,0.,1.)); bDORMANT = (target.health <= 0); if ( Inventory(target) && target.bInvisible ) bDORMANT = true; // alert monsters hit by the light if ( GetClass() != "mkLight" ) return; if ( !bDORMANT && target.player && (target.health > 0) ) { BlockThingsIterator bt = BlockThingsIterator.Create(target,args[LIGHT_INTENSITY]); while ( bt.Next() ) { if ( !bt.Thing || (Distance3D(bt.Thing) > args[LIGHT_INTENSITY]) ) continue; Vector3 aimdir = (cos(angle)*cos(pitch),sin(angle)*cos(pitch),-sin(pitch)); Vector3 reldir = Vec3To(bt.Thing).unit(); if ( (acos(aimdir dot reldir) < SpotOuterAngle+5) && bt.Thing.CheckSight(target) ) bt.Thing.LastHeard = target; } } } } Class mkLight2 : mkLight { Default { args 128,112,96,300; DynamicLight.SpotInnerAngle 0; DynamicLight.SpotOuterAngle 50; } } Class mkLight3 : DynamicLight { int basecolor[3]; Default { DynamicLight.Type "Point"; +DynamicLight.ATTENUATE; args 32,28,24,0; } override void PostBeginPlay() { Super.PostBeginPlay(); basecolor[0] = args[LIGHT_RED]; basecolor[1] = args[LIGHT_GREEN]; basecolor[2] = args[LIGHT_BLUE]; } override void Tick() { Super.Tick(); if ( !target || Inventory(target) || !Inventory(master) ) { Destroy(); return; } args[LIGHT_RED] = int(basecolor[0]*clamp(Inventory(master).amount/40.,0.,1.)); args[LIGHT_GREEN] = int(basecolor[1]*clamp(Inventory(master).amount/40.,0.,1.)); args[LIGHT_BLUE] = int(basecolor[2]*clamp(Inventory(master).amount/40.,0.,1.)); SetOrigin(target.vec3Offset(0,0,target.height*0.5),true); } }