mirror of
https://github.com/ZDoom/gzdoom.git
synced 2024-11-10 06:42:08 +00:00
Further morphing clean up
Players will now use their Alternative field to check if they're morphed instead of their MorphTics. This makes the current state of morphing more reliable, otherwise setting this to 0 manually without unmorphing could have very odd results. Both monsters and players consider 0 morph time to mean infinite now (previously this only applied to monsters). Player unmorphs no longer die in the case of a failed unmorph on death. Removed inventory swapping on player pointer substitution as it's too messy to do here.
This commit is contained in:
parent
30730647fe
commit
12dc5c1506
17 changed files with 37 additions and 45 deletions
|
@ -479,7 +479,7 @@ FGameTexture *FMugShot::GetFace(player_t *player, const char *default_face, int
|
|||
if (CurrentState != NULL)
|
||||
{
|
||||
int skin = player->userinfo.GetSkin();
|
||||
const char *skin_face = (stateflags & FMugShot::CUSTOM) ? nullptr : (player->morphTics ? (GetDefaultByType(player->MorphedPlayerClass))->NameVar(NAME_Face).GetChars() : Skins[skin].Face.GetChars());
|
||||
const char *skin_face = (stateflags & FMugShot::CUSTOM) ? nullptr : (player->mo->alternative != nullptr ? (GetDefaultByType(player->MorphedPlayerClass))->NameVar(NAME_Face).GetChars() : Skins[skin].Face.GetChars());
|
||||
return CurrentState->GetCurrentFrameTexture(default_face, skin_face, level, angle);
|
||||
}
|
||||
return NULL;
|
||||
|
|
|
@ -145,7 +145,6 @@ xx(Reflection)
|
|||
xx(CustomInventory)
|
||||
xx(Inventory)
|
||||
xx(StateProvider)
|
||||
xx(ObtainInventory)
|
||||
xx(CallTryPickup)
|
||||
xx(QuestItem25)
|
||||
xx(QuestItem28)
|
||||
|
|
|
@ -1149,7 +1149,7 @@ void FLevelLocals::UnSnapshotLevel(bool hubLoad)
|
|||
// If this isn't the unmorphed original copy of a player, destroy it, because it's extra.
|
||||
for (i = 0; i < MAXPLAYERS; ++i)
|
||||
{
|
||||
if (PlayerInGame(i) && Players[i]->morphTics && Players[i]->mo->alternative == pawn)
|
||||
if (PlayerInGame(i) && Players[i]->mo->alternative == pawn)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -37,7 +37,7 @@ bool P_MorphActor(AActor *activator, AActor *victim, PClassActor *ptype, PClassA
|
|||
|
||||
bool P_UnmorphActor(AActor *activator, AActor *morphed, int flags, bool force)
|
||||
{
|
||||
IFVIRTUALPTR(morphed, AActor, UnMorph)
|
||||
IFVIRTUALPTR(morphed, AActor, Unmorph)
|
||||
{
|
||||
VMValue params[] = { morphed, activator, flags, force };
|
||||
int retval;
|
||||
|
|
|
@ -3115,7 +3115,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_Pain)
|
|||
PARAM_SELF_PROLOGUE(AActor);
|
||||
|
||||
// [RH] Vary player pain sounds depending on health (ala Quake2)
|
||||
if (self->player && self->player->morphTics == 0)
|
||||
if (self->player && self->alternative == nullptr)
|
||||
{
|
||||
const char *pain_amount;
|
||||
FSoundID sfx_id = NO_SOUND;
|
||||
|
|
|
@ -329,8 +329,10 @@ void AActor::Die (AActor *source, AActor *inflictor, int dmgflags, FName MeansOf
|
|||
VMValue params[] = { this };
|
||||
VMCall(func, params, 1, nullptr, 0);
|
||||
|
||||
// Always kill the dummy Actor if it didn't unmorph, otherwise checking the morph flags.
|
||||
if (realMo != nullptr && (!(morphStyle & MORPH_UNDOBYDEATH) || !(morphStyle & MORPH_UNDOBYDEATHSAVES)))
|
||||
// Kill the dummy Actor if it didn't unmorph, otherwise checking the morph flags. Player pawns need
|
||||
// to stay, otherwise they won't respawn correctly.
|
||||
if (realMo != nullptr
|
||||
&& ((alternative != nullptr && player == nullptr) || (alternative == nullptr && !(morphStyle & MORPH_UNDOBYDEATHSAVES))))
|
||||
{
|
||||
if (wasgibbed)
|
||||
{
|
||||
|
@ -460,7 +462,7 @@ void AActor::Die (AActor *source, AActor *inflictor, int dmgflags, FName MeansOf
|
|||
++source->player->spreecount;
|
||||
}
|
||||
|
||||
if (source->player->morphTics)
|
||||
if (source->alternative != nullptr)
|
||||
{ // Make a super chicken
|
||||
source->GiveInventoryType (PClass::FindActor(NAME_PowerWeaponLevel2));
|
||||
}
|
||||
|
@ -1331,7 +1333,7 @@ static int DamageMobj (AActor *target, AActor *inflictor, AActor *source, int da
|
|||
|
||||
if (damage >= player->health && !telefragDamage
|
||||
&& (G_SkillProperty(SKILLP_AutoUseHealth) || deathmatch)
|
||||
&& !player->morphTics)
|
||||
&& target->alternative == nullptr)
|
||||
{ // Try to use some inventory health
|
||||
P_AutoUseHealth (player, damage - player->health + 1);
|
||||
}
|
||||
|
@ -1465,7 +1467,7 @@ static int DamageMobj (AActor *target, AActor *inflictor, AActor *source, int da
|
|||
// check for special fire damage or ice damage deaths
|
||||
if (mod == NAME_Fire)
|
||||
{
|
||||
if (player && !player->morphTics)
|
||||
if (player && target->alternative == nullptr)
|
||||
{ // Check for flame death
|
||||
if (!inflictor ||
|
||||
((target->health > -50) && (damage > 25)) ||
|
||||
|
@ -1799,7 +1801,7 @@ void P_PoisonDamage (player_t *player, AActor *source, int damage, bool playPain
|
|||
}
|
||||
if (damage >= player->health
|
||||
&& (G_SkillProperty(SKILLP_AutoUseHealth) || deathmatch)
|
||||
&& !player->morphTics)
|
||||
&& target->alternative == nullptr)
|
||||
{ // Try to use some inventory health
|
||||
P_AutoUseHealth(player, damage - player->health+1);
|
||||
}
|
||||
|
@ -1829,7 +1831,7 @@ void P_PoisonDamage (player_t *player, AActor *source, int damage, bool playPain
|
|||
else
|
||||
{
|
||||
target->special1 = damage;
|
||||
if (player && !player->morphTics)
|
||||
if (player && target->alternative == nullptr)
|
||||
{ // Check for flame death
|
||||
if ((player->poisontype == NAME_Fire) && (target->health > -50) && (damage > 25))
|
||||
{
|
||||
|
|
|
@ -835,7 +835,7 @@ int P_GetRealMaxHealth(AActor *actor, int max)
|
|||
{
|
||||
max = actor->GetMaxHealth(true);
|
||||
// [MH] First step in predictable generic morph effects
|
||||
if (player->morphTics)
|
||||
if (actor->alternative != nullptr)
|
||||
{
|
||||
if (player->MorphStyle & MORPH_FULLHEALTH)
|
||||
{
|
||||
|
@ -857,7 +857,7 @@ int P_GetRealMaxHealth(AActor *actor, int max)
|
|||
else
|
||||
{
|
||||
// Bonus health should be added on top of the item's limit.
|
||||
if (player->morphTics == 0 || (player->MorphStyle & MORPH_ADDSTAMINA))
|
||||
if (actor->alternative == nullptr || (player->MorphStyle & MORPH_ADDSTAMINA))
|
||||
{
|
||||
max += actor->IntVar(NAME_BonusHealth);
|
||||
}
|
||||
|
@ -5225,14 +5225,6 @@ void PlayerPointerSubstitution(AActor* oldPlayer, AActor* newPlayer)
|
|||
return;
|
||||
}
|
||||
|
||||
// Swap over the inventory.
|
||||
auto func = dyn_cast<PFunction>(newPlayer->GetClass()->FindSymbol(NAME_ObtainInventory, true));
|
||||
if (func)
|
||||
{
|
||||
VMValue params[] = { newPlayer, oldPlayer };
|
||||
VMCall(func->Variants[0].Implementation, params, 2, nullptr, 0);
|
||||
}
|
||||
|
||||
// Go through player infos.
|
||||
for (int i = 0; i < MAXPLAYERS; ++i)
|
||||
{
|
||||
|
@ -5314,11 +5306,10 @@ int MorphPointerSubstitution(AActor* from, AActor* to)
|
|||
// Since the check is good, move the inventory items over. This should always be done when
|
||||
// morphing to emulate Heretic/Hexen's behavior since those stored the inventory in their
|
||||
// player structs.
|
||||
auto func = dyn_cast<PFunction>(to->GetClass()->FindSymbol(NAME_ObtainInventory, true));
|
||||
if (func)
|
||||
IFVM(Actor, ObtainInventory)
|
||||
{
|
||||
VMValue params[] = { to, from };
|
||||
VMCall(func->Variants[0].Implementation, params, 2, nullptr, 0);
|
||||
VMCall(func, params, 2, nullptr, 0);
|
||||
}
|
||||
|
||||
// Only change some gameplay-related pointers that we know we can safely swap to whatever
|
||||
|
|
|
@ -693,7 +693,7 @@ bool player_t::Resurrect()
|
|||
P_BringUpWeapon(this);
|
||||
}
|
||||
|
||||
if (morphTics)
|
||||
if (mo->alternative != nullptr)
|
||||
{
|
||||
P_UnmorphActor(mo, mo);
|
||||
}
|
||||
|
@ -1172,7 +1172,7 @@ void P_CheckEnvironment(player_t *player)
|
|||
P_PlayerOnSpecialFlat(player, P_GetThingFloorType(player->mo));
|
||||
}
|
||||
if (player->mo->Vel.Z <= -player->mo->FloatVar(NAME_FallingScreamMinSpeed) &&
|
||||
player->mo->Vel.Z >= -player->mo->FloatVar(NAME_FallingScreamMaxSpeed) && !player->morphTics &&
|
||||
player->mo->Vel.Z >= -player->mo->FloatVar(NAME_FallingScreamMaxSpeed) && player->mo->alternative == nullptr &&
|
||||
player->mo->waterlevel == 0)
|
||||
{
|
||||
auto id = S_FindSkinnedSound(player->mo, S_FindSound("*falling"));
|
||||
|
|
|
@ -1406,7 +1406,7 @@ class Actor : Thinker native
|
|||
bool grunted;
|
||||
|
||||
// [RH] only make noise if alive
|
||||
if (self.health > 0 && self.player.morphTics == 0)
|
||||
if (self.health > 0 && !Alternative)
|
||||
{
|
||||
grunted = false;
|
||||
// Why should this number vary by gravity?
|
||||
|
|
|
@ -221,7 +221,7 @@ class ChickenPlayer : PlayerPawn
|
|||
pspr.y = WEAPONTOP + player.chickenPeck / 2;
|
||||
}
|
||||
}
|
||||
if (player.morphTics & 15)
|
||||
if ((player.MorphTics ? player.MorphTics : Random[ChickenPlayerThink]()) & 15)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -145,7 +145,7 @@ class PigPlayer : PlayerPawn
|
|||
|
||||
override void MorphPlayerThink ()
|
||||
{
|
||||
if (player.morphTics & 15)
|
||||
if ((player.MorphTics ? player.MorphTics : Random[PigPlayerThink]()) & 15)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -1933,7 +1933,7 @@ class PowerMorph : Powerup
|
|||
|
||||
EMorphFlags mStyle = MorphedPlayer ? MorphedPlayer.MorphStyle : MorphStyle;
|
||||
|
||||
Owner.Unmorph(Owner, 0, mStyle & MRF_UNDOALWAYS);
|
||||
Owner.Unmorph(Owner, force: mStyle & MRF_UNDOALWAYS);
|
||||
MorphedPlayer = null;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -262,7 +262,7 @@ class Weapon : StateProvider
|
|||
}
|
||||
let psp = player.GetPSprite(PSP_WEAPON);
|
||||
if (!psp) return;
|
||||
if (player.morphTics || player.cheats & CF_INSTANTWEAPSWITCH)
|
||||
if (Alternative || player.cheats & CF_INSTANTWEAPSWITCH)
|
||||
{
|
||||
psp.y = WEAPONBOTTOM;
|
||||
}
|
||||
|
|
|
@ -94,7 +94,7 @@ extend class Actor
|
|||
|
||||
virtual bool CheckUnmorph()
|
||||
{
|
||||
return UnmorphTime <= Level.Time && Unmorph(self);
|
||||
return UnmorphTime && UnmorphTime <= Level.Time && Unmorph(self, MRF_UNDOBYTIMEOUT);
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
|
|
|
@ -477,7 +477,7 @@ class PlayerPawn : Actor
|
|||
let player = self.player;
|
||||
if (!player) return;
|
||||
if ((player.WeaponState & WF_DISABLESWITCH) || // Weapon changing has been disabled.
|
||||
player.morphTics != 0) // Morphed classes cannot change weapons.
|
||||
Alternative) // Morphed classes cannot change weapons.
|
||||
{ // ...so throw away any pending weapon requests.
|
||||
player.PendingWeapon = WP_NOCHANGE;
|
||||
}
|
||||
|
@ -651,7 +651,7 @@ class PlayerPawn : Actor
|
|||
}
|
||||
}
|
||||
|
||||
if (player.morphTics)
|
||||
if (Alternative)
|
||||
{
|
||||
bob = 0;
|
||||
}
|
||||
|
@ -1072,7 +1072,7 @@ class PlayerPawn : Actor
|
|||
|
||||
virtual bool CanCrouch() const
|
||||
{
|
||||
return player.morphTics == 0 || bCrouchableMorph;
|
||||
return !Alternative || bCrouchableMorph;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
|
@ -1238,7 +1238,7 @@ class PlayerPawn : Actor
|
|||
side *= SideMove2;
|
||||
}
|
||||
|
||||
if (!player.morphTics)
|
||||
if (!Alternative)
|
||||
{
|
||||
double factor = 1.;
|
||||
for(let it = Inv; it != null; it = it.Inv)
|
||||
|
@ -1528,13 +1528,13 @@ class PlayerPawn : Actor
|
|||
{
|
||||
let player = self.player;
|
||||
// Morph counter
|
||||
if (player.morphTics)
|
||||
if (Alternative)
|
||||
{
|
||||
if (player.chickenPeck)
|
||||
{ // Chicken attack counter
|
||||
player.chickenPeck -= 3;
|
||||
}
|
||||
if (!--player.morphTics)
|
||||
if (player.MorphTics && !--player.MorphTics)
|
||||
{ // Attempt to undo the chicken/pig
|
||||
Unmorph(self, MRF_UNDOBYTIMEOUT);
|
||||
}
|
||||
|
@ -1661,7 +1661,7 @@ class PlayerPawn : Actor
|
|||
player.jumpTics = 0;
|
||||
}
|
||||
}
|
||||
if (player.morphTics && !(player.cheats & CF_PREDICTING))
|
||||
if (Alternative && !(player.cheats & CF_PREDICTING))
|
||||
{
|
||||
MorphPlayerThink ();
|
||||
}
|
||||
|
@ -2042,9 +2042,9 @@ class PlayerPawn : Actor
|
|||
Inventory item, next;
|
||||
let p = player;
|
||||
|
||||
if (p.morphTics != 0)
|
||||
if (Alternative)
|
||||
{ // Undo morph
|
||||
Unmorph(self, 0, true);
|
||||
Unmorph(self, force: true);
|
||||
}
|
||||
// 'self' will be no longer valid from here on in case of an unmorph
|
||||
let me = p.mo;
|
||||
|
|
|
@ -434,7 +434,7 @@ extend class PlayerPawn
|
|||
int style = MRF_UNDOBYTOMEOFPOWER;
|
||||
if (gameinfo.gametype == GAME_Hexen) style |= MRF_UNDOBYCHAOSDEVICE;
|
||||
|
||||
if (player.morphTics)
|
||||
if (Alternative)
|
||||
{
|
||||
if (Unmorph (self))
|
||||
{
|
||||
|
@ -454,7 +454,7 @@ extend class PlayerPawn
|
|||
|
||||
virtual void CheatTakeWeaps()
|
||||
{
|
||||
if (player.morphTics || health <= 0)
|
||||
if (Alternative || health <= 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -106,7 +106,7 @@ extend class PlayerPawn
|
|||
if (!duration)
|
||||
duration = DEFMORPHTICS;
|
||||
|
||||
if (player.MorphTics)
|
||||
if (Alternative)
|
||||
{
|
||||
// Player is already a beast.
|
||||
if (bCanSuperMorph && spawnType == GetClass()
|
||||
|
|
Loading…
Reference in a new issue