mirror of
https://github.com/ZDoom/qzdoom.git
synced 2024-11-10 23:02:08 +00:00
- scriptified P_MorphMonster.
This commit is contained in:
parent
3ed7f4066d
commit
ac1bffc51b
8 changed files with 115 additions and 201 deletions
|
@ -39,12 +39,11 @@
|
|||
static FRandom pr_morphmonst ("MorphMonster");
|
||||
|
||||
|
||||
bool P_MorphPlayer(player_t *activator, player_t *p, PClassActor *spawntype, 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)
|
||||
{
|
||||
if (!p->mo) return false;
|
||||
IFVIRTUALPTR(p->mo, APlayerPawn, MorphPlayer)
|
||||
IFVIRTUALPTR(victim, AActor, Morph)
|
||||
{
|
||||
VMValue params[] = { p->mo, activator, spawntype, duration, style, enter_flash, exit_flash };
|
||||
VMValue params[] = { victim, activator, ptype, mtype, duration, style, enter_flash, exit_flash };
|
||||
int retval;
|
||||
VMReturn ret(&retval);
|
||||
VMCall(func, params, countof(params), &ret, 1);
|
||||
|
@ -56,7 +55,7 @@ bool P_MorphPlayer(player_t *activator, player_t *p, PClassActor *spawntype, int
|
|||
bool P_UndoPlayerMorph(player_t *activator, player_t *player, int unmorphflag, bool force)
|
||||
{
|
||||
if (!player->mo) return false;
|
||||
IFVIRTUALPTR(player->mo, APlayerPawn, MorphPlayer)
|
||||
IFVIRTUALPTR(player->mo, APlayerPawn, UndoPlayerMorph)
|
||||
{
|
||||
VMValue params[] = { player->mo, activator, unmorphflag, force };
|
||||
int retval;
|
||||
|
@ -67,76 +66,6 @@ bool P_UndoPlayerMorph(player_t *activator, player_t *player, int unmorphflag, b
|
|||
return false;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
//
|
||||
// FUNC P_MorphMonster
|
||||
//
|
||||
// Returns true if the monster gets turned into a chicken/pig.
|
||||
//
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
bool P_MorphMonster (AActor *actor, PClassActor *spawntype, int duration, int style, PClassActor *enter_flash, PClassActor *exit_flash)
|
||||
{
|
||||
AMorphedMonster *morphed;
|
||||
|
||||
if (actor == NULL || actor->player || spawntype == NULL ||
|
||||
actor->flags3 & MF3_DONTMORPH ||
|
||||
!(actor->flags3 & MF3_ISMONSTER) ||
|
||||
!spawntype->IsDescendantOf (PClass::FindActor(NAME_MorphedMonster)))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
morphed = static_cast<AMorphedMonster *>(Spawn (spawntype, actor->Pos(), NO_REPLACE));
|
||||
DObject::StaticPointerSubstitution (actor, morphed);
|
||||
if ((style & MORPH_TRANSFERTRANSLATION) && !(morphed->flags2 & MF2_DONTTRANSLATE))
|
||||
{
|
||||
morphed->Translation = actor->Translation;
|
||||
}
|
||||
morphed->tid = actor->tid;
|
||||
morphed->Angles.Yaw = actor->Angles.Yaw;
|
||||
morphed->UnmorphedMe = actor;
|
||||
morphed->Alpha = actor->Alpha;
|
||||
morphed->RenderStyle = actor->RenderStyle;
|
||||
morphed->Score = actor->Score;
|
||||
|
||||
morphed->UnmorphTime = level.time + ((duration) ? duration : MORPHTICS) + pr_morphmonst();
|
||||
morphed->MorphStyle = style;
|
||||
morphed->MorphExitFlash = (exit_flash) ? exit_flash : PClass::FindActor("TeleportFog");
|
||||
morphed->FlagsSave = actor->flags & ~MF_JUSTHIT;
|
||||
morphed->special = actor->special;
|
||||
memcpy (morphed->args, actor->args, sizeof(actor->args));
|
||||
morphed->CopyFriendliness (actor, true);
|
||||
morphed->flags |= actor->flags & MF_SHADOW;
|
||||
morphed->flags3 |= actor->flags3 & MF3_GHOST;
|
||||
if (actor->renderflags & RF_INVISIBLE)
|
||||
{
|
||||
morphed->FlagsSave |= MF_JUSTHIT;
|
||||
}
|
||||
morphed->AddToHash ();
|
||||
actor->RemoveFromHash ();
|
||||
actor->special = 0;
|
||||
actor->tid = 0;
|
||||
actor->flags &= ~(MF_SOLID|MF_SHOOTABLE);
|
||||
actor->flags |= MF_UNMORPHED;
|
||||
actor->renderflags |= RF_INVISIBLE;
|
||||
AActor *eflash = Spawn(((enter_flash) ? enter_flash : PClass::FindActor("TeleportFog")), actor->PosPlusZ(TELEFOGHEIGHT), ALLOW_REPLACE);
|
||||
if (eflash)
|
||||
eflash->target = morphed;
|
||||
return true;
|
||||
}
|
||||
|
||||
DEFINE_ACTION_FUNCTION(AActor, MorphMonster)
|
||||
{
|
||||
PARAM_SELF_PROLOGUE(AActor);
|
||||
PARAM_CLASS(spawntype, AActor);
|
||||
PARAM_INT(duration);
|
||||
PARAM_INT(style);
|
||||
PARAM_CLASS(enter_flash, AActor);
|
||||
PARAM_CLASS(exit_flash, AActor);
|
||||
ACTION_RETURN_BOOL(P_MorphMonster(self, spawntype, duration, style, enter_flash, exit_flash));
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
//
|
||||
// FUNC P_UndoMonsterMorph
|
||||
|
@ -197,23 +126,6 @@ bool P_UndoMonsterMorph (AMorphedMonster *beast, bool force)
|
|||
return true;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
//
|
||||
// FUNC P_UpdateMorphedMonster
|
||||
//
|
||||
// Returns true if the monster unmorphs.
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
bool P_UpdateMorphedMonster (AMorphedMonster *beast)
|
||||
{
|
||||
if (beast->UnmorphTime > level.time)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return P_UndoMonsterMorph (beast);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
//
|
||||
// FUNC P_MorphedDeath
|
||||
|
@ -280,55 +192,6 @@ bool P_MorphedDeath(AActor *actor, AActor **morphed, int *morphedstyle, int *mor
|
|||
return false;
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
//
|
||||
// EndAllPowerupEffects
|
||||
//
|
||||
// Calls EndEffect() on every Powerup in the inventory list.
|
||||
//
|
||||
//===========================================================================
|
||||
|
||||
void EndAllPowerupEffects(AInventory *item)
|
||||
{
|
||||
auto ptype = PClass::FindActor(NAME_Powerup);
|
||||
while (item != NULL)
|
||||
{
|
||||
if (item->IsKindOf(ptype))
|
||||
{
|
||||
IFVIRTUALPTRNAME(item, NAME_Powerup, EndEffect)
|
||||
{
|
||||
VMValue params[1] = { item };
|
||||
VMCall(func, params, 1, nullptr, 0);
|
||||
}
|
||||
}
|
||||
item = item->Inventory;
|
||||
}
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
//
|
||||
// InitAllPowerupEffects
|
||||
//
|
||||
// Calls InitEffect() on every Powerup in the inventory list.
|
||||
//
|
||||
//===========================================================================
|
||||
|
||||
void InitAllPowerupEffects(AInventory *item)
|
||||
{
|
||||
auto ptype = PClass::FindActor(NAME_Powerup);
|
||||
while (item != NULL)
|
||||
{
|
||||
if (item->IsKindOf(ptype))
|
||||
{
|
||||
IFVIRTUALPTRNAME(item, NAME_Powerup, InitEffect)
|
||||
{
|
||||
VMValue params[1] = { item };
|
||||
VMCall(func, params, 1, nullptr, 0);
|
||||
}
|
||||
}
|
||||
item = item->Inventory;
|
||||
}
|
||||
}
|
||||
|
||||
// Morphed Monster (you must subclass this to do something useful) ---------
|
||||
|
||||
|
@ -380,35 +243,9 @@ void AMorphedMonster::Die (AActor *source, AActor *inflictor, int dmgflags, FNam
|
|||
|
||||
void AMorphedMonster::Tick ()
|
||||
{
|
||||
if (!P_UpdateMorphedMonster (this))
|
||||
if (UnmorphTime > level.time || !P_UndoMonsterMorph(this))
|
||||
{
|
||||
Super::Tick ();
|
||||
Super::Tick();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
DEFINE_ACTION_FUNCTION(AActor, A_Morph)
|
||||
{
|
||||
PARAM_SELF_PROLOGUE(AActor);
|
||||
PARAM_CLASS(type, AActor);
|
||||
PARAM_INT(duration);
|
||||
PARAM_INT(flags);
|
||||
PARAM_CLASS(enter_flash, AActor);
|
||||
PARAM_CLASS(exit_flash, AActor);
|
||||
bool res = false;
|
||||
if (self->player)
|
||||
{
|
||||
if (type->IsDescendantOf(RUNTIME_CLASS(APlayerPawn)))
|
||||
{
|
||||
res = P_MorphPlayer(self->player, self->player, type, duration, flags, enter_flash, exit_flash);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (type->IsDescendantOf(RUNTIME_CLASS(AMorphedMonster)))
|
||||
{
|
||||
res = P_MorphMonster(self, type, duration, flags, enter_flash, exit_flash);
|
||||
}
|
||||
}
|
||||
ACTION_RETURN_BOOL(res);
|
||||
}
|
||||
|
|
|
@ -35,13 +35,10 @@ class AActor;
|
|||
class player_t;
|
||||
class AMorphedMonster;
|
||||
|
||||
bool P_MorphPlayer (player_t *activator, player_t *player, PClassActor *morphclass, int duration = 0, int style = 0,
|
||||
PClassActor *enter_flash = NULL, PClassActor *exit_flash = NULL);
|
||||
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_MorphMonster (AActor *actor, PClassActor *morphclass, int duration = 0, int style = 0,
|
||||
PClassActor *enter_flash = NULL, PClassActor *exit_flash = NULL);
|
||||
bool P_UndoMonsterMorph (AMorphedMonster *beast, bool force = false);
|
||||
bool P_UpdateMorphedMonster (AActor *actor);
|
||||
bool P_MorphedDeath(AActor *actor, AActor **morphed, int *morphedstyle, int *morphedhealth);
|
||||
|
||||
#endif //__A_MORPH__
|
||||
|
|
|
@ -10305,14 +10305,7 @@ scriptwait:
|
|||
|
||||
if (tag == 0)
|
||||
{
|
||||
if (activator != NULL && activator->player)
|
||||
{
|
||||
changes += P_MorphPlayer(activator->player, activator->player, playerclass, duration, style, morphflash, unmorphflash);
|
||||
}
|
||||
else
|
||||
{
|
||||
changes += P_MorphMonster(activator, monsterclass, duration, style, morphflash, unmorphflash);
|
||||
}
|
||||
changes = P_MorphActor(activator, activator, playerclass, monsterclass, duration, style, morphflash, unmorphflash);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -10321,15 +10314,7 @@ scriptwait:
|
|||
|
||||
while ( (actor = iterator.Next ()) )
|
||||
{
|
||||
if (actor->player)
|
||||
{
|
||||
changes += P_MorphPlayer(activator == NULL ? NULL : activator->player,
|
||||
actor->player, playerclass, duration, style, morphflash, unmorphflash);
|
||||
}
|
||||
else
|
||||
{
|
||||
changes += P_MorphMonster(actor, monsterclass, duration, style, morphflash, unmorphflash);
|
||||
}
|
||||
changes += P_MorphActor(activator, actor, playerclass, monsterclass, duration, style, morphflash, unmorphflash);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -293,10 +293,10 @@ CCMD (playerclasses)
|
|||
}
|
||||
}
|
||||
|
||||
DEFINE_ACTION_FUNCTION(APlayerPawn, Substitute)
|
||||
DEFINE_ACTION_FUNCTION(AActor, Substitute)
|
||||
{
|
||||
PARAM_SELF_PROLOGUE(APlayerPawn);
|
||||
PARAM_OBJECT(replace, APlayerPawn);
|
||||
PARAM_SELF_PROLOGUE(AActor);
|
||||
PARAM_OBJECT(replace, AActor);
|
||||
DObject::StaticPointerSubstitution(self, replace);
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -75,6 +75,7 @@ class Actor : Thinker native
|
|||
const LARGE_MASS = 10000000; // not INT_MAX on purpose
|
||||
const ORIG_FRICTION = (0xE800/65536.); // original value
|
||||
const ORIG_FRICTION_FACTOR = (2048/65536.); // original value
|
||||
const DEFMORPHTICS = 40 * TICRATE;
|
||||
|
||||
|
||||
// flags are not defined here, the native fields for those get synthesized from the internal tables.
|
||||
|
@ -329,6 +330,7 @@ class Actor : Thinker native
|
|||
|
||||
// need some definition work first
|
||||
//FRenderStyle RenderStyle;
|
||||
native private int RenderStyle; // This is kept private until its real type has been implemented into the VM. But some code needs to copy this.
|
||||
//int ConversationRoot; // THe root of the current dialogue
|
||||
|
||||
// deprecated things.
|
||||
|
@ -438,6 +440,7 @@ class Actor : Thinker native
|
|||
virtual native bool Slam(Actor victim);
|
||||
virtual native void Touch(Actor toucher);
|
||||
virtual native void MarkPrecacheSounds();
|
||||
native void Substitute(Actor replacement);
|
||||
|
||||
// Called by PIT_CheckThing to check if two actors actually can collide.
|
||||
virtual bool CanCollideWith(Actor other, bool passive)
|
||||
|
@ -735,7 +738,7 @@ class Actor : Thinker native
|
|||
native bool GiveAmmo (Class<Ammo> type, int amount);
|
||||
native bool UsePuzzleItem(int PuzzleItemType);
|
||||
native float AccuracyFactor();
|
||||
native bool MorphMonster (Class<Actor> spawntype, int duration, int style, Class<Actor> enter_flash, Class<Actor> exit_flash);
|
||||
|
||||
action native void SetCamera(Actor cam, bool revert = false);
|
||||
native bool Warp(Actor dest, double xofs = 0, double yofs = 0, double zofs = 0, double angle = 0, int flags = 0, double heightoffset = 0, double radiusoffset = 0, double pitch = 0);
|
||||
|
||||
|
@ -1097,8 +1100,6 @@ class Actor : Thinker native
|
|||
native void Revive();
|
||||
action native bool, Actor A_ThrowGrenade(class<Actor> itemtype, double zheight = 0, double xyvel = 0, double zvel = 0, bool useammo = true);
|
||||
native void A_Weave(int xspeed, int yspeed, double xdist, double ydist);
|
||||
native bool A_Morph(class<Actor> type, int duration = 0, int flags = 0, class<Actor> enter_flash = null, class<Actor> exit_flash = null);
|
||||
|
||||
|
||||
action native state, bool A_Teleport(statelabel teleportstate = null, class<SpecialSpot> targettype = "BossSpot", class<Actor> fogtype = "TeleportFog", int flags = 0, double mindist = 128, double maxdist = 0, int ptr = AAPTR_DEFAULT);
|
||||
action native state, bool A_Warp(int ptr_destination, double xofs = 0, double yofs = 0, double zofs = 0, double angle = 0, int flags = 0, statelabel success_state = null, double heightoffset = 0, double radiusoffset = 0, double pitch = 0);
|
||||
|
@ -1218,6 +1219,7 @@ class Actor : Thinker native
|
|||
return ACS_ExecuteWithResult(-int(script), arg1, arg2, arg3, arg4);
|
||||
}
|
||||
|
||||
|
||||
States(Actor, Overlay, Weapon, Item)
|
||||
{
|
||||
Spawn:
|
||||
|
|
|
@ -71,7 +71,7 @@ Class ArtiTomeOfPower : PowerupGiver
|
|||
Playerinfo p = Owner.player;
|
||||
if (p && p.morphTics && (p.MorphStyle & MRF_UNDOBYTOMEOFPOWER))
|
||||
{ // Attempt to undo chicken
|
||||
if (!p.UndoPlayerMorph (p, MRF_UNDOBYTOMEOFPOWER))
|
||||
if (!p.mo.UndoPlayerMorph (p, MRF_UNDOBYTOMEOFPOWER))
|
||||
{ // Failed
|
||||
if (!(p.MorphStyle & MRF_FAILNOTELEFRAG))
|
||||
{
|
||||
|
|
|
@ -1,3 +1,99 @@
|
|||
extend class Actor
|
||||
{
|
||||
//===========================================================================
|
||||
//
|
||||
// Main entry point
|
||||
//
|
||||
//===========================================================================
|
||||
|
||||
bool Morph(Actor activator, class<PlayerPawn> playerclass, class<MorphedMonster> monsterclass, int duration = 0, int style = 0, class<Actor> morphflash = null, class<Actor>unmorphflash = null)
|
||||
{
|
||||
if (player != null && player.mo != null && playerclass != null)
|
||||
{
|
||||
return player.mo.MorphPlayer(activator.player, playerclass, duration, style, morphflash, unmorphflash);
|
||||
}
|
||||
else
|
||||
{
|
||||
return MorphMonster(monsterclass, duration, style, morphflash, unmorphflash);
|
||||
}
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
//
|
||||
// Action function variant whose arguments differ from the generic one.
|
||||
//
|
||||
//===========================================================================
|
||||
|
||||
bool A_Morph(class<Actor> type, int duration = 0, int style = 0, class<Actor> morphflash = null, class<Actor>unmorphflash = null)
|
||||
{
|
||||
if (self.player != null)
|
||||
{
|
||||
let playerclass = (class<PlayerPawn>)(type);
|
||||
if (playerclass && self.player.mo != null) return player.mo.MorphPlayer(self.player, playerclass, duration, style, morphflash, unmorphflash);
|
||||
}
|
||||
else
|
||||
{
|
||||
return MorphMonster(type, duration, style, morphflash, unmorphflash);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
//
|
||||
// FUNC P_MorphMonster
|
||||
//
|
||||
// Returns true if the monster gets turned into a chicken/pig.
|
||||
//
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
virtual bool MorphMonster (Class<Actor> spawntype, int duration, int style, Class<Actor> enter_flash, Class<Actor> exit_flash)
|
||||
{
|
||||
if (player || spawntype == NULL || bDontMorph || !bIsMonster || !(spawntype is 'MorphedMonster'))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
let morphed = MorphedMonster(Spawn (spawntype, Pos, NO_REPLACE));
|
||||
Substitute (morphed);
|
||||
if ((style & MRF_TRANSFERTRANSLATION) && !morphed.bDontTranslate)
|
||||
{
|
||||
morphed.Translation = Translation;
|
||||
}
|
||||
morphed.ChangeTid(tid);
|
||||
ChangeTid(0);
|
||||
morphed.Angle = Angle;
|
||||
morphed.UnmorphedMe = self;
|
||||
morphed.Alpha = Alpha;
|
||||
morphed.RenderStyle = RenderStyle;
|
||||
morphed.Score = Score;
|
||||
|
||||
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.special = special;
|
||||
morphed.args[0] = args[0];
|
||||
morphed.args[1] = args[1];
|
||||
morphed.args[2] = args[2];
|
||||
morphed.args[3] = args[3];
|
||||
morphed.args[4] = args[4];
|
||||
morphed.CopyFriendliness (self, true);
|
||||
morphed.bShadow |= bShadow;
|
||||
morphed.bGhost |= bGhost;
|
||||
special = 0;
|
||||
bSolid = false;
|
||||
bShootable = false;
|
||||
bUnmorphed = true;
|
||||
bInvisible = true;
|
||||
let eflash = Spawn(enter_flash ? enter_flash : (class<Actor>)("TeleportFog"), Pos + (0, 0, gameinfo.TELEFOGHEIGHT), ALLOW_REPLACE);
|
||||
if (eflash)
|
||||
eflash.target = morphed;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
extend class PlayerPawn
|
||||
{
|
||||
//===========================================================================
|
||||
|
|
|
@ -15,7 +15,6 @@ class PlayerPawn : Actor native
|
|||
const CROUCHSPEED = (1./12);
|
||||
// [RH] # of ticks to complete a turn180
|
||||
const TURN180_TICKS = ((TICRATE / 4) + 1);
|
||||
const DEFMORPHTICS = 40 * TICRATE;
|
||||
|
||||
native int crouchsprite;
|
||||
native int MaxHealth;
|
||||
|
@ -1280,8 +1279,6 @@ class PlayerPawn : Actor native
|
|||
native void CheckWeaponButtons();
|
||||
native Weapon BestWeapon(class<Ammo> ammotype);
|
||||
native Weapon PickNewWeapon(class<Ammo> ammotype);
|
||||
native void Substitute(PlayerPawn replacement);
|
||||
|
||||
}
|
||||
|
||||
class PlayerChunk : PlayerPawn
|
||||
|
|
Loading…
Reference in a new issue