From 363e461c3e8cec1c73ab8843ce5534846b78dde7 Mon Sep 17 00:00:00 2001 From: SoundSSGood <87084363+SoundSSGood@users.noreply.github.com> Date: Sun, 6 Nov 2022 23:29:22 +0200 Subject: [PATCH 01/31] ArtifactUtils and CArtifactFittingSet class --- lib/CArtHandler.cpp | 63 +++++++++++++++++++++++++++++++++++++ lib/CArtHandler.h | 22 +++++++++++++ lib/NetPacks.h | 75 +++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 160 insertions(+) diff --git a/lib/CArtHandler.cpp b/lib/CArtHandler.cpp index ee57823f9..1d0f9cca4 100644 --- a/lib/CArtHandler.cpp +++ b/lib/CArtHandler.cpp @@ -1457,4 +1457,67 @@ void CArtifactSet::serializeJsonSlot(JsonSerializeFormat & handler, const Artifa } } +CArtifactFittingSet::CArtifactFittingSet(ArtBearer::ArtBearer Bearer) +{ + this->Bearer = Bearer; +} + +void CArtifactFittingSet::setNewArtSlot(ArtifactPosition slot, CArtifactInstance * art, bool locked) +{ + ArtSlotInfo & asi = retrieveNewArtSlot(slot); + asi.artifact = art; + asi.locked = locked; +} + +void CArtifactFittingSet::putArtifact(ArtifactPosition pos, CArtifactInstance * art) +{ + if (art->canBeDisassembled() && (pos < ArtifactPosition::AFTER_LAST)) + { + for (auto part : dynamic_cast(art)->constituentsInfo) + { + // For the ArtFittingSet is no needed to do figureMainConstituent, just lock slots + this->setNewArtSlot(part.art->firstAvailableSlot(this), part.art, true); + } + } + else + { + this->setNewArtSlot(pos, art, false); + } +} + +ArtBearer::ArtBearer CArtifactFittingSet::bearerType() const +{ + return this->Bearer; +} + +DLL_LINKAGE ArtifactPosition ArtifactUtils::getArtifactDstPosition(const CArtifactInstance * artifact, + const CArtifactSet * target, ArtBearer::ArtBearer barer) +{ + for (auto slot : artifact->artType->possibleSlots.at(barer)) + { + auto existingArtifact = target->getArt(slot); + auto existingArtInfo = target->getSlot(slot); + + if (!existingArtifact + && (!existingArtInfo || !existingArtInfo->locked) + && artifact->canBePutAt(target, slot)) + { + return slot; + } + } + return ArtifactPosition(GameConstants::BACKPACK_START); +} + +DLL_LINKAGE std::vector ArtifactUtils::unmovablePositions() +{ + return { ArtifactPosition::SPELLBOOK, ArtifactPosition::MACH4 }; +} + +DLL_LINKAGE bool ArtifactUtils::isArtRemovable(const std::pair & slot) +{ + return slot.second.artifact + && !slot.second.locked + && !vstd::contains(unmovablePositions(), slot.first); +} + VCMI_LIB_NAMESPACE_END diff --git a/lib/CArtHandler.h b/lib/CArtHandler.h index a933b70a3..d30bd81f8 100644 --- a/lib/CArtHandler.h +++ b/lib/CArtHandler.h @@ -363,4 +363,26 @@ private: void serializeJsonSlot(JsonSerializeFormat & handler, const ArtifactPosition & slot, CMap * map);//normal slots }; +// Used to try on artifacts before the claimed changes have been applied +class DLL_LINKAGE CArtifactFittingSet : public CArtifactSet +{ +public: + CArtifactFittingSet(ArtBearer::ArtBearer Bearer); + void setNewArtSlot(ArtifactPosition slot, CArtifactInstance * art, bool locked); + void putArtifact(ArtifactPosition pos, CArtifactInstance * art) override; + ArtBearer::ArtBearer bearerType() const override; + +protected: + ArtBearer::ArtBearer Bearer; +}; + +namespace ArtifactUtils +{ + // Calculates where an artifact gets placed when it gets transferred from one hero to another. + DLL_LINKAGE ArtifactPosition getArtifactDstPosition(const CArtifactInstance * artifact, const CArtifactSet * target, + ArtBearer::ArtBearer barer); + DLL_LINKAGE std::vector unmovablePositions(); // TODO: Make this constexpr when the toolset is upgraded + DLL_LINKAGE bool isArtRemovable(const std::pair & slot); +} + VCMI_LIB_NAMESPACE_END diff --git a/lib/NetPacks.h b/lib/NetPacks.h index 171ebdace..e1abab1da 100644 --- a/lib/NetPacks.h +++ b/lib/NetPacks.h @@ -1006,6 +1006,60 @@ struct MoveArtifact : CArtifactOperationPack } }; +struct BulkMoveArtifacts : CArtifactOperationPack +{ + struct HeroArtsToMove + { + struct LinkedSlots + { + ArtifactPosition srcPos; + ArtifactPosition dstPos; + + LinkedSlots() {} + LinkedSlots(ArtifactPosition srcPos, ArtifactPosition dstPos) + : srcPos(srcPos), dstPos(dstPos) {} + + template void serialize(Handler & h, const int version) + { + h & srcPos; + h & dstPos; + } + }; + + TArtHolder srcArtHolder; + TArtHolder dstArtHolder; + std::vector slots; + + CArtifactSet * getSrcHolderArtSet(); + CArtifactSet * getDstHolderArtSet(); + template void serialize(Handler & h, const int version) + { + h & srcArtHolder; + h & dstArtHolder; + h & slots; + } + }; + + BulkMoveArtifacts() {} + BulkMoveArtifacts(TArtHolder srcArtHolder, TArtHolder dstArtHolder) + { + artsPack0.srcArtHolder = srcArtHolder; + artsPack0.dstArtHolder = dstArtHolder; + } + + void applyCl(CClient * cl); + DLL_LINKAGE void applyGs(CGameState * gs); + + HeroArtsToMove artsPack0; + // If the artsPack1 is present then make swap + boost::optional artsPack1; + template void serialize(Handler & h, const int version) + { + h & artsPack0; + h & artsPack1; + } +}; + struct AssembledArtifact : CArtifactOperationPack { ArtifactLocation al; //where assembly will be put @@ -2197,6 +2251,27 @@ struct ExchangeArtifacts : public CPackForServer } }; +struct BulkExchangeArtifacts : public CPackForServer +{ + ObjectInstanceID srcHero; + ObjectInstanceID dstHero; + bool swap; + + BulkExchangeArtifacts() = default; + BulkExchangeArtifacts(ObjectInstanceID srcHero, ObjectInstanceID dstHero, bool swap) + : srcHero(srcHero), dstHero(dstHero), swap(swap) + {} + + bool applyGh(CGameHandler * gh); + template void serialize(Handler & h, const int version) + { + h & static_cast(*this); + h & srcHero; + h & dstHero; + h & swap; + } +}; + struct AssembleArtifacts : public CPackForServer { AssembleArtifacts():assemble(false){}; From d0895e30ef1bccc969d7454e9f71b0232544504f Mon Sep 17 00:00:00 2001 From: SoundSSGood <87084363+SoundSSGood@users.noreply.github.com> Date: Sun, 6 Nov 2022 23:41:29 +0200 Subject: [PATCH 02/31] callback functions and cleaning up unused code --- CCallback.cpp | 14 ++++ CCallback.h | 7 ++ client/windows/GUIClasses.cpp | 114 ++---------------------------- client/windows/GUIClasses.h | 2 - lib/registerTypes/RegisterTypes.h | 2 + 5 files changed, 28 insertions(+), 111 deletions(-) diff --git a/CCallback.cpp b/CCallback.cpp index b9af639f7..36936a0b8 100644 --- a/CCallback.cpp +++ b/CCallback.cpp @@ -181,6 +181,20 @@ bool CCallback::assembleArtifacts (const CGHeroInstance * hero, ArtifactPosition return true; } +bool CCallback::bulkMoveArtifacts(ObjectInstanceID srcHero, ObjectInstanceID dstHero) +{ + BulkExchangeArtifacts bma(srcHero, dstHero, false); + sendRequest(&bma); + return true; +} + +bool CCallback::bulkSwapArtifacts(ObjectInstanceID leftHero, ObjectInstanceID rightHero) +{ + BulkExchangeArtifacts bma(leftHero, rightHero, true); + sendRequest(&bma); + return true; +} + bool CCallback::buildBuilding(const CGTownInstance *town, BuildingID buildingID) { if(town->tempOwner!=player) diff --git a/CCallback.h b/CCallback.h index 49e1a9970..b9b3dcab4 100644 --- a/CCallback.h +++ b/CCallback.h @@ -94,6 +94,11 @@ public: virtual int bulkSplitStack(ObjectInstanceID armyId, SlotID srcSlot, int howMany = 1) = 0; virtual int bulkSmartSplitStack(ObjectInstanceID armyId, SlotID srcSlot) = 0; virtual int bulkMergeStacks(ObjectInstanceID armyId, SlotID srcSlot) = 0; + + + // Moves all artifacts from one hero to another + virtual bool bulkMoveArtifacts(ObjectInstanceID srcHero, ObjectInstanceID dstHero) = 0; + virtual bool bulkSwapArtifacts(ObjectInstanceID leftHero, ObjectInstanceID rightHero) = 0; }; class CBattleCallback : public IBattleCallback, public CPlayerBattleCallback @@ -151,6 +156,8 @@ public: bool dismissHero(const CGHeroInstance * hero) override; bool swapArtifacts(const ArtifactLocation &l1, const ArtifactLocation &l2) override; bool assembleArtifacts(const CGHeroInstance * hero, ArtifactPosition artifactSlot, bool assemble, ArtifactID assembleTo) override; + bool bulkMoveArtifacts(ObjectInstanceID srcHero, ObjectInstanceID dstHero) override; + bool bulkSwapArtifacts(ObjectInstanceID leftHero, ObjectInstanceID rightHero) override; bool buildBuilding(const CGTownInstance *town, BuildingID buildingID) override; void recruitCreatures(const CGDwelling * obj, const CArmedInstance * dst, CreatureID ID, ui32 amount, si32 level=-1) override; bool dismissCreature(const CArmedInstance *obj, SlotID stackPos) override; diff --git a/client/windows/GUIClasses.cpp b/client/windows/GUIClasses.cpp index 4bce0f2d0..2b9d136e3 100644 --- a/client/windows/GUIClasses.cpp +++ b/client/windows/GUIClasses.cpp @@ -872,41 +872,6 @@ std::function CExchangeController::onMoveArmyToRight() return [&]() { moveArmy(true); }; } -void CExchangeController::swapArtifacts(ArtifactPosition slot) -{ - bool leftHasArt = !left->isPositionFree(slot); - bool rightHasArt = !right->isPositionFree(slot); - - if(!leftHasArt && !rightHasArt) - return; - - ArtifactLocation leftLocation = ArtifactLocation(left, slot); - ArtifactLocation rightLocation = ArtifactLocation(right, slot); - - if(leftHasArt && !left->artifactsWorn.at(slot).artifact->canBePutAt(rightLocation, true)) - return; - - if(rightHasArt && !right->artifactsWorn.at(slot).artifact->canBePutAt(leftLocation, true)) - return; - - if(leftHasArt) - { - if(rightHasArt) - { - auto art = right->getArt(slot); - - cb->swapArtifacts(leftLocation, rightLocation); - cb->swapArtifacts(ArtifactLocation(right, right->getArtPos(art)), leftLocation); - } - else - cb->swapArtifacts(leftLocation, rightLocation); - } - else - { - cb->swapArtifacts(rightLocation, leftLocation); - } -} - std::vector getBackpackArts(const CGHeroInstance * hero) { std::vector result; @@ -955,56 +920,13 @@ std::vector CExchangeController::moveCompositeArtsToBackpack() return artPositions; } -void CExchangeController::swapArtifacts() -{ - for(int i = ArtifactPosition::HEAD; i < ArtifactPosition::AFTER_LAST; i++) - { - if(vstd::contains(unmovablePositions, i)) - continue; - - swapArtifacts(ArtifactPosition(i)); - } - - auto leftHeroBackpack = getBackpackArts(left); - auto rightHeroBackpack = getBackpackArts(right); - - for(auto leftArt : leftHeroBackpack) - { - cb->swapArtifacts( - ArtifactLocation(left, left->getArtPos(leftArt)), - ArtifactLocation(right, ArtifactPosition(GameConstants::BACKPACK_START))); - } - - for(auto rightArt : rightHeroBackpack) - { - cb->swapArtifacts( - ArtifactLocation(right, right->getArtPos(rightArt)), - ArtifactLocation(left, ArtifactPosition(GameConstants::BACKPACK_START))); - } -} - std::function CExchangeController::onSwapArtifacts() { return [&]() { GsThread::run([=] { - // it is not possible directly exchange composite artifacts like Angelic Alliance and Armor of Damned - auto compositeArtLocations = moveCompositeArtsToBackpack(); - - swapArtifacts(); - - for(HeroArtifact artLocation : compositeArtLocations) - { - auto target = artLocation.hero == left ? right : left; - auto currentPos = target->getArtPos(artLocation.artifact); - - cb->swapArtifacts( - ArtifactLocation(target, currentPos), - ArtifactLocation(target, artLocation.artPosition)); - } - - view->redraw(); + cb->bulkSwapArtifacts(left->id, right->id); }); }; } @@ -1161,19 +1083,7 @@ void CExchangeController::moveArtifacts(bool leftToRight) GsThread::run([=] { - while(vstd::contains_if(source->artifactsWorn, isArtRemovable)) - { - auto art = std::find_if(source->artifactsWorn.begin(), source->artifactsWorn.end(), isArtRemovable); - - moveArtifact(source, target, art->first); - } - - while(!source->artifactsInBackpack.empty()) - { - moveArtifact(source, target, source->getArtPos(source->artifactsInBackpack.begin()->artifact)); - } - - view->redraw(); + cb->bulkMoveArtifacts(source->id, target->id); }); } @@ -1184,24 +1094,10 @@ void CExchangeController::moveArtifact( { auto artifact = source->getArt(srcPosition); auto srcLocation = ArtifactLocation(source, srcPosition); + auto dstLocation = ArtifactLocation(target, + ArtifactUtils::getArtifactDstPosition(source->getArt(srcPosition), target, target->bearerType())); - for(auto slot : artifact->artType->possibleSlots.at(target->bearerType())) - { - auto existingArtifact = target->getArt(slot); - auto existingArtInfo = target->getSlot(slot); - ArtifactLocation destLocation(target, slot); - - if(!existingArtifact - && (!existingArtInfo || !existingArtInfo->locked) - && artifact->canBePutAt(destLocation)) - { - cb->swapArtifacts(srcLocation, ArtifactLocation(target, slot)); - - return; - } - } - - cb->swapArtifacts(srcLocation, ArtifactLocation(target, ArtifactPosition(GameConstants::BACKPACK_START))); + cb->swapArtifacts(srcLocation, dstLocation); } CExchangeWindow::CExchangeWindow(ObjectInstanceID hero1, ObjectInstanceID hero2, QueryID queryID) diff --git a/client/windows/GUIClasses.h b/client/windows/GUIClasses.h index a56f87d35..d79029c92 100644 --- a/client/windows/GUIClasses.h +++ b/client/windows/GUIClasses.h @@ -324,9 +324,7 @@ private: void moveArtifacts(bool leftToRight); void moveArtifact(const CGHeroInstance * source, const CGHeroInstance * target, ArtifactPosition srcPosition); void moveStack(const CGHeroInstance * source, const CGHeroInstance * target, SlotID sourceSlot); - void swapArtifacts(ArtifactPosition artPosition); std::vector moveCompositeArtsToBackpack(); - void swapArtifacts(); }; class CExchangeWindow : public CStatusbarWindow, public CGarrisonHolder, public CWindowWithArtifacts diff --git a/lib/registerTypes/RegisterTypes.h b/lib/registerTypes/RegisterTypes.h index 519643e33..d2c67e8c1 100644 --- a/lib/registerTypes/RegisterTypes.h +++ b/lib/registerTypes/RegisterTypes.h @@ -319,6 +319,7 @@ void registerTypesClientPacks2(Serializer &s) s.template registerType(); s.template registerType(); s.template registerType(); + s.template registerType(); s.template registerType(); s.template registerType(); @@ -358,6 +359,7 @@ void registerTypesServerPacks(Serializer &s) s.template registerType(); s.template registerType(); s.template registerType(); + s.template registerType(); } template From 95ab343116d72d8dca5bc924d6ddffe10df61bca Mon Sep 17 00:00:00 2001 From: SoundSSGood <87084363+SoundSSGood@users.noreply.github.com> Date: Sun, 6 Nov 2022 23:54:50 +0200 Subject: [PATCH 03/31] Net Packs BulkMoveArtifacts structure and BulkMoveArtifacts::applyCl --- client/CPlayerInterface.cpp | 1 + client/NetPacksClient.cpp | 22 +++++++ lib/CArtHandler.h | 3 +- lib/NetPacks.h | 5 +- lib/NetPacksLib.cpp | 128 +++++++++++++++++++++++++++++++----- server/NetPacksServer.cpp | 10 +++ 6 files changed, 152 insertions(+), 17 deletions(-) diff --git a/client/CPlayerInterface.cpp b/client/CPlayerInterface.cpp index af40aa43f..ebfc72cdf 100644 --- a/client/CPlayerInterface.cpp +++ b/client/CPlayerInterface.cpp @@ -2591,6 +2591,7 @@ void CPlayerInterface::artifactMoved(const ArtifactLocation &src, const Artifact if (artWin) artWin->artifactMoved(src, dst); } + GH.listInt.back()->redraw(); askToAssembleArtifact(dst); } diff --git a/client/NetPacksClient.cpp b/client/NetPacksClient.cpp index d44434b18..c2f297deb 100644 --- a/client/NetPacksClient.cpp +++ b/client/NetPacksClient.cpp @@ -279,6 +279,28 @@ void MoveArtifact::applyCl(CClient *cl) callInterfaceIfPresent(cl, dst.owningPlayer(), &IGameEventsReceiver::artifactMoved, src, dst); } +void BulkMoveArtifacts::applyCl(CClient * cl) +{ + auto & movingArts = artsPack0; + for (auto & slotToMove : movingArts.slots) + { + auto srcLoc = ArtifactLocation(movingArts.srcArtHolder, slotToMove.srcPos); + auto dstLoc = ArtifactLocation(movingArts.dstArtHolder, slotToMove.dstPos); + MoveArtifact(&srcLoc, &dstLoc).applyCl(cl); + } + + if (artsPack1.has_value()) + { + movingArts = artsPack1.value(); + for (auto & slotToMove : movingArts.slots) + { + auto srcLoc = ArtifactLocation(movingArts.srcArtHolder, slotToMove.srcPos); + auto dstLoc = ArtifactLocation(movingArts.dstArtHolder, slotToMove.dstPos); + MoveArtifact(&srcLoc, &dstLoc).applyCl(cl); + } + } +} + void AssembledArtifact::applyCl(CClient *cl) { callInterfaceIfPresent(cl, al.owningPlayer(), &IGameEventsReceiver::artifactAssembled, al); diff --git a/lib/CArtHandler.h b/lib/CArtHandler.h index d30bd81f8..65f1b76ce 100644 --- a/lib/CArtHandler.h +++ b/lib/CArtHandler.h @@ -303,8 +303,9 @@ struct DLL_LINKAGE ArtSlotInfo ui8 locked; //if locked, then artifact points to the combined artifact ArtSlotInfo() : locked(false) {} + const CArtifactInstance * getArt() const; - template void serialize(Handler &h, const int version) + template void serialize(Handler & h, const int version) { h & artifact; h & locked; diff --git a/lib/NetPacks.h b/lib/NetPacks.h index e1abab1da..0805ea3dc 100644 --- a/lib/NetPacks.h +++ b/lib/NetPacks.h @@ -994,12 +994,15 @@ struct EraseArtifact : CArtifactOperationPack struct MoveArtifact : CArtifactOperationPack { + MoveArtifact() {} + MoveArtifact(ArtifactLocation * src, ArtifactLocation * dst) + : src(*src), dst(*dst) {} ArtifactLocation src, dst; void applyCl(CClient *cl); DLL_LINKAGE void applyGs(CGameState *gs); - template void serialize(Handler &h, const int version) + template void serialize(Handler & h, const int version) { h & src; h & dst; diff --git a/lib/NetPacksLib.cpp b/lib/NetPacksLib.cpp index 6339d77ee..ffc5a8612 100644 --- a/lib/NetPacksLib.cpp +++ b/lib/NetPacksLib.cpp @@ -845,18 +845,11 @@ DLL_LINKAGE CBonusSystemNode *ArtifactLocation::getHolderNode() DLL_LINKAGE const CArtifactInstance *ArtifactLocation::getArt() const { - const ArtSlotInfo *s = getSlot(); - if(s && s->artifact) - { - if(!s->locked) - return s->artifact; - else - { - logNetwork->warn("ArtifactLocation::getArt: This location is locked!"); - return nullptr; - } - } - return nullptr; + auto s = getSlot(); + if (s) + return s->getArt(); + else + return nullptr; } DLL_LINKAGE const CArtifactSet * ArtifactLocation::getHolderArtSet() const @@ -1093,13 +1086,13 @@ DLL_LINKAGE void EraseArtifact::applyGs(CGameState *gs) al.removeArtifact(); } -DLL_LINKAGE void MoveArtifact::applyGs(CGameState *gs) +DLL_LINKAGE void MoveArtifact::applyGs(CGameState * gs) { - CArtifactInstance *a = src.getArt(); + CArtifactInstance * art = src.getArt(); if(dst.slot < GameConstants::BACKPACK_START) assert(!dst.getArt()); - a->move(src, dst); + art->move(src, dst); //TODO what'll happen if Titan's thunder is equipped by pickin git up or the start of game? if (a->artType->id == ArtifactID::TITANS_THUNDER && dst.slot == ArtifactPosition::RIGHT_HAND) //Titan's Thunder creates new spellbook on equip @@ -1114,6 +1107,86 @@ DLL_LINKAGE void MoveArtifact::applyGs(CGameState *gs) } } +DLL_LINKAGE void BulkMoveArtifacts::applyGs(CGameState * gs) +{ + int numBackpackArtifactsMoved = 0; + if (artsPack1.has_value()) + { + // Swap + auto & leftRightPack = artsPack0; + auto & rightLeftPack = artsPack1.value(); + auto leftSet = leftRightPack.getSrcHolderArtSet(); + auto rightSet = leftRightPack.getDstHolderArtSet(); + CArtifactFittingSet ArtFittingSet(leftSet->bearerType()); + std::vector> unmovableArtsLeftHero, unmovableArtsRightHero; + + // Keep unmovable artifacts separately until the swap + for (auto artPos : ArtifactUtils::unmovablePositions()) + { + auto slotInfo = leftSet->getSlot(artPos); + if (slotInfo) + { + unmovableArtsLeftHero.push_back(std::make_pair(artPos, *slotInfo)); + leftSet->eraseArtSlot(artPos); + } + + slotInfo = rightSet->getSlot(artPos); + if (slotInfo) + { + unmovableArtsRightHero.push_back(std::make_pair(artPos, *slotInfo)); + rightSet->eraseArtSlot(artPos); + } + } + + ArtFittingSet.artifactsWorn = rightSet->artifactsWorn; + ArtFittingSet.artifactsInBackpack = rightSet->artifactsInBackpack; + rightSet->artifactsWorn = leftSet->artifactsWorn; + rightSet->artifactsInBackpack = leftSet->artifactsInBackpack; + leftSet->artifactsWorn = ArtFittingSet.artifactsWorn; + leftSet->artifactsInBackpack = ArtFittingSet.artifactsInBackpack; + + // Return non movable artifacts to their place after the swap + for (auto & art : unmovableArtsLeftHero) + { + leftSet->putArtifact(art.first, art.second.artifact); + } + for (auto & art : unmovableArtsRightHero) + { + rightSet->putArtifact(art.first, art.second.artifact); + } + } + else + { + // Move + auto & artsPack = artsPack0; + for (auto & slot : artsPack.slots) + { + // When an object gets removed from the backpack, the backpack shrinks + // so all the following indices will be affected. Thus, we need to update + // the subsequent artifact slots to account for that + if (slot.srcPos >= GameConstants::BACKPACK_START) + { + slot.srcPos = ArtifactPosition(slot.srcPos.num - numBackpackArtifactsMoved); + } + auto srcSlotInfo = artsPack.getSrcHolderArtSet()->getSlot(slot.srcPos); + auto dstSlotInfo = artsPack.getDstHolderArtSet()->getSlot(slot.dstPos); + + if (slot.dstPos < GameConstants::BACKPACK_START) + assert(!dstSlotInfo->getArt()); + assert(srcSlotInfo); + + auto art = srcSlotInfo->getArt(); + const_cast(art)->move( + ArtifactLocation(artsPack.srcArtHolder, slot.srcPos), ArtifactLocation(artsPack.dstArtHolder, slot.dstPos)); + + if (slot.srcPos >= GameConstants::BACKPACK_START) + { + numBackpackArtifactsMoved++; + } + } + } +} + DLL_LINKAGE void AssembledArtifact::applyGs(CGameState *gs) { CArtifactSet *artSet = al.getHolderArtSet(); @@ -1712,4 +1785,29 @@ DLL_LINKAGE void EntitiesChanged::applyGs(CGameState * gs) gs->updateEntity(change.metatype, change.entityIndex, change.data); } +const CArtifactInstance * ArtSlotInfo::getArt() const +{ + if (artifact) + { + if (!locked) + return artifact; + else + { + logNetwork->warn("ArtifactLocation::getArt: This location is locked!"); + return nullptr; + } + } + return nullptr; +} + +CArtifactSet * BulkMoveArtifacts::HeroArtsToMove::getSrcHolderArtSet() +{ + return boost::apply_visitor(GetBase(), srcArtHolder); +} + +CArtifactSet * BulkMoveArtifacts::HeroArtsToMove::getDstHolderArtSet() +{ + return boost::apply_visitor(GetBase(), dstArtHolder); +} + VCMI_LIB_NAMESPACE_END diff --git a/server/NetPacksServer.cpp b/server/NetPacksServer.cpp index 907a0e470..122a100cf 100644 --- a/server/NetPacksServer.cpp +++ b/server/NetPacksServer.cpp @@ -180,6 +180,16 @@ bool ExchangeArtifacts::applyGh(CGameHandler * gh) return gh->moveArtifact(src, dst); } +bool BulkExchangeArtifacts::applyGh(CGameHandler * gh) +{ + const CGHeroInstance * pSrcHero = gh->getHero(srcHero); + throwOnWrongPlayer(gh, pSrcHero->getOwner()); + if (swap) + return gh->bulkSwapArtifacts(srcHero, dstHero); + else + return gh->bulkMoveArtifacts(srcHero, dstHero); +} + bool AssembleArtifacts::applyGh(CGameHandler * gh) { throwOnWrongOwner(gh, heroID); From 0f391e19d57587bd8b9a71ba2789e659f48abbe7 Mon Sep 17 00:00:00 2001 From: SoundSSGood <87084363+SoundSSGood@users.noreply.github.com> Date: Sun, 6 Nov 2022 23:59:30 +0200 Subject: [PATCH 04/31] server side funcs --- server/CGameHandler.cpp | 93 +++++++++++++++++++++++++++++++++++++++-- server/CGameHandler.h | 3 ++ 2 files changed, 93 insertions(+), 3 deletions(-) diff --git a/server/CGameHandler.cpp b/server/CGameHandler.cpp index a4f8dedad..46b50dee9 100644 --- a/server/CGameHandler.cpp +++ b/server/CGameHandler.cpp @@ -3917,9 +3917,96 @@ bool CGameHandler::moveArtifact(const ArtifactLocation &al1, const ArtifactLocat (si32)dst.getHolderArtSet()->artifactsInBackpack.size() + GameConstants::BACKPACK_START))); } - MoveArtifact ma; - ma.src = src; - ma.dst = dst; + MoveArtifact ma(&src, &dst); + sendAndApply(&ma); + return true; +} + +bool CGameHandler::bulkMoveArtifacts(ObjectInstanceID srcHero, ObjectInstanceID dstHero) +{ + // Make sure exchange is even possible between the two heroes. + if (!isAllowedExchange(srcHero, dstHero)) + COMPLAIN_RET("That heroes cannot make any exchange!"); + + auto psrcHero = getHero(srcHero); + auto pdstHero = getHero(dstHero); + BulkMoveArtifacts ma(static_cast>(psrcHero), + static_cast>(pdstHero)); + auto slots = &ma.artsPack0.slots; + + // Temporary fitting set for artifacts. Used to select available slots before sending data. + CArtifactFittingSet ArtFittingSet(pdstHero->bearerType()); + ArtFittingSet.artifactsInBackpack = pdstHero->artifactsInBackpack; + ArtFittingSet.artifactsWorn = pdstHero->artifactsWorn; + + // Move over artifacts that are worn + for (auto & artInfo : psrcHero->artifactsWorn) + { + if (ArtifactUtils::isArtRemovable(artInfo)) + { + auto artifact = psrcHero->getArt(artInfo.first); + auto dstSlot = ArtifactUtils::getArtifactDstPosition(artifact, &ArtFittingSet, pdstHero->bearerType()); + ArtFittingSet.putArtifact(dstSlot, + static_cast>(psrcHero->getArt(artInfo.first))); + slots->push_back(BulkMoveArtifacts::HeroArtsToMove::LinkedSlots(artInfo.first, dstSlot)); + } + } + // Move over artifacts that are in backpack + for (auto & slotInfo : psrcHero->artifactsInBackpack) + { + auto artifact = psrcHero->getArt(psrcHero->getArtPos(slotInfo.artifact)); + auto dstSlot = ArtifactUtils::getArtifactDstPosition(artifact, &ArtFittingSet, pdstHero->bearerType()); + ArtFittingSet.putArtifact(dstSlot, static_cast>(slotInfo.artifact)); + slots->push_back(BulkMoveArtifacts::HeroArtsToMove::LinkedSlots(psrcHero->getArtPos(slotInfo.artifact), dstSlot)); + } + sendAndApply(&ma); + return true; +} + +bool CGameHandler::bulkSwapArtifacts(ObjectInstanceID leftHero, ObjectInstanceID rightHero) +{ + // Make sure exchange is even possible between the two heroes. + if (!isAllowedExchange(leftHero, rightHero)) + COMPLAIN_RET("That heroes cannot make any exchange!"); + + auto pleftHero = getHero(leftHero); + auto prightHero = getHero(rightHero); + BulkMoveArtifacts ma(static_cast>(pleftHero), + static_cast>(prightHero)); + ma.artsPack1 = BulkMoveArtifacts::HeroArtsToMove(); + ma.artsPack1.value().srcArtHolder = static_cast>(prightHero); + ma.artsPack1.value().dstArtHolder = static_cast>(pleftHero); + auto slotsLeftRight = &ma.artsPack0.slots; + auto slotsRightLeft = &ma.artsPack1.value().slots; + + auto moveArtsWorn = [this](const CGHeroInstance * srcHero, const CGHeroInstance * dstHero, + std::vector * slots) -> void + { + for (auto & artifact : srcHero->artifactsWorn) + { + if (artifact.second.locked) + continue; + if (!ArtifactUtils::isArtRemovable(artifact)) + continue; + slots->push_back(BulkMoveArtifacts::HeroArtsToMove::LinkedSlots(artifact.first, artifact.first)); + } + }; + // Move over artifacts that are worn leftHero -> rightHero + moveArtsWorn(pleftHero, prightHero, slotsLeftRight); + // Move over artifacts that are worn rightHero -> leftHero + moveArtsWorn(prightHero, pleftHero, slotsRightLeft); + // Move over artifacts that are in backpack leftHero -> rightHero + for (auto & slotInfo : pleftHero->artifactsInBackpack) + { + auto slot = pleftHero->getArtPos(slotInfo.artifact); + slotsLeftRight->push_back(BulkMoveArtifacts::HeroArtsToMove::LinkedSlots(slot, slot)); + } + // Move over artifacts that are in backpack rightHero -> leftHero + for (auto & slotInfo : prightHero->artifactsInBackpack) + { + auto slot = prightHero->getArtPos(slotInfo.artifact); + slotsRightLeft->push_back(BulkMoveArtifacts::HeroArtsToMove::LinkedSlots(slot, slot)); + } sendAndApply(&ma); return true; } diff --git a/server/CGameHandler.h b/server/CGameHandler.h index e2b68c312..2dfb1f3dd 100644 --- a/server/CGameHandler.h +++ b/server/CGameHandler.h @@ -181,6 +181,9 @@ public: void putArtifact(const ArtifactLocation &al, const CArtifactInstance *a) override; void removeArtifact(const ArtifactLocation &al) override; bool moveArtifact(const ArtifactLocation &al1, const ArtifactLocation &al2) override; + bool moveArtifact(const ArtifactLocation & al1, const ArtifactLocation & al2) override; + bool bulkMoveArtifacts(ObjectInstanceID srcHero, ObjectInstanceID dstHero); + bool bulkSwapArtifacts(ObjectInstanceID leftHero, ObjectInstanceID rightHero); void synchronizeArtifactHandlerLists(); void showCompInfo(ShowInInfobox * comp) override; From f72a3e388449a83446b7cb534f5e146f446fdd88 Mon Sep 17 00:00:00 2001 From: SoundSSGood <87084363+SoundSSGood@users.noreply.github.com> Date: Mon, 7 Nov 2022 00:18:05 +0200 Subject: [PATCH 05/31] function ArtifactUtils::checkSpellbookIsNeeded for the artifacts like a Titan's thunder --- client/windows/GUIClasses.cpp | 11 +---------- lib/CArtHandler.cpp | 15 +++++++++++++++ lib/CArtHandler.h | 1 + lib/NetPacksLib.cpp | 12 ------------ server/CGameHandler.cpp | 16 ++++++++++++++++ 5 files changed, 33 insertions(+), 22 deletions(-) diff --git a/client/windows/GUIClasses.cpp b/client/windows/GUIClasses.cpp index 2b9d136e3..0cc28e8c6 100644 --- a/client/windows/GUIClasses.cpp +++ b/client/windows/GUIClasses.cpp @@ -884,15 +884,6 @@ std::vector getBackpackArts(const CGHeroInstance * hero) return result; } -const std::vector unmovablePositions = {ArtifactPosition::SPELLBOOK, ArtifactPosition::MACH4}; - -bool isArtRemovable(const std::pair & slot) -{ - return slot.second.artifact - && !slot.second.locked - && !vstd::contains(unmovablePositions, slot.first); -} - // Puts all composite arts to backpack and returns their previous location std::vector CExchangeController::moveCompositeArtsToBackpack() { @@ -1082,7 +1073,7 @@ void CExchangeController::moveArtifacts(bool leftToRight) } GsThread::run([=] - { + { cb->bulkMoveArtifacts(source->id, target->id); }); } diff --git a/lib/CArtHandler.cpp b/lib/CArtHandler.cpp index 1d0f9cca4..16b862b4c 100644 --- a/lib/CArtHandler.cpp +++ b/lib/CArtHandler.cpp @@ -1520,4 +1520,19 @@ DLL_LINKAGE bool ArtifactUtils::isArtRemovable(const std::pairhasSpellbook()) + return true; + } + } + return false; +} + VCMI_LIB_NAMESPACE_END diff --git a/lib/CArtHandler.h b/lib/CArtHandler.h index 65f1b76ce..4ca7d88fa 100644 --- a/lib/CArtHandler.h +++ b/lib/CArtHandler.h @@ -384,6 +384,7 @@ namespace ArtifactUtils ArtBearer::ArtBearer barer); DLL_LINKAGE std::vector unmovablePositions(); // TODO: Make this constexpr when the toolset is upgraded DLL_LINKAGE bool isArtRemovable(const std::pair & slot); + DLL_LINKAGE bool checkSpellbookIsNeeded(const CGHeroInstance * heroPtr, ArtifactID artID, ArtifactPosition slot); } VCMI_LIB_NAMESPACE_END diff --git a/lib/NetPacksLib.cpp b/lib/NetPacksLib.cpp index ffc5a8612..616790c07 100644 --- a/lib/NetPacksLib.cpp +++ b/lib/NetPacksLib.cpp @@ -1093,18 +1093,6 @@ DLL_LINKAGE void MoveArtifact::applyGs(CGameState * gs) assert(!dst.getArt()); art->move(src, dst); - - //TODO what'll happen if Titan's thunder is equipped by pickin git up or the start of game? - if (a->artType->id == ArtifactID::TITANS_THUNDER && dst.slot == ArtifactPosition::RIGHT_HAND) //Titan's Thunder creates new spellbook on equip - { - auto hPtr = boost::get >(&dst.artHolder); - if(hPtr) - { - CGHeroInstance *h = *hPtr; - if(h && !h->hasSpellbook()) - gs->giveHeroArtifact(h, ArtifactID::SPELLBOOK); - } - } } DLL_LINKAGE void BulkMoveArtifacts::applyGs(CGameState * gs) diff --git a/server/CGameHandler.cpp b/server/CGameHandler.cpp index 46b50dee9..a59452b32 100644 --- a/server/CGameHandler.cpp +++ b/server/CGameHandler.cpp @@ -3916,6 +3916,9 @@ bool CGameHandler::moveArtifact(const ArtifactLocation &al1, const ArtifactLocat moveArtifact(dst, ArtifactLocation(dst.artHolder, ArtifactPosition( (si32)dst.getHolderArtSet()->artifactsInBackpack.size() + GameConstants::BACKPACK_START))); } + auto hero = boost::get>(dst.artHolder); + if (ArtifactUtils::checkSpellbookIsNeeded(hero, srcArtifact->artType->id, dst.slot)) + giveHeroNewArtifact(hero, VLC->arth->objects[ArtifactID::SPELLBOOK], ArtifactPosition::SPELLBOOK); MoveArtifact ma(&src, &dst); sendAndApply(&ma); @@ -3949,6 +3952,10 @@ bool CGameHandler::bulkMoveArtifacts(ObjectInstanceID srcHero, ObjectInstanceID ArtFittingSet.putArtifact(dstSlot, static_cast>(psrcHero->getArt(artInfo.first))); slots->push_back(BulkMoveArtifacts::HeroArtsToMove::LinkedSlots(artInfo.first, dstSlot)); + + + if (ArtifactUtils::checkSpellbookIsNeeded(pdstHero, artifact->artType->id, dstSlot)) + giveHeroNewArtifact(pdstHero, VLC->arth->objects[ArtifactID::SPELLBOOK], ArtifactPosition::SPELLBOOK); } } // Move over artifacts that are in backpack @@ -3958,6 +3965,9 @@ bool CGameHandler::bulkMoveArtifacts(ObjectInstanceID srcHero, ObjectInstanceID auto dstSlot = ArtifactUtils::getArtifactDstPosition(artifact, &ArtFittingSet, pdstHero->bearerType()); ArtFittingSet.putArtifact(dstSlot, static_cast>(slotInfo.artifact)); slots->push_back(BulkMoveArtifacts::HeroArtsToMove::LinkedSlots(psrcHero->getArtPos(slotInfo.artifact), dstSlot)); + + if (ArtifactUtils::checkSpellbookIsNeeded(pdstHero, artifact->artType->id, dstSlot)) + giveHeroNewArtifact(pdstHero, VLC->arth->objects[ArtifactID::SPELLBOOK], ArtifactPosition::SPELLBOOK); } sendAndApply(&ma); return true; @@ -3989,6 +3999,9 @@ bool CGameHandler::bulkSwapArtifacts(ObjectInstanceID leftHero, ObjectInstanceID if (!ArtifactUtils::isArtRemovable(artifact)) continue; slots->push_back(BulkMoveArtifacts::HeroArtsToMove::LinkedSlots(artifact.first, artifact.first)); + + if (ArtifactUtils::checkSpellbookIsNeeded(dstHero, artifact.second.getArt()->artType->id, artifact.first)) + giveHeroNewArtifact(dstHero, VLC->arth->objects[ArtifactID::SPELLBOOK], ArtifactPosition::SPELLBOOK); } }; // Move over artifacts that are worn leftHero -> rightHero @@ -4034,6 +4047,9 @@ bool CGameHandler::assembleArtifacts (ObjectInstanceID heroID, ArtifactPosition COMPLAIN_RET("assembleArtifacts: Artifact being attempted to assemble is not a combined artifacts!"); if (!vstd::contains(destArtifact->assemblyPossibilities(hero), combinedArt)) COMPLAIN_RET("assembleArtifacts: It's impossible to assemble requested artifact!"); + + if (ArtifactUtils::checkSpellbookIsNeeded(hero, assembleTo, artifactSlot)) + giveHeroNewArtifact(hero, VLC->arth->objects[ArtifactID::SPELLBOOK], ArtifactPosition::SPELLBOOK); AssembledArtifact aa; aa.al = ArtifactLocation(hero, artifactSlot); From a35db9a6963597a9416cc408e34d200323f6d6f4 Mon Sep 17 00:00:00 2001 From: SoundSSGood <87084363+SoundSSGood@users.noreply.github.com> Date: Mon, 7 Nov 2022 00:19:43 +0200 Subject: [PATCH 06/31] server blocksPack upd --- server/CQuery.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/server/CQuery.cpp b/server/CQuery.cpp index 4f8270a6f..1a2fd205e 100644 --- a/server/CQuery.cpp +++ b/server/CQuery.cpp @@ -370,6 +370,9 @@ bool CGarrisonDialogQuery::blocksPack(const CPack * pack) const } if(auto dismiss = dynamic_ptr_cast(pack)) return !vstd::contains(ourIds, dismiss->id); + + if (auto arts = dynamic_ptr_cast(pack)) + return !vstd::contains(ourIds, arts->srcHero) || !vstd::contains(ourIds, arts->dstHero); if(auto dismiss = dynamic_ptr_cast(pack)) return !vstd::contains(ourIds, dismiss->heroID); From 0032947735275f9f3c12e2e0e97fbc4ca1fd23e5 Mon Sep 17 00:00:00 2001 From: SoundSSGood <87084363+SoundSSGood@users.noreply.github.com> Date: Mon, 7 Nov 2022 00:36:13 +0200 Subject: [PATCH 07/31] regression fixed. Artifact assemble dialog shows multiple times. --- client/CPlayerInterface.cpp | 6 +++++- client/CPlayerInterface.h | 1 + client/NetPacksClient.cpp | 12 ++++++++++-- lib/IGameEventsReceiver.h | 1 + server/CGameHandler.h | 1 - 5 files changed, 17 insertions(+), 4 deletions(-) diff --git a/client/CPlayerInterface.cpp b/client/CPlayerInterface.cpp index ebfc72cdf..e6c8faff4 100644 --- a/client/CPlayerInterface.cpp +++ b/client/CPlayerInterface.cpp @@ -2591,7 +2591,11 @@ void CPlayerInterface::artifactMoved(const ArtifactLocation &src, const Artifact if (artWin) artWin->artifactMoved(src, dst); } - GH.listInt.back()->redraw(); + GH.objsToBlit.back()->redraw(); +} + +void CPlayerInterface::artifactPossibleAssembling(const ArtifactLocation & dst) +{ askToAssembleArtifact(dst); } diff --git a/client/CPlayerInterface.h b/client/CPlayerInterface.h index f7907594c..14a81895f 100644 --- a/client/CPlayerInterface.h +++ b/client/CPlayerInterface.h @@ -133,6 +133,7 @@ public: void artifactRemoved(const ArtifactLocation &al) override; void artifactMoved(const ArtifactLocation &src, const ArtifactLocation &dst) override; void artifactAssembled(const ArtifactLocation &al) override; + void artifactPossibleAssembling(const ArtifactLocation & dst) override; void artifactDisassembled(const ArtifactLocation &al) override; void heroVisit(const CGHeroInstance * visitor, const CGObjectInstance * visitedObj, bool start) override; diff --git a/client/NetPacksClient.cpp b/client/NetPacksClient.cpp index c2f297deb..14a79f60d 100644 --- a/client/NetPacksClient.cpp +++ b/client/NetPacksClient.cpp @@ -275,8 +275,12 @@ void EraseArtifact::applyCl(CClient *cl) void MoveArtifact::applyCl(CClient *cl) { callInterfaceIfPresent(cl, src.owningPlayer(), &IGameEventsReceiver::artifactMoved, src, dst); + callInterfaceIfPresent(cl, src.owningPlayer(), &IGameEventsReceiver::artifactPossibleAssembling, dst); if(src.owningPlayer() != dst.owningPlayer()) + { callInterfaceIfPresent(cl, dst.owningPlayer(), &IGameEventsReceiver::artifactMoved, src, dst); + callInterfaceIfPresent(cl, dst.owningPlayer(), &IGameEventsReceiver::artifactPossibleAssembling, dst); + } } void BulkMoveArtifacts::applyCl(CClient * cl) @@ -286,7 +290,9 @@ void BulkMoveArtifacts::applyCl(CClient * cl) { auto srcLoc = ArtifactLocation(movingArts.srcArtHolder, slotToMove.srcPos); auto dstLoc = ArtifactLocation(movingArts.dstArtHolder, slotToMove.dstPos); - MoveArtifact(&srcLoc, &dstLoc).applyCl(cl); + callInterfaceIfPresent(cl, srcLoc.owningPlayer(), &IGameEventsReceiver::artifactMoved, srcLoc, dstLoc); + if (srcLoc.owningPlayer() != dstLoc.owningPlayer()) + callInterfaceIfPresent(cl, dstLoc.owningPlayer(), &IGameEventsReceiver::artifactMoved, srcLoc, dstLoc); } if (artsPack1.has_value()) @@ -296,7 +302,9 @@ void BulkMoveArtifacts::applyCl(CClient * cl) { auto srcLoc = ArtifactLocation(movingArts.srcArtHolder, slotToMove.srcPos); auto dstLoc = ArtifactLocation(movingArts.dstArtHolder, slotToMove.dstPos); - MoveArtifact(&srcLoc, &dstLoc).applyCl(cl); + callInterfaceIfPresent(cl, srcLoc.owningPlayer(), &IGameEventsReceiver::artifactMoved, srcLoc, dstLoc); + if (srcLoc.owningPlayer() != dstLoc.owningPlayer()) + callInterfaceIfPresent(cl, dstLoc.owningPlayer(), &IGameEventsReceiver::artifactMoved, srcLoc, dstLoc); } } } diff --git a/lib/IGameEventsReceiver.h b/lib/IGameEventsReceiver.h index 632489c76..9970b2c39 100644 --- a/lib/IGameEventsReceiver.h +++ b/lib/IGameEventsReceiver.h @@ -91,6 +91,7 @@ public: virtual void artifactAssembled(const ArtifactLocation &al){}; virtual void artifactDisassembled(const ArtifactLocation &al){}; virtual void artifactMoved(const ArtifactLocation &src, const ArtifactLocation &dst){}; + virtual void artifactPossibleAssembling(const ArtifactLocation & dst) {}; virtual void heroVisit(const CGHeroInstance *visitor, const CGObjectInstance *visitedObj, bool start){}; virtual void heroCreated(const CGHeroInstance*){}; diff --git a/server/CGameHandler.h b/server/CGameHandler.h index 2dfb1f3dd..0b90b3cf0 100644 --- a/server/CGameHandler.h +++ b/server/CGameHandler.h @@ -180,7 +180,6 @@ public: void giveHeroArtifact(const CGHeroInstance *h, const CArtifactInstance *a, ArtifactPosition pos) override; void putArtifact(const ArtifactLocation &al, const CArtifactInstance *a) override; void removeArtifact(const ArtifactLocation &al) override; - bool moveArtifact(const ArtifactLocation &al1, const ArtifactLocation &al2) override; bool moveArtifact(const ArtifactLocation & al1, const ArtifactLocation & al2) override; bool bulkMoveArtifacts(ObjectInstanceID srcHero, ObjectInstanceID dstHero); bool bulkSwapArtifacts(ObjectInstanceID leftHero, ObjectInstanceID rightHero); From 203c54e95684830478fe727d7a0e825688f35c0f Mon Sep 17 00:00:00 2001 From: SoundSSGood <87084363+SoundSSGood@users.noreply.github.com> Date: Mon, 7 Nov 2022 14:13:36 +0200 Subject: [PATCH 08/31] BulkMoveArtifacts structure optimization --- client/NetPacksClient.cpp | 12 ++++----- lib/NetPacks.h | 53 ++++++++++++++++----------------------- lib/NetPacksLib.cpp | 19 ++++++-------- server/CGameHandler.cpp | 25 +++++++++--------- 4 files changed, 46 insertions(+), 63 deletions(-) diff --git a/client/NetPacksClient.cpp b/client/NetPacksClient.cpp index 14a79f60d..0a1f4e33c 100644 --- a/client/NetPacksClient.cpp +++ b/client/NetPacksClient.cpp @@ -286,10 +286,10 @@ void MoveArtifact::applyCl(CClient *cl) void BulkMoveArtifacts::applyCl(CClient * cl) { auto & movingArts = artsPack0; - for (auto & slotToMove : movingArts.slots) + for (auto & slotToMove : movingArts) { - auto srcLoc = ArtifactLocation(movingArts.srcArtHolder, slotToMove.srcPos); - auto dstLoc = ArtifactLocation(movingArts.dstArtHolder, slotToMove.dstPos); + auto srcLoc = ArtifactLocation(srcArtHolder, slotToMove.srcPos); + auto dstLoc = ArtifactLocation(dstArtHolder, slotToMove.dstPos); callInterfaceIfPresent(cl, srcLoc.owningPlayer(), &IGameEventsReceiver::artifactMoved, srcLoc, dstLoc); if (srcLoc.owningPlayer() != dstLoc.owningPlayer()) callInterfaceIfPresent(cl, dstLoc.owningPlayer(), &IGameEventsReceiver::artifactMoved, srcLoc, dstLoc); @@ -298,10 +298,10 @@ void BulkMoveArtifacts::applyCl(CClient * cl) if (artsPack1.has_value()) { movingArts = artsPack1.value(); - for (auto & slotToMove : movingArts.slots) + for (auto & slotToMove : movingArts) { - auto srcLoc = ArtifactLocation(movingArts.srcArtHolder, slotToMove.srcPos); - auto dstLoc = ArtifactLocation(movingArts.dstArtHolder, slotToMove.dstPos); + auto srcLoc = ArtifactLocation(srcArtHolder, slotToMove.srcPos); + auto dstLoc = ArtifactLocation(dstArtHolder, slotToMove.dstPos); callInterfaceIfPresent(cl, srcLoc.owningPlayer(), &IGameEventsReceiver::artifactMoved, srcLoc, dstLoc); if (srcLoc.owningPlayer() != dstLoc.owningPlayer()) callInterfaceIfPresent(cl, dstLoc.owningPlayer(), &IGameEventsReceiver::artifactMoved, srcLoc, dstLoc); diff --git a/lib/NetPacks.h b/lib/NetPacks.h index 0805ea3dc..1bfb37ff6 100644 --- a/lib/NetPacks.h +++ b/lib/NetPacks.h @@ -1011,55 +1011,44 @@ struct MoveArtifact : CArtifactOperationPack struct BulkMoveArtifacts : CArtifactOperationPack { - struct HeroArtsToMove + struct LinkedSlots { - struct LinkedSlots - { - ArtifactPosition srcPos; - ArtifactPosition dstPos; + ArtifactPosition srcPos; + ArtifactPosition dstPos; - LinkedSlots() {} - LinkedSlots(ArtifactPosition srcPos, ArtifactPosition dstPos) - : srcPos(srcPos), dstPos(dstPos) {} - - template void serialize(Handler & h, const int version) - { - h & srcPos; - h & dstPos; - } - }; - - TArtHolder srcArtHolder; - TArtHolder dstArtHolder; - std::vector slots; - - CArtifactSet * getSrcHolderArtSet(); - CArtifactSet * getDstHolderArtSet(); + LinkedSlots() {} + LinkedSlots(ArtifactPosition srcPos, ArtifactPosition dstPos) + : srcPos(srcPos), dstPos(dstPos) {} + template void serialize(Handler & h, const int version) { - h & srcArtHolder; - h & dstArtHolder; - h & slots; + h & srcPos; + h & dstPos; } }; + TArtHolder srcArtHolder; + TArtHolder dstArtHolder; + BulkMoveArtifacts() {} - BulkMoveArtifacts(TArtHolder srcArtHolder, TArtHolder dstArtHolder) - { - artsPack0.srcArtHolder = srcArtHolder; - artsPack0.dstArtHolder = dstArtHolder; - } + BulkMoveArtifacts(TArtHolder srcArtHolder, TArtHolder dstArtHolder) + : srcArtHolder(srcArtHolder), dstArtHolder(dstArtHolder) {} void applyCl(CClient * cl); DLL_LINKAGE void applyGs(CGameState * gs); - HeroArtsToMove artsPack0; + std::vector artsPack0; // If the artsPack1 is present then make swap - boost::optional artsPack1; + boost::optional> artsPack1; + + CArtifactSet * getSrcHolderArtSet(); + CArtifactSet * getDstHolderArtSet(); template void serialize(Handler & h, const int version) { h & artsPack0; h & artsPack1; + h & srcArtHolder; + h & dstArtHolder; } }; diff --git a/lib/NetPacksLib.cpp b/lib/NetPacksLib.cpp index 616790c07..c51991c2a 100644 --- a/lib/NetPacksLib.cpp +++ b/lib/NetPacksLib.cpp @@ -1102,9 +1102,8 @@ DLL_LINKAGE void BulkMoveArtifacts::applyGs(CGameState * gs) { // Swap auto & leftRightPack = artsPack0; - auto & rightLeftPack = artsPack1.value(); - auto leftSet = leftRightPack.getSrcHolderArtSet(); - auto rightSet = leftRightPack.getDstHolderArtSet(); + auto leftSet = getSrcHolderArtSet(); + auto rightSet = getDstHolderArtSet(); CArtifactFittingSet ArtFittingSet(leftSet->bearerType()); std::vector> unmovableArtsLeftHero, unmovableArtsRightHero; @@ -1147,7 +1146,7 @@ DLL_LINKAGE void BulkMoveArtifacts::applyGs(CGameState * gs) { // Move auto & artsPack = artsPack0; - for (auto & slot : artsPack.slots) + for (auto & slot : artsPack) { // When an object gets removed from the backpack, the backpack shrinks // so all the following indices will be affected. Thus, we need to update @@ -1156,16 +1155,12 @@ DLL_LINKAGE void BulkMoveArtifacts::applyGs(CGameState * gs) { slot.srcPos = ArtifactPosition(slot.srcPos.num - numBackpackArtifactsMoved); } - auto srcSlotInfo = artsPack.getSrcHolderArtSet()->getSlot(slot.srcPos); - auto dstSlotInfo = artsPack.getDstHolderArtSet()->getSlot(slot.dstPos); - - if (slot.dstPos < GameConstants::BACKPACK_START) - assert(!dstSlotInfo->getArt()); + auto srcSlotInfo = getSrcHolderArtSet()->getSlot(slot.srcPos); assert(srcSlotInfo); auto art = srcSlotInfo->getArt(); const_cast(art)->move( - ArtifactLocation(artsPack.srcArtHolder, slot.srcPos), ArtifactLocation(artsPack.dstArtHolder, slot.dstPos)); + ArtifactLocation(srcArtHolder, slot.srcPos), ArtifactLocation(dstArtHolder, slot.dstPos)); if (slot.srcPos >= GameConstants::BACKPACK_START) { @@ -1788,12 +1783,12 @@ const CArtifactInstance * ArtSlotInfo::getArt() const return nullptr; } -CArtifactSet * BulkMoveArtifacts::HeroArtsToMove::getSrcHolderArtSet() +CArtifactSet * BulkMoveArtifacts::getSrcHolderArtSet() { return boost::apply_visitor(GetBase(), srcArtHolder); } -CArtifactSet * BulkMoveArtifacts::HeroArtsToMove::getDstHolderArtSet() +CArtifactSet * BulkMoveArtifacts::getDstHolderArtSet() { return boost::apply_visitor(GetBase(), dstArtHolder); } diff --git a/server/CGameHandler.cpp b/server/CGameHandler.cpp index a59452b32..4d53141ac 100644 --- a/server/CGameHandler.cpp +++ b/server/CGameHandler.cpp @@ -3935,7 +3935,7 @@ bool CGameHandler::bulkMoveArtifacts(ObjectInstanceID srcHero, ObjectInstanceID auto pdstHero = getHero(dstHero); BulkMoveArtifacts ma(static_cast>(psrcHero), static_cast>(pdstHero)); - auto slots = &ma.artsPack0.slots; + auto slots = &ma.artsPack0; // Temporary fitting set for artifacts. Used to select available slots before sending data. CArtifactFittingSet ArtFittingSet(pdstHero->bearerType()); @@ -3951,8 +3951,7 @@ bool CGameHandler::bulkMoveArtifacts(ObjectInstanceID srcHero, ObjectInstanceID auto dstSlot = ArtifactUtils::getArtifactDstPosition(artifact, &ArtFittingSet, pdstHero->bearerType()); ArtFittingSet.putArtifact(dstSlot, static_cast>(psrcHero->getArt(artInfo.first))); - slots->push_back(BulkMoveArtifacts::HeroArtsToMove::LinkedSlots(artInfo.first, dstSlot)); - + slots->push_back(BulkMoveArtifacts::LinkedSlots(artInfo.first, dstSlot)); if (ArtifactUtils::checkSpellbookIsNeeded(pdstHero, artifact->artType->id, dstSlot)) giveHeroNewArtifact(pdstHero, VLC->arth->objects[ArtifactID::SPELLBOOK], ArtifactPosition::SPELLBOOK); @@ -3964,7 +3963,7 @@ bool CGameHandler::bulkMoveArtifacts(ObjectInstanceID srcHero, ObjectInstanceID auto artifact = psrcHero->getArt(psrcHero->getArtPos(slotInfo.artifact)); auto dstSlot = ArtifactUtils::getArtifactDstPosition(artifact, &ArtFittingSet, pdstHero->bearerType()); ArtFittingSet.putArtifact(dstSlot, static_cast>(slotInfo.artifact)); - slots->push_back(BulkMoveArtifacts::HeroArtsToMove::LinkedSlots(psrcHero->getArtPos(slotInfo.artifact), dstSlot)); + slots->push_back(BulkMoveArtifacts::LinkedSlots(psrcHero->getArtPos(slotInfo.artifact), dstSlot)); if (ArtifactUtils::checkSpellbookIsNeeded(pdstHero, artifact->artType->id, dstSlot)) giveHeroNewArtifact(pdstHero, VLC->arth->objects[ArtifactID::SPELLBOOK], ArtifactPosition::SPELLBOOK); @@ -3983,14 +3982,14 @@ bool CGameHandler::bulkSwapArtifacts(ObjectInstanceID leftHero, ObjectInstanceID auto prightHero = getHero(rightHero); BulkMoveArtifacts ma(static_cast>(pleftHero), static_cast>(prightHero)); - ma.artsPack1 = BulkMoveArtifacts::HeroArtsToMove(); - ma.artsPack1.value().srcArtHolder = static_cast>(prightHero); - ma.artsPack1.value().dstArtHolder = static_cast>(pleftHero); - auto slotsLeftRight = &ma.artsPack0.slots; - auto slotsRightLeft = &ma.artsPack1.value().slots; + ma.artsPack1 = std::vector(); + ma.srcArtHolder = static_cast>(prightHero); + ma.dstArtHolder = static_cast>(pleftHero); + auto slotsLeftRight = &ma.artsPack0; + auto slotsRightLeft = &ma.artsPack1.value(); auto moveArtsWorn = [this](const CGHeroInstance * srcHero, const CGHeroInstance * dstHero, - std::vector * slots) -> void + std::vector * slots) -> void { for (auto & artifact : srcHero->artifactsWorn) { @@ -3998,7 +3997,7 @@ bool CGameHandler::bulkSwapArtifacts(ObjectInstanceID leftHero, ObjectInstanceID continue; if (!ArtifactUtils::isArtRemovable(artifact)) continue; - slots->push_back(BulkMoveArtifacts::HeroArtsToMove::LinkedSlots(artifact.first, artifact.first)); + slots->push_back(BulkMoveArtifacts::LinkedSlots(artifact.first, artifact.first)); if (ArtifactUtils::checkSpellbookIsNeeded(dstHero, artifact.second.getArt()->artType->id, artifact.first)) giveHeroNewArtifact(dstHero, VLC->arth->objects[ArtifactID::SPELLBOOK], ArtifactPosition::SPELLBOOK); @@ -4012,13 +4011,13 @@ bool CGameHandler::bulkSwapArtifacts(ObjectInstanceID leftHero, ObjectInstanceID for (auto & slotInfo : pleftHero->artifactsInBackpack) { auto slot = pleftHero->getArtPos(slotInfo.artifact); - slotsLeftRight->push_back(BulkMoveArtifacts::HeroArtsToMove::LinkedSlots(slot, slot)); + slotsLeftRight->push_back(BulkMoveArtifacts::LinkedSlots(slot, slot)); } // Move over artifacts that are in backpack rightHero -> leftHero for (auto & slotInfo : prightHero->artifactsInBackpack) { auto slot = prightHero->getArtPos(slotInfo.artifact); - slotsRightLeft->push_back(BulkMoveArtifacts::HeroArtsToMove::LinkedSlots(slot, slot)); + slotsRightLeft->push_back(BulkMoveArtifacts::LinkedSlots(slot, slot)); } sendAndApply(&ma); return true; From 3a3b559a0bcc94edb924af2a5e31b7af7d2d8e9f Mon Sep 17 00:00:00 2001 From: SoundSSGood <87084363+SoundSSGood@users.noreply.github.com> Date: Mon, 7 Nov 2022 14:20:28 +0200 Subject: [PATCH 09/31] attempt to fix the build --- client/NetPacksClient.cpp | 4 ++-- lib/NetPacks.h | 11 +++++------ lib/NetPacksLib.cpp | 3 +-- server/CGameHandler.cpp | 7 +++---- 4 files changed, 11 insertions(+), 14 deletions(-) diff --git a/client/NetPacksClient.cpp b/client/NetPacksClient.cpp index 0a1f4e33c..95bd449b5 100644 --- a/client/NetPacksClient.cpp +++ b/client/NetPacksClient.cpp @@ -295,9 +295,9 @@ void BulkMoveArtifacts::applyCl(CClient * cl) callInterfaceIfPresent(cl, dstLoc.owningPlayer(), &IGameEventsReceiver::artifactMoved, srcLoc, dstLoc); } - if (artsPack1.has_value()) + if (swap) { - movingArts = artsPack1.value(); + movingArts = artsPack1; for (auto & slotToMove : movingArts) { auto srcLoc = ArtifactLocation(srcArtHolder, slotToMove.srcPos); diff --git a/lib/NetPacks.h b/lib/NetPacks.h index 1bfb37ff6..ee29aada9 100644 --- a/lib/NetPacks.h +++ b/lib/NetPacks.h @@ -1019,7 +1019,6 @@ struct BulkMoveArtifacts : CArtifactOperationPack LinkedSlots() {} LinkedSlots(ArtifactPosition srcPos, ArtifactPosition dstPos) : srcPos(srcPos), dstPos(dstPos) {} - template void serialize(Handler & h, const int version) { h & srcPos; @@ -1031,16 +1030,15 @@ struct BulkMoveArtifacts : CArtifactOperationPack TArtHolder dstArtHolder; BulkMoveArtifacts() {} - BulkMoveArtifacts(TArtHolder srcArtHolder, TArtHolder dstArtHolder) - : srcArtHolder(srcArtHolder), dstArtHolder(dstArtHolder) {} + BulkMoveArtifacts(TArtHolder srcArtHolder, TArtHolder dstArtHolder, bool swap) + : srcArtHolder(srcArtHolder), dstArtHolder(dstArtHolder), swap(swap) {} void applyCl(CClient * cl); DLL_LINKAGE void applyGs(CGameState * gs); std::vector artsPack0; - // If the artsPack1 is present then make swap - boost::optional> artsPack1; - + std::vector artsPack1; + bool swap; CArtifactSet * getSrcHolderArtSet(); CArtifactSet * getDstHolderArtSet(); template void serialize(Handler & h, const int version) @@ -1049,6 +1047,7 @@ struct BulkMoveArtifacts : CArtifactOperationPack h & artsPack1; h & srcArtHolder; h & dstArtHolder; + h & swap; } }; diff --git a/lib/NetPacksLib.cpp b/lib/NetPacksLib.cpp index c51991c2a..a2814b6cf 100644 --- a/lib/NetPacksLib.cpp +++ b/lib/NetPacksLib.cpp @@ -1098,10 +1098,9 @@ DLL_LINKAGE void MoveArtifact::applyGs(CGameState * gs) DLL_LINKAGE void BulkMoveArtifacts::applyGs(CGameState * gs) { int numBackpackArtifactsMoved = 0; - if (artsPack1.has_value()) + if (swap) { // Swap - auto & leftRightPack = artsPack0; auto leftSet = getSrcHolderArtSet(); auto rightSet = getDstHolderArtSet(); CArtifactFittingSet ArtFittingSet(leftSet->bearerType()); diff --git a/server/CGameHandler.cpp b/server/CGameHandler.cpp index 4d53141ac..90ce66823 100644 --- a/server/CGameHandler.cpp +++ b/server/CGameHandler.cpp @@ -3934,7 +3934,7 @@ bool CGameHandler::bulkMoveArtifacts(ObjectInstanceID srcHero, ObjectInstanceID auto psrcHero = getHero(srcHero); auto pdstHero = getHero(dstHero); BulkMoveArtifacts ma(static_cast>(psrcHero), - static_cast>(pdstHero)); + static_cast>(pdstHero), false); auto slots = &ma.artsPack0; // Temporary fitting set for artifacts. Used to select available slots before sending data. @@ -3981,12 +3981,11 @@ bool CGameHandler::bulkSwapArtifacts(ObjectInstanceID leftHero, ObjectInstanceID auto pleftHero = getHero(leftHero); auto prightHero = getHero(rightHero); BulkMoveArtifacts ma(static_cast>(pleftHero), - static_cast>(prightHero)); - ma.artsPack1 = std::vector(); + static_cast>(prightHero), true); ma.srcArtHolder = static_cast>(prightHero); ma.dstArtHolder = static_cast>(pleftHero); auto slotsLeftRight = &ma.artsPack0; - auto slotsRightLeft = &ma.artsPack1.value(); + auto slotsRightLeft = &ma.artsPack1; auto moveArtsWorn = [this](const CGHeroInstance * srcHero, const CGHeroInstance * dstHero, std::vector * slots) -> void From ff63167553312d23ecfd2c02ed8cff6c15627b50 Mon Sep 17 00:00:00 2001 From: SoundSSGood <87084363+SoundSSGood@users.noreply.github.com> Date: Mon, 7 Nov 2022 18:31:22 +0200 Subject: [PATCH 10/31] warnings fixed --- client/windows/GUIClasses.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/client/windows/GUIClasses.cpp b/client/windows/GUIClasses.cpp index 0cc28e8c6..6261446d1 100644 --- a/client/windows/GUIClasses.cpp +++ b/client/windows/GUIClasses.cpp @@ -1083,7 +1083,6 @@ void CExchangeController::moveArtifact( const CGHeroInstance * target, ArtifactPosition srcPosition) { - auto artifact = source->getArt(srcPosition); auto srcLocation = ArtifactLocation(source, srcPosition); auto dstLocation = ArtifactLocation(target, ArtifactUtils::getArtifactDstPosition(source->getArt(srcPosition), target, target->bearerType())); From f2afd9e8313ecea582eccd17d21abf6dd81841ad Mon Sep 17 00:00:00 2001 From: SoundSSGood <87084363+SoundSSGood@users.noreply.github.com> Date: Thu, 10 Nov 2022 17:37:50 +0200 Subject: [PATCH 11/31] Update server/CGameHandler.cpp Co-authored-by: Nordsoft91 --- server/CGameHandler.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/server/CGameHandler.cpp b/server/CGameHandler.cpp index 90ce66823..01e581727 100644 --- a/server/CGameHandler.cpp +++ b/server/CGameHandler.cpp @@ -3984,8 +3984,8 @@ bool CGameHandler::bulkSwapArtifacts(ObjectInstanceID leftHero, ObjectInstanceID static_cast>(prightHero), true); ma.srcArtHolder = static_cast>(prightHero); ma.dstArtHolder = static_cast>(pleftHero); - auto slotsLeftRight = &ma.artsPack0; - auto slotsRightLeft = &ma.artsPack1; + auto & slotsLeftRight = ma.artsPack0; + auto & slotsRightLeft = ma.artsPack1; auto moveArtsWorn = [this](const CGHeroInstance * srcHero, const CGHeroInstance * dstHero, std::vector * slots) -> void From b9087e2d6391f369bdc51608f4e41d4332883681 Mon Sep 17 00:00:00 2001 From: SoundSSGood <87084363+SoundSSGood@users.noreply.github.com> Date: Thu, 10 Nov 2022 17:45:54 +0200 Subject: [PATCH 12/31] Apply suggestions from code review Co-authored-by: Nordsoft91 --- lib/CArtHandler.cpp | 2 +- lib/NetPacksLib.cpp | 16 +++++----------- server/CGameHandler.cpp | 8 ++++---- 3 files changed, 10 insertions(+), 16 deletions(-) diff --git a/lib/CArtHandler.cpp b/lib/CArtHandler.cpp index 16b862b4c..dd9fa427f 100644 --- a/lib/CArtHandler.cpp +++ b/lib/CArtHandler.cpp @@ -1469,7 +1469,7 @@ void CArtifactFittingSet::setNewArtSlot(ArtifactPosition slot, CArtifactInstance asi.locked = locked; } -void CArtifactFittingSet::putArtifact(ArtifactPosition pos, CArtifactInstance * art) +void CArtifactFittingSet::putArtifact(ArtifactPosition pos, CArtifactInstance & art) { if (art->canBeDisassembled() && (pos < ArtifactPosition::AFTER_LAST)) { diff --git a/lib/NetPacksLib.cpp b/lib/NetPacksLib.cpp index a2814b6cf..9a853496a 100644 --- a/lib/NetPacksLib.cpp +++ b/lib/NetPacksLib.cpp @@ -1144,8 +1144,7 @@ DLL_LINKAGE void BulkMoveArtifacts::applyGs(CGameState * gs) else { // Move - auto & artsPack = artsPack0; - for (auto & slot : artsPack) + for (auto & slot : artsPack0) { // When an object gets removed from the backpack, the backpack shrinks // so all the following indices will be affected. Thus, we need to update @@ -1769,17 +1768,12 @@ DLL_LINKAGE void EntitiesChanged::applyGs(CGameState * gs) const CArtifactInstance * ArtSlotInfo::getArt() const { - if (artifact) + if(locked) { - if (!locked) - return artifact; - else - { - logNetwork->warn("ArtifactLocation::getArt: This location is locked!"); - return nullptr; - } + logNetwork->warn("ArtifactLocation::getArt: This location is locked!"); + return nullptr; } - return nullptr; + return artifact; } CArtifactSet * BulkMoveArtifacts::getSrcHolderArtSet() diff --git a/server/CGameHandler.cpp b/server/CGameHandler.cpp index 01e581727..3ea5733ae 100644 --- a/server/CGameHandler.cpp +++ b/server/CGameHandler.cpp @@ -3988,7 +3988,7 @@ bool CGameHandler::bulkSwapArtifacts(ObjectInstanceID leftHero, ObjectInstanceID auto & slotsRightLeft = ma.artsPack1; auto moveArtsWorn = [this](const CGHeroInstance * srcHero, const CGHeroInstance * dstHero, - std::vector * slots) -> void + std::vector & slots) -> void { for (auto & artifact : srcHero->artifactsWorn) { @@ -3996,7 +3996,7 @@ bool CGameHandler::bulkSwapArtifacts(ObjectInstanceID leftHero, ObjectInstanceID continue; if (!ArtifactUtils::isArtRemovable(artifact)) continue; - slots->push_back(BulkMoveArtifacts::LinkedSlots(artifact.first, artifact.first)); + slots.push_back(BulkMoveArtifacts::LinkedSlots(artifact.first, artifact.first)); if (ArtifactUtils::checkSpellbookIsNeeded(dstHero, artifact.second.getArt()->artType->id, artifact.first)) giveHeroNewArtifact(dstHero, VLC->arth->objects[ArtifactID::SPELLBOOK], ArtifactPosition::SPELLBOOK); @@ -4010,13 +4010,13 @@ bool CGameHandler::bulkSwapArtifacts(ObjectInstanceID leftHero, ObjectInstanceID for (auto & slotInfo : pleftHero->artifactsInBackpack) { auto slot = pleftHero->getArtPos(slotInfo.artifact); - slotsLeftRight->push_back(BulkMoveArtifacts::LinkedSlots(slot, slot)); + slotsLeftRight.push_back(BulkMoveArtifacts::LinkedSlots(slot, slot)); } // Move over artifacts that are in backpack rightHero -> leftHero for (auto & slotInfo : prightHero->artifactsInBackpack) { auto slot = prightHero->getArtPos(slotInfo.artifact); - slotsRightLeft->push_back(BulkMoveArtifacts::LinkedSlots(slot, slot)); + slotsRightLeft.push_back(BulkMoveArtifacts::LinkedSlots(slot, slot)); } sendAndApply(&ma); return true; From ad47a7573ca73427f88ee5647dc128df1fd894b4 Mon Sep 17 00:00:00 2001 From: SoundSSGood <87084363+SoundSSGood@users.noreply.github.com> Date: Thu, 10 Nov 2022 18:29:39 +0200 Subject: [PATCH 13/31] Code style. Typo. Code clean up. --- client/NetPacksClient.cpp | 8 ++++---- client/windows/GUIClasses.cpp | 27 --------------------------- client/windows/GUIClasses.h | 1 - lib/CArtHandler.cpp | 18 +++++++++--------- lib/CArtHandler.h | 2 +- lib/NetPacksLib.cpp | 20 ++++++++++---------- server/CGameHandler.cpp | 26 +++++++++++++------------- server/CQuery.cpp | 2 +- server/NetPacksServer.cpp | 2 +- 9 files changed, 39 insertions(+), 67 deletions(-) diff --git a/client/NetPacksClient.cpp b/client/NetPacksClient.cpp index 95bd449b5..f625ec226 100644 --- a/client/NetPacksClient.cpp +++ b/client/NetPacksClient.cpp @@ -286,7 +286,7 @@ void MoveArtifact::applyCl(CClient *cl) void BulkMoveArtifacts::applyCl(CClient * cl) { auto & movingArts = artsPack0; - for (auto & slotToMove : movingArts) + for(auto & slotToMove : movingArts) { auto srcLoc = ArtifactLocation(srcArtHolder, slotToMove.srcPos); auto dstLoc = ArtifactLocation(dstArtHolder, slotToMove.dstPos); @@ -295,15 +295,15 @@ void BulkMoveArtifacts::applyCl(CClient * cl) callInterfaceIfPresent(cl, dstLoc.owningPlayer(), &IGameEventsReceiver::artifactMoved, srcLoc, dstLoc); } - if (swap) + if(swap) { movingArts = artsPack1; - for (auto & slotToMove : movingArts) + for(auto & slotToMove : movingArts) { auto srcLoc = ArtifactLocation(srcArtHolder, slotToMove.srcPos); auto dstLoc = ArtifactLocation(dstArtHolder, slotToMove.dstPos); callInterfaceIfPresent(cl, srcLoc.owningPlayer(), &IGameEventsReceiver::artifactMoved, srcLoc, dstLoc); - if (srcLoc.owningPlayer() != dstLoc.owningPlayer()) + if(srcLoc.owningPlayer() != dstLoc.owningPlayer()) callInterfaceIfPresent(cl, dstLoc.owningPlayer(), &IGameEventsReceiver::artifactMoved, srcLoc, dstLoc); } } diff --git a/client/windows/GUIClasses.cpp b/client/windows/GUIClasses.cpp index 6261446d1..07ce6e590 100644 --- a/client/windows/GUIClasses.cpp +++ b/client/windows/GUIClasses.cpp @@ -884,33 +884,6 @@ std::vector getBackpackArts(const CGHeroInstance * hero) return result; } -// Puts all composite arts to backpack and returns their previous location -std::vector CExchangeController::moveCompositeArtsToBackpack() -{ - std::vector sides = {left, right}; - std::vector artPositions; - - for(auto hero : sides) - { - for(int i = ArtifactPosition::HEAD; i < ArtifactPosition::AFTER_LAST; i++) - { - auto artPosition = ArtifactPosition(i); - auto art = hero->getArt(artPosition); - - if(art && art->canBeDisassembled()) - { - cb->swapArtifacts( - ArtifactLocation(hero, artPosition), - ArtifactLocation(hero, ArtifactPosition(GameConstants::BACKPACK_START))); - - artPositions.push_back(HeroArtifact(hero, art, artPosition)); - } - } - } - - return artPositions; -} - std::function CExchangeController::onSwapArtifacts() { return [&]() diff --git a/client/windows/GUIClasses.h b/client/windows/GUIClasses.h index d79029c92..56097d0b4 100644 --- a/client/windows/GUIClasses.h +++ b/client/windows/GUIClasses.h @@ -324,7 +324,6 @@ private: void moveArtifacts(bool leftToRight); void moveArtifact(const CGHeroInstance * source, const CGHeroInstance * target, ArtifactPosition srcPosition); void moveStack(const CGHeroInstance * source, const CGHeroInstance * target, SlotID sourceSlot); - std::vector moveCompositeArtsToBackpack(); }; class CExchangeWindow : public CStatusbarWindow, public CGarrisonHolder, public CWindowWithArtifacts diff --git a/lib/CArtHandler.cpp b/lib/CArtHandler.cpp index dd9fa427f..c4bf095a2 100644 --- a/lib/CArtHandler.cpp +++ b/lib/CArtHandler.cpp @@ -1469,11 +1469,11 @@ void CArtifactFittingSet::setNewArtSlot(ArtifactPosition slot, CArtifactInstance asi.locked = locked; } -void CArtifactFittingSet::putArtifact(ArtifactPosition pos, CArtifactInstance & art) +void CArtifactFittingSet::putArtifact(ArtifactPosition pos, CArtifactInstance * art) { - if (art->canBeDisassembled() && (pos < ArtifactPosition::AFTER_LAST)) + if(art && art->canBeDisassembled() && (pos < ArtifactPosition::AFTER_LAST)) { - for (auto part : dynamic_cast(art)->constituentsInfo) + for(auto & part : dynamic_cast(art)->constituentsInfo) { // For the ArtFittingSet is no needed to do figureMainConstituent, just lock slots this->setNewArtSlot(part.art->firstAvailableSlot(this), part.art, true); @@ -1491,14 +1491,14 @@ ArtBearer::ArtBearer CArtifactFittingSet::bearerType() const } DLL_LINKAGE ArtifactPosition ArtifactUtils::getArtifactDstPosition(const CArtifactInstance * artifact, - const CArtifactSet * target, ArtBearer::ArtBearer barer) + const CArtifactSet * target, ArtBearer::ArtBearer bearer) { - for (auto slot : artifact->artType->possibleSlots.at(barer)) + for(auto slot : artifact->artType->possibleSlots.at(bearer)) { auto existingArtifact = target->getArt(slot); auto existingArtInfo = target->getSlot(slot); - if (!existingArtifact + if(!existingArtifact && (!existingArtInfo || !existingArtInfo->locked) && artifact->canBePutAt(target, slot)) { @@ -1524,11 +1524,11 @@ DLL_LINKAGE bool ArtifactUtils::checkSpellbookIsNeeded(const CGHeroInstance * he { // TODO what'll happen if Titan's thunder is equipped by pickin git up or the start of game? // Titan's Thunder creates new spellbook on equip - if (artID == ArtifactID::TITANS_THUNDER && slot == ArtifactPosition::RIGHT_HAND) + if(artID == ArtifactID::TITANS_THUNDER && slot == ArtifactPosition::RIGHT_HAND) { - if (heroPtr) + if(heroPtr) { - if (heroPtr && !heroPtr->hasSpellbook()) + if(heroPtr && !heroPtr->hasSpellbook()) return true; } } diff --git a/lib/CArtHandler.h b/lib/CArtHandler.h index 4ca7d88fa..ab273670c 100644 --- a/lib/CArtHandler.h +++ b/lib/CArtHandler.h @@ -381,7 +381,7 @@ namespace ArtifactUtils { // Calculates where an artifact gets placed when it gets transferred from one hero to another. DLL_LINKAGE ArtifactPosition getArtifactDstPosition(const CArtifactInstance * artifact, const CArtifactSet * target, - ArtBearer::ArtBearer barer); + ArtBearer::ArtBearer bearer); DLL_LINKAGE std::vector unmovablePositions(); // TODO: Make this constexpr when the toolset is upgraded DLL_LINKAGE bool isArtRemovable(const std::pair & slot); DLL_LINKAGE bool checkSpellbookIsNeeded(const CGHeroInstance * heroPtr, ArtifactID artID, ArtifactPosition slot); diff --git a/lib/NetPacksLib.cpp b/lib/NetPacksLib.cpp index 9a853496a..aeca09873 100644 --- a/lib/NetPacksLib.cpp +++ b/lib/NetPacksLib.cpp @@ -846,7 +846,7 @@ DLL_LINKAGE CBonusSystemNode *ArtifactLocation::getHolderNode() DLL_LINKAGE const CArtifactInstance *ArtifactLocation::getArt() const { auto s = getSlot(); - if (s) + if(s) return s->getArt(); else return nullptr; @@ -1098,7 +1098,7 @@ DLL_LINKAGE void MoveArtifact::applyGs(CGameState * gs) DLL_LINKAGE void BulkMoveArtifacts::applyGs(CGameState * gs) { int numBackpackArtifactsMoved = 0; - if (swap) + if(swap) { // Swap auto leftSet = getSrcHolderArtSet(); @@ -1107,17 +1107,17 @@ DLL_LINKAGE void BulkMoveArtifacts::applyGs(CGameState * gs) std::vector> unmovableArtsLeftHero, unmovableArtsRightHero; // Keep unmovable artifacts separately until the swap - for (auto artPos : ArtifactUtils::unmovablePositions()) + for(auto artPos : ArtifactUtils::unmovablePositions()) { auto slotInfo = leftSet->getSlot(artPos); - if (slotInfo) + if(slotInfo) { unmovableArtsLeftHero.push_back(std::make_pair(artPos, *slotInfo)); leftSet->eraseArtSlot(artPos); } slotInfo = rightSet->getSlot(artPos); - if (slotInfo) + if(slotInfo) { unmovableArtsRightHero.push_back(std::make_pair(artPos, *slotInfo)); rightSet->eraseArtSlot(artPos); @@ -1132,11 +1132,11 @@ DLL_LINKAGE void BulkMoveArtifacts::applyGs(CGameState * gs) leftSet->artifactsInBackpack = ArtFittingSet.artifactsInBackpack; // Return non movable artifacts to their place after the swap - for (auto & art : unmovableArtsLeftHero) + for(auto & art : unmovableArtsLeftHero) { leftSet->putArtifact(art.first, art.second.artifact); } - for (auto & art : unmovableArtsRightHero) + for(auto & art : unmovableArtsRightHero) { rightSet->putArtifact(art.first, art.second.artifact); } @@ -1144,12 +1144,12 @@ DLL_LINKAGE void BulkMoveArtifacts::applyGs(CGameState * gs) else { // Move - for (auto & slot : artsPack0) + for(auto & slot : artsPack0) { // When an object gets removed from the backpack, the backpack shrinks // so all the following indices will be affected. Thus, we need to update // the subsequent artifact slots to account for that - if (slot.srcPos >= GameConstants::BACKPACK_START) + if(slot.srcPos >= GameConstants::BACKPACK_START) { slot.srcPos = ArtifactPosition(slot.srcPos.num - numBackpackArtifactsMoved); } @@ -1160,7 +1160,7 @@ DLL_LINKAGE void BulkMoveArtifacts::applyGs(CGameState * gs) const_cast(art)->move( ArtifactLocation(srcArtHolder, slot.srcPos), ArtifactLocation(dstArtHolder, slot.dstPos)); - if (slot.srcPos >= GameConstants::BACKPACK_START) + if(slot.srcPos >= GameConstants::BACKPACK_START) { numBackpackArtifactsMoved++; } diff --git a/server/CGameHandler.cpp b/server/CGameHandler.cpp index 3ea5733ae..4eab99cc4 100644 --- a/server/CGameHandler.cpp +++ b/server/CGameHandler.cpp @@ -3943,9 +3943,9 @@ bool CGameHandler::bulkMoveArtifacts(ObjectInstanceID srcHero, ObjectInstanceID ArtFittingSet.artifactsWorn = pdstHero->artifactsWorn; // Move over artifacts that are worn - for (auto & artInfo : psrcHero->artifactsWorn) + for(auto & artInfo : psrcHero->artifactsWorn) { - if (ArtifactUtils::isArtRemovable(artInfo)) + if(ArtifactUtils::isArtRemovable(artInfo)) { auto artifact = psrcHero->getArt(artInfo.first); auto dstSlot = ArtifactUtils::getArtifactDstPosition(artifact, &ArtFittingSet, pdstHero->bearerType()); @@ -3953,19 +3953,19 @@ bool CGameHandler::bulkMoveArtifacts(ObjectInstanceID srcHero, ObjectInstanceID static_cast>(psrcHero->getArt(artInfo.first))); slots->push_back(BulkMoveArtifacts::LinkedSlots(artInfo.first, dstSlot)); - if (ArtifactUtils::checkSpellbookIsNeeded(pdstHero, artifact->artType->id, dstSlot)) + if(ArtifactUtils::checkSpellbookIsNeeded(pdstHero, artifact->artType->id, dstSlot)) giveHeroNewArtifact(pdstHero, VLC->arth->objects[ArtifactID::SPELLBOOK], ArtifactPosition::SPELLBOOK); } } // Move over artifacts that are in backpack - for (auto & slotInfo : psrcHero->artifactsInBackpack) + for(auto & slotInfo : psrcHero->artifactsInBackpack) { auto artifact = psrcHero->getArt(psrcHero->getArtPos(slotInfo.artifact)); auto dstSlot = ArtifactUtils::getArtifactDstPosition(artifact, &ArtFittingSet, pdstHero->bearerType()); ArtFittingSet.putArtifact(dstSlot, static_cast>(slotInfo.artifact)); slots->push_back(BulkMoveArtifacts::LinkedSlots(psrcHero->getArtPos(slotInfo.artifact), dstSlot)); - if (ArtifactUtils::checkSpellbookIsNeeded(pdstHero, artifact->artType->id, dstSlot)) + if(ArtifactUtils::checkSpellbookIsNeeded(pdstHero, artifact->artType->id, dstSlot)) giveHeroNewArtifact(pdstHero, VLC->arth->objects[ArtifactID::SPELLBOOK], ArtifactPosition::SPELLBOOK); } sendAndApply(&ma); @@ -3975,7 +3975,7 @@ bool CGameHandler::bulkMoveArtifacts(ObjectInstanceID srcHero, ObjectInstanceID bool CGameHandler::bulkSwapArtifacts(ObjectInstanceID leftHero, ObjectInstanceID rightHero) { // Make sure exchange is even possible between the two heroes. - if (!isAllowedExchange(leftHero, rightHero)) + if(!isAllowedExchange(leftHero, rightHero)) COMPLAIN_RET("That heroes cannot make any exchange!"); auto pleftHero = getHero(leftHero); @@ -3990,15 +3990,15 @@ bool CGameHandler::bulkSwapArtifacts(ObjectInstanceID leftHero, ObjectInstanceID auto moveArtsWorn = [this](const CGHeroInstance * srcHero, const CGHeroInstance * dstHero, std::vector & slots) -> void { - for (auto & artifact : srcHero->artifactsWorn) + for(auto & artifact : srcHero->artifactsWorn) { - if (artifact.second.locked) + if(artifact.second.locked) continue; - if (!ArtifactUtils::isArtRemovable(artifact)) + if(!ArtifactUtils::isArtRemovable(artifact)) continue; slots.push_back(BulkMoveArtifacts::LinkedSlots(artifact.first, artifact.first)); - if (ArtifactUtils::checkSpellbookIsNeeded(dstHero, artifact.second.getArt()->artType->id, artifact.first)) + if(ArtifactUtils::checkSpellbookIsNeeded(dstHero, artifact.second.getArt()->artType->id, artifact.first)) giveHeroNewArtifact(dstHero, VLC->arth->objects[ArtifactID::SPELLBOOK], ArtifactPosition::SPELLBOOK); } }; @@ -4007,13 +4007,13 @@ bool CGameHandler::bulkSwapArtifacts(ObjectInstanceID leftHero, ObjectInstanceID // Move over artifacts that are worn rightHero -> leftHero moveArtsWorn(prightHero, pleftHero, slotsRightLeft); // Move over artifacts that are in backpack leftHero -> rightHero - for (auto & slotInfo : pleftHero->artifactsInBackpack) + for(auto & slotInfo : pleftHero->artifactsInBackpack) { auto slot = pleftHero->getArtPos(slotInfo.artifact); slotsLeftRight.push_back(BulkMoveArtifacts::LinkedSlots(slot, slot)); } // Move over artifacts that are in backpack rightHero -> leftHero - for (auto & slotInfo : prightHero->artifactsInBackpack) + for(auto & slotInfo : prightHero->artifactsInBackpack) { auto slot = prightHero->getArtPos(slotInfo.artifact); slotsRightLeft.push_back(BulkMoveArtifacts::LinkedSlots(slot, slot)); @@ -4046,7 +4046,7 @@ bool CGameHandler::assembleArtifacts (ObjectInstanceID heroID, ArtifactPosition if (!vstd::contains(destArtifact->assemblyPossibilities(hero), combinedArt)) COMPLAIN_RET("assembleArtifacts: It's impossible to assemble requested artifact!"); - if (ArtifactUtils::checkSpellbookIsNeeded(hero, assembleTo, artifactSlot)) + if(ArtifactUtils::checkSpellbookIsNeeded(hero, assembleTo, artifactSlot)) giveHeroNewArtifact(hero, VLC->arth->objects[ArtifactID::SPELLBOOK], ArtifactPosition::SPELLBOOK); AssembledArtifact aa; diff --git a/server/CQuery.cpp b/server/CQuery.cpp index 1a2fd205e..7c1df47be 100644 --- a/server/CQuery.cpp +++ b/server/CQuery.cpp @@ -371,7 +371,7 @@ bool CGarrisonDialogQuery::blocksPack(const CPack * pack) const if(auto dismiss = dynamic_ptr_cast(pack)) return !vstd::contains(ourIds, dismiss->id); - if (auto arts = dynamic_ptr_cast(pack)) + if(auto arts = dynamic_ptr_cast(pack)) return !vstd::contains(ourIds, arts->srcHero) || !vstd::contains(ourIds, arts->dstHero); if(auto dismiss = dynamic_ptr_cast(pack)) diff --git a/server/NetPacksServer.cpp b/server/NetPacksServer.cpp index 122a100cf..7a2666512 100644 --- a/server/NetPacksServer.cpp +++ b/server/NetPacksServer.cpp @@ -184,7 +184,7 @@ bool BulkExchangeArtifacts::applyGh(CGameHandler * gh) { const CGHeroInstance * pSrcHero = gh->getHero(srcHero); throwOnWrongPlayer(gh, pSrcHero->getOwner()); - if (swap) + if(swap) return gh->bulkSwapArtifacts(srcHero, dstHero); else return gh->bulkMoveArtifacts(srcHero, dstHero); From 30db38c0fe3737358690ed2525925e3424da7cdc Mon Sep 17 00:00:00 2001 From: SoundSSGood <87084363+SoundSSGood@users.noreply.github.com> Date: Thu, 10 Nov 2022 19:09:37 +0200 Subject: [PATCH 14/31] Unified CGameHandler::bulkMoveArtifacts and CGameHandler::bulkSwapArtifacts to one --- server/CGameHandler.cpp | 142 +++++++++++++++++--------------------- server/CGameHandler.h | 3 +- server/NetPacksServer.cpp | 5 +- 3 files changed, 67 insertions(+), 83 deletions(-) diff --git a/server/CGameHandler.cpp b/server/CGameHandler.cpp index 4eab99cc4..46792d646 100644 --- a/server/CGameHandler.cpp +++ b/server/CGameHandler.cpp @@ -3917,7 +3917,7 @@ bool CGameHandler::moveArtifact(const ArtifactLocation &al1, const ArtifactLocat (si32)dst.getHolderArtSet()->artifactsInBackpack.size() + GameConstants::BACKPACK_START))); } auto hero = boost::get>(dst.artHolder); - if (ArtifactUtils::checkSpellbookIsNeeded(hero, srcArtifact->artType->id, dst.slot)) + if(ArtifactUtils::checkSpellbookIsNeeded(hero, srcArtifact->artType->id, dst.slot)) giveHeroNewArtifact(hero, VLC->arth->objects[ArtifactID::SPELLBOOK], ArtifactPosition::SPELLBOOK); MoveArtifact ma(&src, &dst); @@ -3925,98 +3925,86 @@ bool CGameHandler::moveArtifact(const ArtifactLocation &al1, const ArtifactLocat return true; } -bool CGameHandler::bulkMoveArtifacts(ObjectInstanceID srcHero, ObjectInstanceID dstHero) +bool CGameHandler::bulkMoveArtifacts(ObjectInstanceID srcHero, ObjectInstanceID dstHero, bool swap) { // Make sure exchange is even possible between the two heroes. - if (!isAllowedExchange(srcHero, dstHero)) + if(!isAllowedExchange(srcHero, dstHero)) COMPLAIN_RET("That heroes cannot make any exchange!"); auto psrcHero = getHero(srcHero); auto pdstHero = getHero(dstHero); - BulkMoveArtifacts ma(static_cast>(psrcHero), - static_cast>(pdstHero), false); - auto slots = &ma.artsPack0; - // Temporary fitting set for artifacts. Used to select available slots before sending data. - CArtifactFittingSet ArtFittingSet(pdstHero->bearerType()); - ArtFittingSet.artifactsInBackpack = pdstHero->artifactsInBackpack; - ArtFittingSet.artifactsWorn = pdstHero->artifactsWorn; + BulkMoveArtifacts ma(static_cast>(psrcHero), + static_cast>(pdstHero), swap); + auto & slotsSrcDst = ma.artsPack0; + auto & slotsDstSrc = ma.artsPack1; - // Move over artifacts that are worn - for(auto & artInfo : psrcHero->artifactsWorn) + if(swap) { - if(ArtifactUtils::isArtRemovable(artInfo)) + auto moveArtsWorn = [this](const CGHeroInstance * srcHero, const CGHeroInstance * dstHero, + std::vector & slots) -> void + { + for(auto & artifact : srcHero->artifactsWorn) + { + if(artifact.second.locked) + continue; + if(!ArtifactUtils::isArtRemovable(artifact)) + continue; + slots.push_back(BulkMoveArtifacts::LinkedSlots(artifact.first, artifact.first)); + + if(ArtifactUtils::checkSpellbookIsNeeded(dstHero, artifact.second.getArt()->artType->id, artifact.first)) + giveHeroNewArtifact(dstHero, VLC->arth->objects[ArtifactID::SPELLBOOK], ArtifactPosition::SPELLBOOK); + } + }; + // Move over artifacts that are worn srcHero -> dstHero + moveArtsWorn(psrcHero, pdstHero, slotsSrcDst); + // Move over artifacts that are worn dstHero -> srcHero + moveArtsWorn(pdstHero, psrcHero, slotsDstSrc); + // Move over artifacts that are in backpack srcHero -> dstHero + for(auto & slotInfo : psrcHero->artifactsInBackpack) + { + auto slot = psrcHero->getArtPos(slotInfo.artifact); + slotsSrcDst.push_back(BulkMoveArtifacts::LinkedSlots(slot, slot)); + } + // Move over artifacts that are in backpack dstHero -> srcHero + for(auto & slotInfo : pdstHero->artifactsInBackpack) + { + auto slot = pdstHero->getArtPos(slotInfo.artifact); + slotsDstSrc.push_back(BulkMoveArtifacts::LinkedSlots(slot, slot)); + } + } + else + { + auto & slots = ma.artsPack0; + // Temporary fitting set for artifacts. Used to select available slots before sending data. + CArtifactFittingSet ArtFittingSet(pdstHero->bearerType()); + ArtFittingSet.artifactsInBackpack = pdstHero->artifactsInBackpack; + ArtFittingSet.artifactsWorn = pdstHero->artifactsWorn; + + auto moveArtifact = [this, &ArtFittingSet, &slots](const CArtifactInstance * artifact, + ArtifactPosition srcSlot, const CGHeroInstance * pdstHero) -> void { - auto artifact = psrcHero->getArt(artInfo.first); auto dstSlot = ArtifactUtils::getArtifactDstPosition(artifact, &ArtFittingSet, pdstHero->bearerType()); - ArtFittingSet.putArtifact(dstSlot, - static_cast>(psrcHero->getArt(artInfo.first))); - slots->push_back(BulkMoveArtifacts::LinkedSlots(artInfo.first, dstSlot)); - + ArtFittingSet.putArtifact(dstSlot, static_cast>(artifact)); + slots.push_back(BulkMoveArtifacts::LinkedSlots(srcSlot, dstSlot)); + if(ArtifactUtils::checkSpellbookIsNeeded(pdstHero, artifact->artType->id, dstSlot)) giveHeroNewArtifact(pdstHero, VLC->arth->objects[ArtifactID::SPELLBOOK], ArtifactPosition::SPELLBOOK); - } - } - // Move over artifacts that are in backpack - for(auto & slotInfo : psrcHero->artifactsInBackpack) - { - auto artifact = psrcHero->getArt(psrcHero->getArtPos(slotInfo.artifact)); - auto dstSlot = ArtifactUtils::getArtifactDstPosition(artifact, &ArtFittingSet, pdstHero->bearerType()); - ArtFittingSet.putArtifact(dstSlot, static_cast>(slotInfo.artifact)); - slots->push_back(BulkMoveArtifacts::LinkedSlots(psrcHero->getArtPos(slotInfo.artifact), dstSlot)); - - if(ArtifactUtils::checkSpellbookIsNeeded(pdstHero, artifact->artType->id, dstSlot)) - giveHeroNewArtifact(pdstHero, VLC->arth->objects[ArtifactID::SPELLBOOK], ArtifactPosition::SPELLBOOK); - } - sendAndApply(&ma); - return true; -} + }; -bool CGameHandler::bulkSwapArtifacts(ObjectInstanceID leftHero, ObjectInstanceID rightHero) -{ - // Make sure exchange is even possible between the two heroes. - if(!isAllowedExchange(leftHero, rightHero)) - COMPLAIN_RET("That heroes cannot make any exchange!"); - - auto pleftHero = getHero(leftHero); - auto prightHero = getHero(rightHero); - BulkMoveArtifacts ma(static_cast>(pleftHero), - static_cast>(prightHero), true); - ma.srcArtHolder = static_cast>(prightHero); - ma.dstArtHolder = static_cast>(pleftHero); - auto & slotsLeftRight = ma.artsPack0; - auto & slotsRightLeft = ma.artsPack1; - - auto moveArtsWorn = [this](const CGHeroInstance * srcHero, const CGHeroInstance * dstHero, - std::vector & slots) -> void - { - for(auto & artifact : srcHero->artifactsWorn) + // Move over artifacts that are worn + for(auto & artInfo : psrcHero->artifactsWorn) { - if(artifact.second.locked) - continue; - if(!ArtifactUtils::isArtRemovable(artifact)) - continue; - slots.push_back(BulkMoveArtifacts::LinkedSlots(artifact.first, artifact.first)); - - if(ArtifactUtils::checkSpellbookIsNeeded(dstHero, artifact.second.getArt()->artType->id, artifact.first)) - giveHeroNewArtifact(dstHero, VLC->arth->objects[ArtifactID::SPELLBOOK], ArtifactPosition::SPELLBOOK); + if(ArtifactUtils::isArtRemovable(artInfo)) + { + moveArtifact(psrcHero->getArt(artInfo.first), artInfo.first, pdstHero); + } + } + // Move over artifacts that are in backpack + for(auto & slotInfo : psrcHero->artifactsInBackpack) + { + moveArtifact(psrcHero->getArt(psrcHero->getArtPos(slotInfo.artifact)), psrcHero->getArtPos(slotInfo.artifact), pdstHero); } - }; - // Move over artifacts that are worn leftHero -> rightHero - moveArtsWorn(pleftHero, prightHero, slotsLeftRight); - // Move over artifacts that are worn rightHero -> leftHero - moveArtsWorn(prightHero, pleftHero, slotsRightLeft); - // Move over artifacts that are in backpack leftHero -> rightHero - for(auto & slotInfo : pleftHero->artifactsInBackpack) - { - auto slot = pleftHero->getArtPos(slotInfo.artifact); - slotsLeftRight.push_back(BulkMoveArtifacts::LinkedSlots(slot, slot)); - } - // Move over artifacts that are in backpack rightHero -> leftHero - for(auto & slotInfo : prightHero->artifactsInBackpack) - { - auto slot = prightHero->getArtPos(slotInfo.artifact); - slotsRightLeft.push_back(BulkMoveArtifacts::LinkedSlots(slot, slot)); } sendAndApply(&ma); return true; diff --git a/server/CGameHandler.h b/server/CGameHandler.h index 0b90b3cf0..5d9800e49 100644 --- a/server/CGameHandler.h +++ b/server/CGameHandler.h @@ -181,8 +181,7 @@ public: void putArtifact(const ArtifactLocation &al, const CArtifactInstance *a) override; void removeArtifact(const ArtifactLocation &al) override; bool moveArtifact(const ArtifactLocation & al1, const ArtifactLocation & al2) override; - bool bulkMoveArtifacts(ObjectInstanceID srcHero, ObjectInstanceID dstHero); - bool bulkSwapArtifacts(ObjectInstanceID leftHero, ObjectInstanceID rightHero); + bool bulkMoveArtifacts(ObjectInstanceID srcHero, ObjectInstanceID dstHero, bool swap); void synchronizeArtifactHandlerLists(); void showCompInfo(ShowInInfobox * comp) override; diff --git a/server/NetPacksServer.cpp b/server/NetPacksServer.cpp index 7a2666512..bc80920a3 100644 --- a/server/NetPacksServer.cpp +++ b/server/NetPacksServer.cpp @@ -184,10 +184,7 @@ bool BulkExchangeArtifacts::applyGh(CGameHandler * gh) { const CGHeroInstance * pSrcHero = gh->getHero(srcHero); throwOnWrongPlayer(gh, pSrcHero->getOwner()); - if(swap) - return gh->bulkSwapArtifacts(srcHero, dstHero); - else - return gh->bulkMoveArtifacts(srcHero, dstHero); + return gh->bulkMoveArtifacts(srcHero, dstHero, swap); } bool AssembleArtifacts::applyGh(CGameHandler * gh) From 6e5932c016c975080be86e2cd5c19b74c135e88b Mon Sep 17 00:00:00 2001 From: SoundSSGood <87084363+SoundSSGood@users.noreply.github.com> Date: Thu, 10 Nov 2022 20:48:19 +0200 Subject: [PATCH 15/31] Apply suggested changes next part --- client/CPlayerInterface.cpp | 3 ++- client/NetPacksClient.cpp | 21 +++++++-------------- lib/NetPacks.h | 11 ++++++----- lib/NetPacksLib.cpp | 2 +- 4 files changed, 16 insertions(+), 21 deletions(-) diff --git a/client/CPlayerInterface.cpp b/client/CPlayerInterface.cpp index e6c8faff4..93556219a 100644 --- a/client/CPlayerInterface.cpp +++ b/client/CPlayerInterface.cpp @@ -2591,7 +2591,8 @@ void CPlayerInterface::artifactMoved(const ArtifactLocation &src, const Artifact if (artWin) artWin->artifactMoved(src, dst); } - GH.objsToBlit.back()->redraw(); + if(!GH.objsToBlit.empty()) + GH.objsToBlit.back()->redraw(); } void CPlayerInterface::artifactPossibleAssembling(const ArtifactLocation & dst) diff --git a/client/NetPacksClient.cpp b/client/NetPacksClient.cpp index f625ec226..f2d27ffdc 100644 --- a/client/NetPacksClient.cpp +++ b/client/NetPacksClient.cpp @@ -285,20 +285,9 @@ void MoveArtifact::applyCl(CClient *cl) void BulkMoveArtifacts::applyCl(CClient * cl) { - auto & movingArts = artsPack0; - for(auto & slotToMove : movingArts) + auto applyMove = [this, cl](std::vector & artsPack) -> void { - auto srcLoc = ArtifactLocation(srcArtHolder, slotToMove.srcPos); - auto dstLoc = ArtifactLocation(dstArtHolder, slotToMove.dstPos); - callInterfaceIfPresent(cl, srcLoc.owningPlayer(), &IGameEventsReceiver::artifactMoved, srcLoc, dstLoc); - if (srcLoc.owningPlayer() != dstLoc.owningPlayer()) - callInterfaceIfPresent(cl, dstLoc.owningPlayer(), &IGameEventsReceiver::artifactMoved, srcLoc, dstLoc); - } - - if(swap) - { - movingArts = artsPack1; - for(auto & slotToMove : movingArts) + for(auto & slotToMove : artsPack) { auto srcLoc = ArtifactLocation(srcArtHolder, slotToMove.srcPos); auto dstLoc = ArtifactLocation(dstArtHolder, slotToMove.dstPos); @@ -306,7 +295,11 @@ void BulkMoveArtifacts::applyCl(CClient * cl) if(srcLoc.owningPlayer() != dstLoc.owningPlayer()) callInterfaceIfPresent(cl, dstLoc.owningPlayer(), &IGameEventsReceiver::artifactMoved, srcLoc, dstLoc); } - } + }; + + applyMove(artsPack0); + if(swap) + applyMove(artsPack1); } void AssembledArtifact::applyCl(CClient *cl) diff --git a/lib/NetPacks.h b/lib/NetPacks.h index ee29aada9..115f1647f 100644 --- a/lib/NetPacks.h +++ b/lib/NetPacks.h @@ -1029,8 +1029,9 @@ struct BulkMoveArtifacts : CArtifactOperationPack TArtHolder srcArtHolder; TArtHolder dstArtHolder; - BulkMoveArtifacts() {} - BulkMoveArtifacts(TArtHolder srcArtHolder, TArtHolder dstArtHolder, bool swap) + BulkMoveArtifacts() + : swap(false) {} + BulkMoveArtifacts(TArtHolder srcArtHolder, TArtHolder dstArtHolder, bool swap) : srcArtHolder(srcArtHolder), dstArtHolder(dstArtHolder), swap(swap) {} void applyCl(CClient * cl); @@ -2248,10 +2249,10 @@ struct BulkExchangeArtifacts : public CPackForServer ObjectInstanceID dstHero; bool swap; - BulkExchangeArtifacts() = default; + BulkExchangeArtifacts() + : swap(false) {} BulkExchangeArtifacts(ObjectInstanceID srcHero, ObjectInstanceID dstHero, bool swap) - : srcHero(srcHero), dstHero(dstHero), swap(swap) - {} + : srcHero(srcHero), dstHero(dstHero), swap(swap) {} bool applyGh(CGameHandler * gh); template void serialize(Handler & h, const int version) diff --git a/lib/NetPacksLib.cpp b/lib/NetPacksLib.cpp index aeca09873..62b69795e 100644 --- a/lib/NetPacksLib.cpp +++ b/lib/NetPacksLib.cpp @@ -1097,7 +1097,6 @@ DLL_LINKAGE void MoveArtifact::applyGs(CGameState * gs) DLL_LINKAGE void BulkMoveArtifacts::applyGs(CGameState * gs) { - int numBackpackArtifactsMoved = 0; if(swap) { // Swap @@ -1144,6 +1143,7 @@ DLL_LINKAGE void BulkMoveArtifacts::applyGs(CGameState * gs) else { // Move + int numBackpackArtifactsMoved = 0; for(auto & slot : artsPack0) { // When an object gets removed from the backpack, the backpack shrinks From 36761526443e1bf2bb55f3d023d0e7ca5a7172f0 Mon Sep 17 00:00:00 2001 From: Andrii Danylchenko Date: Thu, 10 Nov 2022 21:10:34 +0200 Subject: [PATCH 16/31] #1102 - NKAI: one more freeze - no mains with strong army --- AI/Nullkiller/Behaviors/BuyArmyBehavior.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/AI/Nullkiller/Behaviors/BuyArmyBehavior.cpp b/AI/Nullkiller/Behaviors/BuyArmyBehavior.cpp index c4e96bb54..366f5f076 100644 --- a/AI/Nullkiller/Behaviors/BuyArmyBehavior.cpp +++ b/AI/Nullkiller/Behaviors/BuyArmyBehavior.cpp @@ -57,8 +57,7 @@ Goals::TGoalVec BuyArmyBehavior::decompose() const continue; } - if(ai->nullkiller->heroManager->getHeroRole(targetHero) == HeroRole::MAIN - && targetHero->getArmyStrength() >= 300) + if(ai->nullkiller->heroManager->getHeroRole(targetHero) == HeroRole::MAIN) { auto reinforcement = ai->nullkiller->armyManager->howManyReinforcementsCanGet( targetHero, From 9647758812226e25be4d464f9d0e00ff46de91d6 Mon Sep 17 00:00:00 2001 From: SoundSSGood <87084363+SoundSSGood@users.noreply.github.com> Date: Thu, 10 Nov 2022 23:24:41 +0200 Subject: [PATCH 17/31] Apply suggested changes next part --- CCallback.cpp | 11 ++--------- CCallback.h | 6 ++---- client/windows/GUIClasses.cpp | 4 ++-- 3 files changed, 6 insertions(+), 15 deletions(-) diff --git a/CCallback.cpp b/CCallback.cpp index 36936a0b8..b56aeb2c8 100644 --- a/CCallback.cpp +++ b/CCallback.cpp @@ -181,16 +181,9 @@ bool CCallback::assembleArtifacts (const CGHeroInstance * hero, ArtifactPosition return true; } -bool CCallback::bulkMoveArtifacts(ObjectInstanceID srcHero, ObjectInstanceID dstHero) +bool CCallback::bulkMoveArtifacts(ObjectInstanceID srcHero, ObjectInstanceID dstHero, bool swap) { - BulkExchangeArtifacts bma(srcHero, dstHero, false); - sendRequest(&bma); - return true; -} - -bool CCallback::bulkSwapArtifacts(ObjectInstanceID leftHero, ObjectInstanceID rightHero) -{ - BulkExchangeArtifacts bma(leftHero, rightHero, true); + BulkExchangeArtifacts bma(srcHero, dstHero, swap); sendRequest(&bma); return true; } diff --git a/CCallback.h b/CCallback.h index b9b3dcab4..61f240568 100644 --- a/CCallback.h +++ b/CCallback.h @@ -97,8 +97,7 @@ public: // Moves all artifacts from one hero to another - virtual bool bulkMoveArtifacts(ObjectInstanceID srcHero, ObjectInstanceID dstHero) = 0; - virtual bool bulkSwapArtifacts(ObjectInstanceID leftHero, ObjectInstanceID rightHero) = 0; + virtual bool bulkMoveArtifacts(ObjectInstanceID srcHero, ObjectInstanceID dstHero, bool swap) = 0; }; class CBattleCallback : public IBattleCallback, public CPlayerBattleCallback @@ -156,8 +155,7 @@ public: bool dismissHero(const CGHeroInstance * hero) override; bool swapArtifacts(const ArtifactLocation &l1, const ArtifactLocation &l2) override; bool assembleArtifacts(const CGHeroInstance * hero, ArtifactPosition artifactSlot, bool assemble, ArtifactID assembleTo) override; - bool bulkMoveArtifacts(ObjectInstanceID srcHero, ObjectInstanceID dstHero) override; - bool bulkSwapArtifacts(ObjectInstanceID leftHero, ObjectInstanceID rightHero) override; + bool bulkMoveArtifacts(ObjectInstanceID srcHero, ObjectInstanceID dstHero, bool swap) override; bool buildBuilding(const CGTownInstance *town, BuildingID buildingID) override; void recruitCreatures(const CGDwelling * obj, const CArmedInstance * dst, CreatureID ID, ui32 amount, si32 level=-1) override; bool dismissCreature(const CArmedInstance *obj, SlotID stackPos) override; diff --git a/client/windows/GUIClasses.cpp b/client/windows/GUIClasses.cpp index 07ce6e590..af55bb14e 100644 --- a/client/windows/GUIClasses.cpp +++ b/client/windows/GUIClasses.cpp @@ -890,7 +890,7 @@ std::function CExchangeController::onSwapArtifacts() { GsThread::run([=] { - cb->bulkSwapArtifacts(left->id, right->id); + cb->bulkMoveArtifacts(left->id, right->id, true); }); }; } @@ -1047,7 +1047,7 @@ void CExchangeController::moveArtifacts(bool leftToRight) GsThread::run([=] { - cb->bulkMoveArtifacts(source->id, target->id); + cb->bulkMoveArtifacts(source->id, target->id, false); }); } From 3142f32cbb233bb21a13b10db8077267ccceeb86 Mon Sep 17 00:00:00 2001 From: SoundSSGood <87084363+SoundSSGood@users.noreply.github.com> Date: Fri, 11 Nov 2022 01:01:55 +0200 Subject: [PATCH 18/31] Fix for callback return. More code optimization --- CCallback.cpp | 3 +-- CCallback.h | 4 ++-- client/windows/GUIClasses.cpp | 2 +- server/CGameHandler.cpp | 26 +++++++++++++------------- 4 files changed, 17 insertions(+), 18 deletions(-) diff --git a/CCallback.cpp b/CCallback.cpp index b56aeb2c8..6545c9729 100644 --- a/CCallback.cpp +++ b/CCallback.cpp @@ -181,11 +181,10 @@ bool CCallback::assembleArtifacts (const CGHeroInstance * hero, ArtifactPosition return true; } -bool CCallback::bulkMoveArtifacts(ObjectInstanceID srcHero, ObjectInstanceID dstHero, bool swap) +void CCallback::bulkMoveArtifacts(ObjectInstanceID srcHero, ObjectInstanceID dstHero, bool swap) { BulkExchangeArtifacts bma(srcHero, dstHero, swap); sendRequest(&bma); - return true; } bool CCallback::buildBuilding(const CGTownInstance *town, BuildingID buildingID) diff --git a/CCallback.h b/CCallback.h index 61f240568..d96d9dd83 100644 --- a/CCallback.h +++ b/CCallback.h @@ -97,7 +97,7 @@ public: // Moves all artifacts from one hero to another - virtual bool bulkMoveArtifacts(ObjectInstanceID srcHero, ObjectInstanceID dstHero, bool swap) = 0; + virtual void bulkMoveArtifacts(ObjectInstanceID srcHero, ObjectInstanceID dstHero, bool swap) = 0; }; class CBattleCallback : public IBattleCallback, public CPlayerBattleCallback @@ -155,7 +155,7 @@ public: bool dismissHero(const CGHeroInstance * hero) override; bool swapArtifacts(const ArtifactLocation &l1, const ArtifactLocation &l2) override; bool assembleArtifacts(const CGHeroInstance * hero, ArtifactPosition artifactSlot, bool assemble, ArtifactID assembleTo) override; - bool bulkMoveArtifacts(ObjectInstanceID srcHero, ObjectInstanceID dstHero, bool swap) override; + void bulkMoveArtifacts(ObjectInstanceID srcHero, ObjectInstanceID dstHero, bool swap) override; bool buildBuilding(const CGTownInstance *town, BuildingID buildingID) override; void recruitCreatures(const CGDwelling * obj, const CArmedInstance * dst, CreatureID ID, ui32 amount, si32 level=-1) override; bool dismissCreature(const CArmedInstance *obj, SlotID stackPos) override; diff --git a/client/windows/GUIClasses.cpp b/client/windows/GUIClasses.cpp index af55bb14e..0f9875d96 100644 --- a/client/windows/GUIClasses.cpp +++ b/client/windows/GUIClasses.cpp @@ -1058,7 +1058,7 @@ void CExchangeController::moveArtifact( { auto srcLocation = ArtifactLocation(source, srcPosition); auto dstLocation = ArtifactLocation(target, - ArtifactUtils::getArtifactDstPosition(source->getArt(srcPosition), target, target->bearerType())); + ArtifactUtils::getArtifactDstPosition(source->getArt(srcPosition), target, target->bearerType())); cb->swapArtifacts(srcLocation, dstLocation); } diff --git a/server/CGameHandler.cpp b/server/CGameHandler.cpp index 46792d646..ad5a573ff 100644 --- a/server/CGameHandler.cpp +++ b/server/CGameHandler.cpp @@ -3956,37 +3956,37 @@ bool CGameHandler::bulkMoveArtifacts(ObjectInstanceID srcHero, ObjectInstanceID giveHeroNewArtifact(dstHero, VLC->arth->objects[ArtifactID::SPELLBOOK], ArtifactPosition::SPELLBOOK); } }; + auto moveArtsInBackpack = [](const CGHeroInstance * pHero, + std::vector & slots) -> void + { + for(auto & slotInfo : pHero->artifactsInBackpack) + { + auto slot = pHero->getArtPos(slotInfo.artifact); + slots.push_back(BulkMoveArtifacts::LinkedSlots(slot, slot)); + } + }; // Move over artifacts that are worn srcHero -> dstHero moveArtsWorn(psrcHero, pdstHero, slotsSrcDst); // Move over artifacts that are worn dstHero -> srcHero moveArtsWorn(pdstHero, psrcHero, slotsDstSrc); // Move over artifacts that are in backpack srcHero -> dstHero - for(auto & slotInfo : psrcHero->artifactsInBackpack) - { - auto slot = psrcHero->getArtPos(slotInfo.artifact); - slotsSrcDst.push_back(BulkMoveArtifacts::LinkedSlots(slot, slot)); - } + moveArtsInBackpack(psrcHero, slotsSrcDst); // Move over artifacts that are in backpack dstHero -> srcHero - for(auto & slotInfo : pdstHero->artifactsInBackpack) - { - auto slot = pdstHero->getArtPos(slotInfo.artifact); - slotsDstSrc.push_back(BulkMoveArtifacts::LinkedSlots(slot, slot)); - } + moveArtsInBackpack(pdstHero, slotsDstSrc); } else { - auto & slots = ma.artsPack0; // Temporary fitting set for artifacts. Used to select available slots before sending data. CArtifactFittingSet ArtFittingSet(pdstHero->bearerType()); ArtFittingSet.artifactsInBackpack = pdstHero->artifactsInBackpack; ArtFittingSet.artifactsWorn = pdstHero->artifactsWorn; - auto moveArtifact = [this, &ArtFittingSet, &slots](const CArtifactInstance * artifact, + auto moveArtifact = [this, &ArtFittingSet, &slotsSrcDst](const CArtifactInstance * artifact, ArtifactPosition srcSlot, const CGHeroInstance * pdstHero) -> void { auto dstSlot = ArtifactUtils::getArtifactDstPosition(artifact, &ArtFittingSet, pdstHero->bearerType()); ArtFittingSet.putArtifact(dstSlot, static_cast>(artifact)); - slots.push_back(BulkMoveArtifacts::LinkedSlots(srcSlot, dstSlot)); + slotsSrcDst.push_back(BulkMoveArtifacts::LinkedSlots(srcSlot, dstSlot)); if(ArtifactUtils::checkSpellbookIsNeeded(pdstHero, artifact->artType->id, dstSlot)) giveHeroNewArtifact(pdstHero, VLC->arth->objects[ArtifactID::SPELLBOOK], ArtifactPosition::SPELLBOOK); From 84841a5f0a713a25c12110d18a03dbdee811d39e Mon Sep 17 00:00:00 2001 From: SoundSSGood <87084363+SoundSSGood@users.noreply.github.com> Date: Sat, 12 Nov 2022 19:30:24 +0200 Subject: [PATCH 19/31] BulkMoveArtifacts::applyGs reworked --- lib/NetPacksLib.cpp | 107 +++++++++++++++++++++----------------------- 1 file changed, 52 insertions(+), 55 deletions(-) diff --git a/lib/NetPacksLib.cpp b/lib/NetPacksLib.cpp index 62b69795e..77c5f09ca 100644 --- a/lib/NetPacksLib.cpp +++ b/lib/NetPacksLib.cpp @@ -1097,74 +1097,71 @@ DLL_LINKAGE void MoveArtifact::applyGs(CGameState * gs) DLL_LINKAGE void BulkMoveArtifacts::applyGs(CGameState * gs) { + enum class EBulkArtsOp + { + BULK_MOVE, + BULK_REMOVE, + BULK_PUT + }; + + auto bulkArtsOperation = [this](std::vector & artsPack, + CArtifactSet * artSet, EBulkArtsOp operation) -> void + { + int numBackpackArtifactsMoved = 0; + for(auto & slot : artsPack) + { + // When an object gets removed from the backpack, the backpack shrinks + // so all the following indices will be affected. Thus, we need to update + // the subsequent artifact slots to account for that + auto srcPos = slot.srcPos; + if((srcPos >= GameConstants::BACKPACK_START) && (operation != EBulkArtsOp::BULK_PUT)) + { + srcPos = ArtifactPosition(srcPos.num - numBackpackArtifactsMoved); + } + auto slotInfo = artSet->getSlot(srcPos); + assert(slotInfo); + auto art = const_cast(slotInfo->getArt()); + assert(art); + switch(operation) + { + case EBulkArtsOp::BULK_MOVE: + const_cast(art)->move( + ArtifactLocation(srcArtHolder, srcPos), ArtifactLocation(dstArtHolder, slot.dstPos)); + break; + case EBulkArtsOp::BULK_REMOVE: + art->removeFrom(ArtifactLocation(dstArtHolder, srcPos)); + break; + case EBulkArtsOp::BULK_PUT: + art->putAt(ArtifactLocation(srcArtHolder, slot.dstPos)); + break; + default: + break; + } + + if(srcPos >= GameConstants::BACKPACK_START) + { + numBackpackArtifactsMoved++; + } + } + }; + if(swap) { // Swap auto leftSet = getSrcHolderArtSet(); auto rightSet = getDstHolderArtSet(); CArtifactFittingSet ArtFittingSet(leftSet->bearerType()); - std::vector> unmovableArtsLeftHero, unmovableArtsRightHero; - - // Keep unmovable artifacts separately until the swap - for(auto artPos : ArtifactUtils::unmovablePositions()) - { - auto slotInfo = leftSet->getSlot(artPos); - if(slotInfo) - { - unmovableArtsLeftHero.push_back(std::make_pair(artPos, *slotInfo)); - leftSet->eraseArtSlot(artPos); - } - - slotInfo = rightSet->getSlot(artPos); - if(slotInfo) - { - unmovableArtsRightHero.push_back(std::make_pair(artPos, *slotInfo)); - rightSet->eraseArtSlot(artPos); - } - } ArtFittingSet.artifactsWorn = rightSet->artifactsWorn; ArtFittingSet.artifactsInBackpack = rightSet->artifactsInBackpack; - rightSet->artifactsWorn = leftSet->artifactsWorn; - rightSet->artifactsInBackpack = leftSet->artifactsInBackpack; - leftSet->artifactsWorn = ArtFittingSet.artifactsWorn; - leftSet->artifactsInBackpack = ArtFittingSet.artifactsInBackpack; - // Return non movable artifacts to their place after the swap - for(auto & art : unmovableArtsLeftHero) - { - leftSet->putArtifact(art.first, art.second.artifact); - } - for(auto & art : unmovableArtsRightHero) - { - rightSet->putArtifact(art.first, art.second.artifact); - } + bulkArtsOperation(artsPack1, rightSet, EBulkArtsOp::BULK_REMOVE); + bulkArtsOperation(artsPack0, leftSet, EBulkArtsOp::BULK_MOVE); + bulkArtsOperation(artsPack1, &ArtFittingSet, EBulkArtsOp::BULK_PUT); } else { - // Move - int numBackpackArtifactsMoved = 0; - for(auto & slot : artsPack0) - { - // When an object gets removed from the backpack, the backpack shrinks - // so all the following indices will be affected. Thus, we need to update - // the subsequent artifact slots to account for that - if(slot.srcPos >= GameConstants::BACKPACK_START) - { - slot.srcPos = ArtifactPosition(slot.srcPos.num - numBackpackArtifactsMoved); - } - auto srcSlotInfo = getSrcHolderArtSet()->getSlot(slot.srcPos); - assert(srcSlotInfo); - - auto art = srcSlotInfo->getArt(); - const_cast(art)->move( - ArtifactLocation(srcArtHolder, slot.srcPos), ArtifactLocation(dstArtHolder, slot.dstPos)); - - if(slot.srcPos >= GameConstants::BACKPACK_START) - { - numBackpackArtifactsMoved++; - } - } + bulkArtsOperation(artsPack0, getSrcHolderArtSet(), EBulkArtsOp::BULK_MOVE); } } From 79bc82af63ff60cfb7b41a5b944535d8fd5e46c4 Mon Sep 17 00:00:00 2001 From: lainon Date: Sun, 13 Nov 2022 05:35:16 +0300 Subject: [PATCH 20/31] Fix [3144] --- client/CServerHandler.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/CServerHandler.cpp b/client/CServerHandler.cpp index 1390680f5..37c5a11a5 100644 --- a/client/CServerHandler.cpp +++ b/client/CServerHandler.cpp @@ -489,7 +489,7 @@ void CServerHandler::sendMessage(const std::string & txt) const std::string connectedId, playerColorId; readed >> connectedId; readed >> playerColorId; - if(connectedId.length(), playerColorId.length()) // BUG https://bugs.vcmi.eu/view.php?id=3144 + if(connectedId.length() && playerColorId.length()) { ui8 connected = boost::lexical_cast(connectedId); auto color = PlayerColor(boost::lexical_cast(playerColorId)); From 4af9bc2461b321e6fb42f2b593ee1616af9b618f Mon Sep 17 00:00:00 2001 From: Ivan Savenko Date: Sun, 13 Nov 2022 14:05:51 +0200 Subject: [PATCH 21/31] Music: remember playback position of music tracks Town & terrain themes will now resume from previously stopped position instead of playing from start, as it was in original game. Fixes #965 --- client/CMusicHandler.cpp | 55 ++++++++++++++++------- client/CMusicHandler.h | 16 ++++--- client/CPlayerInterface.cpp | 2 +- client/battle/CBattleInterface.cpp | 4 +- client/battle/CBattleInterfaceClasses.cpp | 4 +- client/mainmenu/CMainMenu.cpp | 2 +- client/mainmenu/CPrologEpilogVideo.cpp | 2 +- client/windows/CAdvmapInterface.cpp | 4 +- client/windows/CCastleInterface.cpp | 2 +- 9 files changed, 59 insertions(+), 32 deletions(-) diff --git a/client/CMusicHandler.cpp b/client/CMusicHandler.cpp index 97160bded..a6b30c11d 100644 --- a/client/CMusicHandler.cpp +++ b/client/CMusicHandler.cpp @@ -9,6 +9,7 @@ */ #include "StdInc.h" #include +#include #include "CMusicHandler.h" #include "CGameInfo.h" @@ -410,15 +411,15 @@ void CMusicHandler::release() CAudioBase::release(); } -void CMusicHandler::playMusic(const std::string & musicURI, bool loop) +void CMusicHandler::playMusic(const std::string & musicURI, bool loop, bool fromStart) { if (current && current->isTrack(musicURI)) return; - queueNext(this, "", musicURI, loop); + queueNext(this, "", musicURI, loop, fromStart); } -void CMusicHandler::playMusicFromSet(const std::string & whichSet, bool loop) +void CMusicHandler::playMusicFromSet(const std::string & whichSet, bool loop, bool fromStart) { auto selectedSet = musicsSet.find(whichSet); if (selectedSet == musicsSet.end()) @@ -431,10 +432,10 @@ void CMusicHandler::playMusicFromSet(const std::string & whichSet, bool loop) return; // in this mode - play random track from set - queueNext(this, whichSet, "", loop); + queueNext(this, whichSet, "", loop, fromStart); } -void CMusicHandler::playMusicFromSet(const std::string & whichSet, const std::string & entryID, bool loop) +void CMusicHandler::playMusicFromSet(const std::string & whichSet, const std::string & entryID, bool loop, bool fromStart) { auto selectedSet = musicsSet.find(whichSet); if (selectedSet == musicsSet.end()) @@ -454,7 +455,7 @@ void CMusicHandler::playMusicFromSet(const std::string & whichSet, const std::st return; // in this mode - play specific track from set - queueNext(this, "", selectedEntry->second, loop); + queueNext(this, "", selectedEntry->second, loop, fromStart); } void CMusicHandler::queueNext(std::unique_ptr queued) @@ -473,11 +474,11 @@ void CMusicHandler::queueNext(std::unique_ptr queued) } } -void CMusicHandler::queueNext(CMusicHandler *owner, const std::string & setName, const std::string & musicURI, bool looped) +void CMusicHandler::queueNext(CMusicHandler *owner, const std::string & setName, const std::string & musicURI, bool looped, bool fromStart) { try { - queueNext(make_unique(owner, setName, musicURI, looped)); + queueNext(make_unique(owner, setName, musicURI, looped, fromStart)); } catch(std::exception &e) { @@ -526,10 +527,13 @@ void CMusicHandler::musicFinishedCallback() } } -MusicEntry::MusicEntry(CMusicHandler *owner, std::string setName, std::string musicURI, bool looped): +MusicEntry::MusicEntry(CMusicHandler *owner, std::string setName, std::string musicURI, bool looped, bool fromStart): owner(owner), music(nullptr), + startTime(uint64_t(-1)), + startPosition(0), loop(looped ? -1 : 1), + fromStart(fromStart), setName(std::move(setName)) { if (!musicURI.empty()) @@ -578,20 +582,39 @@ bool MusicEntry::play() } logGlobal->trace("Playing music file %s", currentName); - if(Mix_PlayMusic(music, 1) == -1) - { - logGlobal->error("Unable to play music (%s)", Mix_GetError()); - return false; - } - return true; + + if ( !fromStart && owner->trackPositions.count(currentName) > 0 && owner->trackPositions[currentName] > 0) + { + float timeToStart = owner->trackPositions[currentName]; + startPosition = std::round(timeToStart * 1000); + + if (Mix_FadeInMusicPos(music, 1, 1000, timeToStart) == -1) + { + logGlobal->error("Unable to play music (%s)", Mix_GetError()); + return false; + } + } + else if(Mix_PlayMusic(music, 1) == -1) + { + logGlobal->error("Unable to play music (%s)", Mix_GetError()); + return false; + } + + startTime = SDL_GetTicks64(); + return true; } bool MusicEntry::stop(int fade_ms) { if (Mix_PlayingMusic()) { - logGlobal->trace("Stopping music file %s", currentName); loop = 0; + uint64_t endTime = SDL_GetTicks64(); + assert(startTime != uint64_t(-1)); + float playDuration = (endTime - startTime + startPosition) / 1000.f; + owner->trackPositions[currentName] = playDuration; + logGlobal->info("Stopping music file %s at %f", currentName, playDuration); + Mix_FadeOutMusic(fade_ms); return true; } diff --git a/client/CMusicHandler.h b/client/CMusicHandler.h index fa69d8a28..72bd4fbb1 100644 --- a/client/CMusicHandler.h +++ b/client/CMusicHandler.h @@ -99,7 +99,10 @@ class MusicEntry Mix_Music *music; int loop; // -1 = indefinite - //if not null - set from which music will be randomly selected + bool fromStart; + uint64_t startTime; + uint64_t startPosition; + //if not null - set from which music will be randomly selected std::string setName; std::string currentName; @@ -110,7 +113,7 @@ public: bool isSet(std::string setName); bool isTrack(std::string trackName); - MusicEntry(CMusicHandler *owner, std::string setName, std::string musicURI, bool looped); + MusicEntry(CMusicHandler *owner, std::string setName, std::string musicURI, bool looped, bool fromStart); ~MusicEntry(); bool play(); @@ -128,10 +131,11 @@ private: std::unique_ptr current; std::unique_ptr next; - void queueNext(CMusicHandler *owner, const std::string & setName, const std::string & musicURI, bool looped); + void queueNext(CMusicHandler *owner, const std::string & setName, const std::string & musicURI, bool looped, bool fromStart); void queueNext(std::unique_ptr queued); std::map> musicsSet; + std::map trackPositions; public: CMusicHandler(); @@ -145,11 +149,11 @@ public: void setVolume(ui32 percent) override; /// play track by URI, if loop = true music will be looped - void playMusic(const std::string & musicURI, bool loop); + void playMusic(const std::string & musicURI, bool loop, bool fromStart); /// play random track from this set - void playMusicFromSet(const std::string & musicSet, bool loop); + void playMusicFromSet(const std::string & musicSet, bool loop, bool fromStart); /// play specific track from set - void playMusicFromSet(const std::string & musicSet, const std::string & entryID, bool loop); + void playMusicFromSet(const std::string & musicSet, const std::string & entryID, bool loop, bool fromStart); void stopMusic(int fade_ms=1000); void musicFinishedCallback(); diff --git a/client/CPlayerInterface.cpp b/client/CPlayerInterface.cpp index af40aa43f..25fa2bb1d 100644 --- a/client/CPlayerInterface.cpp +++ b/client/CPlayerInterface.cpp @@ -276,7 +276,7 @@ void CPlayerInterface::heroMoved(const TryMoveHero & details, bool verbose) { updateAmbientSounds(); //We may need to change music - select new track, music handler will change it if needed - CCS->musich->playMusicFromSet("terrain", LOCPLINT->cb->getTile(hero->visitablePos())->terType->name, true); + CCS->musich->playMusicFromSet("terrain", LOCPLINT->cb->getTile(hero->visitablePos())->terType->name, true, false); if(details.result == TryMoveHero::TELEPORTATION) { diff --git a/client/battle/CBattleInterface.cpp b/client/battle/CBattleInterface.cpp index 8576a3d66..856d66e26 100644 --- a/client/battle/CBattleInterface.cpp +++ b/client/battle/CBattleInterface.cpp @@ -411,7 +411,7 @@ CBattleInterface::CBattleInterface(const CCreatureSet *army1, const CCreatureSet { if(LOCPLINT->battleInt) { - CCS->musich->playMusicFromSet("battle", true); + CCS->musich->playMusicFromSet("battle", true, true); battleActionsStarted = true; blockUI(settings["session"]["spectate"].Bool()); battleIntroSoundChannel = -1; @@ -457,7 +457,7 @@ CBattleInterface::~CBattleInterface() if (adventureInt && adventureInt->selection) { const auto & terrain = *(LOCPLINT->cb->getTile(adventureInt->selection->visitablePos())->terType); - CCS->musich->playMusicFromSet("terrain", terrain.name, true); + CCS->musich->playMusicFromSet("terrain", terrain.name, true, false); } animsAreDisplayed.setn(false); } diff --git a/client/battle/CBattleInterfaceClasses.cpp b/client/battle/CBattleInterfaceClasses.cpp index f9902989f..cd199f424 100644 --- a/client/battle/CBattleInterfaceClasses.cpp +++ b/client/battle/CBattleInterfaceClasses.cpp @@ -506,7 +506,7 @@ CBattleResultWindow::CBattleResultWindow(const BattleResult & br, CPlayerInterfa break; } - CCS->musich->playMusic("Music/Win Battle", false); + CCS->musich->playMusic("Music/Win Battle", false, true); CCS->videoh->open("WIN3.BIK"); std::string str = CGI->generaltexth->allTexts[text]; @@ -543,7 +543,7 @@ CBattleResultWindow::CBattleResultWindow(const BattleResult & br, CPlayerInterfa logGlobal->error("Invalid battle result code %d. Assumed normal.", static_cast(br.result)); break; } - CCS->musich->playMusic(musicName, false); + CCS->musich->playMusic(musicName, false, true); CCS->videoh->open(videoName); labels.push_back(std::make_shared(235, 235, FONT_SMALL, CENTER, Colors::WHITE, CGI->generaltexth->allTexts[text])); diff --git a/client/mainmenu/CMainMenu.cpp b/client/mainmenu/CMainMenu.cpp index 83de1e91d..dd928d0da 100644 --- a/client/mainmenu/CMainMenu.cpp +++ b/client/mainmenu/CMainMenu.cpp @@ -115,7 +115,7 @@ void CMenuScreen::show(SDL_Surface * to) void CMenuScreen::activate() { - CCS->musich->playMusic("Music/MainMenu", true); + CCS->musich->playMusic("Music/MainMenu", true, true); if(!config["video"].isNull()) CCS->videoh->open(config["video"]["name"].String()); CIntObject::activate(); diff --git a/client/mainmenu/CPrologEpilogVideo.cpp b/client/mainmenu/CPrologEpilogVideo.cpp index 5f2e5d92b..1b9c590bd 100644 --- a/client/mainmenu/CPrologEpilogVideo.cpp +++ b/client/mainmenu/CPrologEpilogVideo.cpp @@ -29,7 +29,7 @@ CPrologEpilogVideo::CPrologEpilogVideo(CCampaignScenario::SScenarioPrologEpilog updateShadow(); CCS->videoh->open(CCampaignHandler::prologVideoName(spe.prologVideo)); - CCS->musich->playMusic("Music/" + CCampaignHandler::prologMusicName(spe.prologMusic), true); + CCS->musich->playMusic("Music/" + CCampaignHandler::prologMusicName(spe.prologMusic), true, true); // MPTODO: Custom campaign crashing on this? // voiceSoundHandle = CCS->soundh->playSound(CCampaignHandler::prologVoiceName(spe.prologVideo)); diff --git a/client/windows/CAdvmapInterface.cpp b/client/windows/CAdvmapInterface.cpp index 538fc554d..dd93d8677 100644 --- a/client/windows/CAdvmapInterface.cpp +++ b/client/windows/CAdvmapInterface.cpp @@ -1413,7 +1413,7 @@ void CAdvMapInt::select(const CArmedInstance *sel, bool centerView) auto pos = sel->visitablePos(); auto tile = LOCPLINT->cb->getTile(pos); if(tile) - CCS->musich->playMusicFromSet("terrain", tile->terType->name, true); + CCS->musich->playMusicFromSet("terrain", tile->terType->name, true, false); } if(centerView) centerOn(sel); @@ -1863,7 +1863,7 @@ void CAdvMapInt::aiTurnStarted() return; adjustActiveness(true); - CCS->musich->playMusicFromSet("enemy-turn", true); + CCS->musich->playMusicFromSet("enemy-turn", true, false); adventureInt->minimap.setAIRadar(true); adventureInt->infoBar.startEnemyTurn(LOCPLINT->cb->getCurrentPlayer()); adventureInt->infoBar.showAll(screen);//force refresh on inactive object diff --git a/client/windows/CCastleInterface.cpp b/client/windows/CCastleInterface.cpp index 9cfd8f991..dc2c62931 100644 --- a/client/windows/CCastleInterface.cpp +++ b/client/windows/CCastleInterface.cpp @@ -1171,7 +1171,7 @@ CCastleInterface::CCastleInterface(const CGTownInstance * Town, const CGTownInst townlist->onSelect = std::bind(&CCastleInterface::townChange, this); recreateIcons(); - CCS->musich->playMusic(town->town->clientInfo.musicTheme, true); + CCS->musich->playMusic(town->town->clientInfo.musicTheme, true, false); } CCastleInterface::~CCastleInterface() From 38b8fc0af8c82938d821af9e73c6981a5da174f2 Mon Sep 17 00:00:00 2001 From: Ivan Savenko Date: Sun, 13 Nov 2022 14:24:15 +0200 Subject: [PATCH 22/31] Formatting: space -> tabs --- client/CMusicHandler.cpp | 58 +++++++++++------------ client/CMusicHandler.h | 20 ++++---- client/CPlayerInterface.cpp | 2 +- client/battle/CBattleInterface.cpp | 4 +- client/battle/CBattleInterfaceClasses.cpp | 4 +- client/mainmenu/CMainMenu.cpp | 2 +- client/mainmenu/CPrologEpilogVideo.cpp | 2 +- client/windows/CAdvmapInterface.cpp | 4 +- client/windows/CCastleInterface.cpp | 2 +- 9 files changed, 49 insertions(+), 49 deletions(-) diff --git a/client/CMusicHandler.cpp b/client/CMusicHandler.cpp index a6b30c11d..0e0c674e4 100644 --- a/client/CMusicHandler.cpp +++ b/client/CMusicHandler.cpp @@ -416,7 +416,7 @@ void CMusicHandler::playMusic(const std::string & musicURI, bool loop, bool from if (current && current->isTrack(musicURI)) return; - queueNext(this, "", musicURI, loop, fromStart); + queueNext(this, "", musicURI, loop, fromStart); } void CMusicHandler::playMusicFromSet(const std::string & whichSet, bool loop, bool fromStart) @@ -432,7 +432,7 @@ void CMusicHandler::playMusicFromSet(const std::string & whichSet, bool loop, bo return; // in this mode - play random track from set - queueNext(this, whichSet, "", loop, fromStart); + queueNext(this, whichSet, "", loop, fromStart); } void CMusicHandler::playMusicFromSet(const std::string & whichSet, const std::string & entryID, bool loop, bool fromStart) @@ -455,7 +455,7 @@ void CMusicHandler::playMusicFromSet(const std::string & whichSet, const std::st return; // in this mode - play specific track from set - queueNext(this, "", selectedEntry->second, loop, fromStart); + queueNext(this, "", selectedEntry->second, loop, fromStart); } void CMusicHandler::queueNext(std::unique_ptr queued) @@ -478,7 +478,7 @@ void CMusicHandler::queueNext(CMusicHandler *owner, const std::string & setName, { try { - queueNext(make_unique(owner, setName, musicURI, looped, fromStart)); + queueNext(make_unique(owner, setName, musicURI, looped, fromStart)); } catch(std::exception &e) { @@ -530,10 +530,10 @@ void CMusicHandler::musicFinishedCallback() MusicEntry::MusicEntry(CMusicHandler *owner, std::string setName, std::string musicURI, bool looped, bool fromStart): owner(owner), music(nullptr), - startTime(uint64_t(-1)), - startPosition(0), + startTime(uint64_t(-1)), + startPosition(0), loop(looped ? -1 : 1), - fromStart(fromStart), + fromStart(fromStart), setName(std::move(setName)) { if (!musicURI.empty()) @@ -583,25 +583,25 @@ bool MusicEntry::play() logGlobal->trace("Playing music file %s", currentName); - if ( !fromStart && owner->trackPositions.count(currentName) > 0 && owner->trackPositions[currentName] > 0) - { - float timeToStart = owner->trackPositions[currentName]; - startPosition = std::round(timeToStart * 1000); + if ( !fromStart && owner->trackPositions.count(currentName) > 0 && owner->trackPositions[currentName] > 0) + { + float timeToStart = owner->trackPositions[currentName]; + startPosition = std::round(timeToStart * 1000); - if (Mix_FadeInMusicPos(music, 1, 1000, timeToStart) == -1) - { - logGlobal->error("Unable to play music (%s)", Mix_GetError()); - return false; - } - } - else if(Mix_PlayMusic(music, 1) == -1) - { - logGlobal->error("Unable to play music (%s)", Mix_GetError()); - return false; - } + if (Mix_FadeInMusicPos(music, 1, 1000, timeToStart) == -1) + { + logGlobal->error("Unable to play music (%s)", Mix_GetError()); + return false; + } + } + else if(Mix_PlayMusic(music, 1) == -1) + { + logGlobal->error("Unable to play music (%s)", Mix_GetError()); + return false; + } - startTime = SDL_GetTicks64(); - return true; + startTime = SDL_GetTicks64(); + return true; } bool MusicEntry::stop(int fade_ms) @@ -609,11 +609,11 @@ bool MusicEntry::stop(int fade_ms) if (Mix_PlayingMusic()) { loop = 0; - uint64_t endTime = SDL_GetTicks64(); - assert(startTime != uint64_t(-1)); - float playDuration = (endTime - startTime + startPosition) / 1000.f; - owner->trackPositions[currentName] = playDuration; - logGlobal->info("Stopping music file %s at %f", currentName, playDuration); + uint64_t endTime = SDL_GetTicks64(); + assert(startTime != uint64_t(-1)); + float playDuration = (endTime - startTime + startPosition) / 1000.f; + owner->trackPositions[currentName] = playDuration; + logGlobal->info("Stopping music file %s at %f", currentName, playDuration); Mix_FadeOutMusic(fade_ms); return true; diff --git a/client/CMusicHandler.h b/client/CMusicHandler.h index 72bd4fbb1..23b69ae49 100644 --- a/client/CMusicHandler.h +++ b/client/CMusicHandler.h @@ -99,10 +99,10 @@ class MusicEntry Mix_Music *music; int loop; // -1 = indefinite - bool fromStart; - uint64_t startTime; - uint64_t startPosition; - //if not null - set from which music will be randomly selected + bool fromStart; + uint64_t startTime; + uint64_t startPosition; + //if not null - set from which music will be randomly selected std::string setName; std::string currentName; @@ -113,7 +113,7 @@ public: bool isSet(std::string setName); bool isTrack(std::string trackName); - MusicEntry(CMusicHandler *owner, std::string setName, std::string musicURI, bool looped, bool fromStart); + MusicEntry(CMusicHandler *owner, std::string setName, std::string musicURI, bool looped, bool fromStart); ~MusicEntry(); bool play(); @@ -131,11 +131,11 @@ private: std::unique_ptr current; std::unique_ptr next; - void queueNext(CMusicHandler *owner, const std::string & setName, const std::string & musicURI, bool looped, bool fromStart); + void queueNext(CMusicHandler *owner, const std::string & setName, const std::string & musicURI, bool looped, bool fromStart); void queueNext(std::unique_ptr queued); std::map> musicsSet; - std::map trackPositions; + std::map trackPositions; public: CMusicHandler(); @@ -149,11 +149,11 @@ public: void setVolume(ui32 percent) override; /// play track by URI, if loop = true music will be looped - void playMusic(const std::string & musicURI, bool loop, bool fromStart); + void playMusic(const std::string & musicURI, bool loop, bool fromStart); /// play random track from this set - void playMusicFromSet(const std::string & musicSet, bool loop, bool fromStart); + void playMusicFromSet(const std::string & musicSet, bool loop, bool fromStart); /// play specific track from set - void playMusicFromSet(const std::string & musicSet, const std::string & entryID, bool loop, bool fromStart); + void playMusicFromSet(const std::string & musicSet, const std::string & entryID, bool loop, bool fromStart); void stopMusic(int fade_ms=1000); void musicFinishedCallback(); diff --git a/client/CPlayerInterface.cpp b/client/CPlayerInterface.cpp index 25fa2bb1d..428149a33 100644 --- a/client/CPlayerInterface.cpp +++ b/client/CPlayerInterface.cpp @@ -276,7 +276,7 @@ void CPlayerInterface::heroMoved(const TryMoveHero & details, bool verbose) { updateAmbientSounds(); //We may need to change music - select new track, music handler will change it if needed - CCS->musich->playMusicFromSet("terrain", LOCPLINT->cb->getTile(hero->visitablePos())->terType->name, true, false); + CCS->musich->playMusicFromSet("terrain", LOCPLINT->cb->getTile(hero->visitablePos())->terType->name, true, false); if(details.result == TryMoveHero::TELEPORTATION) { diff --git a/client/battle/CBattleInterface.cpp b/client/battle/CBattleInterface.cpp index 856d66e26..b02d7153c 100644 --- a/client/battle/CBattleInterface.cpp +++ b/client/battle/CBattleInterface.cpp @@ -411,7 +411,7 @@ CBattleInterface::CBattleInterface(const CCreatureSet *army1, const CCreatureSet { if(LOCPLINT->battleInt) { - CCS->musich->playMusicFromSet("battle", true, true); + CCS->musich->playMusicFromSet("battle", true, true); battleActionsStarted = true; blockUI(settings["session"]["spectate"].Bool()); battleIntroSoundChannel = -1; @@ -457,7 +457,7 @@ CBattleInterface::~CBattleInterface() if (adventureInt && adventureInt->selection) { const auto & terrain = *(LOCPLINT->cb->getTile(adventureInt->selection->visitablePos())->terType); - CCS->musich->playMusicFromSet("terrain", terrain.name, true, false); + CCS->musich->playMusicFromSet("terrain", terrain.name, true, false); } animsAreDisplayed.setn(false); } diff --git a/client/battle/CBattleInterfaceClasses.cpp b/client/battle/CBattleInterfaceClasses.cpp index cd199f424..7bf3d8f1d 100644 --- a/client/battle/CBattleInterfaceClasses.cpp +++ b/client/battle/CBattleInterfaceClasses.cpp @@ -506,7 +506,7 @@ CBattleResultWindow::CBattleResultWindow(const BattleResult & br, CPlayerInterfa break; } - CCS->musich->playMusic("Music/Win Battle", false, true); + CCS->musich->playMusic("Music/Win Battle", false, true); CCS->videoh->open("WIN3.BIK"); std::string str = CGI->generaltexth->allTexts[text]; @@ -543,7 +543,7 @@ CBattleResultWindow::CBattleResultWindow(const BattleResult & br, CPlayerInterfa logGlobal->error("Invalid battle result code %d. Assumed normal.", static_cast(br.result)); break; } - CCS->musich->playMusic(musicName, false, true); + CCS->musich->playMusic(musicName, false, true); CCS->videoh->open(videoName); labels.push_back(std::make_shared(235, 235, FONT_SMALL, CENTER, Colors::WHITE, CGI->generaltexth->allTexts[text])); diff --git a/client/mainmenu/CMainMenu.cpp b/client/mainmenu/CMainMenu.cpp index dd928d0da..4b5de6c45 100644 --- a/client/mainmenu/CMainMenu.cpp +++ b/client/mainmenu/CMainMenu.cpp @@ -115,7 +115,7 @@ void CMenuScreen::show(SDL_Surface * to) void CMenuScreen::activate() { - CCS->musich->playMusic("Music/MainMenu", true, true); + CCS->musich->playMusic("Music/MainMenu", true, true); if(!config["video"].isNull()) CCS->videoh->open(config["video"]["name"].String()); CIntObject::activate(); diff --git a/client/mainmenu/CPrologEpilogVideo.cpp b/client/mainmenu/CPrologEpilogVideo.cpp index 1b9c590bd..f84e2038a 100644 --- a/client/mainmenu/CPrologEpilogVideo.cpp +++ b/client/mainmenu/CPrologEpilogVideo.cpp @@ -29,7 +29,7 @@ CPrologEpilogVideo::CPrologEpilogVideo(CCampaignScenario::SScenarioPrologEpilog updateShadow(); CCS->videoh->open(CCampaignHandler::prologVideoName(spe.prologVideo)); - CCS->musich->playMusic("Music/" + CCampaignHandler::prologMusicName(spe.prologMusic), true, true); + CCS->musich->playMusic("Music/" + CCampaignHandler::prologMusicName(spe.prologMusic), true, true); // MPTODO: Custom campaign crashing on this? // voiceSoundHandle = CCS->soundh->playSound(CCampaignHandler::prologVoiceName(spe.prologVideo)); diff --git a/client/windows/CAdvmapInterface.cpp b/client/windows/CAdvmapInterface.cpp index dd93d8677..ebc7d55e8 100644 --- a/client/windows/CAdvmapInterface.cpp +++ b/client/windows/CAdvmapInterface.cpp @@ -1413,7 +1413,7 @@ void CAdvMapInt::select(const CArmedInstance *sel, bool centerView) auto pos = sel->visitablePos(); auto tile = LOCPLINT->cb->getTile(pos); if(tile) - CCS->musich->playMusicFromSet("terrain", tile->terType->name, true, false); + CCS->musich->playMusicFromSet("terrain", tile->terType->name, true, false); } if(centerView) centerOn(sel); @@ -1863,7 +1863,7 @@ void CAdvMapInt::aiTurnStarted() return; adjustActiveness(true); - CCS->musich->playMusicFromSet("enemy-turn", true, false); + CCS->musich->playMusicFromSet("enemy-turn", true, false); adventureInt->minimap.setAIRadar(true); adventureInt->infoBar.startEnemyTurn(LOCPLINT->cb->getCurrentPlayer()); adventureInt->infoBar.showAll(screen);//force refresh on inactive object diff --git a/client/windows/CCastleInterface.cpp b/client/windows/CCastleInterface.cpp index dc2c62931..a656dad68 100644 --- a/client/windows/CCastleInterface.cpp +++ b/client/windows/CCastleInterface.cpp @@ -1171,7 +1171,7 @@ CCastleInterface::CCastleInterface(const CGTownInstance * Town, const CGTownInst townlist->onSelect = std::bind(&CCastleInterface::townChange, this); recreateIcons(); - CCS->musich->playMusic(town->town->clientInfo.musicTheme, true, false); + CCS->musich->playMusic(town->town->clientInfo.musicTheme, true, false); } CCastleInterface::~CCastleInterface() From 2324148187f839628ef46063a3c800016a7e3d87 Mon Sep 17 00:00:00 2001 From: Ivan Savenko Date: Sun, 13 Nov 2022 14:59:28 +0200 Subject: [PATCH 23/31] Fix compilation using older SDL library --- client/CMusicHandler.cpp | 8 ++++---- client/CMusicHandler.h | 4 ++-- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/client/CMusicHandler.cpp b/client/CMusicHandler.cpp index 0e0c674e4..b879dddf6 100644 --- a/client/CMusicHandler.cpp +++ b/client/CMusicHandler.cpp @@ -530,7 +530,7 @@ void CMusicHandler::musicFinishedCallback() MusicEntry::MusicEntry(CMusicHandler *owner, std::string setName, std::string musicURI, bool looped, bool fromStart): owner(owner), music(nullptr), - startTime(uint64_t(-1)), + startTime(uint32_t(-1)), startPosition(0), loop(looped ? -1 : 1), fromStart(fromStart), @@ -600,7 +600,7 @@ bool MusicEntry::play() return false; } - startTime = SDL_GetTicks64(); + startTime = SDL_GetTicks(); return true; } @@ -609,8 +609,8 @@ bool MusicEntry::stop(int fade_ms) if (Mix_PlayingMusic()) { loop = 0; - uint64_t endTime = SDL_GetTicks64(); - assert(startTime != uint64_t(-1)); + uint32_t endTime = SDL_GetTicks(); + assert(startTime != uint32_t(-1)); float playDuration = (endTime - startTime + startPosition) / 1000.f; owner->trackPositions[currentName] = playDuration; logGlobal->info("Stopping music file %s at %f", currentName, playDuration); diff --git a/client/CMusicHandler.h b/client/CMusicHandler.h index 23b69ae49..0c40566ab 100644 --- a/client/CMusicHandler.h +++ b/client/CMusicHandler.h @@ -100,8 +100,8 @@ class MusicEntry int loop; // -1 = indefinite bool fromStart; - uint64_t startTime; - uint64_t startPosition; + uint32_t startTime; + uint32_t startPosition; //if not null - set from which music will be randomly selected std::string setName; std::string currentName; From aef87dd482722e81a1c85062fb670fd0c868b7d2 Mon Sep 17 00:00:00 2001 From: SoundSSGood <87084363+SoundSSGood@users.noreply.github.com> Date: Sun, 13 Nov 2022 12:04:51 +0200 Subject: [PATCH 24/31] Apply suggested cosmetic changes --- lib/CArtHandler.cpp | 5 +++-- lib/CArtHandler.h | 5 +++-- lib/NetPacksLib.cpp | 8 ++++---- server/CGameHandler.cpp | 12 ++++++------ 4 files changed, 16 insertions(+), 14 deletions(-) diff --git a/lib/CArtHandler.cpp b/lib/CArtHandler.cpp index c4bf095a2..ea86da199 100644 --- a/lib/CArtHandler.cpp +++ b/lib/CArtHandler.cpp @@ -1490,8 +1490,9 @@ ArtBearer::ArtBearer CArtifactFittingSet::bearerType() const return this->Bearer; } -DLL_LINKAGE ArtifactPosition ArtifactUtils::getArtifactDstPosition(const CArtifactInstance * artifact, - const CArtifactSet * target, ArtBearer::ArtBearer bearer) +DLL_LINKAGE ArtifactPosition ArtifactUtils::getArtifactDstPosition( const CArtifactInstance * artifact, + const CArtifactSet * target, + ArtBearer::ArtBearer bearer) { for(auto slot : artifact->artType->possibleSlots.at(bearer)) { diff --git a/lib/CArtHandler.h b/lib/CArtHandler.h index ab273670c..e6e80a24d 100644 --- a/lib/CArtHandler.h +++ b/lib/CArtHandler.h @@ -380,8 +380,9 @@ protected: namespace ArtifactUtils { // Calculates where an artifact gets placed when it gets transferred from one hero to another. - DLL_LINKAGE ArtifactPosition getArtifactDstPosition(const CArtifactInstance * artifact, const CArtifactSet * target, - ArtBearer::ArtBearer bearer); + DLL_LINKAGE ArtifactPosition getArtifactDstPosition(const CArtifactInstance * artifact, + const CArtifactSet * target, + ArtBearer::ArtBearer bearer); DLL_LINKAGE std::vector unmovablePositions(); // TODO: Make this constexpr when the toolset is upgraded DLL_LINKAGE bool isArtRemovable(const std::pair & slot); DLL_LINKAGE bool checkSpellbookIsNeeded(const CGHeroInstance * heroPtr, ArtifactID artID, ArtifactPosition slot); diff --git a/lib/NetPacksLib.cpp b/lib/NetPacksLib.cpp index 77c5f09ca..6d3073d67 100644 --- a/lib/NetPacksLib.cpp +++ b/lib/NetPacksLib.cpp @@ -1150,14 +1150,14 @@ DLL_LINKAGE void BulkMoveArtifacts::applyGs(CGameState * gs) // Swap auto leftSet = getSrcHolderArtSet(); auto rightSet = getDstHolderArtSet(); - CArtifactFittingSet ArtFittingSet(leftSet->bearerType()); + CArtifactFittingSet artFittingSet(leftSet->bearerType()); - ArtFittingSet.artifactsWorn = rightSet->artifactsWorn; - ArtFittingSet.artifactsInBackpack = rightSet->artifactsInBackpack; + artFittingSet.artifactsWorn = rightSet->artifactsWorn; + artFittingSet.artifactsInBackpack = rightSet->artifactsInBackpack; bulkArtsOperation(artsPack1, rightSet, EBulkArtsOp::BULK_REMOVE); bulkArtsOperation(artsPack0, leftSet, EBulkArtsOp::BULK_MOVE); - bulkArtsOperation(artsPack1, &ArtFittingSet, EBulkArtsOp::BULK_PUT); + bulkArtsOperation(artsPack1, &artFittingSet, EBulkArtsOp::BULK_PUT); } else { diff --git a/server/CGameHandler.cpp b/server/CGameHandler.cpp index ad5a573ff..c66a4321c 100644 --- a/server/CGameHandler.cpp +++ b/server/CGameHandler.cpp @@ -3977,15 +3977,15 @@ bool CGameHandler::bulkMoveArtifacts(ObjectInstanceID srcHero, ObjectInstanceID else { // Temporary fitting set for artifacts. Used to select available slots before sending data. - CArtifactFittingSet ArtFittingSet(pdstHero->bearerType()); - ArtFittingSet.artifactsInBackpack = pdstHero->artifactsInBackpack; - ArtFittingSet.artifactsWorn = pdstHero->artifactsWorn; + CArtifactFittingSet artFittingSet(pdstHero->bearerType()); + artFittingSet.artifactsInBackpack = pdstHero->artifactsInBackpack; + artFittingSet.artifactsWorn = pdstHero->artifactsWorn; - auto moveArtifact = [this, &ArtFittingSet, &slotsSrcDst](const CArtifactInstance * artifact, + auto moveArtifact = [this, &artFittingSet, &slotsSrcDst](const CArtifactInstance * artifact, ArtifactPosition srcSlot, const CGHeroInstance * pdstHero) -> void { - auto dstSlot = ArtifactUtils::getArtifactDstPosition(artifact, &ArtFittingSet, pdstHero->bearerType()); - ArtFittingSet.putArtifact(dstSlot, static_cast>(artifact)); + auto dstSlot = ArtifactUtils::getArtifactDstPosition(artifact, &artFittingSet, pdstHero->bearerType()); + artFittingSet.putArtifact(dstSlot, static_cast>(artifact)); slotsSrcDst.push_back(BulkMoveArtifacts::LinkedSlots(srcSlot, dstSlot)); if(ArtifactUtils::checkSpellbookIsNeeded(pdstHero, artifact->artType->id, dstSlot)) From f9738f0d0b2f954da70cd2d8518567d61076fa4e Mon Sep 17 00:00:00 2001 From: SoundSSGood <87084363+SoundSSGood@users.noreply.github.com> Date: Sun, 13 Nov 2022 16:24:23 +0200 Subject: [PATCH 25/31] nullptr checks --- lib/CArtHandler.cpp | 2 +- server/CGameHandler.cpp | 7 ++++++- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/lib/CArtHandler.cpp b/lib/CArtHandler.cpp index ea86da199..1bc68666b 100644 --- a/lib/CArtHandler.cpp +++ b/lib/CArtHandler.cpp @@ -1518,7 +1518,7 @@ DLL_LINKAGE bool ArtifactUtils::isArtRemovable(const std::pair>(psrcHero), static_cast>(pdstHero), swap); @@ -3952,7 +3954,9 @@ bool CGameHandler::bulkMoveArtifacts(ObjectInstanceID srcHero, ObjectInstanceID continue; slots.push_back(BulkMoveArtifacts::LinkedSlots(artifact.first, artifact.first)); - if(ArtifactUtils::checkSpellbookIsNeeded(dstHero, artifact.second.getArt()->artType->id, artifact.first)) + auto art = artifact.second.getArt(); + assert(art); + if(ArtifactUtils::checkSpellbookIsNeeded(dstHero, art->artType->id, artifact.first)) giveHeroNewArtifact(dstHero, VLC->arth->objects[ArtifactID::SPELLBOOK], ArtifactPosition::SPELLBOOK); } }; @@ -3984,6 +3988,7 @@ bool CGameHandler::bulkMoveArtifacts(ObjectInstanceID srcHero, ObjectInstanceID auto moveArtifact = [this, &artFittingSet, &slotsSrcDst](const CArtifactInstance * artifact, ArtifactPosition srcSlot, const CGHeroInstance * pdstHero) -> void { + assert(artifact); auto dstSlot = ArtifactUtils::getArtifactDstPosition(artifact, &artFittingSet, pdstHero->bearerType()); artFittingSet.putArtifact(dstSlot, static_cast>(artifact)); slotsSrcDst.push_back(BulkMoveArtifacts::LinkedSlots(srcSlot, dstSlot)); From 57ab13c820e5b78de813b9d1c53da7220dba0df5 Mon Sep 17 00:00:00 2001 From: SoundSSGood <87084363+SoundSSGood@users.noreply.github.com> Date: Sun, 13 Nov 2022 17:09:48 +0200 Subject: [PATCH 26/31] cosmetic correction --- lib/CArtHandler.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/CArtHandler.cpp b/lib/CArtHandler.cpp index 1bc68666b..9ab956a32 100644 --- a/lib/CArtHandler.cpp +++ b/lib/CArtHandler.cpp @@ -1491,8 +1491,8 @@ ArtBearer::ArtBearer CArtifactFittingSet::bearerType() const } DLL_LINKAGE ArtifactPosition ArtifactUtils::getArtifactDstPosition( const CArtifactInstance * artifact, - const CArtifactSet * target, - ArtBearer::ArtBearer bearer) + const CArtifactSet * target, + ArtBearer::ArtBearer bearer) { for(auto slot : artifact->artType->possibleSlots.at(bearer)) { From 98bf6931a195d012367bb72014246df0392fc602 Mon Sep 17 00:00:00 2001 From: SoundSSGood <87084363+SoundSSGood@users.noreply.github.com> Date: Sun, 13 Nov 2022 17:10:39 +0200 Subject: [PATCH 27/31] cosmetic correction --- lib/CArtHandler.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/CArtHandler.h b/lib/CArtHandler.h index e6e80a24d..46f14d490 100644 --- a/lib/CArtHandler.h +++ b/lib/CArtHandler.h @@ -380,9 +380,9 @@ protected: namespace ArtifactUtils { // Calculates where an artifact gets placed when it gets transferred from one hero to another. - DLL_LINKAGE ArtifactPosition getArtifactDstPosition(const CArtifactInstance * artifact, - const CArtifactSet * target, - ArtBearer::ArtBearer bearer); + DLL_LINKAGE ArtifactPosition getArtifactDstPosition( const CArtifactInstance * artifact, + const CArtifactSet * target, + ArtBearer::ArtBearer bearer); DLL_LINKAGE std::vector unmovablePositions(); // TODO: Make this constexpr when the toolset is upgraded DLL_LINKAGE bool isArtRemovable(const std::pair & slot); DLL_LINKAGE bool checkSpellbookIsNeeded(const CGHeroInstance * heroPtr, ArtifactID artID, ArtifactPosition slot); From 4fe8ff9b014aeccb728ba6703a60ee21a0f61f74 Mon Sep 17 00:00:00 2001 From: Ivan Savenko Date: Mon, 14 Nov 2022 15:53:07 +0200 Subject: [PATCH 28/31] Fixes #825 - do not wait for new week dialog in single-player --- client/CPlayerInterface.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/client/CPlayerInterface.cpp b/client/CPlayerInterface.cpp index af40aa43f..7ab32d13d 100644 --- a/client/CPlayerInterface.cpp +++ b/client/CPlayerInterface.cpp @@ -2338,10 +2338,13 @@ void CPlayerInterface::acceptTurn() while(CInfoWindow *iw = dynamic_cast(GH.topInt().get())) iw->close(); } - waitWhileDialog(); if(CSH->howManyPlayerInterfaces() > 1) + { + waitWhileDialog(); // wait for player to accept turn in hot-seat mode + adventureInt->startTurn(); + } adventureInt->heroList.update(); adventureInt->townList.update(); From e06db2365d6be0b47892aceab9ebc07081350302 Mon Sep 17 00:00:00 2001 From: Ivan Savenko Date: Mon, 14 Nov 2022 17:16:49 +0200 Subject: [PATCH 29/31] Fixes #1096 - do not propose banned skills on levelup Remove possibility to get banned skill on levelup as "obligatory skill" if all other such skills have been learned before. May happen under some conditions, e.g. if hero quickly learns other magic schools - in witch hut/university, leading to case where banned skill is the only obligatory skill that can be offered on levelup --- lib/mapObjects/CGHeroInstance.cpp | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/lib/mapObjects/CGHeroInstance.cpp b/lib/mapObjects/CGHeroInstance.cpp index 4785f1eb7..be7f0efda 100644 --- a/lib/mapObjects/CGHeroInstance.cpp +++ b/lib/mapObjects/CGHeroInstance.cpp @@ -1117,7 +1117,9 @@ std::vector CGHeroInstance::getLevelUpProposedSecondarySkills() std::vector obligatorySkills; //hero is offered magic school or wisdom if possible if (!skillsInfo.wisdomCounter) { - if (cb->isAllowed(2, SecondarySkill::WISDOM) && !getSecSkillLevel(SecondarySkill::WISDOM)) + if (cb->isAllowed(2, SecondarySkill::WISDOM) && + !getSecSkillLevel(SecondarySkill::WISDOM) && + type->heroClass->secSkillProbability[SecondarySkill::WISDOM] > 0) obligatorySkills.push_back(SecondarySkill::WISDOM); } if (!skillsInfo.magicSchoolCounter) @@ -1131,7 +1133,7 @@ std::vector CGHeroInstance::getLevelUpProposedSecondarySkills() for (auto skill : ss) { - if (cb->isAllowed(2, skill) && !getSecSkillLevel(skill)) //only schools hero doesn't know yet + if (cb->isAllowed(2, skill) && !getSecSkillLevel(skill) && type->heroClass->secSkillProbability[skill] > 0) //only schools hero doesn't know yet { obligatorySkills.push_back(skill); break; //only one @@ -1143,7 +1145,7 @@ std::vector CGHeroInstance::getLevelUpProposedSecondarySkills() //picking sec. skills for choice std::set basicAndAdv, expert, none; for(int i = 0; i < VLC->skillh->size(); i++) - if (cb->isAllowed(2,i)) + if (cb->isAllowed(2,i) && type->heroClass->secSkillProbability[i] > 0) none.insert(SecondarySkill(i)); for(auto & elem : secSkills) From 729357824bf3bbcfc72af7ca2eda44884aff083d Mon Sep 17 00:00:00 2001 From: Ivan Savenko Date: Mon, 14 Nov 2022 19:08:49 +0200 Subject: [PATCH 30/31] Added common method for secondary skill availability checks --- client/windows/GUIClasses.cpp | 4 +--- lib/mapObjects/CGHeroInstance.cpp | 25 ++++++++++++++++++++----- lib/mapObjects/CGHeroInstance.h | 1 + server/CGameHandler.cpp | 2 +- 4 files changed, 23 insertions(+), 9 deletions(-) diff --git a/client/windows/GUIClasses.cpp b/client/windows/GUIClasses.cpp index 4bce0f2d0..9d7afa516 100644 --- a/client/windows/GUIClasses.cpp +++ b/client/windows/GUIClasses.cpp @@ -1700,9 +1700,7 @@ int CUniversityWindow::CItem::state() { if(parent->hero->getSecSkillLevel(SecondarySkill(ID)))//hero know this skill return 1; - if(!parent->hero->canLearnSkill())//can't learn more skills - return 0; - if(parent->hero->type->heroClass->secSkillProbability[ID]==0)//can't learn this skill (like necromancy for most of non-necros) + if(!parent->hero->canLearnSkill(SecondarySkill(ID)))//can't learn more skills return 0; return 2; } diff --git a/lib/mapObjects/CGHeroInstance.cpp b/lib/mapObjects/CGHeroInstance.cpp index be7f0efda..b14473ddd 100644 --- a/lib/mapObjects/CGHeroInstance.cpp +++ b/lib/mapObjects/CGHeroInstance.cpp @@ -195,6 +195,23 @@ bool CGHeroInstance::canLearnSkill() const return secSkills.size() < GameConstants::SKILL_PER_HERO; } +bool CGHeroInstance::canLearnSkill(SecondarySkill which) const +{ + if ( !canLearnSkill()) + return false; + + if (!cb->isAllowed(2, which)) + return false; + + if (getSecSkillLevel(which) > 0) + return false; + + if (type->heroClass->secSkillProbability[which] == 0) + return false; + + return true; +} + int CGHeroInstance::maxMovePoints(bool onLand) const { TurnInfo ti(this); @@ -1117,9 +1134,7 @@ std::vector CGHeroInstance::getLevelUpProposedSecondarySkills() std::vector obligatorySkills; //hero is offered magic school or wisdom if possible if (!skillsInfo.wisdomCounter) { - if (cb->isAllowed(2, SecondarySkill::WISDOM) && - !getSecSkillLevel(SecondarySkill::WISDOM) && - type->heroClass->secSkillProbability[SecondarySkill::WISDOM] > 0) + if (canLearnSkill(SecondarySkill::WISDOM)) obligatorySkills.push_back(SecondarySkill::WISDOM); } if (!skillsInfo.magicSchoolCounter) @@ -1133,7 +1148,7 @@ std::vector CGHeroInstance::getLevelUpProposedSecondarySkills() for (auto skill : ss) { - if (cb->isAllowed(2, skill) && !getSecSkillLevel(skill) && type->heroClass->secSkillProbability[skill] > 0) //only schools hero doesn't know yet + if (canLearnSkill(skill)) //only schools hero doesn't know yet { obligatorySkills.push_back(skill); break; //only one @@ -1145,7 +1160,7 @@ std::vector CGHeroInstance::getLevelUpProposedSecondarySkills() //picking sec. skills for choice std::set basicAndAdv, expert, none; for(int i = 0; i < VLC->skillh->size(); i++) - if (cb->isAllowed(2,i) && type->heroClass->secSkillProbability[i] > 0) + if (canLearnSkill(SecondarySkill(i))) none.insert(SecondarySkill(i)); for(auto & elem : secSkills) diff --git a/lib/mapObjects/CGHeroInstance.h b/lib/mapObjects/CGHeroInstance.h index 8c56f8798..5e05eafe5 100644 --- a/lib/mapObjects/CGHeroInstance.h +++ b/lib/mapObjects/CGHeroInstance.h @@ -187,6 +187,7 @@ public: /// Returns true if hero has free secondary skill slot. bool canLearnSkill() const; + bool canLearnSkill(SecondarySkill which) const; void setPrimarySkill(PrimarySkill::PrimarySkill primarySkill, si64 value, ui8 abs); void setSecSkillLevel(SecondarySkill which, int val, bool abs);// abs == 0 - changes by value; 1 - sets to value diff --git a/server/CGameHandler.cpp b/server/CGameHandler.cpp index a4f8dedad..13f977817 100644 --- a/server/CGameHandler.cpp +++ b/server/CGameHandler.cpp @@ -4083,7 +4083,7 @@ bool CGameHandler::buySecSkill(const IMarket *m, const CGHeroInstance *h, Second if (!h->canLearnSkill()) COMPLAIN_RET("Hero can't learn any more skills"); - if (h->type->heroClass->secSkillProbability.at(skill)==0)//can't learn this skill (like necromancy for most of non-necros) + if (!h->canLearnSkill(skill)) COMPLAIN_RET("The hero can't learn this skill!"); if (!vstd::contains(m->availableItemsIds(EMarketMode::RESOURCE_SKILL), skill)) From 7fdad4e0f6edc1fae14b1008360f9bc2a9d885ef Mon Sep 17 00:00:00 2001 From: lainon Date: Tue, 15 Nov 2022 03:20:55 +0300 Subject: [PATCH 31/31] Code refactor following C++ standard and condition fixes --- AI/Nullkiller/Analyzers/BuildAnalyzer.cpp | 2 +- client/CVideoHandler.cpp | 2 +- client/widgets/AdventureMapClasses.cpp | 2 +- client/widgets/CArtifactHolder.cpp | 4 ++-- client/widgets/TextControls.cpp | 2 +- client/windows/CAdvmapInterface.cpp | 2 +- client/windows/CSpellWindow.cpp | 2 +- client/windows/CTradeWindow.cpp | 2 +- lib/CArtHandler.cpp | 2 +- lib/CBonusTypeHandler.cpp | 4 +++- lib/CCreatureSet.cpp | 2 +- lib/CGameState.cpp | 2 +- lib/CModHandler.cpp | 12 ++++++------ lib/CPathfinder.cpp | 2 +- lib/CTownHandler.cpp | 5 ++--- lib/HeroBonus.cpp | 8 ++++---- lib/battle/CBattleInfoCallback.cpp | 2 +- lib/mapObjects/CGTownInstance.cpp | 2 +- lib/mapObjects/CObjectClassesHandler.cpp | 2 +- lib/mapObjects/CQuest.cpp | 4 ++-- lib/mapObjects/MiscObjects.cpp | 6 +++--- lib/mapping/CMap.cpp | 6 +++--- lib/mapping/MapFormatH3M.cpp | 8 ++++---- lib/mapping/MapFormatJson.cpp | 4 ++-- lib/serializer/JsonDeserializer.cpp | 2 +- lib/serializer/JsonSerializer.cpp | 2 +- mapeditor/objectbrowser.cpp | 2 +- 27 files changed, 48 insertions(+), 47 deletions(-) diff --git a/AI/Nullkiller/Analyzers/BuildAnalyzer.cpp b/AI/Nullkiller/Analyzers/BuildAnalyzer.cpp index 314b4174f..d719c03f4 100644 --- a/AI/Nullkiller/Analyzers/BuildAnalyzer.cpp +++ b/AI/Nullkiller/Analyzers/BuildAnalyzer.cpp @@ -334,7 +334,7 @@ BuildingInfo::BuildingInfo() buildCost = 0; buildCostWithPrerequisits = 0; prerequisitesCount = 0; - name = ""; + name.clear(); armyStrength = 0; } diff --git a/client/CVideoHandler.cpp b/client/CVideoHandler.cpp index afe18c924..31c2cebf6 100644 --- a/client/CVideoHandler.cpp +++ b/client/CVideoHandler.cpp @@ -381,7 +381,7 @@ void CVideoPlayer::update( int x, int y, SDL_Surface *dst, bool forceRedraw, boo void CVideoPlayer::close() { - fname = ""; + fname.clear(); if (sws) { sws_freeContext(sws); diff --git a/client/widgets/AdventureMapClasses.cpp b/client/widgets/AdventureMapClasses.cpp index b0d351a2b..1a4be8d59 100644 --- a/client/widgets/AdventureMapClasses.cpp +++ b/client/widgets/AdventureMapClasses.cpp @@ -1158,7 +1158,7 @@ void CInGameConsole::endEnteringText(bool printEnteredText) previouslyEntered.push_back(txt); //print(txt); } - enteredText = ""; + enteredText.clear(); if(GH.topInt() == adventureInt) { GH.statusbar->alignment = CENTER; diff --git a/client/widgets/CArtifactHolder.cpp b/client/widgets/CArtifactHolder.cpp index 746b2fc0c..2800b579e 100644 --- a/client/widgets/CArtifactHolder.cpp +++ b/client/widgets/CArtifactHolder.cpp @@ -367,7 +367,7 @@ void CHeroArtPlace::setArtifact(const CArtifactInstance *art) if(!art) { image->disable(); - text = std::string(); + text.clear(); hoverText = CGI->generaltexth->allTexts[507]; return; } @@ -1034,7 +1034,7 @@ void CCommanderArtPlace::setArtifact(const CArtifactInstance * art) if (!art) { image->disable(); - text = std::string(); + text.clear(); return; } diff --git a/client/widgets/TextControls.cpp b/client/widgets/TextControls.cpp index b7854f127..96a0ec71c 100644 --- a/client/widgets/TextControls.cpp +++ b/client/widgets/TextControls.cpp @@ -577,7 +577,7 @@ void CTextInput::textInputed(const SDL_TextInputEvent & event) redraw(); cb(text); } - newText = ""; + newText.clear(); #ifdef VCMI_ANDROID notifyAndroidTextInputChanged(text); diff --git a/client/windows/CAdvmapInterface.cpp b/client/windows/CAdvmapInterface.cpp index 538fc554d..e75a22297 100644 --- a/client/windows/CAdvmapInterface.cpp +++ b/client/windows/CAdvmapInterface.cpp @@ -573,7 +573,7 @@ CAdvMapInt::CAdvMapInt(): strongInterest = true; // handle all mouse move events to prevent dead mouse move space in fullscreen mode townList.onSelect = std::bind(&CAdvMapInt::selectionChanged,this); bg = BitmapHandler::loadBitmap(ADVOPT.mainGraphic); - if (ADVOPT.worldViewGraphic != "") + if(!ADVOPT.worldViewGraphic.empty()) { bgWorldView = BitmapHandler::loadBitmap(ADVOPT.worldViewGraphic); } diff --git a/client/windows/CSpellWindow.cpp b/client/windows/CSpellWindow.cpp index ad48699e2..b5dcd5e93 100644 --- a/client/windows/CSpellWindow.cpp +++ b/client/windows/CSpellWindow.cpp @@ -593,7 +593,7 @@ void CSpellWindow::SpellArea::clickRight(tribool down, bool previousState) std::string dmgInfo; auto causedDmg = owner->myInt->cb->estimateSpellDamage(mySpell, owner->myHero); if(causedDmg == 0 || mySpell->id == SpellID::TITANS_LIGHTNING_BOLT) //Titan's Lightning Bolt already has damage info included - dmgInfo = ""; + dmgInfo.clear(); else { dmgInfo = CGI->generaltexth->allTexts[343]; diff --git a/client/windows/CTradeWindow.cpp b/client/windows/CTradeWindow.cpp index 05091a70d..63381e08e 100644 --- a/client/windows/CTradeWindow.cpp +++ b/client/windows/CTradeWindow.cpp @@ -192,7 +192,7 @@ void CTradeWindow::CTradeableItem::clickLeft(tribool down, bool previousState) aw->arts->artifactsOnAltar.erase(art); setID(-1); - subtitle = ""; + subtitle.clear(); aw->deal->block(!aw->arts->artifactsOnAltar.size()); } diff --git a/lib/CArtHandler.cpp b/lib/CArtHandler.cpp index ee57823f9..a6a6b1031 100644 --- a/lib/CArtHandler.cpp +++ b/lib/CArtHandler.cpp @@ -352,7 +352,7 @@ CArtifact * CArtHandler::loadFromJson(const std::string & scope, const JsonNode } const JsonNode & warMachine = node["warMachine"]; - if(warMachine.getType() == JsonNode::JsonType::DATA_STRING && warMachine.String() != "") + if(warMachine.getType() == JsonNode::JsonType::DATA_STRING && !warMachine.String().empty()) { VLC->modh->identifiers.requestIdentifier("creature", warMachine, [=](si32 id) { diff --git a/lib/CBonusTypeHandler.cpp b/lib/CBonusTypeHandler.cpp index 00342ec9f..7edd984b4 100644 --- a/lib/CBonusTypeHandler.cpp +++ b/lib/CBonusTypeHandler.cpp @@ -94,7 +94,9 @@ std::string MacroString::build(const GetValue & getValue) const CBonusType::CBonusType() { hidden = true; - icon = nameTemplate = descriptionTemplate = ""; + icon.clear(); + nameTemplate.clear(); + descriptionTemplate.clear(); } CBonusType::~CBonusType() diff --git a/lib/CCreatureSet.cpp b/lib/CCreatureSet.cpp index 412316449..2e3bbc8f2 100644 --- a/lib/CCreatureSet.cpp +++ b/lib/CCreatureSet.cpp @@ -1052,7 +1052,7 @@ void CStackBasicDescriptor::serializeJson(JsonSerializeFormat & handler) { std::string typeName(""); handler.serializeString("type", typeName); - if(typeName != "") + if(!typeName.empty()) setType(VLC->creh->getCreature("core", typeName)); } } diff --git a/lib/CGameState.cpp b/lib/CGameState.cpp index d2482bb99..823989e24 100644 --- a/lib/CGameState.cpp +++ b/lib/CGameState.cpp @@ -532,7 +532,7 @@ std::pair CGameState::pickObject (CGObjectInstance *obj) if (auto info = dynamic_cast(dwl->info)) { faction = getRandomGenerator().nextInt((int)VLC->townh->size() - 1); - if(info->asCastle && info->instanceId != "") + if(info->asCastle && !info->instanceId.empty()) { auto iter = map->instanceNames.find(info->instanceId); diff --git a/lib/CModHandler.cpp b/lib/CModHandler.cpp index 3d112f0ed..fdf5229ab 100644 --- a/lib/CModHandler.cpp +++ b/lib/CModHandler.cpp @@ -226,7 +226,7 @@ std::vector CIdentifierStorage::getPossibleIdent //for map format support core mod has access to any mod //TODO: better solution for access from map? - if(request.localScope == "core" || request.localScope == "") + if(request.localScope == "core" || request.localScope.empty()) { allowedScopes.insert(request.remoteScope); } @@ -1116,13 +1116,13 @@ void CModHandler::parseIdentifier(const std::string & fullIdentifier, std::strin else { type = p.second; - identifier = ""; + identifier.clear(); } } std::string CModHandler::makeFullIdentifier(const std::string & scope, const std::string & type, const std::string & identifier) { - if(type == "") + if(type.empty()) logGlobal->error("Full identifier (%s %s) requires type name", scope, identifier); std::string actualScope = scope; @@ -1137,13 +1137,13 @@ std::string CModHandler::makeFullIdentifier(const std::string & scope, const std actualName = scopeAndName.second; } - if(actualScope == "") + if(actualScope.empty()) { - return actualName == "" ? type : type + "." + actualName; + return actualName.empty() ? type : type + "." + actualName; } else { - return actualName == "" ? actualScope+ ":" + type : actualScope + ":" + type + "." + actualName; + return actualName.empty() ? actualScope+ ":" + type : actualScope + ":" + type + "." + actualName; } } diff --git a/lib/CPathfinder.cpp b/lib/CPathfinder.cpp index bc2fca93d..86aea5b07 100644 --- a/lib/CPathfinder.cpp +++ b/lib/CPathfinder.cpp @@ -1252,7 +1252,7 @@ int CPathfinderHelper::getMovementCost( if(src.x != dst.x && src.y != dst.y) //it's diagonal move { int old = ret; - ret = static_cast < int>(ret * 1.414213); + ret = static_cast(ret * M_SQRT2); //diagonal move costs too much but normal move is possible - allow diagonal move for remaining move points if(ret > remainingMovePoints && remainingMovePoints >= old) { diff --git a/lib/CTownHandler.cpp b/lib/CTownHandler.cpp index c50d097d4..ced8fdf0b 100644 --- a/lib/CTownHandler.cpp +++ b/lib/CTownHandler.cpp @@ -822,11 +822,11 @@ void CTownHandler::loadClientData(CTown &town, const JsonNode & source) info.buildingsIcons = source["buildingsIcons"].String(); //left for back compatibility - will be removed later - if (source["guildBackground"].String() != "") + if(!source["guildBackground"].String().empty()) info.guildBackground = source["guildBackground"].String(); else info.guildBackground = "TPMAGE.bmp"; - if (source["tavernVideo"].String() != "") + if(!source["tavernVideo"].String().empty()) info.tavernVideo = source["tavernVideo"].String(); else info.tavernVideo = "TAVERN.BIK"; @@ -963,7 +963,6 @@ TerrainId CTownHandler::getDefaultTerrainForAlignment(EAlignment::EAlignment ali CFaction * CTownHandler::loadFromJson(const std::string & scope, const JsonNode & source, const std::string & identifier, size_t index) { auto faction = new CFaction(); - faction->index = index; faction->index = static_cast(index); faction->name = source["name"].String(); diff --git a/lib/HeroBonus.cpp b/lib/HeroBonus.cpp index b43346658..5dd53bbbd 100644 --- a/lib/HeroBonus.cpp +++ b/lib/HeroBonus.cpp @@ -1016,7 +1016,7 @@ TConstBonusListPtr CBonusSystemNode::getAllBonuses(const CSelector &selector, co // If a bonus system request comes with a caching string then look up in the map if there are any // pre-calculated bonus results. Limiters can't be cached so they have to be calculated. - if (cachingStr != "") + if(!cachingStr.empty()) { auto it = cachedRequests.find(cachingStr); if(it != cachedRequests.end()) @@ -1032,7 +1032,7 @@ TConstBonusListPtr CBonusSystemNode::getAllBonuses(const CSelector &selector, co cachedBonuses.getBonuses(*ret, selector, limit); // Save the results in the cache - if(cachingStr != "") + if(!cachingStr.empty()) cachedRequests[cachingStr] = ret; return ret; @@ -1708,9 +1708,9 @@ JsonNode Bonus::toJsonNode() const root["val"].Integer() = val; if(valType != ADDITIVE_VALUE) root["valueType"].String() = vstd::findKey(bonusValueMap, valType); - if(stacking != "") + if(!stacking.empty()) root["stacking"].String() = stacking; - if(description != "") + if(!description.empty()) root["description"].String() = description; if(effectRange != NO_LIMIT) root["effectRange"].String() = vstd::findKey(bonusLimitEffect, effectRange); diff --git a/lib/battle/CBattleInfoCallback.cpp b/lib/battle/CBattleInfoCallback.cpp index 8d891a8f6..7f309e876 100644 --- a/lib/battle/CBattleInfoCallback.cpp +++ b/lib/battle/CBattleInfoCallback.cpp @@ -55,7 +55,7 @@ static void retrieveTurretDamageRange(const CGTownInstance * town, const battle: const int baseDamage = 15; outMinDmg = multiplier * (baseDamage + town->getTownLevel() * 3); - outMaxDmg = multiplier * (baseDamage + town->getTownLevel() * 3); + outMaxDmg = outMinDmg; } static BattleHex lineToWallHex(int line) //returns hex with wall in given line (y coordinate) diff --git a/lib/mapObjects/CGTownInstance.cpp b/lib/mapObjects/CGTownInstance.cpp index 9afffeaee..4206b9fc8 100644 --- a/lib/mapObjects/CGTownInstance.cpp +++ b/lib/mapObjects/CGTownInstance.cpp @@ -46,7 +46,7 @@ void CCreGenAsCastleInfo::serializeJson(JsonSerializeFormat & handler) if(!handler.saving) { - asCastle = (instanceId != ""); + asCastle = !instanceId.empty(); allowedFactions.clear(); } diff --git a/lib/mapObjects/CObjectClassesHandler.cpp b/lib/mapObjects/CObjectClassesHandler.cpp index 2b9d87392..5f2810ed5 100644 --- a/lib/mapObjects/CObjectClassesHandler.cpp +++ b/lib/mapObjects/CObjectClassesHandler.cpp @@ -572,7 +572,7 @@ void AObjectTypeHandler::addTemplate(JsonNode config) auto tmpl = new ObjectTemplate; tmpl->id = Obj(type); tmpl->subid = subtype; - tmpl->stringID = ""; // TODO? + tmpl->stringID.clear(); // TODO? tmpl->readJson(config); templates.emplace_back(tmpl); } diff --git a/lib/mapObjects/CQuest.cpp b/lib/mapObjects/CQuest.cpp index 04aa4efac..a63ff4eca 100644 --- a/lib/mapObjects/CQuest.cpp +++ b/lib/mapObjects/CQuest.cpp @@ -938,7 +938,7 @@ void CGSeerHut::serializeJsonOptions(JsonSerializeFormat & handler) case MANA_POINTS: case MORALE_BONUS: case LUCK_BONUS: - identifier = ""; + identifier.clear(); break; case RESOURCES: identifier = GameConstants::RESOURCE_NAMES[rID]; @@ -976,7 +976,7 @@ void CGSeerHut::serializeJsonOptions(JsonSerializeFormat & handler) const JsonNode & rewardsJson = handler.getCurrent(); - fullIdentifier = ""; + fullIdentifier.clear(); if(rewardsJson.Struct().empty()) return; diff --git a/lib/mapObjects/MiscObjects.cpp b/lib/mapObjects/MiscObjects.cpp index bb51fadb7..bedd9b7c1 100644 --- a/lib/mapObjects/MiscObjects.cpp +++ b/lib/mapObjects/MiscObjects.cpp @@ -1802,7 +1802,7 @@ void CGScholar::serializeJsonOptions(JsonSerializeFormat & handler) //TODO: unify const JsonNode & json = handler.getCurrent(); bonusType = RANDOM; - if(json["rewardPrimSkill"].String() != "") + if(!json["rewardPrimSkill"].String().empty()) { auto raw = VLC->modh->identifiers.getIdentifier("core", "primSkill", json["rewardPrimSkill"].String()); if(raw) @@ -1811,7 +1811,7 @@ void CGScholar::serializeJsonOptions(JsonSerializeFormat & handler) bonusID = raw.get(); } } - else if(json["rewardSkill"].String() != "") + else if(!json["rewardSkill"].String().empty()) { auto raw = VLC->modh->identifiers.getIdentifier("core", "skill", json["rewardSkill"].String()); if(raw) @@ -1820,7 +1820,7 @@ void CGScholar::serializeJsonOptions(JsonSerializeFormat & handler) bonusID = raw.get(); } } - else if(json["rewardSpell"].String() != "") + else if(!json["rewardSpell"].String().empty()) { auto raw = VLC->modh->identifiers.getIdentifier("core", "spell", json["rewardSpell"].String()); if(raw) diff --git a/lib/mapping/CMap.cpp b/lib/mapping/CMap.cpp index b2583721b..d5f3fee82 100644 --- a/lib/mapping/CMap.cpp +++ b/lib/mapping/CMap.cpp @@ -203,7 +203,7 @@ void CMapHeader::setupEvents() standardVictory.effect.type = EventEffect::VICTORY; standardVictory.effect.toOtherMessage = VLC->generaltexth->allTexts[5]; standardVictory.identifier = "standardVictory"; - standardVictory.description = ""; // TODO: display in quest window + standardVictory.description.clear(); // TODO: display in quest window standardVictory.onFulfill = VLC->generaltexth->allTexts[659]; standardVictory.trigger = EventExpression(victoryCondition); @@ -212,7 +212,7 @@ void CMapHeader::setupEvents() standardDefeat.effect.type = EventEffect::DEFEAT; standardDefeat.effect.toOtherMessage = VLC->generaltexth->allTexts[8]; standardDefeat.identifier = "standardDefeat"; - standardDefeat.description = ""; // TODO: display in quest window + standardDefeat.description.clear(); // TODO: display in quest window standardDefeat.onFulfill = VLC->generaltexth->allTexts[7]; standardDefeat.trigger = EventExpression(defeatCondition); @@ -651,7 +651,7 @@ void CMap::addNewObject(CGObjectInstance * obj) if(obj->id != ObjectInstanceID((si32)objects.size())) throw std::runtime_error("Invalid object instance id"); - if(obj->instanceName == "") + if(obj->instanceName.empty()) throw std::runtime_error("Object instance name missing"); if (vstd::contains(instanceNames, obj->instanceName)) diff --git a/lib/mapping/MapFormatH3M.cpp b/lib/mapping/MapFormatH3M.cpp index 59e8d845d..5ca1087d6 100644 --- a/lib/mapping/MapFormatH3M.cpp +++ b/lib/mapping/MapFormatH3M.cpp @@ -313,7 +313,7 @@ void CMapLoaderH3M::readVictoryLossConditions() standardVictory.effect.type = EventEffect::VICTORY; standardVictory.effect.toOtherMessage = VLC->generaltexth->allTexts[5]; standardVictory.identifier = "standardVictory"; - standardVictory.description = ""; // TODO: display in quest window + standardVictory.description.clear(); // TODO: display in quest window standardVictory.onFulfill = VLC->generaltexth->allTexts[659]; standardVictory.trigger = EventExpression(victoryCondition); @@ -321,7 +321,7 @@ void CMapLoaderH3M::readVictoryLossConditions() standardDefeat.effect.type = EventEffect::DEFEAT; standardDefeat.effect.toOtherMessage = VLC->generaltexth->allTexts[8]; standardDefeat.identifier = "standardDefeat"; - standardDefeat.description = ""; // TODO: display in quest window + standardDefeat.description.clear(); // TODO: display in quest window standardDefeat.onFulfill = VLC->generaltexth->allTexts[7]; standardDefeat.trigger = EventExpression(defeatCondition); @@ -338,7 +338,7 @@ void CMapLoaderH3M::readVictoryLossConditions() TriggeredEvent specialVictory; specialVictory.effect.type = EventEffect::VICTORY; specialVictory.identifier = "specialVictory"; - specialVictory.description = ""; // TODO: display in quest window + specialVictory.description.clear(); // TODO: display in quest window mapHeader->victoryIconIndex = ui16(vicCondition); mapHeader->victoryMessage = VLC->generaltexth->victoryConditions[size_t(vicCondition) + 1]; @@ -526,7 +526,7 @@ void CMapLoaderH3M::readVictoryLossConditions() specialDefeat.effect.type = EventEffect::DEFEAT; specialDefeat.effect.toOtherMessage = VLC->generaltexth->allTexts[5]; specialDefeat.identifier = "specialDefeat"; - specialDefeat.description = ""; // TODO: display in quest window + specialDefeat.description.clear(); // TODO: display in quest window mapHeader->defeatIconIndex = ui16(lossCond); mapHeader->defeatMessage = VLC->generaltexth->lossCondtions[size_t(lossCond) + 1]; diff --git a/lib/mapping/MapFormatJson.cpp b/lib/mapping/MapFormatJson.cpp index e1efb5b2c..4e26cdfe9 100644 --- a/lib/mapping/MapFormatJson.cpp +++ b/lib/mapping/MapFormatJson.cpp @@ -134,7 +134,7 @@ namespace TriggeredEventsDetail static EMetaclass decodeMetaclass(const std::string & source) { - if(source == "") + if(source.empty()) return EMetaclass::INVALID; auto rawId = vstd::find_pos(NMetaclass::names, source); @@ -286,7 +286,7 @@ namespace TriggeredEventsDetail if(event.value > 0) data["value"].Integer() = event.value; - if(event.objectInstanceName != "") + if(!event.objectInstanceName.empty()) data["object"].String() = event.objectInstanceName; } break; diff --git a/lib/serializer/JsonDeserializer.cpp b/lib/serializer/JsonDeserializer.cpp index 85cb80797..a5378dada 100644 --- a/lib/serializer/JsonDeserializer.cpp +++ b/lib/serializer/JsonDeserializer.cpp @@ -38,7 +38,7 @@ void JsonDeserializer::serializeInternal(const std::string & fieldName, si32 & v value = defaultValue ? defaultValue.get() : 0; - if(identifier != "") + if(!identifier.empty()) { si32 rawId = decoder(identifier); diff --git a/lib/serializer/JsonSerializer.cpp b/lib/serializer/JsonSerializer.cpp index d01ca0e4c..69253b986 100644 --- a/lib/serializer/JsonSerializer.cpp +++ b/lib/serializer/JsonSerializer.cpp @@ -108,7 +108,7 @@ void JsonSerializer::serializeLIC(const std::string & fieldName, LICSet & value) void JsonSerializer::serializeString(const std::string & fieldName, std::string & value) { - if(value != "") + if(!value.empty()) currentObject->operator[](fieldName).String() = value; } diff --git a/mapeditor/objectbrowser.cpp b/mapeditor/objectbrowser.cpp index 960fde550..416b8abfa 100644 --- a/mapeditor/objectbrowser.cpp +++ b/mapeditor/objectbrowser.cpp @@ -51,7 +51,7 @@ bool ObjectBrowser::filterAcceptsRow(int source_row, const QModelIndex & source_ auto factory = VLC->objtypeh->getHandlerFor(objId, objSubId); auto templ = factory->getTemplates()[templateId]; - result = result & templ->canBePlacedAt(terrain); + result = result && templ->canBePlacedAt(terrain); //if we are here, just text filter will be applied return result;