From ac1bffc51be822cb166207fd715bc5751d15a5c3 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sat, 24 Nov 2018 09:33:03 +0100 Subject: [PATCH] - scriptified P_MorphMonster. --- src/g_shared/a_morph.cpp | 175 +----------------- src/g_shared/a_morph.h | 7 +- src/p_acs.cpp | 19 +- src/p_user.cpp | 6 +- wadsrc/static/zscript/actor.txt | 8 +- .../zscript/heretic/hereticartifacts.txt | 2 +- wadsrc/static/zscript/shared/morph.txt | 96 ++++++++++ wadsrc/static/zscript/shared/player.txt | 3 - 8 files changed, 115 insertions(+), 201 deletions(-) diff --git a/src/g_shared/a_morph.cpp b/src/g_shared/a_morph.cpp index 7cc62b0eb..631510106 100644 --- a/src/g_shared/a_morph.cpp +++ b/src/g_shared/a_morph.cpp @@ -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(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); -} diff --git a/src/g_shared/a_morph.h b/src/g_shared/a_morph.h index 1c0047c69..4a7177301 100644 --- a/src/g_shared/a_morph.h +++ b/src/g_shared/a_morph.h @@ -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__ diff --git a/src/p_acs.cpp b/src/p_acs.cpp index 808b724e1..04db70d32 100644 --- a/src/p_acs.cpp +++ b/src/p_acs.cpp @@ -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); } } diff --git a/src/p_user.cpp b/src/p_user.cpp index ea583dde3..579b33f0c 100644 --- a/src/p_user.cpp +++ b/src/p_user.cpp @@ -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; } diff --git a/wadsrc/static/zscript/actor.txt b/wadsrc/static/zscript/actor.txt index c5426936e..4b710f2ab 100644 --- a/wadsrc/static/zscript/actor.txt +++ b/wadsrc/static/zscript/actor.txt @@ -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 type, int amount); native bool UsePuzzleItem(int PuzzleItemType); native float AccuracyFactor(); - native bool MorphMonster (Class spawntype, int duration, int style, Class enter_flash, Class 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 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 type, int duration = 0, int flags = 0, class enter_flash = null, class exit_flash = null); - action native state, bool A_Teleport(statelabel teleportstate = null, class targettype = "BossSpot", class 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: diff --git a/wadsrc/static/zscript/heretic/hereticartifacts.txt b/wadsrc/static/zscript/heretic/hereticartifacts.txt index 3b7f14ad8..688ca6ebf 100644 --- a/wadsrc/static/zscript/heretic/hereticartifacts.txt +++ b/wadsrc/static/zscript/heretic/hereticartifacts.txt @@ -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)) { diff --git a/wadsrc/static/zscript/shared/morph.txt b/wadsrc/static/zscript/shared/morph.txt index e643623fa..ebb4a3437 100644 --- a/wadsrc/static/zscript/shared/morph.txt +++ b/wadsrc/static/zscript/shared/morph.txt @@ -1,3 +1,99 @@ +extend class Actor +{ + //=========================================================================== + // + // Main entry point + // + //=========================================================================== + + bool Morph(Actor activator, class playerclass, class monsterclass, int duration = 0, int style = 0, class morphflash = null, classunmorphflash = 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 type, int duration = 0, int style = 0, class morphflash = null, classunmorphflash = null) + { + if (self.player != null) + { + let playerclass = (class)(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 spawntype, int duration, int style, Class enter_flash, Class 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)("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)("TeleportFog"), Pos + (0, 0, gameinfo.TELEFOGHEIGHT), ALLOW_REPLACE); + if (eflash) + eflash.target = morphed; + return true; + } +} + extend class PlayerPawn { //=========================================================================== diff --git a/wadsrc/static/zscript/shared/player.txt b/wadsrc/static/zscript/shared/player.txt index 2d6ef3cac..25f025d29 100644 --- a/wadsrc/static/zscript/shared/player.txt +++ b/wadsrc/static/zscript/shared/player.txt @@ -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 ammotype); native Weapon PickNewWeapon(class ammotype); - native void Substitute(PlayerPawn replacement); - } class PlayerChunk : PlayerPawn