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

* support for battles in creature banks (hopefully)

This commit is contained in:
mateuszb 2009-08-17 10:47:08 +00:00
parent fbc117b034
commit e892913635
8 changed files with 164 additions and 135 deletions

View File

@ -76,7 +76,7 @@ void processCommand(const std::string &message);
static void setScreenRes(int w, int h, int bpp, bool fullscreen);
void dispose();
void playIntro();
void listenForEvents();
void listenForEvents();
void startGame(StartInfo * options);
void init()
@ -414,95 +414,95 @@ static void setScreenRes(int w, int h, int bpp, bool fullscreen)
SDL_ShowCursor(SDL_DISABLE);
}
void listenForEvents()
{
SDL_Event *ev = NULL;
while(1) //main SDL events loop
{
ev = new SDL_Event();
int ret = SDL_WaitEvent(ev);
if(ret == 0 || (ev->type==SDL_QUIT) || (ev->type == SDL_KEYDOWN && ev->key.keysym.sym==SDLK_F4 && (ev->key.keysym.mod & KMOD_ALT)))
{
LOCPLINT->pim->lock();
client->close();
console->end();
SDL_Delay(750);
tlog0 << "Ending...\n";
exit(EXIT_SUCCESS);
}
else if(ev->type == SDL_KEYDOWN && ev->key.keysym.sym==SDLK_F4)
{
boost::unique_lock<boost::recursive_mutex> lock(*LOCPLINT->pim);
bool full = !(screen->flags&SDL_FULLSCREEN);
setScreenRes(conf.cc.resx,conf.cc.resy,conf.cc.bpp,full);
GH.totalRedraw();
}
eventsM.lock();
events.push(ev);
eventsM.unlock();
}
}
void startGame(StartInfo * options)
{
if(gOnlyAI)
{
for (size_t i =0; i < options->playerInfos.size(); i++)
{
options->playerInfos[i].human = false;
}
}
if(screen->w != conf.cc.resx || screen->h != conf.cc.resy)
{
setScreenRes(conf.cc.resx,conf.cc.resy,conf.cc.bpp,conf.cc.fullscreen);
}
CClient cl;
if(options->mode == 0) //new game
{
timeHandler pomtime;
char portc[10];
SDL_itoa(conf.cc.port,portc,10);
CClient::runServer(portc);
tlog0<<"Preparing shared memory and starting server: "<<pomtime.getDif()<<std::endl;
pomtime.getDif();//reset timers
CConnection *c=NULL;
//wait until server is ready
tlog0<<"Waiting for server... ";
cl.waitForServer();
tlog0 << pomtime.getDif()<<std::endl;
while(!c)
{
try
{
tlog0 << "Establishing connection...\n";
c = new CConnection(conf.cc.server,portc,NAME);
}
catch(...)
{
tlog1 << "\nCannot establish connection! Retrying within 2 seconds" <<std::endl;
SDL_Delay(2000);
}
}
THC tlog0<<"\tConnecting to the server: "<<pomtime.getDif()<<std::endl;
cl.newGame(c,options);
client = &cl;
CGI->musich->stopMusic();
client->run();
//boost::thread t(boost::bind(&CClient::run,&cl));
}
else //load game
{
std::string fname = options->mapname;
boost::algorithm::erase_last(fname,".vlgm1");
cl.load(fname);
client = &cl;
CGI->musich->stopMusic();
client->run();
//boost::thread t(boost::bind(&CClient::run,&cl));
}
void listenForEvents()
{
SDL_Event *ev = NULL;
while(1) //main SDL events loop
{
ev = new SDL_Event();
int ret = SDL_WaitEvent(ev);
if(ret == 0 || (ev->type==SDL_QUIT) || (ev->type == SDL_KEYDOWN && ev->key.keysym.sym==SDLK_F4 && (ev->key.keysym.mod & KMOD_ALT)))
{
LOCPLINT->pim->lock();
client->close();
console->end();
SDL_Delay(750);
tlog0 << "Ending...\n";
exit(EXIT_SUCCESS);
}
else if(ev->type == SDL_KEYDOWN && ev->key.keysym.sym==SDLK_F4)
{
boost::unique_lock<boost::recursive_mutex> lock(*LOCPLINT->pim);
bool full = !(screen->flags&SDL_FULLSCREEN);
setScreenRes(conf.cc.resx,conf.cc.resy,conf.cc.bpp,full);
GH.totalRedraw();
}
eventsM.lock();
events.push(ev);
eventsM.unlock();
}
}
void startGame(StartInfo * options)
{
if(gOnlyAI)
{
for (size_t i =0; i < options->playerInfos.size(); i++)
{
options->playerInfos[i].human = false;
}
}
if(screen->w != conf.cc.resx || screen->h != conf.cc.resy)
{
setScreenRes(conf.cc.resx,conf.cc.resy,conf.cc.bpp,conf.cc.fullscreen);
}
CClient cl;
if(options->mode == 0) //new game
{
timeHandler pomtime;
char portc[10];
SDL_itoa(conf.cc.port,portc,10);
CClient::runServer(portc);
tlog0<<"Preparing shared memory and starting server: "<<pomtime.getDif()<<std::endl;
pomtime.getDif();//reset timers
CConnection *c=NULL;
//wait until server is ready
tlog0<<"Waiting for server... ";
cl.waitForServer();
tlog0 << pomtime.getDif()<<std::endl;
while(!c)
{
try
{
tlog0 << "Establishing connection...\n";
c = new CConnection(conf.cc.server,portc,NAME);
}
catch(...)
{
tlog1 << "\nCannot establish connection! Retrying within 2 seconds" <<std::endl;
SDL_Delay(2000);
}
}
THC tlog0<<"\tConnecting to the server: "<<pomtime.getDif()<<std::endl;
cl.newGame(c,options);
client = &cl;
CGI->musich->stopMusic();
client->run();
//boost::thread t(boost::bind(&CClient::run,&cl));
}
else //load game
{
std::string fname = options->mapname;
boost::algorithm::erase_last(fname,".vlgm1");
cl.load(fname);
client = &cl;
CGI->musich->stopMusic();
client->run();
//boost::thread t(boost::bind(&CClient::run,&cl));
}
}

View File

@ -32,7 +32,7 @@
* Full text of license available in license.txt file, in main folder
*
*/
namespace fs = boost::filesystem;
namespace fs = boost::filesystem;
void startGame(StartInfo * options);
CGPreGame * CGP;

View File

@ -101,9 +101,9 @@ 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
void startBattleI(const CArmedInstance *army1, const CArmedInstance *army2, int3 tile, const CGHeroInstance *hero1, const CGHeroInstance *hero2, boost::function<void(BattleResult*)> cb = 0){}; //use hero=NULL for no hero
void startBattleI(const CArmedInstance *army1, const CArmedInstance *army2, int3 tile, boost::function<void(BattleResult*)> cb = 0){}; //if any of armies is hero, hero will be used
void startBattleI(const CArmedInstance *army1, const CArmedInstance *army2, 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, int3 tile, const CGHeroInstance *hero1, const CGHeroInstance *hero2, bool creatureBank, boost::function<void(BattleResult*)> cb = 0){}; //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, 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 setAmount(int objid, ui32 val){};
bool moveHero(si32 hid, int3 dst, ui8 instant, ui8 asker = 255){return false;};
void giveHeroBonus(GiveBonus * bonus){};

View File

@ -31,4 +31,21 @@
66 83 117 134
66 83 100 117 134
49 66 83 117 134 151
49 66 83 100 117 134 151
49 66 83 100 117 134 151
//creature_bank
//attacker
57
57 61
57 61 90
57 61 90 93
57 61 90 93 96
57 61 90 93 96 125
57 61 90 93 96 125 129
//defender
2
2 15
2 15 100
2 15 100 185
2 15 100 185 172
2 15 100 185 172 87
2 15 100 185 172 87 8

View File

@ -677,7 +677,7 @@ void CGHeroInstance::onHeroVisit(const CGHeroInstance * h) const
else
{
//battle
cb->startBattleI(h, this);
cb->startBattleI(h, this, false);
}
}
else if(ID == 62) //prison
@ -1160,7 +1160,7 @@ void CGDwelling::heroAcceptsCreatures( const CGHeroInstance *h, ui32 answer ) co
void CGDwelling::wantsFight( const CGHeroInstance *h, ui32 answer ) const
{
if(answer)
cb->startBattleI(h, this, boost::bind(&CGDwelling::fightOver, this, h, _1));
cb->startBattleI(h, this, false, boost::bind(&CGDwelling::fightOver, this, h, _1));
}
void CGDwelling::fightOver(const CGHeroInstance *h, BattleResult *result) const
@ -1942,7 +1942,7 @@ void CGCreature::joinDecision(const CGHeroInstance *h, int cost, ui32 accept) co
void CGCreature::fight( const CGHeroInstance *h ) const
{
cb->startBattleI(h, this, boost::bind(&CGCreature::endBattle,this,_1));
cb->startBattleI(h, this, false, boost::bind(&CGCreature::endBattle,this,_1));
}
void CGCreature::flee( const CGHeroInstance * h ) const
@ -2078,7 +2078,7 @@ void CGResource::collectRes( int player ) const
void CGResource::fightForRes(ui32 agreed, const CGHeroInstance *h) const
{
if(agreed)
cb->startBattleI(h, this, boost::bind(&CGResource::endBattle,this,_1,h));
cb->startBattleI(h, this, false, boost::bind(&CGResource::endBattle,this,_1,h));
}
void CGResource::endBattle( BattleResult *result, const CGHeroInstance *h ) const
@ -2288,7 +2288,7 @@ void CGArtifact::pick(const CGHeroInstance * h) const
void CGArtifact::fightForArt( ui32 agreed, const CGHeroInstance *h ) const
{
if(agreed)
cb->startBattleI(h, this, boost::bind(&CGArtifact::endBattle,this,_1,h));
cb->startBattleI(h, this, false, boost::bind(&CGArtifact::endBattle,this,_1,h));
}
void CGArtifact::endBattle( BattleResult *result, const CGHeroInstance *h ) const
@ -2800,7 +2800,7 @@ void CGEvent::activated( const CGHeroInstance * h ) const
else
iw.text.addTxt(MetaString::ADVOB_TXT, 16);
cb->showInfoDialog(&iw);
cb->startBattleI(h, this, boost::bind(&CGEvent::endBattle,this,h,_1));
cb->startBattleI(h, this, false, boost::bind(&CGEvent::endBattle,this,h,_1));
}
else
{
@ -2812,6 +2812,7 @@ void CGPandoraBox::initObj()
{
blockVisit = true;
}
void CGPandoraBox::onHeroVisit(const CGHeroInstance * h) const
{
BlockingDialog bd (true, false);
@ -2820,23 +2821,24 @@ void CGPandoraBox::onHeroVisit(const CGHeroInstance * h) const
bd.text.addTxt (MetaString::ADVOB_TXT, 14);
cb->showBlockingDialog (&bd, boost::bind (&CGPandoraBox::open, this, h, _1));
}
void CGPandoraBox::open( const CGHeroInstance * h, ui32 accept ) const
{
if (accept)
{
if (army)
if (army) //if pandora's box is protested by army
{
InfoWindow iw;
iw.player = h->tempOwner;
iw.text.addTxt(MetaString::ADVOB_TXT, 16);
cb->showInfoDialog(&iw);
cb->startBattleI(h, this, boost::bind(&CGPandoraBox::endBattle, this, h,_1));
cb->startBattleI(h, this, false, boost::bind(&CGPandoraBox::endBattle, this, h, _1)); //grants things after battle
}
else if (message.size() == resources.size() ==
primskills.size() == abilities.size() ==
abilityLevels.size() == artifacts.size() ==
spells.size() == creatures ==
gainedExp == manaDiff == moraleDiff == luckDiff == 0) //yeaha!
else if (message.size() == 0 && resources.size() == 0
&& primskills.size() == 0 && abilities.size() == 0
&& abilityLevels.size() == 0 && artifacts.size() == 0
&& spells.size() == 0 && creatures == 0
&& gainedExp == 0 && manaDiff == 0 && moraleDiff == 0 && luckDiff == 0) //if it gives nothing without battle
{
InfoWindow iw;
iw.player = h->tempOwner;
@ -2844,12 +2846,13 @@ void CGPandoraBox::open( const CGHeroInstance * h, ui32 accept ) const
cb->showInfoDialog(&iw);
}
else
else //if it gives something without battle
{
giveContents (h, false);
}
}
}
void CGPandoraBox::giveContents( const CGHeroInstance *h, bool afterBattle ) const
{
InfoWindow iw;

View File

@ -77,9 +77,9 @@ 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 void startBattleI(const CArmedInstance *army1, const CArmedInstance *army2, int3 tile, const CGHeroInstance *hero1, const CGHeroInstance *hero2, boost::function<void(BattleResult*)> cb = 0)=0; //use hero=NULL for no hero
virtual void startBattleI(const CArmedInstance *army1, const CArmedInstance *army2, int3 tile, 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, 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, int3 tile, const CGHeroInstance *hero1, const CGHeroInstance *hero2, bool creatureBank, boost::function<void(BattleResult*)> cb = 0)=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, 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(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 bool moveHero(si32 hid, int3 dst, ui8 instant, ui8 asker = 255)=0;

View File

@ -322,10 +322,10 @@ static CCreatureSet takeCasualties(int color, const CCreatureSet &set, BattleInf
return ret;
}
void CGameHandler::startBattle(const CArmedInstance *army1, const CArmedInstance * army2, int3 tile, const CGHeroInstance *hero1, const CGHeroInstance *hero2, boost::function<void(BattleResult*)> cb)
void CGameHandler::startBattle(const CArmedInstance *army1, const CArmedInstance * army2, int3 tile, const CGHeroInstance *hero1, const CGHeroInstance *hero2, bool creatureBank, boost::function<void(BattleResult*)> cb)
{
BattleInfo *curB = new BattleInfo;
setupBattle(curB, tile, army1->army, army2->army, hero1, hero2); //initializes stacks, places creatures on battlefield, blocks and informs player interfaces
setupBattle(curB, tile, army1->army, army2->army, hero1, hero2, creatureBank); //initializes stacks, places creatures on battlefield, blocks and informs player interfaces
NEW_ROUND;
//TODO: pre-tactic stuff, call scripts etc.
@ -842,7 +842,7 @@ void CGameHandler::run(bool resume)
namespace CGH
{
using namespace std;
static void readItTo(ifstream & input, vector< vector<int> > & dest)
static void readItTo(ifstream & input, vector< vector<int> > & dest) //reads 7 lines, i-th one containing i integers, and puts it to dest
{
for(int j=0; j<7; ++j)
{
@ -857,7 +857,7 @@ namespace CGH
}
}
void CGameHandler::setupBattle( BattleInfo * curB, int3 tile, const CCreatureSet &army1, const CCreatureSet &army2, const CGHeroInstance * hero1, const CGHeroInstance * hero2 )
void CGameHandler::setupBattle( BattleInfo * curB, int3 tile, const CCreatureSet &army1, const CCreatureSet &army2, const CGHeroInstance * hero1, const CGHeroInstance * hero2, bool creatureBank )
{
battleResult.set(NULL);
std::vector<CStack*> & stacks = (curB->stacks);
@ -882,7 +882,7 @@ void CGameHandler::setupBattle( BattleInfo * curB, int3 tile, const CCreatureSet
}
std::string dump;
positions>>dump; positions>>dump;
std::vector< std::vector<int> > attackerLoose, defenderLoose, attackerTight, defenderTight;
std::vector< std::vector<int> > attackerLoose, defenderLoose, attackerTight, defenderTight, attackerCreBank, defenderCreBank;
CGH::readItTo(positions, attackerLoose);
positions>>dump;
CGH::readItTo(positions, defenderLoose);
@ -891,6 +891,11 @@ void CGameHandler::setupBattle( BattleInfo * curB, int3 tile, const CCreatureSet
CGH::readItTo(positions, attackerTight);
positions>>dump;
CGH::readItTo(positions, defenderTight);
positions>>dump;
positions>>dump;
CGH::readItTo(positions, attackerCreBank);
positions>>dump;
CGH::readItTo(positions, defenderCreBank);
positions.close();
//battleStartpos read
@ -898,7 +903,9 @@ void CGameHandler::setupBattle( BattleInfo * curB, int3 tile, const CCreatureSet
for(std::map<si32,std::pair<ui32,si32> >::const_iterator i = army1.slots.begin(); i!=army1.slots.end(); i++, k++)
{
int pos;
if(army1.formation)
if(creatureBank)
pos = attackerCreBank[army1.slots.size()-1][k];
else if(army1.formation)
pos = attackerTight[army1.slots.size()-1][k];
else
pos = attackerLoose[army1.slots.size()-1][k];
@ -911,7 +918,9 @@ void CGameHandler::setupBattle( BattleInfo * curB, int3 tile, const CCreatureSet
for(std::map<si32,std::pair<ui32,si32> >::const_iterator i = army2.slots.begin(); i!=army2.slots.end(); i++, k++)
{
int pos;
if(army2.formation)
if(creatureBank)
pos = defenderCreBank[army1.slots.size()-1][k];
else if(army2.formation)
pos = defenderTight[army2.slots.size()-1][k];
else
pos = defenderLoose[army2.slots.size()-1][k];
@ -1374,7 +1383,7 @@ bool CGameHandler::moveHero( si32 hid, int3 dst, ui8 instant, ui8 asker /*= 255*
return true;
}
//TODO: check for ally
startBattleI(h, dh);
startBattleI(h, dh, false);
return true;
}
}
@ -1530,7 +1539,7 @@ void CGameHandler::giveHeroArtifact(int artid, int hid, int position) //pos==-1
sendAndApply(&sha);
}
void CGameHandler::startBattleI(const CArmedInstance *army1, const CArmedInstance *army2, int3 tile, const CGHeroInstance *hero1, const CGHeroInstance *hero2, boost::function<void(BattleResult*)> cb) //use hero=NULL for no hero
void CGameHandler::startBattleI(const CArmedInstance *army1, const CArmedInstance *army2, int3 tile, const CGHeroInstance *hero1, const CGHeroInstance *hero2, bool creatureBank, boost::function<void(BattleResult*)> cb) //use hero=NULL for no hero
{
engageIntoBattle(army1->tempOwner);
engageIntoBattle(army2->tempOwner);
@ -1538,20 +1547,20 @@ void CGameHandler::startBattleI(const CArmedInstance *army1, const CArmedInstanc
if(army2->tempOwner < PLAYER_LIMIT)
states.setFlag(army2->tempOwner,&PlayerStatus::engagedIntoBattle,true);
boost::thread(boost::bind(&CGameHandler::startBattle,this,army1,army2,tile,hero1,hero2,cb));
boost::thread(boost::bind(&CGameHandler::startBattle, this, army1, army2, tile, hero1, hero2, creatureBank, cb));
}
void CGameHandler::startBattleI( const CArmedInstance *army1, const CArmedInstance *army2, int3 tile, boost::function<void(BattleResult*)> cb )
void CGameHandler::startBattleI( const CArmedInstance *army1, const CArmedInstance *army2, int3 tile, bool creatureBank, boost::function<void(BattleResult*)> cb )
{
startBattleI(army1, army2, tile,
army1->ID == 34 ? static_cast<const CGHeroInstance*>(army1) : NULL,
army2->ID == 34 ? static_cast<const CGHeroInstance*>(army2) : NULL,
cb);
army1->ID == HEROI_TYPE ? static_cast<const CGHeroInstance*>(army1) : NULL,
army2->ID == HEROI_TYPE ? static_cast<const CGHeroInstance*>(army2) : NULL,
creatureBank, cb);
}
void CGameHandler::startBattleI( const CArmedInstance *army1, const CArmedInstance *army2, boost::function<void(BattleResult*)> cb)
void CGameHandler::startBattleI( const CArmedInstance *army1, const CArmedInstance *army2, bool creatureBank, boost::function<void(BattleResult*)> cb)
{
startBattleI(army1, army2, army2->pos - army2->getVisitableOffset(), cb);
startBattleI(army1, army2, army2->pos - army2->getVisitableOffset(), creatureBank, cb);
}
//void CGameHandler::startBattleI(int heroID, CCreatureSet army, int3 tile, boost::function<void(BattleResult*)> cb) //for hero<=>neutral army

View File

@ -84,11 +84,11 @@ public:
bool isAllowedExchange(int id1, int id2);
void giveSpells(const CGTownInstance *t, const CGHeroInstance *h);
void moveStack(int stack, int dest);
void startBattle(const CArmedInstance *army1, const CArmedInstance *army2, int3 tile, const CGHeroInstance *hero1, const CGHeroInstance *hero2, boost::function<void(BattleResult*)> cb); //use hero=NULL for no hero
void startBattle(const CArmedInstance *army1, const CArmedInstance *army2, int3 tile, const CGHeroInstance *hero1, const CGHeroInstance *hero2, bool creatureBank, boost::function<void(BattleResult*)> cb); //use hero=NULL for no hero
void prepareAttack(BattleAttack &bat, CStack *att, CStack *def); //if last parameter is true, attack is by shooting, if false it's a melee attack
void prepareAttacked(BattleStackAttacked &bsa, CStack *def);
void checkForBattleEnd( std::vector<CStack*> &stacks );
void setupBattle( BattleInfo * curB, int3 tile, const CCreatureSet &army1, const CCreatureSet &army2, const CGHeroInstance * hero1, const CGHeroInstance * hero2 );
void setupBattle( BattleInfo * curB, int3 tile, const CCreatureSet &army1, const CCreatureSet &army2, const CGHeroInstance * hero1, const CGHeroInstance * hero2, bool creatureBank );
CGameHandler(void);
@ -122,9 +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 moveArtifact(int hid, int oldPosition, int destPos);
void removeArtifact(int hid, int pos);
void startBattleI(const CArmedInstance *army1, const CArmedInstance *army2, int3 tile, const CGHeroInstance *hero1, const CGHeroInstance *hero2, boost::function<void(BattleResult*)> cb); //use hero=NULL for no hero
void startBattleI(const CArmedInstance *army1, const CArmedInstance *army2, int3 tile, boost::function<void(BattleResult*)> cb);
void startBattleI(const CArmedInstance *army1, const CArmedInstance *army2, 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, int3 tile, const CGHeroInstance *hero1, const CGHeroInstance *hero2, bool creatureBank, boost::function<void(BattleResult*)> cb); //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, 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(int heroID, CCreatureSet army, int3 tile, boost::function<void(BattleResult*)> cb); //for hero<=>neutral army
void setAmount(int objid, ui32 val);
bool moveHero(si32 hid, int3 dst, ui8 instant, ui8 asker = 255);