From 08059f718b552c13f23f05c10a21fc83ef9e25c8 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sat, 24 Nov 2018 20:58:33 +0100 Subject: [PATCH] - scriptified FilterCoopRespawnInventory. --- src/d_player.h | 3 +- src/g_statusbar/sbarinfo_commands.cpp | 5 +- src/p_mobj.cpp | 12 ++- src/p_user.cpp | 121 +----------------------- wadsrc/static/zscript/actor.txt | 1 + wadsrc/static/zscript/shared/player.txt | 107 +++++++++++++++++++++ 6 files changed, 124 insertions(+), 125 deletions(-) diff --git a/src/d_player.h b/src/d_player.h index cf2fffa0a..ad6635c21 100644 --- a/src/d_player.h +++ b/src/d_player.h @@ -101,8 +101,7 @@ public: AWeapon *PickNewWeapon (PClassActor *ammotype); AWeapon *BestWeapon (PClassActor *ammotype); void GiveDeathmatchInventory (); - void FilterCoopRespawnInventory (APlayerPawn *oldplayer); - + void GiveDefaultInventory (); // These are virtual on the script side only. diff --git a/src/g_statusbar/sbarinfo_commands.cpp b/src/g_statusbar/sbarinfo_commands.cpp index 0eba791b3..5a6da4b31 100644 --- a/src/g_statusbar/sbarinfo_commands.cpp +++ b/src/g_statusbar/sbarinfo_commands.cpp @@ -597,8 +597,9 @@ class CommandDrawSwitchableImage : public CommandDrawImage auto armor = statusBar->CPlayer->mo->FindInventory(NAME_BasicArmor); if(armor != NULL) { - bool matches1 = armor->NameVar(NAME_ArmorType).GetIndex() == armorType[0] && EvaluateOperation(conditionalOperator[0], conditionalValue[0], armor->Amount); - bool matches2 = armor->NameVar(NAME_ArmorType).GetIndex() == armorType[1] && EvaluateOperation(conditionalOperator[1], conditionalValue[1], armor->Amount); + auto n = armor->NameVar(NAME_ArmorType).GetIndex(); + bool matches1 = n == armorType[0] && EvaluateOperation(conditionalOperator[0], conditionalValue[0], armor->Amount); + bool matches2 = n == armorType[1] && EvaluateOperation(conditionalOperator[1], conditionalValue[1], armor->Amount); drawAlt = 1; if(conditionAnd) diff --git a/src/p_mobj.cpp b/src/p_mobj.cpp index 507fb90d5..043b61824 100644 --- a/src/p_mobj.cpp +++ b/src/p_mobj.cpp @@ -1085,6 +1085,12 @@ void AActor::DestroyAllInventory () } } +DEFINE_ACTION_FUNCTION(AActor, DestroyAllInventory) +{ + PARAM_SELF_PROLOGUE(AActor); + self->DestroyAllInventory(); + return 0; +} //============================================================================ // // AActor :: FirstInv @@ -5745,7 +5751,11 @@ APlayerPawn *P_SpawnPlayer (FPlayerStart *mthing, int playernum, int flags) else if ((multiplayer || (level.flags2 & LEVEL2_ALLOWRESPAWN) || sv_singleplayerrespawn || !!G_SkillProperty(SKILLP_PlayerRespawn)) && state == PST_REBORN && oldactor != NULL) { // Special inventory handling for respawning in coop - p->mo->FilterCoopRespawnInventory (oldactor); + IFVM(PlayerPawn, FilterCoopRespawnInventory) + { + VMValue params[] = { p->mo, oldactor }; + VMCall(func, params, 2, nullptr, 0); + } } if (oldactor != NULL) { // Remove any inventory left from the old actor. Coop handles diff --git a/src/p_user.cpp b/src/p_user.cpp index 37ecc1425..ca159bf9a 100644 --- a/src/p_user.cpp +++ b/src/p_user.cpp @@ -1079,125 +1079,6 @@ void APlayerPawn::GiveDeathmatchInventory() } } -//=========================================================================== -// -// APlayerPawn :: FilterCoopRespawnInventory -// -// When respawning in coop, this function is called to walk through the dead -// player's inventory and modify it according to the current game flags so -// that it can be transferred to the new live player. This player currently -// has the default inventory, and the oldplayer has the inventory at the time -// of death. -// -//=========================================================================== - -void APlayerPawn::FilterCoopRespawnInventory (APlayerPawn *oldplayer) -{ - AInventory *item, *next, *defitem; - - // If we're losing everything, this is really simple. - if (dmflags & DF_COOP_LOSE_INVENTORY) - { - oldplayer->DestroyAllInventory(); - return; - } - - if (dmflags & (DF_COOP_LOSE_KEYS | - DF_COOP_LOSE_WEAPONS | - DF_COOP_LOSE_AMMO | - DF_COOP_HALVE_AMMO | - DF_COOP_LOSE_ARMOR | - DF_COOP_LOSE_POWERUPS)) - { - // Walk through the old player's inventory and destroy or modify - // according to dmflags. - for (item = oldplayer->Inventory; item != NULL; item = next) - { - next = item->Inventory; - - // If this item is part of the default inventory, we never want - // to destroy it, although we might want to copy the default - // inventory amount. - defitem = FindInventory (item->GetClass()); - - if ((dmflags & DF_COOP_LOSE_KEYS) && - defitem == NULL && - item->IsKindOf(NAME_Key)) - { - item->Destroy(); - } - else if ((dmflags & DF_COOP_LOSE_WEAPONS) && - defitem == NULL && - item->IsKindOf(NAME_Weapon)) - { - item->Destroy(); - } - else if ((dmflags & DF_COOP_LOSE_ARMOR) && - item->IsKindOf(NAME_Armor)) - { - if (defitem == NULL) - { - item->Destroy(); - } - else if (item->IsKindOf(NAME_BasicArmor)) - { - item->IntVar(NAME_SavePercent) = defitem->IntVar(NAME_SavePercent); - item->Amount = defitem->Amount; - } - else if (item->IsKindOf(NAME_HexenArmor)) - { - double *SlotsTo = (double*)item->ScriptVar(NAME_Slots, nullptr); - double *SlotsFrom = (double*)defitem->ScriptVar(NAME_Slots, nullptr); - memcpy(SlotsTo, SlotsFrom, 4 * sizeof(double)); - } - } - else if ((dmflags & DF_COOP_LOSE_POWERUPS) && - defitem == NULL && - item->IsKindOf(NAME_PowerupGiver)) - { - item->Destroy(); - } - else if ((dmflags & (DF_COOP_LOSE_AMMO | DF_COOP_HALVE_AMMO)) && - item->IsKindOf(NAME_Ammo)) - { - if (defitem == NULL) - { - if (dmflags & DF_COOP_LOSE_AMMO) - { - // Do NOT destroy the ammo, because a weapon might reference it. - item->Amount = 0; - } - else if (item->Amount > 1) - { - item->Amount /= 2; - } - } - else - { - // When set to lose ammo, you get to keep all your starting ammo. - // When set to halve ammo, you won't be left with less than your starting amount. - if (dmflags & DF_COOP_LOSE_AMMO) - { - item->Amount = defitem->Amount; - } - else if (item->Amount > 1) - { - item->Amount = MAX(item->Amount / 2, defitem->Amount); - } - } - } - } - } - - // Now destroy the default inventory this player is holding and move - // over the old player's remaining inventory. - DestroyAllInventory(); - ObtainInventory (oldplayer); - - player->ReadyWeapon = NULL; - PickNewWeapon (NULL); -} - //=========================================================================== // // APlayerPawn :: GetSoundClass @@ -1337,7 +1218,7 @@ void APlayerPawn::GiveDefaultInventory () VMCall(func, params, 1, nullptr, 0); } } - + //=========================================================================== // // A_PlayerScream diff --git a/wadsrc/static/zscript/actor.txt b/wadsrc/static/zscript/actor.txt index 32465b9c3..1ca039d40 100644 --- a/wadsrc/static/zscript/actor.txt +++ b/wadsrc/static/zscript/actor.txt @@ -726,6 +726,7 @@ class Actor : Thinker native native void AddInventory(Inventory inv); native void RemoveInventory(Inventory inv); native void ClearInventory(); + protected native void DestroyAllInventory(); // This is not supposed to be called by user code! native bool GiveInventory(class type, int amount, bool givecheat = false); native bool SetInventory(class itemclass, int amount, bool beyondMax = false); native bool TakeInventory(class itemclass, int amount, bool fromdecorate = false, bool notakeinfinite = false); diff --git a/wadsrc/static/zscript/shared/player.txt b/wadsrc/static/zscript/shared/player.txt index 9747ef1dd..041d1e49d 100644 --- a/wadsrc/static/zscript/shared/player.txt +++ b/wadsrc/static/zscript/shared/player.txt @@ -615,6 +615,113 @@ class PlayerPawn : Actor native } } } + + //=========================================================================== + // + // APlayerPawn :: FilterCoopRespawnInventory + // + // When respawning in coop, this function is called to walk through the dead + // player's inventory and modify it according to the current game flags so + // that it can be transferred to the new live player. This player currently + // has the default inventory, and the oldplayer has the inventory at the time + // of death. + // + //=========================================================================== + + void FilterCoopRespawnInventory (PlayerPawn oldplayer) + { + // If we're losing everything, this is really simple. + if (sv_cooploseinventory) + { + oldplayer.DestroyAllInventory(); + return; + } + + // Walk through the old player's inventory and destroy or modify + // according to dmflags. + Inventory next; + for (Inventory item = oldplayer.Inv; item != NULL; item = next) + { + next = item.Inv; + + // If this item is part of the default inventory, we never want + // to destroy it, although we might want to copy the default + // inventory amount. + let defitem = FindInventory (item.GetClass()); + + if (sv_cooplosekeys && defitem == NULL && item is 'Key') + { + item.Destroy(); + } + else if (sv_cooploseweapons && defitem == NULL && item is 'Weapon') + { + item.Destroy(); + } + else if (sv_cooplosearmor && item is 'Armor') + { + if (defitem == NULL) + { + item.Destroy(); + } + else if (item is 'BasicArmor') + { + BasicArmor(item).SavePercent = BasicArmor(defitem).SavePercent; + item.Amount = defitem.Amount; + } + else if (item is 'HexenArmor') + { + let to = HexenArmor(item); + let from = HexenArmor(defitem); + to.Slots[0] = from.Slots[0]; + to.Slots[1] = from.Slots[1]; + to.Slots[2] = from.Slots[2]; + to.Slots[3] = from.Slots[3]; + } + } + else if (sv_cooplosepowerups && defitem == NULL && item is 'Powerup') + { + item.Destroy(); + } + else if ((sv_cooploseammo || sv_coophalveammo) && item is 'Ammo') + { + if (defitem == NULL) + { + if (sv_cooploseammo) + { + // Do NOT destroy the ammo, because a weapon might reference it. + item.Amount = 0; + } + else if (item.Amount > 1) + { + item.Amount /= 2; + } + } + else + { + // When set to lose ammo, you get to keep all your starting ammo. + // When set to halve ammo, you won't be left with less than your starting amount. + if (sv_cooploseammo) + { + item.Amount = defitem.Amount; + } + else if (item.Amount > 1) + { + item.Amount = MAX(item.Amount / 2, defitem.Amount); + } + } + } + } + + // Now destroy the default inventory this player is holding and move + // over the old player's remaining inventory. + DestroyAllInventory(); + ObtainInventory (oldplayer); + + player.ReadyWeapon = NULL; + PickNewWeapon (NULL); + } + + //---------------------------------------------------------------------------- // // PROC P_CheckFOV