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:
Boondorl 2024-01-01 11:50:01 -05:00 committed by Rachael Alexanderson
commit 12dc5c1506
17 changed files with 37 additions and 45 deletions

View file

@ -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