|
@@ -11,13 +11,9 @@
|
|
|
#include "CArtifactHolder.h"
|
|
|
|
|
|
#include "../gui/CGuiHandler.h"
|
|
|
-#include "../gui/CursorHandler.h"
|
|
|
|
|
|
-#include "Buttons.h"
|
|
|
#include "CComponent.h"
|
|
|
|
|
|
-#include "../windows/CHeroWindow.h"
|
|
|
-#include "../windows/CSpellWindow.h"
|
|
|
#include "../windows/GUIClasses.h"
|
|
|
#include "../renderSDL/SDL_Extensions.h"
|
|
|
#include "../CPlayerInterface.h"
|
|
@@ -25,369 +21,29 @@
|
|
|
|
|
|
#include "../../CCallback.h"
|
|
|
|
|
|
-#include "../../lib/CArtHandler.h"
|
|
|
#include "../../lib/CGeneralTextHandler.h"
|
|
|
|
|
|
#include "../../lib/mapObjects/CGHeroInstance.h"
|
|
|
|
|
|
-CHeroArtPlace::CHeroArtPlace(Point position, const CArtifactInstance * Art)
|
|
|
- : CArtPlace(position, Art),
|
|
|
- locked(false),
|
|
|
- picked(false),
|
|
|
- marked(false),
|
|
|
- ourOwner(nullptr)
|
|
|
-{
|
|
|
- createImage();
|
|
|
-}
|
|
|
-
|
|
|
-void CHeroArtPlace::createImage()
|
|
|
-{
|
|
|
- OBJECT_CONSTRUCTION_CAPTURING(255-DISPOSE);
|
|
|
-
|
|
|
- si32 imageIndex = 0;
|
|
|
-
|
|
|
- if(locked)
|
|
|
- imageIndex = ArtifactID::ART_LOCK;
|
|
|
- else if(ourArt)
|
|
|
- imageIndex = ourArt->artType->getIconIndex();
|
|
|
-
|
|
|
- image = std::make_shared<CAnimImage>("artifact", imageIndex);
|
|
|
- if(!ourArt)
|
|
|
- image->disable();
|
|
|
-
|
|
|
- selection = std::make_shared<CAnimImage>("artifact", ArtifactID::ART_SELECTION);
|
|
|
- selection->disable();
|
|
|
-}
|
|
|
-
|
|
|
-void CHeroArtPlace::lockSlot(bool on)
|
|
|
-{
|
|
|
- if (locked == on)
|
|
|
- return;
|
|
|
-
|
|
|
- locked = on;
|
|
|
-
|
|
|
- if (on)
|
|
|
- image->setFrame(ArtifactID::ART_LOCK);
|
|
|
- else if (ourArt)
|
|
|
- image->setFrame(ourArt->artType->getIconIndex());
|
|
|
- else
|
|
|
- image->setFrame(0);
|
|
|
-}
|
|
|
-
|
|
|
-void CHeroArtPlace::pickSlot(bool on)
|
|
|
-{
|
|
|
- if (picked == on)
|
|
|
- return;
|
|
|
-
|
|
|
- picked = on;
|
|
|
- if (on)
|
|
|
- image->disable();
|
|
|
- else
|
|
|
- image->enable();
|
|
|
-}
|
|
|
-
|
|
|
-void CHeroArtPlace::selectSlot(bool on)
|
|
|
-{
|
|
|
- if (marked == on)
|
|
|
- return;
|
|
|
-
|
|
|
- marked = on;
|
|
|
- if (on)
|
|
|
- selection->enable();
|
|
|
- else
|
|
|
- selection->disable();
|
|
|
-}
|
|
|
-
|
|
|
-void CHeroArtPlace::clickLeft(tribool down, bool previousState)
|
|
|
-{
|
|
|
- //LRClickableAreaWTextComp::clickLeft(down);
|
|
|
- bool inBackpack = ArtifactUtils::isSlotBackpack(slotID);
|
|
|
- bool srcInBackpack = ArtifactUtils::isSlotBackpack(ourOwner->commonInfo->src.slotID);
|
|
|
- bool srcInSameHero = ourOwner->commonInfo->src.AOH == ourOwner;
|
|
|
-
|
|
|
- if(ourOwner->highlightModeCallback && ourArt)
|
|
|
- {
|
|
|
- if(down)
|
|
|
- {
|
|
|
- if(!ourArt->artType->isTradable()) //War Machine or Spellbook
|
|
|
- {
|
|
|
- LOCPLINT->showInfoDialog(CGI->generaltexth->allTexts[21]); //This item can't be traded.
|
|
|
- }
|
|
|
- else
|
|
|
- {
|
|
|
- ourOwner->unmarkSlots(false);
|
|
|
- selectSlot(true);
|
|
|
- ourOwner->highlightModeCallback(this);
|
|
|
- }
|
|
|
- }
|
|
|
- return;
|
|
|
- }
|
|
|
-
|
|
|
- // If clicked on spellbook, open it only if no artifact is held at the moment.
|
|
|
- if(ourArt && !down && previousState && !ourOwner->commonInfo->src.AOH)
|
|
|
- {
|
|
|
- if(ourArt->artType->getId() == ArtifactID::SPELLBOOK)
|
|
|
- GH.pushIntT<CSpellWindow>(ourOwner->curHero, LOCPLINT, LOCPLINT->battleInt.get());
|
|
|
- }
|
|
|
-
|
|
|
- if (!down && previousState)
|
|
|
- {
|
|
|
- if(ourArt && ourArt->artType->getId() == ArtifactID::SPELLBOOK)
|
|
|
- return; //this is handled separately
|
|
|
-
|
|
|
- if(!ourOwner->commonInfo->src.AOH) //nothing has been clicked
|
|
|
- {
|
|
|
- if(ourArt //to prevent selecting empty slots (bugfix to what GrayFace reported)
|
|
|
- && ourOwner->curHero->tempOwner == LOCPLINT->playerID)//can't take art from another player
|
|
|
- {
|
|
|
- if(ourArt->artType->getId() == ArtifactID::CATAPULT) //catapult cannot be highlighted
|
|
|
- {
|
|
|
- std::vector<std::shared_ptr<CComponent>> catapult(1, std::make_shared<CComponent>(CComponent::artifact, 3, 0));
|
|
|
- LOCPLINT->showInfoDialog(CGI->generaltexth->allTexts[312], catapult); //The Catapult must be equipped.
|
|
|
- return;
|
|
|
- }
|
|
|
- select();
|
|
|
- }
|
|
|
- }
|
|
|
- // Perform artifact transition
|
|
|
- else if(ourArt != ourOwner->commonInfo->src.art)
|
|
|
- {
|
|
|
- if(inBackpack) // Backpack destination.
|
|
|
- {
|
|
|
- if(!srcInBackpack || slotID != ourOwner->commonInfo->src.slotID + 1)
|
|
|
- {
|
|
|
- const CArtifact * const cur = ourOwner->commonInfo->src.art->artType;
|
|
|
-
|
|
|
- if(cur->getId() == ArtifactID::CATAPULT)
|
|
|
- {
|
|
|
- //should not happen, catapult cannot be selected
|
|
|
- logGlobal->error("Attempt to move Catapult");
|
|
|
- }
|
|
|
- else if(cur->isBig())
|
|
|
- {
|
|
|
- //war machines cannot go to backpack
|
|
|
- LOCPLINT->showInfoDialog(boost::str(boost::format(CGI->generaltexth->allTexts[153]) % cur->getNameTranslated()));
|
|
|
- }
|
|
|
- else
|
|
|
- {
|
|
|
- setMeAsDest();
|
|
|
- vstd::amin(ourOwner->commonInfo->dst.slotID, ourOwner->curHero->artifactsInBackpack.size() + GameConstants::BACKPACK_START);
|
|
|
- if(ArtifactUtils::isBackpackFreeSlots(ourOwner->curHero))
|
|
|
- {
|
|
|
- if(!srcInSameHero || ourOwner->commonInfo->dst.slotID != ourOwner->commonInfo->src.slotID)
|
|
|
- ourOwner->realizeCurrentTransaction();
|
|
|
- }
|
|
|
- else
|
|
|
- {
|
|
|
- LOCPLINT->showInfoDialog(CGI->generaltexth->translate("core.genrltxt.152"));
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
- //check if swap is possible
|
|
|
- else if (fitsHere(ourOwner->commonInfo->src.art) &&
|
|
|
- (!ourArt || ourOwner->curHero->tempOwner == LOCPLINT->playerID))
|
|
|
- {
|
|
|
- setMeAsDest();
|
|
|
- ourOwner->realizeCurrentTransaction();
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
-bool CHeroArtPlace::askToAssemble(const CGHeroInstance * hero, ArtifactPosition slot)
|
|
|
+void CArtPlace::setInternals(const CArtifactInstance * artInst)
|
|
|
{
|
|
|
- assert(hero);
|
|
|
- const auto art = hero->getArt(slot);
|
|
|
- assert(art);
|
|
|
- auto assemblyPossibilities = ArtifactUtils::assemblyPossibilities(hero, art->getTypeId(), ArtifactUtils::isSlotEquipment(slot));
|
|
|
-
|
|
|
- // If the artifact can be assembled, display dialog.
|
|
|
- for(const auto * combination : assemblyPossibilities)
|
|
|
- {
|
|
|
- LOCPLINT->showArtifactAssemblyDialog(
|
|
|
- art->artType,
|
|
|
- combination,
|
|
|
- std::bind(&CCallback::assembleArtifacts, LOCPLINT->cb.get(), hero, slot, true, combination->getId()));
|
|
|
-
|
|
|
- if(assemblyPossibilities.size() > 2)
|
|
|
- logGlobal->warn("More than one possibility of assembling on %s... taking only first", art->artType->getNameTranslated());
|
|
|
- return true;
|
|
|
- }
|
|
|
- return false;
|
|
|
-}
|
|
|
-
|
|
|
-bool CHeroArtPlace::askToDisassemble(const CGHeroInstance * hero, ArtifactPosition slot)
|
|
|
-{
|
|
|
- assert(hero);
|
|
|
- const auto art = hero->getArt(slot);
|
|
|
- assert(art);
|
|
|
-
|
|
|
- if(art->canBeDisassembled())
|
|
|
- {
|
|
|
- if(ArtifactUtils::isSlotBackpack(slot) && !ArtifactUtils::isBackpackFreeSlots(hero, art->artType->constituents->size() - 1))
|
|
|
- return false;
|
|
|
-
|
|
|
- LOCPLINT->showArtifactAssemblyDialog(
|
|
|
- art->artType,
|
|
|
- nullptr,
|
|
|
- std::bind(&CCallback::assembleArtifacts, LOCPLINT->cb.get(), hero, slot, false, ArtifactID()));
|
|
|
- return true;
|
|
|
- }
|
|
|
- return false;
|
|
|
-}
|
|
|
-
|
|
|
-void CHeroArtPlace::clickRight(tribool down, bool previousState)
|
|
|
-{
|
|
|
- if(ourArt && down && !locked && text.size() && !picked) //if there is no description or it's a lock, do nothing ;]
|
|
|
- {
|
|
|
- if(ourOwner->allowedAssembling)
|
|
|
- {
|
|
|
- // If the artifact can be assembled, display dialog.
|
|
|
- if(askToAssemble(ourOwner->curHero, slotID))
|
|
|
- {
|
|
|
- return;
|
|
|
- }
|
|
|
- if(askToDisassemble(ourOwner->curHero, slotID))
|
|
|
- {
|
|
|
- return;
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- // Lastly just show the artifact description.
|
|
|
- LRClickableAreaWTextComp::clickRight(down, previousState);
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
-void CArtifactsOfHero::activate()
|
|
|
-{
|
|
|
- if (commonInfo->src.AOH == this && commonInfo->src.art)
|
|
|
- CCS->curh->dragAndDropCursor("artifact", commonInfo->src.art->artType->getIconIndex());
|
|
|
-
|
|
|
- CIntObject::activate();
|
|
|
-}
|
|
|
-
|
|
|
-void CArtifactsOfHero::deactivate()
|
|
|
-{
|
|
|
- if (commonInfo->src.AOH == this && commonInfo->src.art)
|
|
|
- CCS->curh->dragAndDropCursor(nullptr);
|
|
|
-
|
|
|
- CIntObject::deactivate();
|
|
|
-}
|
|
|
-
|
|
|
-/**
|
|
|
- * Selects artifact slot so that the containing artifact looks like it's picked up.
|
|
|
- */
|
|
|
-void CHeroArtPlace::select()
|
|
|
-{
|
|
|
- if(locked)
|
|
|
- return;
|
|
|
-
|
|
|
- pickSlot(true);
|
|
|
- if(ourArt->canBeDisassembled() && ArtifactUtils::isSlotEquipment(slotID)) //worn combined artifact -> locks have to disappear
|
|
|
- {
|
|
|
- for(auto slot : ArtifactUtils::constituentWornSlots())
|
|
|
- {
|
|
|
- auto ap = ourOwner->getArtPlace(slot);
|
|
|
- if(ap)//getArtPlace may return null
|
|
|
- ap->pickSlot(ourArt->isPart(ap->ourArt));
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- ourOwner->commonInfo->src.setTo(this, false);
|
|
|
- ourOwner->commonInfo->src.slotID = ArtifactPosition::TRANSITION_POS;
|
|
|
-
|
|
|
- LOCPLINT->cb->swapArtifacts(ArtifactLocation(ourOwner->curHero, slotID),
|
|
|
- ArtifactLocation(ourOwner->curHero, ArtifactPosition::TRANSITION_POS));
|
|
|
-}
|
|
|
-
|
|
|
-void CHeroArtPlace::showAll(SDL_Surface * to)
|
|
|
-{
|
|
|
- if (ourArt && !picked && ourArt == ourOwner->curHero->getArt(slotID, false)) //last condition is needed for disassembling -> artifact may be gone, but we don't know yet TODO: real, nice solution
|
|
|
- {
|
|
|
- CIntObject::showAll(to);
|
|
|
- }
|
|
|
-
|
|
|
- if(marked && active)
|
|
|
- {
|
|
|
- // Draw vertical bars.
|
|
|
- for (int i = 0; i < pos.h; ++i)
|
|
|
- {
|
|
|
- CSDL_Ext::putPixelWithoutRefresh(to, pos.x, pos.y + i, 240, 220, 120);
|
|
|
- CSDL_Ext::putPixelWithoutRefresh(to, pos.x + pos.w - 1, pos.y + i, 240, 220, 120);
|
|
|
- }
|
|
|
-
|
|
|
- // Draw horizontal bars.
|
|
|
- for (int i = 0; i < pos.w; ++i)
|
|
|
- {
|
|
|
- CSDL_Ext::putPixelWithoutRefresh(to, pos.x + i, pos.y, 240, 220, 120);
|
|
|
- CSDL_Ext::putPixelWithoutRefresh(to, pos.x + i, pos.y + pos.h - 1, 240, 220, 120);
|
|
|
- }
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
-bool CHeroArtPlace::fitsHere(const CArtifactInstance * art) const
|
|
|
-{
|
|
|
- // You can place 'no artifact' anywhere.
|
|
|
- if(!art)
|
|
|
- return true;
|
|
|
-
|
|
|
- // Anything but War Machines can be placed in backpack.
|
|
|
- if (slotID >= GameConstants::BACKPACK_START)
|
|
|
- return !art->artType->isBig();
|
|
|
-
|
|
|
- return art->canBePutAt(ArtifactLocation(ourOwner->curHero, slotID), true);
|
|
|
-}
|
|
|
-
|
|
|
-void CHeroArtPlace::setMeAsDest(bool backpackAsVoid)
|
|
|
-{
|
|
|
- ourOwner->commonInfo->dst.setTo(this, backpackAsVoid);
|
|
|
-}
|
|
|
-
|
|
|
-void CHeroArtPlace::setArtifact(const CArtifactInstance *art)
|
|
|
-{
|
|
|
- baseType = -1; //by default we don't store any component
|
|
|
- ourArt = art;
|
|
|
- if(!art)
|
|
|
+ baseType = -1; // By default we don't store any component
|
|
|
+ ourArt = artInst;
|
|
|
+ if(!artInst)
|
|
|
{
|
|
|
image->disable();
|
|
|
text.clear();
|
|
|
hoverText = CGI->generaltexth->allTexts[507];
|
|
|
return;
|
|
|
}
|
|
|
-
|
|
|
image->enable();
|
|
|
- image->setFrame(locked ? ArtifactID::ART_LOCK : art->artType->getIconIndex());
|
|
|
-
|
|
|
- text = art->getDescription();
|
|
|
-
|
|
|
- // Display info about set
|
|
|
- if(ourOwner && ourOwner->curHero && !art->canBeDisassembled())
|
|
|
+ image->setFrame(artInst->artType->getIconIndex());
|
|
|
+ if(artInst->getTypeId() == ArtifactID::SPELL_SCROLL)
|
|
|
{
|
|
|
- for(const auto combinedArt : art->artType->constituentOf)
|
|
|
+ auto spellID = artInst->getScrollSpellID();
|
|
|
+ if(spellID.num >= 0)
|
|
|
{
|
|
|
- std::string artList;
|
|
|
- text += "\n\n";
|
|
|
- text += "{" + combinedArt->getNameTranslated() + "}";
|
|
|
- int wornArtifacts = 0;
|
|
|
- for(const auto part : *combinedArt->constituents)
|
|
|
- {
|
|
|
- if(art->artType->constituentOf.size() <= 1)
|
|
|
- artList += "\n" + part->getNameTranslated();
|
|
|
- if(ourOwner->curHero->hasArt(part->getId(), true))
|
|
|
- wornArtifacts++;
|
|
|
- }
|
|
|
- text += " (" + boost::str(boost::format("%d") % wornArtifacts) + " / " +
|
|
|
- boost::str(boost::format("%d") % combinedArt->constituents->size()) + ")" + artList;
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- if(art->artType->getId() == ArtifactID::SPELL_SCROLL)
|
|
|
- {
|
|
|
- int spellID = art->getScrollSpellID();
|
|
|
- if(spellID >= 0)
|
|
|
- {
|
|
|
- //add spell component info (used to provide a pic in r-click popup)
|
|
|
+ // Add spell component info (used to provide a pic in r-click popup)
|
|
|
baseType = CComponent::spell;
|
|
|
type = spellID;
|
|
|
bonusValue = 0;
|
|
@@ -396,687 +52,275 @@ void CHeroArtPlace::setArtifact(const CArtifactInstance *art)
|
|
|
else
|
|
|
{
|
|
|
baseType = CComponent::artifact;
|
|
|
- type = art->artType->getId();
|
|
|
+ type = artInst->getTypeId();
|
|
|
bonusValue = 0;
|
|
|
}
|
|
|
-
|
|
|
- if (locked) // Locks should appear as empty.
|
|
|
- hoverText = CGI->generaltexth->allTexts[507];
|
|
|
- else
|
|
|
- hoverText = boost::str(boost::format(CGI->generaltexth->heroscrn[1]) % ourArt->artType->getNameTranslated());
|
|
|
+ text = artInst->getDescription();
|
|
|
}
|
|
|
|
|
|
-void CArtifactsOfHero::SCommonPart::reset()
|
|
|
+CArtPlace::CArtPlace(Point position, const CArtifactInstance * Art)
|
|
|
+ : ourArt(Art)
|
|
|
{
|
|
|
- src.clear();
|
|
|
- dst.clear();
|
|
|
- CCS->curh->dragAndDropCursor(nullptr);
|
|
|
-}
|
|
|
-
|
|
|
-void CArtifactsOfHero::setHero(const CGHeroInstance * hero)
|
|
|
-{
|
|
|
- curHero = hero;
|
|
|
- if (curHero->artifactsInBackpack.size() > 0)
|
|
|
- backpackPos %= curHero->artifactsInBackpack.size();
|
|
|
- else
|
|
|
- backpackPos = 0;
|
|
|
-
|
|
|
- // Fill the slots for worn artifacts and backpack.
|
|
|
-
|
|
|
- for(auto p : artWorn)
|
|
|
- {
|
|
|
- setSlotData(p.second, p.first);
|
|
|
- }
|
|
|
-
|
|
|
- scrollBackpack(0);
|
|
|
+ image = nullptr;
|
|
|
+ pos += position;
|
|
|
+ pos.w = pos.h = 44;
|
|
|
}
|
|
|
|
|
|
-void CArtifactsOfHero::dispose()
|
|
|
+void CArtPlace::clickLeft(tribool down, bool previousState)
|
|
|
{
|
|
|
- CCS->curh->dragAndDropCursor(nullptr);
|
|
|
+ LRClickableAreaWTextComp::clickLeft(down, previousState);
|
|
|
}
|
|
|
|
|
|
-void CArtifactsOfHero::scrollBackpack(int dir)
|
|
|
+void CArtPlace::clickRight(tribool down, bool previousState)
|
|
|
{
|
|
|
- int artsInBackpack = static_cast<int>(curHero->artifactsInBackpack.size());
|
|
|
- backpackPos += dir;
|
|
|
- if(backpackPos < 0)// No guarantee of modulus behavior with negative operands -> we keep it positive
|
|
|
- backpackPos += artsInBackpack;
|
|
|
-
|
|
|
- if(artsInBackpack)
|
|
|
- backpackPos %= artsInBackpack;
|
|
|
-
|
|
|
- std::multiset<const CArtifactInstance *> toOmit = artifactsOnAltar;
|
|
|
- if(commonInfo->src.art) //if we picked an art from backapck, its slot has to be omitted
|
|
|
- toOmit.insert(commonInfo->src.art);
|
|
|
-
|
|
|
- int omitedSoFar = 0;
|
|
|
-
|
|
|
- //set new data
|
|
|
- size_t s = 0;
|
|
|
- for( ; s < artsInBackpack; ++s)
|
|
|
- {
|
|
|
-
|
|
|
- if (s < artsInBackpack)
|
|
|
- {
|
|
|
- auto slotID = ArtifactPosition(GameConstants::BACKPACK_START + (s + backpackPos)%artsInBackpack);
|
|
|
- const CArtifactInstance *art = curHero->getArt(slotID);
|
|
|
- assert(art);
|
|
|
- if(!vstd::contains(toOmit, art))
|
|
|
- {
|
|
|
- if(s - omitedSoFar < backpack.size())
|
|
|
- setSlotData(backpack[s-omitedSoFar], slotID);
|
|
|
- }
|
|
|
- else
|
|
|
- {
|
|
|
- toOmit -= art;
|
|
|
- omitedSoFar++;
|
|
|
- continue;
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
- for( ; s - omitedSoFar < backpack.size(); s++)
|
|
|
- eraseSlotData(backpack[s-omitedSoFar], ArtifactPosition(GameConstants::BACKPACK_START + (si32)s));
|
|
|
-
|
|
|
- //in artifact merchant selling artifacts we may have highlight on one of backpack artifacts -> market needs update, cause artifact under highlight changed
|
|
|
- if(highlightModeCallback)
|
|
|
- {
|
|
|
- for(auto & elem : backpack)
|
|
|
- {
|
|
|
- if(elem->marked)
|
|
|
- {
|
|
|
- highlightModeCallback(elem.get());
|
|
|
- break;
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- //blocking scrolling if there is not enough artifacts to scroll
|
|
|
- bool scrollingPossible = artsInBackpack - omitedSoFar > backpack.size();
|
|
|
- leftArtRoll->block(!scrollingPossible);
|
|
|
- rightArtRoll->block(!scrollingPossible);
|
|
|
-
|
|
|
- safeRedraw();
|
|
|
+ LRClickableAreaWTextComp::clickRight(down, previousState);
|
|
|
}
|
|
|
|
|
|
-/**
|
|
|
- * Marks possible slots where a given artifact can be placed, except backpack.
|
|
|
- *
|
|
|
- * @param art Artifact checked against.
|
|
|
- */
|
|
|
-void CArtifactsOfHero::markPossibleSlots(const CArtifactInstance* art, bool withRedraw)
|
|
|
+const CArtifactInstance * CArtPlace::getArt()
|
|
|
{
|
|
|
- for(CArtifactsOfHero *aoh : commonInfo->participants)
|
|
|
- for(auto p : aoh->artWorn)
|
|
|
- p.second->selectSlot(art->canBePutAt(ArtifactLocation(aoh->curHero, p.second->slotID), true));
|
|
|
-
|
|
|
- if(withRedraw)
|
|
|
- safeRedraw();
|
|
|
+ return ourArt;
|
|
|
}
|
|
|
|
|
|
-/**
|
|
|
- * Unamarks all slots.
|
|
|
- */
|
|
|
-void CArtifactsOfHero::unmarkSlots(bool withRedraw)
|
|
|
+CCommanderArtPlace::CCommanderArtPlace(Point position, const CGHeroInstance * commanderOwner, ArtifactPosition artSlot, const CArtifactInstance * Art)
|
|
|
+ : CArtPlace(position, Art),
|
|
|
+ commanderOwner(commanderOwner),
|
|
|
+ commanderSlotID(artSlot.num)
|
|
|
{
|
|
|
- if(commonInfo)
|
|
|
- for(CArtifactsOfHero *aoh : commonInfo->participants)
|
|
|
- aoh->unmarkLocalSlots(false);
|
|
|
- else
|
|
|
- unmarkLocalSlots(false);
|
|
|
-
|
|
|
- if(withRedraw)
|
|
|
- safeRedraw();
|
|
|
+ createImage();
|
|
|
+ setArtifact(Art);
|
|
|
}
|
|
|
|
|
|
-void CArtifactsOfHero::unmarkLocalSlots(bool withRedraw)
|
|
|
+void CCommanderArtPlace::createImage()
|
|
|
{
|
|
|
- for(auto & p : artWorn)
|
|
|
- p.second->selectSlot(false);
|
|
|
+ OBJECT_CONSTRUCTION_CAPTURING(255 - DISPOSE);
|
|
|
|
|
|
- for(auto & place : backpack)
|
|
|
- place->selectSlot(false);
|
|
|
+ int imageIndex = 0;
|
|
|
+ if(ourArt)
|
|
|
+ imageIndex = ourArt->artType->getIconIndex();
|
|
|
|
|
|
- if(withRedraw)
|
|
|
- safeRedraw();
|
|
|
+ image = std::make_shared<CAnimImage>("artifact", imageIndex);
|
|
|
+ if(!ourArt)
|
|
|
+ image->disable();
|
|
|
}
|
|
|
|
|
|
-/**
|
|
|
- * Assigns an artifacts to an artifact place depending on it's new slot ID.
|
|
|
- */
|
|
|
-void CArtifactsOfHero::setSlotData(ArtPlacePtr artPlace, ArtifactPosition slotID)
|
|
|
+void CCommanderArtPlace::returnArtToHeroCallback()
|
|
|
{
|
|
|
- if(!artPlace && slotID >= GameConstants::BACKPACK_START) //spurious call from artifactMoved in attempt to update hidden backpack slot
|
|
|
- {
|
|
|
- return;
|
|
|
- }
|
|
|
-
|
|
|
- artPlace->pickSlot(false);
|
|
|
- artPlace->slotID = slotID;
|
|
|
-
|
|
|
- if(const ArtSlotInfo *asi = curHero->getSlot(slotID))
|
|
|
+ ArtifactPosition artifactPos = commanderSlotID;
|
|
|
+ ArtifactPosition freeSlot = ArtifactUtils::getArtBackpackPosition(commanderOwner, ourArt->getTypeId());
|
|
|
+ if(freeSlot == ArtifactPosition::PRE_FIRST)
|
|
|
{
|
|
|
- artPlace->lockSlot(asi->locked);
|
|
|
- artPlace->setArtifact(asi->artifact);
|
|
|
+ LOCPLINT->showInfoDialog(CGI->generaltexth->translate("core.genrltxt.152"));
|
|
|
}
|
|
|
else
|
|
|
- artPlace->setArtifact(nullptr);
|
|
|
-}
|
|
|
-
|
|
|
-/**
|
|
|
- * Makes given artifact slot appear as empty with a certain slot ID.
|
|
|
- */
|
|
|
-void CArtifactsOfHero::eraseSlotData(ArtPlacePtr artPlace, ArtifactPosition slotID)
|
|
|
-{
|
|
|
- artPlace->pickSlot(false);
|
|
|
- artPlace->slotID = slotID;
|
|
|
- artPlace->setArtifact(nullptr);
|
|
|
-}
|
|
|
-
|
|
|
-CArtifactsOfHero::CArtifactsOfHero(ArtPlaceMap ArtWorn, std::vector<ArtPlacePtr> Backpack,
|
|
|
- std::shared_ptr<CButton> leftScroll, std::shared_ptr<CButton> rightScroll, bool createCommonPart)
|
|
|
- : curHero(nullptr),
|
|
|
- artWorn(ArtWorn),
|
|
|
- backpack(Backpack),
|
|
|
- backpackPos(0),
|
|
|
- commonInfo(nullptr),
|
|
|
- leftArtRoll(leftScroll),
|
|
|
- rightArtRoll(rightScroll),
|
|
|
- allowedAssembling(true),
|
|
|
- highlightModeCallback(nullptr)
|
|
|
-{
|
|
|
- if(createCommonPart)
|
|
|
- {
|
|
|
- commonInfo = std::make_shared<CArtifactsOfHero::SCommonPart>();
|
|
|
- commonInfo->participants.insert(this);
|
|
|
- }
|
|
|
-
|
|
|
- // Init slots for worn artifacts.
|
|
|
- for(auto p : artWorn)
|
|
|
- {
|
|
|
- p.second->ourOwner = this;
|
|
|
- eraseSlotData(p.second, p.first);
|
|
|
- }
|
|
|
-
|
|
|
- // Init slots for the backpack.
|
|
|
- for(size_t s=0; s<backpack.size(); ++s)
|
|
|
- {
|
|
|
- backpack[s]->ourOwner = this;
|
|
|
- eraseSlotData(backpack[s], ArtifactPosition(GameConstants::BACKPACK_START + (si32)s));
|
|
|
- }
|
|
|
-
|
|
|
- leftArtRoll->addCallback(std::bind(&CArtifactsOfHero::scrollBackpack, this,-1));
|
|
|
- rightArtRoll->addCallback(std::bind(&CArtifactsOfHero::scrollBackpack, this,+1));
|
|
|
-}
|
|
|
-
|
|
|
-CArtifactsOfHero::CArtifactsOfHero(const Point & position, bool createCommonPart)
|
|
|
- : curHero(nullptr),
|
|
|
- backpackPos(0),
|
|
|
- commonInfo(nullptr),
|
|
|
- allowedAssembling(true),
|
|
|
- highlightModeCallback(nullptr)
|
|
|
-{
|
|
|
- if(createCommonPart)
|
|
|
- {
|
|
|
- commonInfo = std::make_shared<CArtifactsOfHero::SCommonPart>();
|
|
|
- commonInfo->participants.insert(this);
|
|
|
- }
|
|
|
-
|
|
|
- OBJECT_CONSTRUCTION_CAPTURING(255-DISPOSE);
|
|
|
- pos += position;
|
|
|
-
|
|
|
- std::vector<Point> slotPos =
|
|
|
- {
|
|
|
- Point(509,30), Point(567,240), Point(509,80), //0-2
|
|
|
- Point(383,68), Point(564,183), Point(509,130), //3-5
|
|
|
- Point(431,68), Point(610,183), Point(515,295), //6-8
|
|
|
- Point(383,143), Point(399,194), Point(415,245), //9-11
|
|
|
- Point(431,296), Point(564,30), Point(610,30), //12-14
|
|
|
- Point(610,76), Point(610,122), Point(610,310), //15-17
|
|
|
- Point(381,296) //18
|
|
|
- };
|
|
|
-
|
|
|
- // Create slots for worn artifacts.
|
|
|
- for(si32 g = 0; g < GameConstants::BACKPACK_START; g++)
|
|
|
{
|
|
|
- artWorn[ArtifactPosition(g)] = std::make_shared<CHeroArtPlace>(slotPos[g]);
|
|
|
- artWorn[ArtifactPosition(g)]->ourOwner = this;
|
|
|
- eraseSlotData(artWorn[ArtifactPosition(g)], ArtifactPosition(g));
|
|
|
- }
|
|
|
-
|
|
|
- // Create slots for the backpack.
|
|
|
- for(int s=0; s<5; ++s)
|
|
|
- {
|
|
|
- auto add = std::make_shared<CHeroArtPlace>(Point(403 + 46 * s, 365));
|
|
|
-
|
|
|
- add->ourOwner = this;
|
|
|
- eraseSlotData(add, ArtifactPosition(GameConstants::BACKPACK_START + s));
|
|
|
-
|
|
|
- backpack.push_back(add);
|
|
|
- }
|
|
|
-
|
|
|
- leftArtRoll = std::make_shared<CButton>(Point(379, 364), "hsbtns3.def", CButton::tooltip(), [&](){ scrollBackpack(-1);}, SDLK_LEFT);
|
|
|
- rightArtRoll = std::make_shared<CButton>(Point(632, 364), "hsbtns5.def", CButton::tooltip(), [&](){ scrollBackpack(+1);}, SDLK_RIGHT);
|
|
|
-}
|
|
|
+ ArtifactLocation src(commanderOwner->commander.get(), artifactPos);
|
|
|
+ ArtifactLocation dst(commanderOwner, freeSlot);
|
|
|
|
|
|
-CArtifactsOfHero::~CArtifactsOfHero()
|
|
|
-{
|
|
|
- dispose();
|
|
|
- // Artifact located in artifactsTransitionPos should be returned
|
|
|
- if(!curHero->artifactsTransitionPos.empty())
|
|
|
- {
|
|
|
- auto artPlace = getArtPlace(
|
|
|
- ArtifactUtils::getArtAnyPosition(curHero, curHero->artifactsTransitionPos.begin()->artifact->getTypeId()));
|
|
|
- if(artPlace)
|
|
|
- {
|
|
|
- assert(artPlace->ourOwner);
|
|
|
- artPlace->setMeAsDest();
|
|
|
- artPlace->ourOwner->realizeCurrentTransaction();
|
|
|
- }
|
|
|
- else
|
|
|
+ if(ourArt->canBePutAt(dst, true))
|
|
|
{
|
|
|
- LOCPLINT->cb->eraseArtifactByClient(ArtifactLocation(curHero, ArtifactPosition::TRANSITION_POS));
|
|
|
+ LOCPLINT->cb->swapArtifacts(src, dst);
|
|
|
+ setArtifact(nullptr);
|
|
|
+ parent->redraw();
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
|
|
|
-void CArtifactsOfHero::updateParentWindow()
|
|
|
+void CCommanderArtPlace::clickLeft(tribool down, bool previousState)
|
|
|
{
|
|
|
- if(CHeroWindow * chw = dynamic_cast<CHeroWindow*>(GH.topInt().get()))
|
|
|
- {
|
|
|
- chw->update(curHero, true);
|
|
|
- }
|
|
|
- else if(CExchangeWindow * cew = dynamic_cast<CExchangeWindow*>(GH.topInt().get()))
|
|
|
- {
|
|
|
- cew->updateWidgets();
|
|
|
- }
|
|
|
+ if(ourArt && text.size() && down)
|
|
|
+ LOCPLINT->showYesNoDialog(CGI->generaltexth->translate("vcmi.commanderWindow.artifactMessage"), [this]() { returnArtToHeroCallback(); }, []() {});
|
|
|
}
|
|
|
|
|
|
-void CArtifactsOfHero::safeRedraw()
|
|
|
+void CCommanderArtPlace::clickRight(tribool down, bool previousState)
|
|
|
{
|
|
|
- if (active)
|
|
|
- {
|
|
|
- if(parent)
|
|
|
- parent->redraw();
|
|
|
- else
|
|
|
- redraw();
|
|
|
- }
|
|
|
+ if(ourArt && text.size() && down)
|
|
|
+ CArtPlace::clickRight(down, previousState);
|
|
|
}
|
|
|
|
|
|
-void CArtifactsOfHero::realizeCurrentTransaction()
|
|
|
+void CCommanderArtPlace::setArtifact(const CArtifactInstance * art)
|
|
|
{
|
|
|
- assert(commonInfo->src.AOH);
|
|
|
- assert(commonInfo->dst.AOH);
|
|
|
- LOCPLINT->cb->swapArtifacts(ArtifactLocation(commonInfo->src.AOH->curHero, commonInfo->src.slotID),
|
|
|
- ArtifactLocation(commonInfo->dst.AOH->curHero, commonInfo->dst.slotID));
|
|
|
+ setInternals(art);
|
|
|
}
|
|
|
|
|
|
-void CArtifactsOfHero::artifactMoved(const ArtifactLocation & src, const ArtifactLocation & dst, bool withUIUpdate)
|
|
|
+CHeroArtPlace::CHeroArtPlace(Point position, const CArtifactInstance * Art)
|
|
|
+ : CArtPlace(position, Art),
|
|
|
+ locked(false),
|
|
|
+ marked(false)
|
|
|
{
|
|
|
- bool isCurHeroSrc = src.isHolder(curHero),
|
|
|
- isCurHeroDst = dst.isHolder(curHero);
|
|
|
- if(isCurHeroSrc && ArtifactUtils::isSlotBackpack(src.slot))
|
|
|
- updateSlot(src.slot);
|
|
|
- if(isCurHeroDst && ArtifactUtils::isSlotBackpack(dst.slot))
|
|
|
- updateSlot(dst.slot);
|
|
|
- // We need to update all slots, artifact might be combined and affect more slots
|
|
|
- if(isCurHeroSrc || isCurHeroDst)
|
|
|
- updateWornSlots(false);
|
|
|
-
|
|
|
- if(!isCurHeroSrc && !isCurHeroDst)
|
|
|
- return;
|
|
|
-
|
|
|
- // When moving one artifact onto another it leads to two art movements: dst->TRANSITION_POS; src->dst
|
|
|
- // however after first movement we pick the art from TRANSITION_POS and the second movement coming when
|
|
|
- // we have a different artifact may look surprising... but it's valid.
|
|
|
-
|
|
|
- // Used when doing dragAndDrop and artifact swap multiple times
|
|
|
- if(src.slot == ArtifactPosition::TRANSITION_POS &&
|
|
|
- commonInfo->src.slotID == ArtifactPosition::TRANSITION_POS &&
|
|
|
- commonInfo->dst.slotID == ArtifactPosition::PRE_FIRST &&
|
|
|
- isCurHeroDst)
|
|
|
- {
|
|
|
- auto art = curHero->getArt(ArtifactPosition::TRANSITION_POS);
|
|
|
- assert(art);
|
|
|
- CCS->curh->dragAndDropCursor("artifact", art->artType->getIconIndex());
|
|
|
- if(withUIUpdate)
|
|
|
- markPossibleSlots(art);
|
|
|
-
|
|
|
- commonInfo->src.art = art;
|
|
|
- commonInfo->src.slotID = src.slot;
|
|
|
- }
|
|
|
- // Artifact was taken from us
|
|
|
- else if(commonInfo->src == src && dst.slot != ArtifactPosition::TRANSITION_POS)
|
|
|
- {
|
|
|
- // Expected movement from slot ot slot
|
|
|
- assert(commonInfo->dst == dst
|
|
|
- // Artifact moved back to backpack (eg. to make place for art we are moving)
|
|
|
- || dst.slot == dst.getHolderArtSet()->artifactsInBackpack.size() + GameConstants::BACKPACK_START
|
|
|
- || dst.getHolderArtSet()->bearerType() != ArtBearer::HERO);
|
|
|
- commonInfo->reset();
|
|
|
- unmarkSlots();
|
|
|
- }
|
|
|
- else
|
|
|
- {
|
|
|
- // The dest artifact was moved after the swap -> we are picking it
|
|
|
- if(commonInfo->dst == src)
|
|
|
- {
|
|
|
- assert(dst.slot == ArtifactPosition::TRANSITION_POS);
|
|
|
- commonInfo->reset();
|
|
|
-
|
|
|
- for(CArtifactsOfHero * aoh : commonInfo->participants)
|
|
|
- {
|
|
|
- if(dst.isHolder(aoh->curHero))
|
|
|
- {
|
|
|
- commonInfo->src.AOH = aoh;
|
|
|
- break;
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- commonInfo->src.art = dst.getArt();
|
|
|
- commonInfo->src.slotID = dst.slot;
|
|
|
- assert(commonInfo->src.AOH);
|
|
|
- CCS->curh->dragAndDropCursor("artifact", dst.getArt()->artType->getIconIndex());
|
|
|
- }
|
|
|
- if(!curHero->artifactsTransitionPos.empty() && withUIUpdate)
|
|
|
- {
|
|
|
- auto artInst = curHero->getArt(ArtifactPosition::TRANSITION_POS);
|
|
|
- markPossibleSlots(artInst);
|
|
|
- CCS->curh->dragAndDropCursor("artifact", artInst->artType->getIconIndex());
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- if(withUIUpdate)
|
|
|
- {
|
|
|
- updateParentWindow();
|
|
|
- scrollBackpack(0);
|
|
|
- }
|
|
|
+ createImage();
|
|
|
}
|
|
|
|
|
|
-void CArtifactsOfHero::artifactRemoved(const ArtifactLocation &al)
|
|
|
+void CHeroArtPlace::lockSlot(bool on)
|
|
|
{
|
|
|
- if(al.isHolder(curHero))
|
|
|
- {
|
|
|
- if(al.slot < GameConstants::BACKPACK_START)
|
|
|
- updateWornSlots(0);
|
|
|
- else
|
|
|
- scrollBackpack(0); //update backpack slots
|
|
|
- }
|
|
|
-}
|
|
|
+ if(locked == on)
|
|
|
+ return;
|
|
|
|
|
|
-CArtifactsOfHero::ArtPlacePtr CArtifactsOfHero::getArtPlace(ArtifactPosition slot)
|
|
|
-{
|
|
|
- if(ArtifactUtils::isSlotEquipment(slot))
|
|
|
- {
|
|
|
- if(artWorn.find(slot) == artWorn.end())
|
|
|
- {
|
|
|
- logGlobal->error("CArtifactsOfHero::getArtPlace: invalid slot %d", slot);
|
|
|
- return nullptr;
|
|
|
- }
|
|
|
+ locked = on;
|
|
|
|
|
|
- return artWorn[slot];
|
|
|
- }
|
|
|
- if(ArtifactUtils::isSlotBackpack(slot))
|
|
|
- {
|
|
|
- for(ArtPlacePtr ap : backpack)
|
|
|
- if(ap->slotID == slot)
|
|
|
- return ap;
|
|
|
- return nullptr;
|
|
|
- }
|
|
|
+ if(on)
|
|
|
+ image->setFrame(ArtifactID::ART_LOCK);
|
|
|
+ else if(ourArt)
|
|
|
+ image->setFrame(ourArt->artType->getIconIndex());
|
|
|
else
|
|
|
- {
|
|
|
- return nullptr;
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
-void CArtifactsOfHero::artifactUpdateSlots(const ArtifactLocation & al)
|
|
|
-{
|
|
|
- if(al.isHolder(curHero))
|
|
|
- {
|
|
|
- if(ArtifactUtils::isSlotBackpack(al.slot))
|
|
|
- updateBackpackSlots(true);
|
|
|
- else
|
|
|
- updateWornSlots(true);
|
|
|
- }
|
|
|
+ image->setFrame(0);
|
|
|
}
|
|
|
|
|
|
-void CArtifactsOfHero::updateWornSlots(bool redrawParent)
|
|
|
+bool CHeroArtPlace::isLocked()
|
|
|
{
|
|
|
- for(auto p : artWorn)
|
|
|
- updateSlot(p.first);
|
|
|
-
|
|
|
- if(redrawParent)
|
|
|
- updateParentWindow();
|
|
|
+ return locked;
|
|
|
}
|
|
|
|
|
|
-void CArtifactsOfHero::updateBackpackSlots(bool redrawParent)
|
|
|
+void CHeroArtPlace::selectSlot(bool on)
|
|
|
{
|
|
|
- for(auto artPlace : backpack)
|
|
|
- updateSlot(artPlace->slotID);
|
|
|
- scrollBackpack(0);
|
|
|
+ if(marked == on)
|
|
|
+ return;
|
|
|
|
|
|
- if(redrawParent)
|
|
|
- updateParentWindow();
|
|
|
+ marked = on;
|
|
|
+ if(on)
|
|
|
+ selection->enable();
|
|
|
+ else
|
|
|
+ selection->disable();
|
|
|
}
|
|
|
|
|
|
-const CGHeroInstance * CArtifactsOfHero::getHero() const
|
|
|
+bool CHeroArtPlace::isMarked() const
|
|
|
{
|
|
|
- return curHero;
|
|
|
+ return marked;
|
|
|
}
|
|
|
|
|
|
-void CArtifactsOfHero::updateSlot(ArtifactPosition slotID)
|
|
|
+void CHeroArtPlace::clickLeft(tribool down, bool previousState)
|
|
|
{
|
|
|
- setSlotData(getArtPlace(slotID), slotID);
|
|
|
-}
|
|
|
+ if(down || !previousState)
|
|
|
+ return;
|
|
|
|
|
|
-CArtifactHolder::CArtifactHolder()
|
|
|
-{
|
|
|
+ if(leftClickCallback)
|
|
|
+ leftClickCallback(*this);
|
|
|
}
|
|
|
|
|
|
-void CWindowWithArtifacts::addSet(std::shared_ptr<CArtifactsOfHero> artSet)
|
|
|
-{
|
|
|
- artSets.emplace_back(artSet);
|
|
|
-}
|
|
|
-
|
|
|
-std::shared_ptr<CArtifactsOfHero::SCommonPart> CWindowWithArtifacts::getCommonPart()
|
|
|
+void CHeroArtPlace::clickRight(tribool down, bool previousState)
|
|
|
{
|
|
|
- for(auto artSetWeak : artSets)
|
|
|
+ if(down)
|
|
|
{
|
|
|
- std::shared_ptr<CArtifactsOfHero> realPtr = artSetWeak.lock();
|
|
|
- if(realPtr)
|
|
|
- return realPtr->commonInfo;
|
|
|
+ if(rightClickCallback)
|
|
|
+ rightClickCallback(*this);
|
|
|
}
|
|
|
-
|
|
|
- return std::shared_ptr<CArtifactsOfHero::SCommonPart>();
|
|
|
}
|
|
|
|
|
|
-void CWindowWithArtifacts::artifactRemoved(const ArtifactLocation &artLoc)
|
|
|
+void CHeroArtPlace::showAll(SDL_Surface* to)
|
|
|
{
|
|
|
- for(auto artSetWeak : artSets)
|
|
|
+ if(ourArt)
|
|
|
{
|
|
|
- std::shared_ptr<CArtifactsOfHero> realPtr = artSetWeak.lock();
|
|
|
- if(realPtr)
|
|
|
- realPtr->artifactRemoved(artLoc);
|
|
|
+ CIntObject::showAll(to);
|
|
|
}
|
|
|
-}
|
|
|
-
|
|
|
-void CWindowWithArtifacts::artifactMoved(const ArtifactLocation &artLoc, const ArtifactLocation &destLoc, bool withRedraw)
|
|
|
-{
|
|
|
- CArtifactsOfHero * destaoh = nullptr;
|
|
|
|
|
|
- for(auto artSetWeak : artSets)
|
|
|
+ if(marked && active)
|
|
|
{
|
|
|
- std::shared_ptr<CArtifactsOfHero> realPtr = artSetWeak.lock();
|
|
|
- if(realPtr)
|
|
|
+ // Draw vertical bars.
|
|
|
+ for(int i = 0; i < pos.h; ++i)
|
|
|
{
|
|
|
- realPtr->artifactMoved(artLoc, destLoc, withRedraw);
|
|
|
- if(destLoc.isHolder(realPtr->getHero()))
|
|
|
- destaoh = realPtr.get();
|
|
|
+ CSDL_Ext::putPixelWithoutRefresh(to, pos.x, pos.y + i, 240, 220, 120);
|
|
|
+ CSDL_Ext::putPixelWithoutRefresh(to, pos.x + pos.w - 1, pos.y + i, 240, 220, 120);
|
|
|
}
|
|
|
- }
|
|
|
|
|
|
- //Make sure the status bar is updated so it does not display old text
|
|
|
- if(destaoh != nullptr && destaoh->getArtPlace(destLoc.slot) != nullptr)
|
|
|
- {
|
|
|
- destaoh->getArtPlace(destLoc.slot)->hover(true);
|
|
|
+ // Draw horizontal bars.
|
|
|
+ for(int i = 0; i < pos.w; ++i)
|
|
|
+ {
|
|
|
+ CSDL_Ext::putPixelWithoutRefresh(to, pos.x + i, pos.y, 240, 220, 120);
|
|
|
+ CSDL_Ext::putPixelWithoutRefresh(to, pos.x + i, pos.y + pos.h - 1, 240, 220, 120);
|
|
|
+ }
|
|
|
}
|
|
|
}
|
|
|
|
|
|
-void CWindowWithArtifacts::artifactDisassembled(const ArtifactLocation &artLoc)
|
|
|
+void CHeroArtPlace::setArtifact(const CArtifactInstance * art)
|
|
|
{
|
|
|
- for(auto artSetWeak : artSets)
|
|
|
+ setInternals(art);
|
|
|
+ if(art)
|
|
|
{
|
|
|
- std::shared_ptr<CArtifactsOfHero> realPtr = artSetWeak.lock();
|
|
|
- if(realPtr)
|
|
|
- realPtr->artifactUpdateSlots(artLoc);
|
|
|
- }
|
|
|
-}
|
|
|
+ image->setFrame(locked ? ArtifactID::ART_LOCK : art->artType->getIconIndex());
|
|
|
|
|
|
-void CWindowWithArtifacts::artifactAssembled(const ArtifactLocation &artLoc)
|
|
|
-{
|
|
|
- for(auto artSetWeak : artSets)
|
|
|
- {
|
|
|
- std::shared_ptr<CArtifactsOfHero> realPtr = artSetWeak.lock();
|
|
|
- if(realPtr)
|
|
|
- realPtr->artifactUpdateSlots(artLoc);
|
|
|
+ if(locked) // Locks should appear as empty.
|
|
|
+ hoverText = CGI->generaltexth->allTexts[507];
|
|
|
+ else
|
|
|
+ hoverText = boost::str(boost::format(CGI->generaltexth->heroscrn[1]) % ourArt->artType->getNameTranslated());
|
|
|
}
|
|
|
-}
|
|
|
-
|
|
|
-void CArtifactsOfHero::SCommonPart::Artpos::clear()
|
|
|
-{
|
|
|
- slotID = ArtifactPosition::PRE_FIRST;
|
|
|
- AOH = nullptr;
|
|
|
- art = nullptr;
|
|
|
-}
|
|
|
-
|
|
|
-void CArtifactsOfHero::SCommonPart::Artpos::setTo(const CHeroArtPlace *place, bool dontTakeBackpack)
|
|
|
-{
|
|
|
- slotID = place->slotID;
|
|
|
- AOH = place->ourOwner;
|
|
|
-
|
|
|
- if(ArtifactUtils::isSlotBackpack(slotID) && dontTakeBackpack)
|
|
|
- art = nullptr;
|
|
|
else
|
|
|
- art = place->ourArt;
|
|
|
-}
|
|
|
-
|
|
|
-bool CArtifactsOfHero::SCommonPart::Artpos::operator==(const ArtifactLocation &al) const
|
|
|
-{
|
|
|
- if(!AOH)
|
|
|
- return false;
|
|
|
- bool ret = al.isHolder(AOH->curHero) && al.slot == slotID;
|
|
|
-
|
|
|
- //assert(al.getArt() == art);
|
|
|
- return ret;
|
|
|
-}
|
|
|
-
|
|
|
-bool CArtifactsOfHero::SCommonPart::Artpos::valid()
|
|
|
-{
|
|
|
- assert(AOH && art);
|
|
|
- return art == AOH->curHero->getArt(slotID);
|
|
|
-}
|
|
|
-
|
|
|
-CArtPlace::CArtPlace(Point position, const CArtifactInstance * Art) : ourArt(Art)
|
|
|
-{
|
|
|
- image = nullptr;
|
|
|
- pos += position;
|
|
|
- pos.w = pos.h = 44;
|
|
|
-}
|
|
|
-
|
|
|
-void CArtPlace::clickLeft(tribool down, bool previousState)
|
|
|
-{
|
|
|
- LRClickableAreaWTextComp::clickLeft(down, previousState);
|
|
|
-}
|
|
|
-
|
|
|
-void CArtPlace::clickRight(tribool down, bool previousState)
|
|
|
-{
|
|
|
- LRClickableAreaWTextComp::clickRight(down, previousState);
|
|
|
-}
|
|
|
-
|
|
|
-CCommanderArtPlace::CCommanderArtPlace(Point position, const CGHeroInstance * commanderOwner, ArtifactPosition artSlot, const CArtifactInstance * Art) : CArtPlace(position, Art), commanderOwner(commanderOwner), commanderSlotID(artSlot.num)
|
|
|
-{
|
|
|
- createImage();
|
|
|
- setArtifact(Art);
|
|
|
+ {
|
|
|
+ lockSlot(false);
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
-void CCommanderArtPlace::clickLeft(tribool down, bool previousState)
|
|
|
+void CHeroArtPlace::addCombinedArtInfo(std::map<const CArtifact*, int> & arts)
|
|
|
{
|
|
|
- if (ourArt && text.size() && down)
|
|
|
- LOCPLINT->showYesNoDialog(CGI->generaltexth->translate("vcmi.commanderWindow.artifactMessage"), [this](){ returnArtToHeroCallback(); }, [](){});
|
|
|
-}
|
|
|
-
|
|
|
-void CCommanderArtPlace::clickRight(tribool down, bool previousState)
|
|
|
-{
|
|
|
- if (ourArt && text.size() && down)
|
|
|
- CArtPlace::clickRight(down, previousState);
|
|
|
+ for(const auto & combinedArt : arts)
|
|
|
+ {
|
|
|
+ std::string artList;
|
|
|
+ text += "\n\n";
|
|
|
+ text += "{" + combinedArt.first->getNameTranslated() + "}";
|
|
|
+ if(arts.size() == 1)
|
|
|
+ {
|
|
|
+ for(const auto part : *combinedArt.first->constituents)
|
|
|
+ artList += "\n" + part->getNameTranslated();
|
|
|
+ }
|
|
|
+ text += " (" + boost::str(boost::format("%d") % combinedArt.second) + " / " +
|
|
|
+ boost::str(boost::format("%d") % combinedArt.first->constituents->size()) + ")" + artList;
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
-void CCommanderArtPlace::createImage()
|
|
|
+void CHeroArtPlace::createImage()
|
|
|
{
|
|
|
OBJECT_CONSTRUCTION_CAPTURING(255-DISPOSE);
|
|
|
|
|
|
- int imageIndex = 0;
|
|
|
- if(ourArt)
|
|
|
+ si32 imageIndex = 0;
|
|
|
+
|
|
|
+ if(locked)
|
|
|
+ imageIndex = ArtifactID::ART_LOCK;
|
|
|
+ else if(ourArt)
|
|
|
imageIndex = ourArt->artType->getIconIndex();
|
|
|
|
|
|
image = std::make_shared<CAnimImage>("artifact", imageIndex);
|
|
|
if(!ourArt)
|
|
|
image->disable();
|
|
|
+
|
|
|
+ selection = std::make_shared<CAnimImage>("artifact", ArtifactID::ART_SELECTION);
|
|
|
+ selection->disable();
|
|
|
}
|
|
|
|
|
|
-void CCommanderArtPlace::returnArtToHeroCallback()
|
|
|
+bool ArtifactUtilsClient::askToAssemble(const CGHeroInstance * hero, const ArtifactPosition & slot)
|
|
|
{
|
|
|
- ArtifactPosition artifactPos = commanderSlotID;
|
|
|
- ArtifactPosition freeSlot = ArtifactUtils::getArtBackpackPosition(commanderOwner, ourArt->getTypeId());
|
|
|
- if(freeSlot == ArtifactPosition::PRE_FIRST)
|
|
|
- {
|
|
|
- LOCPLINT->showInfoDialog(CGI->generaltexth->translate("core.genrltxt.152"));
|
|
|
- }
|
|
|
- else
|
|
|
+ assert(hero);
|
|
|
+ const auto art = hero->getArt(slot);
|
|
|
+ assert(art);
|
|
|
+ auto assemblyPossibilities = ArtifactUtils::assemblyPossibilities(hero, art->getTypeId(), ArtifactUtils::isSlotEquipment(slot));
|
|
|
+
|
|
|
+ for(const auto combinedArt : assemblyPossibilities)
|
|
|
{
|
|
|
- ArtifactLocation src(commanderOwner->commander.get(), artifactPos);
|
|
|
- ArtifactLocation dst(commanderOwner, freeSlot);
|
|
|
+ LOCPLINT->showArtifactAssemblyDialog(
|
|
|
+ art->artType,
|
|
|
+ combinedArt,
|
|
|
+ std::bind(&CCallback::assembleArtifacts, LOCPLINT->cb.get(), hero, slot, true, combinedArt->getId()));
|
|
|
|
|
|
- if(ourArt->canBePutAt(dst, true))
|
|
|
- {
|
|
|
- LOCPLINT->cb->swapArtifacts(src, dst);
|
|
|
- setArtifact(nullptr);
|
|
|
- parent->redraw();
|
|
|
- }
|
|
|
+ if(assemblyPossibilities.size() > 2)
|
|
|
+ logGlobal->warn("More than one possibility of assembling on %s... taking only first", art->artType->getNameTranslated());
|
|
|
+ return true;
|
|
|
}
|
|
|
+ return false;
|
|
|
}
|
|
|
|
|
|
-void CCommanderArtPlace::setArtifact(const CArtifactInstance * art)
|
|
|
+bool ArtifactUtilsClient::askToDisassemble(const CGHeroInstance * hero, const ArtifactPosition & slot)
|
|
|
{
|
|
|
- baseType = -1; //by default we don't store any component
|
|
|
- ourArt = art;
|
|
|
- if (!art)
|
|
|
- {
|
|
|
- image->disable();
|
|
|
- text.clear();
|
|
|
- return;
|
|
|
- }
|
|
|
-
|
|
|
- image->enable();
|
|
|
- image->setFrame(art->artType->getIconIndex());
|
|
|
-
|
|
|
- text = art->getDescription();
|
|
|
+ assert(hero);
|
|
|
+ const auto art = hero->getArt(slot);
|
|
|
+ assert(art);
|
|
|
|
|
|
- if (art->artType->getId() == ArtifactID::SPELL_SCROLL)
|
|
|
- {
|
|
|
- int spellID = art->getScrollSpellID();
|
|
|
- if (spellID >= 0)
|
|
|
- {
|
|
|
- //add spell component info (used to provide a pic in r-click popup)
|
|
|
- baseType = CComponent::spell;
|
|
|
- type = spellID;
|
|
|
- bonusValue = 0;
|
|
|
- }
|
|
|
- }
|
|
|
- else
|
|
|
+ if(art->canBeDisassembled())
|
|
|
{
|
|
|
- baseType = CComponent::artifact;
|
|
|
- type = art->artType->getId();
|
|
|
- bonusValue = 0;
|
|
|
+ if(ArtifactUtils::isSlotBackpack(slot) && !ArtifactUtils::isBackpackFreeSlots(hero, art->artType->constituents->size() - 1))
|
|
|
+ return false;
|
|
|
+
|
|
|
+ LOCPLINT->showArtifactAssemblyDialog(
|
|
|
+ art->artType,
|
|
|
+ nullptr,
|
|
|
+ std::bind(&CCallback::assembleArtifacts, LOCPLINT->cb.get(), hero, slot, false, ArtifactID()));
|
|
|
+ return true;
|
|
|
}
|
|
|
+ return false;
|
|
|
}
|