mirror of
https://github.com/ZDoom/gzdoom-gles.git
synced 2024-11-16 09:31:14 +00:00
- scriptified the rest of the morph code.
This commit is contained in:
parent
5f5410e35f
commit
9e6279ed5b
8 changed files with 237 additions and 277 deletions
|
@ -1272,7 +1272,7 @@ void G_PlayerFinishLevel (int player, EFinishLevelType mode, int flags)
|
||||||
|
|
||||||
if (p->morphTics != 0)
|
if (p->morphTics != 0)
|
||||||
{ // Undo morph
|
{ // 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.
|
// 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 2018 Christoph Oelckers
|
||||||
// Copyright 1999-2016 Randy Heit
|
|
||||||
// Copyright 2002-2016 Christoph Oelckers
|
|
||||||
// Copyright 2005-2008 Martin Howe
|
|
||||||
//
|
//
|
||||||
// This program is free software: you can redistribute it and/or modify
|
// 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
|
// it under the terms of the GNU General Public License as published by
|
||||||
|
@ -57,12 +54,11 @@ bool P_MorphActor(AActor *activator, AActor *victim, PClassActor *ptype, PClassA
|
||||||
return false;
|
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(morphed, AActor, UnMorph)
|
||||||
IFVIRTUALPTR(player->mo, APlayerPawn, UndoPlayerMorph)
|
|
||||||
{
|
{
|
||||||
VMValue params[] = { player->mo, activator, unmorphflag, force };
|
VMValue params[] = { morphed, activator, flags, force };
|
||||||
int retval;
|
int retval;
|
||||||
VMReturn ret(&retval);
|
VMReturn ret(&retval);
|
||||||
VMCall(func, params, countof(params), &ret, 1);
|
VMCall(func, params, countof(params), &ret, 1);
|
||||||
|
@ -71,186 +67,4 @@ bool P_UndoPlayerMorph(player_t *activator, player_t *player, int unmorphflag, b
|
||||||
return false;
|
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 PClass;
|
||||||
class AActor;
|
class AActor;
|
||||||
class player_t;
|
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_MorphActor(AActor *activator, AActor *victim, PClassActor *ptype, PClassActor *mtype, int duration, int style, PClassActor *enter_flash, PClassActor *exit_flash);
|
||||||
|
bool P_UnmorphActor(AActor *activator, AActor *morphed, int flags = 0, bool force = false);
|
||||||
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);
|
|
||||||
|
|
||||||
#endif //__A_MORPH__
|
#endif //__A_MORPH__
|
||||||
|
|
|
@ -154,21 +154,4 @@ private:
|
||||||
DEarthquake ();
|
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__
|
#endif //__A_SHAREDGLOBAL_H__
|
||||||
|
|
|
@ -10346,24 +10346,7 @@ scriptwait:
|
||||||
|
|
||||||
if (tag == 0)
|
if (tag == 0)
|
||||||
{
|
{
|
||||||
if (activator->player)
|
changes += P_UnmorphActor(activator, activator, 0, force);
|
||||||
{
|
|
||||||
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++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -10372,24 +10355,7 @@ scriptwait:
|
||||||
|
|
||||||
while ( (actor = iterator.Next ()) )
|
while ( (actor = iterator.Next ()) )
|
||||||
{
|
{
|
||||||
if (actor->player)
|
changes += P_UnmorphActor(activator, actor, 0, force);
|
||||||
{
|
|
||||||
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++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -294,39 +294,41 @@ void AActor::Die (AActor *source, AActor *inflictor, int dmgflags, FName MeansOf
|
||||||
{
|
{
|
||||||
// Handle possible unmorph on death
|
// Handle possible unmorph on death
|
||||||
bool wasgibbed = (health < GetGibHealth());
|
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 (wasgibbed)
|
||||||
if (realthis->health >= realgibhealth)
|
|
||||||
{
|
{
|
||||||
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 :)
|
// [SO] 9/2/02 -- It's rather funny to see an exploded player body with the invuln sparkle active :)
|
||||||
effects &= ~FX_RESPAWNINVUL;
|
effects &= ~FX_RESPAWNINVUL;
|
||||||
//flags &= ~MF_INVINCIBLE;
|
//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.
|
// [RH] Notify this actor's items.
|
||||||
for (AInventory *item = Inventory; item != NULL; )
|
for (AInventory *item = Inventory; item != NULL; )
|
||||||
{
|
{
|
||||||
|
|
|
@ -682,7 +682,7 @@ bool player_t::Resurrect()
|
||||||
|
|
||||||
if (morphTics)
|
if (morphTics)
|
||||||
{
|
{
|
||||||
P_UndoPlayerMorph(this, this);
|
P_UnmorphActor(mo, mo);
|
||||||
}
|
}
|
||||||
|
|
||||||
// player is now alive.
|
// 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
|
extend class Actor
|
||||||
{
|
{
|
||||||
|
virtual Actor, int, int MorphedDeath()
|
||||||
|
{
|
||||||
|
return null, 0, 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
//===========================================================================
|
//===========================================================================
|
||||||
//
|
//
|
||||||
// Main entry point
|
// Main entry point
|
||||||
|
@ -10,7 +39,7 @@ extend class Actor
|
||||||
{
|
{
|
||||||
if (player != null && player.mo != null && playerclass != null)
|
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
|
else
|
||||||
{
|
{
|
||||||
|
@ -38,7 +67,28 @@ extend class Actor
|
||||||
return false;
|
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
|
// FUNC P_MorphMonster
|
||||||
|
@ -71,7 +121,7 @@ extend class Actor
|
||||||
morphed.UnmorphTime = level.time + ((duration) ? duration : DEFMORPHTICS) + random[morphmonst]();
|
morphed.UnmorphTime = level.time + ((duration) ? duration : DEFMORPHTICS) + random[morphmonst]();
|
||||||
morphed.MorphStyle = style;
|
morphed.MorphStyle = style;
|
||||||
morphed.MorphExitFlash = (exit_flash) ? exit_flash : (class<Actor>)("TeleportFog");
|
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.special = special;
|
||||||
morphed.args[0] = args[0];
|
morphed.args[0] = args[0];
|
||||||
|
@ -501,9 +551,38 @@ extend class PlayerPawn
|
||||||
return true;
|
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
|
class MorphProjectile : Actor
|
||||||
{
|
{
|
||||||
|
|
||||||
|
@ -536,11 +615,18 @@ class MorphProjectile : Actor
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
class MorphedMonster : Actor native
|
//===========================================================================
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//===========================================================================
|
||||||
|
|
||||||
|
class MorphedMonster : Actor
|
||||||
{
|
{
|
||||||
native Actor UnmorphedMe;
|
Actor UnmorphedMe;
|
||||||
native int UnmorphTime, MorphStyle;
|
int UnmorphTime, MorphStyle;
|
||||||
native Class<Actor> MorphExitFlash;
|
Class<Actor> MorphExitFlash;
|
||||||
|
int FlagsSave;
|
||||||
|
|
||||||
Default
|
Default
|
||||||
{
|
{
|
||||||
|
@ -548,5 +634,118 @@ class MorphedMonster : Actor native
|
||||||
-COUNTKILL
|
-COUNTKILL
|
||||||
+FLOORCLIP
|
+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