1
0
mirror of https://github.com/vcmi/vcmi.git synced 2024-12-24 22:14:36 +02:00

Restored Warmonger's changes to artifacts system.

They will be subject of my further work, along with next part of bonus system.
This commit is contained in:
Michał W. Urbańczyk 2010-11-10 00:06:25 +00:00
parent d1c1758aad
commit bce805dacc
21 changed files with 388 additions and 194 deletions

View File

@ -17,6 +17,7 @@
#include <boost/thread.hpp>
#include <boost/thread/shared_mutex.hpp>
#include "hch/CSpellHandler.h"
#include "hch/CArtHandler.h"
#ifdef min
#undef min
#endif

View File

@ -784,7 +784,7 @@ void CKingdomInterface::CHeroItem::setHero(const CGHeroInstance * newHero)
for (int i=0; i<artifacts.size(); i++)
{
artifacts[i]->type = 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; i<backpack.size(); i++)
{
backpack[i]->type = 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; i<backpack.size(); i++)
{
backpack[i]->type = 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 ; i<iter+9;i++)
{
int artID = hero->getArtAtPos(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 ; it<iter;it++)
blitAt(graphics->artDefs->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);

View File

@ -117,7 +117,8 @@ 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;};
void giveNewArtifact(int hid, int position){};
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<void(BattleResult*)> cb = 0, const CGTownInstance *town = NULL){}; //use hero=NULL for no hero
void startBattleI(const CArmedInstance *army1, const CArmedInstance *army2, int3 tile, boost::function<void(BattleResult*)> 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<void(BattleResult*)> cb = 0, bool creatureBank = false){}; //if any of armies is hero, hero will be used, visitable tile of second obj is place of battle

View File

@ -2640,7 +2640,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<CArtifact*>(movedArt));
aw->arts->commonInfo->destAOH = aw->arts;
CGI->curh->dragAndDropCursor(graphics->artDefs->ourImages[movedArt->id].bitmap);
@ -3622,10 +3622,10 @@ void CAltarWindow::SacrificeAll()
}
else
{
for(std::map<ui16,ui32>::const_iterator i = hero->artifWorn.begin(); i != hero->artifWorn.end(); i++)
for(std::map<ui16,CArtifact*>::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();
@ -3778,13 +3778,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();

View File

@ -10,6 +10,7 @@
#include <boost/lexical_cast.hpp>
#include <boost/foreach.hpp>
#include <boost/random/linear_congruential.hpp>
#include <boost/algorithm/string/replace.hpp>
#include "../lib/VCMI_Lib.h"
extern CLodHandler *bitmaph;
using namespace boost::assign;
@ -47,25 +48,31 @@ bool CArtifact::isBig () const
return VLC->arth->isBigArtifact(id);
}
bool CArtifact::isModable () const
{
return (bool)dynamic_cast<const IModableArt *>(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<ui16, ui32> &artifWorn, ui16 slotID) const
bool CArtifact::fitsAt (const std::map<ui16, CArtifact*> &artifWorn, ui16 slotID) const
{
if (!vstd::contains(possibleSlots, slotID))
return false;
// Can't put an artifact in a locked slot.
std::map<ui16, ui32>::const_iterator it = artifWorn.find(slotID);
if (it != artifWorn.end() && it->second == 145)
std::map<ui16, CArtifact*>::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<ui16, ui32> tempArtifWorn = artifWorn;
if (constituents != NULL)
{
std::map<ui16, CArtifact*> tempArtifWorn = artifWorn;
const ui16 ringSlots[] = {6, 7};
const ui16 miscSlots[] = {9, 10, 11, 12, 18};
int rings = 0;
@ -108,7 +115,7 @@ bool CArtifact::fitsAt (const std::map<ui16, ui32> &artifWorn, ui16 slotID) cons
return true;
}
bool CArtifact::canBeAssembledTo (const std::map<ui16, ui32> &artifWorn, ui32 artifactID) const
bool CArtifact::canBeAssembledTo (const std::map<ui16, CArtifact*> &artifWorn, ui32 artifactID) const
{
if (constituentOf == NULL || !vstd::contains(*constituentOf, artifactID))
return false;
@ -119,9 +126,9 @@ bool CArtifact::canBeAssembledTo (const std::map<ui16, ui32> &artifWorn, ui32 ar
BOOST_FOREACH(ui32 constituentID, *artifact.constituents)
{
bool found = false;
for (std::map<ui16, ui32>::const_iterator it = artifWorn.begin(); it != artifWorn.end(); ++it)
for (std::map<ui16, CArtifact*>::const_iterator it = artifWorn.begin(); it != artifWorn.end(); ++it)
{
if (it->second == constituentID)
if (it->second->id == constituentID)
{
found = true;
break;
@ -174,6 +181,12 @@ void CArtifact::getParents(TCNodes &out, const CBonusSystemNode *root /*= NULL*/
}
}
void CScroll::Init()
{
bonuses.push_back (Bonus (Bonus::PERMANENT, Bonus::SPELL, Bonus::ARTIFACT, 1, id, spellid, Bonus::INDEPENDENT_MAX));
//boost::algorithm::replace_first(description, "[spell name]", VLC->spellh->spells[spellid].name);
}
CArtHandler::CArtHandler()
{
VLC->arth = this;
@ -181,11 +194,13 @@ CArtHandler::CArtHandler()
// War machines are the default big artifacts.
for (ui32 i = 3; i <= 6; i++)
bigArtifacts.insert(i);
modableArtifacts = boost::assign::map_list_of(1, 1)(146,3)(147,3)(148,3)(150,3)(151,3)(152,3)(154,3)(156,2);
}
CArtHandler::~CArtHandler()
{
for (std::vector<CArtifact*>::iterator it = artifacts.begin(); it != artifacts.end(); ++it) {
for (std::vector<CArtifact*>::iterator it = artifacts.begin(); it != artifacts.end(); ++it)
{
delete (*it)->constituents;
delete (*it)->constituentOf;
}
@ -205,9 +220,28 @@ void CArtHandler::loadArtifacts(bool onlyTxt)
}
VLC->generaltexth->artifNames.resize(ARTIFACTS_QUANTITY);
VLC->generaltexth->artifDescriptions.resize(ARTIFACTS_QUANTITY);
std::map<ui32,ui8>::iterator itr;
for (int i=0; i<ARTIFACTS_QUANTITY; i++)
{
CArtifact *art = new CArtifact;
CArtifact *art;
if ((itr = modableArtifacts.find(i)) != modableArtifacts.end())
{
switch (itr->second)
{
case 1:
art = new CScroll;
break;
case 2:
art = new CCustomizableArt;
break;
case 3:
art = new CCommanderArt;
break;
};
}
else
art = new CArtifact;
CArtifact &nart = *art;
nart.id=i;
loadToIt(VLC->generaltexth->artifNames[i],buf,it,4);
@ -718,36 +752,39 @@ 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<ui16, ui32> &artifWorn, ui16 slotID, ui32 artifactID)
void CArtHandler::equipArtifact(std::map<ui16, CArtifact*> &artifWorn, ui16 slotID, const CArtifact* newArtifact)
{
unequipArtifact(artifWorn, slotID);
const CArtifact &artifact = *artifacts[artifactID];
// Add artifact.
artifWorn[slotID] = artifactID;
// Add locks, in reverse order of being removed.
if (artifact.constituents != NULL)
if (newArtifact) //false when artifact is NULL -> slot set to empty
{
bool destConsumed = false; // Determines which constituent that will be counted for together with the artifact.
const CArtifact &artifact = *newArtifact;
BOOST_FOREACH(ui32 constituentID, *artifact.constituents)
// Add artifact.
artifWorn[slotID] = const_cast<CArtifact*>(newArtifact);
// Add locks, in reverse order of being removed.
if (artifact.constituents != NULL)
{
const CArtifact &constituent = *artifacts[constituentID];
bool destConsumed = false; // Determines which constituent that will be counted for together with the artifact.
if (!destConsumed && vstd::contains(constituent.possibleSlots, slotID))
BOOST_FOREACH(ui32 constituentID, *artifact.constituents)
{
destConsumed = true;
}
else
{
BOOST_FOREACH(ui16 slot, constituent.possibleSlots)
const CArtifact &constituent = *artifacts[constituentID];
if (!destConsumed && vstd::contains(constituent.possibleSlots, slotID))
{
if (!vstd::contains(artifWorn, slot))
destConsumed = true;
}
else
{
BOOST_FOREACH(ui16 slot, constituent.possibleSlots)
{
artifWorn[slot] = 145;
break;
if (!vstd::contains(artifWorn, slot))
{
artifWorn[slot] = VLC->arth->artifacts[145]; //lock
break;
}
}
}
}
@ -761,12 +798,12 @@ void CArtHandler::equipArtifact(std::map<ui16, ui32> &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<ui16, ui32> &artifWorn, ui16 slotID)
void CArtHandler::unequipArtifact(std::map<ui16, CArtifact*> &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 +825,7 @@ void CArtHandler::unequipArtifact(std::map<ui16, ui32> &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;

View File

@ -17,19 +17,24 @@
*
*/
class CDefHandler;
class CArtifact;
class DLL_EXPORT CArtifact : public CBonusSystemNode //container for artifacts
{
protected:
std::string name, description; //set if custom
public:
enum EartClass {ART_SPECIAL=1, ART_TREASURE=2, ART_MINOR=4, ART_MAJOR=8, ART_RELIC=16}; //artifact classes
const std::string &Name() const; //getter
const std::string &Description() const; //getter
bool isBig () const;
bool fitsAt (const std::map<ui16, ui32> &artifWorn, ui16 slot) const;
bool canBeAssembledTo (const std::map<ui16, ui32> &artifWorn, ui32 artifactID) const;
bool isModable () const;
bool fitsAt (const std::map<ui16, CArtifact*> &artifWorn, ui16 slot) const;
bool canBeAssembledTo (const std::map<ui16, CArtifact*> &artifWorn, ui32 artifactID) const;
void addBonusesTo (BonusList *otherBonuses) const;
void removeBonusesFrom (BonusList *otherBonuses) const;
virtual void SetProperty (int mod){};
virtual void Init(){};
int getArtClassSerial() const; //0 - treasure, 1 - minor, 2 - major, 3 - relic, 4 - spell scroll, 5 - other
ui32 price;
@ -52,46 +57,58 @@ public:
void getParents(TCNodes &out, const CBonusSystemNode *root = NULL) const;
};
class DLL_EXPORT IModableArt //artifact which can have different properties, such as scroll or banner
{
class DLL_EXPORT IModableArt : public CArtifact //artifact which can have different properties, such as scroll or banner
{ //used only for dynamic cast :P
public:
virtual void Init() = 0;
};
si32 ID; //used for smart serialization
class DLL_EXPORT CScroll : public CArtifact, public IModableArt // Spell Scroll
{
public:
spelltype spellid;
void Init(){};
template <typename Handler> void serialize(Handler &h, const int version)
{
h & static_cast<CArtifact&>(*this);
h & ID;
}
};
class DLL_EXPORT CScroll : public IModableArt // Spell Scroll
{
public:
CScroll(){spellid=0;};
CScroll(spelltype sid){spellid = sid;};
spelltype spellid;
void Init();
void SetProperty (int mod){spellid = mod;};
template <typename Handler> void serialize(Handler &h, const int version)
{
h & static_cast<IModableArt&>(*this);
h & spellid;
}
};
class DLL_EXPORT CCustomizableArt : public CArtifact, public IModableArt // Warlord's Banner with multiple options
class DLL_EXPORT CCustomizableArt : public IModableArt // Warlord's Banner with multiple options
{
public:
ui8 mode;
CCustomizableArt(){mode=0;};
void Init(){};
void SelectMode (int mod){};
void SetProperty (int mod){};
template <typename Handler> void serialize(Handler &h, const int version)
{
h & static_cast<CArtifact&>(*this);
h & static_cast<IModableArt&>(*this);
h & mode;
}
};
class DLL_EXPORT CCommanderArt : public CArtifact, public IModableArt // Growing with time
class DLL_EXPORT CCommanderArt : public IModableArt // Growing with time
{
public:
ui32 level;
CCommanderArt(){level = 0;};
void Init(){};
void SetProperty (int mod){level = mod;};
void Upgrade(){level++;};
template <typename Handler> void serialize(Handler &h, const int version)
{
h & static_cast<CArtifact&>(*this);
h & static_cast<IModableArt&>(*this);
h & level;
}
};
@ -104,6 +121,7 @@ public:
std::vector<CArtifact *> artifacts;
std::vector<CArtifact *> allowedArtifacts;
std::set<ui32> bigArtifacts; // Artifacts that cannot be moved to backpack, e.g. war machines.
std::map<ui32, ui8> modableArtifacts; //1-scroll, 2-banner, 3-commander art with progressive bonus
void loadArtifacts(bool onlyTxt);
void sortArts();
@ -116,8 +134,8 @@ public:
void getAllowed(std::vector<CArtifact*> &out, int flags);
void erasePickedArt (si32 id);
bool isBigArtifact (ui32 artID) {return bigArtifacts.find(artID) != bigArtifacts.end();}
void equipArtifact (std::map<ui16, ui32> &artifWorn, ui16 slotID, ui32 artifactID);
void unequipArtifact (std::map<ui16, ui32> &artifWorn, ui16 slotID);
void equipArtifact (std::map<ui16, CArtifact*> &artifWorn, ui16 slotID, const CArtifact* art);
void unequipArtifact (std::map<ui16, CArtifact*> &artifWorn, ui16 slotID);
void initAllowedArtifactsList(const std::vector<ui8> &allowed); //allowed[art_id] -> 0 if not allowed, 1 if allowed
static int convertMachineID(int id, bool creToArt);
CArtHandler();

View File

@ -522,7 +522,7 @@ void CCampaignScenario::prepareCrossoverHeroes( std::vector<CGHeroInstance *> he
{
BOOST_FOREACH(CGHeroInstance * cgh, crossoverHeroes)
{
cgh->artifacts -= g;
cgh->artifacts -= VLC->arth->artifacts[g];
}
}
}

View File

@ -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<ui16,ui32>::const_iterator i = artifWorn.begin(); i != artifWorn.end(); i++)
if(i->second == aid)
for(std::map<ui16,CArtifact*>::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<ui16>::const_iterator it = artifact.possibleSlots.begin(); it != artifact.possibleSlots.end(); ++it)
for (std::vector<ui16>::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<ui16,ui32>::const_iterator i = artifWorn.begin(); i != artifWorn.end(); i++)
if(i->second == aid)
for(std::vector<CArtifact*>::const_iterator i = artifacts.begin(); i != artifacts.end(); i++)
if((*i)->id == aid)
return true;
for(std::map<ui16,CArtifact*>::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<ui16,ui32>::const_iterator i = artifWorn.begin(); i != artifWorn.end(); i++)
out.insert(VLC->arth->artifacts[i->second]);
for (std::map<ui16,CArtifact*>::const_iterator i = artifWorn.begin(); i != artifWorn.end(); i++)
out.insert(i->second);
out.insert(&speciality);
}
@ -3594,24 +3591,36 @@ void CGArtifact::initObj()
blockVisit = true;
if(ID == 5)
hoverName = VLC->arth->artifacts[subID]->Name();
if(ID == 93)
subID = 1;
}
void CGArtifact::onHeroVisit( const CGHeroInstance * h ) const
{
if(!stacksCount())
{
if(ID == 5)
InfoWindow iw;
iw.soundID = soundBase::treasure;
iw.player = h->tempOwner;
switch(ID)
{
InfoWindow iw;
iw.soundID = soundBase::treasure;
iw.player = h->tempOwner;
iw.components.push_back(Component(4,subID,0,0));
if(message.length())
iw.text << message;
else
iw.text << std::pair<ui8,ui32>(12,subID);
cb->showInfoDialog(&iw);
case 5:
{
iw.components.push_back(Component(4,subID,0,0));
if(message.length())
iw.text << message;
else
iw.text << std::pair<ui8,ui32>(12,subID);
}
break;
case 93:
iw.components.push_back (Component(Component::SPELL, spell,0,0));
iw.text.addTxt (MetaString::ADVOB_TXT,135);
iw.text.addReplacement(MetaString::SPELL_NAME, spell);
break;
}
cb->showInfoDialog(&iw);
pick(h);
}
else
@ -3632,14 +3641,23 @@ void CGArtifact::onHeroVisit( const CGHeroInstance * h ) const
void CGArtifact::pick(const CGHeroInstance * h) const
{
if(ID == 5) //Artifact
if (VLC->arth->artifacts[subID]->isModable())
{//TODO: create new instance, initialize it
if (ID == 93) //scroll
{
NewArtifact na;
na.value = spell;
na.artid = subID;
cb->sendAndApply(&na);
cb->giveNewArtifact(h->id, -2);
}
else
cb->giveNewArtifact(h->id, -2);; //nothing / zero / empty by default
}
else
{
cb->giveHeroArtifact(subID,h->id,-2);
}
else if(ID == 93) // Spell scroll
{
//TODO: support for the spell scroll
}
cb->removeObject(id);
}
@ -4373,7 +4391,7 @@ void CGSeerHut::finishQuest (const CGHeroInstance * h, ui32 accept) const
case CQuest::MISSION_ART:
for (std::vector<ui16>::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:

View File

@ -47,6 +47,7 @@ struct InfoWindow;
struct Component;
struct BankConfig;
struct UpdateHeroSpeciality;
struct NewArtifact;
class CGBoat;
class DLL_EXPORT CQuest
@ -266,8 +267,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<ui32> artifacts; //hero's artifacts from bag
std::map<ui16,ui32> artifWorn; //map<position,artifact_id>; 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<CArtifact*> artifacts; //hero's artifacts from bag
std::map<ui16, CArtifact*> artifWorn; //map<position,artifact_id>; 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<ui32> spells; //known spells (spell IDs)
struct DLL_EXPORT Patrol
@ -337,7 +338,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)

View File

@ -1949,7 +1949,7 @@ void CGameState::init( StartInfo * si, ui32 checksum, int Seed )
CGHeroInstance *hero = k->second.heroes[0];
std::vector<ui16>::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);
}

View File

@ -61,6 +61,7 @@ struct TerrainTile;
class CHeroClass;
class CCampaign;
class CCampaignState;
class IModableArt;
namespace boost
{
@ -142,7 +143,8 @@ public:
template <typename Handler> void serialize(Handler &h, const int version)
{
h & color & human & currentSelection & team & resources & status;
h & heroes & towns & availableHeroes & dwellings & bonuses & status & daysWithoutCastle;
h & heroes & towns & availableHeroes & dwellings & bonuses;
h & status & daysWithoutCastle;
h & enteredLosingCheatCode & enteredWinningCheatCode;
h & static_cast<CBonusSystemNode&>(*this);
}

View File

@ -402,8 +402,9 @@ CSerializer::CSerializer()
void CSerializer::addStdVecItems(CGameState *gs, LibClasses *lib)
{
registerVectoredType(&gs->map->objects, &CGObjectInstance::id);
registerVectoredType(&lib->heroh->heroes, &CHero::ID);
registerVectoredType(&lib->creh->creatures, &CCreature::idNumber);
registerVectoredType(&lib->arth->artifacts, &CArtifact::id);
registerVectoredType(&lib->heroh->heroes, &CHero::ID);
registerVectoredType(&gs->map->artInstances, &IModableArt::ID);
smartVectorMembersSerialization = true;
}

View File

@ -93,7 +93,8 @@ 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 void giveNewArtifact(int hid, int position)=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<void(BattleResult*)> 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<void(BattleResult*)> 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<void(BattleResult*)> 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

View File

@ -602,18 +602,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<ui32> artifacts; //hero's artifacts from bag
std::map<ui16,ui32> artifWorn; //map<position,artifact_id>; 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<CArtifact*> artifacts; //hero's artifacts from bag
std::map<ui16,CArtifact*> artifWorn; //map<position,artifact_id>; 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 <typename Handler> void serialize(Handler &h, const int version)
{
h & hid & artifacts & artifWorn;
}
std::vector<ui32> equiped, unequiped; //used locally
std::vector<CArtifact*> equiped, unequiped; //used locally
BonusList gained, lost; //used locally as hlp when applying
};
@ -697,6 +697,21 @@ struct SetAvailableArtifacts : public CPackForClient //519
}
};
struct NewArtifact : public CPackForClient
{
NewArtifact(){type = 520;};
//void applyCl(CClient *cl);
DLL_EXPORT void applyGs(CGameState *gs);
si32 artid;
si32 value; //initializing parameter
template <typename Handler> void serialize(Handler &h, const int version)
{
h & artid & value;
}
};
struct NewTurn : public CPackForClient //101
{
enum weekType {NORMAL, DOUBLE_GROWTH, BONUS_GROWTH, DEITYOFFIRE, PLAGUE, CUSTOM, NO_ACTION, NONE};

View File

@ -451,20 +451,22 @@ DLL_EXPORT void SetHeroesInTown::applyGs( CGameState *gs )
DLL_EXPORT void SetHeroArtifacts::applyGs( CGameState *gs )
{
CGHeroInstance *h = gs->getHero(hid);
for(std::map<ui16,ui32>::const_iterator i = h->artifWorn.begin(); i != h->artifWorn.end(); i++)
for(std::map<ui16,CArtifact*>::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<ui16,ui32>::const_iterator i = artifWorn.begin(); i != artifWorn.end(); i++)
for(std::map<ui16,CArtifact*>::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);
}
//update hero data
h->artifacts = artifacts;
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 +479,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<CArtifact*>(art));
else
artifacts.push_back(art);
artifacts.push_back(const_cast<CArtifact*>(art));
}
}
}
@ -584,6 +586,31 @@ DLL_EXPORT void NewObject::applyGs( CGameState *gs )
o->initObj();
assert(o->defInfo);
}
DLL_EXPORT void NewArtifact::applyGs( CGameState *gs )
{
IModableArt * art;
std::map<ui32,ui8>::iterator itr = VLC->arth->modableArtifacts.find(artid);
switch (itr->second)
{
case 1:
art = new CScroll;
break;
case 2:
art = new CCustomizableArt;
break;
case 3:
art = new CCommanderArt;
break;
default:
tlog1<<"unhandled customizable artifact!\n";
};
*art = *static_cast<IModableArt*>(VLC->arth->artifacts[artid]); //copy properties
art->ID = gs->map->artInstances.size();
art->SetProperty (value); //init scroll, banner, commander art
art->Init(); //set bonuses for new instance
gs->map->artInstances.push_back(art);
}
DLL_EXPORT void SetAvailableArtifacts::applyGs( CGameState *gs )
{

View File

@ -137,6 +137,7 @@ void registerTypes2(Serializer &s)
s.template registerType<AdvmapSpellCast>();
s.template registerType<OpenWindow>();
s.template registerType<NewObject>();
s.template registerType<NewArtifact>();
s.template registerType<SetAvailableArtifacts>();
s.template registerType<SaveGame>();

View File

@ -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;

View File

@ -30,7 +30,7 @@ class CGHeroInstance;
class CGCreature;
class CQuest;
class CGTownInstance;
class IModableArt;
struct DLL_EXPORT TerrainTile
@ -279,6 +279,7 @@ struct DLL_EXPORT Mapa : public CMapHeader
std::vector<CGObjectInstance*> objects;
std::vector<CGHeroInstance*> heroes;
std::vector<CGTownInstance*> towns;
std::vector<IModableArt *> artInstances; //stores single scrolls
std::map<ui16, CGCreature*> monsters;
std::map<ui16, CGHeroInstance*> heroesToBeat;
@ -313,7 +314,7 @@ struct DLL_EXPORT Mapa : public CMapHeader
{
h & static_cast<CMapHeader&>(*this);
h & rumors & allowedSpell & allowedAbilities & allowedArtifact & allowedHeroes & events & grailPos;
h & monsters & heroesToBeat; //hoprfully serialization is now automagical?
h & monsters & heroesToBeat & artInstances; //hopefully serialization is now automagical?
//TODO: viccondetails
if(h.saving)

View File

@ -2225,7 +2225,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;
@ -2237,38 +2237,84 @@ void CGameHandler::giveHeroArtifact(int artid, int hid, int position) //pos==-1
if(position == -2)
{
int i;
for(i=0; i<art.possibleSlots.size(); i++) //try to put artifact into first available slot
for(i=0; i<art->possibleSlots.size(); i++) //try to put artifact into first available slot
{
if(art.fitsAt(sha.artifWorn, art.possibleSlots[i]))
if(art->fitsAt(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(art.fitsAt(sha.artifWorn, ui16(position)))
if(art->fitsAt(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)
void CGameHandler::giveNewArtifact(int hid, int position)
{
const CGHeroInstance* h = getHero(hid);
CArtifact * art = gs->map->artInstances.back(); //we use it only to immediatelly equip new artifact
SetHeroArtifacts sha;
sha.hid = hid;
sha.artifacts = h->artifacts;
sha.artifWorn = h->artifWorn;
if(position<0)
{
if(position == -2)
{
int i;
for(i=0; i<art->possibleSlots.size(); i++) //try to put artifact into first available slot
{
if( !vstd::contains(sha.artifWorn, art->possibleSlots[i]) )
{
//we've found a free suitable slot
VLC->arth->equipArtifact(sha.artifWorn, art->possibleSlots[i], art);
break;
}
}
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
{
sha.artifacts.push_back(art);
}
}
else
{
if(!vstd::contains(sha.artifWorn,ui16(position)))
{
VLC->arth->equipArtifact(sha.artifWorn, position, art);
}
else if (!art->isBig())
{
sha.artifacts.push_back(art);
}
}
sendAndApply(&sha);
}
bool CGameHandler::removeArtifact(CArtifact* art, int hid)
{
const CGHeroInstance* h = getHero(hid);
@ -2277,15 +2323,15 @@ bool CGameHandler::removeArtifact(int artid, int hid)
sha.artifacts = h->artifacts;
sha.artifWorn = h->artifWorn;
std::vector<ui32>::iterator it;
if ((it = std::find(sha.artifacts.begin(), sha.artifacts.end(), artid)) != sha.artifacts.end()) //it is in backpack
std::vector<CArtifact*>::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<ui16,ui32>::iterator itr;
std::map<ui16,CArtifact*>::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;
@ -2760,7 +2806,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;
@ -3152,7 +3198,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;
}
@ -3186,14 +3232,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)
@ -3211,7 +3257,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);
@ -3243,20 +3289,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;
}
@ -3265,32 +3315,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<ui16, ui32>::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<ui16, CArtifact*>::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;
@ -3303,19 +3364,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;
}
}
@ -4049,9 +4118,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
@ -4108,10 +4177,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);
}
@ -5231,13 +5300,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;
}

View File

@ -143,8 +143,9 @@ public:
void vistiCastleObjects (const CGTownInstance *t, const CGHeroInstance *h);
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 giveNewArtifact(int hid, int position);
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<void(BattleResult*)> cb = 0, const CGTownInstance *town = NULL); //use hero=NULL for no hero
void startBattleI(const CArmedInstance *army1, const CArmedInstance *army2, int3 tile, boost::function<void(BattleResult*)> 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<void(BattleResult*)> 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<void(BattleResult*)> cb); //for hero<=>neutral army
@ -222,7 +223,7 @@ public:
void run(bool resume);
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;
};

View File

@ -166,7 +166,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!");
}