1
0
mirror of https://github.com/vcmi/vcmi.git synced 2025-07-17 01:32:21 +02:00

* fixed crashes with paths when fastly switching heroes

* fixed and improved slider behavior
* fixed possible thread access conflicts
* support for attacking town with visiting hero
* fixed dwellings saving
* minor improvements
This commit is contained in:
Michał W. Urbańczyk
2009-09-12 22:17:23 +00:00
parent a939e134a1
commit efb1049860
15 changed files with 92 additions and 45 deletions

View File

@ -738,6 +738,13 @@ void CCallback::setSelection(const CArmedInstance * obj)
ss.player = player; ss.player = player;
ss.id = obj->id; ss.id = obj->id;
sendRequest(&ss); sendRequest(&ss);
if(obj->ID == HEROI_TYPE)
{
cl->gs->calculatePaths(static_cast<const CGHeroInstance *>(obj), *cl->pathInfo);
//nasty workaround. TODO: nice workaround
cl->gs->getPlayer(player)->currentSelection = obj->id;
}
} }
void CCallback::recruitHero(const CGTownInstance *town, const CGHeroInstance *hero) void CCallback::recruitHero(const CGTownInstance *town, const CGHeroInstance *hero)

View File

@ -91,6 +91,7 @@ AdventureMapButton::AdventureMapButton ()
ourObj=NULL; ourObj=NULL;
state=0; state=0;
blocked = actOnDown = false; blocked = actOnDown = false;
used = LCLICK | RCLICK | HOVER | KEYBOARD;
} }
//AdventureMapButton::AdventureMapButton( std::string Name, std::string HelpBox, boost::function<void()> Callback, int x, int y, std::string defName, bool activ, std::vector<std::string> * add, bool playerColoredButton) //AdventureMapButton::AdventureMapButton( std::string Name, std::string HelpBox, boost::function<void()> Callback, int x, int y, std::string defName, bool activ, std::vector<std::string> * add, bool playerColoredButton)
//{ //{
@ -435,10 +436,9 @@ void CHighlightableButtonsGroup::block( ui8 on )
void CSlider::sliderClicked() void CSlider::sliderClicked()
{ {
if(!moving) if(!(active & MOVE))
{ {
activateMouseMove(); activateMouseMove();
moving = true;
} }
} }
@ -527,26 +527,24 @@ void CSlider::clickLeft(tribool down, bool previousState)
float rw = 0; float rw = 0;
if(horizontal) if(horizontal)
{ {
pw = GH.current->motion.x-pos.x-16; pw = GH.current->motion.x-pos.x-25;
rw = pw / ((float)(pos.w-48)); rw = pw / ((float)(pos.w-48));
} }
else else
{ {
pw = GH.current->motion.y-pos.y-16; pw = GH.current->motion.y-pos.y-24;
rw = pw / ((float)(pos.h-48)); rw = pw / ((float)(pos.h-48));
} }
if(pw < 0 || pw > (horizontal ? pos.w : pos.h) - 32) if(pw < -8 || pw > (horizontal ? pos.w : pos.h) - 40)
return; return;
// if (rw>1) return; // if (rw>1) return;
// if (rw<0) return; // if (rw<0) return;
slider->clickLeft(true, slider->pressedL);
moveTo(rw * positions + 0.5f); moveTo(rw * positions + 0.5f);
return; return;
} }
if(moving) if(active & MOVE)
{
deactivateMouseMove(); deactivateMouseMove();
moving = false;
}
} }
CSlider::~CSlider() CSlider::~CSlider()
@ -561,7 +559,6 @@ CSlider::CSlider(int x, int y, int totalw, boost::function<void(int)> Moved, int
setAmount(amount); setAmount(amount);
used = LCLICK; used = LCLICK;
moving = false;
strongInterest = true; strongInterest = true;

View File

@ -120,7 +120,7 @@ public:
amount, //how many elements amount, //how many elements
positions, //number of highest position (0 if there is only one) positions, //number of highest position (0 if there is only one)
value; //first active element value; //first active element
bool horizontal, moving; bool horizontal;
CDefEssential *imgs ; CDefEssential *imgs ;
boost::function<void(int)> moved; boost::function<void(int)> moved;

View File

@ -1896,13 +1896,17 @@ void CAdvMapInt::select(const CArmedInstance *sel )
{ {
int pos = vstd::findPos(townList.items,sel); int pos = vstd::findPos(townList.items,sel);
townList.selected = pos; townList.selected = pos;
townList.fixPos();
} }
else //hero selected else //hero selected
{ {
const CGHeroInstance *h = static_cast<const CGHeroInstance*>(sel); const CGHeroInstance *h = static_cast<const CGHeroInstance*>(sel);
if(LOCPLINT->getWHero(heroList.selected) != h) if(LOCPLINT->getWHero(heroList.selected) != h)
{
heroList.selected = heroList.getPosOfHero(h); heroList.selected = heroList.getPosOfHero(h);
heroList.fixPos();
}
if(vstd::contains(paths,h)) //hero has assigned path if(vstd::contains(paths,h)) //hero has assigned path
{ {

View File

@ -1504,12 +1504,14 @@ void CPlayerInterface::requestRealized( PackageApplied *pa )
void CPlayerInterface::heroExchangeStarted(si32 hero1, si32 hero2) void CPlayerInterface::heroExchangeStarted(si32 hero1, si32 hero2)
{ {
boost::unique_lock<boost::recursive_mutex> un(*pim);
GH.pushInt(new CExchangeWindow(hero2, hero1)); GH.pushInt(new CExchangeWindow(hero2, hero1));
} }
void CPlayerInterface::objectPropertyChanged(const SetObjectProperty * sop) void CPlayerInterface::objectPropertyChanged(const SetObjectProperty * sop)
{ {
//redraw minimap if owner changed //redraw minimap if owner changed
boost::unique_lock<boost::recursive_mutex> un(*pim);
if(sop->what == 1) if(sop->what == 1)
{ {
const CGObjectInstance * obj = cb->getObjectInfo(sop->id); const CGObjectInstance * obj = cb->getObjectInfo(sop->id);

View File

@ -104,9 +104,9 @@ public:
void heroVisitCastle(int obj, int heroID){}; void heroVisitCastle(int obj, int heroID){};
void stopHeroVisitCastle(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 void giveHeroArtifact(int artid, int hid, int position){}; //pos==-1 - first free slot in backpack=0; pos==-2 - default if available or backpack
void startBattleI(const CArmedInstance *army1, const CArmedInstance *army2, int3 tile, const CGHeroInstance *hero1, const CGHeroInstance *hero2, bool creatureBank, 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, 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, bool creatureBank, boost::function<void(BattleResult*)> cb = 0){}; //if any of armies is hero, hero will be used 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, bool creatureBank, boost::function<void(BattleResult*)> cb = 0){}; //if any of armies is hero, hero will be used, visitable tile of second obj is place of battle 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 setAmount(int objid, ui32 val){}; void setAmount(int objid, ui32 val){};
bool moveHero(si32 hid, int3 dst, ui8 instant, ui8 asker = 255){return false;}; bool moveHero(si32 hid, int3 dst, ui8 instant, ui8 asker = 255){return false;};
void giveHeroBonus(GiveBonus * bonus){}; void giveHeroBonus(GiveBonus * bonus){};

View File

@ -1126,6 +1126,20 @@ CList::CList(int Size)
{ {
} }
void CList::fixPos()
{
int oldFrom = from;
if(selected < 0) //no selection, do nothing
return;
if(selected < from) //scroll up
from = selected;
else if(from + SIZE <= selected)
from = selected - SIZE + 1;
amin(from, size() - SIZE);
amax(from, 0);
}
CHeroList::CHeroList(int Size) CHeroList::CHeroList(int Size)
:CList(Size), heroes(LOCPLINT->wanderingHeroes) :CList(Size), heroes(LOCPLINT->wanderingHeroes)
{ {
@ -1422,6 +1436,12 @@ void CHeroList::show( SDL_Surface * to )
{ {
} }
int CHeroList::size()
{
return heroes.size();
}
CTownList::~CTownList() CTownList::~CTownList()
{ {
delete arrup; delete arrup;
@ -1659,6 +1679,11 @@ void CTownList::show( SDL_Surface * to )
} }
int CTownList::size()
{
return items.size();
}
CCreaturePic::CCreaturePic(const CCreature *cre, bool Big) CCreaturePic::CCreaturePic(const CCreature *cre, bool Big)
:c(cre),big(Big) :c(cre),big(Big)
{ {

View File

@ -272,6 +272,8 @@ public:
virtual void genList()=0; virtual void genList()=0;
virtual void select(int which)=0; virtual void select(int which)=0;
virtual void draw(SDL_Surface * to)=0; virtual void draw(SDL_Surface * to)=0;
virtual int size() = 0; //how many elements do we have
void fixPos(); //scrolls list, so the selection will be visible
}; };
class CHeroList class CHeroList
: public CList : public CList
@ -295,6 +297,7 @@ public:
void draw(SDL_Surface * to); void draw(SDL_Surface * to);
void show(SDL_Surface * to); void show(SDL_Surface * to);
void init(); void init();
int size(); //how many elements do we have
}; };
class CTownList class CTownList
@ -316,6 +319,7 @@ public:
void keyPressed (const SDL_KeyboardEvent & key); //call-in void keyPressed (const SDL_KeyboardEvent & key); //call-in
void draw(SDL_Surface * to); void draw(SDL_Surface * to);
void show(SDL_Surface * to); void show(SDL_Surface * to);
int size(); //how many elements do we have
}; };
class CCreaturePic //draws picture with creature on background, use nextFrame=true to get animation class CCreaturePic //draws picture with creature on background, use nextFrame=true to get animation

View File

@ -547,7 +547,7 @@ void SetSelection::applyCl(CClient *cl)
if(!h) if(!h)
return; return;
CPackForClient::GS(cl)->calculatePaths(h, *cl->pathInfo); //CPackForClient::GS(cl)->calculatePaths(h, *cl->pathInfo);
} }
void ShowInInfobox::applyCl(CClient *cl) void ShowInInfobox::applyCl(CClient *cl)

View File

@ -777,10 +777,12 @@ void CGHeroInstance::onHeroVisit(const CGHeroInstance * h) const
//exchange //exchange
cb->heroExchange(id, h->id); cb->heroExchange(id, h->id);
} }
else else //battle
{ {
//battle if(visitedTown) //we're in town
cb->startBattleI(h, this, false); visitedTown->onHeroVisit(h); //town will handle attacking
else
cb->startBattleI(h, this);
} }
} }
else if(ID == 62) //prison else if(ID == 62) //prison
@ -1350,7 +1352,7 @@ void CGDwelling::heroAcceptsCreatures( const CGHeroInstance *h, ui32 answer ) co
void CGDwelling::wantsFight( const CGHeroInstance *h, ui32 answer ) const void CGDwelling::wantsFight( const CGHeroInstance *h, ui32 answer ) const
{ {
if(answer) if(answer)
cb->startBattleI(h, this, false, boost::bind(&CGDwelling::fightOver, this, h, _1)); cb->startBattleI(h, this, boost::bind(&CGDwelling::fightOver, this, h, _1));
} }
void CGDwelling::fightOver(const CGHeroInstance *h, BattleResult *result) const void CGDwelling::fightOver(const CGHeroInstance *h, BattleResult *result) const
@ -1503,7 +1505,7 @@ void CGTownInstance::onHeroVisit(const CGHeroInstance * h) const
if(getOwner() != h->getOwner()) if(getOwner() != h->getOwner())
{ {
//TODO ally check //TODO ally check
if(army) if(army || visitingHero)
{ {
const CGHeroInstance *defendingHero = NULL; const CGHeroInstance *defendingHero = NULL;
if(visitingHero) if(visitingHero)
@ -2226,7 +2228,7 @@ void CGCreature::joinDecision(const CGHeroInstance *h, int cost, ui32 accept) co
void CGCreature::fight( const CGHeroInstance *h ) const void CGCreature::fight( const CGHeroInstance *h ) const
{ {
cb->startBattleI(h, this, false, boost::bind(&CGCreature::endBattle,this,_1)); cb->startBattleI(h, this, boost::bind(&CGCreature::endBattle,this,_1));
} }
void CGCreature::flee( const CGHeroInstance * h ) const void CGCreature::flee( const CGHeroInstance * h ) const
@ -2362,7 +2364,7 @@ void CGResource::collectRes( int player ) const
void CGResource::fightForRes(ui32 agreed, const CGHeroInstance *h) const void CGResource::fightForRes(ui32 agreed, const CGHeroInstance *h) const
{ {
if(agreed) if(agreed)
cb->startBattleI(h, this, false, boost::bind(&CGResource::endBattle,this,_1,h)); cb->startBattleI(h, this, boost::bind(&CGResource::endBattle,this,_1,h));
} }
void CGResource::endBattle( BattleResult *result, const CGHeroInstance *h ) const void CGResource::endBattle( BattleResult *result, const CGHeroInstance *h ) const
@ -2614,7 +2616,7 @@ void CGArtifact::pick(const CGHeroInstance * h) const
void CGArtifact::fightForArt( ui32 agreed, const CGHeroInstance *h ) const void CGArtifact::fightForArt( ui32 agreed, const CGHeroInstance *h ) const
{ {
if(agreed) if(agreed)
cb->startBattleI(h, this, false, boost::bind(&CGArtifact::endBattle,this,_1,h)); cb->startBattleI(h, this, boost::bind(&CGArtifact::endBattle,this,_1,h));
} }
void CGArtifact::endBattle( BattleResult *result, const CGHeroInstance *h ) const void CGArtifact::endBattle( BattleResult *result, const CGHeroInstance *h ) const
@ -3118,7 +3120,7 @@ void CGPandoraBox::open( const CGHeroInstance * h, ui32 accept ) const
iw.player = h->tempOwner; iw.player = h->tempOwner;
iw.text.addTxt(MetaString::ADVOB_TXT, 16); iw.text.addTxt(MetaString::ADVOB_TXT, 16);
cb->showInfoDialog(&iw); cb->showInfoDialog(&iw);
cb->startBattleI(h, this, false, boost::bind(&CGPandoraBox::endBattle, this, h, _1)); //grants things after battle cb->startBattleI(h, this, boost::bind(&CGPandoraBox::endBattle, this, h, _1)); //grants things after battle
} }
else if (message.size() == 0 && resources.size() == 0 else if (message.size() == 0 && resources.size() == 0
&& primskills.size() == 0 && abilities.size() == 0 && primskills.size() == 0 && abilities.size() == 0
@ -3415,7 +3417,7 @@ void CGEvent::activated( const CGHeroInstance * h ) const
else else
iw.text.addTxt(MetaString::ADVOB_TXT, 16); iw.text.addTxt(MetaString::ADVOB_TXT, 16);
cb->showInfoDialog(&iw); cb->showInfoDialog(&iw);
cb->startBattleI(h, this, false, boost::bind(&CGEvent::endBattle,this,h,_1)); cb->startBattleI(h, this, boost::bind(&CGEvent::endBattle,this,h,_1));
} }
else else
{ {
@ -3623,7 +3625,7 @@ void CGGarrison::onHeroVisit (const CGHeroInstance *h) const
{ {
if (h->tempOwner != tempOwner && army) { if (h->tempOwner != tempOwner && army) {
//TODO: Find a way to apply magic garrison effects in battle. //TODO: Find a way to apply magic garrison effects in battle.
cb->startBattleI(h, this, false, boost::bind(&CGGarrison::fightOver, this, h, _1)); cb->startBattleI(h, this, boost::bind(&CGGarrison::fightOver, this, h, _1));
return; return;
} }
@ -4026,7 +4028,7 @@ void CBank::fightGuards (const CGHeroInstance * h, ui32 accept) const
if (accept) if (accept)
{ {
cb->setObjProperty (id, 17, ran()); //get army cb->setObjProperty (id, 17, ran()); //get army
cb->startBattleI (h, this, true, boost::bind (&CBank::endBattle, this, h, _1)); cb->startBattleI (h, this, boost::bind (&CBank::endBattle, this, h, _1), true);
} }
} }
void CBank::endBattle (const CGHeroInstance *h, const BattleResult *result) const void CBank::endBattle (const CGHeroInstance *h, const BattleResult *result) const

View File

@ -1485,16 +1485,22 @@ void CGameState::init(StartInfo * si, Mapa * map, int Seed)
//init visiting and garrisoned heroes //init visiting and garrisoned heroes
for(unsigned int l=0; l<k->second.heroes.size();l++) for(unsigned int l=0; l<k->second.heroes.size();l++)
{ {
CGHeroInstance *h = k->second.heroes[l];
for(unsigned int m=0; m<k->second.towns.size();m++) for(unsigned int m=0; m<k->second.towns.size();m++)
{ {
int3 vistile = k->second.towns[m]->pos; vistile.x--; //tile next to the entrance CGTownInstance *t = k->second.towns[m];
if(vistile == k->second.heroes[l]->pos || k->second.heroes[l]->pos==k->second.towns[m]->pos) int3 vistile = t->pos; vistile.x--; //tile next to the entrance
if(vistile == h->pos || h->pos==t->pos)
{ {
k->second.towns[m]->visitingHero = k->second.heroes[l]; t->visitingHero = h;
k->second.heroes[l]->visitedTown = k->second.towns[m]; h->visitedTown = t;
k->second.heroes[l]->inTownGarrison = false; h->inTownGarrison = false;
if(k->second.heroes[l]->pos==k->second.towns[m]->pos) if(h->pos == t->pos) //visiting hero placed in the editor has same pos as the town - we need to correct it
k->second.heroes[l]->pos.x -= 1; {
map->removeBlockVisTiles(h);
h->pos.x -= 1;
map->addBlockVisTiles(h);
}
break; break;
} }
} }

View File

@ -80,9 +80,9 @@ public:
virtual void heroVisitCastle(int obj, int heroID)=0; virtual void heroVisitCastle(int obj, int heroID)=0;
virtual void stopHeroVisitCastle(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 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 void startBattleI(const CArmedInstance *army1, const CArmedInstance *army2, int3 tile, const CGHeroInstance *hero1, const CGHeroInstance *hero2, bool creatureBank, 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, 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, bool creatureBank, boost::function<void(BattleResult*)> cb = 0)=0; //if any of armies is hero, hero will be used 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, bool creatureBank, boost::function<void(BattleResult*)> cb = 0)=0; //if any of armies is hero, hero will be used, visitable tile of second obj is place of battle 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
//virtual void startBattleI(int heroID, CCreatureSet army, int3 tile, boost::function<void(BattleResult*)> cb)=0; //for hero<=>neutral army //virtual void startBattleI(int heroID, CCreatureSet army, int3 tile, boost::function<void(BattleResult*)> cb)=0; //for hero<=>neutral army
virtual void setAmount(int objid, ui32 val)=0; virtual void setAmount(int objid, ui32 val)=0;
virtual bool moveHero(si32 hid, int3 dst, ui8 instant, ui8 asker = 255)=0; virtual bool moveHero(si32 hid, int3 dst, ui8 instant, ui8 asker = 255)=0;

View File

@ -25,6 +25,7 @@ void registerTypes1(Serializer &s)
s.template registerType<CTownBonus>(); s.template registerType<CTownBonus>();
s.template registerType<CGPandoraBox>(); s.template registerType<CGPandoraBox>();
s.template registerType<CGEvent>(); s.template registerType<CGEvent>();
s.template registerType<CGDwelling>();
s.template registerType<CGVisitableOPH>(); s.template registerType<CGVisitableOPH>();
s.template registerType<CGVisitableOPW>(); s.template registerType<CGVisitableOPW>();
s.template registerType<CGTeleport>(); s.template registerType<CGTeleport>();

View File

@ -1501,7 +1501,7 @@ bool CGameHandler::moveHero( si32 hid, int3 dst, ui8 instant, ui8 asker /*= 255*
return true; return true;
} }
//TODO: check for ally //TODO: check for ally
startBattleI(h, dh, false); startBattleI(h, dh);
return true; return true;
} }
} }
@ -1670,7 +1670,7 @@ void CGameHandler::startBattleI(const CArmedInstance *army1, const CArmedInstanc
boost::thread(boost::bind(&CGameHandler::startBattle, this, army1, army2, tile, hero1, hero2, creatureBank, cb, town)); boost::thread(boost::bind(&CGameHandler::startBattle, this, army1, army2, tile, hero1, hero2, creatureBank, cb, town));
} }
void CGameHandler::startBattleI( const CArmedInstance *army1, const CArmedInstance *army2, int3 tile, bool creatureBank, boost::function<void(BattleResult*)> cb ) void CGameHandler::startBattleI( const CArmedInstance *army1, const CArmedInstance *army2, int3 tile, boost::function<void(BattleResult*)> cb, bool creatureBank )
{ {
startBattleI(army1, army2, tile, startBattleI(army1, army2, tile,
army1->ID == HEROI_TYPE ? static_cast<const CGHeroInstance*>(army1) : NULL, army1->ID == HEROI_TYPE ? static_cast<const CGHeroInstance*>(army1) : NULL,
@ -1678,9 +1678,9 @@ void CGameHandler::startBattleI( const CArmedInstance *army1, const CArmedInstan
creatureBank, cb); creatureBank, cb);
} }
void CGameHandler::startBattleI( const CArmedInstance *army1, const CArmedInstance *army2, bool creatureBank, boost::function<void(BattleResult*)> cb) void CGameHandler::startBattleI( const CArmedInstance *army1, const CArmedInstance *army2, boost::function<void(BattleResult*)> cb, bool creatureBank)
{ {
startBattleI(army1, army2, army2->pos - army2->getVisitableOffset(), creatureBank, cb); startBattleI(army1, army2, army2->pos - army2->getVisitableOffset(), cb, creatureBank);
} }
//void CGameHandler::startBattleI(int heroID, CCreatureSet army, int3 tile, boost::function<void(BattleResult*)> cb) //for hero<=>neutral army //void CGameHandler::startBattleI(int heroID, CCreatureSet army, int3 tile, boost::function<void(BattleResult*)> cb) //for hero<=>neutral army

View File

@ -122,10 +122,9 @@ public:
void giveHeroArtifact(int artid, int hid, int position); //pos==-1 - first free slot in backpack; pos==-2 - default if available or backpack 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); void moveArtifact(int hid, int oldPosition, int destPos);
void removeArtifact(int hid, int pos); void removeArtifact(int hid, int pos);
void startBattleI(const CArmedInstance *army1, const CArmedInstance *army2, int3 tile, const CGHeroInstance *hero1, const CGHeroInstance *hero2, bool creatureBank, boost::function<void(BattleResult*)> cb, const CGTownInstance *town = NULL); //use hero=NULL for no hero 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, bool creatureBank, boost::function<void(BattleResult*)> cb); 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, bool creatureBank, boost::function<void(BattleResult*)> cb = 0); //if any of armies is hero, hero will be used, visitable tile of second obj is place of battle 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
//void startBattleI(int heroID, CCreatureSet army, int3 tile, boost::function<void(BattleResult*)> cb); //for hero<=>neutral army
void setAmount(int objid, ui32 val); void setAmount(int objid, ui32 val);
bool moveHero(si32 hid, int3 dst, ui8 instant, ui8 asker = 255); bool moveHero(si32 hid, int3 dst, ui8 instant, ui8 asker = 255);
void giveHeroBonus(GiveBonus * bonus); void giveHeroBonus(GiveBonus * bonus);