diff --git a/CCallback.cpp b/CCallback.cpp index b52dcaaa8..64c403a86 100644 --- a/CCallback.cpp +++ b/CCallback.cpp @@ -17,6 +17,7 @@ #include #include #include "hch/CSpellHandler.h" +#include "hch/CArtHandler.h" #ifdef min #undef min #endif diff --git a/CCallback.h b/CCallback.h index 91e821c62..ebcb52b60 100644 --- a/CCallback.h +++ b/CCallback.h @@ -43,6 +43,7 @@ class CMapHeader; struct CGPathNode; struct CGPath; class CGGarrison; +class CArtifact; struct InfoAboutTown { diff --git a/client/CKingdomInterface.cpp b/client/CKingdomInterface.cpp index 554aa0ad4..c8d4f43ce 100644 --- a/client/CKingdomInterface.cpp +++ b/client/CKingdomInterface.cpp @@ -784,7 +784,7 @@ void CKingdomInterface::CHeroItem::setHero(const CGHeroInstance * newHero) for (int i=0; itype = hero->getArtAtPos(i); + artifacts[i]->type = hero->getArtAtPos(i)->id; if (artifacts[i]->type<0 || artifacts[i]->type == 145 ) artifacts[i]->hoverText = CGI->generaltexth->heroscrn[11]; else @@ -796,7 +796,7 @@ void CKingdomInterface::CHeroItem::setHero(const CGHeroInstance * newHero) for (int i=0; itype = hero->getArtAtPos(19+i); + backpack[i]->type = hero->getArtAtPos(19+i)->id; if (backpack[i]->type<0) backpack[i]->hoverText =""; else @@ -847,7 +847,7 @@ void CKingdomInterface::CHeroItem::scrollArts(int move) backpackPos = ( backpackPos + move + hero->artifacts.size()) % hero->artifacts.size(); for (int i=0; itype = hero->getArtAtPos(19+(backpackPos + i)%hero->artifacts.size()); + backpack[i]->type = hero->getArtAtPos(19+(backpackPos + i)%hero->artifacts.size())->id; if (backpack[i]->type<0) backpack[i]->hoverText =""; else @@ -912,7 +912,7 @@ void CKingdomInterface::CHeroItem::showAll(SDL_Surface * to) case 0://equipped arts for (int i = iter ; igetArtAtPos(i); + int artID = hero->getArtAtPos(i)->id; if (artID>=0) blitAt(graphics->artDefs->ourImages[artID].bitmap,pos.x+268+48*(i%9),pos.y+66,to); } @@ -923,7 +923,7 @@ void CKingdomInterface::CHeroItem::showAll(SDL_Surface * to) int max = hero->artifacts.size(); iter = std::min(8, max); for (size_t it = 0 ; itartDefs->ourImages[hero->artifacts[(it+backpackPos)%max]].bitmap,pos.x+293+48*it,pos.y+66,to); + blitAt(graphics->artDefs->ourImages[hero->artifacts[(it+backpackPos)%max]->id].bitmap,pos.x+293+48*it,pos.y+66,to); break; } show(to); diff --git a/client/Client.h b/client/Client.h index 1c2cc865c..042f6c9e6 100644 --- a/client/Client.h +++ b/client/Client.h @@ -113,7 +113,7 @@ public: void heroVisitCastle(int obj, int heroID){}; void stopHeroVisitCastle(int obj, int heroID){}; void giveHeroArtifact(int artid, int hid, int position){}; //pos==-1 - first free slot in backpack=0; pos==-2 - default if available or backpack - bool removeArtifact(int artid, int hid){return false;}; + bool removeArtifact(CArtifact* art, int hid){return false;}; void startBattleI(const CArmedInstance *army1, const CArmedInstance *army2, int3 tile, const CGHeroInstance *hero1, const CGHeroInstance *hero2, bool creatureBank = false, boost::function cb = 0, const CGTownInstance *town = NULL){}; //use hero=NULL for no hero void startBattleI(const CArmedInstance *army1, const CArmedInstance *army2, int3 tile, boost::function cb = 0, bool creatureBank = false){}; //if any of armies is hero, hero will be used void startBattleI(const CArmedInstance *army1, const CArmedInstance *army2, boost::function cb = 0, bool creatureBank = false){}; //if any of armies is hero, hero will be used, visitable tile of second obj is place of battle diff --git a/client/GUIClasses.cpp b/client/GUIClasses.cpp index ba56897b2..882bbb54c 100644 --- a/client/GUIClasses.cpp +++ b/client/GUIClasses.cpp @@ -2639,7 +2639,7 @@ void CTradeWindow::CTradeableItem::clickLeft(tribool down, bool previousState) movedArt = CGI->arth->artifacts[id]; aw->arts->commonInfo->srcAOH = aw->arts; aw->arts->commonInfo->srcArtifact = movedArt; - aw->arts->commonInfo->srcSlotID = 19 + vstd::findPos(aw->hero->artifacts, movedArt->id); + aw->arts->commonInfo->srcSlotID = 19 + vstd::findPos(aw->hero->artifacts, const_cast(movedArt)); aw->arts->commonInfo->destAOH = aw->arts; CGI->curh->dragAndDropCursor(graphics->artDefs->ourImages[movedArt->id].bitmap); @@ -3613,10 +3613,10 @@ void CAltarWindow::SacrificeAll() } else { - for(std::map::const_iterator i = hero->artifWorn.begin(); i != hero->artifWorn.end(); i++) + for(std::map::const_iterator i = hero->artifWorn.begin(); i != hero->artifWorn.end(); i++) { - if(i->second != 145) //ignore locks from assembled artifacts - moveFromSlotToAltar(i->first, NULL, i->second); + if(i->second->id != 145) //ignore locks from assembled artifacts + moveFromSlotToAltar(i->first, NULL, i->second->id); } SacrificeBackpack(); @@ -3769,13 +3769,13 @@ void CAltarWindow::SacrificeBackpack() for (int i = 0; i < hero->artifacts.size(); i++) { - if(vstd::contains(toOmmit, hero->artifacts[i])) + if(vstd::contains(toOmmit, hero->artifacts[i]->id)) { - toOmmit -= hero->artifacts[i]; + toOmmit -= hero->artifacts[i]->id; continue; } - putOnAltar(NULL, hero->artifacts[i]); + putOnAltar(NULL, hero->artifacts[i]->id); } arts->scrollBackpack(0); calcTotalExp(); diff --git a/hch/CArtHandler.cpp b/hch/CArtHandler.cpp index 527657ff6..7b1c73133 100644 --- a/hch/CArtHandler.cpp +++ b/hch/CArtHandler.cpp @@ -47,25 +47,31 @@ bool CArtifact::isBig () const return VLC->arth->isBigArtifact(id); } +bool CArtifact::isModable () const +{ + return (bool)dynamic_cast(this); +} + /** * Checks whether the artifact fits at a given slot. * @param artifWorn A hero's set of worn artifacts. */ -bool CArtifact::fitsAt (const std::map &artifWorn, ui16 slotID) const +bool CArtifact::fitsAt (const std::map &artifWorn, ui16 slotID) const { if (!vstd::contains(possibleSlots, slotID)) return false; // Can't put an artifact in a locked slot. - std::map::const_iterator it = artifWorn.find(slotID); - if (it != artifWorn.end() && it->second == 145) + std::map::const_iterator it = artifWorn.find(slotID); + if (it != artifWorn.end() && it->second->id == 145) return false; // Check if a combination artifact fits. // TODO: Might want a more general algorithm? // Assumes that misc & rings fits only in their slots, and others in only one slot and no duplicates. - if (constituents != NULL) { - std::map tempArtifWorn = artifWorn; + if (constituents != NULL) + { + std::map tempArtifWorn = artifWorn; const ui16 ringSlots[] = {6, 7}; const ui16 miscSlots[] = {9, 10, 11, 12, 18}; int rings = 0; @@ -108,7 +114,7 @@ bool CArtifact::fitsAt (const std::map &artifWorn, ui16 slotID) cons return true; } -bool CArtifact::canBeAssembledTo (const std::map &artifWorn, ui32 artifactID) const +bool CArtifact::canBeAssembledTo (const std::map &artifWorn, ui32 artifactID) const { if (constituentOf == NULL || !vstd::contains(*constituentOf, artifactID)) return false; @@ -119,9 +125,9 @@ bool CArtifact::canBeAssembledTo (const std::map &artifWorn, ui32 ar BOOST_FOREACH(ui32 constituentID, *artifact.constituents) { bool found = false; - for (std::map::const_iterator it = artifWorn.begin(); it != artifWorn.end(); ++it) + for (std::map::const_iterator it = artifWorn.begin(); it != artifWorn.end(); ++it) { - if (it->second == constituentID) + if (it->second->id == constituentID) { found = true; break; @@ -174,6 +180,11 @@ void CArtifact::getParents(TCNodes &out, const CBonusSystemNode *root /*= NULL*/ } } +void CScroll::Init() +{ + bonuses.push_back (Bonus (Bonus::PERMANENT, Bonus::SPELL,0, id, spellid, Bonus::INDEPENDENT_MAX)); +} + CArtHandler::CArtHandler() { VLC->arth = this; @@ -185,7 +196,8 @@ CArtHandler::CArtHandler() CArtHandler::~CArtHandler() { - for (std::vector::iterator it = artifacts.begin(); it != artifacts.end(); ++it) { + for (std::vector::iterator it = artifacts.begin(); it != artifacts.end(); ++it) + { delete (*it)->constituents; delete (*it)->constituentOf; } @@ -718,14 +730,14 @@ void CArtHandler::clear() * @param artifWorn A hero's set of worn artifacts. * @param bonuses Optional list of bonuses to update. */ -void CArtHandler::equipArtifact(std::map &artifWorn, ui16 slotID, ui32 artifactID) +void CArtHandler::equipArtifact(std::map &artifWorn, ui16 slotID, const CArtifact* newArtifact) { unequipArtifact(artifWorn, slotID); - const CArtifact &artifact = *artifacts[artifactID]; + const CArtifact &artifact = *newArtifact; // Add artifact. - artifWorn[slotID] = artifactID; + artifWorn[slotID] = const_cast(newArtifact); // Add locks, in reverse order of being removed. if (artifact.constituents != NULL) @@ -746,7 +758,7 @@ void CArtHandler::equipArtifact(std::map &artifWorn, ui16 slotID, ui { if (!vstd::contains(artifWorn, slot)) { - artifWorn[slot] = 145; + artifWorn[slot] = VLC->arth->artifacts[145]; //lock break; } } @@ -761,12 +773,12 @@ void CArtHandler::equipArtifact(std::map &artifWorn, ui16 slotID, ui * @param artifWorn A hero's set of worn artifacts. * @param bonuses Optional list of bonuses to update. */ -void CArtHandler::unequipArtifact(std::map &artifWorn, ui16 slotID) +void CArtHandler::unequipArtifact(std::map &artifWorn, ui16 slotID) { if (!vstd::contains(artifWorn, slotID)) return; - const CArtifact &artifact = *artifacts[artifWorn[slotID]]; + const CArtifact &artifact = *artifWorn[slotID]; // Remove artifact, if it's not already removed. artifWorn.erase(slotID); @@ -788,7 +800,7 @@ void CArtHandler::unequipArtifact(std::map &artifWorn, ui16 slotID) { BOOST_REVERSE_FOREACH(ui16 slot, constituent.possibleSlots) { - if (vstd::contains(artifWorn, slot) && artifWorn[slot] == 145) + if (vstd::contains(artifWorn, slot) && artifWorn[slot]->id == 145) { artifWorn.erase(slot); break; diff --git a/hch/CArtHandler.h b/hch/CArtHandler.h index 71e9b6b82..767ec5fcb 100644 --- a/hch/CArtHandler.h +++ b/hch/CArtHandler.h @@ -17,6 +17,7 @@ * */ class CDefHandler; +class CArtifact; class DLL_EXPORT CArtifact : public CBonusSystemNode //container for artifacts { @@ -26,8 +27,9 @@ public: const std::string &Name() const; //getter const std::string &Description() const; //getter bool isBig () const; - bool fitsAt (const std::map &artifWorn, ui16 slot) const; - bool canBeAssembledTo (const std::map &artifWorn, ui32 artifactID) const; + bool isModable () const; + bool fitsAt (const std::map &artifWorn, ui16 slot) const; + bool canBeAssembledTo (const std::map &artifWorn, ui32 artifactID) const; void addBonusesTo (BonusList *otherBonuses) const; void removeBonusesFrom (BonusList *otherBonuses) const; int getArtClassSerial() const; //0 - treasure, 1 - minor, 2 - major, 3 - relic, 4 - spell scroll, 5 - other @@ -61,8 +63,9 @@ public: class DLL_EXPORT CScroll : public CArtifact, public IModableArt // Spell Scroll { public: + CScroll(spelltype sid){spellid = sid;}; spelltype spellid; - void Init(){}; + void Init(); template void serialize(Handler &h, const int version) { h & static_cast(*this); @@ -116,8 +119,8 @@ public: void getAllowed(std::vector &out, int flags); void erasePickedArt (si32 id); bool isBigArtifact (ui32 artID) {return bigArtifacts.find(artID) != bigArtifacts.end();} - void equipArtifact (std::map &artifWorn, ui16 slotID, ui32 artifactID); - void unequipArtifact (std::map &artifWorn, ui16 slotID); + void equipArtifact (std::map &artifWorn, ui16 slotID, const CArtifact* art); + void unequipArtifact (std::map &artifWorn, ui16 slotID); void initAllowedArtifactsList(const std::vector &allowed); //allowed[art_id] -> 0 if not allowed, 1 if allowed static int convertMachineID(int id, bool creToArt); CArtHandler(); diff --git a/hch/CCampaignHandler.cpp b/hch/CCampaignHandler.cpp index 4cb7ed8e9..a2005f314 100644 --- a/hch/CCampaignHandler.cpp +++ b/hch/CCampaignHandler.cpp @@ -523,7 +523,7 @@ void CCampaignScenario::prepareCrossoverHeroes( std::vector he { BOOST_FOREACH(CGHeroInstance * cgh, crossoverHeroes) { - cgh->artifacts -= g; + cgh->artifacts -= VLC->arth->artifacts[g]; } } } diff --git a/hch/CObjectHandler.cpp b/hch/CObjectHandler.cpp index 57c214e5c..c601f7a64 100644 --- a/hch/CObjectHandler.cpp +++ b/hch/CObjectHandler.cpp @@ -729,27 +729,23 @@ int CGHeroInstance::maxMovePoints(bool onLand) const return int(base + base*modifier) + bonus; } -ui32 CGHeroInstance::getArtAtPos(ui16 pos) const +CArtifact* CGHeroInstance::getArtAtPos(ui16 pos) const { if(pos<19) if(vstd::contains(artifWorn,pos)) return artifWorn.find(pos)->second; else - return -1; + return NULL; else if(pos-19 < artifacts.size()) return artifacts[pos-19]; else - return -1; + return NULL; } const CArtifact * CGHeroInstance::getArt(int pos) const { - int id = getArtAtPos(pos); - if(id>=0) - return VLC->arth->artifacts[id]; - else - return NULL; + return getArtAtPos(pos); } // int CGHeroInstance::getSpellSecLevel(int spell) const @@ -814,9 +810,9 @@ void CGHeroInstance::initHero() if(!vstd::contains(artifWorn, 16) && type->startingSpell >= 0) //no catapult means we haven't read pre-existant set { - VLC->arth->equipArtifact(artifWorn, 17, 0); //give spellbook + VLC->arth->equipArtifact(artifWorn, 17, VLC->arth->artifacts[0]); //give spellbook } - VLC->arth->equipArtifact(artifWorn, 16, 3); //everyone has a catapult + VLC->arth->equipArtifact(artifWorn, 16, VLC->arth->artifacts[3]); //everyone has a catapult if(portrait < 0 || portrait == 255) portrait = subID; @@ -886,13 +882,13 @@ void CGHeroInstance::initArmy(CCreatureSet *dst /*= NULL*/) switch (creID) { case 145: //catapult - VLC->arth->equipArtifact(artifWorn, 16, 3); + VLC->arth->equipArtifact(artifWorn, 16, VLC->arth->artifacts[3]); break; default: VLC->arth->equipArtifact( artifWorn, 9+CArtHandler::convertMachineID(creID,true), - CArtHandler::convertMachineID(creID,true)); + VLC->arth->artifacts[CArtHandler::convertMachineID(creID,true)]); break; } } @@ -1421,8 +1417,8 @@ si32 CGHeroInstance::manaRegain() const si32 CGHeroInstance::getArtPos(int aid) const { - for(std::map::const_iterator i = artifWorn.begin(); i != artifWorn.end(); i++) - if(i->second == aid) + for(std::map::const_iterator i = artifWorn.begin(); i != artifWorn.end(); i++) + if(i->second->id == aid) return i->first; return -1; } @@ -1431,33 +1427,34 @@ si32 CGHeroInstance::getArtPos(int aid) const * Places an artifact in hero's backpack. If it's a big artifact equips it * or discards it if it cannot be equipped. */ -void CGHeroInstance::giveArtifact (ui32 aid) +void CGHeroInstance::giveArtifact (ui32 aid) //use only for fixed artifacts { - const CArtifact &artifact = *VLC->arth->artifacts[aid]; + CArtifact * const artifact = VLC->arth->artifacts[aid]; //pointer to constant object - if (artifact.isBig()) + if (artifact->isBig()) { - for (std::vector::const_iterator it = artifact.possibleSlots.begin(); it != artifact.possibleSlots.end(); ++it) + for (std::vector::const_iterator it = artifact->possibleSlots.begin(); it != artifact->possibleSlots.end(); ++it) { if (!vstd::contains(artifWorn, *it)) { - VLC->arth->equipArtifact(artifWorn, *it, aid); + VLC->arth->equipArtifact(artifWorn, *it, artifact); break; } } } else { - artifacts.push_back(aid); + artifacts.push_back(artifact); } } bool CGHeroInstance::hasArt( ui32 aid ) const { - if(vstd::contains(artifacts, aid)) - return true; - for(std::map::const_iterator i = artifWorn.begin(); i != artifWorn.end(); i++) - if(i->second == aid) + for(std::vector::const_iterator i = artifacts.begin(); i != artifacts.end(); i++) + if((*i)->id == aid) + return true; + for(std::map::const_iterator i = artifWorn.begin(); i != artifWorn.end(); i++) + if(i->second->id == aid) return true; return false; @@ -1500,8 +1497,8 @@ void CGHeroInstance::getParents(TCNodes &out, const CBonusSystemNode *root /*= N out.insert(visitedTown); } - for (std::map::const_iterator i = artifWorn.begin(); i != artifWorn.end(); i++) - out.insert(VLC->arth->artifacts[i->second]); + for (std::map::const_iterator i = artifWorn.begin(); i != artifWorn.end(); i++) + out.insert(i->second); out.insert(&speciality); } @@ -3634,6 +3631,8 @@ void CGArtifact::pick(const CGHeroInstance * h) const { if(ID == 5) //Artifact { + if (VLC->arth->artifacts[subID]->isModable()) //TODO: create new instance, initialize it + {} cb->giveHeroArtifact(subID,h->id,-2); } else if(ID == 93) // Spell scroll @@ -4373,7 +4372,7 @@ void CGSeerHut::finishQuest (const CGHeroInstance * h, ui32 accept) const case CQuest::MISSION_ART: for (std::vector::const_iterator it = m5arts.begin(); it != m5arts.end(); ++it) { - cb->removeArtifact(*it, h->id); + cb->removeArtifact(VLC->arth->artifacts[*it], h->id); } break; case CQuest::MISSION_ARMY: diff --git a/hch/CObjectHandler.h b/hch/CObjectHandler.h index da3c6964c..de980f03b 100644 --- a/hch/CObjectHandler.h +++ b/hch/CObjectHandler.h @@ -266,8 +266,8 @@ public: ui8 inTownGarrison; // if hero is in town garrison const CGTownInstance * visitedTown; //set if hero is visiting town or in the town garrison const CGBoat *boat; //set to CGBoat when sailing - std::vector artifacts; //hero's artifacts from bag - std::map artifWorn; //map; positions: 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 artifacts; //hero's artifacts from bag + std::map artifWorn; //map; positions: 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::set spells; //known spells (spell IDs) struct DLL_EXPORT Patrol @@ -337,7 +337,7 @@ public: int maxMovePoints(bool onLand) const; - ui32 getArtAtPos(ui16 pos) const; //-1 - no artifact + CArtifact* getArtAtPos(ui16 pos) const; //NULL - no artifact const CArtifact * getArt(int pos) const; si32 getArtPos(int aid) const; //looks for equipped artifact with given ID and returns its slot ID or -1 if none(if more than one such artifact lower ID is returned) bool hasArt(ui32 aid) const; //checks if hero possess artifact of given id (either in backack or worn) diff --git a/lib/CGameState.cpp b/lib/CGameState.cpp index 93f3ee708..e2a904f16 100644 --- a/lib/CGameState.cpp +++ b/lib/CGameState.cpp @@ -1938,7 +1938,7 @@ void CGameState::init( StartInfo * si, ui32 checksum, int Seed ) CGHeroInstance *hero = k->second.heroes[0]; std::vector::iterator slot = vstd::findFirstNot (hero->artifWorn, toGive->possibleSlots); if(slot != toGive->possibleSlots.end()) - VLC->arth->equipArtifact(hero->artifWorn, *slot, toGive->id); + VLC->arth->equipArtifact(hero->artifWorn, *slot, toGive); else hero->giveArtifact(toGive->id); } diff --git a/lib/IGameCallback.h b/lib/IGameCallback.h index 3354462ea..3591c4386 100644 --- a/lib/IGameCallback.h +++ b/lib/IGameCallback.h @@ -93,7 +93,7 @@ public: virtual void heroVisitCastle(int obj, int heroID)=0; virtual void stopHeroVisitCastle(int obj, int heroID)=0; virtual void giveHeroArtifact(int artid, int hid, int position)=0; //pos==-1 - first free slot in backpack=0; pos==-2 - default if available or backpack - virtual bool removeArtifact(int artid, int hid) = 0; + virtual bool removeArtifact(CArtifact* art, int hid) = 0; virtual void startBattleI(const CArmedInstance *army1, const CArmedInstance *army2, int3 tile, const CGHeroInstance *hero1, const CGHeroInstance *hero2, bool creatureBank = false, boost::function cb = 0, const CGTownInstance *town = NULL)=0; //use hero=NULL for no hero virtual void startBattleI(const CArmedInstance *army1, const CArmedInstance *army2, int3 tile, boost::function cb = 0, bool creatureBank = false)=0; //if any of armies is hero, hero will be used virtual void startBattleI(const CArmedInstance *army1, const CArmedInstance *army2, boost::function cb = 0, bool creatureBank = false)=0; //if any of armies is hero, hero will be used, visitable tile of second obj is place of battle diff --git a/lib/NetPacks.h b/lib/NetPacks.h index d3e681414..50b5c7824 100644 --- a/lib/NetPacks.h +++ b/lib/NetPacks.h @@ -599,18 +599,18 @@ struct SetHeroArtifacts : public CPackForClient //509 SetHeroArtifacts(){type = 509;}; void applyCl(CClient *cl); DLL_EXPORT void applyGs(CGameState *gs); - DLL_EXPORT void setArtAtPos(ui16 pos, int art); + DLL_EXPORT void setArtAtPos(ui16 pos, const CArtifact* art); si32 hid; - std::vector artifacts; //hero's artifacts from bag - std::map artifWorn; //map; positions: 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 artifacts; //hero's artifacts from bag + std::map artifWorn; //map; positions: 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 template void serialize(Handler &h, const int version) { h & hid & artifacts & artifWorn; } - std::vector equiped, unequiped; //used locally + std::vector equiped, unequiped; //used locally BonusList gained, lost; //used locally as hlp when applying }; diff --git a/lib/NetPacksLib.cpp b/lib/NetPacksLib.cpp index 193a5310d..d230694c0 100644 --- a/lib/NetPacksLib.cpp +++ b/lib/NetPacksLib.cpp @@ -451,11 +451,11 @@ DLL_EXPORT void SetHeroesInTown::applyGs( CGameState *gs ) DLL_EXPORT void SetHeroArtifacts::applyGs( CGameState *gs ) { CGHeroInstance *h = gs->getHero(hid); - for(std::map::const_iterator i = h->artifWorn.begin(); i != h->artifWorn.end(); i++) + for(std::map::const_iterator i = h->artifWorn.begin(); i != h->artifWorn.end(); i++) if(!vstd::contains(artifWorn,i->first) || artifWorn[i->first] != i->second) unequiped.push_back(i->second); - for(std::map::const_iterator i = artifWorn.begin(); i != artifWorn.end(); i++) + for(std::map::const_iterator i = artifWorn.begin(); i != artifWorn.end(); i++) if(!vstd::contains(h->artifWorn,i->first) || h->artifWorn[i->first] != i->second) equiped.push_back(i->second); @@ -464,7 +464,7 @@ DLL_EXPORT void SetHeroArtifacts::applyGs( CGameState *gs ) h->artifWorn = artifWorn; } -DLL_EXPORT void SetHeroArtifacts::setArtAtPos(ui16 pos, int art) +DLL_EXPORT void SetHeroArtifacts::setArtAtPos(ui16 pos, const CArtifact* art) { if(art < 0) { @@ -477,14 +477,14 @@ DLL_EXPORT void SetHeroArtifacts::setArtAtPos(ui16 pos, int art) { if (pos < 19) { - VLC->arth->equipArtifact(artifWorn, pos, (ui32) art); + VLC->arth->equipArtifact(artifWorn, pos, art); } else // Goes into the backpack. { if(pos - 19 < artifacts.size()) - artifacts.insert(artifacts.begin() + (pos - 19), art); + artifacts.insert(artifacts.begin() + (pos - 19), const_cast(art)); else - artifacts.push_back(art); + artifacts.push_back(const_cast(art)); } } } diff --git a/lib/map.cpp b/lib/map.cpp index d93de0ae1..b304ee383 100644 --- a/lib/map.cpp +++ b/lib/map.cpp @@ -858,27 +858,27 @@ void Mapa::loadHero( CGObjectInstance * &nobj, const unsigned char * bufor, int { int id = readNormalNr(bufor,i, artidlen); i+=artidlen; if(id != artmask) - VLC->arth->equipArtifact(nhi->artifWorn, pom, id); + VLC->arth->equipArtifact(nhi->artifWorn, pom, VLC->arth->artifacts[id]); } //misc5 art //17 if(version>=SoD) { int id = readNormalNr(bufor,i, artidlen); i+=artidlen; if(id!=artmask) - VLC->arth->equipArtifact(nhi->artifWorn, 16, id); + VLC->arth->equipArtifact(nhi->artifWorn, 16, VLC->arth->artifacts[id]); else - VLC->arth->equipArtifact(nhi->artifWorn, 16, 3); //catapult by default + VLC->arth->equipArtifact(nhi->artifWorn, 16, VLC->arth->artifacts[3]); //catapult by default } //spellbook int id = readNormalNr(bufor,i, artidlen); i+=artidlen; if(id!=artmask) - VLC->arth->equipArtifact(nhi->artifWorn, 17, id); + VLC->arth->equipArtifact(nhi->artifWorn, 17, VLC->arth->artifacts[id]); //19 //???what is that? gap in file or what? - it's probably fifth slot.. if(version>RoE) { id = readNormalNr(bufor,i, artidlen); i+=artidlen; if(id!=artmask) - VLC->arth->equipArtifact(nhi->artifWorn, 18, id); + VLC->arth->equipArtifact(nhi->artifWorn, 18, VLC->arth->artifacts[id]); } else i+=1; @@ -1102,7 +1102,7 @@ void Mapa::readPredefinedHeroes( const unsigned char * bufor, int &i) { int id = readNormalNr(bufor,i, artidlen); i+=artidlen; if(id!=artmask) - VLC->arth->equipArtifact(cgh->artifWorn, pom, id); + VLC->arth->equipArtifact(cgh->artifWorn, pom, VLC->arth->artifacts[id]); } //misc5 art //17 if(version>=SoD) @@ -1115,13 +1115,13 @@ void Mapa::readPredefinedHeroes( const unsigned char * bufor, int &i) //spellbook int id = readNormalNr(bufor,i, artidlen); i+=artidlen; if(id!=artmask) - VLC->arth->equipArtifact(cgh->artifWorn, 17, id); + VLC->arth->equipArtifact(cgh->artifWorn, 17, VLC->arth->artifacts[id]); //19 //???what is that? gap in file or what? - it's probably fifth slot.. if(version>RoE) { id = readNormalNr(bufor,i, artidlen); i+=artidlen; if(id!=artmask) - VLC->arth->equipArtifact(cgh->artifWorn, 18, id); + VLC->arth->equipArtifact(cgh->artifWorn, 18, VLC->arth->artifacts[id]); } else i+=1; diff --git a/server/CGameHandler.cpp b/server/CGameHandler.cpp index 2d82ac48f..e835f5a76 100644 --- a/server/CGameHandler.cpp +++ b/server/CGameHandler.cpp @@ -2221,7 +2221,7 @@ void CGameHandler::stopHeroVisitCastle(int obj, int heroID) void CGameHandler::giveHeroArtifact(int artid, int hid, int position) //pos==-1 - first free slot in backpack { const CGHeroInstance* h = getHero(hid); - const CArtifact &art = *VLC->arth->artifacts[artid]; + CArtifact * const art = VLC->arth->artifacts[artid]; SetHeroArtifacts sha; sha.hid = hid; @@ -2233,38 +2233,38 @@ void CGameHandler::giveHeroArtifact(int artid, int hid, int position) //pos==-1 if(position == -2) { int i; - for(i=0; ipossibleSlots.size(); i++) //try to put artifact into first available slot { - if( !vstd::contains(sha.artifWorn,art.possibleSlots[i]) ) + if( !vstd::contains(sha.artifWorn, art->possibleSlots[i]) ) { //we've found a free suitable slot - VLC->arth->equipArtifact(sha.artifWorn, art.possibleSlots[i], artid); + VLC->arth->equipArtifact(sha.artifWorn, art->possibleSlots[i], VLC->arth->artifacts[artid]); break; } } - if(i == art.possibleSlots.size() && !art.isBig()) //if haven't find proper slot, use backpack or discard big artifact - sha.artifacts.push_back(artid); + if(i == art->possibleSlots.size() && !art->isBig()) //if haven't find proper slot, use backpack or discard big artifact + sha.artifacts.push_back(art); } - else if (!art.isBig()) //should be -1 => put artifact into backpack + else if (!art->isBig()) //should be -1 => put artifact into backpack { - sha.artifacts.push_back(artid); + sha.artifacts.push_back(art); } } else { if(!vstd::contains(sha.artifWorn,ui16(position))) { - VLC->arth->equipArtifact(sha.artifWorn, position, artid); + VLC->arth->equipArtifact(sha.artifWorn, position, art); } - else if (!art.isBig()) + else if (!art->isBig()) { - sha.artifacts.push_back(artid); + sha.artifacts.push_back(art); } } sendAndApply(&sha); } -bool CGameHandler::removeArtifact(int artid, int hid) +bool CGameHandler::removeArtifact(CArtifact* art, int hid) { const CGHeroInstance* h = getHero(hid); @@ -2273,15 +2273,15 @@ bool CGameHandler::removeArtifact(int artid, int hid) sha.artifacts = h->artifacts; sha.artifWorn = h->artifWorn; - std::vector::iterator it; - if ((it = std::find(sha.artifacts.begin(), sha.artifacts.end(), artid)) != sha.artifacts.end()) //it is in backpack + std::vector::iterator it; + if ((it = std::find(sha.artifacts.begin(), sha.artifacts.end(), art)) != sha.artifacts.end()) //it is in backpack sha.artifacts.erase(it); else //worn { - std::map::iterator itr; + std::map::iterator itr; for (itr = sha.artifWorn.begin(); itr != sha.artifWorn.end(); ++itr) { - if (itr->second == artid) + if (itr->second == art) { VLC->arth->unequipArtifact(sha.artifWorn, itr->first); break; @@ -2756,7 +2756,7 @@ bool CGameHandler::buildStructure( si32 tid, si32 bid, bool force /*=false*/ ) return false; } - removeArtifact(2, t->visitingHero->id); + removeArtifact(VLC->arth->artifacts[2], t->visitingHero->id); } NewStructures ns; @@ -3148,7 +3148,7 @@ bool CGameHandler::swapArtifacts(si32 srcHeroID, si32 destHeroID, ui16 srcSlot, // Combinational artifacts needs to be removed first so they don't get denied movement because of their own locks. if (srcHeroID == destHeroID && srcSlot < 19 && destSlot < 19) { - sha.setArtAtPos(srcSlot, -1); + sha.setArtAtPos(srcSlot, NULL); if (!vstd::contains(sha.artifWorn, destSlot)) destArtifact = NULL; } @@ -3182,14 +3182,14 @@ bool CGameHandler::swapArtifacts(si32 srcHeroID, si32 destHeroID, ui16 srcSlot, // If dest does not fit in src, put it in dest's backpack instead. if (srcHeroID == destHeroID) // To avoid stumbling on own locks, remove artifact first. - sha.setArtAtPos(destSlot, -1); + sha.setArtAtPos(destSlot, NULL); const bool destFits = !destArtifact || srcSlot >= 19 || destSlot >= 19 || destArtifact->fitsAt(sha.artifWorn, srcSlot); if (srcHeroID == destHeroID && destArtifact) - sha.setArtAtPos(destSlot, destArtifact->id); + sha.setArtAtPos(destSlot, destArtifact); - sha.setArtAtPos(srcSlot, -1); + sha.setArtAtPos(srcSlot, NULL); if (destSlot < 19 && (destArtifact || srcSlot < 19) && destFits) - sha.setArtAtPos(srcSlot, destArtifact ? destArtifact->id : -1); + sha.setArtAtPos(srcSlot, destArtifact ? destArtifact : NULL); // Internal hero artifact arrangement. if(srcHero == destHero) @@ -3207,7 +3207,7 @@ bool CGameHandler::swapArtifacts(si32 srcHeroID, si32 destHeroID, ui16 srcSlot, sha2.hid = destHeroID; sha2.artifacts = destHero->artifacts; sha2.artifWorn = destHero->artifWorn; - sha2.setArtAtPos(destSlot, srcArtifact ? srcArtifact->id : -1); + sha2.setArtAtPos(destSlot, srcArtifact ? srcArtifact : NULL); if (!destFits) sha2.setArtAtPos(sha2.artifacts.size() + 19, destHero->getArtAtPos(destSlot)); sendAndApply(&sha2); @@ -3239,20 +3239,24 @@ bool CGameHandler::assembleArtifacts (si32 heroID, ui16 artifactSlot, bool assem sha.artifacts = hero->artifacts; sha.artifWorn = hero->artifWorn; - if (assemble) { - if (VLC->arth->artifacts.size() < assembleTo) { + if (assemble) + { + if (VLC->arth->artifacts.size() < assembleTo) + { complain("Illegal artifact to assemble to."); return false; } - if (!destArtifact->canBeAssembledTo(hero->artifWorn, assembleTo)) { + if (!destArtifact->canBeAssembledTo(hero->artifWorn, assembleTo)) + { complain("Artifact cannot be assembled."); return false; } const CArtifact &artifact = *VLC->arth->artifacts[assembleTo]; - if (artifact.constituents == NULL) { + if (artifact.constituents == NULL) + { complain("Not a combinational artifact."); return false; } @@ -3261,32 +3265,43 @@ bool CGameHandler::assembleArtifacts (si32 heroID, ui16 artifactSlot, bool assem bool destConsumed = false; // Determines which constituent that will be counted for together with the artifact. const bool destSpecific = vstd::contains(artifact.possibleSlots, artifactSlot); // Prefer the chosen slot as the location for the assembled artifact. - BOOST_FOREACH(ui32 constituentID, *artifact.constituents) { - if (destSpecific && constituentID == destArtifact->id) { - sha.artifWorn[artifactSlot] = assembleTo; + BOOST_FOREACH(ui32 constituentID, *artifact.constituents) + { + if (destSpecific && constituentID == destArtifact->id) + { + sha.artifWorn[artifactSlot] = VLC->arth->artifacts[assembleTo]; destConsumed = true; continue; } bool found = false; - for (std::map::iterator it = sha.artifWorn.begin(); it != sha.artifWorn.end(); ++it) { - if (it->second == constituentID) { // Found possible constituent to substitute. - if (destSpecific && !destConsumed && it->second == destArtifact->id) { + for (std::map::iterator it = sha.artifWorn.begin(); it != sha.artifWorn.end(); ++it) + { + if (it->second->id == constituentID) + { // Found possible constituent to substitute. + if (destSpecific && !destConsumed && it->second->id == destArtifact->id) + { // Find the specified destination for assembled artifact. - if (it->first == artifactSlot) { - it->second = assembleTo; + if (it->first == artifactSlot) + { + it->second = VLC->arth->artifacts[assembleTo]; destConsumed = true; found = true; break; } - } else { + } + else + { // Either put the assembled artifact in a fitting spot, or put a lock. - if (!destSpecific && !destConsumed && vstd::contains(artifact.possibleSlots, it->first)) { - it->second = assembleTo; + if (!destSpecific && !destConsumed && vstd::contains(artifact.possibleSlots, it->first)) + { + it->second = VLC->arth->artifacts[assembleTo]; destConsumed = true; - } else { - it->second = 145; + } + else + { + it->second = VLC->arth->artifacts[145]; } found = true; @@ -3299,19 +3314,27 @@ bool CGameHandler::assembleArtifacts (si32 heroID, ui16 artifactSlot, bool assem return false; } } - } else { + } + else + { // Perform disassembly. bool destConsumed = false; // Determines which constituent that will be counted for together with the artifact. - BOOST_FOREACH(ui32 constituentID, *destArtifact->constituents) { + BOOST_FOREACH(ui32 constituentID, *destArtifact->constituents) + { const CArtifact &constituent = *VLC->arth->artifacts[constituentID]; - if (!destConsumed && vstd::contains(constituent.possibleSlots, artifactSlot)) { - sha.artifWorn[artifactSlot] = constituentID; + if (!destConsumed && vstd::contains(constituent.possibleSlots, artifactSlot)) + { + sha.artifWorn[artifactSlot] = VLC->arth->artifacts[constituentID]; destConsumed = true; - } else { - BOOST_REVERSE_FOREACH(ui16 slotID, constituent.possibleSlots) { - if (vstd::contains(sha.artifWorn, slotID) && sha.artifWorn[slotID] == 145) { - sha.artifWorn[slotID] = constituentID; + } + else + { + BOOST_REVERSE_FOREACH(ui16 slotID, constituent.possibleSlots) + { + if (vstd::contains(sha.artifWorn, slotID) && sha.artifWorn[slotID]->id == 145) + { + sha.artifWorn[slotID]->id = constituentID; break; } } @@ -4045,9 +4068,9 @@ void CGameHandler::playerMessage( ui8 player, const std::string &message ) sha.hid = hero->id; sha.artifacts = hero->artifacts; sha.artifWorn = hero->artifWorn; - VLC->arth->equipArtifact(sha.artifWorn, 13, 4); - VLC->arth->equipArtifact(sha.artifWorn, 14, 5); - VLC->arth->equipArtifact(sha.artifWorn, 15, 6); + VLC->arth->equipArtifact(sha.artifWorn, 13, VLC->arth->artifacts[4]); + VLC->arth->equipArtifact(sha.artifWorn, 14, VLC->arth->artifacts[5]); + VLC->arth->equipArtifact(sha.artifWorn, 15, VLC->arth->artifacts[6]); sendAndApply(&sha); } else if(message == "vcminahar") //1000000 movement points @@ -4104,10 +4127,10 @@ void CGameHandler::playerMessage( ui8 player, const std::string &message ) sha.hid = hero->id; sha.artifacts = hero->artifacts; sha.artifWorn = hero->artifWorn; - sha.artifacts.push_back(2); //grail + sha.artifacts.push_back(VLC->arth->artifacts[2]); //grail for (int g=7; g<=140; ++g) { - sha.artifacts.push_back(g); + sha.artifacts.push_back(VLC->arth->artifacts[g]); } sendAndApply(&sha); } @@ -5228,13 +5251,13 @@ bool CGameHandler::sacrificeCreatures(const IMarket *market, const CGHeroInstanc return true; } -bool CGameHandler::sacrificeArtifact(const IMarket * m, const CGHeroInstance * hero, ui32 artID) +bool CGameHandler::sacrificeArtifact(const IMarket * m, const CGHeroInstance * hero, CArtifact* art) { - if(!removeArtifact(artID, hero->id)) + if(!removeArtifact(art, hero->id)) COMPLAIN_RET("Cannot find artifact to sacrifice!"); int dmp, expToGive; - m->getOffer(artID, 0, dmp, expToGive, ARTIFACT_EXP); + m->getOffer(art->id, 0, dmp, expToGive, ARTIFACT_EXP); changePrimSkill(hero->id, 4, expToGive); return true; } diff --git a/server/CGameHandler.h b/server/CGameHandler.h index 90089d521..3ca626756 100644 --- a/server/CGameHandler.h +++ b/server/CGameHandler.h @@ -144,7 +144,7 @@ public: void stopHeroVisitCastle(int obj, int heroID); void giveHeroArtifact(int artid, int hid, int position); //pos==-1 - first free slot in backpack; pos==-2 - default if available or backpack void moveArtifact(int hid, int oldPosition, int destPos); - bool removeArtifact(int artid, int hid); + bool removeArtifact(CArtifact* art, int hid); void startBattleI(const CArmedInstance *army1, const CArmedInstance *army2, int3 tile, const CGHeroInstance *hero1, const CGHeroInstance *hero2, bool creatureBank = false, boost::function cb = 0, const CGTownInstance *town = NULL); //use hero=NULL for no hero void startBattleI(const CArmedInstance *army1, const CArmedInstance *army2, int3 tile, boost::function cb = 0, bool creatureBank = false); //if any of armies is hero, hero will be used void startBattleI(const CArmedInstance *army1, const CArmedInstance *army2, boost::function cb = 0, bool creatureBank = false); //if any of armies is hero, hero will be used, visitable tile of second obj is place of battle//void startBattleI(int heroID, CCreatureSet army, int3 tile, boost::function cb); //for hero<=>neutral army @@ -222,7 +222,7 @@ public: void run(bool resume, const StartInfo *si = NULL); void newTurn(); void handleAfterAttackCasting( const BattleAttack & bat ); - bool sacrificeArtifact(const IMarket * m, const CGHeroInstance * hero, ui32 artID); + bool sacrificeArtifact(const IMarket * m, const CGHeroInstance * hero, CArtifact* art); friend class CVCMIServer; friend class CScriptCallback; }; diff --git a/server/NetPacksServer.cpp b/server/NetPacksServer.cpp index 955c008be..779c9d4ab 100644 --- a/server/NetPacksServer.cpp +++ b/server/NetPacksServer.cpp @@ -164,7 +164,7 @@ bool TradeOnMarketplace::applyGh( CGameHandler *gh ) case CREATURE_EXP: return gh->sacrificeCreatures(m, hero, r1, val); case ARTIFACT_EXP: - return gh->sacrificeArtifact(m, hero, r1); + return gh->sacrificeArtifact(m, hero, hero->getArtAtPos(r1)); default: COMPLAIN_AND_RETURN("Unknown exchange mode!"); }