diff --git a/CCallback.cpp b/CCallback.cpp index 217f8a4dd..59e14e758 100644 --- a/CCallback.cpp +++ b/CCallback.cpp @@ -416,6 +416,16 @@ bool CCallback::swapArtifacts(const CGHeroInstance * hero1, ui16 pos1, const CGH return true; } +bool CCallback::setArtifact(const CGHeroInstance * hero, ui16 pos, int artID) +{ + if(player != hero->tempOwner) + return false; + + SetArtifact sa(hero->id, pos, artID); + sendRequest(&sa); + return true; +} + bool CCallback::buildBuilding(const CGTownInstance *town, si32 buildingID) { CGTownInstance * t = const_cast(town); diff --git a/CCallback.h b/CCallback.h index 809302222..f9899d382 100644 --- a/CCallback.h +++ b/CCallback.h @@ -224,6 +224,7 @@ public: int splitStack(const CArmedInstance *s1, const CArmedInstance *s2, int p1, int p2, int val); bool dismissHero(const CGHeroInstance * hero); bool swapArtifacts(const CGHeroInstance * hero1, ui16 pos1, const CGHeroInstance * hero2, ui16 pos2); + bool setArtifact(const CGHeroInstance * hero, ui16 pos, int artID); bool buildBuilding(const CGTownInstance *town, si32 buildingID); void recruitCreatures(const CGObjectInstance *obj, ui32 ID, ui32 amount); bool dismissCreature(const CArmedInstance *obj, int stackPos); diff --git a/client/CHeroWindow.cpp b/client/CHeroWindow.cpp index fabc8bc41..1fa43c39d 100644 --- a/client/CHeroWindow.cpp +++ b/client/CHeroWindow.cpp @@ -55,7 +55,6 @@ CHeroWindow::CHeroWindow(int playerColor): artifs = new CArtifactsOfHero(pos); artifs->commonInfo = new CArtifactsOfHero::SCommonPart; artifs->commonInfo->participants.insert(artifs); - artifs->commonInfo->activeArtPlace = NULL; garr = NULL; ourBar = new CStatusBar(pos.x+72, pos.y+567, "ADROLLVR.bmp", 660); @@ -146,6 +145,7 @@ CHeroWindow::~CHeroWindow() delete garr; delete ourBar; + artifs->rollback(); delete artifs->commonInfo; artifs->commonInfo = NULL; //to prevent heap corruption delete artifs; @@ -506,6 +506,7 @@ void CHeroWindow::dispose() curBack = NULL; curHero = NULL; + artifs->rollback(); artifs->dispose(); } diff --git a/client/GUIClasses.cpp b/client/GUIClasses.cpp index 3614da8da..0e137238a 100644 --- a/client/GUIClasses.cpp +++ b/client/GUIClasses.cpp @@ -3497,7 +3497,7 @@ CRClickPopupInt::~CRClickPopupInt() CGI->curh->show(); } -CArtPlace::CArtPlace(const CArtifact* Art): active(false), clicked(false), marked(false), ourArt(Art)/*, +CArtPlace::CArtPlace(const CArtifact* Art): active(false), marked(false), ourArt(Art)/*, spellBook(false), warMachine1(false), warMachine2(false), warMachine3(false), warMachine4(false),misc1(false), misc2(false), misc3(false), misc4(false), misc5(false), feet(false), lRing(false), rRing(false), torso(false), @@ -3520,7 +3520,7 @@ void CArtPlace::clickLeft(tribool down, bool previousState) //LRClickableAreaWTextComp::clickLeft(down); // If clicked on spellbook, open it only if no artifact is held at the moment. - if(ourArt && !down && previousState && !ourOwner->commonInfo->activeArtPlace) + if(ourArt && !down && previousState && !ourOwner->commonInfo->srcAOH) { if(ourArt->id == 0) { @@ -3528,11 +3528,11 @@ void CArtPlace::clickLeft(tribool down, bool previousState) GH.pushInt(spellWindow); } } - if(!down && (!clicked || ourOwner->commonInfo->srcSlotID >= 19) && previousState) //not clicked before + if (!down && previousState) { if(ourArt && ourArt->id == 0) return; //this is handled separately - if(!ourOwner->commonInfo->activeArtPlace) //nothing has been clicked + if(!ourOwner->commonInfo->srcAOH) //nothing has been clicked { if(ourArt) //to prevent selecting empty slots (bugfix to what GrayFace reported) { @@ -3567,39 +3567,36 @@ void CArtPlace::clickLeft(tribool down, bool previousState) default: ourOwner->commonInfo->destAOH = ourOwner; ourOwner->commonInfo->destSlotID = slotID; + ourOwner->commonInfo->destArtifact = NULL; - LOCPLINT->cb->swapArtifacts( - ourOwner->commonInfo->activeArtPlace->ourOwner->curHero, - ourOwner->commonInfo->srcSlotID, + LOCPLINT->cb->setArtifact( ourOwner->curHero, - slotID); + slotID, + ourOwner->commonInfo->srcArtifact->id); - ourOwner->commonInfo->activeArtPlace->deselect(); break; } } //check if swap is possible - else if(this->fitsHere(ourOwner->commonInfo->srcArtifact) && ourOwner->commonInfo->activeArtPlace->fitsHere(this->ourArt)) + else if (this->fitsHere(ourOwner->commonInfo->srcArtifact)) { ourOwner->commonInfo->destAOH = ourOwner; ourOwner->commonInfo->destSlotID = slotID; + ourOwner->commonInfo->destArtifact = ourArt; - LOCPLINT->cb->swapArtifacts( - ourOwner->commonInfo->activeArtPlace->ourOwner->curHero, - ourOwner->commonInfo->srcSlotID, + LOCPLINT->cb->setArtifact( ourOwner->curHero, - slotID); - - ourOwner->commonInfo->activeArtPlace->deselect(); + slotID, + ourOwner->commonInfo->srcArtifact->id); } } } - else if(!down && clicked) + /*else if(!down && clicked) { if(ourArt && ourArt->id == 0) return; //this is handled separately deselect(); - } + }*/ //ClickableL::clickLeft(down); } @@ -3615,20 +3612,19 @@ void CArtPlace::clickRight(tribool down, bool previousState) void CArtPlace::select () { CGI->curh->dragAndDropCursor(graphics->artDefs->ourImages[ourArt->id].bitmap); - clicked = true; ourOwner->markPossibleSlots(ourArt); - ourOwner->commonInfo->activeArtPlace = this; ourOwner->commonInfo->srcArtifact = ourArt; ourOwner->commonInfo->srcSlotID = slotID; ourOwner->commonInfo->srcAOH = ourOwner; if (slotID >= 19) { - // Updates backpack, possibly correcting the position. + // Correcting position in backpack. ourOwner->scrollBackpack(-(slotID - 19 < ourOwner->backpackPos)); } else { ourOwner->eraseSlotData(this, slotID); } + LOCPLINT->cb->setArtifact(ourOwner->curHero, slotID, -1); } /** @@ -3636,14 +3632,8 @@ void CArtPlace::select () */ void CArtPlace::deselect () { - clicked = false; CGI->curh->dragAndDropCursor(NULL); ourOwner->unmarkSlots(); - ourOwner->commonInfo->activeArtPlace = NULL; - - // If a worn artifact is deselected, restore it's picture. - if (slotID < 19 && !ourOwner->commonInfo->destAOH) - ourOwner->setSlotData(this, slotID); } void CArtPlace::deactivate() @@ -3658,10 +3648,9 @@ void CArtPlace::deactivate() void CArtPlace::show(SDL_Surface *to) { - if(ourArt && (!clicked || slotID >= 19)) - { + if (ourArt) blitAt(graphics->artDefs->ourImages[ourArt->id].bitmap, pos.x, pos.y, to); - } + if(marked && active) { // Draw vertical bars. @@ -3685,8 +3674,8 @@ bool CArtPlace::fitsHere(const CArtifact * art) return true; // Anything can be placed in the backpack, except War Machines. - if(slotID > 18 && !(art->id >= 3 && art->id <= 6) - || vstd::contains(art->possibleSlots,slotID)) + if (slotID >= 19 && !CGI->arth->isBigArtifact(art->id) + || vstd::contains(art->possibleSlots, slotID)) { return true; } @@ -3697,10 +3686,6 @@ bool CArtPlace::fitsHere(const CArtifact * art) CArtPlace::~CArtPlace() { deactivate(); - - // Make sure a currently held artifact does not affect the outside. - if (clicked) - CGI->curh->dragAndDropCursor(NULL); } void LClickableArea::activate() @@ -3867,124 +3852,141 @@ void CArtifactsOfHero::setHero(const CGHeroInstance * hero) { // An update is made, rather than initialization. if (curHero == hero) { - // Compensate backpack pos if an artifact is insertad before it. + // Compensate backpack pos if an artifact was insertad before it. if (commonInfo->destSlotID >= 19 && commonInfo->destAOH == this && commonInfo->destSlotID - 19 < backpackPos) { backpackPos++; } + + // A swap was made, make the replaced artifact into current selected. + if (commonInfo->destSlotID < 19 && commonInfo->destArtifact) { + // Source <- Dest + commonInfo->srcAOH = commonInfo->destAOH; + commonInfo->srcArtifact = commonInfo->destArtifact; + commonInfo->srcSlotID = -1; // The artifact's original place is taken now. + + // Reset destination parameters. + commonInfo->destAOH = NULL; + commonInfo->destArtifact = NULL; + commonInfo->destSlotID = -1; + + CGI->curh->dragAndDropCursor( + graphics->artDefs->ourImages[commonInfo->srcArtifact->id].bitmap); + markPossibleSlots(commonInfo->srcArtifact); + } else if (commonInfo->destAOH != NULL) { + // Reset all parameters. + commonInfo->srcAOH = NULL; + commonInfo->srcArtifact = NULL; + commonInfo->srcSlotID = -1; + commonInfo->destAOH = NULL; + commonInfo->destArtifact = NULL; + commonInfo->destSlotID = -1; + + CGI->curh->dragAndDropCursor(NULL); + unmarkSlots(); + } + } else { + rollback(); } - commonInfo->srcAOH = NULL; - commonInfo->srcArtifact = NULL; - commonInfo->srcSlotID = 0; // Can be anything that's not in backpack range. - commonInfo->destAOH = NULL; - commonInfo->destSlotID = 0; - curHero = hero; - backpackSize = curHero->artifacts.size(); - // Remove any previously allocated slots. - for(size_t g=0; g slotPos; if (curHero->artifacts.size() > 0) backpackPos %= curHero->artifacts.size(); else backpackPos = 0; - slotPos += genRect(44,44,pos.x+509,pos.y+30), genRect(44,44,pos.x+567,pos.y+240), genRect(44,44,pos.x+509,pos.y+80), - genRect(44,44,pos.x+383,pos.y+68), genRect(44,44,pos.x+564,pos.y+183), genRect(44,44,pos.x+509,pos.y+130), - genRect(44,44,pos.x+431,pos.y+68), genRect(44,44,pos.x+610,pos.y+183), genRect(44,44,pos.x+515,pos.y+295), - genRect(44,44,pos.x+383,pos.y+143), genRect(44,44,pos.x+399,pos.y+194), genRect(44,44,pos.x+415,pos.y+245), - genRect(44,44,pos.x+431,pos.y+296), genRect(44,44,pos.x+564,pos.y+30), genRect(44,44,pos.x+610,pos.y+30), - genRect(44,44,pos.x+610,pos.y+76), genRect(44,44,pos.x+610,pos.y+122), genRect(44,44,pos.x+610,pos.y+310), - genRect(44,44,pos.x+381,pos.y+296); - - // Fill the slots for worn artifacts. + // Fill the slots for worn artifacts and backpack. for (int g = 0; g < 19 ; g++) - { - artWorn[g] = new CArtPlace(hero->getArt(g)); - artWorn[g]->pos = slotPos[g]; - artWorn[g]->ourOwner = this; setSlotData(artWorn[g], g); - } - - // Fill the slots for the backpack. - for(size_t s=0; s<5; ++s) - { - CArtPlace * add = new CArtPlace(NULL); - - add->ourOwner = this; - add->pos.x = pos.x + 403 + 46*s; - add->pos.y = pos.y + 365; - add->pos.h = add->pos.w = 44; - - if (s < curHero->artifacts.size()) - setSlotData(add, 19 + (s + backpackPos)%curHero->artifacts.size()); - else - setSlotData(add, 19 + s); - backpack.push_back(add); - } - commonInfo->activeArtPlace = NULL; + scrollBackpack(0); //blocking scrolling if there is not enough artifacts to scroll leftArtRoll->block(curHero->artifacts.size() <= backpack.size()); rightArtRoll->block(curHero->artifacts.size() <= backpack.size()); } +/** + * Any held artifacts, marked slots etc. will be restored to it's original way. + */ +void CArtifactsOfHero::rollback() +{ + if (curHero != NULL) { + // Restore any held artifact to it's original position. + if (commonInfo->destArtifact && commonInfo->destAOH == this) { + // For an unlikely race condition scenario, put swapped artifact into backpack. + LOCPLINT->cb->setArtifact( + curHero, + 19 + curHero->artifacts.size(), + commonInfo->destArtifact->id); + } + else if (commonInfo->srcArtifact && commonInfo->srcAOH == this) { + if (commonInfo->srcSlotID != -1) { // Held artifact, just put it back to it's spot. + LOCPLINT->cb->setArtifact( + curHero, + commonInfo->srcSlotID, + commonInfo->srcArtifact->id); + } else { // Swapped artifact. + // Wear the artifact in a suitable spot. + ui16 i = 0; + for (; i < 19; i++) { + if (artWorn[i]->fitsHere(commonInfo->srcArtifact) + && curHero->artifWorn.find(i) == curHero->artifWorn.end()) + { + LOCPLINT->cb->setArtifact( + curHero, i, commonInfo->srcArtifact->id); + break; + } + } + + // If it can't be worn, put it in the backpack. + if (i == 19) + LOCPLINT->cb->setArtifact( + curHero, + 19 + curHero->artifacts.size(), + commonInfo->srcArtifact->id); + } + } + } + unmarkSlots(); + backpackPos = 0; + + commonInfo->srcAOH = NULL; + commonInfo->srcArtifact = NULL; + commonInfo->srcSlotID = -1; + commonInfo->destAOH = NULL; + commonInfo->destArtifact = NULL; + commonInfo->destSlotID = -1; + + CGI->curh->dragAndDropCursor(NULL); +} + void CArtifactsOfHero::dispose() { curHero = NULL; - for(size_t g=0; gactiveArtPlace = NULL; } void CArtifactsOfHero::scrollBackpack(int dir) { backpackPos += dir; - if (backpackPos < 0) { // No guarantee of modulus behavior with negative operands. - do { - backpackPos += curHero->artifacts.size(); - } while (backpackPos < 0); - } else { - backpackPos %= curHero->artifacts.size(); + if (curHero->artifacts.size() > 0) { + if (backpackPos < 0) { // No guarantee of modulus behavior with negative operands. + do { + backpackPos += curHero->artifacts.size(); + } while (backpackPos < 0); + } else { + backpackPos %= curHero->artifacts.size(); + } } - const int tempBackpackSize = curHero->artifacts.size() - (commonInfo->srcSlotID >= 19); - //set new data for (size_t s = 0; s < backpack.size(); ++s) { - int slotID = 19 + (s + backpackPos)%tempBackpackSize; - - // Don't show the held artifact, skip it. - if (commonInfo->srcAOH == this && commonInfo->srcSlotID >= 19 && slotID >= commonInfo->srcSlotID) - slotID++; - - if (s < tempBackpackSize) - setSlotData(backpack[s], slotID); + if (s < curHero->artifacts.size()) + setSlotData(backpack[s], 19 + (s + backpackPos)%curHero->artifacts.size()); else - eraseSlotData(backpack[s], slotID); + eraseSlotData(backpack[s], 19 + s); } - - // Activate/deactivate sliders. - leftArtRoll->block(tempBackpackSize <= backpack.size()); - rightArtRoll->block(tempBackpackSize <= backpack.size()); } /** @@ -4053,6 +4055,38 @@ CArtifactsOfHero::CArtifactsOfHero(const SDL_Rect & position) : pos = position; artWorn.resize(19); + std::vector slotPos; + slotPos += genRect(44,44,pos.x+509,pos.y+30), genRect(44,44,pos.x+567,pos.y+240), genRect(44,44,pos.x+509,pos.y+80), + genRect(44,44,pos.x+383,pos.y+68), genRect(44,44,pos.x+564,pos.y+183), genRect(44,44,pos.x+509,pos.y+130), + genRect(44,44,pos.x+431,pos.y+68), genRect(44,44,pos.x+610,pos.y+183), genRect(44,44,pos.x+515,pos.y+295), + genRect(44,44,pos.x+383,pos.y+143), genRect(44,44,pos.x+399,pos.y+194), genRect(44,44,pos.x+415,pos.y+245), + genRect(44,44,pos.x+431,pos.y+296), genRect(44,44,pos.x+564,pos.y+30), genRect(44,44,pos.x+610,pos.y+30), + genRect(44,44,pos.x+610,pos.y+76), genRect(44,44,pos.x+610,pos.y+122), genRect(44,44,pos.x+610,pos.y+310), + genRect(44,44,pos.x+381,pos.y+296); + + // Create slots for worn artifacts. + for (int g = 0; g < 19 ; g++) + { + artWorn[g] = new CArtPlace(NULL); + artWorn[g]->pos = slotPos[g]; + artWorn[g]->ourOwner = this; + eraseSlotData(artWorn[g], g); + } + + // Create slots for the backpack. + for(size_t s=0; s<5; ++s) + { + CArtPlace * add = new CArtPlace(NULL); + + add->ourOwner = this; + add->pos.x = pos.x + 403 + 46*s; + add->pos.y = pos.y + 365; + add->pos.h = add->pos.w = 44; + eraseSlotData(add, 19 + s); + + backpack.push_back(add); + } + leftArtRoll = new AdventureMapButton(std::string(), std::string(), boost::bind(&CArtifactsOfHero::scrollBackpack,this,-1), pos.x+379, pos.y+364, "hsbtns3.def", SDLK_LEFT); rightArtRoll = new AdventureMapButton(std::string(), std::string(), boost::bind(&CArtifactsOfHero::scrollBackpack,this,+1), pos.x+632, pos.y+364, "hsbtns5.def", SDLK_RIGHT); } @@ -4060,6 +4094,17 @@ CArtifactsOfHero::CArtifactsOfHero(const SDL_Rect & position) : CArtifactsOfHero::~CArtifactsOfHero() { dispose(); + for(size_t g=0; gcommonInfo = new CArtifactsOfHero::SCommonPart; artifs[0]->commonInfo->participants.insert(artifs[0]); - artifs[0]->commonInfo->activeArtPlace = NULL; artifs[0]->setHero(heroInst[0]); artifs[1] = new CArtifactsOfHero(genRect(600, 800, pos.x + 96, pos.y + 150)); artifs[1]->commonInfo = artifs[0]->commonInfo; @@ -4353,6 +4397,8 @@ CExchangeWindow::~CExchangeWindow() //d-tor delete quit; //warning: don't experiment with these =NULL lines, they prevent heap corruption! + artifs[0]->rollback(); + artifs[1]->rollback(); delete artifs[0]->commonInfo; artifs[0]->commonInfo = NULL; delete artifs[0]; diff --git a/client/GUIClasses.h b/client/GUIClasses.h index 8ee56260f..1050636eb 100644 --- a/client/GUIClasses.h +++ b/client/GUIClasses.h @@ -645,7 +645,6 @@ public: // lHand, rHand, neck, shoulders, head; //my types 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 clicked; bool marked; CArtifactsOfHero * ourOwner; const CArtifact * ourArt; @@ -666,7 +665,6 @@ class CArtifactsOfHero : public CIntObject { const CGHeroInstance * curHero; - size_t backpackSize; // Used to check differences in backpack sizes. std::vector artWorn; // 0 - head; 1 - shoulders; 2 - neck; 3 - right hand; 4 - left hand; 5 - torso; 6 - right ring; 7 - left ring; 8 - feet; 9 - misc1; 10 - misc2; 11 - misc3; 12 - misc4; 13 - mach1; 14 - mach2; 15 - mach3; 16 - mach4; 17 - spellbook; 18 - misc5 std::vector backpack; //hero's visible backpack (only 5 elements!) int backpackPos; //unmber of first art visible in backpack (in hero's vector) @@ -675,12 +673,12 @@ public: struct SCommonPart { std::set participants; // Needed to mark slots. - CArtPlace * activeArtPlace; - const CArtifact * srcArtifact; // Held artifact., technically superfluous right now. + const CArtifact * srcArtifact; // Held artifact. const CArtifactsOfHero * srcAOH; // Following two needed to uniquely identify the source. int srcSlotID; // const CArtifactsOfHero * destAOH; // For swapping. (i.e. changing what is held) int destSlotID; // Needed to determine what kind of action was last taken in setHero + const CArtifact * destArtifact; // For swapping. } * commonInfo; //when we have more than one CArtifactsOfHero in one window with exchange possibility, we use this (eg. in exchange window); to be provided externally AdventureMapButton * leftArtRoll, * rightArtRoll; @@ -691,6 +689,7 @@ public: void setHero(const CGHeroInstance * hero); void dispose(); //free resources not needed after closing windows and reset state + void rollback(); void scrollBackpack(int dir); //dir==-1 => to left; dir==1 => to right void markPossibleSlots (const CArtifact* art); void unmarkSlots (); diff --git a/hch/CArtHandler.cpp b/hch/CArtHandler.cpp index 62faec8b6..b14a3d9e1 100644 --- a/hch/CArtHandler.cpp +++ b/hch/CArtHandler.cpp @@ -38,6 +38,10 @@ const std::string & CArtifact::Description() const CArtHandler::CArtHandler() { VLC->arth = this; + + // War machines are the default big artifacts. + for (ui32 i = 3; i <= 6; i++) + bigArtifacts.insert(i); } void CArtHandler::loadArtifacts(bool onlyTxt) { diff --git a/hch/CArtHandler.h b/hch/CArtHandler.h index caabf6902..31be33856 100644 --- a/hch/CArtHandler.h +++ b/hch/CArtHandler.h @@ -2,6 +2,7 @@ #define __CARTHANDLER_H__ #include "../global.h" #include "../lib/HeroBonus.h" +#include #include #include #include @@ -43,11 +44,13 @@ class DLL_EXPORT CArtHandler //handles artifacts public: std::vector treasures, minors, majors, relics; std::vector artifacts; + std::set bigArtifacts; // Artifacts that cannot be moved to backpack, e.g. war machines. void loadArtifacts(bool onlyTxt); void sortArts(); void addBonuses(); void clear(); + bool isBigArtifact (ui32 artID) {return bigArtifacts.find(artID) != bigArtifacts.end();} static int convertMachineID(int id, bool creToArt); CArtHandler(); diff --git a/lib/CGameState.cpp b/lib/CGameState.cpp index 7adf2e929..d05e49987 100644 --- a/lib/CGameState.cpp +++ b/lib/CGameState.cpp @@ -1307,7 +1307,7 @@ void CGameState::init(StartInfo * si, Mapa * map, int Seed) players.insert(ins); } /******************RESOURCES****************************************************/ - //TODO: computer player should receive other amount of resource than computer (depending on difficulty) + //TODO: computer player should receive other amount of resource than player (depending on difficulty) std::vector startres; std::ifstream tis(DATA_DIR "/config/startres.txt"); int k; diff --git a/lib/NetPacks.h b/lib/NetPacks.h index a5d06c0f3..a7592095f 100644 --- a/lib/NetPacks.h +++ b/lib/NetPacks.h @@ -1226,6 +1226,22 @@ struct ExchangeArtifacts : public CPackForServer } }; +struct SetArtifact : public CPackForServer +{ + SetArtifact () {}; + SetArtifact (si32 hid, ui16 slot, int artID) + :hid(hid), slot(slot), artID(artID) {}; + si32 hid; + ui16 slot; + int artID; + + bool applyGh(CGameHandler *gh); + template void serialize(Handler &h, const int version) + { + h & hid & slot & artID; + } +}; + struct BuyArtifact : public CPackForServer { BuyArtifact(){}; diff --git a/lib/RegisterTypes.cpp b/lib/RegisterTypes.cpp index 7f3828504..a5b3e8945 100644 --- a/lib/RegisterTypes.cpp +++ b/lib/RegisterTypes.cpp @@ -137,6 +137,7 @@ void registerTypes3(Serializer &s) s.template registerType(); s.template registerType(); s.template registerType(); + s.template registerType(); s.template registerType(); s.template registerType(); s.template registerType(); diff --git a/server/CGameHandler.cpp b/server/CGameHandler.cpp index 304901170..e0e1abe28 100644 --- a/server/CGameHandler.cpp +++ b/server/CGameHandler.cpp @@ -2326,6 +2326,7 @@ bool CGameHandler::swapArtifacts(si32 srcHeroID, si32 destHeroID, ui16 srcSlot, return false; } + // TODO: This relates to bug #112, fix later. // Make sure the artifacts are not war machines. if ((srcSlot>=13 && srcSlot<=16) || (destSlot>=13 && destSlot<=16)) { complain("Cannot move war machine!"); @@ -2363,6 +2364,28 @@ bool CGameHandler::swapArtifacts(si32 srcHeroID, si32 destHeroID, ui16 srcSlot, return true; } +/** + * Sets a hero artifact slot to contain a specific artifact. + * + * @param artID ID of an artifact or -1 for no artifact. + */ +bool CGameHandler::setArtifact(si32 heroID, ui16 slot, int artID) +{ + CGHeroInstance *hero = gs->getHero(heroID); + + // TODO: Deal with war machine placement. + + // Perform the exchange. + SetHeroArtifacts sha; + sha.hid = heroID; + sha.artifacts = hero->artifacts; + sha.artifWorn = hero->artifWorn; + sha.setArtAtPos(slot, artID); + sendAndApply(&sha); + + return true; +} + bool CGameHandler::buyArtifact( ui32 hid, si32 aid ) { CGHeroInstance *hero = gs->getHero(hid); diff --git a/server/CGameHandler.h b/server/CGameHandler.h index 1c69045a0..d2d974fe1 100644 --- a/server/CGameHandler.h +++ b/server/CGameHandler.h @@ -155,6 +155,7 @@ public: bool tradeResources( ui32 val, ui8 player, ui32 id1, ui32 id2 ); bool buyArtifact( ui32 hid, si32 aid ); bool swapArtifacts(si32 srcHeroID, si32 destHeroID, ui16 srcSlot, ui16 destSlot); + bool setArtifact(si32 heroID, ui16 slot, int artID); bool garrisonSwap(si32 tid); bool upgradeCreature( ui32 objid, ui8 pos, ui32 upgID ); bool recruitCreatures(si32 objid, ui32 crid, ui32 cram); diff --git a/server/NetPacksServer.cpp b/server/NetPacksServer.cpp index 6d39fbc99..35f3e3ade 100644 --- a/server/NetPacksServer.cpp +++ b/server/NetPacksServer.cpp @@ -98,6 +98,12 @@ bool ExchangeArtifacts::applyGh( CGameHandler *gh ) return gh->swapArtifacts(hid1,hid2,slot1,slot2); } +bool SetArtifact::applyGh( CGameHandler *gh ) +{ + ERROR_IF_NOT_OWNS(hid); + return gh->setArtifact(hid, slot, artID); +} + bool BuyArtifact::applyGh( CGameHandler *gh ) { ERROR_IF_NOT_OWNS(hid);