mirror of
https://github.com/vcmi/vcmi.git
synced 2025-02-03 13:01:33 +02:00
Merge pull request #4186 from SoundSSGood/end-of-battle-artifacts-transfer
End of battle artifacts transfer
This commit is contained in:
commit
ad9750ed3e
@ -173,9 +173,9 @@ bool CCallback::swapArtifacts(const ArtifactLocation &l1, const ArtifactLocation
|
||||
* @param assembleTo If assemble is true, this represents the artifact ID of the combination
|
||||
* artifact to assemble to. Otherwise it's not used.
|
||||
*/
|
||||
void CCallback::assembleArtifacts(const CGHeroInstance * hero, ArtifactPosition artifactSlot, bool assemble, ArtifactID assembleTo)
|
||||
void CCallback::assembleArtifacts(const ObjectInstanceID & heroID, ArtifactPosition artifactSlot, bool assemble, ArtifactID assembleTo)
|
||||
{
|
||||
AssembleArtifacts aa(hero->id, artifactSlot, assemble, assembleTo);
|
||||
AssembleArtifacts aa(heroID, artifactSlot, assemble, assembleTo);
|
||||
sendRequest(&aa);
|
||||
}
|
||||
|
||||
|
@ -93,7 +93,7 @@ public:
|
||||
virtual bool swapArtifacts(const ArtifactLocation &l1, const ArtifactLocation &l2)=0;
|
||||
virtual void scrollBackpackArtifacts(ObjectInstanceID hero, bool left) = 0;
|
||||
virtual void manageHeroCostume(ObjectInstanceID hero, size_t costumeIndex, bool saveCostume) = 0;
|
||||
virtual void assembleArtifacts(const CGHeroInstance * hero, ArtifactPosition artifactSlot, bool assemble, ArtifactID assembleTo)=0;
|
||||
virtual void assembleArtifacts(const ObjectInstanceID & heroID, ArtifactPosition artifactSlot, bool assemble, ArtifactID assembleTo)=0;
|
||||
virtual void eraseArtifactByClient(const ArtifactLocation & al)=0;
|
||||
virtual bool dismissCreature(const CArmedInstance *obj, SlotID stackPos)=0;
|
||||
virtual void endTurn()=0;
|
||||
@ -176,7 +176,7 @@ public:
|
||||
int bulkMergeStacks(ObjectInstanceID armyId, SlotID srcSlot) override;
|
||||
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 assembleArtifacts(const ObjectInstanceID & heroID, ArtifactPosition artifactSlot, bool assemble, ArtifactID assembleTo) override;
|
||||
void bulkMoveArtifacts(ObjectInstanceID srcHero, ObjectInstanceID dstHero, bool swap, bool equipped = true, bool backpack = true) override;
|
||||
void scrollBackpackArtifacts(ObjectInstanceID hero, bool left) override;
|
||||
void manageHeroCostume(ObjectInstanceID hero, size_t costumeIdx, bool saveCostume) override;
|
||||
|
166
client/ArtifactsUIController.cpp
Normal file
166
client/ArtifactsUIController.cpp
Normal file
@ -0,0 +1,166 @@
|
||||
/*
|
||||
* ArtifactsUIController.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 "ArtifactsUIController.h"
|
||||
#include "CGameInfo.h"
|
||||
#include "CPlayerInterface.h"
|
||||
|
||||
#include "../CCallback.h"
|
||||
#include "../lib/ArtifactUtils.h"
|
||||
#include "../lib/CGeneralTextHandler.h"
|
||||
#include "../lib/mapObjects/CGHeroInstance.h"
|
||||
|
||||
#include "gui/CGuiHandler.h"
|
||||
#include "gui/WindowHandler.h"
|
||||
#include "widgets/CComponent.h"
|
||||
#include "windows/CWindowWithArtifacts.h"
|
||||
|
||||
ArtifactsUIController::ArtifactsUIController()
|
||||
{
|
||||
numOfMovedArts = 0;
|
||||
}
|
||||
|
||||
bool ArtifactsUIController::askToAssemble(const ArtifactLocation & al, const bool onlyEquipped, const bool checkIgnored)
|
||||
{
|
||||
if(auto hero = LOCPLINT->cb->getHero(al.artHolder))
|
||||
{
|
||||
if(hero->getArt(al.slot) == nullptr)
|
||||
{
|
||||
logGlobal->error("artifact location %d points to nothing", al.slot.num);
|
||||
return false;
|
||||
}
|
||||
return askToAssemble(hero, al.slot, onlyEquipped, checkIgnored);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool ArtifactsUIController::askToAssemble(const CGHeroInstance * hero, const ArtifactPosition & slot,
|
||||
const bool onlyEquipped, const bool checkIgnored)
|
||||
{
|
||||
assert(hero);
|
||||
const auto art = hero->getArt(slot);
|
||||
assert(art);
|
||||
|
||||
if(hero->tempOwner != LOCPLINT->playerID)
|
||||
return false;
|
||||
|
||||
if(numOfArtsAskAssembleSession != 0)
|
||||
numOfArtsAskAssembleSession--;
|
||||
auto assemblyPossibilities = ArtifactUtils::assemblyPossibilities(hero, art->getTypeId(), onlyEquipped);
|
||||
if(!assemblyPossibilities.empty())
|
||||
{
|
||||
auto askThread = new boost::thread([this, hero, art, slot, assemblyPossibilities, checkIgnored]() -> void
|
||||
{
|
||||
boost::mutex::scoped_lock askLock(askAssembleArtifactMutex);
|
||||
for(const auto combinedArt : assemblyPossibilities)
|
||||
{
|
||||
boost::mutex::scoped_lock interfaceLock(GH.interfaceMutex);
|
||||
if(checkIgnored)
|
||||
{
|
||||
if(vstd::contains(ignoredArtifacts, combinedArt->getId()))
|
||||
continue;
|
||||
ignoredArtifacts.emplace(combinedArt->getId());
|
||||
}
|
||||
|
||||
bool assembleConfirmed = false;
|
||||
MetaString message = MetaString::createFromTextID(art->artType->getDescriptionTextID());
|
||||
message.appendEOL();
|
||||
message.appendEOL();
|
||||
message.appendRawString(CGI->generaltexth->allTexts[732]); // You possess all of the components needed to assemble the
|
||||
message.replaceName(ArtifactID(combinedArt->getId()));
|
||||
LOCPLINT->showYesNoDialog(message.toString(), [&assembleConfirmed, hero, slot, combinedArt]()
|
||||
{
|
||||
assembleConfirmed = true;
|
||||
LOCPLINT->cb.get()->assembleArtifacts(hero->id, slot, true, combinedArt->getId());
|
||||
}, nullptr, {std::make_shared<CComponent>(ComponentType::ARTIFACT, combinedArt->getId())});
|
||||
|
||||
LOCPLINT->waitWhileDialog();
|
||||
if(assembleConfirmed)
|
||||
break;
|
||||
}
|
||||
});
|
||||
askThread->detach();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool ArtifactsUIController::askToDisassemble(const CGHeroInstance * hero, const ArtifactPosition & slot)
|
||||
{
|
||||
assert(hero);
|
||||
const auto art = hero->getArt(slot);
|
||||
assert(art);
|
||||
|
||||
if(hero->tempOwner != LOCPLINT->playerID)
|
||||
return false;
|
||||
|
||||
if(art->isCombined())
|
||||
{
|
||||
if(ArtifactUtils::isSlotBackpack(slot) && !ArtifactUtils::isBackpackFreeSlots(hero, art->artType->getConstituents().size() - 1))
|
||||
return false;
|
||||
|
||||
MetaString message = MetaString::createFromTextID(art->artType->getDescriptionTextID());
|
||||
message.appendEOL();
|
||||
message.appendEOL();
|
||||
message.appendRawString(CGI->generaltexth->allTexts[733]); // Do you wish to disassemble this artifact?
|
||||
LOCPLINT->showYesNoDialog(message.toString(), [hero, slot]()
|
||||
{
|
||||
LOCPLINT->cb->assembleArtifacts(hero->id, slot, false, ArtifactID());
|
||||
}, nullptr);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void ArtifactsUIController::artifactRemoved()
|
||||
{
|
||||
for(const auto & artWin : GH.windows().findWindows<CWindowWithArtifacts>())
|
||||
artWin->update();
|
||||
LOCPLINT->waitWhileDialog();
|
||||
}
|
||||
|
||||
void ArtifactsUIController::artifactMoved()
|
||||
{
|
||||
// If a bulk transfer has arrived, then redrawing only the last art movement.
|
||||
if(numOfMovedArts != 0)
|
||||
numOfMovedArts--;
|
||||
|
||||
if(numOfMovedArts == 0)
|
||||
for(const auto & artWin : GH.windows().findWindows<CWindowWithArtifacts>())
|
||||
{
|
||||
artWin->update();
|
||||
}
|
||||
LOCPLINT->waitWhileDialog();
|
||||
}
|
||||
|
||||
void ArtifactsUIController::bulkArtMovementStart(size_t totalNumOfArts, size_t possibleAssemblyNumOfArts)
|
||||
{
|
||||
assert(totalNumOfArts >= possibleAssemblyNumOfArts);
|
||||
numOfMovedArts = totalNumOfArts;
|
||||
if(numOfArtsAskAssembleSession == 0)
|
||||
{
|
||||
// Do not start the next session until the previous one is finished
|
||||
numOfArtsAskAssembleSession = possibleAssemblyNumOfArts;
|
||||
ignoredArtifacts.clear();
|
||||
}
|
||||
}
|
||||
|
||||
void ArtifactsUIController::artifactAssembled()
|
||||
{
|
||||
for(const auto & artWin : GH.windows().findWindows<CWindowWithArtifacts>())
|
||||
artWin->update();
|
||||
}
|
||||
|
||||
void ArtifactsUIController::artifactDisassembled()
|
||||
{
|
||||
for(const auto & artWin : GH.windows().findWindows<CWindowWithArtifacts>())
|
||||
artWin->update();
|
||||
}
|
42
client/ArtifactsUIController.h
Normal file
42
client/ArtifactsUIController.h
Normal file
@ -0,0 +1,42 @@
|
||||
/*
|
||||
* ArtifactsUIController.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 "../lib/constants/EntityIdentifiers.h"
|
||||
#include "../lib/networkPacks/ArtifactLocation.h"
|
||||
|
||||
VCMI_LIB_NAMESPACE_BEGIN
|
||||
|
||||
class CGHeroInstance;
|
||||
|
||||
VCMI_LIB_NAMESPACE_END
|
||||
|
||||
class ArtifactsUIController
|
||||
{
|
||||
size_t numOfMovedArts;
|
||||
size_t numOfArtsAskAssembleSession;
|
||||
std::set<ArtifactID> ignoredArtifacts;
|
||||
|
||||
boost::mutex askAssembleArtifactMutex;
|
||||
|
||||
public:
|
||||
ArtifactsUIController();
|
||||
bool askToAssemble(const ArtifactLocation & al, const bool onlyEquipped = false, const bool checkIgnored = false);
|
||||
bool askToAssemble(const CGHeroInstance * hero, const ArtifactPosition & slot, const bool onlyEquipped = false,
|
||||
const bool checkIgnored = false);
|
||||
bool askToDisassemble(const CGHeroInstance * hero, const ArtifactPosition & slot);
|
||||
|
||||
void artifactRemoved();
|
||||
void artifactMoved();
|
||||
void bulkArtMovementStart(size_t totalNumOfArts, size_t possibleAssemblyNumOfArts);
|
||||
void artifactAssembled();
|
||||
void artifactDisassembled();
|
||||
};
|
||||
|
@ -168,6 +168,7 @@ set(client_SRCS
|
||||
windows/settings/BattleOptionsTab.cpp
|
||||
windows/settings/AdventureOptionsTab.cpp
|
||||
|
||||
ArtifactsUIController.cpp
|
||||
CGameInfo.cpp
|
||||
CMT.cpp
|
||||
CPlayerInterface.cpp
|
||||
@ -371,6 +372,7 @@ set(client_HEADERS
|
||||
windows/settings/BattleOptionsTab.h
|
||||
windows/settings/AdventureOptionsTab.h
|
||||
|
||||
ArtifactsUIController.h
|
||||
CGameInfo.h
|
||||
CMT.h
|
||||
CPlayerInterface.h
|
||||
|
@ -66,7 +66,6 @@
|
||||
|
||||
#include "../CCallback.h"
|
||||
|
||||
#include "../lib/CArtHandler.h"
|
||||
#include "../lib/CConfigHandler.h"
|
||||
#include "../lib/CGeneralTextHandler.h"
|
||||
#include "../lib/CHeroHandler.h"
|
||||
@ -132,7 +131,9 @@ struct HeroObjectRetriever
|
||||
|
||||
CPlayerInterface::CPlayerInterface(PlayerColor Player):
|
||||
localState(std::make_unique<PlayerLocalState>(*this)),
|
||||
movementController(std::make_unique<HeroMovementController>())
|
||||
movementController(std::make_unique<HeroMovementController>()),
|
||||
artifactController(std::make_unique<ArtifactsUIController>())
|
||||
|
||||
{
|
||||
logGlobal->trace("\tHuman player interface for player %s being constructed", Player.toString());
|
||||
GH.defActionsDef = 0;
|
||||
@ -148,7 +149,6 @@ CPlayerInterface::CPlayerInterface(PlayerColor Player):
|
||||
isAutoFightOn = false;
|
||||
isAutoFightEndBattle = false;
|
||||
ignoreEvents = false;
|
||||
numOfMovedArts = 0;
|
||||
}
|
||||
|
||||
CPlayerInterface::~CPlayerInterface()
|
||||
@ -1252,35 +1252,6 @@ void CPlayerInterface::showGarrisonDialog( const CArmedInstance *up, const CGHer
|
||||
GH.windows().pushWindow(cgw);
|
||||
}
|
||||
|
||||
/**
|
||||
* Shows the dialog that appears when right-clicking an artifact that can be assembled
|
||||
* into a combinational one on an artifact screen. Does not require the combination of
|
||||
* artifacts to be legal.
|
||||
*/
|
||||
void CPlayerInterface::showArtifactAssemblyDialog(const Artifact * artifact, const Artifact * assembledArtifact, CFunctionList<void()> onYes)
|
||||
{
|
||||
std::string text = artifact->getDescriptionTranslated();
|
||||
text += "\n\n";
|
||||
std::vector<std::shared_ptr<CComponent>> scs;
|
||||
|
||||
if(assembledArtifact)
|
||||
{
|
||||
// You possess all of the components to...
|
||||
text += boost::str(boost::format(CGI->generaltexth->allTexts[732]) % assembledArtifact->getNameTranslated());
|
||||
|
||||
// Picture of assembled artifact at bottom.
|
||||
auto sc = std::make_shared<CComponent>(ComponentType::ARTIFACT, assembledArtifact->getId());
|
||||
scs.push_back(sc);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Do you wish to disassemble this artifact?
|
||||
text += CGI->generaltexth->allTexts[733];
|
||||
}
|
||||
|
||||
showYesNoDialog(text, onYes, nullptr, scs);
|
||||
}
|
||||
|
||||
void CPlayerInterface::requestRealized( PackageApplied *pa )
|
||||
{
|
||||
if(pa->packType == CTypeList::getInstance().getTypeID<MoveHero>(nullptr))
|
||||
@ -1738,17 +1709,7 @@ void CPlayerInterface::showShipyardDialogOrProblemPopup(const IShipyard *obj)
|
||||
|
||||
void CPlayerInterface::askToAssembleArtifact(const ArtifactLocation &al)
|
||||
{
|
||||
if(auto hero = cb->getHero(al.artHolder))
|
||||
{
|
||||
auto art = hero->getArt(al.slot);
|
||||
if(art == nullptr)
|
||||
{
|
||||
logGlobal->error("artifact location %d points to nothing",
|
||||
al.slot.num);
|
||||
return;
|
||||
}
|
||||
ArtifactUtilsClient::askToAssemble(hero, al.slot);
|
||||
}
|
||||
artifactController->askToAssemble(al, true, true);
|
||||
}
|
||||
|
||||
void CPlayerInterface::artifactPut(const ArtifactLocation &al)
|
||||
@ -1761,55 +1722,33 @@ void CPlayerInterface::artifactRemoved(const ArtifactLocation &al)
|
||||
{
|
||||
EVENT_HANDLER_CALLED_BY_CLIENT;
|
||||
adventureInt->onHeroChanged(cb->getHero(al.artHolder));
|
||||
|
||||
for(auto artWin : GH.windows().findWindows<CWindowWithArtifacts>())
|
||||
artWin->artifactRemoved(al);
|
||||
|
||||
waitWhileDialog();
|
||||
artifactController->artifactRemoved();
|
||||
}
|
||||
|
||||
void CPlayerInterface::artifactMoved(const ArtifactLocation &src, const ArtifactLocation &dst)
|
||||
{
|
||||
EVENT_HANDLER_CALLED_BY_CLIENT;
|
||||
adventureInt->onHeroChanged(cb->getHero(dst.artHolder));
|
||||
|
||||
// If a bulk transfer has arrived, then redrawing only the last art movement.
|
||||
if(numOfMovedArts != 0)
|
||||
numOfMovedArts--;
|
||||
|
||||
for(auto artWin : GH.windows().findWindows<CWindowWithArtifacts>())
|
||||
{
|
||||
artWin->artifactMoved(src, dst);
|
||||
if(numOfMovedArts == 0)
|
||||
{
|
||||
artWin->update();
|
||||
artWin->redraw();
|
||||
}
|
||||
}
|
||||
waitWhileDialog();
|
||||
artifactController->artifactMoved();
|
||||
}
|
||||
|
||||
void CPlayerInterface::bulkArtMovementStart(size_t numOfArts)
|
||||
void CPlayerInterface::bulkArtMovementStart(size_t totalNumOfArts, size_t possibleAssemblyNumOfArts)
|
||||
{
|
||||
numOfMovedArts = numOfArts;
|
||||
artifactController->bulkArtMovementStart(totalNumOfArts, possibleAssemblyNumOfArts);
|
||||
}
|
||||
|
||||
void CPlayerInterface::artifactAssembled(const ArtifactLocation &al)
|
||||
{
|
||||
EVENT_HANDLER_CALLED_BY_CLIENT;
|
||||
adventureInt->onHeroChanged(cb->getHero(al.artHolder));
|
||||
|
||||
for(auto artWin : GH.windows().findWindows<CWindowWithArtifacts>())
|
||||
artWin->artifactAssembled(al);
|
||||
artifactController->artifactAssembled();
|
||||
}
|
||||
|
||||
void CPlayerInterface::artifactDisassembled(const ArtifactLocation &al)
|
||||
{
|
||||
EVENT_HANDLER_CALLED_BY_CLIENT;
|
||||
adventureInt->onHeroChanged(cb->getHero(al.artHolder));
|
||||
|
||||
for(auto artWin : GH.windows().findWindows<CWindowWithArtifacts>())
|
||||
artWin->artifactDisassembled(al);
|
||||
artifactController->artifactDisassembled();
|
||||
}
|
||||
|
||||
void CPlayerInterface::waitForAllDialogs()
|
||||
|
@ -9,6 +9,8 @@
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include "ArtifactsUIController.h"
|
||||
|
||||
#include "../lib/FunctionList.h"
|
||||
#include "../lib/CGameInterface.h"
|
||||
#include "gui/CIntObject.h"
|
||||
@ -16,9 +18,7 @@
|
||||
VCMI_LIB_NAMESPACE_BEGIN
|
||||
|
||||
class Artifact;
|
||||
|
||||
struct TryMoveHero;
|
||||
class CGHeroInstance;
|
||||
class CStack;
|
||||
class CCreature;
|
||||
struct CGPath;
|
||||
@ -59,14 +59,13 @@ namespace boost
|
||||
class CPlayerInterface : public CGameInterface, public IUpdateable
|
||||
{
|
||||
bool ignoreEvents;
|
||||
size_t numOfMovedArts;
|
||||
|
||||
int autosaveCount;
|
||||
|
||||
std::list<std::shared_ptr<CInfoWindow>> dialogs; //queue of dialogs awaiting to be shown (not currently shown!)
|
||||
|
||||
std::unique_ptr<HeroMovementController> movementController;
|
||||
public: // TODO: make private
|
||||
std::unique_ptr<ArtifactsUIController> artifactController;
|
||||
std::shared_ptr<Environment> env;
|
||||
|
||||
std::unique_ptr<PlayerLocalState> localState;
|
||||
@ -98,7 +97,7 @@ protected: // Call-ins from server, should not be called directly, but only via
|
||||
void artifactPut(const ArtifactLocation &al) override;
|
||||
void artifactRemoved(const ArtifactLocation &al) override;
|
||||
void artifactMoved(const ArtifactLocation &src, const ArtifactLocation &dst) override;
|
||||
void bulkArtMovementStart(size_t numOfArts) override;
|
||||
void bulkArtMovementStart(size_t totalNumOfArts, size_t possibleAssemblyNumOfArts) override;
|
||||
void artifactAssembled(const ArtifactLocation &al) override;
|
||||
void askToAssembleArtifact(const ArtifactLocation & dst) override;
|
||||
void artifactDisassembled(const ArtifactLocation &al) override;
|
||||
@ -180,7 +179,6 @@ public: // public interface for use by client via LOCPLINT access
|
||||
void showShipyardDialog(const IShipyard *obj) override; //obj may be town or shipyard;
|
||||
|
||||
void showHeroExchange(ObjectInstanceID hero1, ObjectInstanceID hero2);
|
||||
void showArtifactAssemblyDialog(const Artifact * artifact, const Artifact * assembledArtifact, CFunctionList<void()> onYes);
|
||||
void waitWhileDialog();
|
||||
void waitForAllDialogs();
|
||||
void openTownWindow(const CGTownInstance * town); //shows townscreen
|
||||
|
@ -48,7 +48,6 @@ public:
|
||||
void visitBulkSmartRebalanceStacks(BulkSmartRebalanceStacks & pack) override;
|
||||
void visitPutArtifact(PutArtifact & pack) override;
|
||||
void visitEraseArtifact(EraseArtifact & pack) override;
|
||||
void visitMoveArtifact(MoveArtifact & pack) override;
|
||||
void visitBulkMoveArtifacts(BulkMoveArtifacts & pack) override;
|
||||
void visitAssembledArtifact(AssembledArtifact & pack) override;
|
||||
void visitDisassembledArtifact(DisassembledArtifact & pack) override;
|
||||
|
@ -296,45 +296,45 @@ void ApplyClientNetPackVisitor::visitEraseArtifact(EraseArtifact & pack)
|
||||
callInterfaceIfPresent(cl, cl.getOwner(pack.al.artHolder), &IGameEventsReceiver::artifactRemoved, pack.al);
|
||||
}
|
||||
|
||||
void ApplyClientNetPackVisitor::visitMoveArtifact(MoveArtifact & pack)
|
||||
{
|
||||
auto moveArtifact = [this, &pack](PlayerColor player) -> void
|
||||
{
|
||||
callInterfaceIfPresent(cl, player, &IGameEventsReceiver::artifactMoved, pack.src, pack.dst);
|
||||
if(pack.askAssemble)
|
||||
callInterfaceIfPresent(cl, player, &IGameEventsReceiver::askToAssembleArtifact, pack.dst);
|
||||
};
|
||||
|
||||
moveArtifact(pack.interfaceOwner);
|
||||
if(pack.interfaceOwner != cl.getOwner(pack.dst.artHolder))
|
||||
moveArtifact(cl.getOwner(pack.dst.artHolder));
|
||||
|
||||
cl.invalidatePaths(); // hero might have equipped/unequipped Angel Wings
|
||||
}
|
||||
|
||||
void ApplyClientNetPackVisitor::visitBulkMoveArtifacts(BulkMoveArtifacts & pack)
|
||||
{
|
||||
auto applyMove = [this, &pack](std::vector<BulkMoveArtifacts::LinkedSlots> & artsPack) -> void
|
||||
const auto dstOwner = cl.getOwner(pack.dstArtHolder);
|
||||
const auto applyMove = [this, &pack, dstOwner](std::vector<BulkMoveArtifacts::LinkedSlots> & artsPack)
|
||||
{
|
||||
for(auto & slotToMove : artsPack)
|
||||
for(const auto & slotToMove : artsPack)
|
||||
{
|
||||
auto srcLoc = ArtifactLocation(pack.srcArtHolder, slotToMove.srcPos);
|
||||
auto dstLoc = ArtifactLocation(pack.dstArtHolder, slotToMove.dstPos);
|
||||
MoveArtifact ma(pack.interfaceOwner, srcLoc, dstLoc, pack.askAssemble);
|
||||
visitMoveArtifact(ma);
|
||||
const auto srcLoc = ArtifactLocation(pack.srcArtHolder, slotToMove.srcPos);
|
||||
const auto dstLoc = ArtifactLocation(pack.dstArtHolder, slotToMove.dstPos);
|
||||
|
||||
callInterfaceIfPresent(cl, pack.interfaceOwner, &IGameEventsReceiver::artifactMoved, srcLoc, dstLoc);
|
||||
if(slotToMove.askAssemble)
|
||||
callInterfaceIfPresent(cl, pack.interfaceOwner, &IGameEventsReceiver::askToAssembleArtifact, dstLoc);
|
||||
if(pack.interfaceOwner != dstOwner)
|
||||
callInterfaceIfPresent(cl, dstOwner, &IGameEventsReceiver::artifactMoved, srcLoc, dstLoc);
|
||||
|
||||
cl.invalidatePaths(); // hero might have equipped/unequipped Angel Wings
|
||||
}
|
||||
};
|
||||
|
||||
auto srcOwner = cl.getOwner(pack.srcArtHolder);
|
||||
auto dstOwner = cl.getOwner(pack.dstArtHolder);
|
||||
size_t possibleAssemblyNumOfArts = 0;
|
||||
const auto calcPossibleAssemblyNumOfArts = [&possibleAssemblyNumOfArts](const auto & slotToMove)
|
||||
{
|
||||
if(slotToMove.askAssemble)
|
||||
possibleAssemblyNumOfArts++;
|
||||
};
|
||||
std::for_each(pack.artsPack0.cbegin(), pack.artsPack0.cend(), calcPossibleAssemblyNumOfArts);
|
||||
std::for_each(pack.artsPack1.cbegin(), pack.artsPack1.cend(), calcPossibleAssemblyNumOfArts);
|
||||
|
||||
|
||||
// Begin a session of bulk movement of arts. It is not necessary but useful for the client optimization.
|
||||
callInterfaceIfPresent(cl, srcOwner, &IGameEventsReceiver::bulkArtMovementStart, pack.artsPack0.size() + pack.artsPack1.size());
|
||||
if(srcOwner != dstOwner)
|
||||
callInterfaceIfPresent(cl, dstOwner, &IGameEventsReceiver::bulkArtMovementStart, pack.artsPack0.size() + pack.artsPack1.size());
|
||||
callInterfaceIfPresent(cl, pack.interfaceOwner, &IGameEventsReceiver::bulkArtMovementStart,
|
||||
pack.artsPack0.size() + pack.artsPack1.size(), possibleAssemblyNumOfArts);
|
||||
if(pack.interfaceOwner != dstOwner)
|
||||
callInterfaceIfPresent(cl, dstOwner, &IGameEventsReceiver::bulkArtMovementStart,
|
||||
pack.artsPack0.size() + pack.artsPack1.size(), possibleAssemblyNumOfArts);
|
||||
|
||||
applyMove(pack.artsPack0);
|
||||
if(pack.swap)
|
||||
if(!pack.artsPack1.empty())
|
||||
applyMove(pack.artsPack1);
|
||||
}
|
||||
|
||||
|
@ -245,59 +245,3 @@ void CArtPlace::addCombinedArtInfo(const std::map<const ArtifactID, std::vector<
|
||||
text += info.toString();
|
||||
}
|
||||
}
|
||||
|
||||
bool ArtifactUtilsClient::askToAssemble(const CGHeroInstance * hero, const ArtifactPosition & slot)
|
||||
{
|
||||
assert(hero);
|
||||
const auto art = hero->getArt(slot);
|
||||
assert(art);
|
||||
|
||||
if(hero->tempOwner != LOCPLINT->playerID)
|
||||
return false;
|
||||
|
||||
auto assemblyPossibilities = ArtifactUtils::assemblyPossibilities(hero, art->getTypeId());
|
||||
if(!assemblyPossibilities.empty())
|
||||
{
|
||||
auto askThread = new boost::thread([hero, art, slot, assemblyPossibilities]() -> void
|
||||
{
|
||||
boost::mutex::scoped_lock interfaceLock(GH.interfaceMutex);
|
||||
for(const auto combinedArt : assemblyPossibilities)
|
||||
{
|
||||
bool assembleConfirmed = false;
|
||||
CFunctionList<void()> onYesHandlers([&assembleConfirmed]() -> void {assembleConfirmed = true; });
|
||||
onYesHandlers += std::bind(&CCallback::assembleArtifacts, LOCPLINT->cb.get(), hero, slot, true, combinedArt->getId());
|
||||
|
||||
LOCPLINT->showArtifactAssemblyDialog(art->artType, combinedArt, onYesHandlers);
|
||||
LOCPLINT->waitWhileDialog();
|
||||
if(assembleConfirmed)
|
||||
break;
|
||||
}
|
||||
});
|
||||
askThread->detach();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool ArtifactUtilsClient::askToDisassemble(const CGHeroInstance * hero, const ArtifactPosition & slot)
|
||||
{
|
||||
assert(hero);
|
||||
const auto art = hero->getArt(slot);
|
||||
assert(art);
|
||||
|
||||
if(hero->tempOwner != LOCPLINT->playerID)
|
||||
return false;
|
||||
|
||||
if(art->isCombined())
|
||||
{
|
||||
if(ArtifactUtils::isSlotBackpack(slot) && !ArtifactUtils::isBackpackFreeSlots(hero, art->artType->getConstituents().size() - 1))
|
||||
return false;
|
||||
|
||||
LOCPLINT->showArtifactAssemblyDialog(
|
||||
art->artType,
|
||||
nullptr,
|
||||
std::bind(&CCallback::assembleArtifacts, LOCPLINT->cb.get(), hero, slot, false, ArtifactID()));
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
@ -59,9 +59,3 @@ public:
|
||||
void clickPressed(const Point & cursorPosition) override;
|
||||
void showPopupWindow(const Point & cursorPosition) override;
|
||||
};
|
||||
|
||||
namespace ArtifactUtilsClient
|
||||
{
|
||||
bool askToAssemble(const CGHeroInstance * hero, const ArtifactPosition & slot);
|
||||
bool askToDisassemble(const CGHeroInstance * hero, const ArtifactPosition & slot);
|
||||
}
|
||||
|
@ -176,9 +176,9 @@ void CArtifactsOfHeroQuickBackpack::setHero(const CGHeroInstance * hero)
|
||||
initAOHbackpack(requiredSlots, false);
|
||||
auto artPlace = backpack.begin();
|
||||
for(auto & art : filteredArts)
|
||||
setSlotData(*artPlace++, curHero->getSlotByInstance(art.second));
|
||||
setSlotData(*artPlace++, curHero->getArtPos(art.second));
|
||||
for(auto & art : filteredScrolls)
|
||||
setSlotData(*artPlace++, curHero->getSlotByInstance(art.second));
|
||||
setSlotData(*artPlace++, curHero->getArtPos(art.second));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -146,7 +146,7 @@ void CAltarArtifacts::updateAltarSlots()
|
||||
for(auto & tradeSlot : tradeSlotsMapNewArts)
|
||||
{
|
||||
assert(tradeSlot.first->id == -1);
|
||||
assert(altarArtifacts->getSlotByInstance(tradeSlot.second) != ArtifactPosition::PRE_FIRST);
|
||||
assert(altarArtifacts->getArtPos(tradeSlot.second) != ArtifactPosition::PRE_FIRST);
|
||||
tradeSlot.first->setID(tradeSlot.second->getTypeId().num);
|
||||
tradeSlot.first->subtitle->setText(std::to_string(calcExpCost(tradeSlot.second->getTypeId())));
|
||||
}
|
||||
@ -221,7 +221,7 @@ void CAltarArtifacts::onSlotClickPressed(const std::shared_ptr<CTradeableItem> &
|
||||
else if(altarSlot->id != -1)
|
||||
{
|
||||
assert(tradeSlotsMap.at(altarSlot));
|
||||
const auto slot = altarArtifacts->getSlotByInstance(tradeSlotsMap.at(altarSlot));
|
||||
const auto slot = altarArtifacts->getArtPos(tradeSlotsMap.at(altarSlot));
|
||||
assert(slot != ArtifactPosition::PRE_FIRST);
|
||||
LOCPLINT->cb->swapArtifacts(ArtifactLocation(heroArts->altarId, slot),
|
||||
ArtifactLocation(hero->id, GH.isKeyboardCtrlDown() ? ArtifactPosition::FIRST_AVAILABLE : ArtifactPosition::TRANSITION_POS));
|
||||
|
@ -117,9 +117,9 @@ void CWindowWithArtifacts::showArtifactAssembling(const CArtifactsOfHeroBase & a
|
||||
{
|
||||
if(artsInst.getArt(artPlace.slot))
|
||||
{
|
||||
if(ArtifactUtilsClient::askToDisassemble(artsInst.getHero(), artPlace.slot))
|
||||
if(LOCPLINT->artifactController->askToDisassemble(artsInst.getHero(), artPlace.slot))
|
||||
return;
|
||||
if(ArtifactUtilsClient::askToAssemble(artsInst.getHero(), artPlace.slot))
|
||||
if(LOCPLINT->artifactController->askToAssemble(artsInst.getHero(), artPlace.slot))
|
||||
return;
|
||||
if(artPlace.text.size())
|
||||
artPlace.LRClickableAreaWTextComp::showPopupWindow(cursorPosition);
|
||||
@ -166,14 +166,13 @@ void CWindowWithArtifacts::enableKeyboardShortcuts() const
|
||||
artSet->enableKeyboardShortcuts();
|
||||
}
|
||||
|
||||
void CWindowWithArtifacts::artifactRemoved(const ArtifactLocation & artLoc)
|
||||
{
|
||||
update();
|
||||
}
|
||||
|
||||
void CWindowWithArtifacts::artifactMoved(const ArtifactLocation & srcLoc, const ArtifactLocation & destLoc)
|
||||
void CWindowWithArtifacts::update()
|
||||
{
|
||||
for(const auto & artSet : artSets)
|
||||
{
|
||||
artSet->updateWornSlots();
|
||||
artSet->updateBackpackSlots();
|
||||
|
||||
if(const auto pickedArtInst = getPickedArtifact())
|
||||
{
|
||||
markPossibleSlots();
|
||||
@ -184,30 +183,12 @@ void CWindowWithArtifacts::artifactMoved(const ArtifactLocation & srcLoc, const
|
||||
artSet->unmarkSlots();
|
||||
CCS->curh->dragAndDropCursor(nullptr);
|
||||
}
|
||||
}
|
||||
|
||||
void CWindowWithArtifacts::artifactDisassembled(const ArtifactLocation & artLoc)
|
||||
{
|
||||
update();
|
||||
}
|
||||
|
||||
void CWindowWithArtifacts::artifactAssembled(const ArtifactLocation & artLoc)
|
||||
{
|
||||
markPossibleSlots();
|
||||
update();
|
||||
}
|
||||
|
||||
void CWindowWithArtifacts::update()
|
||||
{
|
||||
for(const auto & artSet : artSets)
|
||||
{
|
||||
artSet->updateWornSlots();
|
||||
artSet->updateBackpackSlots();
|
||||
|
||||
// Make sure the status bar is updated so it does not display old text
|
||||
if(auto artPlace = artSet->getArtPlace(GH.getCursorPosition()))
|
||||
artPlace->hover(true);
|
||||
}
|
||||
redraw();
|
||||
}
|
||||
|
||||
void CWindowWithArtifacts::markPossibleSlots() const
|
||||
|
@ -37,10 +37,6 @@ public:
|
||||
void deactivate() override;
|
||||
void enableKeyboardShortcuts() const;
|
||||
|
||||
virtual void artifactRemoved(const ArtifactLocation & artLoc);
|
||||
virtual void artifactMoved(const ArtifactLocation & srcLoc, const ArtifactLocation & destLoc);
|
||||
virtual void artifactDisassembled(const ArtifactLocation & artLoc);
|
||||
virtual void artifactAssembled(const ArtifactLocation & artLoc);
|
||||
virtual void update();
|
||||
|
||||
protected:
|
||||
|
@ -196,7 +196,7 @@ DLL_LINKAGE bool ArtifactUtils::isBackpackFreeSlots(const CArtifactSet * target,
|
||||
}
|
||||
|
||||
DLL_LINKAGE std::vector<const CArtifact*> ArtifactUtils::assemblyPossibilities(
|
||||
const CArtifactSet * artSet, const ArtifactID & aid)
|
||||
const CArtifactSet * artSet, const ArtifactID & aid, const bool onlyEquiped)
|
||||
{
|
||||
std::vector<const CArtifact*> arts;
|
||||
const auto * art = aid.toArtifact();
|
||||
@ -210,7 +210,7 @@ DLL_LINKAGE std::vector<const CArtifact*> ArtifactUtils::assemblyPossibilities(
|
||||
|
||||
for(const auto constituent : artifact->getConstituents()) //check if all constituents are available
|
||||
{
|
||||
if(!artSet->hasArt(constituent->getId(), false, false, false))
|
||||
if(!artSet->hasArt(constituent->getId(), onlyEquiped, false, false))
|
||||
{
|
||||
possible = false;
|
||||
break;
|
||||
|
@ -39,7 +39,7 @@ namespace ArtifactUtils
|
||||
DLL_LINKAGE bool isSlotBackpack(const ArtifactPosition & slot);
|
||||
DLL_LINKAGE bool isSlotEquipment(const ArtifactPosition & slot);
|
||||
DLL_LINKAGE bool isBackpackFreeSlots(const CArtifactSet * target, const size_t reqSlots = 1);
|
||||
DLL_LINKAGE std::vector<const CArtifact*> assemblyPossibilities(const CArtifactSet * artSet, const ArtifactID & aid);
|
||||
DLL_LINKAGE std::vector<const CArtifact*> assemblyPossibilities(const CArtifactSet * artSet, const ArtifactID & aid, const bool onlyEquiped = false);
|
||||
DLL_LINKAGE CArtifactInstance * createScroll(const SpellID & sid);
|
||||
DLL_LINKAGE CArtifactInstance * createNewArtifactInstance(const CArtifact * art);
|
||||
DLL_LINKAGE CArtifactInstance * createNewArtifactInstance(const ArtifactID & aid);
|
||||
|
@ -741,19 +741,6 @@ std::vector<ArtifactPosition> CArtifactSet::getBackpackArtPositions(const Artifa
|
||||
return result;
|
||||
}
|
||||
|
||||
ArtifactPosition CArtifactSet::getArtPos(const CArtifactInstance *art) const
|
||||
{
|
||||
for(auto i : artifactsWorn)
|
||||
if(i.second.artifact == art)
|
||||
return i.first;
|
||||
|
||||
for(int i = 0; i < artifactsInBackpack.size(); i++)
|
||||
if(artifactsInBackpack[i].artifact == art)
|
||||
return ArtifactPosition::BACKPACK_START + i;
|
||||
|
||||
return ArtifactPosition::PRE_FIRST;
|
||||
}
|
||||
|
||||
const CArtifactInstance * CArtifactSet::getArtByInstanceId(const ArtifactInstanceID & artInstId) const
|
||||
{
|
||||
for(auto i : artifactsWorn)
|
||||
@ -767,7 +754,7 @@ const CArtifactInstance * CArtifactSet::getArtByInstanceId(const ArtifactInstanc
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
const ArtifactPosition CArtifactSet::getSlotByInstance(const CArtifactInstance * artInst) const
|
||||
const ArtifactPosition CArtifactSet::getArtPos(const CArtifactInstance * artInst) const
|
||||
{
|
||||
if(artInst)
|
||||
{
|
||||
@ -1079,8 +1066,8 @@ void CArtifactSet::serializeJsonSlot(JsonSerializeFormat & handler, const Artifa
|
||||
}
|
||||
}
|
||||
|
||||
CArtifactFittingSet::CArtifactFittingSet(ArtBearer::ArtBearer Bearer):
|
||||
Bearer(Bearer)
|
||||
CArtifactFittingSet::CArtifactFittingSet(ArtBearer::ArtBearer bearer)
|
||||
: bearer(bearer)
|
||||
{
|
||||
}
|
||||
|
||||
@ -1094,7 +1081,7 @@ CArtifactFittingSet::CArtifactFittingSet(const CArtifactSet & artSet)
|
||||
|
||||
ArtBearer::ArtBearer CArtifactFittingSet::bearerType() const
|
||||
{
|
||||
return this->Bearer;
|
||||
return this->bearer;
|
||||
}
|
||||
|
||||
VCMI_LIB_NAMESPACE_END
|
||||
|
@ -207,11 +207,10 @@ public:
|
||||
/// Looks for equipped artifact with given ID and returns its slot ID or -1 if none
|
||||
/// (if more than one such artifact lower ID is returned)
|
||||
ArtifactPosition getArtPos(const ArtifactID & aid, bool onlyWorn = true, bool allowLocked = true) const;
|
||||
ArtifactPosition getArtPos(const CArtifactInstance *art) const;
|
||||
const ArtifactPosition getArtPos(const CArtifactInstance * art) const;
|
||||
std::vector<ArtifactPosition> getAllArtPositions(const ArtifactID & aid, bool onlyWorn, bool allowLocked, bool getAll) const;
|
||||
std::vector<ArtifactPosition> getBackpackArtPositions(const ArtifactID & aid) const;
|
||||
const CArtifactInstance * getArtByInstanceId(const ArtifactInstanceID & artInstId) const;
|
||||
const ArtifactPosition getSlotByInstance(const CArtifactInstance * artInst) const;
|
||||
/// Search for constituents of assemblies in backpack which do not have an ArtifactPosition
|
||||
const CArtifactInstance * getHiddenArt(const ArtifactID & aid) const;
|
||||
const CArtifactInstance * getAssemblyByConstituent(const ArtifactID & aid) const;
|
||||
@ -255,7 +254,7 @@ public:
|
||||
ArtBearer::ArtBearer bearerType() const override;
|
||||
|
||||
protected:
|
||||
ArtBearer::ArtBearer Bearer;
|
||||
ArtBearer::ArtBearer bearer;
|
||||
};
|
||||
|
||||
VCMI_LIB_NAMESPACE_END
|
||||
|
@ -284,6 +284,10 @@ CArtifactSet * CNonConstInfoCallback::getArtSet(const ArtifactLocation & loc)
|
||||
return hero;
|
||||
}
|
||||
}
|
||||
else if(auto army = getArmyInstance(loc.artHolder))
|
||||
{
|
||||
return army->getStackPtr(loc.creature.value());
|
||||
}
|
||||
else if(auto market = dynamic_cast<CGArtifactsAltar*>(getObjInstance(loc.artHolder)))
|
||||
{
|
||||
return market;
|
||||
|
@ -90,7 +90,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 bulkArtMovementStart(size_t numOfArts) {};
|
||||
virtual void bulkArtMovementStart(size_t totalNumOfArts, size_t possibleAssemblyNumOfArts) {};
|
||||
virtual void askToAssembleArtifact(const ArtifactLocation & dst) {};
|
||||
|
||||
virtual void heroVisit(const CGHeroInstance *visitor, const CGObjectInstance *visitedObj, bool start){};
|
||||
|
@ -49,7 +49,7 @@ private:
|
||||
REPLACE_TEXTID_STRING,
|
||||
REPLACE_NUMBER,
|
||||
REPLACE_POSITIVE_NUMBER,
|
||||
APPEND_EOL
|
||||
APPEND_EOL
|
||||
};
|
||||
|
||||
std::vector<EMessage> message;
|
||||
|
@ -54,6 +54,7 @@ namespace GameConstants
|
||||
constexpr int ALTAR_ARTIFACTS_SLOTS = 22;
|
||||
constexpr int TOURNAMENT_RULES_DD_MAP_TILES_THRESHOLD = 144*144*2; //map tiles count threshold for 2 dimension door casts with tournament rules
|
||||
constexpr int KINGDOM_WINDOW_HEROES_SLOTS = 4;
|
||||
constexpr int INFO_WINDOW_ARTIFACTS_MAX_ITEMS = 14;
|
||||
}
|
||||
|
||||
VCMI_LIB_NAMESPACE_END
|
||||
|
@ -37,6 +37,12 @@ struct ArtifactLocation
|
||||
, creature(creatureSlot)
|
||||
{
|
||||
}
|
||||
ArtifactLocation(const ObjectInstanceID id, const std::optional<SlotID> creatureSlot, const ArtifactPosition & slot)
|
||||
: artHolder(id)
|
||||
, slot(slot)
|
||||
, creature(creatureSlot)
|
||||
{
|
||||
}
|
||||
|
||||
template <typename Handler> void serialize(Handler & h)
|
||||
{
|
||||
|
@ -78,7 +78,6 @@ public:
|
||||
virtual void visitBulkSmartRebalanceStacks(BulkSmartRebalanceStacks & pack) {}
|
||||
virtual void visitPutArtifact(PutArtifact & pack) {}
|
||||
virtual void visitEraseArtifact(EraseArtifact & pack) {}
|
||||
virtual void visitMoveArtifact(MoveArtifact & pack) {}
|
||||
virtual void visitBulkMoveArtifacts(BulkMoveArtifacts & pack) {}
|
||||
virtual void visitAssembledArtifact(AssembledArtifact & pack) {}
|
||||
virtual void visitDisassembledArtifact(DisassembledArtifact & pack) {}
|
||||
|
@ -338,11 +338,6 @@ void EraseArtifact::visitTyped(ICPackVisitor & visitor)
|
||||
visitor.visitEraseArtifact(*this);
|
||||
}
|
||||
|
||||
void MoveArtifact::visitTyped(ICPackVisitor & visitor)
|
||||
{
|
||||
visitor.visitMoveArtifact(*this);
|
||||
}
|
||||
|
||||
void BulkMoveArtifacts::visitTyped(ICPackVisitor & visitor)
|
||||
{
|
||||
visitor.visitBulkMoveArtifacts(*this);
|
||||
@ -1794,17 +1789,6 @@ void EraseArtifact::applyGs(CGameState *gs)
|
||||
art->removeFrom(*artSet, al.slot);
|
||||
}
|
||||
|
||||
void MoveArtifact::applyGs(CGameState * gs)
|
||||
{
|
||||
auto srcHero = gs->getArtSet(src);
|
||||
auto dstHero = gs->getArtSet(dst);
|
||||
assert(srcHero);
|
||||
assert(dstHero);
|
||||
auto art = srcHero->getArt(src.slot);
|
||||
assert(art && art->canBePutAt(dstHero, dst.slot));
|
||||
art->move(*srcHero, src.slot, *dstHero, dst.slot);
|
||||
}
|
||||
|
||||
void BulkMoveArtifacts::applyGs(CGameState * gs)
|
||||
{
|
||||
const auto bulkArtsRemove = [](std::vector<LinkedSlots> & artsPack, CArtifactSet & artSet)
|
||||
@ -1861,7 +1845,7 @@ void AssembledArtifact::applyGs(CGameState *gs)
|
||||
return art->getId() == builtArt->getId();
|
||||
}));
|
||||
|
||||
const auto transformedArtSlot = hero->getSlotByInstance(transformedArt);
|
||||
const auto transformedArtSlot = hero->getArtPos(transformedArt);
|
||||
auto * combinedArt = new CArtifactInstance(builtArt);
|
||||
gs->map->addNewArtifactInstance(combinedArt);
|
||||
|
||||
|
@ -1025,47 +1025,26 @@ struct DLL_LINKAGE EraseArtifact : CArtifactOperationPack
|
||||
}
|
||||
};
|
||||
|
||||
struct DLL_LINKAGE MoveArtifact : CArtifactOperationPack
|
||||
{
|
||||
MoveArtifact() = default;
|
||||
MoveArtifact(const PlayerColor & interfaceOwner, const ArtifactLocation & src, const ArtifactLocation & dst, bool askAssemble = true)
|
||||
: interfaceOwner(interfaceOwner), src(src), dst(dst), askAssemble(askAssemble)
|
||||
{
|
||||
}
|
||||
PlayerColor interfaceOwner;
|
||||
ArtifactLocation src;
|
||||
ArtifactLocation dst;
|
||||
bool askAssemble = true;
|
||||
|
||||
void applyGs(CGameState * gs);
|
||||
void visitTyped(ICPackVisitor & visitor) override;
|
||||
|
||||
template <typename Handler> void serialize(Handler & h)
|
||||
{
|
||||
h & interfaceOwner;
|
||||
h & src;
|
||||
h & dst;
|
||||
h & askAssemble;
|
||||
}
|
||||
};
|
||||
|
||||
struct DLL_LINKAGE BulkMoveArtifacts : CArtifactOperationPack
|
||||
{
|
||||
struct LinkedSlots
|
||||
{
|
||||
ArtifactPosition srcPos;
|
||||
ArtifactPosition dstPos;
|
||||
bool askAssemble;
|
||||
|
||||
LinkedSlots() = default;
|
||||
LinkedSlots(const ArtifactPosition & srcPos, const ArtifactPosition & dstPos)
|
||||
LinkedSlots(const ArtifactPosition & srcPos, const ArtifactPosition & dstPos, bool askAssemble = false)
|
||||
: srcPos(srcPos)
|
||||
, dstPos(dstPos)
|
||||
, askAssemble(askAssemble)
|
||||
{
|
||||
}
|
||||
template <typename Handler> void serialize(Handler & h)
|
||||
{
|
||||
h & srcPos;
|
||||
h & dstPos;
|
||||
h & askAssemble;
|
||||
}
|
||||
};
|
||||
|
||||
@ -1079,8 +1058,6 @@ struct DLL_LINKAGE BulkMoveArtifacts : CArtifactOperationPack
|
||||
: interfaceOwner(PlayerColor::NEUTRAL)
|
||||
, srcArtHolder(ObjectInstanceID::NONE)
|
||||
, dstArtHolder(ObjectInstanceID::NONE)
|
||||
, swap(false)
|
||||
, askAssemble(false)
|
||||
, srcCreature(std::nullopt)
|
||||
, dstCreature(std::nullopt)
|
||||
{
|
||||
@ -1089,8 +1066,6 @@ struct DLL_LINKAGE BulkMoveArtifacts : CArtifactOperationPack
|
||||
: interfaceOwner(interfaceOwner)
|
||||
, srcArtHolder(srcArtHolder)
|
||||
, dstArtHolder(dstArtHolder)
|
||||
, swap(swap)
|
||||
, askAssemble(false)
|
||||
, srcCreature(std::nullopt)
|
||||
, dstCreature(std::nullopt)
|
||||
{
|
||||
@ -1100,8 +1075,6 @@ struct DLL_LINKAGE BulkMoveArtifacts : CArtifactOperationPack
|
||||
|
||||
std::vector<LinkedSlots> artsPack0;
|
||||
std::vector<LinkedSlots> artsPack1;
|
||||
bool swap;
|
||||
bool askAssemble;
|
||||
|
||||
void visitTyped(ICPackVisitor & visitor) override;
|
||||
|
||||
@ -1114,8 +1087,6 @@ struct DLL_LINKAGE BulkMoveArtifacts : CArtifactOperationPack
|
||||
h & dstArtHolder;
|
||||
h & srcCreature;
|
||||
h & dstCreature;
|
||||
h & swap;
|
||||
h & askAssemble;
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -112,7 +112,6 @@ void registerTypesClientPacks(Serializer &s)
|
||||
s.template registerType<CPackForClient, CArtifactOperationPack>();
|
||||
s.template registerType<CArtifactOperationPack, PutArtifact>();
|
||||
s.template registerType<CArtifactOperationPack, EraseArtifact>();
|
||||
s.template registerType<CArtifactOperationPack, MoveArtifact>();
|
||||
s.template registerType<CArtifactOperationPack, AssembledArtifact>();
|
||||
s.template registerType<CArtifactOperationPack, DisassembledArtifact>();
|
||||
s.template registerType<CArtifactOperationPack, BulkMoveArtifacts>();
|
||||
|
@ -2779,7 +2779,6 @@ bool CGameHandler::moveArtifact(const PlayerColor & player, const ArtifactLocati
|
||||
// Previous artifact must be swapped
|
||||
COMPLAIN_RET_FALSE_IF(!dstArtifact->canBePutAt(srcArtSet, src.slot, true), "Cannot swap artifacts!");
|
||||
ma.artsPack1.push_back(BulkMoveArtifacts::LinkedSlots(dstSlot, src.slot));
|
||||
ma.swap = true;
|
||||
}
|
||||
|
||||
auto hero = getHero(dst.artHolder);
|
||||
@ -2788,7 +2787,7 @@ bool CGameHandler::moveArtifact(const PlayerColor & player, const ArtifactLocati
|
||||
|
||||
ma.artsPack0.push_back(BulkMoveArtifacts::LinkedSlots(src.slot, dstSlot));
|
||||
if(src.artHolder != dst.artHolder)
|
||||
ma.askAssemble = true;
|
||||
ma.artsPack0.back().askAssemble = true;
|
||||
sendAndApply(&ma);
|
||||
return true;
|
||||
}
|
||||
@ -2896,7 +2895,7 @@ bool CGameHandler::bulkMoveArtifacts(const PlayerColor & player, ObjectInstanceI
|
||||
|
||||
bool CGameHandler::scrollBackpackArtifacts(const PlayerColor & player, const ObjectInstanceID heroID, bool left)
|
||||
{
|
||||
auto artSet = getArtSet(heroID);
|
||||
const auto artSet = getArtSet(heroID);
|
||||
COMPLAIN_RET_FALSE_IF(artSet == nullptr, "scrollBackpackArtifacts: wrong hero's ID");
|
||||
|
||||
BulkMoveArtifacts bma(player, heroID, heroID, false);
|
||||
@ -2961,7 +2960,7 @@ bool CGameHandler::switchArtifactsCostume(const PlayerColor & player, const Obje
|
||||
{
|
||||
bma.artsPack0.emplace_back(BulkMoveArtifacts::LinkedSlots
|
||||
{
|
||||
artSet->getSlotByInstance(artFittingSet.getArt(availableArts.front())),
|
||||
artSet->getArtPos(artFittingSet.getArt(availableArts.front())),
|
||||
artPos.first
|
||||
});
|
||||
artFittingSet.removeArtifact(availableArts.front());
|
||||
@ -3926,7 +3925,7 @@ bool CGameHandler::sacrificeArtifact(const IMarket * m, const CGHeroInstance * h
|
||||
int expToGive;
|
||||
m->getOffer(art->getTypeId(), 0, dmp, expToGive, EMarketMode::ARTIFACT_EXP);
|
||||
expSum += expToGive;
|
||||
removeArtifact(ArtifactLocation(altarObj->id, altarObj->getSlotByInstance(art)));
|
||||
removeArtifact(ArtifactLocation(altarObj->id, altarObj->getArtPos(art)));
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -323,176 +323,9 @@ void BattleResultProcessor::endBattleConfirm(const CBattleInfoCallback & battle)
|
||||
CasualtiesAfterBattle cab1(battle, BattleSide::ATTACKER);
|
||||
CasualtiesAfterBattle cab2(battle, BattleSide::DEFENDER);
|
||||
|
||||
ChangeSpells cs; //for Eagle Eye
|
||||
|
||||
if(!finishingBattle->isDraw() && finishingBattle->winnerHero)
|
||||
{
|
||||
if (int eagleEyeLevel = finishingBattle->winnerHero->valOfBonuses(BonusType::LEARN_BATTLE_SPELL_LEVEL_LIMIT))
|
||||
{
|
||||
double eagleEyeChance = finishingBattle->winnerHero->valOfBonuses(BonusType::LEARN_BATTLE_SPELL_CHANCE);
|
||||
for(auto & spellId : battle.getBattle()->getUsedSpells(battle.otherSide(battleResult->winner)))
|
||||
{
|
||||
auto spell = spellId.toEntity(VLC->spells());
|
||||
if(spell && spell->getLevel() <= eagleEyeLevel && !finishingBattle->winnerHero->spellbookContainsSpell(spell->getId()) && gameHandler->getRandomGenerator().nextInt(99) < eagleEyeChance)
|
||||
cs.spells.insert(spell->getId());
|
||||
}
|
||||
}
|
||||
}
|
||||
std::vector<const CArtifactInstance *> arts; //display them in window
|
||||
|
||||
if(result == EBattleResult::NORMAL && !finishingBattle->isDraw() && finishingBattle->winnerHero)
|
||||
{
|
||||
auto sendMoveArtifact = [&](const CArtifactInstance *art, MoveArtifact *ma)
|
||||
{
|
||||
const auto slot = ArtifactUtils::getArtAnyPosition(finishingBattle->winnerHero, art->getTypeId());
|
||||
if(slot != ArtifactPosition::PRE_FIRST)
|
||||
{
|
||||
arts.push_back(art);
|
||||
ma->dst = ArtifactLocation(finishingBattle->winnerHero->id, slot);
|
||||
if(ArtifactUtils::isSlotBackpack(slot))
|
||||
ma->askAssemble = false;
|
||||
gameHandler->sendAndApply(ma);
|
||||
}
|
||||
};
|
||||
|
||||
if (finishingBattle->loserHero)
|
||||
{
|
||||
//TODO: wrap it into a function, somehow (std::variant -_-)
|
||||
auto artifactsWorn = finishingBattle->loserHero->artifactsWorn;
|
||||
for (auto artSlot : artifactsWorn)
|
||||
{
|
||||
MoveArtifact ma;
|
||||
ma.src = ArtifactLocation(finishingBattle->loserHero->id, artSlot.first);
|
||||
const CArtifactInstance * art = finishingBattle->loserHero->getArt(artSlot.first);
|
||||
if (art && !art->artType->isBig() &&
|
||||
art->artType->getId() != ArtifactID::SPELLBOOK)
|
||||
// don't move war machines or locked arts (spellbook)
|
||||
{
|
||||
sendMoveArtifact(art, &ma);
|
||||
}
|
||||
}
|
||||
for(int slotNumber = finishingBattle->loserHero->artifactsInBackpack.size() - 1; slotNumber >= 0; slotNumber--)
|
||||
{
|
||||
//we assume that no big artifacts can be found
|
||||
MoveArtifact ma;
|
||||
ma.src = ArtifactLocation(finishingBattle->loserHero->id,
|
||||
ArtifactPosition(ArtifactPosition::BACKPACK_START + slotNumber)); //backpack automatically shifts arts to beginning
|
||||
const CArtifactInstance * art = finishingBattle->loserHero->getArt(ArtifactPosition::BACKPACK_START + slotNumber);
|
||||
if (art->artType->getId() != ArtifactID::GRAIL) //grail may not be won
|
||||
{
|
||||
sendMoveArtifact(art, &ma);
|
||||
}
|
||||
}
|
||||
if (finishingBattle->loserHero->commander) //TODO: what if commanders belong to no hero?
|
||||
{
|
||||
artifactsWorn = finishingBattle->loserHero->commander->artifactsWorn;
|
||||
for (auto artSlot : artifactsWorn)
|
||||
{
|
||||
MoveArtifact ma;
|
||||
ma.src = ArtifactLocation(finishingBattle->loserHero->id, artSlot.first);
|
||||
ma.src.creature = finishingBattle->loserHero->findStack(finishingBattle->loserHero->commander);
|
||||
const auto art = finishingBattle->loserHero->commander->getArt(artSlot.first);
|
||||
if (art && !art->artType->isBig())
|
||||
{
|
||||
sendMoveArtifact(art, &ma);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
auto loser = battle.otherSide(battleResult->winner);
|
||||
|
||||
for (auto armySlot : battle.battleGetArmyObject(loser)->stacks)
|
||||
{
|
||||
auto artifactsWorn = armySlot.second->artifactsWorn;
|
||||
for(const auto & artSlot : artifactsWorn)
|
||||
{
|
||||
MoveArtifact ma;
|
||||
ma.src = ArtifactLocation(finishingBattle->loserHero->id, artSlot.first);
|
||||
ma.src.creature = finishingBattle->loserHero->findStack(finishingBattle->loserHero->commander);
|
||||
const auto art = finishingBattle->loserHero->commander->getArt(artSlot.first);
|
||||
if (art && !art->artType->isBig())
|
||||
{
|
||||
sendMoveArtifact(art, &ma);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (arts.size()) //display loot
|
||||
{
|
||||
InfoWindow iw;
|
||||
iw.player = finishingBattle->winnerHero->tempOwner;
|
||||
|
||||
iw.text.appendLocalString (EMetaText::GENERAL_TXT, 30); //You have captured enemy artifact
|
||||
|
||||
for (auto art : arts) //TODO; separate function to display loot for various objects?
|
||||
{
|
||||
if (art->artType->getId() == ArtifactID::SPELL_SCROLL)
|
||||
iw.components.emplace_back(ComponentType::SPELL_SCROLL, art->getScrollSpellID());
|
||||
else
|
||||
iw.components.emplace_back(ComponentType::ARTIFACT, art->artType->getId());
|
||||
|
||||
if (iw.components.size() >= 14)
|
||||
{
|
||||
gameHandler->sendAndApply(&iw);
|
||||
iw.components.clear();
|
||||
}
|
||||
}
|
||||
if (iw.components.size())
|
||||
{
|
||||
gameHandler->sendAndApply(&iw);
|
||||
}
|
||||
}
|
||||
//Eagle Eye secondary skill handling
|
||||
if (!cs.spells.empty())
|
||||
{
|
||||
cs.learn = 1;
|
||||
cs.hid = finishingBattle->winnerHero->id;
|
||||
|
||||
InfoWindow iw;
|
||||
iw.player = finishingBattle->winnerHero->tempOwner;
|
||||
iw.text.appendLocalString(EMetaText::GENERAL_TXT, 221); //Through eagle-eyed observation, %s is able to learn %s
|
||||
iw.text.replaceRawString(finishingBattle->winnerHero->getNameTranslated());
|
||||
|
||||
std::ostringstream names;
|
||||
for (int i = 0; i < cs.spells.size(); i++)
|
||||
{
|
||||
names << "%s";
|
||||
if (i < cs.spells.size() - 2)
|
||||
names << ", ";
|
||||
else if (i < cs.spells.size() - 1)
|
||||
names << "%s";
|
||||
}
|
||||
names << ".";
|
||||
|
||||
iw.text.replaceRawString(names.str());
|
||||
|
||||
auto it = cs.spells.begin();
|
||||
for (int i = 0; i < cs.spells.size(); i++, it++)
|
||||
{
|
||||
iw.text.replaceName(*it);
|
||||
if (i == cs.spells.size() - 2) //we just added pre-last name
|
||||
iw.text.replaceLocalString(EMetaText::GENERAL_TXT, 141); // " and "
|
||||
iw.components.emplace_back(ComponentType::SPELL, *it);
|
||||
}
|
||||
gameHandler->sendAndApply(&iw);
|
||||
gameHandler->sendAndApply(&cs);
|
||||
}
|
||||
cab1.updateArmy(gameHandler);
|
||||
cab2.updateArmy(gameHandler); //take casualties after battle is deleted
|
||||
|
||||
if(finishingBattle->loserHero) //remove beaten hero
|
||||
{
|
||||
RemoveObject ro(finishingBattle->loserHero->id, finishingBattle->victor);
|
||||
gameHandler->sendAndApply(&ro);
|
||||
}
|
||||
if(finishingBattle->isDraw() && finishingBattle->winnerHero) //for draw case both heroes should be removed
|
||||
{
|
||||
RemoveObject ro(finishingBattle->winnerHero->id, finishingBattle->loser);
|
||||
gameHandler->sendAndApply(&ro);
|
||||
}
|
||||
|
||||
if(battleResult->winner == BattleSide::DEFENDER
|
||||
&& finishingBattle->winnerHero
|
||||
&& finishingBattle->winnerHero->visitedTown
|
||||
@ -505,6 +338,160 @@ void BattleResultProcessor::endBattleConfirm(const CBattleInfoCallback & battle)
|
||||
if(!finishingBattle->isDraw() && battleResult->exp[finishingBattle->winnerSide] && finishingBattle->winnerHero)
|
||||
gameHandler->giveExperience(finishingBattle->winnerHero, battleResult->exp[finishingBattle->winnerSide]);
|
||||
|
||||
// Eagle Eye handling
|
||||
if(!finishingBattle->isDraw() && finishingBattle->winnerHero)
|
||||
{
|
||||
ChangeSpells spells;
|
||||
|
||||
if(auto eagleEyeLevel = finishingBattle->winnerHero->valOfBonuses(BonusType::LEARN_BATTLE_SPELL_LEVEL_LIMIT))
|
||||
{
|
||||
auto eagleEyeChance = finishingBattle->winnerHero->valOfBonuses(BonusType::LEARN_BATTLE_SPELL_CHANCE);
|
||||
for(auto & spellId : battle.getBattle()->getUsedSpells(battle.otherSide(battleResult->winner)))
|
||||
{
|
||||
auto spell = spellId.toEntity(VLC->spells());
|
||||
if(spell
|
||||
&& spell->getLevel() <= eagleEyeLevel
|
||||
&& !finishingBattle->winnerHero->spellbookContainsSpell(spell->getId())
|
||||
&& gameHandler->getRandomGenerator().nextInt(99) < eagleEyeChance)
|
||||
{
|
||||
spells.spells.insert(spell->getId());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(!spells.spells.empty())
|
||||
{
|
||||
spells.learn = 1;
|
||||
spells.hid = finishingBattle->winnerHero->id;
|
||||
|
||||
InfoWindow iw;
|
||||
iw.player = finishingBattle->winnerHero->tempOwner;
|
||||
iw.text.appendLocalString(EMetaText::GENERAL_TXT, 221); //Through eagle-eyed observation, %s is able to learn %s
|
||||
iw.text.replaceRawString(finishingBattle->winnerHero->getNameTranslated());
|
||||
|
||||
std::ostringstream names;
|
||||
for(int i = 0; i < spells.spells.size(); i++)
|
||||
{
|
||||
names << "%s";
|
||||
if(i < spells.spells.size() - 2)
|
||||
names << ", ";
|
||||
else if(i < spells.spells.size() - 1)
|
||||
names << "%s";
|
||||
}
|
||||
names << ".";
|
||||
|
||||
iw.text.replaceRawString(names.str());
|
||||
|
||||
auto it = spells.spells.begin();
|
||||
for(int i = 0; i < spells.spells.size(); i++, it++)
|
||||
{
|
||||
iw.text.replaceName(*it);
|
||||
if(i == spells.spells.size() - 2) //we just added pre-last name
|
||||
iw.text.replaceLocalString(EMetaText::GENERAL_TXT, 141); // " and "
|
||||
iw.components.emplace_back(ComponentType::SPELL, *it);
|
||||
}
|
||||
gameHandler->sendAndApply(&iw);
|
||||
gameHandler->sendAndApply(&spells);
|
||||
}
|
||||
}
|
||||
// Artifacts handling
|
||||
if(result == EBattleResult::NORMAL && !finishingBattle->isDraw() && finishingBattle->winnerHero)
|
||||
{
|
||||
std::vector<const CArtifactInstance*> arts; // display them in window
|
||||
CArtifactFittingSet artFittingSet(*finishingBattle->winnerHero);
|
||||
|
||||
const auto addArtifactToTransfer = [&artFittingSet, &arts](BulkMoveArtifacts & pack, const ArtifactPosition & srcSlot, const CArtifactInstance * art)
|
||||
{
|
||||
assert(art);
|
||||
const auto dstSlot = ArtifactUtils::getArtAnyPosition(&artFittingSet, art->getTypeId());
|
||||
if(dstSlot != ArtifactPosition::PRE_FIRST)
|
||||
{
|
||||
pack.artsPack0.emplace_back(BulkMoveArtifacts::LinkedSlots(srcSlot, dstSlot));
|
||||
if(ArtifactUtils::isSlotEquipment(dstSlot))
|
||||
pack.artsPack0.back().askAssemble = true;
|
||||
arts.emplace_back(art);
|
||||
artFittingSet.putArtifact(dstSlot, const_cast<CArtifactInstance*>(art));
|
||||
}
|
||||
};
|
||||
const auto sendArtifacts = [this](BulkMoveArtifacts & bma)
|
||||
{
|
||||
if(!bma.artsPack0.empty())
|
||||
gameHandler->sendAndApply(&bma);
|
||||
};
|
||||
|
||||
BulkMoveArtifacts packHero(finishingBattle->winnerHero->getOwner(), ObjectInstanceID::NONE, finishingBattle->winnerHero->id, false);
|
||||
if(finishingBattle->loserHero)
|
||||
{
|
||||
packHero.srcArtHolder = finishingBattle->loserHero->id;
|
||||
for(const auto & artSlot : finishingBattle->loserHero->artifactsWorn)
|
||||
{
|
||||
if(ArtifactUtils::isArtRemovable(artSlot))
|
||||
addArtifactToTransfer(packHero, artSlot.first, artSlot.second.getArt());
|
||||
}
|
||||
for(const auto & artSlot : finishingBattle->loserHero->artifactsInBackpack)
|
||||
{
|
||||
if(const auto art = artSlot.getArt(); art->getTypeId() != ArtifactID::GRAIL)
|
||||
addArtifactToTransfer(packHero, finishingBattle->loserHero->getArtPos(art), art);
|
||||
}
|
||||
|
||||
if(finishingBattle->loserHero->commander)
|
||||
{
|
||||
BulkMoveArtifacts packCommander(finishingBattle->winnerHero->getOwner(), finishingBattle->loserHero->id, finishingBattle->winnerHero->id, false);
|
||||
packCommander.srcCreature = finishingBattle->loserHero->findStack(finishingBattle->loserHero->commander);
|
||||
for(const auto & artSlot : finishingBattle->loserHero->commander->artifactsWorn)
|
||||
addArtifactToTransfer(packCommander, artSlot.first, artSlot.second.getArt());
|
||||
sendArtifacts(packCommander);
|
||||
}
|
||||
}
|
||||
auto armyObj = battle.battleGetArmyObject(battle.otherSide(battleResult->winner));
|
||||
for(const auto & armySlot : armyObj->stacks)
|
||||
{
|
||||
BulkMoveArtifacts packsArmy(finishingBattle->winnerHero->getOwner(), finishingBattle->loserHero->id, finishingBattle->winnerHero->id, false);
|
||||
packsArmy.srcArtHolder = armyObj->id;
|
||||
packsArmy.srcCreature = armySlot.first;
|
||||
for(const auto & artSlot : armySlot.second->artifactsWorn)
|
||||
addArtifactToTransfer(packsArmy, artSlot.first, armySlot.second->getArt(artSlot.first));
|
||||
sendArtifacts(packsArmy);
|
||||
}
|
||||
// Display loot
|
||||
if(!arts.empty())
|
||||
{
|
||||
InfoWindow iw;
|
||||
iw.player = finishingBattle->winnerHero->tempOwner;
|
||||
iw.text.appendLocalString(EMetaText::GENERAL_TXT, 30); //You have captured enemy artifact
|
||||
|
||||
for(const auto art : arts) //TODO; separate function to display loot for various objects?
|
||||
{
|
||||
if(art->isScroll())
|
||||
iw.components.emplace_back(ComponentType::SPELL_SCROLL, art->getScrollSpellID());
|
||||
else
|
||||
iw.components.emplace_back(ComponentType::ARTIFACT, art->getTypeId());
|
||||
|
||||
if(iw.components.size() >= GameConstants::INFO_WINDOW_ARTIFACTS_MAX_ITEMS)
|
||||
{
|
||||
gameHandler->sendAndApply(&iw);
|
||||
iw.components.clear();
|
||||
}
|
||||
}
|
||||
gameHandler->sendAndApply(&iw);
|
||||
}
|
||||
if(!packHero.artsPack0.empty())
|
||||
sendArtifacts(packHero);
|
||||
}
|
||||
|
||||
// Remove beaten hero
|
||||
if(finishingBattle->loserHero)
|
||||
{
|
||||
RemoveObject ro(finishingBattle->loserHero->id, finishingBattle->victor);
|
||||
gameHandler->sendAndApply(&ro);
|
||||
}
|
||||
// For draw case both heroes should be removed
|
||||
if(finishingBattle->isDraw() && finishingBattle->winnerHero)
|
||||
{
|
||||
RemoveObject ro(finishingBattle->winnerHero->id, finishingBattle->loser);
|
||||
gameHandler->sendAndApply(&ro);
|
||||
}
|
||||
|
||||
BattleResultAccepted raccepted;
|
||||
raccepted.battleID = battle.getBattle()->getBattleID();
|
||||
raccepted.heroResult[0].army = const_cast<CArmedInstance*>(battle.battleGetArmyObject(BattleSide::ATTACKER));
|
||||
@ -513,7 +500,7 @@ void BattleResultProcessor::endBattleConfirm(const CBattleInfoCallback & battle)
|
||||
raccepted.heroResult[1].hero = const_cast<CGHeroInstance*>(battle.battleGetFightingHero(BattleSide::DEFENDER));
|
||||
raccepted.heroResult[0].exp = battleResult->exp[0];
|
||||
raccepted.heroResult[1].exp = battleResult->exp[1];
|
||||
raccepted.winnerSide = finishingBattle->winnerSide;
|
||||
raccepted.winnerSide = finishingBattle->winnerSide;
|
||||
gameHandler->sendAndApply(&raccepted);
|
||||
|
||||
gameHandler->queries->popIfTop(battleQuery);
|
||||
|
Loading…
x
Reference in New Issue
Block a user