mirror of
https://github.com/ZDoom/gzdoom.git
synced 2024-11-26 22:11:43 +00:00
- scriptified the methods of APowerMorph.
- made some changes to PowerMorph to better deal with recursive calls from UndoPlayerMorph. The flag hackery was only needed because the 'alternative' pointers were cleared far too late.
This commit is contained in:
parent
2d2963ead4
commit
66cc68606f
5 changed files with 88 additions and 86 deletions
|
@ -1759,7 +1759,6 @@ DEFINE_FIELD(APowerMorph, MorphFlash)
|
|||
DEFINE_FIELD(APowerMorph, UnMorphFlash)
|
||||
DEFINE_FIELD(APowerMorph, MorphStyle)
|
||||
DEFINE_FIELD(APowerMorph, MorphedPlayer)
|
||||
DEFINE_FIELD(APowerMorph, bInUndoMorph)
|
||||
|
||||
//===========================================================================
|
||||
//
|
||||
|
@ -1777,77 +1776,3 @@ void APowerMorph::Serialize(FSerializer &arc)
|
|||
("morphedplayer", MorphedPlayer);
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
//
|
||||
// APowerMorph :: InitEffect
|
||||
//
|
||||
//===========================================================================
|
||||
|
||||
void APowerMorph::InitEffect( )
|
||||
{
|
||||
Super::InitEffect();
|
||||
|
||||
if (Owner != nullptr && Owner->player != nullptr && PlayerClass != nullptr)
|
||||
{
|
||||
player_t *realplayer = Owner->player; // Remember the identity of the player
|
||||
if (P_MorphPlayer(realplayer, realplayer, PlayerClass, INT_MAX/*INDEFINITELY*/, MorphStyle, MorphFlash, UnMorphFlash))
|
||||
{
|
||||
Owner = realplayer->mo; // Replace the new owner in our owner; safe because we are not attached to anything yet
|
||||
ItemFlags |= IF_CREATECOPYMOVED; // 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
|
||||
{
|
||||
ItemFlags |= IF_INITEFFECTFAILED; // Let the caller know that the activation failed (can fail the pickup if appropriate)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
//
|
||||
// APowerMorph :: EndEffect
|
||||
//
|
||||
//===========================================================================
|
||||
|
||||
void APowerMorph::EndEffect( )
|
||||
{
|
||||
Super::EndEffect();
|
||||
|
||||
// Abort if owner already destroyed or unmorphed
|
||||
if (Owner == nullptr || MorphedPlayer == nullptr)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// Abort if owner is dead; their Die() method will
|
||||
// take care of any required unmorphing on death.
|
||||
if (MorphedPlayer->health <= 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// Unmorph if possible
|
||||
if (!bInUndoMorph)
|
||||
{
|
||||
int savedMorphTics = MorphedPlayer->morphTics;
|
||||
P_UndoPlayerMorph (MorphedPlayer, MorphedPlayer, 0, !!(MorphedPlayer->MorphStyle & MORPH_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;
|
||||
}
|
||||
|
||||
|
|
|
@ -228,18 +228,12 @@ class APowerMorph : public APowerup
|
|||
public:
|
||||
|
||||
virtual void Serialize(FSerializer &arc) override;
|
||||
void SetNoCallUndoMorph() { bInUndoMorph = true; }
|
||||
|
||||
// Variables
|
||||
PClassPlayerPawn *PlayerClass;
|
||||
PClassActor *MorphFlash, *UnMorphFlash;
|
||||
int MorphStyle;
|
||||
player_t *MorphedPlayer;
|
||||
bool bInUndoMorph; // Because P_UndoPlayerMorph() can call EndEffect recursively
|
||||
|
||||
protected:
|
||||
virtual void InitEffect () override;
|
||||
virtual void EndEffect () override;
|
||||
};
|
||||
|
||||
#endif //__A_ARTIFACTS_H__
|
||||
|
|
|
@ -154,6 +154,18 @@ bool P_MorphPlayer (player_t *activator, player_t *p, PClassPlayerPawn *spawntyp
|
|||
return true;
|
||||
}
|
||||
|
||||
DEFINE_ACTION_FUNCTION(_PlayerInfo, MorphPlayer)
|
||||
{
|
||||
PARAM_SELF_STRUCT_PROLOGUE(player_t);
|
||||
PARAM_POINTER(victim, player_t);
|
||||
PARAM_CLASS(spawntype, APlayerPawn);
|
||||
PARAM_INT(duration);
|
||||
PARAM_INT(style);
|
||||
PARAM_CLASS_DEF(enter_flash, AActor);
|
||||
PARAM_CLASS_DEF(exit_flash, AActor);
|
||||
ACTION_RETURN_BOOL(P_MorphPlayer(self, victim, spawntype, duration, style, enter_flash, exit_flash));
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
//
|
||||
// FUNC P_UndoPlayerMorph
|
||||
|
@ -204,14 +216,15 @@ bool P_UndoPlayerMorph (player_t *activator, player_t *player, int unmorphflag,
|
|||
mo->target = pmo->target;
|
||||
mo->tracer = pmo->tracer;
|
||||
pmo->player = nullptr;
|
||||
mo->alternative = pmo->alternative = nullptr;
|
||||
|
||||
// Remove the morph power if the morph is being undone prematurely.
|
||||
auto pmtype = PClass::FindActor("PowerMorph");
|
||||
for (AInventory *item = pmo->Inventory, *next = nullptr; item != nullptr; item = next)
|
||||
{
|
||||
next = item->Inventory;
|
||||
if (item->IsKindOf(RUNTIME_CLASS(APowerMorph)))
|
||||
if (item->IsKindOf(pmtype))
|
||||
{
|
||||
static_cast<APowerMorph *>(item)->SetNoCallUndoMorph();
|
||||
item->Destroy();
|
||||
}
|
||||
}
|
||||
|
@ -348,8 +361,6 @@ bool P_UndoPlayerMorph (player_t *activator, player_t *player, int unmorphflag,
|
|||
beastweap->Destroy ();
|
||||
}
|
||||
}
|
||||
mo->alternative = nullptr;
|
||||
pmo->alternative = nullptr;
|
||||
pmo->Destroy ();
|
||||
// Restore playerclass armor to its normal amount.
|
||||
AHexenArmor *hxarmor = mo->FindInventory<AHexenArmor>();
|
||||
|
|
|
@ -251,6 +251,7 @@ FWeaponSlots weapons;
|
|||
*/
|
||||
|
||||
|
||||
native bool MorphPlayer(playerinfo p, Class<PlayerPawn> spawntype, int duration, int style, Class<Actor> enter_flash = null, Class<Actor> exit_flash = null);
|
||||
native bool UndoPlayerMorph(playerinfo player, int unmorphflag = 0, bool force = false);
|
||||
native bool PoisonPlayer(Actor poisoner, Actor source, int poison);
|
||||
native void PoisonDamage(Actor source, int damage, bool playPainSound);
|
||||
|
|
|
@ -430,11 +430,82 @@ class PowerMorph : Powerup native
|
|||
native Class<Actor> MorphFlash, UnMorphFlash;
|
||||
native int MorphStyle;
|
||||
native PlayerInfo MorphedPlayer;
|
||||
native bool bInUndoMorph;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue