Class UInvisibility : UnrealInventory { Default { Tag "$T_INVISIBILITY"; +COUNTITEM; +INVENTORY.BIGPOWERUP; +INVENTORY.ALWAYSPICKUP; Inventory.Icon "I_Invis"; Inventory.PickupMessage "$I_INVISIBILITY"; Inventory.RespawnTics 3500; Inventory.MaxAmount 1; UnrealInventory.Charge 100; } override bool Use( bool pickup ) { if ( pickup ) return false; bActive = !bActive; if ( bActive ) { Owner.A_PlaySound("invis/pickup",CHAN_ITEM); Owner.GiveInventory("PowerUInvisibility",1); } else Owner.TakeInventory("PowerUInvisibility",1); return false; } override void DoEffect() { Super.DoEffect(); if ( !bActive ) return; if ( special1 == -1 ) { Owner.TakeInventory("PowerUInvisibility",1); special1 = 3; } else if ( special1 > 1 ) special1--; else if ( special1 == 1 ) { Owner.GiveInventory("PowerUInvisibility",1); special1 = 0; } if ( !(level.maptime%35) && DrainCharge(1) ) { if ( Owner.CheckLocalView() ) Console.Printf(StringTable.Localize("$D_INVISIBILITY")); Owner.TakeInventory("PowerUInvisibility",1); DepleteOrDestroy(); } } override void DetachFromOwner() { Owner.TakeInventory("PowerUInvisibility",1); Super.DetachFromOwner(); } override void OwnerDied() { Owner.TakeInventory("PowerUInvisibility",1); Super.OwnerDied(); } override void PostBeginPlay() { Super.PostBeginPlay(); tracer = Spawn("UInvisibilityX",pos); tracer.angle = angle; tracer.target = self; } States { Spawn: INVS A -1; Stop; } } Class UInvisibilityX : AsmdAmmoX { States { Spawn: INVS A -1 Bright; Stop; } } Class PowerUInvisibility : PowerInvisibility { Default { Powerup.Duration 0x7FFFFFFD; Powerup.Strength 90; Powerup.Mode "Additive"; } } Class Amplifier : UnrealInventory { Default { Tag "$T_AMPLIFIER"; +COUNTITEM; +INVENTORY.BIGPOWERUP; +INVENTORY.ALWAYSPICKUP; Inventory.Icon "I_Amp"; Inventory.PickupMessage "$I_AMPLIFIER"; Inventory.RespawnTics 3150; Inventory.MaxAmount 1; UnrealInventory.Charge 1000; } static double GetMult( Actor Owner, int val ) { if ( !Owner ) return 1.; let d = Amplifier(Owner.FindInventory("Amplifier")); if ( !d || !d.bActive ) return 1.; double Multiplier = max(1,4*(double(d.Charge-val)/d.DefaultCharge)); if ( d.DrainCharge(val) ) { d.Owner.A_PlaySound("amplifier/unset",CHAN_ITEM); if ( d.Owner.CheckLocalView() ) Console.Printf(StringTable.Localize("$D_AMPLIFIER")); if ( d.tracer ) d.tracer.Destroy(); if ( d.Amount <= 0 ) d.DepleteOrDestroy(); } return Multiplier; } override bool Use( bool pickup ) { if ( pickup ) return false; bActive = !bActive; Owner.A_PlaySound(bActive?"amplifier/set":"amplifier/unset",CHAN_ITEM); return false; } override void DoEffect() { Super.DoEffect(); if ( bActive && !tracer ) { tracer = Spawn("AmpSound",Owner.pos); tracer.target = Owner; tracer.master = self; } else if ( !bActive && tracer ) tracer.Destroy(); if ( !bActive ) return; if ( !(level.maptime%35) && DrainCharge(2) ) { Owner.A_PlaySound("amplifier/unset",CHAN_ITEM); if ( Owner.CheckLocalView() ) Console.Printf(StringTable.Localize("$D_AMPLIFIER")); if ( tracer ) tracer.Destroy(); if ( Amount <= 0 ) DepleteOrDestroy(); } } States { Spawn: AMPP A -1; Stop; } } Class AmpSound : Actor { Default { +NOBLOCKMAP; +NOGRAVITY; } override void Tick() { Super.Tick(); if ( !target || !master ) { Destroy(); return; } SetOrigin(target.pos,true); if ( target.CheckLocalView() ) { A_SoundVolume(CHAN_VOICE,0.0); A_SoundVolume(CHAN_7,1.0); } else { A_SoundVolume(CHAN_VOICE,0.25); A_SoundVolume(CHAN_7,0.0); } } override void PostBeginPlay() { Super.PostBeginPlay(); A_PlaySound("amplifier/act",CHAN_VOICE,0.25,true,1.5); A_PlaySound("amplifier/act",CHAN_7,1.0,true,ATTN_NONE); } override void OnDestroy() { Super.OnDestroy(); A_StopSound(CHAN_VOICE); A_StopSound(CHAN_7); } } Class UJumpBoots : UnrealInventory { int draincnt; Default { Tag "$T_LBOOTS"; +COUNTITEM; +INVENTORY.BIGPOWERUP; +INVENTORY.ALWAYSPICKUP; Inventory.Icon "I_Boots"; Inventory.PickupMessage "$I_LBOOTS"; Inventory.RespawnTics 1050; Inventory.MaxAmount 1; UnrealInventory.Charge 3; } override bool Use( bool pickup ) { if ( pickup ) return false; bActive = !bActive; Owner.A_PlaySound("boot/pickup",CHAN_ITEM); if ( bActive ) Owner.GiveInventory("PowerJumpBoots_HighJump",1); else Owner.TakeInventory("PowerJumpBoots_HighJump",1); return false; } override void DoEffect() { Super.DoEffect(); if ( !Owner || !Owner.player ) return; draincnt++; if ( (draincnt >= 700) || (bActive && (owner.player.jumptics == -1)) ) { draincnt = 0; charge--; Owner.A_PlaySound("boot/jump",CHAN_BODY); } else if ( (charge <= 0) && owner.player.onground ) { if ( Owner.CheckLocalView() ) Console.Printf(StringTable.Localize("$D_LBOOTS")); Amount--; Owner.TakeInventory("PowerJumpBoots_HighJump",1); charge = defaultcharge; bActive = false; if ( Amount <= 0 ) DepleteOrDestroy(); } } override void PostBeginPlay() { Super.PostBeginPlay(); if ( (level.maptime > 0) || !InStateSequence(CurState,FindState("Spawn")) ) return; // detect hurtfloors // can't detect terraindef-based damage // this is currently an engine limitation bool foundslime = false; bool foundlava = false; bool foundswim = false; for ( int i=0; i replacements; replacements.Clear(); if ( foundslime ) replacements.Push("ToxinSuit"); if ( foundlava ) replacements.Push("AsbestosSuit"); if ( foundswim ) replacements.Push("SCUBAGear"); if ( replacements.Size() > 0 ) { int rslot = Random[LBootRep](0,replacements.Size()-1); let r = Spawn(replacements[rslot],pos,ALLOW_REPLACE); r.spawnangle = spawnangle; r.spawnpoint = spawnpoint; r.angle = angle; r.pitch = pitch; r.roll = roll; r.special = special; r.args[0] = args[0]; r.args[1] = args[1]; r.args[2] = args[2]; r.args[3] = args[3]; r.args[4] = args[4]; r.ChangeTid(tid); r.SpawnFlags = SpawnFlags&~MTF_SECRET; r.HandleSpawnFlags(); r.SpawnFlags = SpawnFlags; r.bCountSecret = SpawnFlags&MTF_SECRET; r.vel = vel; r.master = master; r.target = target; r.tracer = tracer; r.bDropped = bDropped; Destroy(); } } override void AttachToOwner( Actor Other ) { Super.AttachToOwner(Other); Other.GiveInventory("PowerJumpBoots_IronFeet",1); } override void DetachFromOwner() { Super.DetachFromOwner(); Owner.TakeInventory("PowerJumpBoots_HighJump",1); Owner.TakeInventory("PowerJumpBoots_IronFeet",1); } States { Spawn: JBUT A -1; Stop; } } // cheap replacement when proto content disabled Class UAllMap : MapRevealer { Default { Tag "$T_ALLMAP"; +COUNTITEM; +INVENTORY.ALWAYSPICKUP; Inventory.MaxAmount 0; Inventory.Icon "I_Detect"; Inventory.PickupSound "misc/p_pkup"; Inventory.PickupMessage "$I_ALLMAP"; Inventory.RespawnTics 1050; } States { Spawn: PMAP ABCDCB 6; Loop; } } Class MotionDetector : UnrealInventory { ui TextureID DetHud, DetSpot[2]; Array nearscan; Default { Tag "$T_DETECTOR"; +COUNTITEM; +INVENTORY.ALWAYSPICKUP; Inventory.MaxAmount 1; Inventory.Icon "I_Detect"; Inventory.PickupMessage "$I_DETECTOR"; Inventory.RespawnTics 1050; UnrealInventory.Charge 7000; } override bool TryPickup( in out Actor toucher ) { if ( !sting_proto ) return false; // not allowed bool valid = Super.TryPickup(toucher); if ( valid ) level.allmap = true; return valid; } override void Tick() { Super.Tick(); if ( sting_proto ) return; if ( !Owner ) { let r = Spawn("AllMap",pos,ALLOW_REPLACE); r.spawnangle = spawnangle; r.spawnpoint = spawnpoint; r.angle = angle; r.pitch = pitch; r.roll = roll; r.special = special; r.args[0] = args[0]; r.args[1] = args[1]; r.args[2] = args[2]; r.args[3] = args[3]; r.args[4] = args[4]; r.ChangeTid(tid); r.SpawnFlags = SpawnFlags&~MTF_SECRET; r.HandleSpawnFlags(); r.SpawnFlags = SpawnFlags; r.bCountSecret = SpawnFlags&MTF_SECRET; r.vel = vel; r.master = master; r.target = target; r.tracer = tracer; r.bDropped = bDropped; Destroy(); } else { Owner.RemoveInventory(self); Destroy(); } } override void PostRender( double lbottom ) { if ( !bActive ) return; double xpos = UnrealHUD(StatusBar).ClipX-96; double ypos = 0; // offset if inventory display present on top right if ( UnrealHUD(StatusBar).HudMode < 2 ) ypos += 32; if ( DetHud.IsNull() ) DetHud = TexMan.CheckForTexture("DetHud",TexMan.Type_Any); if ( DetSpot[0].IsNull() ) DetSpot[0] = TexMan.CheckForTexture("DetSpot0",TexMan.Type_Any); if ( DetSpot[1].IsNull() ) DetSpot[1] = TexMan.CheckForTexture("DetSpot1",TexMan.Type_Any); Screen.DrawTexture(DetHud,false,xpos,ypos,DTA_VirtualWidthF,UnrealHUD(StatusBar).ClipX,DTA_VirtualHeightF,UnrealHUD(StatusBar).ClipY,DTA_KeepRatio,true); double alph = max(0.,0.25+0.75*sin((gametic+UnrealHUD(StatusBar).fractic)*6.)); Screen.Dim(Color("FF 40 00"),alph*.25,int((xpos+3)*UnrealHUD(StatusBar).scalev.x),int((ypos+3)*UnrealHUD(StatusBar).scalev.y),int(90*UnrealHUD(StatusBar).scalev.x),int(90*UnrealHUD(StatusBar).scalev.y)); Screen.DrawTexture(DetSpot[0],false,xpos+48,ypos+48,DTA_VirtualWidthF,UnrealHUD(StatusBar).ClipX,DTA_VirtualHeightF,UnrealHUD(StatusBar).ClipY,DTA_KeepRatio,true); alph = max(0.,0.5+0.5*sin((gametic+UnrealHUD(StatusBar).fractic-10)*6.)); for ( int i=0; i 48. ) continue; // this is a long line, but it's not the longest I've ever seen // oh I have seen things... php code that would make you want to stab your eyes with forks... Screen.DrawTexture(DetSpot[1],false,xpos+48+relofs.x,ypos+48+relofs.y,DTA_VirtualWidthF,UnrealHUD(StatusBar).ClipX,DTA_VirtualHeightF,UnrealHUD(StatusBar).ClipY,DTA_KeepRatio,true,DTA_Alpha,alph,DTA_ClipLeft,int((xpos+3)*UnrealHUD(StatusBar).scalev.x),DTA_ClipTop,int((ypos+3)*UnrealHUD(StatusBar).scalev.y),DTA_ClipRight,int((xpos+93)*UnrealHUD(StatusBar).scalev.x),DTA_ClipBottom,int((ypos+93)*UnrealHUD(StatusBar).scalev.y)); } } override bool Use( bool pickup ) { if ( pickup ) return false; bActive = !bActive; if ( bActive ) Owner.A_PlaySound("detector/start",CHAN_ITEM); else Owner.A_PlaySound("detector/stop",CHAN_ITEM,0.1,false,3.); return false; } override void DoEffect() { Super.DoEffect(); if ( bActive && !tracer ) { tracer = Spawn("DetectorSound",Owner.pos); tracer.target = Owner; tracer.master = self; } else if ( !bActive && tracer ) tracer.Destroy(); if ( !bActive ) return; nearscan.Clear(); let bi = BlockThingsIterator.Create(Owner,1024); while ( bi.Next() ) { if ( !bi.Thing || (bi.Thing == Owner) || !bi.Thing.bISMONSTER || bi.Thing.Health <= 0 ) continue; nearscan.Push(bi.Thing); } if ( (Charge <= 0) || DrainCharge(1) ) { Owner.A_PlaySound("detector/stop",CHAN_ITEM,0.1,false,3.); if ( Owner.CheckLocalView() ) Console.Printf(StringTable.Localize("$D_DETECTOR")); if ( tracer ) tracer.Destroy(); DepleteOrDestroy(); } } States { Spawn: MDET A -1; Stop; } } Class DetectorSound : Actor { Default { +NOBLOCKMAP; +NOGRAVITY; } override void Tick() { Super.Tick(); if ( !target || !master ) { Destroy(); return; } SetOrigin(target.pos,true); A_SoundVolume(CHAN_VOICE,target.CheckLocalView()?0.1:0.0); A_SoundVolume(CHAN_7,!target.CheckLocalView()?0.1:0.0); } override void PostBeginPlay() { Super.PostBeginPlay(); A_PlaySound("detector/active",CHAN_VOICE,0.1,true,ATTN_NONE); A_PlaySound("detector/active",CHAN_7,0.1,true,3.); } override void OnDestroy() { Super.OnDestroy(); A_StopSound(CHAN_VOICE); A_StopSound(CHAN_7); } } Class SCUBAGear : UnrealInventory { int oldwaterlevel; Default { Tag "$T_SCUBA"; Inventory.MaxAmount 1; Inventory.Icon "I_Scuba"; Inventory.PickupMessage "$I_SCUBA"; Inventory.RespawnTics 700; UnrealInventory.Charge 4200; } override bool Use( bool pickup ) { if ( pickup ) return false; bActive = !bActive; if ( !bActive ) Owner.A_PlaySound("scuba/stop",CHAN_ITEM); return false; } override void AttachToOwner( Actor other ) { Super.AttachToOwner(other); oldwaterlevel = other.waterlevel; } override void AbsorbDamage( int damage, Name damageType, out int newdamage ) { if ( bActive && (damageType == 'Drowning') ) newdamage = 0; } override void DoEffect() { Super.DoEffect(); if ( (oldwaterlevel < 2) && (owner.waterlevel > 2) ) { if ( sting_autoscuba && !bActive ) Use(false); oldwaterlevel = owner.waterlevel; } else if ( (oldwaterlevel > 2) && (owner.waterlevel < 2) ) { if ( sting_autoscuba && bActive ) Use(false); oldwaterlevel = owner.waterlevel; } if ( bActive && !tracer ) { tracer = Spawn("SCUBASound",Owner.pos); tracer.target = Owner; tracer.master = self; } else if ( !bActive && tracer ) tracer.Destroy(); if ( !bActive ) return; if ( PlayerPawn(Owner) ) PlayerPawn(Owner).ResetAirSupply(); if ( (Charge <= 0) || DrainCharge(1) ) { Owner.A_PlaySound("scuba/stop",CHAN_ITEM); if ( Owner.CheckLocalView() ) Console.Printf(StringTable.Localize("$D_SCUBA")); if ( tracer ) tracer.Destroy(); DepleteOrDestroy(); } } States { Spawn: SCUB A -1; Stop; } } Class SCUBASound : Actor { Default { +NOBLOCKMAP; +NOGRAVITY; } override void Tick() { Super.Tick(); if ( !target || !master ) { Destroy(); return; } SetOrigin(target.pos,true); if ( target.CheckLocalView() ) { A_SoundVolume(CHAN_VOICE,0.0); A_SoundVolume(CHAN_5,0.0); A_SoundVolume(CHAN_6,(target.waterlevel<3)?1.0:0.0); A_SoundVolume(CHAN_7,(target.waterlevel>=3)?1.0:0.0); } else { A_SoundVolume(CHAN_VOICE,(target.waterlevel<3)?0.25:0.0); A_SoundVolume(CHAN_5,(target.waterlevel>=3)?0.25:0.0); A_SoundVolume(CHAN_6,0.0); A_SoundVolume(CHAN_7,0.0); } } override void PostBeginPlay() { Super.PostBeginPlay(); A_PlaySound("scuba/air",CHAN_VOICE,0.25,true,1.5); A_PlaySound("scuba/water",CHAN_5,0.25,true,1.5); A_PlaySound("scuba/air",CHAN_6,1.0,true,ATTN_NONE); A_PlaySound("scuba/water",CHAN_7,1.0,true,ATTN_NONE); } override void OnDestroy() { Super.OnDestroy(); A_StopSound(CHAN_VOICE); A_StopSound(CHAN_5); A_StopSound(CHAN_6); A_StopSound(CHAN_7); } }