While in the latter case this may result in longer loops, it also reduces GC thrashing by not needing to allocate an iterator every time. This also simplifies the DoBlast code as there is no longer a need to manually traverse portals vertically.
1470 lines
36 KiB
Text
1470 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") )
|
|
{
|
|
let hnd = SWWMHandler(EventHandler.Find("SWWMHandler"));
|
|
if ( hnd ) foreach ( a:hnd.suckableactors )
|
|
{
|
|
if ( !a || !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
|
|
let hnd = SWWMHandler(EventHandler.Find("SWWMHandler"));
|
|
Actor gt = null;
|
|
if ( hnd ) foreach ( a:hnd.suckableactors )
|
|
{
|
|
if ( !a || !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(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]) && (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 {}
|