diff --git a/client/CPlayerInterface.cpp b/client/CPlayerInterface.cpp index 2dd678c9f..a9ae9ae59 100644 --- a/client/CPlayerInterface.cpp +++ b/client/CPlayerInterface.cpp @@ -32,6 +32,7 @@ #include "../mapHandler.h" #include "../timeHandler.h" #include +#include #include #include #include @@ -1098,6 +1099,43 @@ void CPlayerInterface::showGarrisonDialog( const CArmedInstance *up, const CGHer GH.pushInt(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. + * @param artifactID ID of a constituent artifact. + * @param assembleTo ID of artifact to assemble a constituent into, not used when assemble + * is false. + * @param assemble True if the artifact is to be assembled, false if it is to be disassembled. + */ +void CPlayerInterface::showArtifactAssemblyDialog (ui32 artifactID, ui32 assembleTo, bool assemble, CFunctionList onYes, CFunctionList onNo) +{ + const CArtifact &artifact = CGI->arth->artifacts[artifactID]; + std::string text = artifact.Description(); + text += "\n\n"; + std::vector scs; + + if (assemble) { + const CArtifact &assembledArtifact = CGI->arth->artifacts[assembleTo]; + + // You possess all of the components to... + text += boost::str(boost::format(CGI->generaltexth->allTexts[732]) % assembledArtifact.Name()); + + // Picture of assembled artifact at bottom. + SComponent* sc = new SComponent; + sc->type = SComponent::Etype::artifact; + sc->subtype = assembledArtifact.id; + sc->description = assembledArtifact.Description(); + sc->subtitle = assembledArtifact.Name(); + scs.push_back(sc); + } else { + // Do you wish to disassemble this artifact? + text += CGI->generaltexth->allTexts[733]; + } + + showYesNoDialog(text, scs, onYes, onNo, true); +} + void CPlayerInterface::requestRealized( PackageApplied *pa ) { if(stillMoveHero.get() == DURING_MOVE) diff --git a/client/CPlayerInterface.h b/client/CPlayerInterface.h index 0bf3ca00b..d6578c284 100644 --- a/client/CPlayerInterface.h +++ b/client/CPlayerInterface.h @@ -159,6 +159,7 @@ public: void showShipyardDialog(const IShipyard *obj); //obj may be town or shipyard; void showBlockingDialog(const std::string &text, const std::vector &components, ui32 askID, int soundID, bool selection, bool cancel); //Show a dialog, player must take decision. If selection then he has to choose between one of given components, if cancel he is allowed to not choose. After making choice, CCallback::selectionMade should be called with number of selected component (1 - n) or 0 for cancel (if allowed) and askID. void showGarrisonDialog(const CArmedInstance *up, const CGHeroInstance *down, bool removableUnits, boost::function &onEnd); + void showArtifactAssemblyDialog(ui32 artifactID, ui32 assembleTo, bool assemble, CFunctionList onYes, CFunctionList onNo); void showPuzzleMap(); void tileHidden(const std::set &pos); //called when given tiles become hidden under fog of war void tileRevealed(const std::set &pos); //called when fog of war disappears from given tiles diff --git a/client/GUIClasses.cpp b/client/GUIClasses.cpp index 335bf5d5a..4aeccc771 100644 --- a/client/GUIClasses.cpp +++ b/client/GUIClasses.cpp @@ -3692,24 +3692,51 @@ void CArtPlace::clickLeft(tribool down, bool previousState) void CArtPlace::clickRight(tribool down, bool previousState) { if(ourArt && !locked() && text.size()) { //if there is no description or it's a lock, do nothing ;] - LRClickableAreaWTextComp::clickRight(down, previousState); + if (slotID < 19) { + selectedNo = false; - /*if (ourArt->constituentOf != NULL) { - BOOST_FOREACH(ui32 combination, *ourArt->constituentOf) { - if (ourArt->canBeAssembledTo(ourOwner->curHero->artifWorn, combination)) { - LOCPLINT->cb->assembleArtifacts(ourOwner->curHero, slotID, true, combination); - return; + // If the artifact can be assembled, display dialog. + if (ourArt->constituentOf != NULL) { + BOOST_FOREACH(ui32 combination, *ourArt->constituentOf) { + if (ourArt->canBeAssembledTo(ourOwner->curHero->artifWorn, combination)) { + LOCPLINT->showArtifactAssemblyDialog( + ourArt->id, + combination, + true, + boost::bind(&CCallback::assembleArtifacts, LOCPLINT->cb, ourOwner->curHero, slotID, true, combination), + boost::bind(&CArtPlace::userSelectedNo, this)); + if (!selectedNo) + return; + } } } + + // Otherwise if the artifact can be diasassembled, display dialog. + if (ourArt->constituents != NULL) { + LOCPLINT->showArtifactAssemblyDialog( + ourArt->id, + 0, + false, + boost::bind(&CCallback::assembleArtifacts, LOCPLINT->cb, ourOwner->curHero, slotID, false, 0), + boost::bind(&CArtPlace::userSelectedNo, this)); + if (!selectedNo) + return; + } } - if (ourArt->constituents != NULL) { - LOCPLINT->cb->assembleArtifacts(ourOwner->curHero, slotID, false, 0); - return; - }*/ + // Lastly just show the artifact description. + LRClickableAreaWTextComp::clickRight(down, previousState); } } +/** + * Helper function to catch when a user selects no in an artifact assembly dialog. + */ +void CArtPlace::userSelectedNo () +{ + selectedNo = true; +} + /** * Selects artifact slot so that the containing artifact looks like it's picked up. */ diff --git a/client/GUIClasses.h b/client/GUIClasses.h index 9a302b9d6..ca12a560b 100644 --- a/client/GUIClasses.h +++ b/client/GUIClasses.h @@ -749,6 +749,7 @@ public: ui16 slotID; //0 head 1 shoulders 2 neck 3 right hand 4 left hand 5 torso 6 right ring 7 left ring 8 feet 9 misc. slot 1 10 misc. slot 2 11 misc. slot 3 12 misc. slot 4 13 ballista (war machine 1) 14 ammo cart (war machine 2) 15 first aid tent (war machine 3) 16 catapult 17 spell book 18 misc. slot 5 19+ backpack slots bool marked; + bool selectedNo; CArtifactsOfHero * ourOwner; const CArtifact * ourArt; CArtPlace(const CArtifact * Art); //c-tor @@ -761,6 +762,7 @@ public: void show(SDL_Surface * to); bool fitsHere (const CArtifact * art); //returns true if given artifact can be placed here bool locked () const; + void userSelectedNo (); ~CArtPlace(); //d-tor }; diff --git a/server/CGameHandler.cpp b/server/CGameHandler.cpp index d04f511c3..06fdf01ac 100644 --- a/server/CGameHandler.cpp +++ b/server/CGameHandler.cpp @@ -2680,7 +2680,7 @@ bool CGameHandler::assembleArtifacts (si32 heroID, ui16 artifactSlot, bool assem sha.artifWorn = hero->artifWorn; if (assemble) { - if (VLC->arth->artifacts.size() >= assembleTo) { + if (VLC->arth->artifacts.size() < assembleTo) { complain("Illegal artifact to assemble to."); return false; } @@ -2718,13 +2718,18 @@ bool CGameHandler::assembleArtifacts (si32 heroID, ui16 artifactSlot, bool assem } } } else { + bool destConsumed = false; // Determines which constituent that will be counted for together with the artifact. BOOST_FOREACH(ui32 constituentID, *destArtifact->constituents) { const CArtifact &constituent = VLC->arth->artifacts[constituentID]; BOOST_REVERSE_FOREACH(ui16 slotID, constituent.possibleSlots) { if (sha.artifWorn.find(slotID) != sha.artifWorn.end()) { - if (sha.artifWorn[slotID] == 145 || slotID == artifactSlot) + if (sha.artifWorn[slotID] == 145 || (!destConsumed && slotID == artifactSlot)) { + if (slotID == artifactSlot) + destConsumed = true; sha.artifWorn[slotID] = constituentID; + break; + } } } }