This reverts commit 68704316e7.
Turns out this wasn't really necessary here, as I was already doing the "bookkeeping" myself.
1504 lines
37 KiB
Text
1504 lines
37 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, 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.player == players[consoleplayer] )
|
|
SWWMScoreObj.SpawnAtActorBunch(1000,Owner,Font.CR_BLUE);
|
|
if ( Owner is 'Demolitionist' )
|
|
{
|
|
let n = Owner.FindInventory("ArmorNugget");
|
|
if ( !n ) Owner.GiveInventory("ArmorNugget",GetDefaultByType("ArmorNugget").MaxAmount);
|
|
else
|
|
{
|
|
n.Amount = n.MaxAmount;
|
|
if ( Owner.player == players[consoleplayer] )
|
|
SWWMScoreObj.SpawnAtActorBunch(n.MaxAmount,Owner,Font.CR_GREEN);
|
|
}
|
|
let b = Owner.FindInventory("BlastSuit");
|
|
if ( !b ) Owner.GiveInventory("BlastSuit",GetDefaultByType("BlastSuit").MaxAmount);
|
|
else
|
|
{
|
|
b.Amount = b.MaxAmount;
|
|
if ( Owner.player == players[consoleplayer] )
|
|
SWWMScoreObj.SpawnAtActorBunch(b.MaxAmount,Owner,Font.CR_GREEN);
|
|
}
|
|
let w = Owner.FindInventory("WarArmor");
|
|
if ( !w ) Owner.GiveInventory("WarArmor",GetDefaultByType("WarArmor").MaxAmount);
|
|
else
|
|
{
|
|
w.Amount = w.MaxAmount;
|
|
if ( Owner.player == players[consoleplayer] )
|
|
SWWMScoreObj.SpawnAtActorBunch(w.MaxAmount,Owner,Font.CR_GREEN);
|
|
}
|
|
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, 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);
|
|
let bt = BlockThingsIterator.Create(self,256);
|
|
foreach ( t,p,f:bt )
|
|
{
|
|
if ( !t || !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;
|
|
}
|
|
}
|
|
bt.Destroy();
|
|
// player made noise or is visible again
|
|
if ( !master || (LastHeard == master) || !master.FindInventory("GhostPower") )
|
|
{
|
|
// note: this is faster than using a thinkeriterator
|
|
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, bSavedMVisBlocked;
|
|
|
|
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;
|
|
bSavedMVisBlocked = Owner.bMVISBLOCKED;
|
|
Owner.bINVISIBLE = true; // makes sure player doesn't render while still keeping psprites intact
|
|
Owner.bCANTSEEK = true; // seeking missiles don't track
|
|
Owner.bSHADOW = true; // monsters don't aim straight
|
|
Owner.bMVISBLOCKED = true; // ensure full invisibility
|
|
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.bMVISBLOCKED = bSavedMVisBlocked;
|
|
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);
|
|
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);
|
|
SWWMHandler.AddOneliner("invinciball",2,40);
|
|
}
|
|
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] )
|
|
{
|
|
SWWMScoreObj.SpawnAtActorBunch(1,Owner,Font.CR_BLUE);
|
|
if ( (gametic > lastrage) && (swwm_mutevoice < 2) )
|
|
lastrage = SWWMHandler.AddOneliner("ragekit",2,5)+20;
|
|
}
|
|
Owner.A_QuakeEx(1.5,1.5,1.5,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] )
|
|
{
|
|
SWWMScoreObj.SpawnAtActorBunch(5,Owner,Font.CR_BLUE);
|
|
if ( (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, 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);
|
|
if ( Owner.player == players[consoleplayer] )
|
|
SWWMScoreObj.SpawnAtActorBunch(100,Owner,Font.CR_BLUE);
|
|
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;
|
|
// do not auto-use if we're invincible, that'd be a waste
|
|
if ( Owner.bINVULNERABLE || (Owner.player && (Owner.player.cheats&(CF_GODMODE|CF_GODMODE2))) || Owner.FindInventory("InvinciballPower") )
|
|
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 {}
|