qzdoom-gpl/wadsrc/static/zscript/inventory/powerups.txt

1228 lines
26 KiB
Text
Raw Normal View History

class PowerupGiver : Inventory native
{
native Class<Actor> PowerupType;
native int EffectTics; // Non-0 to override the powerup's default tics
native color BlendColor; // Non-0 to override the powerup's default blend
native Name Mode; // Meaning depends on powerup - used for Invulnerability and Invisibility
native double Strength; // Meaning depends on powerup - currently used only by Invisibility
Default
{
Inventory.DefMaxAmount;
+INVENTORY.INVBAR
+INVENTORY.FANCYPICKUPSOUND
Inventory.PickupSound "misc/p_pkup";
}
}
class Powerup : Inventory native
{
native int EffectTics;
native color BlendColor;
native Name Mode; // Meaning depends on powerup - used for Invulnerability and Invisibility
native double Strength; // Meaning depends on powerup - currently used only by Invisibility
// Note, that while this is an inventory flag, it only has meaning on an active powerup.
2016-11-30 15:19:13 +00:00
override bool GetNoTeleportFreeze() { return bNoTeleportFreeze; }
native virtual void InitEffect();
native virtual void EndEffect();
native bool isBlinking();
}
class PowerInvulnerable : Powerup native
{
Default
{
Powerup.Duration -30;
inventory.icon "SPSHLD0";
}
}
class PowerStrength : Powerup native
{
Default
{
Powerup.Duration 1;
Powerup.Color "ff 00 00", 0.5;
+INVENTORY.HUBPOWER
}
}
class PowerInvisibility : Powerup native
{
Default
{
+SHADOW;
Powerup.Duration -60;
Powerup.Strength 80;
Powerup.Mode "Fuzzy";
}
}
class PowerGhost : PowerInvisibility
{
Default
{
+GHOST;
Powerup.Duration -60;
Powerup.Strength 60;
Powerup.Mode "None";
}
}
class PowerShadow : PowerInvisibility
{
Default
{
+INVENTORY.HUBPOWER
Powerup.Duration -55;
Powerup.Strength 75;
Powerup.Mode "Cumulative";
}
}
class PowerIronFeet : Powerup native
{
Default
{
Powerup.Duration -60;
Powerup.Color "00 ff 00", 0.125;
}
}
class PowerMask : PowerIronFeet native
{
Default
{
Powerup.Duration -80;
Powerup.Color "00 00 00", 0;
+INVENTORY.HUBPOWER
Inventory.Icon "I_MASK";
}
}
class PowerLightAmp : Powerup native
{
Default
{
Powerup.Duration -120;
}
}
class PowerTorch : PowerLightAmp native {}
//===========================================================================
//
// Flight
//
//===========================================================================
class PowerFlight : Powerup
{
Default
{
Powerup.Duration -60;
+INVENTORY.HUBPOWER
}
bool HitCenterFrame;
//===========================================================================
//
// APowerFlight :: InitEffect
//
//===========================================================================
override void InitEffect ()
{
Super.InitEffect();
Owner.bFly = true;
Owner.bNoGravity = true;
if (Owner.pos.Z <= Owner.floorz)
{
Owner.Vel.Z = 4;; // thrust the player in the air a bit
}
if (Owner.Vel.Z <= -35)
{ // stop falling scream
Owner.A_StopSound (CHAN_VOICE);
}
}
//===========================================================================
//
// APowerFlight :: DoEffect
//
//===========================================================================
override void Tick ()
{
// The Wings of Wrath only expire in multiplayer and non-hub games
if (!multiplayer && level.infinite_flight)
{
EffectTics++;
}
Super.Tick ();
}
//===========================================================================
//
// APowerFlight :: EndEffect
//
//===========================================================================
override void EndEffect ()
{
Super.EndEffect();
if (Owner == NULL || Owner.player == NULL)
{
return;
}
if (!(Owner.bFlyCheat))
{
if (Owner.pos.Z != Owner.floorz)
{
Owner.player.centering = true;
}
Owner.bFly = false;
Owner.bNoGravity = false;
}
}
//===========================================================================
//
// APowerFlight :: DrawPowerup
//
//===========================================================================
override bool DrawPowerup (int x, int y)
{
// If this item got a valid icon use that instead of the default spinning wings.
if (Icon.isValid())
{
return Super.DrawPowerup(x, y);
}
if (EffectTics > BLINKTHRESHOLD || !(EffectTics & 16))
{
TextureID picnum = TexMan.CheckForTexture ("SPFLY0", TexMan.Type_MiscPatch);
int frame = (level.time/3) & 15;
if (!picnum.isValid())
{
return false;
}
if (Owner.bNoGravity)
{
if (HitCenterFrame && (frame != 15 && frame != 0))
{
screen.DrawHUDTexture (picnum + 15, x, y);
}
else
{
screen.DrawHUDTexture (picnum + frame, x, y);
HitCenterFrame = false;
}
}
else
{
if (!HitCenterFrame && (frame != 15 && frame != 0))
{
screen.DrawHUDTexture (picnum + frame, x, y);
HitCenterFrame = false;
}
else
{
screen.DrawHUDTexture (picnum+15, x, y);
HitCenterFrame = true;
}
}
}
return true;
}
}
//===========================================================================
//
// WeaponLevel2
//
//===========================================================================
class PowerWeaponLevel2 : Powerup
{
Default
{
Powerup.Duration -40;
Inventory.Icon "SPINBK0";
+INVENTORY.NOTELEPORTFREEZE
}
//===========================================================================
//
// APowerWeaponLevel2 :: InitEffect
//
//===========================================================================
override void InitEffect ()
{
Super.InitEffect();
let player = Owner.player;
if (player == null)
return;
let weap = player.ReadyWeapon;
if (weap == null)
return;
let sister = weap.SisterWeapon;
if (sister == null)
return;
if (!sister.bPowered_Up)
return;
let ready = sister.GetReadyState();
if (weap.GetReadyState() != ready)
{
player.ReadyWeapon = sister;
player.SetPsprite(PSP_WEAPON, ready);
}
else
{
PSprite psp = player.FindPSprite(PSprite.WEAPON);
if (psp != null && psp.Caller == player.ReadyWeapon)
{
// If the weapon changes but the state does not, we have to manually change the PSprite's caller here.
psp.Caller = sister;
player.ReadyWeapon = sister;
}
else
{
// Something went wrong. Initiate a regular weapon change.
player.PendingWeapon = sister;
}
}
}
//===========================================================================
//
// APowerWeaponLevel2 :: EndEffect
//
//===========================================================================
override void EndEffect ()
{
Super.EndEffect();
if (Owner == null) return;
let player = Owner.player;
if (player != NULL)
{
if (player.ReadyWeapon != NULL && player.ReadyWeapon.bPowered_Up)
{
player.ReadyWeapon.EndPowerup ();
}
if (player.PendingWeapon != NULL && player.PendingWeapon != WP_NOCHANGE &&
player.PendingWeapon.bPowered_Up &&
player.PendingWeapon.SisterWeapon != NULL)
{
player.PendingWeapon = player.PendingWeapon.SisterWeapon;
}
}
}
}
2017-01-15 19:58:52 +00:00
//===========================================================================
//
// Speed
//
//===========================================================================
class PowerSpeed : Powerup native
{
native int SpeedFlags;
2017-01-15 19:58:52 +00:00
const PSF_NOTRAIL = 1;
Default
{
Powerup.Duration -45;
Speed 1.5;
Inventory.Icon "SPBOOT0";
+INVENTORY.NOTELEPORTFREEZE
}
2017-01-15 19:58:52 +00:00
override double GetSpeedFactor()
{
return Speed;
}
//===========================================================================
//
// APowerSpeed :: DoEffect
//
//===========================================================================
override void DoEffect ()
{
Super.DoEffect ();
if (Owner == NULL || Owner.player == NULL)
return;
if (Owner.player.cheats & CF_PREDICTING)
return;
if (SpeedFlags & PSF_NOTRAIL)
return;
if (level.time & 1)
return;
// Check if another speed item is present to avoid multiple drawing of the speed trail.
// Only the last PowerSpeed without PSF_NOTRAIL set will actually draw the trail.
for (Inventory item = Inv; item != NULL; item = item.Inv)
{
let sitem = PowerSpeed(item);
if (sitem != null && !(sitem.SpeedFlags & PSF_NOTRAIL))
{
return;
}
}
if (Owner.Vel.Length() <= 12)
return;
Actor speedMo = Spawn("PlayerSpeedTrail", Owner.Pos, NO_REPLACE);
if (speedMo)
{
speedMo.Angle = Owner.Angle;
speedMo.Translation = Owner.Translation;
speedMo.target = Owner;
speedMo.sprite = Owner.sprite;
speedMo.frame = Owner.frame;
speedMo.Floorclip = Owner.Floorclip;
// [BC] Also get the scale from the owner.
speedMo.Scale = Owner.Scale;
if (Owner == players[consoleplayer].camera &&
!(Owner.player.cheats & CF_CHASECAM))
{
speedMo.bInvisible = true;
}
}
}
}
// Player Speed Trail (used by the Speed Powerup) ----------------------------
class PlayerSpeedTrail : Actor
{
Default
{
+NOBLOCKMAP
+NOGRAVITY
Alpha 0.6;
RenderStyle "Translucent";
}
override void Tick()
{
Alpha -= .6 / 8;
if (Alpha <= 0)
{
Destroy ();
}
}
}
2017-01-15 19:58:52 +00:00
//===========================================================================
//
// Minotaur
//
//===========================================================================
class PowerMinotaur : Powerup
{
Default
{
Powerup.Duration -25;
Inventory.Icon "SPMINO0";
}
}
2017-01-15 19:58:52 +00:00
//===========================================================================
//
// Targeter
//
//===========================================================================
2017-01-15 18:44:43 +00:00
class PowerTargeter : Powerup
{
Default
{
Powerup.Duration -160;
+INVENTORY.HUBPOWER
}
States
{
Targeter:
TRGT A -1;
Stop;
TRGT B -1;
Stop;
TRGT C -1;
Stop;
}
2017-01-15 18:44:43 +00:00
override void Travelled ()
{
InitEffect ();
}
override void InitEffect ()
{
// Why is this called when the inventory isn't even attached yet
// in APowerup.CreateCopy?
if (!Owner.FindInventory(GetClass(), true))
return;
let player = Owner.player;
Super.InitEffect();
if (player == null)
return;
let stat = FindState("Targeter");
if (stat != null)
{
player.SetPsprite(PSprite.TARGETCENTER, stat);
player.SetPsprite(PSprite.TARGETLEFT, stat + 1);
player.SetPsprite(PSprite.TARGETRIGHT, stat + 2);
}
player.GetPSprite(PSprite.TARGETCENTER).x = (160-3);
player.GetPSprite(PSprite.TARGETCENTER).y =
player.GetPSprite(PSprite.TARGETLEFT).y =
player.GetPSprite(PSprite.TARGETRIGHT).y = (100-3);
PositionAccuracy ();
}
override void AttachToOwner(Actor other)
{
Super.AttachToOwner(other);
// Let's actually properly call this for the targeters.
InitEffect();
}
override bool HandlePickup(Inventory item)
{
if (Super.HandlePickup(item))
{
InitEffect(); // reset the HUD sprites
return true;
}
return false;
}
override void DoEffect ()
{
Super.DoEffect ();
if (Owner != null && Owner.player != null)
{
let player = Owner.player;
PositionAccuracy ();
if (EffectTics < 5*TICRATE)
{
let stat = FindState("Targeter");
if (stat != null)
{
if (EffectTics & 32)
{
player.SetPsprite(PSprite.TARGETRIGHT, null);
player.SetPsprite(PSprite.TARGETLEFT, stat + 1);
}
else if (EffectTics & 16)
{
player.SetPsprite(PSprite.TARGETRIGHT, stat + 2);
player.SetPsprite(PSprite.TARGETLEFT, null);
}
}
}
}
}
override void EndEffect ()
{
Super.EndEffect();
if (Owner != null && Owner.player != null)
{
// Calling GetPSprite here could crash if we're creating a new game.
// This is because P_SetupLevel nulls the player's mo before destroying
// every DThinker which in turn ends up calling this.
// However P_SetupLevel is only called after G_NewInit which calls
// every player's dtor which destroys all their psprites.
let player = Owner.player;
PSprite pspr;
if ((pspr = player.FindPSprite(PSprite.TARGETCENTER)) != null) pspr.SetState(null);
if ((pspr = player.FindPSprite(PSprite.TARGETLEFT)) != null) pspr.SetState(null);
if ((pspr = player.FindPSprite(PSprite.TARGETRIGHT)) != null) pspr.SetState(null);
}
}
private void PositionAccuracy ()
{
let player = Owner.player;
if (player != null)
{
player.GetPSprite(PSprite.TARGETLEFT).x = (160-3) - ((100 - player.mo.accuracy));
player.GetPSprite(PSprite.TARGETRIGHT).x = (160-3)+ ((100 - player.mo.accuracy));
}
}
}
//===========================================================================
//
// Frightener
//
//===========================================================================
class PowerFrightener : Powerup
{
Default
{
Powerup.Duration -60;
}
override void InitEffect ()
{
Super.InitEffect();
if (Owner== null || Owner.player == null)
return;
Owner.player.cheats |= CF_FRIGHTENING;
}
override void EndEffect ()
{
Super.EndEffect();
if (Owner== null || Owner.player == null)
return;
Owner.player.cheats &= ~CF_FRIGHTENING;
}
}
//===========================================================================
//
// Buddha
//
//===========================================================================
class PowerBuddha : Powerup
{
Default
{
Powerup.Duration -60;
}
override void InitEffect ()
{
Super.InitEffect();
if (Owner== null || Owner.player == null)
return;
Owner.player.cheats |= CF_BUDDHA;
}
override void EndEffect ()
{
Super.EndEffect();
if (Owner== null || Owner.player == null)
return;
Owner.player.cheats &= ~CF_BUDDHA;
}
}
//===========================================================================
//
// Scanner (this is active just by being present)
//
//===========================================================================
class PowerScanner : Powerup
{
Default
{
Powerup.Duration -80;
+INVENTORY.HUBPOWER
}
}
2017-01-03 19:06:20 +00:00
//===========================================================================
//
// TimeFreezer
//
//===========================================================================
class PowerTimeFreezer : Powerup
{
Default
{
Powerup.Duration -12;
}
2017-01-03 19:06:20 +00:00
//===========================================================================
//
// InitEffect
//
//===========================================================================
override void InitEffect()
{
int freezemask;
Super.InitEffect();
if (Owner == null || Owner.player == null)
return;
// When this powerup is in effect, pause the music.
S_PauseSound(false, false);
// Give the player and his teammates the power to move when time is frozen.
freezemask = 1 << Owner.PlayerNumber();
Owner.player.timefreezer |= freezemask;
for (int i = 0; i < MAXPLAYERS; i++)
{
if (playeringame[i] &&
players[i].mo != null &&
players[i].mo.IsTeammate(Owner)
)
{
players[i].timefreezer |= freezemask;
}
}
// [RH] The effect ends one tic after the counter hits zero, so make
// sure we start at an odd count.
EffectTics += !(EffectTics & 1);
if ((EffectTics & 1) == 0)
{
EffectTics++;
}
// Make sure the effect starts and ends on an even tic.
if ((level.time & 1) == 0)
{
level.frozen = true;;
}
else
{
// Compensate for skipped tic, but beware of overflow.
if(EffectTics < 0x7fffffff)
EffectTics++;
}
}
//===========================================================================
//
// APowerTimeFreezer :: DoEffect
//
//===========================================================================
override void DoEffect()
{
Super.DoEffect();
// [RH] Do not change LEVEL_FROZEN on odd tics, or the Revenant's tracer
// will get thrown off.
// [ED850] Don't change it if the player is predicted either.
if (level.time & 1 || (Owner != null && Owner.player != null && Owner.player.cheats & CF_PREDICTING))
{
return;
}
// [RH] The "blinking" can't check against EffectTics exactly or it will
// never happen, because InitEffect ensures that EffectTics will always
// be odd when level.time is even.
level.frozen = ( EffectTics > 4*32
|| (( EffectTics > 3*32 && EffectTics <= 4*32 ) && ((EffectTics + 1) & 15) != 0 )
|| (( EffectTics > 2*32 && EffectTics <= 3*32 ) && ((EffectTics + 1) & 7) != 0 )
|| (( EffectTics > 32 && EffectTics <= 2*32 ) && ((EffectTics + 1) & 3) != 0 )
|| (( EffectTics > 0 && EffectTics <= 1*32 ) && ((EffectTics + 1) & 1) != 0 ));
}
//===========================================================================
//
// APowerTimeFreezer :: EndEffect
//
//===========================================================================
override void EndEffect()
{
Super.EndEffect();
// If there is an owner, remove the timefreeze flag corresponding to
// her from all players.
if (Owner != null && Owner.player != null)
{
int freezemask = ~(1 << Owner.PlayerNumber());
for (int i = 0; i < MAXPLAYERS; ++i)
{
players[i].timefreezer &= freezemask;
}
}
// Are there any players who still have timefreezer bits set?
for (int i = 0; i < MAXPLAYERS; ++i)
{
if (playeringame[i] && players[i].timefreezer != 0)
{
return;
}
}
// No, so allow other actors to move about freely once again.
level.frozen = false;
// Also, turn the music back on.
S_ResumeSound(false);
}
}
//===========================================================================
//
// Damage
//
//===========================================================================
class PowerDamage : Powerup
{
Default
{
Powerup.Duration -25;
}
//===========================================================================
//
// InitEffect
//
//===========================================================================
override void InitEffect()
{
Super.InitEffect();
if (Owner != null)
{
Owner.A_PlaySound(SeeSound, CHAN_5, 1.0, false, ATTN_NONE);
}
}
//===========================================================================
//
// EndEffect
//
//===========================================================================
override void EndEffect()
{
Super.EndEffect();
if (Owner != null)
{
Owner.A_PlaySound(DeathSound, CHAN_5, 1.0, false, ATTN_NONE);
}
}
//===========================================================================
//
// ModifyDamage
//
//===========================================================================
override void ModifyDamage(int damage, Name damageType, out int newdamage, bool passive)
{
if (!passive && damage > 0)
{
newdamage = max(1, ApplyDamageFactors(GetClass(), damageType, damage, damage * 4));
if (Owner != null && newdamage > damage) Owner.A_PlaySound(ActiveSound, CHAN_AUTO, 1.0, false, ATTN_NONE);
}
}
}
//===========================================================================
//
// Protection
//
//===========================================================================
class PowerProtection : Powerup
{
Default
{
Powerup.Duration -25;
}
//===========================================================================
//
// InitEffect
//
//===========================================================================
override void InitEffect()
{
Super.InitEffect();
let o = Owner; // copy to a local variable for quicker access.
if (o != null)
{
o.A_PlaySound(SeeSound, CHAN_AUTO, 1.0, false, ATTN_NONE);
// Transfer various protection flags if owner does not already have them.
// If the owner already has the flag, clear it from the powerup.
// If the powerup still has a flag set, add it to the owner.
bNoRadiusDmg &= !o.bNoRadiusDmg;
o.bNoRadiusDmg |= bNoRadiusDmg;
bDontMorph &= !o.bDontMorph;
o.bDontMorph |= bDontMorph;
bDontSquash &= !o.bDontSquash;
o.bDontSquash |= bDontSquash;
bDontBlast &= !o.bDontBlast;
o.bDontBlast |= bDontBlast;
bNoTeleOther &= !o.bNoTeleOther;
o.bNoTeleOther |= bNoTeleOther;
bNoPain &= !o.bNoPain;
o.bNoPain |= bNoPain;
bDontRip &= !o.bDontRip;
o.bDontRip |= bDontRip;
}
}
//===========================================================================
//
// EndEffect
//
//===========================================================================
override void EndEffect()
{
Super.EndEffect();
let o = Owner; // copy to a local variable for quicker access.
if (o != null)
{
o.A_PlaySound(DeathSound, CHAN_AUTO, 1.0, false, ATTN_NONE);
o.bNoRadiusDmg &= !bNoRadiusDmg;
o.bDontMorph &= !bDontMorph;
o.bDontSquash &= !bDontSquash;
o.bDontBlast &= !bDontBlast;
o.bNoTeleOther &= !bNoTeleOther;
o.bNoPain &= !bNoPain;
o.bDontRip &= !bDontRip;
}
}
//===========================================================================
//
// AbsorbDamage
//
//===========================================================================
override void ModifyDamage(int damage, Name damageType, out int newdamage, bool passive)
{
if (passive && damage > 0)
{
newdamage = max(1, ApplyDamageFactors(GetClass(), damageType, damage, damage / 4));
if (Owner != null && newdamage < damage) Owner.A_PlaySound(ActiveSound, CHAN_AUTO, 1.0, false, ATTN_NONE);
}
}
}
//===========================================================================
//
// Drain
//
//===========================================================================
class PowerDrain : Powerup
{
Default
{
Powerup.Duration -60;
}
override void InitEffect()
{
Super.InitEffect();
if (Owner!= null && Owner.player != null)
{
// Give the player the power to drain life from opponents when he damages them.
Owner.player.cheats |= CF_DRAIN;
}
}
override void EndEffect()
{
Super.EndEffect();
// Nothing to do if there's no owner.
if (Owner!= null && Owner.player != null)
{
// Take away the drain power.
Owner.player.cheats &= ~CF_DRAIN;
}
}
}
//===========================================================================
//
// Regeneration
//
//===========================================================================
class PowerRegeneration : Powerup
{
Default
{
Powerup.Duration -120;
Powerup.Strength 5;
}
override void DoEffect()
{
Super.DoEffect();
if (Owner != null && Owner.health > 0 && (level.time & 31) == 0)
{
if (Owner.GiveBody(int(Strength)))
{
Owner.A_PlaySound("*regenerate", CHAN_ITEM);
}
}
}
}
//===========================================================================
//
// HighJump
//
//===========================================================================
class PowerHighJump : Powerup
{
override void InitEffect()
{
Super.InitEffect();
if (Owner!= null && Owner.player != null)
{
// Give the player the power to jump much higher.
Owner.player.cheats |= CF_HIGHJUMP;
}
}
override void EndEffect()
{
Super.EndEffect();
// Nothing to do if there's no owner.
if (Owner!= null && Owner.player != null)
{
// Take away the high jump power.
Owner.player.cheats &= ~CF_HIGHJUMP;
}
}
}
//===========================================================================
//
// DoubleFiringSpeed
//
//===========================================================================
class PowerDoubleFiringSpeed : Powerup
{
override void InitEffect()
{
Super.InitEffect();
if (Owner!= null && Owner.player != null)
{
// Give the player the power to shoot twice as fast.
Owner.player.cheats |= CF_DOUBLEFIRINGSPEED;
}
}
override void EndEffect()
{
Super.EndEffect();
// Nothing to do if there's no owner.
if (Owner!= null && Owner.player != null)
{
// Take away the shooting twice as fast power.
Owner.player.cheats &= ~CF_DOUBLEFIRINGSPEED;
}
}
}
//===========================================================================
//
// InfiniteAmmo
//
//===========================================================================
class PowerInfiniteAmmo : Powerup
{
Default
{
Powerup.Duration -30;
}
override void InitEffect()
{
Super.InitEffect();
if (Owner!= null && Owner.player != null)
{
// Give the player infinite ammo
Owner.player.cheats |= CF_INFINITEAMMO;
}
}
override void EndEffect()
{
Super.EndEffect();
// Nothing to do if there's no owner.
if (Owner!= null && Owner.player != null)
{
// Take away the limitless ammo
Owner.player.cheats &= ~CF_INFINITEAMMO;
}
}
}
//===========================================================================
//
// PowerMorph
//
//===========================================================================
class PowerMorph : Powerup native
{
native Class<PlayerPawn> PlayerClass;
native Class<Actor> MorphFlash, UnMorphFlash;
native int MorphStyle;
native PlayerInfo MorphedPlayer;
Default
{
Powerup.Duration -40;
}
//===========================================================================
//
// InitEffect
//
//===========================================================================
override void InitEffect()
{
Super.InitEffect();
if (Owner != null && Owner.player != null && PlayerClass != null)
{
let realplayer = Owner.player; // Remember the identity of the player
if (realplayer.MorphPlayer(realplayer, PlayerClass, 0x7fffffff/*INDEFINITELY*/, MorphStyle, MorphFlash, UnMorphFlash))
{
Owner = realplayer.mo; // Replace the new owner in our owner; safe because we are not attached to anything yet
bCreateCopyMoved = true; // Let the caller know the "real" owner has changed (to the morphed actor)
MorphedPlayer = realplayer; // Store the player identity (morphing clears the unmorphed actor's "player" field)
}
else // morph failed - give the caller an opportunity to fail the pickup completely
{
bInitEffectFailed = true; // Let the caller know that the activation failed (can fail the pickup if appropriate)
}
}
}
//===========================================================================
//
// EndEffect
//
//===========================================================================
override void EndEffect()
{
Super.EndEffect();
// Abort if owner already destroyed or unmorphed
if (Owner == null || MorphedPlayer == null || Owner.alternative == null)
{
return;
}
// Abort if owner is dead; their Die() method will
// take care of any required unmorphing on death.
if (MorphedPlayer.health <= 0)
{
return;
}
int savedMorphTics = MorphedPlayer.morphTics;
MorphedPlayer.UndoPlayerMorph (MorphedPlayer, 0, !!(MorphedPlayer.MorphStyle & MRF_UNDOALWAYS));
// Abort if unmorph failed; in that case,
// set the usual retry timer and return.
if (MorphedPlayer != null && MorphedPlayer.morphTics)
{
// Transfer retry timeout
// to the powerup's timer.
EffectTics = MorphedPlayer.morphTics;
// Reload negative morph tics;
// use actual value; it may
// be in use for animation.
MorphedPlayer.morphTics = savedMorphTics;
// Try again some time later
return;
}
// Unmorph suceeded
MorphedPlayer = null;
}
}