swwmgz_m/zscript/items/swwm_powerups.zsc

1465 lines
36 KiB
Text

// Powerups go here
Class GrilledCheeseSafeguard : Powerup
{
Default
{
Inventory.Icon "graphics/HUD/Icons/I_Sandwich.png";
Powerup.Duration -3;
}
override void ModifyDamage( int damage, Name damageType, out int newdamage, bool passive, Actor inflictor, Actor source, int flags )
{
if ( passive ) newdamage = 0;
}
}
Class GrilledCheeseSandwich : Inventory
{
Mixin SWWMAutoUseFix;
Mixin SWWMOverlapPickupSound;
Mixin SWWMUseToPickup;
Mixin SWWMRespawn;
Mixin SWWMRotatingPickup;
Mixin SWWMPickupGlow;
// for falling off cliffs and others
// last 5 seconds of safe positions
bool lastsafevalid;
Vector3 lastsafepos[5];
double lastsafeangle[5];
int safetic;
int dteleport;
Actor lastdropper;
override Inventory CreateCopy( Actor other )
{
// additional lore
SWWMLoreLibrary.Add(other.player,"GCSandwich");
return Super.CreateCopy(other);
}
void DoTheThing( bool extrasafe = false )
{
SWWMUtility.AchievementProgressInc("gcsandwich",1,Owner.player);
SWWMHandler.DoFlash(Owner,Color(64,255,255,64),10);
Owner.A_QuakeEx(9,9,9,3,0,1,"",QF_RELATIVE|QF_SCALEDOWN|QF_3D,rollIntensity:1.);
Owner.GiveBody(1000,1000);
if ( Owner is 'Demolitionist' )
{
let n = Owner.FindInventory("ArmorNugget");
if ( !n ) Owner.GiveInventory("ArmorNugget",GetDefaultByType("ArmorNugget").MaxAmount);
else n.Amount = n.MaxAmount;
let b = Owner.FindInventory("BlastSuit");
if ( !b ) Owner.GiveInventory("BlastSuit",GetDefaultByType("BlastSuit").MaxAmount);
else b.Amount = b.MaxAmount;
let w = Owner.FindInventory("WarArmor");
if ( !w ) Owner.GiveInventory("WarArmor",GetDefaultByType("WarArmor").MaxAmount);
else w.Amount = w.MaxAmount;
SWWMLoreLibrary.Add(Owner.player,"Nugget");
SWWMLoreLibrary.Add(Owner.player,"BlastSuit");
SWWMLoreLibrary.Add(Owner.player,"WarArmor");
Demolitionist(Owner).lastbump *= 1.2;
}
let f = Spawn("SWWMItemFog",Owner.Vec3Offset(0,0,Owner.Height/2));
f.bAMBUSH = true;
if ( !extrasafe ) return;
let s = Owner.FindInventory("GrilledCheeseSafeguard");
if ( !s ) Owner.GiveInventory("GrilledCheeseSafeguard",1);
else Powerup(s).EffectTics = Powerup(s).default.EffectTics;
}
override bool Use( bool pickup )
{
if ( pickup && !deathmatch ) return false;
if ( Owner.Health > 500 ) return false;
if ( pickup && ((Owner.player == players[consoleplayer]) || bBigPowerup) ) Owner.A_StartSound(UseSound,CHAN_ITEMEXTRA,CHANF_OVERLAP);
if ( (Owner.player == players[consoleplayer]) && (swwm_mutevoice < 2) )
{
SWWMHandler.AddOneliner("eat",2);
if ( Owner is 'Demolitionist' ) Demolitionist(Owner).facegrin = true;
}
DoTheThing();
return true;
}
override void AbsorbDamage( int damage, Name damageType, out int newdamage, Actor inflictor, Actor source, int flags )
{
if ( Owner.FindInventory("GrilledCheeseSafeguard") )
return; // the safeguard absorbs all
if ( Owner.ApplyDamageFactor(damageType,damage) <= 0 )
return; // this damage type is ignored by the player, so it does not affect us
if ( damageType == 'EndLevel' )
return; // don't trigger on endlevel damage
if ( (damageType == 'Telefrag') && source )
{
// prevent overlap with voodoo doll
if ( source.player == Owner.player )
dteleport = 1; // teleport has to be on next tic
else source.DamageMobj(Owner,Owner,damage,damageType,flags); // kill what attempted the telefrag
}
if ( (Owner.Health-damage <= 0) && (Amount > 0) )
{
if ( (swwm_strictuntouchable == 1) && Owner.player )
{
let hnd = SWWMHandler(EventHandler.Find("SWWMHandler"));
if ( hnd ) hnd.tookdamage[Owner.PlayerNumber()] = true;
}
if ( damageType == 'InstantDeath' )
SafeTeleport(); // get out of pits
newdamage = 0;
if ( (Owner.player == players[consoleplayer]) || bBigPowerup ) Owner.A_StartSound(UseSound,CHAN_ITEMEXTRA,CHANF_OVERLAP);
DoTheThing(true);
Amount--;
}
}
void SafeTeleport( bool tostart = false )
{
Spawn("SWWMItemFog",Owner.Vec3Offset(0,0,Owner.Height/2));
Vector3 safepos;
double safeangle;
if ( tostart || !lastsafevalid )
{
if ( deathmatch ) [safepos, safeangle] = level.PickDeathmatchStart();
else [safepos, safeangle] = level.PickPlayerStart(Owner.PlayerNumber());
if ( !level.useplayerstartz ) safepos.z = ONFLOORZ;
}
else
{
safepos = lastsafepos[4];
safeangle = lastsafeangle[4];
}
Owner.Teleport(safepos,safeangle,0);
}
override void Travelled()
{
Super.Travelled();
dteleport = 0; // ensure we don't teleport immediately after a death exit (yes, this can happen)
}
override void DoEffect()
{
Super.DoEffect();
if ( dteleport > 0 )
{
dteleport--;
if ( dteleport <= 0 ) dteleport = -1;
}
else if ( dteleport == -1 )
{
dteleport = 0;
SafeTeleport();
}
// check safe spot
if ( Owner && !(Owner.CurSector.flags&Sector.SECF_ENDLEVEL) && (Owner.CurSector.DamageAmount <= 0) && (Owner.waterlevel < 2) && (Owner.GetFloorTerrain().DamageAmount <= 0) && (Owner.pos.z <= Owner.floorz) )
{
if ( safetic == 0 )
{
if ( lastsafevalid )
{
for ( int i=4; i>0; i-- )
{
lastsafepos[i] = lastsafepos[i-1];
lastsafeangle[i] = lastsafeangle[i-1];
}
lastsafepos[0] = Owner.pos;
lastsafeangle[0] = Owner.angle;
}
else
{
lastsafevalid = true;
for ( int i=0; i<5; i++ )
{
lastsafepos[i] = Owner.pos;
lastsafeangle[i] = Owner.angle;
}
}
}
safetic = (safetic+1)%35;
}
else safetic = 1;
if ( (Amount <= 0) && (dteleport == 0) ) DepleteOrDestroy();
}
override void AttachToOwner( Actor other )
{
Super.AttachToOwner(other);
// find last armor/health item
Inventory found = null;
for ( Inventory i=other.Inv; i; i=i.Inv )
{
if ( !(i is 'SWWMHealth') && !(i is 'SWWMArmor') ) continue;
found = i;
}
if ( !found ) return;
// place ourselves right after it
Inventory saved = found.Inv;
found.Inv = self;
other.Inv = Inv;
Inv = saved;
}
override void OnDrop( Actor dropper )
{
lastdropper = dropper;
if ( !(dropper is 'Demolitionist') ) return;
Vector3 ofs = SWWMUtility.RotateVector3((dropper.radius,0.,dropper.height*.5),dropper.angle);
SetOrigin(level.Vec3Offset(dropper.pos,ofs),false);
vel = SWWMUtility.GetPlayerViewDir(dropper)*12.+(0.,0.,4.);
angle = dropper.angle;
pitch = 0;
roll = 0;
}
override void PostTeleport( Vector3 destpos, double destangle, int flags )
{
if ( !lastdropper ) return;
SWWMUtility.MarkAchievement("tele",lastdropper.player);
}
Default
{
Tag "$T_SANDWICH";
Stamina 800000;
Inventory.Icon "graphics/HUD/Icons/I_Sandwich.png";
Inventory.PickupSound "misc/p_pkup";
Inventory.UseSound "powerup/sandwich";
Inventory.PickupMessage "$T_SANDWICH";
Inventory.MaxAmount 5;
Inventory.InterHubAmount 5;
Inventory.PickupFlash "SWWMPurplePickupFlash";
+INVENTORY.ALWAYSPICKUP;
+INVENTORY.AUTOACTIVATE;
+INVENTORY.INVBAR;
+COUNTITEM;
+INVENTORY.BIGPOWERUP;
+FLOATBOB;
+DONTGIB;
FloatBobStrength 0.25;
}
States
{
Spawn:
XZW1 A -1;
Stop;
}
}
Mixin Class SWWMShadedPowerup
{
override Color GetBlend()
{
if ( swwm_shaders ) return 0;
return Super.GetBlend();
}
}
Class GhostSnd : SWWMNonInteractiveActor
{
override void Tick()
{
if ( !target || !master )
{
Destroy();
return;
}
SetOrigin(target.pos,true);
if ( players[consoleplayer].Camera == target )
{
A_SoundVolume(CHAN_VOICE,0.);
A_SoundVolume(CHAN_7,.4);
}
else
{
A_SoundVolume(CHAN_VOICE,.1);
A_SoundVolume(CHAN_7,0.);
}
}
override void PostBeginPlay()
{
Super.PostBeginPlay();
A_StartSound("powerup/ghostact",CHAN_VOICE,CHANF_LOOP,.1,1.5);
A_StartSound("powerup/ghostact",CHAN_7,CHANF_LOOP,.4,ATTN_NONE);
}
override void OnDestroy()
{
Super.OnDestroy();
A_StopSound(CHAN_VOICE);
A_StopSound(CHAN_7);
}
}
Class GhostTarget : Actor
{
bool diedie;
Default
{
+SPECTRAL;
+NOGRAVITY;
+DONTSPLASH;
+SHOOTABLE;
+NONSHOOTABLE;
+NOTELEPORT;
+NODAMAGE;
+NOBLOOD;
+CANTSEEK;
+SHADOW; // so they can barely aim
Radius .1;
Height 56;
}
override void Tick()
{
if ( freezetics > 0 )
{
freezetics--;
return;
}
if ( isFrozen() ) return;
if ( diedie ) A_FadeOut(.05);
foreach ( s:level.Sectors ) for ( Actor t=s.thinglist; t; t=t.snext )
{
if ( !t.bIsMonster || t.player || !t.IsHostile(master) || (t.target != self) ) continue;
if ( SWWMUtility.BoxIntersect(self,t,pad:16) || t.CheckMeleeRange() )
{
// they found out, there's no one here
diedie = true;
break;
}
}
// player made noise or is visible again
if ( !master || (LastHeard == master) || !master.FindInventory("GhostPower") )
{
foreach ( s:level.Sectors ) for ( Actor a=s.thinglist; a; a=a.snext )
{
if ( !a.bISMONSTER || a.player || !a.IsHostile(master) || (a.Health <= 0) ) continue;
if ( a.target == self ) a.target = master;
}
Destroy();
}
}
}
Class GhostPower : Powerup
{
Mixin SWWMShadedPowerup;
Actor snd;
bool bSavedInvisible, bSavedCantSeek, bSavedShadow;
Default
{
Inventory.Icon "graphics/HUD/Icons/I_Ghost.png";
Powerup.Duration -60;
Powerup.Color "F0 E0 FF", 0.1;
+INVENTORY.ADDITIVETIME;
}
override void InitEffect()
{
Super.InitEffect();
if ( !Owner ) return;
bSavedInvisible = Owner.bINVISIBLE;
bSavedCantSeek = Owner.bCANTSEEK;
bSavedShadow = Owner.bSHADOW;
Owner.bINVISIBLE = true;
Owner.bCANTSEEK = true;
Owner.bSHADOW = true;
SWWMHandler.DoFlash(Owner,Color(96,224,192,255),20);
if ( Owner is 'Demolitionist' )
Demolitionist(Owner).lastbump *= 1.04;
DoEffect();
}
override void EndEffect()
{
Super.EndEffect();
if ( !Owner ) return;
Owner.bINVISIBLE = bSavedInvisible;
Owner.bCANTSEEK = bSavedCantSeek;
Owner.bSHADOW = bSavedShadow;
Owner.A_StartSound("powerup/ghostend",CHAN_ITEMEXTRA,CHANF_OVERLAP);
SWWMHandler.DoFlash(Owner,Color(96,224,192,255),20);
if ( Owner is 'Demolitionist' )
Demolitionist(Owner).lastbump *= 1.02;
if ( (EffectTics <= 0) && Owner && Owner.CheckLocalView() ) Console.Printf(StringTable.Localize("$D_GHOSTARTI"));
}
override void DoEffect()
{
Super.DoEffect();
if ( !Owner ) return;
// are any enemies targetting us? if so, make them focus on a fake target located where we currently are standing
Actor gt = null;
foreach ( s:level.Sectors ) for ( Actor a=s.thinglist; a; a=a.snext )
{
if ( !a.bISMONSTER || a.player || !a.IsHostile(Owner) || (a.Health <= 0) ) continue;
// make them forget the ghost if we make noise
if ( (a.LastHeard == Owner) && (a.target is 'GhostTarget') && (a.target.master == Owner) )
{
a.target = Owner;
continue;
}
if ( a.target != Owner ) continue;
if ( !gt )
{
gt = Spawn("GhostTarget",Owner.pos);
if ( Owner.bFRIENDLY || Owner.player ) gt.bFRIENDLY = true;
}
a.target = gt;
a.LastHeard = gt;
gt.master = Owner;
}
if ( !snd ) snd = Spawn("GhostSnd",Owner.pos);
snd.target = Owner;
snd.master = self;
}
}
Class GhostArtifactX : SWWMItemOverlay {}
Class GhostArtifact : Inventory
{
Mixin SWWMAutoUseFix;
Mixin SWWMOverlapPickupSound;
Mixin SWWMUseToPickup;
Mixin SWWMRespawn;
Mixin SWWMRotatingPickup;
Mixin SWWMPickupGlow;
Mixin SWWMUnrealStyleDrop;
Default
{
Tag "$T_GHOSTARTI";
Stamina 120000;
Inventory.Icon "graphics/HUD/Icons/I_Ghost.png";
Inventory.PickupSound "misc/p_pkup";
Inventory.UseSound "powerup/ghost";
Inventory.PickupMessage "$T_GHOSTARTI";
Inventory.MaxAmount 5;
Inventory.InterHubAmount 5;
Inventory.PickupFlash "SWWMPurplePickupFlash";
+INVENTORY.ALWAYSPICKUP;
+INVENTORY.AUTOACTIVATE;
+INVENTORY.INVBAR;
+COUNTITEM;
+INVENTORY.BIGPOWERUP;
+FLOATBOB;
+DONTGIB;
FloatBobStrength 0.25;
}
override bool Use( bool pickup )
{
if ( pickup && !deathmatch ) return false;
if ( pickup && ((Owner.player == players[consoleplayer]) || bBigPowerup) ) Owner.A_StartSound(UseSound,CHAN_ITEMEXTRA,CHANF_OVERLAP);
let g = GhostPower(Owner.FindInventory("GhostPower"));
if ( g )
{
g.EffectTics += g.default.EffectTics;
if ( Owner is 'Demolitionist' )
Demolitionist(Owner).lastbump *= 1.04;
}
else Owner.GiveInventory("GhostPower",1);
SWWMUtility.AchievementProgressInc("ghost",1,Owner.player);
return true;
}
override void PreTravelled()
{
if ( tracer ) tracer.Destroy();
}
override void Travelled()
{
if ( tracer ) return;
tracer = Spawn("GhostArtifactX",pos);
tracer.angle = angle;
tracer.target = self;
tracer.FloatBobPhase = FloatBobPhase;
}
override void PostBeginPlay()
{
Super.PostBeginPlay();
tracer = Spawn("GhostArtifactX",pos);
tracer.angle = angle;
tracer.target = self;
tracer.FloatBobPhase = FloatBobPhase;
}
States
{
Spawn:
XZW1 A -1;
Stop;
}
}
Class GravSnd : SWWMNonInteractiveActor
{
override void Tick()
{
if ( !target || !master )
{
Destroy();
return;
}
SetOrigin(target.pos,true);
if ( players[consoleplayer].Camera == target )
{
A_SoundVolume(CHAN_VOICE,0.);
A_SoundVolume(CHAN_7,.7);
}
else
{
A_SoundVolume(CHAN_VOICE,.2);
A_SoundVolume(CHAN_7,0.);
}
}
override void PostBeginPlay()
{
Super.PostBeginPlay();
A_StartSound("powerup/gravityact",CHAN_VOICE,CHANF_LOOP,.2,1.5);
A_StartSound("powerup/gravityact",CHAN_7,CHANF_LOOP,.7,ATTN_NONE);
}
override void OnDestroy()
{
Super.OnDestroy();
A_StopSound(CHAN_VOICE);
A_StopSound(CHAN_7);
}
}
Class GravityPower : Powerup
{
Mixin SWWMShadedPowerup;
Actor snd;
Default
{
Inventory.Icon "graphics/HUD/Icons/I_Gravity.png";
Powerup.Duration -60;
+INVENTORY.ADDITIVETIME;
}
override void InitEffect()
{
Super.InitEffect();
if ( !Owner ) return;
DoEffect();
if ( Owner.pos.z <= Owner.floorz )
Owner.vel.z = 1;
if ( Owner is 'Demolitionist' )
Demolitionist(Owner).lastbump *= 1.04;
}
override void EndEffect()
{
Super.EndEffect();
if ( !Owner ) return;
if ( !Owner.bFLYCHEAT )
{
Owner.bFLY = false;
Owner.bNOGRAVITY = false;
if ( Owner.pos.z > Owner.floorz ) Owner.player.centering = true;
}
Owner.A_StartSound("powerup/gravityend",CHAN_ITEMEXTRA,CHANF_OVERLAP);
if ( Owner is 'Demolitionist' )
Demolitionist(Owner).lastbump *= 1.02;
if ( (EffectTics <= 0) && Owner && Owner.CheckLocalView() ) Console.Printf(StringTable.Localize("$D_GRAVITYS"));
}
override void DoEffect()
{
Super.DoEffect();
if ( !Owner ) return;
Owner.bFLY = true;
Owner.bNOGRAVITY = true;
if ( !snd ) snd = Spawn("GravSnd",Owner.pos);
snd.target = Owner;
snd.master = self;
}
}
Class GravityX : SWWMItemOverlay
{
Default
{
RenderStyle "Normal";
}
}
Class GravitySuppressor : Inventory
{
Mixin SWWMAutoUseFix;
Mixin SWWMOverlapPickupSound;
Mixin SWWMUseToPickup;
Mixin SWWMRespawn;
Mixin SWWMRotatingPickup;
Mixin SWWMPickupGlow;
Mixin SWWMUnrealStyleDrop;
override bool Use( bool pickup )
{
if ( pickup && !deathmatch ) return false;
if ( pickup && ((Owner.player == players[consoleplayer]) || bBigPowerup) ) Owner.A_StartSound(UseSound,CHAN_ITEMEXTRA,CHANF_OVERLAP);
let g = GravityPower(Owner.FindInventory("GravityPower"));
if ( g )
{
g.EffectTics += g.default.EffectTics;
if ( Owner is 'Demolitionist' )
Demolitionist(Owner).lastbump *= 1.04;
}
else Owner.GiveInventory("GravityPower",1);
SWWMUtility.AchievementProgressInc("gravity",1,Owner.player);
return true;
}
override void PreTravelled()
{
if ( tracer ) tracer.Destroy();
}
override void Travelled()
{
if ( tracer ) return;
tracer = Spawn("GravityX",pos);
tracer.angle = angle;
tracer.target = self;
tracer.FloatBobPhase = FloatBobPhase;
}
override void PostBeginPlay()
{
Super.PostBeginPlay();
tracer = Spawn("GravityX",pos);
tracer.angle = angle;
tracer.target = self;
tracer.FloatBobPhase = FloatBobPhase;
}
Default
{
Tag "$T_GRAVITYS";
Stamina 150000;
Inventory.Icon "graphics/HUD/Icons/I_Gravity.png";
Inventory.PickupSound "misc/p_pkup";
Inventory.UseSound "powerup/gravity";
Inventory.PickupMessage "$T_GRAVITYS";
Inventory.MaxAmount 5;
Inventory.InterHubAmount 5;
Inventory.PickupFlash "SWWMPurplePickupFlash";
+INVENTORY.ALWAYSPICKUP;
+INVENTORY.AUTOACTIVATE;
+INVENTORY.INVBAR;
+COUNTITEM;
+INVENTORY.BIGPOWERUP;
+FLOATBOB;
+DONTGIB;
FloatBobStrength 0.25;
}
States
{
Spawn:
XZW1 A -1;
Stop;
}
}
Class InvinciballLight : PointLightAttenuated
{
Default
{
Args 192,64,0,80;
}
override void Tick()
{
Super.Tick();
if ( !target || !master )
{
Destroy();
return;
}
if ( target.player ) SetOrigin(SWWMUtility.GetFireOffset(target,10,0,0),true);
else SetOrigin(target.Vec3Angle(10,target.angle,target.missileheight),true);
args[LIGHT_INTENSITY] = Random[Invinciball](10,12)*8;
bDORMANT = Powerup(master).isBlinking();
}
}
Class InvinciSnd : SWWMNonInteractiveActor
{
override void Tick()
{
if ( !target || !master )
{
Destroy();
return;
}
SetOrigin(target.pos,true);
if ( players[consoleplayer].Camera == target )
{
A_SoundVolume(CHAN_VOICE,0.);
A_SoundVolume(CHAN_7,.8);
}
else
{
A_SoundVolume(CHAN_VOICE,.4);
A_SoundVolume(CHAN_7,0.);
}
}
override void PostBeginPlay()
{
Super.PostBeginPlay();
A_StartSound("powerup/invinciballact",CHAN_VOICE,CHANF_LOOP,.4,1.5);
A_StartSound("powerup/invinciballact",CHAN_7,CHANF_LOOP,.8,ATTN_NONE);
}
override void OnDestroy()
{
Super.OnDestroy();
A_StopSound(CHAN_VOICE);
A_StopSound(CHAN_7);
}
}
Class InvinciballArmor : SWWMArmor
{
Default
{
+SWWMARMOR.NOHITSOUND;
+SWWMARMOR.NOHITFLASH;
+SWWMARMOR.NODRAIN;
SWWMArmor.ArmorPriority 9;
}
override int HandleDamage( int damage, Name damageType, int flags )
{
if ( damageType == 'EndLevel' ) return 0;
if ( master ) InvinciballPower(master).DoHitFX();
return damage;
}
override void DoEffect()
{
Super.DoEffect();
if ( !Owner.FindInventory('InvinciballPower') )
Destroy();
}
}
Class InvinciballPower : Powerup
{
Mixin SWWMShadedPowerup;
Actor l, snd;
Inventory am;
int lasteffect;
transient int lastpulse;
Default
{
Powerup.Duration -30;
Inventory.Icon "graphics/HUD/Icons/I_Invinciball.png";
Powerup.Color "FF 30 00", 0.1;
+INVENTORY.ADDITIVETIME;
}
override void InitEffect()
{
Super.InitEffect();
if ( !Owner ) return;
lasteffect = int.min;
l = Spawn("InvinciballLight",Owner.pos);
l.target = Owner;
l.master = self;
lastpulse = max(lastpulse,gametic+35);
SWWMHandler.DoFlash(Owner,Color(96,255,64,0),20);
if ( Owner is 'Demolitionist' )
Demolitionist(Owner).lastbump *= 1.1;
}
override void DoEffect()
{
Super.DoEffect();
if ( !Owner ) return;
if ( !snd ) snd = Spawn("InvinciSnd",Owner.pos);
snd.target = Owner;
snd.master = self;
if ( am ) return;
am = Owner.FindInventory("InvinciballArmor");
if ( !am )
{
am = Inventory(Spawn("InvinciballArmor"));
am.AttachToOwner(Owner);
}
am.master = self;
}
override void EndEffect()
{
Super.EndEffect();
if ( !Owner ) return;
Owner.A_StartSound("powerup/invinciballend",CHAN_ITEMEXTRA,CHANF_OVERLAP);
SWWMHandler.DoFlash(Owner,Color(96,255,64,0),20);
if ( Owner is 'Demolitionist' )
Demolitionist(Owner).lastbump *= 1.05;
if ( (EffectTics <= 0) && Owner && Owner.CheckLocalView() ) Console.Printf(StringTable.Localize("$D_INVINCIBALL"));
}
void DoHitFX()
{
if ( level.maptime > lasteffect+5 )
{
SWWMHandler.DoFlash(Owner,Color(64,255,64,0),15);
Owner.A_StartSound("powerup/invinciballhit",CHAN_POWERUP,CHANF_OVERLAP);
lasteffect = level.maptime;
lastpulse = max(lastpulse,gametic+20);
if ( Owner is 'Demolitionist' )
Demolitionist(Owner).lastbump *= 1.05;
}
}
}
Class InvinciballX : SWWMItemOverlay
{
Default
{
RenderStyle "Normal";
}
}
Class FuckingInvinciball : Inventory
{
Mixin SWWMAutoUseFix;
Mixin SWWMOverlapPickupSound;
Mixin SWWMUseToPickup;
Mixin SWWMRespawn;
Mixin SWWMRotatingPickup;
Mixin SWWMPickupGlow;
Mixin SWWMUnrealStyleDrop;
override Inventory CreateCopy( Actor other )
{
// additional lore
SWWMLoreLibrary.Add(other.player,"Invinciball");
return Super.CreateCopy(other);
}
override bool Use( bool pickup )
{
if ( pickup && !deathmatch ) return false;
if ( pickup && ((Owner.player == players[consoleplayer]) || bBigPowerup) ) Owner.A_StartSound(UseSound,CHAN_ITEMEXTRA,CHANF_OVERLAP);
Owner.A_StartSound("misc/sundowner",CHAN_POWERUPEXTRA);
let i = InvinciballPower(Owner.FindInventory("InvinciballPower"));
if ( i )
{
i.EffectTics += i.default.EffectTics;
i.lastpulse = max(i.lastpulse,gametic+35);
SWWMHandler.DoFlash(Owner,Color(96,255,64,0),20);
if ( Owner is 'Demolitionist' )
Demolitionist(Owner).lastbump *= 1.1;
}
else Owner.GiveInventory("InvinciballPower",1);
SWWMUtility.AchievementProgressInc("sunny",1,Owner.player);
return true;
}
override void PreTravelled()
{
if ( tracer ) tracer.Destroy();
}
override void Travelled()
{
if ( tracer ) return;
tracer = Spawn("InvinciballX",pos);
tracer.angle = angle;
tracer.target = self;
tracer.FloatBobPhase = FloatBobPhase;
}
override void PostBeginPlay()
{
Super.PostBeginPlay();
tracer = Spawn("InvinciballX",pos);
tracer.angle = angle;
tracer.target = self;
tracer.FloatBobPhase = FloatBobPhase;
}
Default
{
Tag "$T_INVINCIBALL";
Stamina 640000;
Inventory.Icon "graphics/HUD/Icons/I_Invinciball.png";
Inventory.PickupSound "misc/p_pkup";
Inventory.UseSound "powerup/invinciball";
Inventory.PickupMessage "$T_INVINCIBALL";
Inventory.MaxAmount 5;
Inventory.InterHubAmount 5;
Inventory.PickupFlash "SWWMPurplePickupFlash";
+INVENTORY.ALWAYSPICKUP;
+INVENTORY.AUTOACTIVATE;
+INVENTORY.INVBAR;
+COUNTITEM;
+INVENTORY.BIGPOWERUP;
+FLOATBOB;
+DONTGIB;
FloatBobStrength 0.25;
}
States
{
Spawn:
XZW1 A -1;
Stop;
}
}
Class RagekitLight : PointLightAttenuated
{
Default
{
Args 255,0,0,80;
}
override void Tick()
{
Super.Tick();
if ( !target || !master )
{
Destroy();
return;
}
if ( target.player ) SetOrigin(SWWMUtility.GetFireOffset(target,10,0,0),true);
else SetOrigin(target.Vec3Angle(10,target.angle,target.missileheight),true);
args[LIGHT_INTENSITY] = Random[Invinciball](10,12)*8;
bDORMANT = Powerup(master).isBlinking();
}
}
Class RageSnd : SWWMNonInteractiveActor
{
override void Tick()
{
if ( !target || !master )
{
Destroy();
return;
}
SetOrigin(target.pos,true);
if ( players[consoleplayer].Camera == target )
{
A_SoundVolume(CHAN_VOICE,0.);
A_SoundVolume(CHAN_7,.5);
}
else
{
A_SoundVolume(CHAN_VOICE,.4);
A_SoundVolume(CHAN_7,0.);
}
}
override void PostBeginPlay()
{
Super.PostBeginPlay();
A_StartSound("powerup/ragekitact",CHAN_VOICE,CHANF_LOOP,.4,1.5);
A_StartSound("powerup/ragekitact",CHAN_7,CHANF_LOOP,.5,ATTN_NONE);
}
override void OnDestroy()
{
Super.OnDestroy();
A_StopSound(CHAN_VOICE);
A_StopSound(CHAN_7);
}
}
Class RagekitArmor : SWWMArmor
{
Default
{
+SWWMARMOR.NOHITSOUND;
+SWWMARMOR.NOHITFLASH;
+SWWMARMOR.NODRAIN;
SWWMArmor.ArmorPriority 8;
}
override int HandleDamage( int damage, Name damageType, int flags )
{
if ( damageType != 'EndLevel' ) return 0;
return int(damage*.75);
}
override void DoEffect()
{
Super.DoEffect();
if ( !Owner.FindInventory('RagekitPower') )
Destroy();
}
}
Class RagekitPower : Powerup
{
Mixin SWWMShadedPowerup;
Actor l, snd;
Inventory am;
int lasteffect;
transient int lastpulse, lastrage;
override double GetSpeedFactor()
{
return 2.;
}
Default
{
Powerup.Duration -30;
Inventory.Icon "graphics/HUD/Icons/I_Ragekit.png";
Powerup.Color "FF 00 00", 0.2;
+INVENTORY.ADDITIVETIME;
}
override void InitEffect()
{
Super.InitEffect();
if ( !Owner ) return;
if ( !(Owner is 'Demolitionist') )
{
// only usable by Demolitionist
Destroy();
return;
}
if ( Owner.player == players[consoleplayer] )
lastrage = SWWMHandler.AddOneliner("ragekit",2,20)+40;
Owner.A_AlertMonsters(swwm_uncapalert?0:5000);
SWWMHandler.DoFlash(Owner,Color(64,255,0,0),30);
Owner.A_QuakeEx(8,8,8,20,0,1,"",QF_RELATIVE|QF_SCALEDOWN|QF_3D,rollIntensity:1.);
lasteffect = int.min;
lastpulse = max(lastpulse,gametic+35);
Demolitionist(Owner).lastbump *= .95;
l = Spawn("RagekitLight",Owner.pos);
l.target = Owner;
l.master = self;
}
override void DoEffect()
{
Super.DoEffect();
if ( !Owner ) return;
if ( !snd ) snd = Spawn("RageSnd",Owner.pos);
snd.target = Owner;
snd.master = self;
if ( !(level.maptime%30) )
{
SWWMHandler.DoFlash(Owner,Color(16,255,0,0),5);
Owner.GiveBody(1,100);
Owner.A_AlertMonsters(swwm_uncapalert?0:2000);
if ( (Owner.player == players[consoleplayer]) && (gametic > lastrage) && (swwm_mutevoice < 2) )
lastrage = SWWMHandler.AddOneliner("ragekit",2,5)+20;
Owner.A_QuakeEx(2,2,2,Random[Rage](1,2),0,1,"",QF_RELATIVE|QF_SCALEDOWN|QF_3D,rollIntensity:.5);
lastpulse = max(lastpulse,gametic+10);
Demolitionist(Owner).lastbump *= .995;
}
if ( am ) return;
am = Owner.FindInventory("RagekitArmor");
if ( !am )
{
am = Inventory(Spawn("RagekitArmor"));
am.AttachToOwner(Owner);
}
}
override void EndEffect()
{
Super.EndEffect();
if ( !Owner ) return;
Owner.A_StartSound("powerup/ragekitend",CHAN_ITEMEXTRA,CHANF_OVERLAP);
SWWMHandler.DoFlash(Owner,Color(128,255,0,0),30);
Owner.A_QuakeEx(4,4,4,20,0,1,"",QF_RELATIVE|QF_SCALEDOWN|QF_3D,rollIntensity:1.);
Owner.A_AlertMonsters(2000);
Demolitionist(Owner).lastbump *= .9;
if ( (EffectTics <= 0) && Owner && Owner.CheckLocalView() ) Console.Printf(StringTable.Localize("$D_RAGEKIT"));
}
void DoHitFX()
{
if ( level.maptime <= lasteffect+5 ) return;
Owner.GiveBody(5,100);
Owner.A_AlertMonsters(swwm_uncapalert?0:5000);
SWWMHandler.DoFlash(Owner,Color(64,255,0,0),10);
Owner.A_QuakeEx(8,8,8,Random[Rage](3,8),0,1,"",QF_RELATIVE|QF_SCALEDOWN|QF_3D,rollIntensity:1.);
if ( (Owner.player == players[consoleplayer]) && (gametic > lastrage) && (swwm_mutevoice < 2) )
lastrage = SWWMHandler.AddOneliner("ragekit",2,5)+40;
Owner.A_StartSound("powerup/ragekithit",CHAN_POWERUP,CHANF_OVERLAP);
lasteffect = level.maptime;
lastpulse = max(lastpulse,gametic+35);
Demolitionist(Owner).lastbump *= .9;
}
override void ModifyDamage( int damage, Name damageType, out int newdamage, bool passive, Actor inflictor, Actor source, int flags )
{
if ( passive ) return;
if ( (damageType == 'Melee') || (damageType == 'Jump') || (damageType == 'Dash') || (damageType == 'Buttslam') || (damageType == 'GroundPound') || (damageType == 'HammerShockwave') )
{
newdamage = damage*8;
DoHitFX();
}
}
}
Class RagekitX : SWWMItemOverlay
{
Default
{
RenderStyle "Normal";
}
}
Class Ragekit : Inventory
{
Mixin SWWMAutoUseFix;
Mixin SWWMOverlapPickupSound;
Mixin SWWMUseToPickup;
Mixin SWWMRespawn;
Mixin SWWMRotatingPickup;
Mixin SWWMPickupGlow;
Mixin SWWMUnrealStyleDrop;
override bool Use( bool pickup )
{
if ( pickup && !deathmatch ) return false;
if ( pickup && ((Owner.player == players[consoleplayer]) || bBigPowerup) ) Owner.A_StartSound(UseSound,CHAN_ITEMEXTRA);
Owner.GiveBody(100,100);
SWWMUtility.AchievementProgressInc("rage",1,Owner.player);
if ( !(Owner is 'Demolitionist') )
{
SWWMHandler.DoFlash(Owner,Color(64,255,0,0),30);
Owner.A_QuakeEx(8,8,8,20,0,1,"",QF_RELATIVE|QF_SCALEDOWN|QF_3D,rollIntensity:1.);
return true;
}
let r = RagekitPower(Owner.FindInventory("RagekitPower"));
if ( r )
{
r.EffectTics += r.default.EffectTics;
SWWMHandler.DoFlash(Owner,Color(64,255,0,0),30);
Owner.A_QuakeEx(8,8,8,20,0,1,"",QF_RELATIVE|QF_SCALEDOWN|QF_3D,rollIntensity:1.);
r.lastpulse = max(r.lastpulse,gametic+35);
Demolitionist(Owner).lastbump *= .95;
}
else Owner.GiveInventory("RagekitPower",1);
return true;
}
override void PreTravelled()
{
if ( tracer ) tracer.Destroy();
}
override void Travelled()
{
if ( tracer ) return;
tracer = Spawn("RagekitX",pos);
tracer.angle = angle;
tracer.target = self;
tracer.FloatBobPhase = FloatBobPhase;
}
override void PostBeginPlay()
{
Super.PostBeginPlay();
tracer = Spawn("RagekitX",pos);
tracer.angle = angle;
tracer.target = self;
tracer.FloatBobPhase = FloatBobPhase;
}
Default
{
Tag "$T_RAGEKIT";
Stamina 500000;
Inventory.Icon "graphics/HUD/Icons/I_Ragekit.png";
Inventory.PickupSound "misc/p_pkup";
Inventory.UseSound "powerup/ragekit";
Inventory.PickupMessage "$T_RAGEKIT";
Inventory.MaxAmount 5;
Inventory.InterHubAmount 5;
Inventory.PickupFlash "SWWMPurplePickupFlash";
+INVENTORY.ALWAYSPICKUP;
+INVENTORY.AUTOACTIVATE;
+INVENTORY.INVBAR;
+COUNTITEM;
+INVENTORY.BIGPOWERUP;
+FLOATBOB;
+DONTGIB;
FloatBobStrength 0.25;
}
States
{
Spawn:
XZW1 A -1;
Stop;
}
}
Class BarrierLight : PointLightAttenuated
{
Default
{
Args 32,72,0,80;
}
override void Tick()
{
Super.Tick();
if ( !target || !master )
{
Destroy();
return;
}
if ( target.player ) SetOrigin(SWWMUtility.GetFireOffset(target,10,0,0),true);
else SetOrigin(target.Vec3Angle(10,target.angle,target.missileheight),true);
bDORMANT = Powerup(master).isBlinking();
}
}
Class BarrierSnd : SWWMNonInteractiveActor
{
override void Tick()
{
if ( !target || !master )
{
Destroy();
return;
}
SetOrigin(target.pos,true);
if ( players[consoleplayer].Camera == target )
{
A_SoundVolume(CHAN_VOICE,0.);
A_SoundVolume(CHAN_7,.1);
}
else
{
A_SoundVolume(CHAN_VOICE,.06);
A_SoundVolume(CHAN_7,0.);
}
}
override void PostBeginPlay()
{
Super.PostBeginPlay();
A_StartSound("powerup/barrieract",CHAN_VOICE,CHANF_LOOP,.06,1.5);
A_StartSound("powerup/barrieract",CHAN_7,CHANF_LOOP,.1,ATTN_NONE);
}
override void OnDestroy()
{
Super.OnDestroy();
A_StopSound(CHAN_VOICE);
A_StopSound(CHAN_7);
}
}
Class BarrierArmor : SWWMArmor
{
Default
{
+SWWMARMOR.NOHITSOUND;
+SWWMARMOR.NOHITFLASH;
+SWWMARMOR.NODRAIN;
SWWMArmor.ArmorPriority 10;
}
override int HandleDamage( int damage, Name damageType, int flags )
{
if ( (damageType == 'Fire') || (damageType == 'Ice') || (damageType == 'Slime') || (damageType == 'Electric') || (damageType == 'Plasma') || (damageType == 'Radiation') || (damageType == 'Wind') || (damageType == 'Water') || (damageType == 'Corroded') || (damageType == 'Lava') )
return damage;
return 0;
}
override void DoEffect()
{
Super.DoEffect();
if ( !Owner.FindInventory('BarrierPower') )
Destroy();
}
}
Class BarrierPower : PowerIronFeet
{
Mixin SWWMShadedPowerup;
Actor snd, l;
Inventory am;
Default
{
Inventory.Icon "graphics/HUD/Icons/I_Barrier.png";
Powerup.Duration -60;
Powerup.Color "20 FF 00", 0.1;
Powerup.Mode "Full"; // no leaky damage
+INVENTORY.ADDITIVETIME;
}
override void InitEffect()
{
Super.InitEffect();
if ( !Owner ) return;
l = Spawn("BarrierLight",Owner.pos);
l.target = Owner;
l.master = self;
if ( Owner is 'Demolitionist' )
Demolitionist(Owner).lastbump *= 0.95;
}
override void EndEffect()
{
Super.EndEffect();
if ( !Owner ) return;
Owner.A_StartSound("powerup/barrierend",CHAN_ITEMEXTRA,CHANF_OVERLAP);
if ( Owner is 'Demolitionist' )
Demolitionist(Owner).lastbump *= 0.95;
if ( (EffectTics <= 0) && Owner && Owner.CheckLocalView() ) Console.Printf(StringTable.Localize("$D_BARRIER"));
}
override void DoEffect()
{
// don't reset air supply like PowerIronFeet, call parent instead
Powerup.DoEffect();
if ( !Owner ) return;
if ( !snd ) snd = Spawn("BarrierSnd",Owner.pos);
snd.target = Owner;
snd.master = self;
if ( !am )
{
am = Owner.FindInventory("BarrierArmor");
if ( !am )
{
am = Inventory(Spawn("BarrierArmor"));
am.AttachToOwner(Owner);
}
}
// break ourselves if we're in an endlevel sector
bool endlv = false;
for ( int i=0; i<Owner.CurSector.Get3DFloorCount(); i++ )
{
F3DFloor ff = Owner.CurSector.Get3DFloor(i);
if ( !(ff.flags&(F3DFloor.FF_EXISTS|F3DFloor.FF_SWIMMABLE)) ) continue;
if ( (ff.model.DamageAmount <= 0) || (ff.model.damageinterval <= 0) ) continue;
if ( ff.top.ZAtPoint(Owner.pos.xy) <= Owner.pos.z ) continue;
if ( ff.bottom.ZAtPoint(Owner.pos.xy) >= (Owner.pos.z+Owner.Height) ) continue;
if ( !(ff.model.flags&Sector.SECF_ENDLEVEL) ) continue;
endlv = true;
break;
}
if ( !endlv && ((Owner.pos.z == Owner.CurSector.floorplane.ZAtPoint(Owner.pos.xy)) || Owner.waterlevel) )
{
bool damageterrain = false;
if ( (Owner.CurSector.damageamount > 0) && (Owner.CurSector.damageinterval > 0) ) damageterrain = true;
else
{
let t = Owner.CurSector.GetFloorTerrain(0);
if ( t && (t.DamageAmount > 0) && (t.DamageTimeMask > 0) )
damageterrain = true;
}
if ( damageterrain && (Owner.CurSector.flags&Sector.SECF_ENDLEVEL) ) endlv = true;
}
if ( !endlv ) return;
EffectTics = min(0,EffectTics);
}
}
Class EBarrier : Inventory
{
Mixin SWWMAutoUseFix;
Mixin SWWMOverlapPickupSound;
Mixin SWWMUseToPickup;
Mixin SWWMRespawn;
Mixin SWWMRotatingPickup;
Mixin SWWMPickupGlow;
Mixin SWWMUnrealStyleDrop;
int terrainwait;
override bool Use( bool pickup )
{
if ( pickup && !deathmatch ) return false;
if ( pickup && ((Owner.player == players[consoleplayer]) || bBigPowerup) ) Owner.A_StartSound(UseSound,CHAN_ITEMEXTRA,CHANF_OVERLAP);
let b = BarrierPower(Owner.FindInventory("BarrierPower"));
if ( b )
{
b.EffectTics += b.default.EffectTics;
if ( Owner is 'Demolitionist' )
Demolitionist(Owner).lastbump *= 0.95;
}
else Owner.GiveInventory("BarrierPower",1);
SWWMUtility.AchievementProgressInc("barrier",1,Owner.player);
return true;
}
override void PreTravelled()
{
if ( tracer ) tracer.Destroy();
}
override void Travelled()
{
Super.Travelled();
if ( tracer ) return;
tracer = Spawn("EBarrierX",pos);
tracer.angle = angle;
tracer.target = self;
tracer.FloatBobPhase = FloatBobPhase;
}
override void PostBeginPlay()
{
Super.PostBeginPlay();
tracer = Spawn("EBarrierX",pos);
tracer.angle = angle;
tracer.target = self;
tracer.FloatBobPhase = FloatBobPhase;
}
override void DoEffect()
{
Super.DoEffect();
if ( !Owner || (Owner.Health <= 0) ) return;
// check terrain for auto-use
let b = Powerup(Owner.FindInventory("BarrierPower"));
if ( b && (b.EffectTics > 5) )
{
terrainwait = 20;
return;
}
bool damageterrain = false;
bool endlevelterrain = false;
// check any 3d floors first
for ( int i=0; i<Owner.CurSector.Get3DFloorCount(); i++ )
{
F3DFloor ff = Owner.CurSector.Get3DFloor(i);
if ( !(ff.flags&(F3DFloor.FF_EXISTS|F3DFloor.FF_SWIMMABLE)) ) continue;
if ( (ff.model.DamageAmount <= 0) || (ff.model.damageinterval <= 0) ) continue;
if ( ff.top.ZAtPoint(Owner.pos.xy) <= Owner.pos.z ) continue;
if ( ff.bottom.ZAtPoint(Owner.pos.xy) >= (Owner.pos.z+Owner.Height) ) continue;
if ( ff.model.flags&Sector.SECF_ENDLEVEL ) endlevelterrain = true;
damageterrain = true;
break;
}
if ( !damageterrain && ((Owner.pos.z == Owner.CurSector.floorplane.ZAtPoint(Owner.pos.xy)) || Owner.waterlevel) )
{
if ( (Owner.CurSector.damageamount > 0) && (Owner.CurSector.damageinterval > 0) ) damageterrain = true;
else
{
let t = Owner.CurSector.GetFloorTerrain(0);
if ( t && (t.DamageAmount > 0) && (t.DamageTimeMask > 0) )
damageterrain = true;
}
if ( damageterrain && (Owner.CurSector.flags&Sector.SECF_ENDLEVEL) ) endlevelterrain = true;
}
// do not auto-use for these
if ( endlevelterrain ) return;
if ( !damageterrain )
{
terrainwait = max(0,terrainwait-1);
return;
}
else terrainwait++;
if ( terrainwait <= 20 ) return;
terrainwait = 0;
Owner.UseInventory(self);
}
Default
{
Tag "$T_BARRIER";
Stamina 80000;
Inventory.Icon "graphics/HUD/Icons/I_Barrier.png";
Inventory.PickupSound "misc/p_pkup";
Inventory.UseSound "powerup/barrier";
Inventory.PickupMessage "$T_BARRIER";
Inventory.MaxAmount 5;
Inventory.InterHubAmount 5;
Inventory.PickupFlash "SWWMCyanPickupFlash";
+INVENTORY.ALWAYSPICKUP;
+INVENTORY.AUTOACTIVATE;
+INVENTORY.INVBAR;
+FLOATBOB;
+DONTGIB;
FloatBobStrength 0.25;
// must copy height of vanilla radsuit
Height 46;
}
States
{
Spawn:
XZW1 A -1;
Stop;
}
}
Class EBarrierX : SWWMItemOverlay {}