mirror of
https://github.com/vcmi/vcmi.git
synced 2025-01-02 00:10:22 +02:00
Merge pull request #2874 from SoundSSGood/exchange-window-update
Exchange window update
This commit is contained in:
commit
97097c20ad
@ -172,9 +172,9 @@ void CCallback::assembleArtifacts(const CGHeroInstance * hero, ArtifactPosition
|
||||
sendRequest(&aa);
|
||||
}
|
||||
|
||||
void CCallback::bulkMoveArtifacts(ObjectInstanceID srcHero, ObjectInstanceID dstHero, bool swap)
|
||||
void CCallback::bulkMoveArtifacts(ObjectInstanceID srcHero, ObjectInstanceID dstHero, bool swap, bool equipped, bool backpack)
|
||||
{
|
||||
BulkExchangeArtifacts bma(srcHero, dstHero, swap);
|
||||
BulkExchangeArtifacts bma(srcHero, dstHero, swap, equipped, backpack);
|
||||
sendRequest(&bma);
|
||||
}
|
||||
|
||||
|
@ -108,7 +108,7 @@ public:
|
||||
|
||||
|
||||
// Moves all artifacts from one hero to another
|
||||
virtual void bulkMoveArtifacts(ObjectInstanceID srcHero, ObjectInstanceID dstHero, bool swap) = 0;
|
||||
virtual void bulkMoveArtifacts(ObjectInstanceID srcHero, ObjectInstanceID dstHero, bool swap, bool equipped, bool backpack) = 0;
|
||||
};
|
||||
|
||||
class CBattleCallback : public IBattleCallback
|
||||
@ -171,7 +171,7 @@ public:
|
||||
bool dismissHero(const CGHeroInstance * hero) override;
|
||||
bool swapArtifacts(const ArtifactLocation &l1, const ArtifactLocation &l2) override;
|
||||
void assembleArtifacts(const CGHeroInstance * hero, ArtifactPosition artifactSlot, bool assemble, ArtifactID assembleTo) override;
|
||||
void bulkMoveArtifacts(ObjectInstanceID srcHero, ObjectInstanceID dstHero, bool swap) override;
|
||||
void bulkMoveArtifacts(ObjectInstanceID srcHero, ObjectInstanceID dstHero, bool swap, bool equipped = true, bool backpack = true) override;
|
||||
void eraseArtifactByClient(const ArtifactLocation & al) 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;
|
||||
|
@ -95,6 +95,7 @@ set(client_SRCS
|
||||
widgets/Buttons.cpp
|
||||
widgets/CArtifactHolder.cpp
|
||||
widgets/CComponent.cpp
|
||||
widgets/CExchangeController.cpp
|
||||
widgets/CGarrisonInt.cpp
|
||||
widgets/CreatureCostBox.cpp
|
||||
widgets/ComboBox.cpp
|
||||
@ -259,6 +260,7 @@ set(client_HEADERS
|
||||
widgets/Buttons.h
|
||||
widgets/CArtifactHolder.h
|
||||
widgets/CComponent.h
|
||||
widgets/CExchangeController.h
|
||||
widgets/CGarrisonInt.h
|
||||
widgets/CreatureCostBox.h
|
||||
widgets/ComboBox.h
|
||||
|
@ -200,8 +200,8 @@ void CHeroArtPlace::clickPressed(const Point & cursorPosition)
|
||||
|
||||
void CHeroArtPlace::showPopupWindow(const Point & cursorPosition)
|
||||
{
|
||||
if(rightClickCallback)
|
||||
rightClickCallback(*this);
|
||||
if(showPopupCallback)
|
||||
showPopupCallback(*this);
|
||||
}
|
||||
|
||||
void CHeroArtPlace::showAll(Canvas & to)
|
||||
|
@ -66,11 +66,11 @@ public:
|
||||
class CHeroArtPlace: public CArtPlace
|
||||
{
|
||||
public:
|
||||
using ClickHandler = std::function<void(CHeroArtPlace&)>;
|
||||
using ClickFunctor = std::function<void(CHeroArtPlace&)>;
|
||||
|
||||
ArtifactPosition slot;
|
||||
ClickHandler leftClickCallback;
|
||||
ClickHandler rightClickCallback;
|
||||
ClickFunctor leftClickCallback;
|
||||
ClickFunctor showPopupCallback;
|
||||
|
||||
CHeroArtPlace(Point position, const CArtifactInstance * Art = nullptr);
|
||||
void lockSlot(bool on);
|
||||
|
@ -42,7 +42,7 @@ CArtifactsOfHeroBackpack::CArtifactsOfHeroBackpack(const Point & position)
|
||||
artPlace = std::make_shared<CHeroArtPlace>(pos);
|
||||
artPlace->setArtifact(nullptr);
|
||||
artPlace->leftClickCallback = std::bind(&CArtifactsOfHeroBase::leftClickArtPlace, this, _1);
|
||||
artPlace->rightClickCallback = std::bind(&CArtifactsOfHeroBase::rightClickArtPlace, this, _1);
|
||||
artPlace->showPopupCallback = std::bind(&CArtifactsOfHeroBase::rightClickArtPlace, this, _1);
|
||||
artPlaceIdx++;
|
||||
}
|
||||
|
||||
|
@ -55,10 +55,10 @@ void CArtifactsOfHeroBase::setPutBackPickedArtifactCallback(PutBackPickedArtCall
|
||||
}
|
||||
|
||||
void CArtifactsOfHeroBase::init(
|
||||
CHeroArtPlace::ClickHandler lClickCallback,
|
||||
CHeroArtPlace::ClickHandler rClickCallback,
|
||||
CHeroArtPlace::ClickFunctor lClickCallback,
|
||||
CHeroArtPlace::ClickFunctor showPopupCallback,
|
||||
const Point & position,
|
||||
BpackScrollHandler scrollHandler)
|
||||
BpackScrollFunctor scrollCallback)
|
||||
{
|
||||
// CArtifactsOfHeroBase::init may be transform to CArtifactsOfHeroBase::CArtifactsOfHeroBase if OBJECT_CONSTRUCTION_CAPTURING is removed
|
||||
OBJECT_CONSTRUCTION_CAPTURING(255 - DISPOSE);
|
||||
@ -78,16 +78,16 @@ void CArtifactsOfHeroBase::init(
|
||||
artPlace.second->slot = artPlace.first;
|
||||
artPlace.second->setArtifact(nullptr);
|
||||
artPlace.second->leftClickCallback = lClickCallback;
|
||||
artPlace.second->rightClickCallback = rClickCallback;
|
||||
artPlace.second->showPopupCallback = showPopupCallback;
|
||||
}
|
||||
for(auto artPlace : backpack)
|
||||
{
|
||||
artPlace->setArtifact(nullptr);
|
||||
artPlace->leftClickCallback = lClickCallback;
|
||||
artPlace->rightClickCallback = rClickCallback;
|
||||
artPlace->showPopupCallback = showPopupCallback;
|
||||
}
|
||||
leftBackpackRoll = std::make_shared<CButton>(Point(379, 364), AnimationPath::builtin("hsbtns3.def"), CButton::tooltip(), [scrollHandler]() { scrollHandler(-1); }, EShortcut::MOVE_LEFT);
|
||||
rightBackpackRoll = std::make_shared<CButton>(Point(632, 364), AnimationPath::builtin("hsbtns5.def"), CButton::tooltip(), [scrollHandler]() { scrollHandler(+1); }, EShortcut::MOVE_RIGHT);
|
||||
leftBackpackRoll = std::make_shared<CButton>(Point(379, 364), AnimationPath::builtin("hsbtns3.def"), CButton::tooltip(), [scrollCallback]() {scrollCallback(-1);}, EShortcut::MOVE_LEFT);
|
||||
rightBackpackRoll = std::make_shared<CButton>(Point(632, 364), AnimationPath::builtin("hsbtns5.def"), CButton::tooltip(), [scrollCallback]() {scrollCallback(+1);}, EShortcut::MOVE_RIGHT);
|
||||
leftBackpackRoll->block(true);
|
||||
rightBackpackRoll->block(true);
|
||||
|
||||
@ -102,8 +102,8 @@ void CArtifactsOfHeroBase::leftClickArtPlace(CHeroArtPlace & artPlace)
|
||||
|
||||
void CArtifactsOfHeroBase::rightClickArtPlace(CHeroArtPlace & artPlace)
|
||||
{
|
||||
if(rightClickCallback)
|
||||
rightClickCallback(*this, artPlace);
|
||||
if(showPopupCallback)
|
||||
showPopupCallback(*this, artPlace);
|
||||
}
|
||||
|
||||
void CArtifactsOfHeroBase::setHero(const CGHeroInstance * hero)
|
||||
|
@ -15,15 +15,15 @@ class CArtifactsOfHeroBase : public CIntObject
|
||||
{
|
||||
protected:
|
||||
using ArtPlacePtr = std::shared_ptr<CHeroArtPlace>;
|
||||
using BpackScrollHandler = std::function<void(int)>;
|
||||
using BpackScrollFunctor = std::function<void(int)>;
|
||||
|
||||
public:
|
||||
using ArtPlaceMap = std::map<ArtifactPosition, ArtPlacePtr>;
|
||||
using ClickHandler = std::function<void(CArtifactsOfHeroBase&, CHeroArtPlace&)>;
|
||||
using ClickFunctor = std::function<void(CArtifactsOfHeroBase&, CHeroArtPlace&)>;
|
||||
using PutBackPickedArtCallback = std::function<void()>;
|
||||
|
||||
ClickHandler leftClickCallback;
|
||||
ClickHandler rightClickCallback;
|
||||
ClickFunctor leftClickCallback;
|
||||
ClickFunctor showPopupCallback;
|
||||
|
||||
CArtifactsOfHeroBase();
|
||||
virtual void putBackPickedArtifact();
|
||||
@ -61,8 +61,8 @@ protected:
|
||||
Point(381,296) //18
|
||||
};
|
||||
|
||||
virtual void init(CHeroArtPlace::ClickHandler lClickCallback, CHeroArtPlace::ClickHandler rClickCallback,
|
||||
const Point & position, BpackScrollHandler scrollHandler);
|
||||
virtual void init(CHeroArtPlace::ClickFunctor lClickCallback, CHeroArtPlace::ClickFunctor showPopupCallback,
|
||||
const Point & position, BpackScrollFunctor scrollCallback);
|
||||
// Assigns an artifacts to an artifact place depending on it's new slot ID
|
||||
virtual void setSlotData(ArtPlacePtr artPlace, const ArtifactPosition & slot, const CArtifactSet & artSet);
|
||||
virtual void scrollBackpackForArtSet(int offset, const CArtifactSet & artSet);
|
||||
|
@ -29,13 +29,13 @@ CArtifactsOfHeroKingdom::CArtifactsOfHeroKingdom(ArtPlaceMap ArtWorn, std::vecto
|
||||
artPlace.second->slot = artPlace.first;
|
||||
artPlace.second->setArtifact(nullptr);
|
||||
artPlace.second->leftClickCallback = std::bind(&CArtifactsOfHeroBase::leftClickArtPlace, this, _1);
|
||||
artPlace.second->rightClickCallback = std::bind(&CArtifactsOfHeroBase::rightClickArtPlace, this, _1);
|
||||
artPlace.second->showPopupCallback = std::bind(&CArtifactsOfHeroBase::rightClickArtPlace, this, _1);
|
||||
}
|
||||
for(auto artPlace : backpack)
|
||||
{
|
||||
artPlace->setArtifact(nullptr);
|
||||
artPlace->leftClickCallback = std::bind(&CArtifactsOfHeroBase::leftClickArtPlace, this, _1);
|
||||
artPlace->rightClickCallback = std::bind(&CArtifactsOfHeroBase::rightClickArtPlace, this, _1);
|
||||
artPlace->showPopupCallback = std::bind(&CArtifactsOfHeroBase::rightClickArtPlace, this, _1);
|
||||
}
|
||||
leftBackpackRoll->addCallback(std::bind(&CArtifactsOfHeroBase::scrollBackpack, this, -1));
|
||||
rightBackpackRoll->addCallback(std::bind(&CArtifactsOfHeroBase::scrollBackpack, this, +1));
|
||||
|
119
client/widgets/CExchangeController.cpp
Normal file
119
client/widgets/CExchangeController.cpp
Normal file
@ -0,0 +1,119 @@
|
||||
/*
|
||||
* CExchangeController.cpp, part of VCMI engine
|
||||
*
|
||||
* Authors: listed in file AUTHORS in main folder
|
||||
*
|
||||
* License: GNU General Public License v2.0 or later
|
||||
* Full text of license available in license.txt file, in main folder
|
||||
*
|
||||
*/
|
||||
#include "StdInc.h"
|
||||
#include "CExchangeController.h"
|
||||
|
||||
#include "../CPlayerInterface.h"
|
||||
|
||||
#include "../widgets/CGarrisonInt.h"
|
||||
|
||||
#include "../../CCallback.h"
|
||||
|
||||
#include "../lib/mapObjects/CGHeroInstance.h"
|
||||
|
||||
CExchangeController::CExchangeController(ObjectInstanceID hero1, ObjectInstanceID hero2)
|
||||
: left(LOCPLINT->cb->getHero(hero1))
|
||||
, right(LOCPLINT->cb->getHero(hero2))
|
||||
{
|
||||
}
|
||||
|
||||
void CExchangeController::swapArmy()
|
||||
{
|
||||
auto getStacks = [](const CArmedInstance * source) -> std::vector<std::pair<SlotID, CStackInstance*>>
|
||||
{
|
||||
auto slots = source->Slots();
|
||||
return std::vector<std::pair<SlotID, CStackInstance*>>(slots.begin(), slots.end());
|
||||
};
|
||||
|
||||
auto leftSlots = getStacks(left);
|
||||
auto rightSlots = getStacks(right);
|
||||
|
||||
auto i = leftSlots.begin(), j = rightSlots.begin();
|
||||
|
||||
for(; i != leftSlots.end() && j != rightSlots.end(); i++, j++)
|
||||
{
|
||||
LOCPLINT->cb->swapCreatures(left, right, i->first, j->first);
|
||||
}
|
||||
|
||||
if(i != leftSlots.end())
|
||||
{
|
||||
auto freeSlots = right->getFreeSlots();
|
||||
auto slot = freeSlots.begin();
|
||||
|
||||
for(; i != leftSlots.end() && slot != freeSlots.end(); i++, slot++)
|
||||
{
|
||||
LOCPLINT->cb->swapCreatures(left, right, i->first, *slot);
|
||||
}
|
||||
}
|
||||
else if(j != rightSlots.end())
|
||||
{
|
||||
auto freeSlots = left->getFreeSlots();
|
||||
auto slot = freeSlots.begin();
|
||||
|
||||
for(; j != rightSlots.end() && slot != freeSlots.end(); j++, slot++)
|
||||
{
|
||||
LOCPLINT->cb->swapCreatures(left, right, *slot, j->first);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CExchangeController::moveArmy(bool leftToRight, std::optional<SlotID> heldSlot)
|
||||
{
|
||||
const auto source = leftToRight ? left : right;
|
||||
const auto target = leftToRight ? right : left;
|
||||
|
||||
if(!heldSlot.has_value())
|
||||
{
|
||||
auto weakestSlot = vstd::minElementByFun(source->Slots(),
|
||||
[](const std::pair<SlotID, CStackInstance*> & s) -> int
|
||||
{
|
||||
return s.second->getCreatureID().toCreature()->getAIValue();
|
||||
});
|
||||
heldSlot = weakestSlot->first;
|
||||
}
|
||||
LOCPLINT->cb->bulkMoveArmy(source->id, target->id, heldSlot.value());
|
||||
}
|
||||
|
||||
void CExchangeController::moveStack(bool leftToRight, SlotID sourceSlot)
|
||||
{
|
||||
const auto source = leftToRight ? left : right;
|
||||
const auto target = leftToRight ? right : left;
|
||||
auto creature = source->getCreature(sourceSlot);
|
||||
|
||||
if(creature == nullptr)
|
||||
return;
|
||||
|
||||
SlotID targetSlot = target->getSlotFor(creature);
|
||||
if(targetSlot.validSlot())
|
||||
{
|
||||
if(source->stacksCount() == 1 && source->needsLastStack())
|
||||
{
|
||||
LOCPLINT->cb->splitStack(source, target, sourceSlot, targetSlot,
|
||||
target->getStackCount(targetSlot) + source->getStackCount(sourceSlot) - 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
LOCPLINT->cb->mergeOrSwapStacks(source, target, sourceSlot, targetSlot);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CExchangeController::swapArtifacts(bool equipped, bool baclpack)
|
||||
{
|
||||
LOCPLINT->cb->bulkMoveArtifacts(left->id, right->id, true, equipped, baclpack);
|
||||
}
|
||||
|
||||
void CExchangeController::moveArtifacts(bool leftToRight, bool equipped, bool baclpack)
|
||||
{
|
||||
const auto source = leftToRight ? left : right;
|
||||
const auto target = leftToRight ? right : left;
|
||||
|
||||
LOCPLINT->cb->bulkMoveArtifacts(source->id, target->id, false, equipped, baclpack);
|
||||
}
|
30
client/widgets/CExchangeController.h
Normal file
30
client/widgets/CExchangeController.h
Normal file
@ -0,0 +1,30 @@
|
||||
/*
|
||||
* CExchangeController.h, part of VCMI engine
|
||||
*
|
||||
* Authors: listed in file AUTHORS in main folder
|
||||
*
|
||||
* License: GNU General Public License v2.0 or later
|
||||
* Full text of license available in license.txt file, in main folder
|
||||
*
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include "../windows/CWindowObject.h"
|
||||
#include "CWindowWithArtifacts.h"
|
||||
|
||||
class CCallback;
|
||||
|
||||
class CExchangeController
|
||||
{
|
||||
public:
|
||||
CExchangeController(ObjectInstanceID hero1, ObjectInstanceID hero2);
|
||||
void swapArmy();
|
||||
void moveArmy(bool leftToRight, std::optional<SlotID> heldSlot);
|
||||
void moveStack(bool leftToRight, SlotID sourceSlot);
|
||||
void swapArtifacts(bool equipped, bool baclpack);
|
||||
void moveArtifacts(bool leftToRight, bool equipped, bool baclpack);
|
||||
|
||||
private:
|
||||
const CGHeroInstance * left;
|
||||
const CGHeroInstance * right;
|
||||
};
|
@ -32,18 +32,23 @@
|
||||
#include "../../lib/CConfigHandler.h"
|
||||
|
||||
void CWindowWithArtifacts::addSet(CArtifactsOfHeroPtr artSet)
|
||||
{
|
||||
artSets.emplace_back(artSet);
|
||||
}
|
||||
|
||||
void CWindowWithArtifacts::addSetAndCallbacks(CArtifactsOfHeroPtr artSet)
|
||||
{
|
||||
CArtifactsOfHeroBase::PutBackPickedArtCallback artPutBackHandler = []() -> void
|
||||
{
|
||||
CCS->curh->dragAndDropCursor(nullptr);
|
||||
};
|
||||
|
||||
artSets.emplace_back(artSet);
|
||||
addSet(artSet);
|
||||
std::visit([this, artPutBackHandler](auto artSetWeak)
|
||||
{
|
||||
auto artSet = artSetWeak.lock();
|
||||
artSet->leftClickCallback = std::bind(&CWindowWithArtifacts::leftClickArtPlaceHero, this, _1, _2);
|
||||
artSet->rightClickCallback = std::bind(&CWindowWithArtifacts::rightClickArtPlaceHero, this, _1, _2);
|
||||
artSet->showPopupCallback = std::bind(&CWindowWithArtifacts::rightClickArtPlaceHero, this, _1, _2);
|
||||
artSet->setPutBackPickedArtifactCallback(artPutBackHandler);
|
||||
}, artSet);
|
||||
}
|
||||
|
@ -28,6 +28,7 @@ public:
|
||||
using CloseCallback = std::function<void()>;
|
||||
|
||||
void addSet(CArtifactsOfHeroPtr artSet);
|
||||
void addSetAndCallbacks(CArtifactsOfHeroPtr artSet);
|
||||
void addCloseCallback(CloseCallback callback);
|
||||
const CGHeroInstance * getHeroPickedArtifact();
|
||||
const CArtifactInstance * getPickedArtifact();
|
||||
@ -39,7 +40,7 @@ public:
|
||||
void artifactDisassembled(const ArtifactLocation & artLoc) override;
|
||||
void artifactAssembled(const ArtifactLocation & artLoc) override;
|
||||
|
||||
private:
|
||||
protected:
|
||||
std::vector<CArtifactsOfHeroPtr> artSets;
|
||||
CloseCallback closeCallback;
|
||||
|
||||
|
@ -28,7 +28,7 @@ CHeroBackpackWindow::CHeroBackpackWindow(const CGHeroInstance * hero)
|
||||
|
||||
arts = std::make_shared<CArtifactsOfHeroBackpack>(Point(windowMargin, windowMargin));
|
||||
arts->setHero(hero);
|
||||
addSet(arts);
|
||||
addSetAndCallbacks(arts);
|
||||
|
||||
addCloseCallback(std::bind(&CHeroBackpackWindow::close, this));
|
||||
|
||||
|
@ -219,7 +219,7 @@ void CHeroWindow::update(const CGHeroInstance * hero, bool redrawNeeded)
|
||||
{
|
||||
arts = std::make_shared<CArtifactsOfHeroMain>(Point(-65, -8));
|
||||
arts->setHero(curHero);
|
||||
addSet(arts);
|
||||
addSetAndCallbacks(arts);
|
||||
}
|
||||
|
||||
int serial = LOCPLINT->cb->getHeroSerial(curHero, false);
|
||||
|
@ -706,7 +706,7 @@ std::shared_ptr<CIntObject> CKingdHeroList::createHeroItem(size_t index)
|
||||
if(index < heroesList.size())
|
||||
{
|
||||
auto hero = std::make_shared<CHeroItem>(heroesList[index]);
|
||||
addSet(hero->heroArts);
|
||||
addSetAndCallbacks(hero->heroArts);
|
||||
return hero;
|
||||
}
|
||||
else
|
||||
|
@ -680,7 +680,7 @@ CMarketplaceWindow::CMarketplaceWindow(const IMarket * Market, const CGHeroInsta
|
||||
arts = std::make_shared<CArtifactsOfHeroMarket>(Point(-361, 46));
|
||||
arts->selectArtCallback = std::bind(&CTradeWindow::artifactSelected, this, _1);
|
||||
arts->setHero(hero);
|
||||
addSet(arts);
|
||||
addSetAndCallbacks(arts);
|
||||
}
|
||||
initItems(false);
|
||||
initItems(true);
|
||||
@ -1133,7 +1133,7 @@ CAltarWindow::CAltarWindow(const IMarket * Market, const CGHeroInstance * Hero,
|
||||
|
||||
arts = std::make_shared<CArtifactsOfHeroAltar>(Point(-365, -12));
|
||||
arts->setHero(hero);
|
||||
addSet(arts);
|
||||
addSetAndCallbacks(arts);
|
||||
|
||||
initItems(true);
|
||||
initItems(false);
|
||||
|
@ -12,6 +12,7 @@
|
||||
|
||||
#include "CCastleInterface.h"
|
||||
#include "CCreatureWindow.h"
|
||||
#include "CHeroBackpackWindow.h"
|
||||
#include "CHeroWindow.h"
|
||||
#include "InfoWindows.h"
|
||||
|
||||
@ -19,62 +20,40 @@
|
||||
#include "../CMusicHandler.h"
|
||||
#include "../CPlayerInterface.h"
|
||||
#include "../CVideoHandler.h"
|
||||
#include "../CServerHandler.h"
|
||||
|
||||
#include "../battle/BattleInterfaceClasses.h"
|
||||
#include "../battle/BattleInterface.h"
|
||||
|
||||
#include "../gui/CGuiHandler.h"
|
||||
#include "../gui/CursorHandler.h"
|
||||
#include "../gui/TextAlignment.h"
|
||||
#include "../gui/Shortcut.h"
|
||||
#include "../gui/WindowHandler.h"
|
||||
|
||||
#include "../widgets/CComponent.h"
|
||||
#include "../widgets/CGarrisonInt.h"
|
||||
#include "../widgets/MiscWidgets.h"
|
||||
#include "../widgets/CreatureCostBox.h"
|
||||
#include "../widgets/Buttons.h"
|
||||
#include "../widgets/Slider.h"
|
||||
#include "../widgets/TextControls.h"
|
||||
#include "../widgets/ObjectLists.h"
|
||||
|
||||
#include "../lobby/CSavingScreen.h"
|
||||
#include "../render/Canvas.h"
|
||||
#include "../render/CAnimation.h"
|
||||
#include "../render/IRenderHandler.h"
|
||||
#include "../CMT.h"
|
||||
|
||||
#include "../../CCallback.h"
|
||||
|
||||
#include "../lib/mapObjectConstructors/AObjectTypeHandler.h"
|
||||
#include "../lib/mapObjectConstructors/CObjectClassesHandler.h"
|
||||
#include "../lib/mapObjectConstructors/CommonConstructors.h"
|
||||
#include "../lib/mapObjects/CGHeroInstance.h"
|
||||
#include "../lib/mapObjects/CGMarket.h"
|
||||
#include "../lib/ArtifactUtils.h"
|
||||
#include "../lib/mapObjects/CGTownInstance.h"
|
||||
#include "../lib/mapObjects/ObjectTemplate.h"
|
||||
#include "../lib/gameState/CGameState.h"
|
||||
#include "../lib/gameState/InfoAboutArmy.h"
|
||||
#include "../lib/gameState/SThievesGuildInfo.h"
|
||||
#include "../lib/CArtHandler.h"
|
||||
#include "../lib/CBuildingHandler.h"
|
||||
#include "../lib/CConfigHandler.h"
|
||||
#include "../lib/CCreatureHandler.h"
|
||||
#include "../lib/CGeneralTextHandler.h"
|
||||
#include "../lib/CHeroHandler.h"
|
||||
#include "../lib/GameSettings.h"
|
||||
#include "../lib/CondSh.h"
|
||||
#include "../lib/CSkillHandler.h"
|
||||
#include "../lib/spells/CSpellHandler.h"
|
||||
#include "../lib/filesystem/Filesystem.h"
|
||||
#include "../lib/CStopWatch.h"
|
||||
#include "../lib/CTownHandler.h"
|
||||
#include "../lib/GameConstants.h"
|
||||
#include "../lib/bonuses/Bonus.h"
|
||||
#include "../lib/NetPacksBase.h"
|
||||
#include "../lib/StartInfo.h"
|
||||
#include "../lib/TextOperations.h"
|
||||
|
||||
CRecruitmentWindow::CCreatureCard::CCreatureCard(CRecruitmentWindow * window, const CCreature * crea, int totalAmount)
|
||||
@ -623,215 +602,9 @@ static bool isQuickExchangeLayoutAvailable()
|
||||
return CResourceHandler::get()->existsResource(ImagePath::builtin("SPRITES/" + QUICK_EXCHANGE_BG));
|
||||
}
|
||||
|
||||
CExchangeController::CExchangeController(CExchangeWindow * view, ObjectInstanceID hero1, ObjectInstanceID hero2)
|
||||
:left(LOCPLINT->cb->getHero(hero1)), right(LOCPLINT->cb->getHero(hero2)), cb(LOCPLINT->cb), view(view)
|
||||
{
|
||||
}
|
||||
|
||||
std::function<void()> CExchangeController::onMoveArmyToLeft()
|
||||
{
|
||||
return [&]() { moveArmy(false); };
|
||||
}
|
||||
|
||||
std::function<void()> CExchangeController::onMoveArmyToRight()
|
||||
{
|
||||
return [&]() { moveArmy(true); };
|
||||
}
|
||||
|
||||
std::vector<CArtifactInstance *> getBackpackArts(const CGHeroInstance * hero)
|
||||
{
|
||||
std::vector<CArtifactInstance *> result;
|
||||
|
||||
for(auto slot : hero->artifactsInBackpack)
|
||||
{
|
||||
result.push_back(slot.artifact);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
std::function<void()> CExchangeController::onSwapArtifacts()
|
||||
{
|
||||
return [&]()
|
||||
{
|
||||
cb->bulkMoveArtifacts(left->id, right->id, true);
|
||||
};
|
||||
}
|
||||
|
||||
std::function<void()> CExchangeController::onMoveArtifactsToLeft()
|
||||
{
|
||||
return [&]() { moveArtifacts(false); };
|
||||
}
|
||||
|
||||
std::function<void()> CExchangeController::onMoveArtifactsToRight()
|
||||
{
|
||||
return [&]() { moveArtifacts(true); };
|
||||
}
|
||||
|
||||
std::vector<std::pair<SlotID, CStackInstance *>> getStacks(const CArmedInstance * source)
|
||||
{
|
||||
auto slots = source->Slots();
|
||||
|
||||
return std::vector<std::pair<SlotID, CStackInstance *>>(slots.begin(), slots.end());
|
||||
}
|
||||
|
||||
std::function<void()> CExchangeController::onSwapArmy()
|
||||
{
|
||||
return [&]()
|
||||
{
|
||||
if(left->tempOwner != cb->getPlayerID()
|
||||
|| right->tempOwner != cb->getPlayerID())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
auto leftSlots = getStacks(left);
|
||||
auto rightSlots = getStacks(right);
|
||||
|
||||
auto i = leftSlots.begin(), j = rightSlots.begin();
|
||||
|
||||
for(; i != leftSlots.end() && j != rightSlots.end(); i++, j++)
|
||||
{
|
||||
cb->swapCreatures(left, right, i->first, j->first);
|
||||
}
|
||||
|
||||
if(i != leftSlots.end())
|
||||
{
|
||||
auto freeSlots = right->getFreeSlots();
|
||||
auto slot = freeSlots.begin();
|
||||
|
||||
for(; i != leftSlots.end() && slot != freeSlots.end(); i++, slot++)
|
||||
{
|
||||
cb->swapCreatures(left, right, i->first, *slot);
|
||||
}
|
||||
}
|
||||
else if(j != rightSlots.end())
|
||||
{
|
||||
auto freeSlots = left->getFreeSlots();
|
||||
auto slot = freeSlots.begin();
|
||||
|
||||
for(; j != rightSlots.end() && slot != freeSlots.end(); j++, slot++)
|
||||
{
|
||||
cb->swapCreatures(left, right, *slot, j->first);
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
std::function<void()> CExchangeController::onMoveStackToLeft(SlotID slotID)
|
||||
{
|
||||
return [=]()
|
||||
{
|
||||
if(right->tempOwner != cb->getPlayerID())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
moveStack(right, left, slotID);
|
||||
};
|
||||
}
|
||||
|
||||
std::function<void()> CExchangeController::onMoveStackToRight(SlotID slotID)
|
||||
{
|
||||
return [=]()
|
||||
{
|
||||
if(left->tempOwner != cb->getPlayerID())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
moveStack(left, right, slotID);
|
||||
};
|
||||
}
|
||||
|
||||
void CExchangeController::moveStack(
|
||||
const CGHeroInstance * source,
|
||||
const CGHeroInstance * target,
|
||||
SlotID sourceSlot)
|
||||
{
|
||||
auto creature = source->getCreature(sourceSlot);
|
||||
if(creature == nullptr)
|
||||
return;
|
||||
|
||||
SlotID targetSlot = target->getSlotFor(creature);
|
||||
|
||||
if(targetSlot.validSlot())
|
||||
{
|
||||
if(source->stacksCount() == 1 && source->needsLastStack())
|
||||
{
|
||||
cb->splitStack(
|
||||
source,
|
||||
target,
|
||||
sourceSlot,
|
||||
targetSlot,
|
||||
target->getStackCount(targetSlot) + source->getStackCount(sourceSlot) - 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
cb->mergeOrSwapStacks(source, target, sourceSlot, targetSlot);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CExchangeController::moveArmy(bool leftToRight)
|
||||
{
|
||||
const CGHeroInstance * source = leftToRight ? left : right;
|
||||
const CGHeroInstance * target = leftToRight ? right : left;
|
||||
const CGarrisonSlot * selection = this->view->getSelectedSlotID();
|
||||
SlotID slot;
|
||||
|
||||
if(source->tempOwner != cb->getPlayerID())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if(selection && selection->our() && selection->getObj() == source)
|
||||
{
|
||||
slot = selection->getSlot();
|
||||
}
|
||||
else
|
||||
{
|
||||
auto weakestSlot = vstd::minElementByFun(
|
||||
source->Slots(),
|
||||
[](const std::pair<SlotID, CStackInstance *> & s) -> int
|
||||
{
|
||||
return s.second->getCreatureID().toCreature()->getAIValue();
|
||||
});
|
||||
|
||||
slot = weakestSlot->first;
|
||||
}
|
||||
|
||||
cb->bulkMoveArmy(source->id, target->id, slot);
|
||||
}
|
||||
|
||||
void CExchangeController::moveArtifacts(bool leftToRight)
|
||||
{
|
||||
const CGHeroInstance * source = leftToRight ? left : right;
|
||||
const CGHeroInstance * target = leftToRight ? right : left;
|
||||
|
||||
if(source->tempOwner != cb->getPlayerID())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
cb->bulkMoveArtifacts(source->id, target->id, false);
|
||||
}
|
||||
|
||||
void CExchangeController::moveArtifact(
|
||||
const CGHeroInstance * source,
|
||||
const CGHeroInstance * target,
|
||||
ArtifactPosition srcPosition)
|
||||
{
|
||||
auto srcLocation = ArtifactLocation(source, srcPosition);
|
||||
auto dstLocation = ArtifactLocation(target,
|
||||
ArtifactUtils::getArtAnyPosition(target, source->getArt(srcPosition)->getTypeId()));
|
||||
|
||||
cb->swapArtifacts(srcLocation, dstLocation);
|
||||
}
|
||||
|
||||
CExchangeWindow::CExchangeWindow(ObjectInstanceID hero1, ObjectInstanceID hero2, QueryID queryID)
|
||||
: CStatusbarWindow(PLAYER_COLORED | BORDERED, ImagePath::builtin(isQuickExchangeLayoutAvailable() ? QUICK_EXCHANGE_BG : "TRADE2")),
|
||||
controller(this, hero1, hero2),
|
||||
controller(hero1, hero2),
|
||||
moveStackLeftButtons(),
|
||||
moveStackRightButtons()
|
||||
{
|
||||
@ -890,8 +663,8 @@ CExchangeWindow::CExchangeWindow(ObjectInstanceID hero1, ObjectInstanceID hero2,
|
||||
artifs[1] = std::make_shared<CArtifactsOfHeroMain>(Point(98, 150));
|
||||
artifs[1]->setHero(heroInst[1]);
|
||||
|
||||
addSet(artifs[0]);
|
||||
addSet(artifs[1]);
|
||||
addSetAndCallbacks(artifs[0]);
|
||||
addSetAndCallbacks(artifs[1]);
|
||||
|
||||
for(int g=0; g<4; ++g)
|
||||
{
|
||||
@ -982,12 +755,62 @@ CExchangeWindow::CExchangeWindow(ObjectInstanceID hero1, ObjectInstanceID hero2,
|
||||
|
||||
if(qeLayout)
|
||||
{
|
||||
moveAllGarrButtonLeft = std::make_shared<CButton>(Point(325, 118), AnimationPath::builtin(QUICK_EXCHANGE_MOD_PREFIX + "/armRight.DEF"), CButton::tooltip(CGI->generaltexth->qeModCommands[1]), controller.onMoveArmyToRight());
|
||||
echangeGarrButton = std::make_shared<CButton>(Point(377, 118), AnimationPath::builtin(QUICK_EXCHANGE_MOD_PREFIX + "/swapAll.DEF"), CButton::tooltip(CGI->generaltexth->qeModCommands[2]), controller.onSwapArmy());
|
||||
moveAllGarrButtonRight = std::make_shared<CButton>(Point(425, 118), AnimationPath::builtin(QUICK_EXCHANGE_MOD_PREFIX + "/armLeft.DEF"), CButton::tooltip(CGI->generaltexth->qeModCommands[1]), controller.onMoveArmyToLeft());
|
||||
moveArtifactsButtonLeft = std::make_shared<CButton>(Point(325, 154), AnimationPath::builtin(QUICK_EXCHANGE_MOD_PREFIX + "/artRight.DEF"), CButton::tooltip(CGI->generaltexth->qeModCommands[3]), controller.onMoveArtifactsToRight());
|
||||
echangeArtifactsButton = std::make_shared<CButton>(Point(377, 154), AnimationPath::builtin(QUICK_EXCHANGE_MOD_PREFIX + "/swapAll.DEF"), CButton::tooltip(CGI->generaltexth->qeModCommands[4]), controller.onSwapArtifacts());
|
||||
moveArtifactsButtonRight = std::make_shared<CButton>(Point(425, 154), AnimationPath::builtin(QUICK_EXCHANGE_MOD_PREFIX + "/artLeft.DEF"), CButton::tooltip(CGI->generaltexth->qeModCommands[3]), controller.onMoveArtifactsToLeft());
|
||||
auto moveArtifacts = [](const std::function<void(bool, bool)> moveRoutine) -> void
|
||||
{
|
||||
bool moveEquipped = true;
|
||||
bool moveBackpack = true;
|
||||
|
||||
if(GH.isKeyboardCtrlDown())
|
||||
moveBackpack = false;
|
||||
else if(GH.isKeyboardShiftDown())
|
||||
moveEquipped = false;
|
||||
moveRoutine(moveEquipped, moveBackpack);
|
||||
};
|
||||
|
||||
auto moveArmy = [this](const bool leftToRight) -> void
|
||||
{
|
||||
std::optional<SlotID> slotId = std::nullopt;
|
||||
if(auto slot = getSelectedSlotID())
|
||||
slotId = slot->getSlot();
|
||||
controller.moveArmy(leftToRight, slotId);
|
||||
};
|
||||
|
||||
auto openBackpack = [this](const CGHeroInstance * hero) -> void
|
||||
{
|
||||
GH.windows().createAndPushWindow<CHeroBackpackWindow>(hero);
|
||||
for(auto artSet : artSets)
|
||||
GH.windows().topWindow<CHeroBackpackWindow>()->addSet(artSet);
|
||||
};
|
||||
|
||||
moveAllGarrButtonLeft = std::make_shared<CButton>(Point(325, 118), AnimationPath::builtin(QUICK_EXCHANGE_MOD_PREFIX + "/armRight.DEF"), CButton::tooltip(CGI->generaltexth->qeModCommands[1]),
|
||||
std::bind(moveArmy, true));
|
||||
exchangeGarrButton = std::make_shared<CButton>(Point(377, 118), AnimationPath::builtin(QUICK_EXCHANGE_MOD_PREFIX + "/swapAll.DEF"), CButton::tooltip(CGI->generaltexth->qeModCommands[2]),
|
||||
std::bind(&CExchangeController::swapArmy, &controller));
|
||||
moveAllGarrButtonRight = std::make_shared<CButton>(Point(425, 118), AnimationPath::builtin(QUICK_EXCHANGE_MOD_PREFIX + "/armLeft.DEF"), CButton::tooltip(CGI->generaltexth->qeModCommands[1]),
|
||||
std::bind(moveArmy, false));
|
||||
moveArtifactsButtonLeft = std::make_shared<CButton>(Point(325, 154), AnimationPath::builtin(QUICK_EXCHANGE_MOD_PREFIX + "/artRight.DEF"), CButton::tooltip(CGI->generaltexth->qeModCommands[3]),
|
||||
std::bind(moveArtifacts, [this](bool equipped, bool baclpack) -> void {controller.moveArtifacts(true, equipped, baclpack);}));
|
||||
exchangeArtifactsButton = std::make_shared<CButton>(Point(377, 154), AnimationPath::builtin(QUICK_EXCHANGE_MOD_PREFIX + "/swapAll.DEF"), CButton::tooltip(CGI->generaltexth->qeModCommands[4]),
|
||||
std::bind(moveArtifacts, [this](bool equipped, bool baclpack) -> void {controller.swapArtifacts(equipped, baclpack);}));
|
||||
moveArtifactsButtonRight = std::make_shared<CButton>(Point(425, 154), AnimationPath::builtin(QUICK_EXCHANGE_MOD_PREFIX + "/artLeft.DEF"), CButton::tooltip(CGI->generaltexth->qeModCommands[3]),
|
||||
std::bind(moveArtifacts, [this](bool equipped, bool baclpack) -> void {controller.moveArtifacts(false, equipped, baclpack);}));
|
||||
backpackButtonLeft = std::make_shared<CButton>(Point(325, 518), AnimationPath::builtin("buttons/backpack"), CButton::tooltipLocalized("vcmi.heroWindow.openBackpack"),
|
||||
std::bind(openBackpack, heroInst[0]));
|
||||
backpackButtonLeft->addOverlay(std::make_shared<CPicture>(ImagePath::builtin("buttons/backpackButtonIcon")));
|
||||
backpackButtonRight = std::make_shared<CButton>(Point(419, 518), AnimationPath::builtin("buttons/backpack"), CButton::tooltipLocalized("vcmi.heroWindow.openBackpack"),
|
||||
std::bind(openBackpack, heroInst[1]));
|
||||
backpackButtonRight->addOverlay(std::make_shared<CPicture>(ImagePath::builtin("buttons/backpackButtonIcon")));
|
||||
|
||||
auto leftHeroBlock = heroInst[0]->tempOwner != LOCPLINT->cb->getPlayerID();
|
||||
auto rightHeroBlock = heroInst[1]->tempOwner != LOCPLINT->cb->getPlayerID();
|
||||
moveAllGarrButtonLeft->block(leftHeroBlock);
|
||||
exchangeGarrButton->block(leftHeroBlock || rightHeroBlock);
|
||||
moveAllGarrButtonRight->block(rightHeroBlock);
|
||||
moveArtifactsButtonLeft->block(leftHeroBlock);
|
||||
exchangeArtifactsButton->block(leftHeroBlock || rightHeroBlock);
|
||||
moveArtifactsButtonRight->block(rightHeroBlock);
|
||||
backpackButtonLeft->block(leftHeroBlock);
|
||||
backpackButtonRight->block(rightHeroBlock);
|
||||
|
||||
for(int i = 0; i < GameConstants::ARMY_SIZE; i++)
|
||||
{
|
||||
@ -996,14 +819,16 @@ CExchangeWindow::CExchangeWindow(ObjectInstanceID hero1, ObjectInstanceID hero2,
|
||||
Point(484 + 35 * i, 154),
|
||||
AnimationPath::builtin(QUICK_EXCHANGE_MOD_PREFIX + "/unitLeft.DEF"),
|
||||
CButton::tooltip(CGI->generaltexth->qeModCommands[1]),
|
||||
controller.onMoveStackToLeft(SlotID(i))));
|
||||
std::bind(&CExchangeController::moveStack, &controller, false, SlotID(i))));
|
||||
moveStackLeftButtons.back()->block(leftHeroBlock);
|
||||
|
||||
moveStackRightButtons.push_back(
|
||||
std::make_shared<CButton>(
|
||||
Point(66 + 35 * i, 154),
|
||||
AnimationPath::builtin(QUICK_EXCHANGE_MOD_PREFIX + "/unitRight.DEF"),
|
||||
CButton::tooltip(CGI->generaltexth->qeModCommands[1]),
|
||||
controller.onMoveStackToRight(SlotID(i))));
|
||||
std::bind(&CExchangeController::moveStack, &controller, true, SlotID(i))));
|
||||
moveStackLeftButtons.back()->block(rightHeroBlock);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -9,10 +9,8 @@
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include "CWindowObject.h"
|
||||
#include "../lib/GameConstants.h"
|
||||
#include "../lib/ResourceSet.h"
|
||||
#include "../lib/int3.h"
|
||||
#include "../widgets/CExchangeController.h"
|
||||
#include "../widgets/CWindowWithArtifacts.h"
|
||||
#include "../widgets/Images.h"
|
||||
|
||||
@ -28,16 +26,13 @@ class CreatureCostBox;
|
||||
class CCreaturePic;
|
||||
class MoraleLuckBox;
|
||||
class CHeroArea;
|
||||
class CMinorResDataBar;
|
||||
class CSlider;
|
||||
class CComponentBox;
|
||||
class CTextInput;
|
||||
class CListBox;
|
||||
class CLabelGroup;
|
||||
class CToggleButton;
|
||||
class CGStatusBar;
|
||||
class CTextBox;
|
||||
class CResDataBar;
|
||||
class CGarrisonInt;
|
||||
class CGarrisonSlot;
|
||||
|
||||
@ -246,35 +241,6 @@ public:
|
||||
void show(Canvas & to) override;
|
||||
};
|
||||
|
||||
class CCallback;
|
||||
class CExchangeWindow;
|
||||
|
||||
class CExchangeController
|
||||
{
|
||||
private:
|
||||
const CGHeroInstance * left;
|
||||
const CGHeroInstance * right;
|
||||
std::shared_ptr<CCallback> cb;
|
||||
CExchangeWindow * view;
|
||||
|
||||
public:
|
||||
CExchangeController(CExchangeWindow * view, ObjectInstanceID hero1, ObjectInstanceID hero2);
|
||||
std::function<void()> onMoveArmyToRight();
|
||||
std::function<void()> onSwapArmy();
|
||||
std::function<void()> onMoveArmyToLeft();
|
||||
std::function<void()> onSwapArtifacts();
|
||||
std::function<void()> onMoveArtifactsToLeft();
|
||||
std::function<void()> onMoveArtifactsToRight();
|
||||
std::function<void()> onMoveStackToLeft(SlotID slotID);
|
||||
std::function<void()> onMoveStackToRight(SlotID slotID);
|
||||
|
||||
private:
|
||||
void moveArmy(bool leftToRight);
|
||||
void moveArtifacts(bool leftToRight);
|
||||
void moveArtifact(const CGHeroInstance * source, const CGHeroInstance * target, ArtifactPosition srcPosition);
|
||||
void moveStack(const CGHeroInstance * source, const CGHeroInstance * target, SlotID sourceSlot);
|
||||
};
|
||||
|
||||
class CExchangeWindow : public CStatusbarWindow, public IGarrisonHolder, public CWindowWithArtifacts
|
||||
{
|
||||
std::array<std::shared_ptr<CLabel>, 2> titles;
|
||||
@ -303,13 +269,15 @@ class CExchangeWindow : public CStatusbarWindow, public IGarrisonHolder, public
|
||||
|
||||
std::shared_ptr<CGarrisonInt> garr;
|
||||
std::shared_ptr<CButton> moveAllGarrButtonLeft;
|
||||
std::shared_ptr<CButton> echangeGarrButton;
|
||||
std::shared_ptr<CButton> exchangeGarrButton;
|
||||
std::shared_ptr<CButton> moveAllGarrButtonRight;
|
||||
std::shared_ptr<CButton> moveArtifactsButtonLeft;
|
||||
std::shared_ptr<CButton> echangeArtifactsButton;
|
||||
std::shared_ptr<CButton> exchangeArtifactsButton;
|
||||
std::shared_ptr<CButton> moveArtifactsButtonRight;
|
||||
std::vector<std::shared_ptr<CButton>> moveStackLeftButtons;
|
||||
std::vector<std::shared_ptr<CButton>> moveStackRightButtons;
|
||||
std::shared_ptr<CButton> backpackButtonLeft;
|
||||
std::shared_ptr<CButton> backpackButtonRight;
|
||||
CExchangeController controller;
|
||||
|
||||
public:
|
||||
|
@ -170,7 +170,6 @@ DLL_LINKAGE CArtifactInstance * ArtifactUtils::createNewArtifactInstance(CArtifa
|
||||
auto * artInst = new CArtifactInstance(art);
|
||||
if(art->isCombined())
|
||||
{
|
||||
assert(art->isCombined());
|
||||
for(const auto & part : art->getConstituents())
|
||||
artInst->addPart(ArtifactUtils::createNewArtifactInstance(part), ArtifactPosition::PRE_FIRST);
|
||||
}
|
||||
|
@ -9,7 +9,6 @@
|
||||
*/
|
||||
|
||||
#include "StdInc.h"
|
||||
#include "CArtHandler.h"
|
||||
|
||||
#include "ArtifactUtils.h"
|
||||
#include "CGeneralTextHandler.h"
|
||||
@ -925,8 +924,10 @@ unsigned CArtifactSet::getArtPosCount(const ArtifactID & aid, bool onlyWorn, boo
|
||||
return 0;
|
||||
}
|
||||
|
||||
void CArtifactSet::putArtifact(ArtifactPosition slot, CArtifactInstance * art)
|
||||
CArtifactSet::ArtPlacementMap CArtifactSet::putArtifact(ArtifactPosition slot, CArtifactInstance * art)
|
||||
{
|
||||
ArtPlacementMap resArtPlacement;
|
||||
|
||||
setNewArtSlot(slot, art, false);
|
||||
if(art->artType->isCombined() && ArtifactUtils::isSlotEquipment(slot))
|
||||
{
|
||||
@ -939,18 +940,25 @@ void CArtifactSet::putArtifact(ArtifactPosition slot, CArtifactInstance * art)
|
||||
break;
|
||||
}
|
||||
|
||||
for(auto & part : art->getPartsInfo())
|
||||
for(const auto & part : art->getPartsInfo())
|
||||
{
|
||||
if(part.art != mainPart)
|
||||
{
|
||||
if(!part.art->artType->canBePutAt(this, part.slot))
|
||||
part.slot = ArtifactUtils::getArtAnyPosition(this, part.art->getTypeId());
|
||||
auto partSlot = part.slot;
|
||||
if(!part.art->artType->canBePutAt(this, partSlot))
|
||||
partSlot = ArtifactUtils::getArtAnyPosition(this, part.art->getTypeId());
|
||||
|
||||
assert(ArtifactUtils::isSlotEquipment(part.slot));
|
||||
setNewArtSlot(part.slot, part.art, true);
|
||||
assert(ArtifactUtils::isSlotEquipment(partSlot));
|
||||
setNewArtSlot(partSlot, part.art, true);
|
||||
resArtPlacement.emplace(std::make_pair(part.art, partSlot));
|
||||
}
|
||||
else
|
||||
{
|
||||
resArtPlacement.emplace(std::make_pair(part.art, part.slot));
|
||||
}
|
||||
}
|
||||
}
|
||||
return resArtPlacement;
|
||||
}
|
||||
|
||||
void CArtifactSet::removeArtifact(ArtifactPosition slot)
|
||||
@ -1031,7 +1039,7 @@ bool CArtifactSet::isPositionFree(const ArtifactPosition & pos, bool onlyLockChe
|
||||
return true; //no slot means not used
|
||||
}
|
||||
|
||||
void CArtifactSet::setNewArtSlot(const ArtifactPosition & slot, CArtifactInstance * art, bool locked)
|
||||
void CArtifactSet::setNewArtSlot(const ArtifactPosition & slot, ConstTransitivePtr<CArtifactInstance> art, bool locked)
|
||||
{
|
||||
assert(!vstd::contains(artifactsWorn, slot));
|
||||
|
||||
|
@ -246,11 +246,13 @@ struct DLL_LINKAGE ArtSlotInfo
|
||||
class DLL_LINKAGE CArtifactSet
|
||||
{
|
||||
public:
|
||||
using ArtPlacementMap = std::map<CArtifactInstance*, ArtifactPosition>;
|
||||
|
||||
std::vector<ArtSlotInfo> artifactsInBackpack; //hero's artifacts from bag
|
||||
std::map<ArtifactPosition, ArtSlotInfo> artifactsWorn; //map<position,artifact_id>; positions: 0 - head; 1 - shoulders; 2 - neck; 3 - right hand; 4 - left hand; 5 - torso; 6 - right ring; 7 - left ring; 8 - feet; 9 - misc1; 10 - misc2; 11 - misc3; 12 - misc4; 13 - mach1; 14 - mach2; 15 - mach3; 16 - mach4; 17 - spellbook; 18 - misc5
|
||||
std::vector<ArtSlotInfo> artifactsTransitionPos; // Used as transition position for dragAndDrop artifact exchange
|
||||
|
||||
void setNewArtSlot(const ArtifactPosition & slot, CArtifactInstance * art, bool locked);
|
||||
void setNewArtSlot(const ArtifactPosition & slot, ConstTransitivePtr<CArtifactInstance> art, bool locked);
|
||||
void eraseArtSlot(const ArtifactPosition & slot);
|
||||
|
||||
const ArtSlotInfo * getSlot(const ArtifactPosition & pos) const;
|
||||
@ -275,7 +277,7 @@ public:
|
||||
unsigned getArtPosCount(const ArtifactID & aid, bool onlyWorn = true, bool searchBackpackAssemblies = true, bool allowLocked = true) const;
|
||||
|
||||
virtual ArtBearer::ArtBearer bearerType() const = 0;
|
||||
virtual void putArtifact(ArtifactPosition slot, CArtifactInstance * art);
|
||||
virtual ArtPlacementMap putArtifact(ArtifactPosition slot, CArtifactInstance * art);
|
||||
virtual void removeArtifact(ArtifactPosition slot);
|
||||
virtual ~CArtifactSet();
|
||||
|
||||
|
@ -44,17 +44,21 @@ bool CCombinedArtifactInstance::isPart(const CArtifactInstance * supposedPart) c
|
||||
return false;
|
||||
}
|
||||
|
||||
std::vector<CCombinedArtifactInstance::PartInfo> & CCombinedArtifactInstance::getPartsInfo()
|
||||
{
|
||||
// TODO romove this func. encapsulation violation
|
||||
return partsInfo;
|
||||
}
|
||||
|
||||
const std::vector<CCombinedArtifactInstance::PartInfo> & CCombinedArtifactInstance::getPartsInfo() const
|
||||
{
|
||||
return partsInfo;
|
||||
}
|
||||
|
||||
void CCombinedArtifactInstance::addPlacementMap(CArtifactSet::ArtPlacementMap & placementMap)
|
||||
{
|
||||
if(!placementMap.empty())
|
||||
for(auto & part : partsInfo)
|
||||
{
|
||||
assert(placementMap.find(part.art) != placementMap.end());
|
||||
part.slot = placementMap.at(part.art);
|
||||
}
|
||||
}
|
||||
|
||||
SpellID CScrollArtifactInstance::getScrollSpellID() const
|
||||
{
|
||||
auto artInst = static_cast<const CArtifactInstance*>(this);
|
||||
@ -163,7 +167,8 @@ bool CArtifactInstance::isCombined() const
|
||||
|
||||
void CArtifactInstance::putAt(const ArtifactLocation & al)
|
||||
{
|
||||
al.getHolderArtSet()->putArtifact(al.slot, this);
|
||||
auto placementMap = al.getHolderArtSet()->putArtifact(al.slot, this);
|
||||
addPlacementMap(placementMap);
|
||||
}
|
||||
|
||||
void CArtifactInstance::removeFrom(const ArtifactLocation & al)
|
||||
|
@ -12,6 +12,7 @@
|
||||
#include "bonuses/CBonusSystemNode.h"
|
||||
#include "GameConstants.h"
|
||||
#include "ConstTransitivePtr.h"
|
||||
#include "CArtHandler.h"
|
||||
|
||||
VCMI_LIB_NAMESPACE_BEGIN
|
||||
|
||||
@ -37,8 +38,8 @@ public:
|
||||
void addPart(CArtifactInstance * art, const ArtifactPosition & slot);
|
||||
// Checks if supposed part inst is part of this combined art inst
|
||||
bool isPart(const CArtifactInstance * supposedPart) const;
|
||||
std::vector<PartInfo> & getPartsInfo();
|
||||
const std::vector<PartInfo> & getPartsInfo() const;
|
||||
void addPlacementMap(CArtifactSet::ArtPlacementMap & placementMap);
|
||||
|
||||
template <typename Handler> void serialize(Handler & h, const int version)
|
||||
{
|
||||
|
@ -868,14 +868,13 @@ ArtBearer::ArtBearer CStackInstance::bearerType() const
|
||||
return ArtBearer::CREATURE;
|
||||
}
|
||||
|
||||
void CStackInstance::putArtifact(ArtifactPosition pos, CArtifactInstance * art)
|
||||
CStackInstance::ArtPlacementMap CStackInstance::putArtifact(ArtifactPosition pos, CArtifactInstance * art)
|
||||
{
|
||||
assert(!getArt(pos));
|
||||
assert(art->artType->canBePutAt(this, pos));
|
||||
|
||||
CArtifactSet::putArtifact(pos, art);
|
||||
if(ArtifactUtils::isSlotEquipment(pos))
|
||||
attachTo(*art);
|
||||
attachTo(*art);
|
||||
return CArtifactSet::putArtifact(pos, art);
|
||||
}
|
||||
|
||||
void CStackInstance::removeArtifact(ArtifactPosition pos)
|
||||
|
@ -121,7 +121,7 @@ public:
|
||||
void setArmyObj(const CArmedInstance *ArmyObj);
|
||||
virtual void giveStackExp(TExpType exp);
|
||||
bool valid(bool allowUnrandomized) const;
|
||||
void putArtifact(ArtifactPosition pos, CArtifactInstance * art) override;//from CArtifactSet
|
||||
ArtPlacementMap putArtifact(ArtifactPosition pos, CArtifactInstance * art) override;//from CArtifactSet
|
||||
void removeArtifact(ArtifactPosition pos) override;
|
||||
ArtBearer::ArtBearer bearerType() const override; //from CArtifactSet
|
||||
virtual std::string nodeName() const override; //from CBonusSystemnode
|
||||
|
@ -2439,12 +2439,16 @@ struct DLL_LINKAGE BulkExchangeArtifacts : public CPackForServer
|
||||
ObjectInstanceID srcHero;
|
||||
ObjectInstanceID dstHero;
|
||||
bool swap = false;
|
||||
bool equipped = true;
|
||||
bool backpack = true;
|
||||
|
||||
BulkExchangeArtifacts() = default;
|
||||
BulkExchangeArtifacts(const ObjectInstanceID & srcHero, const ObjectInstanceID & dstHero, bool swap)
|
||||
BulkExchangeArtifacts(const ObjectInstanceID & srcHero, const ObjectInstanceID & dstHero, bool swap, bool equipped, bool backpack)
|
||||
: srcHero(srcHero)
|
||||
, dstHero(dstHero)
|
||||
, swap(swap)
|
||||
, equipped(equipped)
|
||||
, backpack(backpack)
|
||||
{
|
||||
}
|
||||
|
||||
@ -2456,6 +2460,8 @@ struct DLL_LINKAGE BulkExchangeArtifacts : public CPackForServer
|
||||
h & srcHero;
|
||||
h & dstHero;
|
||||
h & swap;
|
||||
h & equipped;
|
||||
h & backpack;
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -1066,13 +1066,13 @@ std::string CGHeroInstance::getBiographyTextID() const
|
||||
return "";
|
||||
}
|
||||
|
||||
void CGHeroInstance::putArtifact(ArtifactPosition pos, CArtifactInstance *art)
|
||||
CGHeroInstance::ArtPlacementMap CGHeroInstance::putArtifact(ArtifactPosition pos, CArtifactInstance * art)
|
||||
{
|
||||
assert(art->artType->canBePutAt(this, pos));
|
||||
|
||||
CArtifactSet::putArtifact(pos, art);
|
||||
if(ArtifactUtils::isSlotEquipment(pos))
|
||||
attachTo(*art);
|
||||
return CArtifactSet::putArtifact(pos, art);
|
||||
}
|
||||
|
||||
void CGHeroInstance::removeArtifact(ArtifactPosition pos)
|
||||
|
@ -229,7 +229,7 @@ public:
|
||||
void initHero(CRandomGenerator & rand);
|
||||
void initHero(CRandomGenerator & rand, const HeroTypeID & SUBID);
|
||||
|
||||
void putArtifact(ArtifactPosition pos, CArtifactInstance * art) override;
|
||||
ArtPlacementMap putArtifact(ArtifactPosition pos, CArtifactInstance * art) override;
|
||||
void removeArtifact(ArtifactPosition pos) override;
|
||||
void initExp(CRandomGenerator & rand);
|
||||
void initArmy(CRandomGenerator & rand, IArmyDescriptor *dst = nullptr);
|
||||
|
@ -492,7 +492,7 @@ void CMap::checkForObjectives()
|
||||
}
|
||||
}
|
||||
|
||||
void CMap::addNewArtifactInstance(CArtifactInstance * art)
|
||||
void CMap::addNewArtifactInstance(ConstTransitivePtr<CArtifactInstance> art)
|
||||
{
|
||||
art->setId(static_cast<ArtifactInstanceID>(artInstances.size()));
|
||||
artInstances.emplace_back(art);
|
||||
|
@ -94,7 +94,7 @@ public:
|
||||
void removeBlockVisTiles(CGObjectInstance * obj, bool total = false);
|
||||
void calculateGuardingGreaturePositions();
|
||||
|
||||
void addNewArtifactInstance(CArtifactInstance * art);
|
||||
void addNewArtifactInstance(ConstTransitivePtr<CArtifactInstance> art);
|
||||
void eraseArtifactInstance(CArtifactInstance * art);
|
||||
|
||||
void addNewQuestInstance(CQuest * quest);
|
||||
|
@ -941,10 +941,10 @@ bool CMapLoaderH3M::loadArtifactToSlot(CGHeroInstance * hero, int slot)
|
||||
// He has Shackles of War (normally - MISC slot artifact) in LEFT_HAND slot set in editor
|
||||
// Artifact seems to be missing in game, so skip artifacts that don't fit target slot
|
||||
auto * artifact = ArtifactUtils::createArtifact(map, artifactID);
|
||||
auto artifactPos = ArtifactPosition(slot);
|
||||
if(artifact->canBePutAt(ArtifactLocation(hero, artifactPos)))
|
||||
auto dstLoc = ArtifactLocation(hero, ArtifactPosition(slot));
|
||||
if(artifact->canBePutAt(dstLoc))
|
||||
{
|
||||
hero->putArtifact(artifactPos, artifact);
|
||||
artifact->putAt(dstLoc);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -2744,7 +2744,7 @@ bool CGameHandler::moveArtifact(const ArtifactLocation &al1, const ArtifactLocat
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CGameHandler::bulkMoveArtifacts(ObjectInstanceID srcHero, ObjectInstanceID dstHero, bool swap)
|
||||
bool CGameHandler::bulkMoveArtifacts(ObjectInstanceID srcHero, ObjectInstanceID dstHero, bool swap, bool equipped, bool backpack)
|
||||
{
|
||||
// Make sure exchange is even possible between the two heroes.
|
||||
if(!isAllowedExchange(srcHero, dstHero))
|
||||
@ -2799,34 +2799,45 @@ bool CGameHandler::bulkMoveArtifacts(ObjectInstanceID srcHero, ObjectInstanceID
|
||||
slots.push_back(BulkMoveArtifacts::LinkedSlots(slot, slot));
|
||||
}
|
||||
};
|
||||
// Move over artifacts that are worn srcHero -> dstHero
|
||||
moveArtsWorn(psrcHero, pdstHero, slotsSrcDst);
|
||||
artFittingSet.artifactsWorn.clear();
|
||||
// Move over artifacts that are worn dstHero -> srcHero
|
||||
moveArtsWorn(pdstHero, psrcHero, slotsDstSrc);
|
||||
// Move over artifacts that are in backpack srcHero -> dstHero
|
||||
moveArtsInBackpack(psrcHero, slotsSrcDst);
|
||||
// Move over artifacts that are in backpack dstHero -> srcHero
|
||||
moveArtsInBackpack(pdstHero, slotsDstSrc);
|
||||
if(equipped)
|
||||
{
|
||||
// Move over artifacts that are worn srcHero -> dstHero
|
||||
moveArtsWorn(psrcHero, pdstHero, slotsSrcDst);
|
||||
artFittingSet.artifactsWorn.clear();
|
||||
// Move over artifacts that are worn dstHero -> srcHero
|
||||
moveArtsWorn(pdstHero, psrcHero, slotsDstSrc);
|
||||
}
|
||||
if(backpack)
|
||||
{
|
||||
// Move over artifacts that are in backpack srcHero -> dstHero
|
||||
moveArtsInBackpack(psrcHero, slotsSrcDst);
|
||||
// Move over artifacts that are in backpack dstHero -> srcHero
|
||||
moveArtsInBackpack(pdstHero, slotsDstSrc);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
artFittingSet.artifactsInBackpack = pdstHero->artifactsInBackpack;
|
||||
artFittingSet.artifactsWorn = pdstHero->artifactsWorn;
|
||||
|
||||
// Move over artifacts that are worn
|
||||
for(auto & artInfo : psrcHero->artifactsWorn)
|
||||
if(equipped)
|
||||
{
|
||||
if(ArtifactUtils::isArtRemovable(artInfo))
|
||||
// Move over artifacts that are worn
|
||||
for(auto & artInfo : psrcHero->artifactsWorn)
|
||||
{
|
||||
moveArtifact(psrcHero->getArt(artInfo.first), artInfo.first, pdstHero, slotsSrcDst);
|
||||
if(ArtifactUtils::isArtRemovable(artInfo))
|
||||
{
|
||||
moveArtifact(psrcHero->getArt(artInfo.first), artInfo.first, pdstHero, slotsSrcDst);
|
||||
}
|
||||
}
|
||||
}
|
||||
// Move over artifacts that are in backpack
|
||||
for(auto & slotInfo : psrcHero->artifactsInBackpack)
|
||||
if(backpack)
|
||||
{
|
||||
moveArtifact(psrcHero->getArt(psrcHero->getArtPos(slotInfo.artifact)),
|
||||
psrcHero->getArtPos(slotInfo.artifact), pdstHero, slotsSrcDst);
|
||||
// Move over artifacts that are in backpack
|
||||
for(auto & slotInfo : psrcHero->artifactsInBackpack)
|
||||
{
|
||||
moveArtifact(psrcHero->getArt(psrcHero->getArtPos(slotInfo.artifact)),
|
||||
psrcHero->getArtPos(slotInfo.artifact), pdstHero, slotsSrcDst);
|
||||
}
|
||||
}
|
||||
}
|
||||
sendAndApply(&ma);
|
||||
|
@ -131,7 +131,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 swap);
|
||||
bool bulkMoveArtifacts(ObjectInstanceID srcHero, ObjectInstanceID dstHero, bool swap, bool equipped, bool backpack);
|
||||
bool eraseArtifactByClient(const ArtifactLocation & al);
|
||||
void synchronizeArtifactHandlerLists();
|
||||
|
||||
|
@ -68,7 +68,7 @@ void ApplyGhNetPackVisitor::visitArrangeStacks(ArrangeStacks & pack)
|
||||
|
||||
void ApplyGhNetPackVisitor::visitBulkMoveArmy(BulkMoveArmy & pack)
|
||||
{
|
||||
gh.throwIfWrongPlayer(&pack);
|
||||
gh.throwIfWrongOwner(&pack, pack.srcArmy);
|
||||
result = gh.bulkMoveArmy(pack.srcArmy, pack.destArmy, pack.srcSlot);
|
||||
}
|
||||
|
||||
@ -132,7 +132,9 @@ void ApplyGhNetPackVisitor::visitExchangeArtifacts(ExchangeArtifacts & pack)
|
||||
void ApplyGhNetPackVisitor::visitBulkExchangeArtifacts(BulkExchangeArtifacts & pack)
|
||||
{
|
||||
gh.throwIfWrongOwner(&pack, pack.srcHero);
|
||||
result = gh.bulkMoveArtifacts(pack.srcHero, pack.dstHero, pack.swap);
|
||||
if(pack.swap)
|
||||
gh.throwIfWrongOwner(&pack, pack.dstHero);
|
||||
result = gh.bulkMoveArtifacts(pack.srcHero, pack.dstHero, pack.swap, pack.equipped, pack.backpack);
|
||||
}
|
||||
|
||||
void ApplyGhNetPackVisitor::visitAssembleArtifacts(AssembleArtifacts & pack)
|
||||
|
Loading…
Reference in New Issue
Block a user