1
0
mirror of https://github.com/vcmi/vcmi.git synced 2024-12-22 22:13:35 +02:00
vcmi/client/windows/CWindowWithArtifacts.cpp

317 lines
9.0 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 "CHeroWindow.h"
#include "CSpellWindow.h"
#include "CExchangeWindow.h"
#include "CHeroBackpackWindow.h"
2023-04-23 14:10:35 +02:00
#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 "../CPlayerInterface.h"
#include "../CGameInfo.h"
2023-05-17 15:52:16 +02:00
#include "../../lib/ArtifactUtils.h"
#include "../../lib/texts/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-05-20 14:31:07 +02:00
const CGHeroInstance * CWindowWithArtifacts::getHeroPickedArtifact() const
2023-04-23 14:10:35 +02:00
{
const CGHeroInstance * hero = nullptr;
2024-05-20 14:31:07 +02:00
for(const 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
}
2024-05-20 14:31:07 +02:00
const CArtifactInstance * CWindowWithArtifacts::getPickedArtifact() const
2023-04-23 14:10:35 +02:00
{
2024-05-20 14:31:07 +02:00
for(const auto & artSet : artSets)
if(const auto pickedArt = artSet->getHero()->getArt(ArtifactPosition::TRANSITION_POS))
{
return pickedArt;
}
return nullptr;
2023-04-23 14:10:35 +02:00
}
void CWindowWithArtifacts::clickPressedOnArtPlace(const CGHeroInstance * hero, const ArtifactPosition & slot,
bool allowExchange, bool altarTrading, bool closeWindow, const Point & cursorPosition)
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
}
2024-09-24 15:35:28 +02:00
else if(GH.isKeyboardShiftDown())
{
showQuickBackpackWindow(hero, slot, cursorPosition);
2024-09-24 15:35:28 +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,
2024-05-20 14:31:07 +02:00
const ArtifactLocation & dstLoc)
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-20 14:31:07 +02:00
close();
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::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
{
2024-07-15 23:03:06 +02:00
if(LOCPLINT->artifactController->askToDisassemble(artsInst.getHero(), artPlace.slot))
2024-05-02 00:49:17 +02:00
return;
2024-07-15 23:03:06 +02:00
if(LOCPLINT->artifactController->askToAssemble(artsInst.getHero(), artPlace.slot))
2024-05-02 00:49:17 +02:00
return;
if(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;
if(!ArtifactUtils::isSlotEquipment(slot))
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
}
2024-06-22 18:29:39 +02:00
void CWindowWithArtifacts::update()
2023-04-23 14:10:35 +02:00
{
2024-05-20 14:31:07 +02:00
for(const auto & artSet : artSets)
2024-06-22 18:29:39 +02:00
{
artSet->updateWornSlots();
artSet->updateBackpackSlots();
if(const auto pickedArtInst = getPickedArtifact())
{
markPossibleSlots();
setCursorAnimation(*pickedArtInst);
}
else
{
artSet->unmarkSlots();
CCS->curh->dragAndDropCursor(nullptr);
}
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);
}
2024-06-23 22:48:19 +02:00
redraw();
2023-04-23 14:10:35 +02:00
}
2024-05-20 14:31:07 +02:00
void CWindowWithArtifacts::markPossibleSlots() const
2023-09-03 20:41:00 +02:00
{
if(const auto pickedArtInst = getPickedArtifact())
{
2024-05-20 14:31:07 +02:00
for(const auto & artSet : artSets)
2023-09-03 20:41:00 +02:00
{
2024-05-20 14:31:07 +02:00
const auto hero = artSet->getHero();
if(hero == nullptr || !artSet->isActive())
continue;
if(getHeroPickedArtifact() == hero || !std::dynamic_pointer_cast<CArtifactsOfHeroKingdom>(artSet))
artSet->markPossibleSlots(pickedArtInst->getType(), hero->tempOwner == LOCPLINT->playerID);
2024-05-20 14:31:07 +02:00
}
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;
}
if(isTrade && !artInst.getType()->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
2024-05-20 14:31:07 +02:00
void CWindowWithArtifacts::setCursorAnimation(const CArtifactInstance & artInst) const
2024-04-16 16:45:31 +02:00
{
if(artInst.isScroll() && settings["general"]["enableUiEnhancements"].Bool())
{
assert(artInst.getScrollSpellID().num >= 0);
auto image = GH.renderHandler().loadImage(AnimationPath::builtin("spellscr"), artInst.getScrollSpellID().num, 0, EImageBlitMode::COLORKEY);
image->scaleTo(Point(44,34));
CCS->curh->dragAndDropCursor(image);
2024-04-16 16:45:31 +02:00
}
else
{
CCS->curh->dragAndDropCursor(AnimationPath::builtin("artifact"), artInst.getType()->getIconIndex());
2024-04-16 16:45:31 +02:00
}
}
2024-05-02 00:49:17 +02:00
2024-05-20 14:31:07 +02:00
void CWindowWithArtifacts::putPickedArtifact(const CGHeroInstance & curHero, const ArtifactPosition & targetSlot) const
2024-05-02 00:49:17 +02:00
{
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->getType()->isBig())
2024-05-02 00:49:17 +02:00
{
// War machines cannot go to backpack
LOCPLINT->showInfoDialog(boost::str(boost::format(CGI->generaltexth->allTexts[153]) % pickedArt->getType()->getNameTranslated()));
2024-05-02 00:49:17 +02:00
}
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())
{
2024-05-20 14:31:07 +02:00
for(const auto & anotherSet : artSets)
2024-05-08 13:16:16 +02:00
{
2024-05-20 14:31:07 +02:00
if(std::dynamic_pointer_cast<CArtifactsOfHeroMain>(anotherSet) && curHero.id != anotherSet->getHero()->id)
2024-05-08 13:16:16 +02:00
{
2024-05-20 14:31:07 +02:00
dstLoc.slot = ArtifactPosition::FIRST_AVAILABLE;
dstLoc.artHolder = anotherSet->getHero()->id;
break;
2024-05-08 13:16:16 +02:00
}
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);
}
2024-05-20 14:31:07 +02:00
else if(closeWindow)
2024-05-08 13:16:16 +02:00
{
2024-05-20 14:31:07 +02:00
close();
2024-05-08 13:16:16 +02:00
}
if(dstLoc.slot != ArtifactPosition::PRE_FIRST)
LOCPLINT->cb->swapArtifacts(srcLoc, dstLoc);
}