Browse Source

Fixed fighting guardians of Dwellings (and other objs as well).
Most of creature generators should work fine.

Michał W. Urbańczyk 16 years ago
parent
commit
9206a13390

+ 11 - 12
client/CPlayerInterface.cpp

@@ -1025,12 +1025,7 @@ void CPlayerInterface::receivedResource(int type, int val)
 
 
 void CPlayerInterface::heroGotLevel(const CGHeroInstance *hero, int pskill, std::vector<ui16>& skills, boost::function<void(ui32)> &callback)
 void CPlayerInterface::heroGotLevel(const CGHeroInstance *hero, int pskill, std::vector<ui16>& skills, boost::function<void(ui32)> &callback)
 {
 {
-	{
-		boost::unique_lock<boost::mutex> un(showingDialog->mx);
-		while(showingDialog->data)
-			showingDialog->cond.wait(un);
-	}
-
+	waitWhileDialog();
 	CGI->soundh->playSound(soundBase::heroNewLevel);
 	CGI->soundh->playSound(soundBase::heroNewLevel);
 
 
 	boost::unique_lock<boost::recursive_mutex> un(*pim);
 	boost::unique_lock<boost::recursive_mutex> un(*pim);
@@ -1378,12 +1373,7 @@ void CPlayerInterface::showInfoDialog(const std::string &text, const std::vector
 
 
 void CPlayerInterface::showInfoDialog(const std::string &text, const std::vector<SComponent*> & components, int soundID)
 void CPlayerInterface::showInfoDialog(const std::string &text, const std::vector<SComponent*> & components, int soundID)
 {
 {
-	{
-		boost::unique_lock<boost::mutex> un(showingDialog->mx);
-		while(showingDialog->data)
-			showingDialog->cond.wait(un);
-	}
-
+	waitWhileDialog();
 	boost::unique_lock<boost::recursive_mutex> un(*pim);
 	boost::unique_lock<boost::recursive_mutex> un(*pim);
 	
 	
 	if(stillMoveHero.get() == DURING_MOVE)//if we are in the middle of hero movement
 	if(stillMoveHero.get() == DURING_MOVE)//if we are in the middle of hero movement
@@ -1424,6 +1414,7 @@ void CPlayerInterface::showYesNoDialog(const std::string &text, const std::vecto
 
 
 void CPlayerInterface::showBlockingDialog( const std::string &text, const std::vector<Component> &components, ui32 askID, int soundID, bool selection, bool cancel )
 void CPlayerInterface::showBlockingDialog( const std::string &text, const std::vector<Component> &components, ui32 askID, int soundID, bool selection, bool cancel )
 {
 {
+	waitWhileDialog();
 	boost::unique_lock<boost::recursive_mutex> un(*pim);
 	boost::unique_lock<boost::recursive_mutex> un(*pim);
 
 
 	CGI->soundh->playSound(static_cast<soundBase::soundID>(soundID));
 	CGI->soundh->playSound(static_cast<soundBase::soundID>(soundID));
@@ -1734,6 +1725,7 @@ const CGHeroInstance * CPlayerInterface::getWHero( int pos )
 
 
 void CPlayerInterface::showRecruitmentDialog(const CGDwelling *dwelling, int level)
 void CPlayerInterface::showRecruitmentDialog(const CGDwelling *dwelling, int level)
 {
 {
+	waitWhileDialog();
 	std::vector<std::pair<int,int> > cres;
 	std::vector<std::pair<int,int> > cres;
 	for(int i = 0; i < dwelling->creatures.size(); i++)
 	for(int i = 0; i < dwelling->creatures.size(); i++)
 	{
 	{
@@ -1745,6 +1737,13 @@ void CPlayerInterface::showRecruitmentDialog(const CGDwelling *dwelling, int lev
 	pushInt(cr);
 	pushInt(cr);
 }
 }
 
 
+void CPlayerInterface::waitWhileDialog()
+{
+	boost::unique_lock<boost::mutex> un(showingDialog->mx);
+	while(showingDialog->data)
+		showingDialog->cond.wait(un);
+}
+
 void SystemOptions::setMusicVolume( int newVolume )
 void SystemOptions::setMusicVolume( int newVolume )
 {
 {
 	musicVolume = newVolume;
 	musicVolume = newVolume;

+ 1 - 0
client/CPlayerInterface.h

@@ -192,6 +192,7 @@ public:
 
 
 
 
 	//-------------//
 	//-------------//
+	void waitWhileDialog();
 	bool shiftPressed() const; //determines if shift key is pressed (left or right or both)
 	bool shiftPressed() const; //determines if shift key is pressed (left or right or both)
 	void redrawHeroWin(const CGHeroInstance * hero);
 	void redrawHeroWin(const CGHeroInstance * hero);
 	void updateWater();
 	void updateWater();

+ 3 - 2
client/Client.h

@@ -96,8 +96,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 CCreatureSet * army1, const CCreatureSet * army2, int3 tile, const CGHeroInstance *hero1, const CGHeroInstance *hero2, boost::function<void(BattleResult*)> cb){}; //use hero=NULL for no hero
-	void startBattleI(int heroID, CCreatureSet army, int3 tile, boost::function<void(BattleResult*)> cb){}; //for hero<=>neutral army
+	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 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){};

+ 13 - 18
hch/CObjectHandler.cpp

@@ -652,13 +652,7 @@ void CGHeroInstance::onHeroVisit(const CGHeroInstance * h) const
 		else
 		else
 		{
 		{
 			//battle
 			//battle
-			cb->startBattleI(
-				&h->army,
-				&army,
-				h->pos,
-				h,
-				this,
-				0);
+			cb->startBattleI(h,	this);
 		}
 		}
 	}
 	}
 	else if(ID == 62) //prison
 	else if(ID == 62) //prison
@@ -1113,7 +1107,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->id,army,pos,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
@@ -1667,12 +1661,12 @@ void CGCreature::endBattle( BattleResult *result ) const
 	}
 	}
 	else
 	else
 	{
 	{
-		int killedAmount=0;
-		for(std::set<std::pair<ui32,si32> >::iterator i=result->casualties[1].begin(); i!=result->casualties[1].end(); i++)
-			if(i->first == subID)
-				killedAmount += i->second;
-		cb->setAmount(id, army.slots.find(0)->second.second - killedAmount);	
-		
+		//int killedAmount=0;
+		//for(std::set<std::pair<ui32,si32> >::iterator i=result->casualties[1].begin(); i!=result->casualties[1].end(); i++)
+		//	if(i->first == subID)
+		//		killedAmount += i->second;
+		//cb->setAmount(id, army.slots.find(0)->second.second - killedAmount);	
+
 		MetaString ms;
 		MetaString ms;
 		int pom = CCreature::getQuantityID(army.slots.find(0)->second.second);
 		int pom = CCreature::getQuantityID(army.slots.find(0)->second.second);
 		pom = 174 + 3*pom + 1;
 		pom = 174 + 3*pom + 1;
@@ -1861,7 +1855,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->id,army,pos,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
@@ -1997,7 +1991,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->id,army,pos,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
@@ -2164,6 +2158,7 @@ void CGArtifact::onHeroVisit( const CGHeroInstance * h ) const
 		if(ID == 5)
 		if(ID == 5)
 		{
 		{
 			InfoWindow iw;
 			InfoWindow iw;
+			iw.soundID = soundBase::treasure;
 			iw.player = h->tempOwner;
 			iw.player = h->tempOwner;
 			iw.components.push_back(Component(4,subID,0,0));
 			iw.components.push_back(Component(4,subID,0,0));
 			if(message.length())
 			if(message.length())
@@ -2206,7 +2201,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->id,army,pos,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
@@ -2695,7 +2690,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->id,army,pos,boost::bind(&CGEvent::endBattle,this,h,_1));
+		cb->startBattleI(h, this, boost::bind(&CGEvent::endBattle,this,h,_1));
 	}
 	}
 	else
 	else
 	{
 	{

+ 5 - 2
lib/IGameCallback.h

@@ -31,6 +31,7 @@ struct PlayerSettings;
 struct CPackForClient;
 struct CPackForClient;
 class CArtHandler;
 class CArtHandler;
 class CArtifact;
 class CArtifact;
+class CArmedInstance;
 
 
 class DLL_EXPORT IGameCallback
 class DLL_EXPORT IGameCallback
 {
 {
@@ -73,8 +74,10 @@ 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 CCreatureSet * army1, const CCreatureSet * army2, int3 tile, const CGHeroInstance *hero1, const CGHeroInstance *hero2, boost::function<void(BattleResult*)> cb)=0; //use hero=NULL for no hero
-	virtual void startBattleI(int heroID, CCreatureSet army, int3 tile, boost::function<void(BattleResult*)> cb)=0; //for hero<=>neutral army
+	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(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;
 	virtual void giveHeroBonus(GiveBonus * bonus)=0;
 	virtual void giveHeroBonus(GiveBonus * bonus)=0;

+ 1 - 1
lib/NetPacksLib.cpp

@@ -288,7 +288,7 @@ void TryMoveHero::applyGs( CGameState *gs )
 	CGHeroInstance *h = gs->getHero(id);
 	CGHeroInstance *h = gs->getHero(id);
 	h->movement = movePoints;
 	h->movement = movePoints;
 
 
-	if(result == SUCCESS || result == BLOCKING_VISIT || result == EMBARK || result == DISEMBARK)
+	if((result == SUCCESS || result == BLOCKING_VISIT || result == EMBARK || result == DISEMBARK) && start != end)
 		h->moveDir = getDir(start,end);
 		h->moveDir = getDir(start,end);
 
 
 	if(result == EMBARK) //hero enters boat at dest tile
 	if(result == EMBARK) //hero enters boat at dest tile

+ 38 - 19
server/CGameHandler.cpp

@@ -294,6 +294,8 @@ void CGameHandler::changePrimSkill(int ID, int which, int val, bool abs)
 
 
 static CCreatureSet takeCasualties(int color, const CCreatureSet &set, BattleInfo *bat)
 static CCreatureSet takeCasualties(int color, const CCreatureSet &set, BattleInfo *bat)
 {
 {
+	if(color == 254)
+		color = 255;
 	CCreatureSet ret(set);
 	CCreatureSet ret(set);
 	for(int i=0; i<bat->stacks.size();i++)
 	for(int i=0; i<bat->stacks.size();i++)
 	{
 	{
@@ -309,10 +311,10 @@ static CCreatureSet takeCasualties(int color, const CCreatureSet &set, BattleInf
 	return ret;
 	return ret;
 }
 }
 
 
-void CGameHandler::startBattle(CCreatureSet army1, CCreatureSet army2, int3 tile, CGHeroInstance *hero1, CGHeroInstance *hero2, boost::function<void(BattleResult*)> cb)
+void CGameHandler::startBattle(const CArmedInstance *army1, const CArmedInstance * army2, int3 tile, const CGHeroInstance *hero1, const CGHeroInstance *hero2, boost::function<void(BattleResult*)> cb)
 {
 {
 	BattleInfo *curB = new BattleInfo;
 	BattleInfo *curB = new BattleInfo;
-	setupBattle(curB, tile, army1, army2, hero1, hero2); //initializes stacks, places creatures on battlefield, blocks and informs player interfaces
+	setupBattle(curB, tile, army1->army, army2->army, hero1, hero2); //initializes stacks, places creatures on battlefield, blocks and informs player interfaces
 	NEW_ROUND;
 	NEW_ROUND;
 	//TODO: pre-tactic stuff, call scripts etc.
 	//TODO: pre-tactic stuff, call scripts etc.
 
 
@@ -401,10 +403,8 @@ askInterfaceForMove:
 
 
 	//casualties among heroes armies
 	//casualties among heroes armies
 	SetGarrisons sg;
 	SetGarrisons sg;
-	if(hero1)
-		sg.garrs[hero1->id] = takeCasualties(hero1->tempOwner,hero1->army,gs->curB);
-	if(hero2)
-		sg.garrs[hero2->id] = takeCasualties(hero2->tempOwner,hero2->army,gs->curB);
+	sg.garrs[army1->id] = takeCasualties(army1->tempOwner,army1->army,gs->curB);
+	sg.garrs[army2->id] = takeCasualties(army2->tempOwner,army2->army,gs->curB);
 	sendAndApply(&sg);
 	sendAndApply(&sg);
 
 
 	//end battle, remove all info, free memory
 	//end battle, remove all info, free memory
@@ -822,7 +822,7 @@ namespace CGH
 	}
 	}
 }
 }
 
 
-void CGameHandler::setupBattle( BattleInfo * curB, int3 tile, CCreatureSet &army1, CCreatureSet &army2, CGHeroInstance * hero1, CGHeroInstance * hero2 )
+void CGameHandler::setupBattle( BattleInfo * curB, int3 tile, const CCreatureSet &army1, const CCreatureSet &army2, const CGHeroInstance * hero1, const CGHeroInstance * hero2 )
 {
 {
 	battleResult.set(NULL);
 	battleResult.set(NULL);
 	std::vector<CStack*> & stacks = (curB->stacks);
 	std::vector<CStack*> & stacks = (curB->stacks);
@@ -837,7 +837,7 @@ void CGameHandler::setupBattle( BattleInfo * curB, int3 tile, CCreatureSet &army
 	curB->side2=(hero2)?(hero2->tempOwner):(-1);
 	curB->side2=(hero2)?(hero2->tempOwner):(-1);
 	curB->round = -2;
 	curB->round = -2;
 	curB->activeStack = -1;
 	curB->activeStack = -1;
-	for(std::map<si32,std::pair<ui32,si32> >::iterator i = army1.slots.begin(); i!=army1.slots.end(); i++)
+	for(std::map<si32,std::pair<ui32,si32> >::const_iterator i = army1.slots.begin(); i!=army1.slots.end(); i++)
 	{
 	{
 		stacks.push_back(new CStack(&VLC->creh->creatures[i->second.first],i->second.second,hero1->tempOwner, stacks.size(), true,i->first));
 		stacks.push_back(new CStack(&VLC->creh->creatures[i->second.first],i->second.second,hero1->tempOwner, stacks.size(), true,i->first));
 		if(hero1)
 		if(hero1)
@@ -890,7 +890,7 @@ void CGameHandler::setupBattle( BattleInfo * curB, int3 tile, CCreatureSet &army
 		{
 		{
 			stacks[b]->position = attackerLoose[army1.slots.size()-1][b];
 			stacks[b]->position = attackerLoose[army1.slots.size()-1][b];
 		}
 		}
-	for(std::map<si32,std::pair<ui32,si32> >::iterator i = army2.slots.begin(); i!=army2.slots.end(); i++)
+	for(std::map<si32,std::pair<ui32,si32> >::const_iterator i = army2.slots.begin(); i!=army2.slots.end(); i++)
 	{
 	{
 		stacks.push_back(new CStack(&VLC->creh->creatures[i->second.first],i->second.second,hero2 ? hero2->tempOwner : 255, stacks.size(), false, i->first));
 		stacks.push_back(new CStack(&VLC->creh->creatures[i->second.first],i->second.second,hero2 ? hero2->tempOwner : 255, stacks.size(), false, i->first));
 		//base luck/morale calculations
 		//base luck/morale calculations
@@ -1170,7 +1170,8 @@ bool CGameHandler::moveHero( si32 hid, int3 dst, ui8 instant, ui8 asker /*= 255*
 			&& complain("Cannot move hero, destination tile is on water!")
 			&& complain("Cannot move hero, destination tile is on water!")
 		|| (h->boat && t.tertype != TerrainTile::water && t.blocked)
 		|| (h->boat && t.tertype != TerrainTile::water && t.blocked)
 			&& complain("Cannot disembark hero, tile is blocked!")
 			&& complain("Cannot disembark hero, tile is blocked!")
-		|| !h->movement && complain("Hero don't have any movement points left!"))
+		|| (!h->movement && dst != h->pos)
+			&& complain("Hero don't have any movement points left!"))
 	{
 	{
 		//send info about movement failure
 		//send info about movement failure
 		sendAndApply(&tmh);
 		sendAndApply(&tmh);
@@ -1266,11 +1267,15 @@ bool CGameHandler::moveHero( si32 hid, int3 dst, ui8 instant, ui8 asker /*= 255*
 		{
 		{
 			if(obj->ID==HEROI_TYPE)
 			if(obj->ID==HEROI_TYPE)
 			{
 			{
+				CGHeroInstance *dh = static_cast<CGHeroInstance *>(obj);
+
 				if(obj->tempOwner==h->tempOwner) 
 				if(obj->tempOwner==h->tempOwner) 
-					return true;//TODO: exchange
+				{
+					heroExchange(h->id, dh->id);
+					return true;
+				}
 				//TODO: check for ally
 				//TODO: check for ally
-				CGHeroInstance *dh = static_cast<CGHeroInstance *>(obj);
-				startBattleI(&h->army,&dh->army,dst,h,dh,0);
+				startBattleI(h, dh);
 				return true;
 				return true;
 			}
 			}
 		}
 		}
@@ -1397,17 +1402,31 @@ void CGameHandler::giveHeroArtifact(int artid, int hid, int position) //pos==-1
 	sendAndApply(&sha);
 	sendAndApply(&sha);
 }
 }
 
 
-void CGameHandler::startBattleI(const CCreatureSet * army1, const CCreatureSet * 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, boost::function<void(BattleResult*)> cb) //use hero=NULL for no hero
+{
+	boost::thread(boost::bind(&CGameHandler::startBattle,this,army1,army2,tile,hero1,hero2,cb));
+}
+
+void CGameHandler::startBattleI( const CArmedInstance *army1, const CArmedInstance *army2, int3 tile, boost::function<void(BattleResult*)> cb )
 {
 {
-	boost::thread(boost::bind(&CGameHandler::startBattle,this,*const_cast<CCreatureSet *>(army1),*const_cast<CCreatureSet *>(army2),tile,const_cast<CGHeroInstance *>(hero1), const_cast<CGHeroInstance *>(hero2),cb));
+	startBattleI(army1, army2, tile,
+		army1->ID == 34 ? static_cast<const CGHeroInstance*>(army1) : NULL, 
+		army2->ID == 34 ? static_cast<const CGHeroInstance*>(army2) : NULL, 
+		cb);
 }
 }
-void CGameHandler::startBattleI(int heroID, CCreatureSet army, int3 tile, boost::function<void(BattleResult*)> cb) //for hero<=>neutral army
+
+void CGameHandler::startBattleI( const CArmedInstance *army1, const CArmedInstance *army2, boost::function<void(BattleResult*)> cb)
 {
 {
-	CGHeroInstance* h = const_cast<CGHeroInstance*>(getHero(heroID));
-	startBattleI(&h->army,&army,tile,h,NULL,cb);
-	//battle(&h->army,army,tile,h,NULL);
+	startBattleI(army1, army2, army2->pos - army2->getVisitableOffset(), cb);
 }
 }
 
 
+//void CGameHandler::startBattleI(int heroID, CCreatureSet army, int3 tile, boost::function<void(BattleResult*)> cb) //for hero<=>neutral army
+//{
+//	CGHeroInstance* h = const_cast<CGHeroInstance*>(getHero(heroID));
+//	startBattleI(&h->army,&army,tile,h,NULL,cb);
+//	//battle(&h->army,army,tile,h,NULL);
+//}
+
 void CGameHandler::changeSpells( int hid, bool give, const std::set<ui32> &spells )
 void CGameHandler::changeSpells( int hid, bool give, const std::set<ui32> &spells )
 {
 {
 	ChangeSpells cs;
 	ChangeSpells cs;

+ 6 - 4
server/CGameHandler.h

@@ -84,11 +84,11 @@ public:
 	bool isAllowedExchange(int id1, int id2);
 	bool isAllowedExchange(int id1, int id2);
 	void giveSpells(const CGTownInstance *t, const CGHeroInstance *h);
 	void giveSpells(const CGTownInstance *t, const CGHeroInstance *h);
 	void moveStack(int stack, int dest);
 	void moveStack(int stack, int dest);
-	void startBattle(CCreatureSet army1, CCreatureSet army2, int3 tile, CGHeroInstance *hero1, 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, 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 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 prepareAttacked(BattleStackAttacked &bsa, CStack *def);
 	void checkForBattleEnd( std::vector<CStack*> &stacks );
 	void checkForBattleEnd( std::vector<CStack*> &stacks );
-	void setupBattle( BattleInfo * curB, int3 tile, CCreatureSet &army1, CCreatureSet &army2, CGHeroInstance * hero1, CGHeroInstance * hero2 );
+	void setupBattle( BattleInfo * curB, int3 tile, const CCreatureSet &army1, const CCreatureSet &army2, const CGHeroInstance * hero1, const CGHeroInstance * hero2 );
 
 
 
 
 	CGameHandler(void);
 	CGameHandler(void);
@@ -121,8 +121,10 @@ 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 CCreatureSet * army1, const CCreatureSet * army2, int3 tile, const CGHeroInstance *hero1, const CGHeroInstance *hero2, boost::function<void(BattleResult*)> cb); //use hero=NULL for no hero
-	void startBattleI(int heroID, CCreatureSet army, int3 tile, boost::function<void(BattleResult*)> cb); //for hero<=>neutral army
+	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(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);