From 652f009181d86975bffef20f6b48474b7461372d Mon Sep 17 00:00:00 2001 From: SoundSSGood <87084363+SoundSSGood@users.noreply.github.com> Date: Fri, 12 Jan 2024 23:57:19 +0200 Subject: [PATCH] arts altar - arts holder --- client/widgets/CArtifactsOfHeroAltar.cpp | 69 +------------------ client/widgets/CArtifactsOfHeroAltar.h | 7 -- client/widgets/markets/CAltarArtifacts.cpp | 26 ++++--- client/widgets/markets/CAltarArtifacts.h | 2 + lib/ArtifactUtils.cpp | 13 ++-- lib/CArtHandler.cpp | 6 +- lib/CArtHandler.h | 3 +- lib/CGameInfoCallback.cpp | 23 +++++-- lib/constants/EntityIdentifiers.h | 5 +- .../CommonConstructors.cpp | 5 ++ lib/mapObjects/CGMarket.cpp | 5 ++ lib/mapObjects/CGMarket.h | 15 ++++ lib/registerTypes/RegisterTypesMapObjects.h | 1 + server/CGameHandler.cpp | 22 ++++-- server/NetPacksServer.cpp | 3 +- 15 files changed, 104 insertions(+), 101 deletions(-) diff --git a/client/widgets/CArtifactsOfHeroAltar.cpp b/client/widgets/CArtifactsOfHeroAltar.cpp index bda990634..c95d232fa 100644 --- a/client/widgets/CArtifactsOfHeroAltar.cpp +++ b/client/widgets/CArtifactsOfHeroAltar.cpp @@ -20,14 +20,12 @@ #include "../../lib/networkPacks/ArtifactLocation.h" CArtifactsOfHeroAltar::CArtifactsOfHeroAltar(const Point & position) - : visibleArtSet(ArtBearer::ArtBearer::HERO) { init( std::bind(&CArtifactsOfHeroBase::clickPrassedArtPlace, this, _1, _2), std::bind(&CArtifactsOfHeroBase::showPopupArtPlace, this, _1, _2), position, std::bind(&CArtifactsOfHeroAltar::scrollBackpack, this, _1)); - pickedArtFromSlot = ArtifactPosition::PRE_FIRST; // The backpack is in the altar window above and to the right for(auto & slot : backpack) @@ -41,80 +39,19 @@ CArtifactsOfHeroAltar::~CArtifactsOfHeroAltar() putBackPickedArtifact(); } -void CArtifactsOfHeroAltar::setHero(const CGHeroInstance * hero) -{ - if(hero) - { - visibleArtSet.artifactsWorn = hero->artifactsWorn; - visibleArtSet.artifactsInBackpack = hero->artifactsInBackpack; - CArtifactsOfHeroBase::setHero(hero); - } -} - -void CArtifactsOfHeroAltar::updateWornSlots() -{ - for(auto place : artWorn) - setSlotData(getArtPlace(place.first), place.first, visibleArtSet); -} - -void CArtifactsOfHeroAltar::updateBackpackSlots() -{ - for(auto artPlace : backpack) - setSlotData(getArtPlace(artPlace->slot), artPlace->slot, visibleArtSet); -} - void CArtifactsOfHeroAltar::scrollBackpack(int offset) { - CArtifactsOfHeroBase::scrollBackpackForArtSet(offset, visibleArtSet); + CArtifactsOfHeroBase::scrollBackpackForArtSet(offset, *curHero); redraw(); } void CArtifactsOfHeroAltar::pickUpArtifact(CArtPlace & artPlace) { - if(const auto art = artPlace.getArt()) - { - pickedArtFromSlot = artPlace.slot; - artPlace.setArtifact(nullptr); - deleteFromVisible(art); - if(ArtifactUtils::isSlotBackpack(pickedArtFromSlot)) - pickedArtFromSlot = curHero->getSlotByInstance(art); - assert(pickedArtFromSlot != ArtifactPosition::PRE_FIRST); - LOCPLINT->cb->swapArtifacts(ArtifactLocation(curHero->id, pickedArtFromSlot), ArtifactLocation(curHero->id, ArtifactPosition::TRANSITION_POS)); - } + LOCPLINT->cb->swapArtifacts(ArtifactLocation(curHero->id, artPlace.slot), + ArtifactLocation(curHero->id, ArtifactPosition::TRANSITION_POS)); } void CArtifactsOfHeroAltar::swapArtifacts(const ArtifactLocation & srcLoc, const ArtifactLocation & dstLoc) { LOCPLINT->cb->swapArtifacts(srcLoc, dstLoc); - const auto pickedArtInst = curHero->getArt(ArtifactPosition::TRANSITION_POS); - assert(pickedArtInst); - visibleArtSet.putArtifact(dstLoc.slot, const_cast(pickedArtInst)); -} - -void CArtifactsOfHeroAltar::pickedArtMoveToAltar(const ArtifactPosition & slot) -{ - if(ArtifactUtils::isSlotBackpack(slot) || ArtifactUtils::isSlotEquipment(slot) || slot == ArtifactPosition::TRANSITION_POS) - { - assert(curHero->getSlot(slot)->getArt()); - LOCPLINT->cb->swapArtifacts(ArtifactLocation(curHero->id, slot), ArtifactLocation(curHero->id, pickedArtFromSlot)); - pickedArtFromSlot = ArtifactPosition::PRE_FIRST; - } -} - -void CArtifactsOfHeroAltar::deleteFromVisible(const CArtifactInstance * artInst) -{ - const auto slot = visibleArtSet.getSlotByInstance(artInst); - visibleArtSet.removeArtifact(slot); - if(ArtifactUtils::isSlotBackpack(slot)) - { - scrollBackpackForArtSet(0, visibleArtSet); - } - else - { - for(const auto & part : artInst->getPartsInfo()) - { - if(part.slot != ArtifactPosition::PRE_FIRST) - getArtPlace(part.slot)->setArtifact(nullptr); - } - } } diff --git a/client/widgets/CArtifactsOfHeroAltar.h b/client/widgets/CArtifactsOfHeroAltar.h index 2dd81d68c..324f905af 100644 --- a/client/widgets/CArtifactsOfHeroAltar.h +++ b/client/widgets/CArtifactsOfHeroAltar.h @@ -17,17 +17,10 @@ class CArtifactsOfHeroAltar : public CArtifactsOfHeroBase { public: std::set artifactsOnAltar; - ArtifactPosition pickedArtFromSlot; - CArtifactFittingSet visibleArtSet; CArtifactsOfHeroAltar(const Point & position); ~CArtifactsOfHeroAltar(); - void setHero(const CGHeroInstance * hero) override; - void updateWornSlots() override; - void updateBackpackSlots() override; void scrollBackpack(int offset) override; void pickUpArtifact(CArtPlace & artPlace); void swapArtifacts(const ArtifactLocation & srcLoc, const ArtifactLocation & dstLoc); - void pickedArtMoveToAltar(const ArtifactPosition & slot); - void deleteFromVisible(const CArtifactInstance * artInst); }; diff --git a/client/widgets/markets/CAltarArtifacts.cpp b/client/widgets/markets/CAltarArtifacts.cpp index 70ba7aa36..44dad492c 100644 --- a/client/widgets/markets/CAltarArtifacts.cpp +++ b/client/widgets/markets/CAltarArtifacts.cpp @@ -31,6 +31,11 @@ CAltarArtifacts::CAltarArtifacts(const IMarket * market, const CGHeroInstance * { OBJECT_CONSTRUCTION_CAPTURING(255 - DISPOSE); + assert(market); + auto altarObj = dynamic_cast(market); + altarId = altarObj->id; + altarArtifacts = altarObj; + deal = std::make_shared(dealButtonPos, AnimationPath::builtin("ALTSACR.DEF"), CGI->generaltexth->zelp[585], [this]() {CAltarArtifacts::makeDeal(); }); labels.emplace_back(std::make_shared(450, 34, FONT_SMALL, ETextAlignment::CENTER, Colors::YELLOW, CGI->generaltexth->allTexts[477])); @@ -117,11 +122,11 @@ void CAltarArtifacts::sacrificeAll() void CAltarArtifacts::sacrificeBackpack() { - while(!arts->visibleArtSet.artifactsInBackpack.empty()) + /*while (!arts->visibleArtSet.artifactsInBackpack.empty()) { if(!putArtOnAltar(nullptr, arts->visibleArtSet.artifactsInBackpack[0].artifact)) break; - }; + };*/ calcExpAltarForHero(); } @@ -192,20 +197,21 @@ bool CAltarArtifacts::putArtOnAltar(std::shared_ptr altarSlot, c void CAltarArtifacts::onSlotClickPressed(const std::shared_ptr & newSlot, std::shared_ptr & hCurSlot) { - const auto pickedArtInst = arts->getPickedArtifact(); - if(pickedArtInst) + if(const auto pickedArtInst = arts->getPickedArtifact()) { - arts->pickedArtMoveToAltar(ArtifactPosition::TRANSITION_POS); - moveArtToAltar(newSlot, pickedArtInst); + if(pickedArtInst->canBePutAt(altarArtifacts)) + { + LOCPLINT->cb->swapArtifacts(ArtifactLocation(arts->getHero()->id, ArtifactPosition::TRANSITION_POS), + ArtifactLocation(altarId, ArtifactPosition::ALTAR)); + moveArtToAltar(newSlot, pickedArtInst); + } } else if(const CArtifactInstance * art = newSlot->getArtInstance()) { - const auto hero = arts->getHero(); - const auto slot = hero->getSlotByInstance(art); + const auto slot = altarArtifacts->getSlotByInstance(art); assert(slot != ArtifactPosition::PRE_FIRST); - LOCPLINT->cb->swapArtifacts(ArtifactLocation(hero->id, slot), + LOCPLINT->cb->swapArtifacts(ArtifactLocation(altarId, slot), ArtifactLocation(hero->id, ArtifactPosition::TRANSITION_POS)); - arts->pickedArtFromSlot = slot; arts->artifactsOnAltar.erase(art); newSlot->setID(-1); newSlot->subtitle.clear(); diff --git a/client/widgets/markets/CAltarArtifacts.h b/client/widgets/markets/CAltarArtifacts.h index 67a99bb85..910e798af 100644 --- a/client/widgets/markets/CAltarArtifacts.h +++ b/client/widgets/markets/CAltarArtifacts.h @@ -25,6 +25,8 @@ public: std::shared_ptr getAOHset() const; private: + ObjectInstanceID altarId; + const CArtifactSet * altarArtifacts; std::shared_ptr selectedArt; std::shared_ptr selectedCost; std::shared_ptr sacrificeBackpackButton; diff --git a/lib/ArtifactUtils.cpp b/lib/ArtifactUtils.cpp index a5005a007..66aafc53e 100644 --- a/lib/ArtifactUtils.cpp +++ b/lib/ArtifactUtils.cpp @@ -151,11 +151,16 @@ DLL_LINKAGE bool ArtifactUtils::isSlotEquipment(const ArtifactPosition & slot) DLL_LINKAGE bool ArtifactUtils::isBackpackFreeSlots(const CArtifactSet * target, const size_t reqSlots) { - const auto backpackCap = VLC->settings()->getInteger(EGameSettings::HEROES_BACKPACK_CAP); - if(backpackCap < 0) - return true; + if(target->bearerType() == ArtBearer::HERO) + { + const auto backpackCap = VLC->settings()->getInteger(EGameSettings::HEROES_BACKPACK_CAP); + if(backpackCap < 0) + return true; + else + return target->artifactsInBackpack.size() + reqSlots <= backpackCap; + } else - return target->artifactsInBackpack.size() + reqSlots <= backpackCap; + return false; } DLL_LINKAGE std::vector ArtifactUtils::assemblyPossibilities( diff --git a/lib/CArtHandler.cpp b/lib/CArtHandler.cpp index b3ed48b6a..e230405dc 100644 --- a/lib/CArtHandler.cpp +++ b/lib/CArtHandler.cpp @@ -181,7 +181,7 @@ bool CArtifact::canBePutAt(const CArtifactSet * artSet, ArtifactPosition slot, b { auto simpleArtCanBePutAt = [this](const CArtifactSet * artSet, ArtifactPosition slot, bool assumeDestRemoved) -> bool { - if(ArtifactUtils::isSlotBackpack(slot)) + if(artSet->bearerType() == ArtBearer::HERO && ArtifactUtils::isSlotBackpack(slot)) { if(isBig() || (!assumeDestRemoved && !ArtifactUtils::isBackpackFreeSlots(artSet))) return false; @@ -258,6 +258,7 @@ CArtifact::CArtifact() possibleSlots[ArtBearer::HERO]; //we want to generate map entry even if it will be empty possibleSlots[ArtBearer::CREATURE]; //we want to generate map entry even if it will be empty possibleSlots[ArtBearer::COMMANDER]; + possibleSlots[ArtBearer::ALTAR].push_back(ArtifactPosition::ALTAR); } //This destructor should be placed here to avoid side effects @@ -906,6 +907,9 @@ const ArtSlotInfo * CArtifactSet::getSlot(const ArtifactPosition & pos) const bool CArtifactSet::isPositionFree(const ArtifactPosition & pos, bool onlyLockCheck) const { + if(bearerType() == ArtBearer::ALTAR) + return artifactsInBackpack.size() < 22; + if(const ArtSlotInfo *s = getSlot(pos)) return (onlyLockCheck || !s->artifact) && !s->locked; diff --git a/lib/CArtHandler.h b/lib/CArtHandler.h index f4c4df8c3..4ea8f5481 100644 --- a/lib/CArtHandler.h +++ b/lib/CArtHandler.h @@ -30,7 +30,8 @@ class JsonSerializeFormat; #define ART_BEARER_LIST \ ART_BEARER(HERO)\ ART_BEARER(CREATURE)\ - ART_BEARER(COMMANDER) + ART_BEARER(COMMANDER)\ + ART_BEARER(ALTAR) namespace ArtBearer { diff --git a/lib/CGameInfoCallback.cpp b/lib/CGameInfoCallback.cpp index 2f40a5ab7..da6977d6e 100644 --- a/lib/CGameInfoCallback.cpp +++ b/lib/CGameInfoCallback.cpp @@ -18,6 +18,7 @@ #include "mapObjects/CGHeroInstance.h" #include "mapObjects/CGTownInstance.h" #include "mapObjects/MiscObjects.h" +#include "mapObjects/CGMarket.h" #include "networkPacks/ArtifactLocation.h" #include "CGeneralTextHandler.h" #include "StartInfo.h" // for StartInfo @@ -970,17 +971,27 @@ const CGObjectInstance * CGameInfoCallback::getObjInstance( ObjectInstanceID oid CArtifactSet * CGameInfoCallback::getArtSet(const ArtifactLocation & loc) const { - auto hero = const_cast(getHero(loc.artHolder)); - if(loc.creature.has_value()) + if(auto hero = const_cast(getHero(loc.artHolder))) { - if(loc.creature.value() == SlotID::COMMANDER_SLOT_PLACEHOLDER) - return hero->commander; + if(loc.creature.has_value()) + { + if(loc.creature.value() == SlotID::COMMANDER_SLOT_PLACEHOLDER) + return hero->commander; + else + return hero->getStackPtr(loc.creature.value()); + } else - return hero->getStackPtr(loc.creature.value()); + { + return hero; + } + } + else if(auto market = dynamic_cast(getObj(loc.artHolder, false))) + { + return const_cast(market); } else { - return hero; + return nullptr; } } diff --git a/lib/constants/EntityIdentifiers.h b/lib/constants/EntityIdentifiers.h index 620cce06b..c83d63bdd 100644 --- a/lib/constants/EntityIdentifiers.h +++ b/lib/constants/EntityIdentifiers.h @@ -610,7 +610,10 @@ public: CREATURE_SLOT = 0, // Commander - COMMANDER1 = 0, COMMANDER2, COMMANDER3, COMMANDER4, COMMANDER5, COMMANDER6 + COMMANDER1 = 0, COMMANDER2, COMMANDER3, COMMANDER4, COMMANDER5, COMMANDER6, + + // Altar + ALTAR = BACKPACK_START }; static_assert(MISC5 < BACKPACK_START, "incorrect number of artifact slots"); diff --git a/lib/mapObjectConstructors/CommonConstructors.cpp b/lib/mapObjectConstructors/CommonConstructors.cpp index 707318292..9864bd5bf 100644 --- a/lib/mapObjectConstructors/CommonConstructors.cpp +++ b/lib/mapObjectConstructors/CommonConstructors.cpp @@ -238,6 +238,11 @@ CGMarket * MarketInstanceConstructor::createObject(IGameCallback * cb) const return new CGUniversity(cb); } } + else if(marketModes.size() == 2) + { + if(vstd::contains(marketModes, EMarketMode::ARTIFACT_EXP)) + return new CGArtifactsAltar(cb); + } return new CGMarket(cb); } diff --git a/lib/mapObjects/CGMarket.cpp b/lib/mapObjects/CGMarket.cpp index 6ba715f1f..dfc072366 100644 --- a/lib/mapObjects/CGMarket.cpp +++ b/lib/mapObjects/CGMarket.cpp @@ -113,4 +113,9 @@ void CGUniversity::onHeroVisit(const CGHeroInstance * h) const cb->showObjectWindow(this, EOpenWindowMode::UNIVERSITY_WINDOW, h, true); } +ArtBearer::ArtBearer CGArtifactsAltar::bearerType() const +{ + return ArtBearer::ALTAR; +} + VCMI_LIB_NAMESPACE_END diff --git a/lib/mapObjects/CGMarket.h b/lib/mapObjects/CGMarket.h index eb41e487e..c0a589f3b 100644 --- a/lib/mapObjects/CGMarket.h +++ b/lib/mapObjects/CGMarket.h @@ -11,6 +11,7 @@ #include "CGObjectInstance.h" #include "IMarket.h" +#include "../CArtHandler.h" VCMI_LIB_NAMESPACE_BEGIN @@ -80,4 +81,18 @@ public: } }; +class DLL_LINKAGE CGArtifactsAltar : public CGMarket, public CArtifactSet +{ +public: + using CGMarket::CGMarket; + + ArtBearer::ArtBearer bearerType() const override; + + template void serialize(Handler & h) + { + h & static_cast(*this); + h & static_cast(*this); + } +}; + VCMI_LIB_NAMESPACE_END diff --git a/lib/registerTypes/RegisterTypesMapObjects.h b/lib/registerTypes/RegisterTypesMapObjects.h index 73f87e5e3..ddaac348a 100644 --- a/lib/registerTypes/RegisterTypesMapObjects.h +++ b/lib/registerTypes/RegisterTypesMapObjects.h @@ -54,6 +54,7 @@ void registerTypesMapObjects(Serializer &s) s.template registerType(); s.template registerType(); s.template registerType(); + s.template registerType(); s.template registerType(); s.template registerType(); s.template registerType(); s.template registerType(); diff --git a/server/CGameHandler.cpp b/server/CGameHandler.cpp index 29df932f5..e1cc9a62e 100644 --- a/server/CGameHandler.cpp +++ b/server/CGameHandler.cpp @@ -2713,17 +2713,17 @@ bool CGameHandler::moveArtifact(const ArtifactLocation & src, const ArtifactLoca COMPLAIN_RET("That heroes cannot make any exchange!"); const auto srcArtifact = srcArtSet->getArt(src.slot); - const auto dstArtifact = dstArtSet->getArt(dst.slot); + const bool isDstSlotOccupied = dstArtSet->bearerType() == ArtBearer::ALTAR ? false : dstArtSet->getArt(dst.slot) != nullptr; const bool isDstSlotBackpack = dstArtSet->bearerType() == ArtBearer::HERO ? ArtifactUtils::isSlotBackpack(dst.slot) : false; if(srcArtifact == nullptr) COMPLAIN_RET("No artifact to move!"); - if(dstArtifact && getHero(src.artHolder)->getOwner() != getHero(dst.artHolder)->getOwner() && !isDstSlotBackpack) + if(isDstSlotOccupied && getOwner(src.artHolder) != getOwner(dst.artHolder) && !isDstSlotBackpack) COMPLAIN_RET("Can't touch artifact on hero of another player!"); // Check if src/dest slots are appropriate for the artifacts exchanged. // Moving to the backpack is always allowed. - if((!srcArtifact || !isDstSlotBackpack) && srcArtifact && !srcArtifact->canBePutAt(dstArtSet, dst.slot, true)) + if((!srcArtifact || !isDstSlotBackpack) && !srcArtifact->canBePutAt(dstArtSet, dst.slot, true)) COMPLAIN_RET("Cannot move artifact!"); auto srcSlotInfo = srcArtSet->getSlot(src.slot); @@ -2749,7 +2749,7 @@ bool CGameHandler::moveArtifact(const ArtifactLocation & src, const ArtifactLoca ma.dstCreature = dst.creature; // Check if dst slot is occupied - if(!isDstSlotBackpack && dstArtifact) + if(!isDstSlotBackpack && isDstSlotOccupied) { // Previous artifact must be removed ma.artsPack1.push_back(BulkMoveArtifacts::LinkedSlots(dstSlot, src.slot)); @@ -3432,6 +3432,20 @@ bool CGameHandler::isAllowedExchange(ObjectInstanceID id1, ObjectInstanceID id2) return true; } + if(o1->ID == Obj::ALTAR_OF_SACRIFICE) + { + const auto visitingHero = getVisitingHero(o1); + const auto thisHero = static_cast(o2); + if(visitingHero == thisHero) + return true; + } + if(o2->ID == Obj::ALTAR_OF_SACRIFICE) + { + const auto visitingHero = getVisitingHero(o2); + const auto thisHero = static_cast(o1); + if(visitingHero == thisHero) + return true; + } if (o1->ID == Obj::HERO && o2->ID == Obj::HERO) { const CGHeroInstance *h1 = static_cast(o1); diff --git a/server/NetPacksServer.cpp b/server/NetPacksServer.cpp index ec941cc78..2301208e9 100644 --- a/server/NetPacksServer.cpp +++ b/server/NetPacksServer.cpp @@ -134,7 +134,8 @@ void ApplyGhNetPackVisitor::visitGarrisonHeroSwap(GarrisonHeroSwap & pack) void ApplyGhNetPackVisitor::visitExchangeArtifacts(ExchangeArtifacts & pack) { - gh.throwIfWrongPlayer(&pack, gh.getOwner(pack.src.artHolder)); //second hero can be ally + if(gh.getHero(pack.src.artHolder)) + gh.throwIfWrongPlayer(&pack, gh.getOwner(pack.src.artHolder)); //second hero can be ally result = gh.moveArtifact(pack.src, pack.dst); }