1
0
mirror of https://github.com/vcmi/vcmi.git synced 2024-12-12 10:03:53 +02:00
vcmi/client/windows/CWindowWithArtifacts.cpp

345 lines
9.6 KiB
C++
Raw Normal View History

2023-04-23 14:10:35 +02:00
/*
* CWindowWithArtifacts.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 "CWindowWithArtifacts.h"
#include "../gui/CGuiHandler.h"
#include "../gui/CursorHandler.h"
#include "../gui/WindowHandler.h"
2023-04-23 14:10:35 +02:00
2023-09-25 22:58:59 +02:00
#include "../render/IRenderHandler.h"
#include "../render/CAnimation.h"
#include "../render/IImage.h"
2024-04-23 15:21:45 +02:00
#include "../widgets/CComponent.h"
2023-04-23 14:10:35 +02:00
#include "../windows/CSpellWindow.h"
2023-12-17 16:30:19 +02:00
#include "../windows/CHeroBackpackWindow.h"
2023-04-23 14:10:35 +02:00
#include "../CPlayerInterface.h"
#include "../CGameInfo.h"
2023-05-17 15:52:16 +02:00
#include "../../lib/ArtifactUtils.h"
2023-04-23 14:10:35 +02:00
#include "../../lib/CGeneralTextHandler.h"
2024-05-08 13:16:16 +02:00
#include "../../lib/mapObjects/CGHeroInstance.h"
#include "../../lib/networkPacks/ArtifactLocation.h"
2023-09-25 23:02:16 +02:00
#include "../../lib/CConfigHandler.h"
2023-04-23 14:10:35 +02:00
2024-01-27 23:48:11 +02:00
#include "../../CCallback.h"
CWindowWithArtifacts::CWindowWithArtifacts(const std::vector<CArtifactsOfHeroPtr> * artSets)
2024-04-16 16:45:31 +02:00
{
if(artSets)
this->artSets.insert(this->artSets.end(), artSets->begin(), artSets->end());
}
void CWindowWithArtifacts::addSet(const std::shared_ptr<CArtifactsOfHeroBase> & newArtSet)
2023-09-18 21:58:08 +02:00
{
2024-04-23 19:26:21 +02:00
artSets.emplace_back(newArtSet);
2023-09-18 21:58:08 +02:00
}
2024-04-23 19:26:21 +02:00
void CWindowWithArtifacts::addCloseCallback(const CloseCallback & callback)
2023-07-16 20:16:12 +02:00
{
closeCallback = callback;
}
2023-04-23 14:10:35 +02:00
const CGHeroInstance * CWindowWithArtifacts::getHeroPickedArtifact()
{
const CGHeroInstance * hero = nullptr;
2024-05-01 20:18:36 +02:00
for(auto & artSet : artSets)
if(const auto pickedArt = artSet->getHero()->getArt(ArtifactPosition::TRANSITION_POS))
{
hero = artSet->getHero();
break;
}
return hero;
2023-04-23 14:10:35 +02:00
}
const CArtifactInstance * CWindowWithArtifacts::getPickedArtifact()
{
const CArtifactInstance * art = nullptr;
2024-05-01 20:18:36 +02:00
for(auto & artSet : artSets)
if(const auto pickedArt = artSet->getHero()->getArt(ArtifactPosition::TRANSITION_POS))
{
art = pickedArt;
break;
}
return art;
2023-04-23 14:10:35 +02:00
}
void CWindowWithArtifacts::clickPressedOnArtPlace(const CGHeroInstance * hero, const ArtifactPosition & slot,
2024-05-02 00:49:17 +02:00
bool allowExchange, bool altarTrading, bool closeWindow)
2023-04-23 14:10:35 +02:00
{
2024-05-01 20:18:36 +02:00
if(!LOCPLINT->makingTurn)
return;
if(hero == nullptr)
return;
2024-05-02 00:49:17 +02:00
if(const auto heroArtOwner = getHeroPickedArtifact())
{
if(allowExchange || hero->id == heroArtOwner->id)
putPickedArtifact(*hero, slot);
2024-05-02 00:49:17 +02:00
}
else if(auto art = hero->getArt(slot))
2024-05-02 00:49:17 +02:00
{
if(hero->getOwner() == LOCPLINT->playerID)
2023-04-23 14:10:35 +02:00
{
if(checkSpecialArts(*art, *hero, altarTrading))
onClickPressedCommonArtifact(*hero, slot, closeWindow);
2024-05-02 00:49:17 +02:00
}
else
{
for(const auto & artSlot : ArtifactUtils::unmovableSlots())
if(slot == artSlot)
2023-04-23 14:10:35 +02:00
{
2024-05-02 00:49:17 +02:00
LOCPLINT->showInfoDialog(CGI->generaltexth->allTexts[21]);
break;
2023-04-23 14:10:35 +02:00
}
2024-05-02 00:49:17 +02:00
}
}
2023-04-23 14:10:35 +02:00
}
2024-05-08 13:16:16 +02:00
void CWindowWithArtifacts::swapArtifactAndClose(const CArtifactsOfHeroBase & artsInst, const ArtifactPosition & slot,
const ArtifactLocation & dstLoc) const
2023-04-23 14:10:35 +02:00
{
2024-05-08 13:16:16 +02:00
LOCPLINT->cb->swapArtifacts(ArtifactLocation(artsInst.getHero()->id, slot), dstLoc);
2024-05-02 00:49:17 +02:00
if(closeCallback)
closeCallback();
}
2023-04-23 14:10:35 +02:00
2024-05-08 13:16:16 +02:00
void CWindowWithArtifacts::showArtifactAssembling(const CArtifactsOfHeroBase & artsInst, CArtPlace & artPlace,
const Point & cursorPosition) const
2024-05-02 00:49:17 +02:00
{
2024-05-08 13:16:16 +02:00
if(artsInst.getArt(artPlace.slot))
2024-05-02 00:49:17 +02:00
{
if(ArtifactUtilsClient::askToDisassemble(artsInst.getHero(), artPlace.slot))
return;
if(ArtifactUtilsClient::askToAssemble(artsInst.getHero(), artPlace.slot))
return;
if(artPlace.text.size())
artPlace.LRClickableAreaWTextComp::showPopupWindow(cursorPosition);
}
}
2023-04-23 14:10:35 +02:00
2024-05-08 13:16:16 +02:00
void CWindowWithArtifacts::showArifactInfo(CArtPlace & artPlace, const Point & cursorPosition) const
2024-05-02 00:49:17 +02:00
{
if(artPlace.getArt() && artPlace.text.size())
artPlace.LRClickableAreaWTextComp::showPopupWindow(cursorPosition);
2023-04-23 14:10:35 +02:00
}
void CWindowWithArtifacts::showQuickBackpackWindow(const CGHeroInstance * hero, const ArtifactPosition & slot,
2024-05-08 13:16:16 +02:00
const Point & cursorPosition) const
2023-12-17 16:30:19 +02:00
{
2024-05-02 00:49:17 +02:00
if(!settings["general"]["enableUiEnhancements"].Bool())
2023-12-17 16:30:19 +02:00
return;
GH.windows().createAndPushWindow<CHeroQuickBackpackWindow>(hero, slot);
2024-05-02 00:49:17 +02:00
auto backpackWindow = GH.windows().topWindow<CHeroQuickBackpackWindow>();
backpackWindow->moveTo(cursorPosition - Point(1, 1));
backpackWindow->fitToScreen(15);
2023-12-17 16:30:19 +02:00
}
2024-04-23 15:21:45 +02:00
void CWindowWithArtifacts::activate()
{
if(const auto art = getPickedArtifact())
2024-05-08 13:16:16 +02:00
{
markPossibleSlots();
2024-04-23 15:21:45 +02:00
setCursorAnimation(*art);
2024-05-08 13:16:16 +02:00
}
2024-04-23 15:21:45 +02:00
CWindowObject::activate();
}
void CWindowWithArtifacts::deactivate()
{
CCS->curh->dragAndDropCursor(nullptr);
CWindowObject::deactivate();
}
void CWindowWithArtifacts::enableKeyboardShortcuts() const
2024-04-19 16:14:41 +02:00
{
2024-05-01 20:18:36 +02:00
for(auto & artSet : artSets)
artSet->enableKeyboardShortcuts();
2024-04-19 16:14:41 +02:00
}
2023-04-23 14:10:35 +02:00
void CWindowWithArtifacts::artifactRemoved(const ArtifactLocation & artLoc)
{
2024-04-23 19:26:21 +02:00
update();
2023-04-23 14:10:35 +02:00
}
2024-05-08 13:16:16 +02:00
void CWindowWithArtifacts::artifactMoved(const ArtifactLocation & srcLoc, const ArtifactLocation & destLoc)
2023-04-23 14:10:35 +02:00
{
2024-05-01 20:18:36 +02:00
for(auto & artSet : artSets)
if(const auto pickedArtInst = getPickedArtifact())
{
markPossibleSlots();
setCursorAnimation(*pickedArtInst);
}
else
{
artSet->unmarkSlots();
CCS->curh->dragAndDropCursor(nullptr);
}
2023-04-23 14:10:35 +02:00
}
void CWindowWithArtifacts::artifactDisassembled(const ArtifactLocation & artLoc)
{
2024-04-23 19:26:21 +02:00
update();
2023-04-23 14:10:35 +02:00
}
void CWindowWithArtifacts::artifactAssembled(const ArtifactLocation & artLoc)
{
2023-09-03 20:41:00 +02:00
markPossibleSlots();
2024-04-23 19:26:21 +02:00
update();
2023-04-23 14:10:35 +02:00
}
2024-05-01 20:18:36 +02:00
void CWindowWithArtifacts::update()
2023-04-23 14:10:35 +02:00
{
2024-05-01 20:18:36 +02:00
for(auto & artSet : artSets)
{
artSet->updateWornSlots();
artSet->updateBackpackSlots();
2023-04-23 14:10:35 +02:00
// Make sure the status bar is updated so it does not display old text
if(auto artPlace = artSet->getArtPlace(GH.getCursorPosition()))
artPlace->hover(true);
}
2023-04-23 14:10:35 +02:00
}
2023-09-03 20:41:00 +02:00
void CWindowWithArtifacts::markPossibleSlots()
{
if(const auto pickedArtInst = getPickedArtifact())
{
const auto heroArtOwner = getHeroPickedArtifact();
for(auto & artSet : artSets)
2023-09-03 20:41:00 +02:00
{
if(artSet->isActive())
2023-09-03 20:41:00 +02:00
{
const auto hero = artSet->getHero();
if(heroArtOwner == hero || !std::dynamic_pointer_cast<CArtifactsOfHeroKingdom>(artSet))
artSet->markPossibleSlots(pickedArtInst, hero->tempOwner == LOCPLINT->playerID);
2023-09-03 20:41:00 +02:00
}
};
}
}
2024-01-27 23:48:11 +02:00
2024-05-02 00:49:17 +02:00
bool CWindowWithArtifacts::checkSpecialArts(const CArtifactInstance & artInst, const CGHeroInstance & hero, bool isTrade) const
2024-01-27 23:48:11 +02:00
{
const auto artId = artInst.getTypeId();
if(artId == ArtifactID::SPELLBOOK)
{
2024-05-02 00:49:17 +02:00
GH.windows().createAndPushWindow<CSpellWindow>(&hero, LOCPLINT, LOCPLINT->battleInt.get());
2024-01-27 23:48:11 +02:00
return false;
}
if(artId == ArtifactID::CATAPULT)
{
// The Catapult must be equipped
LOCPLINT->showInfoDialog(CGI->generaltexth->allTexts[312],
std::vector<std::shared_ptr<CComponent>>(1, std::make_shared<CComponent>(ComponentType::ARTIFACT, ArtifactID(ArtifactID::CATAPULT))));
return false;
}
2024-04-23 19:26:21 +02:00
if(isTrade && !artInst.artType->isTradable())
2024-01-27 23:48:11 +02:00
{
2024-04-23 19:26:21 +02:00
LOCPLINT->showInfoDialog(CGI->generaltexth->allTexts[21],
std::vector<std::shared_ptr<CComponent>>(1, std::make_shared<CComponent>(ComponentType::ARTIFACT, artId)));
return false;
2024-01-27 23:48:11 +02:00
}
return true;
}
2024-04-16 16:45:31 +02:00
void CWindowWithArtifacts::setCursorAnimation(const CArtifactInstance & artInst)
{
if(artInst.isScroll() && settings["general"]["enableUiEnhancements"].Bool())
{
assert(artInst.getScrollSpellID().num >= 0);
const auto animation = GH.renderHandler().loadAnimation(AnimationPath::builtin("spellscr"));
animation->load(artInst.getScrollSpellID().num);
CCS->curh->dragAndDropCursor(animation->getImage(artInst.getScrollSpellID().num)->scaleFast(Point(44, 34)));
}
else
{
CCS->curh->dragAndDropCursor(AnimationPath::builtin("artifact"), artInst.artType->getIconIndex());
}
}
2024-05-02 00:49:17 +02:00
void CWindowWithArtifacts::putPickedArtifact(const CGHeroInstance & curHero, const ArtifactPosition & targetSlot)
{
const auto heroArtOwner = getHeroPickedArtifact();
const auto pickedArt = getPickedArtifact();
auto srcLoc = ArtifactLocation(heroArtOwner->id, ArtifactPosition::TRANSITION_POS);
auto dstLoc = ArtifactLocation(curHero.id, targetSlot);
if(ArtifactUtils::isSlotBackpack(dstLoc.slot))
{
if(pickedArt->artType->isBig())
{
// War machines cannot go to backpack
LOCPLINT->showInfoDialog(boost::str(boost::format(CGI->generaltexth->allTexts[153]) % pickedArt->artType->getNameTranslated()));
}
else
{
if(ArtifactUtils::isBackpackFreeSlots(heroArtOwner))
LOCPLINT->cb->swapArtifacts(srcLoc, dstLoc);
else
LOCPLINT->showInfoDialog(CGI->generaltexth->translate("core.genrltxt.152"));
}
}
// Check if artifact transfer is possible
else if(pickedArt->canBePutAt(&curHero, dstLoc.slot, true) && (!curHero.getArt(targetSlot) || curHero.tempOwner == LOCPLINT->playerID))
{
LOCPLINT->cb->swapArtifacts(srcLoc, dstLoc);
}
}
2024-05-08 13:16:16 +02:00
void CWindowWithArtifacts::onClickPressedCommonArtifact(const CGHeroInstance & curHero, const ArtifactPosition & slot, bool closeWindow)
{
assert(curHero.getArt(slot));
auto srcLoc = ArtifactLocation(curHero.id, slot);
auto dstLoc = ArtifactLocation(curHero.id, ArtifactPosition::TRANSITION_POS);
if(GH.isKeyboardCmdDown())
{
for(auto & anotherSet : artSets)
{
if(std::dynamic_pointer_cast<CArtifactsOfHeroMain>(anotherSet))
2024-05-08 13:16:16 +02:00
{
if(curHero.id != anotherSet->getHero()->id)
2024-05-08 13:16:16 +02:00
{
dstLoc.slot = ArtifactPosition::FIRST_AVAILABLE;
dstLoc.artHolder = anotherSet->getHero()->id;
2024-05-08 13:16:16 +02:00
break;
}
}
if(const auto heroSetAltar = std::dynamic_pointer_cast<CArtifactsOfHeroAltar>(anotherSet))
2024-05-08 13:16:16 +02:00
{
dstLoc.slot = ArtifactPosition::FIRST_AVAILABLE;
dstLoc.artHolder = heroSetAltar->altarId;
2024-05-08 13:16:16 +02:00
break;
}
}
}
else if(GH.isKeyboardAltDown())
{
const auto artId = curHero.getArt(slot)->getTypeId();
if(ArtifactUtils::isSlotEquipment(slot))
dstLoc.slot = ArtifactUtils::getArtBackpackPosition(&curHero, artId);
else if(ArtifactUtils::isSlotBackpack(slot))
dstLoc.slot = ArtifactUtils::getArtEquippedPosition(&curHero, artId);
}
else if(closeWindow && closeCallback)
{
closeCallback();
}
if(dstLoc.slot != ArtifactPosition::PRE_FIRST)
LOCPLINT->cb->swapArtifacts(srcLoc, dstLoc);
}