mirror of
				https://github.com/vcmi/vcmi.git
				synced 2025-10-31 00:07:39 +02:00 
			
		
		
		
	Surrendering and related artifacts (Statesman's Medal,
Diplomat's Ring, Ambassador's Sash).
This commit is contained in:
		| @@ -1135,3 +1135,14 @@ bool CBattleCallback::battleMakeTacticAction( BattleAction * action ) | ||||
| 	sendRequest(&ma); | ||||
| 	return true; | ||||
| } | ||||
|  | ||||
| int CBattleCallback::battleGetSurrenderCost() | ||||
| { | ||||
| 	if (!gs->curB) | ||||
| 	{ | ||||
| 		tlog1 << "battleGetSurrenderCost called when no battle!\n"; | ||||
| 		return -1; | ||||
| 	} | ||||
|  | ||||
| 	return gs->curB->getSurrenderingCost(player); | ||||
| } | ||||
| @@ -99,6 +99,7 @@ public: | ||||
| 	virtual bool battleCanCastSpell()=0; //returns true, if caller can cast a spell | ||||
| 	virtual SpellCasting::ESpellCastProblem battleCanCastThisSpell(const CSpell * spell)=0; //determines if given spell can be casted (and returns problem description) | ||||
| 	virtual bool battleCanFlee()=0; //returns true if caller can flee from the battle | ||||
| 	virtual int battleGetSurrenderCost()=0; //returns cost of surrendering battle, -1 if surrendering is not possible | ||||
| 	virtual const CGTownInstance * battleGetDefendedTown()=0; //returns defended town if current battle is a siege, NULL instead | ||||
| 	virtual ui8 battleGetWallState(int partOfWall)=0; //for determining state of a part of the wall; format: parameter [0] - keep, [1] - bottom tower, [2] - bottom wall, [3] - below gate, [4] - over gate, [5] - upper wall, [6] - uppert tower, [7] - gate; returned value: 1 - intact, 2 - damaged, 3 - destroyed; 0 - no battle | ||||
| 	virtual int battleGetWallUnderHex(THex hex)=0; //returns part of destructible wall / gate / keep under given hex or -1 if not found | ||||
| @@ -237,6 +238,7 @@ public: | ||||
| 	bool battleCanCastSpell() OVERRIDE; //returns true, if caller can cast a spell | ||||
| 	SpellCasting::ESpellCastProblem battleCanCastThisSpell(const CSpell * spell) OVERRIDE; //determines if given spell can be casted (and returns problem description) | ||||
| 	bool battleCanFlee() OVERRIDE; //returns true if caller can flee from the battle | ||||
| 	int battleGetSurrenderCost() OVERRIDE; //returns cost of surrendering battle, -1 if surrendering is not possible | ||||
| 	const CGTownInstance * battleGetDefendedTown() OVERRIDE; //returns defended town if current battle is a siege, NULL instead | ||||
| 	ui8 battleGetWallState(int partOfWall) OVERRIDE; //for determining state of a part of the wall; format: parameter [0] - keep, [1] - bottom tower, [2] - bottom wall, [3] - below gate, [4] - over gate, [5] - upper wall, [6] - uppert tower, [7] - gate; returned value: 1 - intact, 2 - damaged, 3 - destroyed; 0 - no battle | ||||
| 	int battleGetWallUnderHex(THex hex) OVERRIDE; //returns part of destructible wall / gate / keep under given hex or -1 if not found | ||||
|   | ||||
| @@ -1,3 +1,11 @@ | ||||
| 0.84 -> 0.85 | ||||
| GENERAL: | ||||
| * New artifacts supported: | ||||
| - Statesman's Medal | ||||
| - Diplomat's Ring | ||||
| - Ambassador's Sash | ||||
|  | ||||
|  | ||||
| 0.83 -> 0.84 (Mar 01 2011) | ||||
| GENERAL: | ||||
| * Bonus system has been rewritten | ||||
|   | ||||
| @@ -37,6 +37,7 @@ const double M_PI = 3.14159265358979323846; | ||||
| #define _USE_MATH_DEFINES | ||||
| #include <cmath> | ||||
| #endif | ||||
| #include <boost/format.hpp> | ||||
|  | ||||
| /* | ||||
|  * CBattleInterface.cpp, part of VCMI engine | ||||
| @@ -1198,8 +1199,8 @@ CBattleInterface::CBattleInterface(const CCreatureSet * army1, const CCreatureSe | ||||
| 	bOptions = new AdventureMapButton (CGI->generaltexth->zelp[381].first, CGI->generaltexth->zelp[381].second, boost::bind(&CBattleInterface::bOptionsf,this), 3 + pos.x, 561 + pos.y, "icm003.def", SDLK_o); | ||||
| 	bSurrender = new AdventureMapButton (CGI->generaltexth->zelp[379].first, CGI->generaltexth->zelp[379].second, boost::bind(&CBattleInterface::bSurrenderf,this), 54 + pos.x, 561 + pos.y, "icm001.def", SDLK_s); | ||||
| 	bFlee = new AdventureMapButton (CGI->generaltexth->zelp[380].first, CGI->generaltexth->zelp[380].second, boost::bind(&CBattleInterface::bFleef,this), 105 + pos.x, 561 + pos.y, "icm002.def", SDLK_r); | ||||
| 	bSurrender->block(!curInt->cb->battleCanFlee()); | ||||
| 	bFlee->block(!curInt->cb->battleCanFlee());	 | ||||
| 	bSurrender->block(curInt->cb->battleGetSurrenderCost() < 0); | ||||
| 	bAutofight  = new AdventureMapButton (CGI->generaltexth->zelp[382].first, CGI->generaltexth->zelp[382].second, boost::bind(&CBattleInterface::bAutofightf,this), 157 + pos.x, 561 + pos.y, "icm004.def", SDLK_a); | ||||
| 	bSpell = new AdventureMapButton (CGI->generaltexth->zelp[385].first, CGI->generaltexth->zelp[385].second, boost::bind(&CBattleInterface::bSpellf,this), 645 + pos.x, 561 + pos.y, "icm005.def", SDLK_c); | ||||
| 	bSpell->block(true); | ||||
| @@ -2160,6 +2161,15 @@ void CBattleInterface::bSurrenderf() | ||||
| { | ||||
| 	if(spellDestSelectMode) //we are casting a spell | ||||
| 		return; | ||||
|  | ||||
| 	int cost = curInt->cb->battleGetSurrenderCost(); | ||||
| 	if(cost >= 0) | ||||
| 	{ | ||||
| 		const CGHeroInstance *opponent = curInt->cb->battleGetFightingHero(1); | ||||
| 		std::string enemyHeroName = opponent ? opponent->name : "#ENEMY#"; //TODO: should surrendering without enemy hero be enabled?  | ||||
| 		std::string surrenderMessage = boost::str(boost::format(CGI->generaltexth->allTexts[32]) % enemyHeroName % cost); //%s states: "I will accept your surrender and grant you and your troops safe passage for the price of %d gold." | ||||
| 		curInt->showYesNoDialog(surrenderMessage, std::vector<SComponent*>(), boost::bind(&CBattleInterface::reallySurrender,this), 0, false); | ||||
| 	} | ||||
| } | ||||
|  | ||||
| void CBattleInterface::bFleef() | ||||
| @@ -2170,7 +2180,7 @@ void CBattleInterface::bFleef() | ||||
| 	if( curInt->cb->battleCanFlee() ) | ||||
| 	{ | ||||
| 		CFunctionList<void()> ony = boost::bind(&CBattleInterface::reallyFlee,this); | ||||
| 		curInt->showYesNoDialog(CGI->generaltexth->allTexts[28],std::vector<SComponent*>(), ony, 0, false); | ||||
| 		curInt->showYesNoDialog(CGI->generaltexth->allTexts[28],std::vector<SComponent*>(), ony, 0, false); //Are you sure you want to retreat? | ||||
| 	} | ||||
| 	else | ||||
| 	{ | ||||
| @@ -2185,7 +2195,7 @@ void CBattleInterface::bFleef() | ||||
| 				heroName = defendingHeroInstance->name; | ||||
| 		//calculating text | ||||
| 		char buffer[1000]; | ||||
| 		sprintf(buffer, CGI->generaltexth->allTexts[340].c_str(), heroName.c_str()); | ||||
| 		sprintf(buffer, CGI->generaltexth->allTexts[340].c_str(), heroName.c_str()); //The Shackles of War are present.  %s can not retreat! | ||||
|  | ||||
| 		//printing message | ||||
| 		curInt->showInfoDialog(std::string(buffer), comps); | ||||
| @@ -2194,10 +2204,23 @@ void CBattleInterface::bFleef() | ||||
|  | ||||
| void CBattleInterface::reallyFlee() | ||||
| { | ||||
| 	giveCommand(4,0,0); | ||||
| 	giveCommand(BattleAction::RETREAT,0,0); | ||||
| 	CCS->curh->changeGraphic(0, 0); | ||||
| } | ||||
|  | ||||
| void CBattleInterface::reallySurrender() | ||||
| { | ||||
| 	if(curInt->cb->getResourceAmount(Res::GOLD) < curInt->cb->battleGetSurrenderCost()) | ||||
| 	{ | ||||
| 		curInt->showInfoDialog(CGI->generaltexth->allTexts[29]); //You don't have enough gold! | ||||
| 	} | ||||
| 	else | ||||
| 	{ | ||||
| 		giveCommand(BattleAction::SURRENDER,0,0); | ||||
| 		CCS->curh->changeGraphic(0, 0); | ||||
| 	} | ||||
| } | ||||
|  | ||||
| void CBattleInterface::bAutofightf() | ||||
| { | ||||
| 	if(spellDestSelectMode) //we are casting a spell | ||||
| @@ -3013,6 +3036,7 @@ void CBattleInterface::activateStack() | ||||
| 	bSpell->block(!curInt->cb->battleCanCastSpell()); | ||||
| 	bSurrender->block((curInt == attackerInt ? defendingHeroInstance : attackingHeroInstance) == NULL); | ||||
| 	bFlee->block(!curInt->cb->battleCanFlee()); | ||||
| 	bSurrender->block(curInt->cb->battleGetSurrenderCost() < 0); | ||||
|  | ||||
| 	GH.fakeMouseMove(); | ||||
|  | ||||
|   | ||||
| @@ -496,6 +496,7 @@ public: | ||||
| 	void bSurrenderf(); | ||||
| 	void bFleef(); | ||||
| 	void reallyFlee(); //performs fleeing without asking player | ||||
| 	void reallySurrender(); //performs surrendering without asking player | ||||
| 	void bAutofightf(); | ||||
| 	void bSpellf(); | ||||
| 	void bWaitf(); | ||||
|   | ||||
| @@ -1883,6 +1883,42 @@ std::vector<ui32> BattleInfo::calculateResistedStacks( const CSpell * sp, const | ||||
| 	return ret; | ||||
| } | ||||
|  | ||||
| int BattleInfo::getSurrenderingCost(int player) const | ||||
| { | ||||
| 	if(!battleCanFlee(player)) //to surrender, conditions of fleeing must be fulfilled | ||||
| 		return -1; | ||||
| 	if(!getHero(theOtherPlayer(player))) //additionally, there must be an enemy hero | ||||
| 		return -2; | ||||
|  | ||||
| 	int ret = 0; | ||||
| 	double discount = 0; | ||||
| 	BOOST_FOREACH(const CStack *s, stacks) | ||||
| 		if(s->owner == player  &&  s->base) //we pay for our stack that comes from our army (the last condition eliminates summoned cres and war machines) | ||||
| 			ret += s->getCreature()->cost[Res::GOLD] * s->count; | ||||
|  | ||||
| 	if(const CGHeroInstance *h = getHero(player)) | ||||
| 		discount += h->valOfBonuses(Bonus::SURRENDER_DISCOUNT); | ||||
|  | ||||
| 	ret *= (100.0 - discount) / 100.0; | ||||
| 	amax(ret, 0); //no negative costs for >100% discounts (impossible in original H3 mechanics, but some day...) | ||||
| 	return ret; | ||||
| } | ||||
|  | ||||
| int BattleInfo::theOtherPlayer(int player) const | ||||
| { | ||||
| 	return sides[!whatSide(player)]; | ||||
| } | ||||
|  | ||||
| ui8 BattleInfo::whatSide(int player) const | ||||
| { | ||||
| 	for(int i = 0; i < ARRAY_COUNT(sides); i++) | ||||
| 		if(sides[i] == player) | ||||
| 			return i; | ||||
|  | ||||
| 	tlog1 << "BattleInfo::whatSide: Player " << player << " is not in battle!\n"; | ||||
| 	return -1; | ||||
| } | ||||
|  | ||||
| CStack::CStack(const CStackInstance *Base, int O, int I, bool AO, int S) | ||||
| 	: base(Base), ID(I), owner(O), slot(S), attackerOwned(AO),    | ||||
| 	counterAttacks(1) | ||||
|   | ||||
| @@ -131,6 +131,10 @@ struct DLL_EXPORT BattleInfo : public CBonusSystemNode | ||||
| 	void localInit(); | ||||
| 	static BattleInfo * setupBattle( int3 tile, int terrain, int terType, const CArmedInstance *armies[2], const CGHeroInstance * heroes[2], bool creatureBank, const CGTownInstance *town ); | ||||
| 	bool isInTacticRange( THex dest ) const; | ||||
| 	int getSurrenderingCost(int player) const; | ||||
|  | ||||
| 	int theOtherPlayer(int player) const; | ||||
| 	ui8 whatSide(int player) const; | ||||
| }; | ||||
|  | ||||
| class DLL_EXPORT CStack : public CBonusSystemNode, public CStackBasicDescriptor | ||||
|   | ||||
| @@ -1177,6 +1177,14 @@ void CGHeroInstance::updateSkill(int which, int val) | ||||
| 		else | ||||
| 			b->val = +val; | ||||
| 	} | ||||
| 	else if(which == DIPLOMACY) //surrender discount: 20% per level | ||||
| 	{ | ||||
| 		 | ||||
| 		if(Bonus *b = getBonus(Selector::type(Bonus::SURRENDER_DISCOUNT) && Selector::sourceType(Bonus::SECONDARY_SKILL))) | ||||
| 			b->val = +val; | ||||
| 		else | ||||
| 			addNewBonus(new Bonus(Bonus::PERMANENT, Bonus::SURRENDER_DISCOUNT, Bonus::SECONDARY_SKILL, val * 20, which)); | ||||
| 	} | ||||
|  | ||||
| 	int skillVal = 0; | ||||
| 	switch (which) | ||||
|   | ||||
| @@ -1254,11 +1254,7 @@ void CGameHandler::checkForBattleEnd( std::vector<CStack*> &stacks ) | ||||
| 	} | ||||
| 	if(!hasStack[0] || !hasStack[1]) //somebody has won | ||||
| 	{ | ||||
| 		BattleResult *br = new BattleResult; //will be deleted at the end of startBattle(...) | ||||
| 		br->result = 0; | ||||
| 		br->winner = hasStack[1]; //fleeing side loses | ||||
| 		gs->curB->calculateCasualties(br->casualties); | ||||
| 		battleResult.set(br); | ||||
| 		setBattleResult(0, hasStack[1]); | ||||
| 	} | ||||
| } | ||||
|  | ||||
| @@ -1665,40 +1661,6 @@ void CGameHandler::stopHeroVisitCastle(int obj, int heroID) | ||||
| 	sendAndApply(&vc); | ||||
| } | ||||
|  | ||||
| // bool CGameHandler::removeArtifact(const CArtifact* art, int hid) | ||||
| // { | ||||
| // 	const CGHeroInstance* h = getHero(hid); | ||||
| //  | ||||
| // 	SetHeroArtifacts sha; | ||||
| // 	sha.hid = hid; | ||||
| // 	sha.artifacts = h->artifacts; | ||||
| // 	sha.artifWorn = h->artifWorn; | ||||
| // 	 | ||||
| // 	std::vector<const 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, const CArtifact*>::iterator itr; | ||||
| // 		for (itr = sha.artifWorn.begin(); itr != sha.artifWorn.end(); ++itr) | ||||
| // 		{ | ||||
| // 			if (itr->second == art) | ||||
| // 			{ | ||||
| // 				VLC->arth->unequipArtifact(sha.artifWorn, itr->first); | ||||
| // 				break; | ||||
| // 			} | ||||
| // 		} | ||||
| //  | ||||
| // 		if(itr == sha.artifWorn.end()) | ||||
| // 		{ | ||||
| // 			tlog2 << "Cannot find artifact to remove!\n"; | ||||
| // 			return false; | ||||
| // 		} | ||||
| // 	} | ||||
| // 	sendAndApply(&sha); | ||||
| // 	return true; | ||||
| // } | ||||
|  | ||||
| void CGameHandler::removeArtifact(const ArtifactLocation &al) | ||||
| { | ||||
| 	assert(al.getArt()); | ||||
| @@ -1737,13 +1699,6 @@ void CGameHandler::startBattleI( const CArmedInstance *army1, const CArmedInstan | ||||
| 	startBattleI(army1, army2, army2->visitablePos(), cb, creatureBank); | ||||
| } | ||||
|  | ||||
| //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 ) | ||||
| { | ||||
| 	ChangeSpells cs; | ||||
| @@ -2534,17 +2489,7 @@ bool CGameHandler::moveArtifact(si32 srcHeroID, si32 destHeroID, ui16 srcSlot, u | ||||
| 		COMPLAIN_RET("No artifact to move!"); | ||||
| 	if (destArtifact && srcHero->tempOwner != destHero->tempOwner) | ||||
| 		COMPLAIN_RET("Can't touch artifact on hero of another player!"); | ||||
|  | ||||
|  | ||||
|  | ||||
| // 	// 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, NULL); | ||||
| // 		if (!vstd::contains(sha.artifWorn, destSlot)) | ||||
| // 			destArtifact = NULL; | ||||
| // 	} | ||||
|  | ||||
| 	 | ||||
| 	// Check if src/dest slots are appropriate for the artifacts exchanged. | ||||
| 	// Moving to the backpack is always allowed. | ||||
| 	if ((!srcArtifact || destSlot < Arts::BACKPACK_START) | ||||
| @@ -2562,10 +2507,6 @@ bool CGameHandler::moveArtifact(si32 srcHeroID, si32 destHeroID, ui16 srcSlot, u | ||||
| 	if(dst.slot >= Arts::BACKPACK_START) | ||||
| 		amin(dst.slot, Arts::BACKPACK_START + dst.hero->artifactsInBackpack.size()); | ||||
|  | ||||
| //  	// Correction for destination from removing source artifact in backpack. | ||||
| //  	if (src.slot >= 19 && dst.slot >= 19 && src.slot < dst.slot) | ||||
| //  		dst.slot--; | ||||
|  | ||||
| 	if (src.slot == dst.slot  &&  src.hero == dst.hero) | ||||
| 		COMPLAIN_RET("Won't move artifact: Dest same as source!"); | ||||
|  | ||||
| @@ -2583,37 +2524,6 @@ bool CGameHandler::moveArtifact(si32 srcHeroID, si32 destHeroID, ui16 srcSlot, u | ||||
| 		moveArtifact(src, dst); | ||||
| 	} | ||||
|  | ||||
| //  | ||||
| // 	// 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, NULL); | ||||
| // 	const bool destFits = !destArtifact || srcSlot >= 19 || destSlot >= 19 || destArtifact->fitsAt(sha.artifWorn, srcSlot); | ||||
| // 	if (srcHeroID == destHeroID && destArtifact) | ||||
| // 		sha.setArtAtPos(destSlot, destArtifact); | ||||
| //  | ||||
| // 	sha.setArtAtPos(srcSlot, NULL); | ||||
| // 	if (destSlot < 19 && (destArtifact || srcSlot < 19) && destFits) | ||||
| // 		sha.setArtAtPos(srcSlot, destArtifact ? destArtifact : NULL); | ||||
| //  | ||||
| // 	// Internal hero artifact arrangement. | ||||
| // 	if(srcHero == destHero)  | ||||
| // 	{ | ||||
| //  | ||||
| // 		sha.setArtAtPos(destSlot, srcHero->getArtAtPos(srcSlot)); | ||||
| // 	} | ||||
| // 	if (srcHeroID != destHeroID)  | ||||
| // 	{ | ||||
| // 		// Exchange between two different heroes. | ||||
| // 		SetHeroArtifacts sha2; | ||||
| // 		sha2.hid = destHeroID; | ||||
| // 		sha2.artifacts = destHero->artifacts; | ||||
| // 		sha2.artifWorn = destHero->artifWorn; | ||||
| // 		sha2.setArtAtPos(destSlot, srcArtifact ? srcArtifact : NULL); | ||||
| // 		if (!destFits) | ||||
| // 			sha2.setArtAtPos(sha2.artifacts.size() + 19, destHero->getArtAtPos(destSlot)); | ||||
| // 		sendAndApply(&sha2); | ||||
| // 	} | ||||
| // 	sendAndApply(&sha); | ||||
| 	return true; | ||||
| } | ||||
|  | ||||
| @@ -2656,118 +2566,7 @@ bool CGameHandler::assembleArtifacts (si32 heroID, ui16 artifactSlot, bool assem | ||||
| 		da.al = ArtifactLocation(hero, artifactSlot); | ||||
| 		sendAndApply(&da); | ||||
| 	} | ||||
| 	/* | ||||
| 	SetHeroArtifacts sha; | ||||
| 	sha.hid = heroID; | ||||
| 	sha.artifacts = hero->artifacts; | ||||
| 	sha.artifWorn = hero->artifWorn; | ||||
|  | ||||
| 	if (assemble) | ||||
| 	{ | ||||
| 		if (VLC->arth->artifacts.size() < assembleTo) | ||||
| 		{ | ||||
| 			complain("Illegal artifact to assemble to."); | ||||
| 			return false; | ||||
| 		} | ||||
|  | ||||
| 		if (!destArtifact->canBeAssembledTo(hero->artifWorn, assembleTo)) | ||||
| 		{ | ||||
| 			complain("Artifact cannot be assembled."); | ||||
| 			return false; | ||||
| 		} | ||||
|  | ||||
| 		const CArtifact &artifact = *VLC->arth->artifacts[assembleTo]; | ||||
|  | ||||
| 		if (artifact.constituents == NULL) | ||||
| 		{ | ||||
| 			complain("Not a combinational artifact."); | ||||
| 			return false; | ||||
| 		} | ||||
|  | ||||
| 		// Perform assembly. | ||||
| 		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] = VLC->arth->artifacts[assembleTo]; | ||||
| 				destConsumed = true; | ||||
| 				continue; | ||||
| 			} | ||||
|  | ||||
| 			bool found = false; | ||||
| 			for (std::map<ui16, const 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 = VLC->arth->artifacts[assembleTo]; | ||||
| 							destConsumed = true; | ||||
|  | ||||
| 							found = true; | ||||
| 							break; | ||||
| 						} | ||||
| 					} | ||||
| 					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 = VLC->arth->artifacts[assembleTo]; | ||||
| 							destConsumed = true; | ||||
| 						} | ||||
| 						else | ||||
| 						{ | ||||
| 							it->second = VLC->arth->artifacts[145]; | ||||
| 						} | ||||
|  | ||||
| 						found = true; | ||||
| 						break; | ||||
| 					} | ||||
| 				} | ||||
| 			} | ||||
| 			if (!found) { | ||||
| 				complain("Constituent missing."); | ||||
| 				return false; | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
| 	else | ||||
| 	{ | ||||
| 		// Perform disassembly. | ||||
| 		bool destConsumed = false; // Determines which constituent that will be counted for together with the artifact. | ||||
| 		BOOST_FOREACH(ui32 constituentID, *destArtifact->constituents) | ||||
| 		{ | ||||
| 			const CArtifact &constituent = *VLC->arth->artifacts[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]->id == 145) | ||||
| 					{ | ||||
| 						const_cast<CArtifact*>(sha.artifWorn[slotID])->id = constituentID; | ||||
| 						break; | ||||
| 					} | ||||
| 				} | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	sendAndApply(&sha); | ||||
|  | ||||
| 	return true;*/ | ||||
| 	return false; | ||||
| } | ||||
|  | ||||
| @@ -3142,17 +2941,28 @@ bool CGameHandler::makeBattleAction( BattleAction &ba ) | ||||
| 		} | ||||
| 	case BattleAction::RETREAT: //retreat/flee | ||||
| 		{ | ||||
| 			if( !gs->curB->battleCanFlee(ba.side ? gs->curB->sides[1] : gs->curB->sides[0]) ) | ||||
| 				break; | ||||
| 			//TODO: remove retreating hero from map and place it in recruitment list | ||||
| 			BattleResult *br = new BattleResult; | ||||
| 			br->result = 1; | ||||
| 			br->winner = !ba.side; //fleeing side loses | ||||
| 			gs->curB->calculateCasualties(br->casualties); | ||||
| 			giveExp(*br); | ||||
| 			battleResult.set(br); | ||||
| 			if(!gs->curB->battleCanFlee(gs->curB->sides[ba.side])) | ||||
| 				complain("Cannot retreat!"); | ||||
| 			else | ||||
| 				setBattleResult(1, !ba.side); //surrendering side loses | ||||
| 			break; | ||||
| 		} | ||||
| 	case BattleAction::SURRENDER: | ||||
| 		{ | ||||
| 			int player = gs->curB->sides[ba.side]; | ||||
| 			int cost = gs->curB->getSurrenderingCost(player); | ||||
| 			if(cost < 0) | ||||
| 				complain("Cannot surrender!"); | ||||
| 			else if(getResource(player, Res::GOLD) < cost) | ||||
| 				complain("Not enough gold to surrender!"); | ||||
| 			else | ||||
| 			{ | ||||
| 				giveResource(player, Res::GOLD, -cost); | ||||
| 				setBattleResult(2, !ba.side); //surrendering side loses | ||||
| 			} | ||||
| 			break; | ||||
| 		} | ||||
| 		break; | ||||
| 	case BattleAction::WALK_AND_ATTACK: //walk or attack | ||||
| 		{ | ||||
| 			sendAndApply(&StartAction(ba)); //start movement and attack | ||||
| @@ -3538,17 +3348,6 @@ void CGameHandler::playerMessage( ui8 player, const std::string &message ) | ||||
| 		if(!hero) return; | ||||
| 		for (int g=7; g<=140; ++g) | ||||
| 			giveHeroNewArtifact(hero, VLC->arth->artifacts[g], -1); | ||||
|  | ||||
| // 		SetHeroArtifacts sha; | ||||
| // 		sha.hid = hero->id; | ||||
| // 		sha.artifacts = hero->artifacts; | ||||
| // 		sha.artifWorn = hero->artifWorn; | ||||
| // 		sha.artifacts.push_back(VLC->arth->artifacts[2]); //grail | ||||
| // 		for (int g=7; g<=140; ++g) | ||||
| // 		{ | ||||
| // 			sha.artifacts.push_back(VLC->arth->artifacts[g]); | ||||
| // 		} | ||||
| // 		sendAndApply(&sha); | ||||
| 	} | ||||
| 	else | ||||
| 		cheated = false; | ||||
| @@ -3730,7 +3529,7 @@ bool CGameHandler::makeCustomAction( BattleAction &ba ) | ||||
| { | ||||
| 	switch(ba.actionType) | ||||
| 	{ | ||||
| 	case 1: //hero casts spell | ||||
| 	case BattleAction::HERO_SPELL: //hero casts spell | ||||
| 		{ | ||||
| 			const CGHeroInstance *h = gs->curB->heroes[ba.side]; | ||||
| 			const CGHeroInstance *secondHero = gs->curB->heroes[!ba.side]; | ||||
| @@ -5062,6 +4861,15 @@ void CGameHandler::giveHeroNewArtifact(const CGHeroInstance *h, const CArtifact | ||||
| 	giveHeroArtifact(h, a, pos); | ||||
| } | ||||
|  | ||||
| void CGameHandler::setBattleResult(int resultType, int victoriusSide) | ||||
| { | ||||
| 	BattleResult *br = new BattleResult; | ||||
| 	br->result = resultType; | ||||
| 	br->winner = victoriusSide; //surrendering side loses | ||||
| 	gs->curB->calculateCasualties(br->casualties); | ||||
| 	battleResult.set(br); | ||||
| } | ||||
|  | ||||
| CasualtiesAfterBattle::CasualtiesAfterBattle(const CArmedInstance *army, BattleInfo *bat) | ||||
| { | ||||
| 	int color = army->tempOwner; | ||||
|   | ||||
| @@ -120,6 +120,7 @@ public: | ||||
| 	void prepareAttack(BattleAttack &bat, const CStack *att, const CStack *def, int distance); //distance - number of hexes travelled before attacking | ||||
| 	void checkForBattleEnd( std::vector<CStack*> &stacks ); | ||||
| 	void setupBattle(int3 tile, const CArmedInstance *armies[2], const CGHeroInstance *heroes[2], bool creatureBank, const CGTownInstance *town); | ||||
| 	void setBattleResult(int resultType, int victoriusSide); | ||||
|  | ||||
| 	CGameHandler(void); | ||||
| 	~CGameHandler(void); | ||||
|   | ||||
		Reference in New Issue
	
	Block a user