mirror of
https://github.com/ZDoom/qzdoom.git
synced 2024-11-24 13:01:47 +00:00
- scriptified the rest of the morph code.
This commit is contained in:
parent
ac1bffc51b
commit
bd84a60663
8 changed files with 237 additions and 277 deletions
|
@ -1249,7 +1249,7 @@ void G_PlayerFinishLevel (int player, EFinishLevelType mode, int flags)
|
|||
|
||||
if (p->morphTics != 0)
|
||||
{ // Undo morph
|
||||
P_UndoPlayerMorph (p, p, 0, true);
|
||||
P_UnmorphActor(p->mo, p->mo, 0, true);
|
||||
}
|
||||
|
||||
// Strip all current powers, unless moving in a hub and the power is okay to keep.
|
||||
|
|
|
@ -1,9 +1,6 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// Copyright 1994-1996 Raven Software
|
||||
// Copyright 1999-2016 Randy Heit
|
||||
// Copyright 2002-2016 Christoph Oelckers
|
||||
// Copyright 2005-2008 Martin Howe
|
||||
// Copyright 2018 Christoph Oelckers
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
|
@ -52,12 +49,11 @@ bool P_MorphActor(AActor *activator, AActor *victim, PClassActor *ptype, PClassA
|
|||
return false;
|
||||
}
|
||||
|
||||
bool P_UndoPlayerMorph(player_t *activator, player_t *player, int unmorphflag, bool force)
|
||||
bool P_UnmorphActor(AActor *activator, AActor *morphed, int flags, bool force)
|
||||
{
|
||||
if (!player->mo) return false;
|
||||
IFVIRTUALPTR(player->mo, APlayerPawn, UndoPlayerMorph)
|
||||
IFVIRTUALPTR(morphed, AActor, UnMorph)
|
||||
{
|
||||
VMValue params[] = { player->mo, activator, unmorphflag, force };
|
||||
VMValue params[] = { morphed, activator, flags, force };
|
||||
int retval;
|
||||
VMReturn ret(&retval);
|
||||
VMCall(func, params, countof(params), &ret, 1);
|
||||
|
@ -66,186 +62,4 @@ bool P_UndoPlayerMorph(player_t *activator, player_t *player, int unmorphflag, b
|
|||
return false;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
//
|
||||
// FUNC P_UndoMonsterMorph
|
||||
//
|
||||
// Returns true if the monster unmorphs.
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
bool P_UndoMonsterMorph (AMorphedMonster *beast, bool force)
|
||||
{
|
||||
AActor *actor;
|
||||
|
||||
if (beast->UnmorphTime == 0 ||
|
||||
beast->UnmorphedMe == NULL ||
|
||||
beast->flags3 & MF3_STAYMORPHED ||
|
||||
beast->UnmorphedMe->flags3 & MF3_STAYMORPHED)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
actor = beast->UnmorphedMe;
|
||||
actor->SetOrigin (beast->Pos(), false);
|
||||
actor->flags |= MF_SOLID;
|
||||
beast->flags &= ~MF_SOLID;
|
||||
ActorFlags6 beastflags6 = beast->flags6;
|
||||
beast->flags6 &= ~MF6_TOUCHY;
|
||||
if (!force && !P_TestMobjLocation (actor))
|
||||
{ // Didn't fit
|
||||
actor->flags &= ~MF_SOLID;
|
||||
beast->flags |= MF_SOLID;
|
||||
beast->flags6 = beastflags6;
|
||||
beast->UnmorphTime = level.time + 5*TICRATE; // Next try in 5 seconds
|
||||
return false;
|
||||
}
|
||||
actor->Angles.Yaw = beast->Angles.Yaw;
|
||||
actor->target = beast->target;
|
||||
actor->FriendPlayer = beast->FriendPlayer;
|
||||
actor->flags = beast->FlagsSave & ~MF_JUSTHIT;
|
||||
actor->flags = (actor->flags & ~(MF_FRIENDLY|MF_SHADOW)) | (beast->flags & (MF_FRIENDLY|MF_SHADOW));
|
||||
actor->flags3 = (actor->flags3 & ~(MF3_NOSIGHTCHECK|MF3_HUNTPLAYERS|MF3_GHOST))
|
||||
| (beast->flags3 & (MF3_NOSIGHTCHECK|MF3_HUNTPLAYERS|MF3_GHOST));
|
||||
actor->flags4 = (actor->flags4 & ~MF4_NOHATEPLAYERS) | (beast->flags4 & MF4_NOHATEPLAYERS);
|
||||
if (!(beast->FlagsSave & MF_JUSTHIT))
|
||||
actor->renderflags &= ~RF_INVISIBLE;
|
||||
actor->health = actor->SpawnHealth();
|
||||
actor->Vel = beast->Vel;
|
||||
actor->tid = beast->tid;
|
||||
actor->special = beast->special;
|
||||
actor->Score = beast->Score;
|
||||
memcpy (actor->args, beast->args, sizeof(actor->args));
|
||||
actor->AddToHash ();
|
||||
beast->UnmorphedMe = NULL;
|
||||
DObject::StaticPointerSubstitution (beast, actor);
|
||||
PClassActor *exit_flash = beast->MorphExitFlash;
|
||||
beast->Destroy ();
|
||||
AActor *eflash = Spawn(exit_flash, beast->PosPlusZ(TELEFOGHEIGHT), ALLOW_REPLACE);
|
||||
if (eflash)
|
||||
eflash->target = actor;
|
||||
return true;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
//
|
||||
// FUNC P_MorphedDeath
|
||||
//
|
||||
// Unmorphs the actor if possible.
|
||||
// Returns the unmorphed actor, the style with which they were morphed and the
|
||||
// health (of the AActor, not the player_t) they last had before unmorphing.
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
bool P_MorphedDeath(AActor *actor, AActor **morphed, int *morphedstyle, int *morphedhealth)
|
||||
{
|
||||
// May be a morphed player
|
||||
if ((actor->player) &&
|
||||
(actor->player->morphTics) &&
|
||||
(actor->player->MorphStyle & MORPH_UNDOBYDEATH) &&
|
||||
(actor->player->mo) &&
|
||||
(actor->player->mo->alternative))
|
||||
{
|
||||
AActor *realme = actor->player->mo->alternative;
|
||||
int realstyle = actor->player->MorphStyle;
|
||||
int realhealth = actor->health;
|
||||
if (P_UndoPlayerMorph(actor->player, actor->player, 0, !!(actor->player->MorphStyle & MORPH_UNDOBYDEATHFORCED)))
|
||||
{
|
||||
*morphed = realme;
|
||||
*morphedstyle = realstyle;
|
||||
*morphedhealth = realhealth;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// May be a morphed monster
|
||||
if (actor->GetClass()->IsDescendantOf(RUNTIME_CLASS(AMorphedMonster)))
|
||||
{
|
||||
AMorphedMonster *fakeme = static_cast<AMorphedMonster *>(actor);
|
||||
AActor *realme = fakeme->UnmorphedMe;
|
||||
if (realme != NULL)
|
||||
{
|
||||
if ((fakeme->UnmorphTime) &&
|
||||
(fakeme->MorphStyle & MORPH_UNDOBYDEATH))
|
||||
{
|
||||
int realstyle = fakeme->MorphStyle;
|
||||
int realhealth = fakeme->health;
|
||||
if (P_UndoMonsterMorph(fakeme, !!(fakeme->MorphStyle & MORPH_UNDOBYDEATHFORCED)))
|
||||
{
|
||||
*morphed = realme;
|
||||
*morphedstyle = realstyle;
|
||||
*morphedhealth = realhealth;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
if (realme->flags4 & MF4_BOSSDEATH)
|
||||
{
|
||||
realme->health = 0; // make sure that A_BossDeath considers it dead.
|
||||
A_BossDeath(realme);
|
||||
}
|
||||
}
|
||||
fakeme->flags3 |= MF3_STAYMORPHED; // moved here from AMorphedMonster::Die()
|
||||
return false;
|
||||
}
|
||||
|
||||
// Not a morphed player or monster
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
// Morphed Monster (you must subclass this to do something useful) ---------
|
||||
|
||||
IMPLEMENT_CLASS(AMorphedMonster, false, true)
|
||||
|
||||
IMPLEMENT_POINTERS_START(AMorphedMonster)
|
||||
IMPLEMENT_POINTER(UnmorphedMe)
|
||||
IMPLEMENT_POINTERS_END
|
||||
|
||||
DEFINE_FIELD(AMorphedMonster, UnmorphedMe)
|
||||
DEFINE_FIELD(AMorphedMonster, UnmorphTime)
|
||||
DEFINE_FIELD(AMorphedMonster, MorphStyle)
|
||||
DEFINE_FIELD(AMorphedMonster, MorphExitFlash)
|
||||
|
||||
void AMorphedMonster::Serialize(FSerializer &arc)
|
||||
{
|
||||
Super::Serialize (arc);
|
||||
arc("unmorphedme", UnmorphedMe)
|
||||
("unmorphtime", UnmorphTime)
|
||||
("morphstyle", MorphStyle)
|
||||
("morphexitflash", MorphExitFlash)
|
||||
("flagsave", FlagsSave);
|
||||
}
|
||||
|
||||
void AMorphedMonster::OnDestroy ()
|
||||
{
|
||||
if (UnmorphedMe != NULL)
|
||||
{
|
||||
UnmorphedMe->Destroy ();
|
||||
}
|
||||
Super::OnDestroy();
|
||||
}
|
||||
|
||||
void AMorphedMonster::Die (AActor *source, AActor *inflictor, int dmgflags, FName MeansOfDeath)
|
||||
{
|
||||
// Dead things don't unmorph
|
||||
// flags3 |= MF3_STAYMORPHED;
|
||||
// [MH]
|
||||
// But they can now, so that line above has been
|
||||
// moved into P_MorphedDeath() and is now set by
|
||||
// that function if and only if it is needed.
|
||||
Super::Die (source, inflictor, dmgflags, MeansOfDeath);
|
||||
if (UnmorphedMe != NULL && (UnmorphedMe->flags & MF_UNMORPHED))
|
||||
{
|
||||
UnmorphedMe->health = health;
|
||||
UnmorphedMe->CallDie (source, inflictor, dmgflags, MeansOfDeath);
|
||||
}
|
||||
}
|
||||
|
||||
void AMorphedMonster::Tick ()
|
||||
{
|
||||
if (UnmorphTime > level.time || !P_UndoMonsterMorph(this))
|
||||
{
|
||||
Super::Tick();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -33,12 +33,8 @@ enum
|
|||
class PClass;
|
||||
class AActor;
|
||||
class player_t;
|
||||
class AMorphedMonster;
|
||||
|
||||
bool P_MorphActor(AActor *activator, AActor *victim, PClassActor *ptype, PClassActor *mtype, int duration, int style, PClassActor *enter_flash, PClassActor *exit_flash);
|
||||
|
||||
bool P_UndoPlayerMorph (player_t *activator, player_t *player, int unmorphflag = 0, bool force = false);
|
||||
bool P_UndoMonsterMorph (AMorphedMonster *beast, bool force = false);
|
||||
bool P_MorphedDeath(AActor *actor, AActor **morphed, int *morphedstyle, int *morphedhealth);
|
||||
bool P_UnmorphActor(AActor *activator, AActor *morphed, int flags = 0, bool force = false);
|
||||
|
||||
#endif //__A_MORPH__
|
||||
|
|
|
@ -154,21 +154,4 @@ private:
|
|||
DEarthquake ();
|
||||
};
|
||||
|
||||
class AMorphedMonster : public AActor
|
||||
{
|
||||
DECLARE_CLASS (AMorphedMonster, AActor)
|
||||
HAS_OBJECT_POINTERS
|
||||
public:
|
||||
void Tick ();
|
||||
|
||||
void Serialize(FSerializer &arc);
|
||||
void Die (AActor *source, AActor *inflictor, int dmgflags, FName MeansOfDeath) override;
|
||||
void OnDestroy() override;
|
||||
|
||||
TObjPtr<AActor*> UnmorphedMe;
|
||||
int UnmorphTime, MorphStyle;
|
||||
PClassActor *MorphExitFlash;
|
||||
ActorFlags FlagsSave;
|
||||
};
|
||||
|
||||
#endif //__A_SHAREDGLOBAL_H__
|
||||
|
|
|
@ -10331,24 +10331,7 @@ scriptwait:
|
|||
|
||||
if (tag == 0)
|
||||
{
|
||||
if (activator->player)
|
||||
{
|
||||
if (P_UndoPlayerMorph(activator->player, activator->player, 0, force))
|
||||
{
|
||||
changes++;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (activator->GetClass()->IsDescendantOf(RUNTIME_CLASS(AMorphedMonster)))
|
||||
{
|
||||
AMorphedMonster *morphed_actor = barrier_cast<AMorphedMonster *>(activator);
|
||||
if (P_UndoMonsterMorph(morphed_actor, force))
|
||||
{
|
||||
changes++;
|
||||
}
|
||||
}
|
||||
}
|
||||
changes += P_UnmorphActor(activator, activator, 0, force);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -10357,24 +10340,7 @@ scriptwait:
|
|||
|
||||
while ( (actor = iterator.Next ()) )
|
||||
{
|
||||
if (actor->player)
|
||||
{
|
||||
if (P_UndoPlayerMorph(activator->player, actor->player, 0, force))
|
||||
{
|
||||
changes++;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (actor->GetClass()->IsDescendantOf(RUNTIME_CLASS(AMorphedMonster)))
|
||||
{
|
||||
AMorphedMonster *morphed_actor = static_cast<AMorphedMonster *>(actor);
|
||||
if (P_UndoMonsterMorph(morphed_actor, force))
|
||||
{
|
||||
changes++;
|
||||
}
|
||||
}
|
||||
}
|
||||
changes += P_UnmorphActor(activator, actor, 0, force);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -289,39 +289,41 @@ void AActor::Die (AActor *source, AActor *inflictor, int dmgflags, FName MeansOf
|
|||
{
|
||||
// Handle possible unmorph on death
|
||||
bool wasgibbed = (health < GetGibHealth());
|
||||
AActor *realthis = NULL;
|
||||
int realstyle = 0;
|
||||
int realhealth = 0;
|
||||
if (P_MorphedDeath(this, &realthis, &realstyle, &realhealth))
|
||||
|
||||
{
|
||||
if (!(realstyle & MORPH_UNDOBYDEATHSAVES))
|
||||
IFVIRTUAL(AActor, MorphedDeath)
|
||||
{
|
||||
if (wasgibbed)
|
||||
AActor *realthis = NULL;
|
||||
int realstyle = 0;
|
||||
int realhealth = 0;
|
||||
|
||||
VMValue params[] = { this };
|
||||
VMReturn returns[3];
|
||||
returns[0].PointerAt((void**)&realthis);
|
||||
returns[1].IntAt(&realstyle);
|
||||
returns[2].IntAt(&realhealth);
|
||||
VMCall(func, params, 1, returns, 3);
|
||||
|
||||
if (realthis && !(realstyle & MORPH_UNDOBYDEATHSAVES))
|
||||
{
|
||||
int realgibhealth = realthis->GetGibHealth();
|
||||
if (realthis->health >= realgibhealth)
|
||||
if (wasgibbed)
|
||||
{
|
||||
realthis->health = realgibhealth -1; // if morphed was gibbed, so must original be (where allowed)l
|
||||
int realgibhealth = realthis->GetGibHealth();
|
||||
if (realthis->health >= realgibhealth)
|
||||
{
|
||||
realthis->health = realgibhealth - 1; // if morphed was gibbed, so must original be (where allowed)l
|
||||
}
|
||||
}
|
||||
realthis->CallDie(source, inflictor, dmgflags, MeansOfDeath);
|
||||
}
|
||||
realthis->CallDie(source, inflictor, dmgflags, MeansOfDeath);
|
||||
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// [SO] 9/2/02 -- It's rather funny to see an exploded player body with the invuln sparkle active :)
|
||||
effects &= ~FX_RESPAWNINVUL;
|
||||
//flags &= ~MF_INVINCIBLE;
|
||||
|
||||
if (debugfile && this->player)
|
||||
{
|
||||
static int dieticks[MAXPLAYERS]; // [ZzZombo] not used? Except if for peeking in debugger...
|
||||
int pnum = int(this->player-players);
|
||||
dieticks[pnum] = gametic;
|
||||
fprintf(debugfile, "died (%d) on tic %d (%s)\n", pnum, gametic,
|
||||
this->player->cheats&CF_PREDICTING ? "predicting" : "real");
|
||||
}
|
||||
|
||||
// [RH] Notify this actor's items.
|
||||
for (AInventory *item = Inventory; item != NULL; )
|
||||
{
|
||||
|
|
|
@ -695,7 +695,7 @@ bool player_t::Resurrect()
|
|||
|
||||
if (morphTics)
|
||||
{
|
||||
P_UndoPlayerMorph(this, this);
|
||||
P_UnmorphActor(mo, mo);
|
||||
}
|
||||
|
||||
// player is now alive.
|
||||
|
|
|
@ -1,5 +1,34 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// Copyright 1994-1996 Raven Software
|
||||
// Copyright 1999-2016 Randy Heit
|
||||
// Copyright 2002-2018 Christoph Oelckers
|
||||
// Copyright 2005-2008 Martin Howe
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see http://www.gnu.org/licenses/
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
|
||||
extend class Actor
|
||||
{
|
||||
virtual Actor, int, int MorphedDeath()
|
||||
{
|
||||
return null, 0, 0;
|
||||
}
|
||||
|
||||
|
||||
//===========================================================================
|
||||
//
|
||||
// Main entry point
|
||||
|
@ -10,7 +39,7 @@ extend class Actor
|
|||
{
|
||||
if (player != null && player.mo != null && playerclass != null)
|
||||
{
|
||||
return player.mo.MorphPlayer(activator.player, playerclass, duration, style, morphflash, unmorphflash);
|
||||
return player.mo.MorphPlayer(activator? activator.player : null, playerclass, duration, style, morphflash, unmorphflash);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -38,7 +67,28 @@ extend class Actor
|
|||
return false;
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
//
|
||||
// Main entry point
|
||||
//
|
||||
//===========================================================================
|
||||
|
||||
bool UnMorph(Actor activator, int flags, bool force)
|
||||
{
|
||||
if (player)
|
||||
{
|
||||
return player.mo.UndoPlayerMorph(activator? activator.player : null, flags, force);
|
||||
}
|
||||
else
|
||||
{
|
||||
let morphed = MorphedMonster(self);
|
||||
if (morphed)
|
||||
return morphed.UndoMonsterMorph(force);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
//
|
||||
// FUNC P_MorphMonster
|
||||
|
@ -71,7 +121,7 @@ extend class Actor
|
|||
morphed.UnmorphTime = level.time + ((duration) ? duration : DEFMORPHTICS) + random[morphmonst]();
|
||||
morphed.MorphStyle = style;
|
||||
morphed.MorphExitFlash = (exit_flash) ? exit_flash : (class<Actor>)("TeleportFog");
|
||||
//morphed.FlagsSave = bSolid * 2 + bShootable * 4 + bInvisible * 0x40; // The factors are for savegame compatibility
|
||||
morphed.FlagsSave = bSolid * 2 + bShootable * 4 + bInvisible * 0x40; // The factors are for savegame compatibility
|
||||
|
||||
morphed.special = special;
|
||||
morphed.args[0] = args[0];
|
||||
|
@ -501,9 +551,38 @@ extend class PlayerPawn
|
|||
return true;
|
||||
}
|
||||
|
||||
|
||||
//===========================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//===========================================================================
|
||||
|
||||
override Actor, int, int MorphedDeath()
|
||||
{
|
||||
// Voodoo dolls should not unmorph the real player here.
|
||||
if ((player.mo == self) &&
|
||||
(player.morphTics) &&
|
||||
(player.MorphStyle & MRF_UNDOBYDEATH) &&
|
||||
(alternative))
|
||||
{
|
||||
Actor realme = alternative;
|
||||
int realstyle = player.MorphStyle;
|
||||
int realhealth = health;
|
||||
if (UndoPlayerMorph(player, 0, !!(player.MorphStyle & MRF_UNDOBYDEATHFORCED)))
|
||||
{
|
||||
return realme, realstyle, realhealth;
|
||||
}
|
||||
}
|
||||
return null, 0, 0;
|
||||
}
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//===========================================================================
|
||||
|
||||
class MorphProjectile : Actor
|
||||
{
|
||||
|
||||
|
@ -536,11 +615,18 @@ class MorphProjectile : Actor
|
|||
|
||||
}
|
||||
|
||||
class MorphedMonster : Actor native
|
||||
//===========================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//===========================================================================
|
||||
|
||||
class MorphedMonster : Actor
|
||||
{
|
||||
native Actor UnmorphedMe;
|
||||
native int UnmorphTime, MorphStyle;
|
||||
native Class<Actor> MorphExitFlash;
|
||||
Actor UnmorphedMe;
|
||||
int UnmorphTime, MorphStyle;
|
||||
Class<Actor> MorphExitFlash;
|
||||
int FlagsSave;
|
||||
|
||||
Default
|
||||
{
|
||||
|
@ -548,5 +634,118 @@ class MorphedMonster : Actor native
|
|||
-COUNTKILL
|
||||
+FLOORCLIP
|
||||
}
|
||||
|
||||
override void OnDestroy ()
|
||||
{
|
||||
if (UnmorphedMe != NULL)
|
||||
{
|
||||
UnmorphedMe.Destroy ();
|
||||
}
|
||||
Super.OnDestroy();
|
||||
}
|
||||
|
||||
override void Die (Actor source, Actor inflictor, int dmgflags, Name MeansOfDeath)
|
||||
{
|
||||
Super.Die (source, inflictor, dmgflags, MeansOfDeath);
|
||||
if (UnmorphedMe != NULL && UnmorphedMe.bUnmorphed)
|
||||
{
|
||||
UnmorphedMe.health = health;
|
||||
UnmorphedMe.Die (source, inflictor, dmgflags, MeansOfDeath);
|
||||
}
|
||||
}
|
||||
|
||||
override void Tick ()
|
||||
{
|
||||
if (UnmorphTime > level.time || !UndoMonsterMorph())
|
||||
{
|
||||
Super.Tick();
|
||||
}
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
//
|
||||
// FUNC P_UndoMonsterMorph
|
||||
//
|
||||
// Returns true if the monster unmorphs.
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
virtual bool UndoMonsterMorph(bool force = false)
|
||||
{
|
||||
if (UnmorphTime == 0 || UnmorphedMe == NULL || bStayMorphed || UnmorphedMe.bStayMorphed)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
let unmorphed = UnmorphedMe;
|
||||
unmorphed.SetOrigin (Pos, false);
|
||||
unmorphed.bSolid = true;
|
||||
bSolid = false;
|
||||
bool save = bTouchy;
|
||||
bTouchy = false;
|
||||
if (!force && !unmorphed.TestMobjLocation ())
|
||||
{ // Didn't fit
|
||||
unmorphed.bSolid = false;
|
||||
bSolid = true;
|
||||
bTouchy = save;
|
||||
UnmorphTime = level.time + 5*TICRATE; // Next try in 5 seconds
|
||||
return false;
|
||||
}
|
||||
unmorphed.Angle = Angle;
|
||||
unmorphed.target = target;
|
||||
unmorphed.bShadow = bShadow;
|
||||
unmorphed.bGhost = bGhost;
|
||||
unmorphed.bSolid = !!(flagssave & 2);
|
||||
unmorphed.bShootable = !!(flagssave & 4);
|
||||
unmorphed.bInvisible = !!(flagssave & 0x40);
|
||||
unmorphed.health = unmorphed.SpawnHealth();
|
||||
unmorphed.Vel = Vel;
|
||||
unmorphed.ChangeTid(tid);
|
||||
unmorphed.special = special;
|
||||
unmorphed.Score = Score;
|
||||
unmorphed.args[0] = args[0];
|
||||
unmorphed.args[1] = args[1];
|
||||
unmorphed.args[2] = args[2];
|
||||
unmorphed.args[3] = args[3];
|
||||
unmorphed.args[4] = args[4];
|
||||
unmorphed.CopyFriendliness (self, true);
|
||||
UnmorphedMe = NULL;
|
||||
Substitute(unmorphed);
|
||||
Destroy ();
|
||||
let eflash = Spawn(MorphExitFlash, Pos + (0, 0, gameinfo.TELEFOGHEIGHT), ALLOW_REPLACE);
|
||||
if (eflash)
|
||||
eflash.target = unmorphed;
|
||||
return true;
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//===========================================================================
|
||||
|
||||
override Actor, int, int MorphedDeath()
|
||||
{
|
||||
let realme = UnmorphedMe;
|
||||
if (realme != NULL)
|
||||
{
|
||||
if ((UnmorphTime) &&
|
||||
(MorphStyle & MRF_UNDOBYDEATH))
|
||||
{
|
||||
int realstyle = MorphStyle;
|
||||
int realhealth = health;
|
||||
if (UndoMonsterMorph(!!(MorphStyle & MRF_UNDOBYDEATHFORCED)))
|
||||
{
|
||||
return realme, realstyle, realhealth;
|
||||
}
|
||||
}
|
||||
if (realme.bBossDeath)
|
||||
{
|
||||
realme.health = 0; // make sure that A_BossDeath considers it dead.
|
||||
realme.A_BossDeath();
|
||||
}
|
||||
}
|
||||
return null, 0, 0;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue