Bazaar developer reference

CvDeal::IsPossibleToTradeItem(PlayerTypes, PlayerTypes, TradeableItems, int, int, int, bool, bool, bool)

Defined in
CvDealClasses.cpp, line 307
Class
CvDeal
Hook name
CivHooks::CvDeal_IsPossibleToTradeItem
Lua events
GameEvents.IsAbleToMakePeace, GameEvents.PlayerCanMakePeace

Hooks

static bool BeforeCvDeal_IsPossibleToTradeItem(CvDeal* self, PlayerTypes ePlayer, PlayerTypes eToPlayer, TradeableItems eItem, int iData1, int iData2, int iData3, bool bFlag1, bool bCheckOtherPlayerValidity, bool bFinalizing, bool& result);static void AfterCvDeal_IsPossibleToTradeItem(CvDeal* self, PlayerTypes ePlayer, PlayerTypes eToPlayer, TradeableItems eItem, int iData1, int iData2, int iData3, bool bFlag1, bool bCheckOtherPlayerValidity, bool bFinalizing, bool& result);static bool ReplaceCvDeal_IsPossibleToTradeItem(bool (*original)(CvDeal*, PlayerTypes, PlayerTypes, TradeableItems, int, int, int, bool, bool, bool), CvDeal* self, PlayerTypes ePlayer, PlayerTypes eToPlayer, TradeableItems eItem, int iData1, int iData2, int iData3, bool bFlag1, bool bCheckOtherPlayerValidity, bool bFinalizing);CivRegisterBefore<CivHooks::CvDeal_IsPossibleToTradeItem>(host, &BeforeCvDeal_IsPossibleToTradeItem);CivRegisterAfter<CivHooks::CvDeal_IsPossibleToTradeItem>(host, &AfterCvDeal_IsPossibleToTradeItem);CivRegisterReplace<CivHooks::CvDeal_IsPossibleToTradeItem>(host, &ReplaceCvDeal_IsPossibleToTradeItem);

Code

306/// Is it actually possible for a player to offer up this trade item?307bool CvDeal::IsPossibleToTradeItem(PlayerTypes ePlayer, PlayerTypes eToPlayer, TradeableItems eItem, int iData1, int iData2, int iData3, bool bFlag1, bool bCheckOtherPlayerValidity, bool bFinalizing)308{309	// The Data parameters can be -1, which means we don't care about whatever data is stored there (e.g. -1 for Gold means can we trade ANY amount of Gold?)310	CvPlayer* pFromPlayer = &GET_PLAYER(ePlayer);311	CvPlayer* pToPlayer = &GET_PLAYER(eToPlayer);312313	TeamTypes eFromTeam = pFromPlayer->getTeam();314	TeamTypes eToTeam = pToPlayer->getTeam();315316	CvTeam* pFromTeam = &GET_TEAM(eFromTeam);317	CvTeam* pToTeam = &GET_TEAM(eToTeam);318319	CvDeal* pRenewDeal = pFromPlayer->GetDiplomacyAI()->GetDealToRenew();320	if (!pRenewDeal)321	{322		pRenewDeal = pToPlayer->GetDiplomacyAI()->GetDealToRenew();323	}324325	int iGoldAvailable = GetGoldAvailable(ePlayer, eItem);326327	// Some items require gold be spent (e.g. Research and Trade Agreements)328	int iCost = GC.getGame().GetGameDeals()->GetTradeItemGoldCost(eItem, ePlayer, eToPlayer);329	if(iCost > 0 && iGoldAvailable < iCost)330		return false;331332	iGoldAvailable -= iCost;333334	////////////////////////////////////////////////////335336	// Gold337	if(eItem == TRADE_ITEM_GOLD)338	{339		// DoF has not been made with this player340		if (!this->IsPeaceTreatyTrade(eToPlayer) && !this->IsPeaceTreatyTrade(ePlayer))341		{342			if (pFromPlayer->getTeam() != pToPlayer->getTeam() && (!pFromPlayer->GetDiplomacyAI()->IsDoFAccepted(eToPlayer) || !pToPlayer->GetDiplomacyAI()->IsDoFAccepted(ePlayer)))343				return false;344		}345346		// Can't trade more Gold than you have347		int iGold = iData1;348		if(iGold != -1 && iGoldAvailable < iGold)349			return false;350	}351	// Gold per Turn352	else if(eItem == TRADE_ITEM_GOLD_PER_TURN)353	{354		// Can't trade more GPT than you're making355		int iGoldPerTurn = iData1;356		if(iGoldPerTurn != -1 && pFromPlayer->calculateGoldRate() < iGoldPerTurn)357			return false;358359		//int iDuration = iData2;360		//if (iDuration != GC.getGame().GetDealDuration())361		//	return false;362	}363	// Map364	else if(eItem == TRADE_ITEM_MAPS)365	{366		return false;367	}368	// Resource369	else if(eItem == TRADE_ITEM_RESOURCES)370	{371		ResourceTypes eResource = (ResourceTypes) iData1;372		if(eResource != NO_RESOURCE)373		{374			int iResourceQuantity = iData2;375376			// Can't trade a negative amount of something!377			if(iResourceQuantity < 0)378				return false;379380			if (GC.getGame().GetGameLeagues()->IsLuxuryHappinessBanned(ePlayer, eResource) || GC.getGame().GetGameLeagues()->IsLuxuryHappinessBanned(eToPlayer, eResource))381			{382				return false;383			}384385			//int iNumAvailable = GetNumResource(ePlayer, eResource, true);386387			int iNumAvailable = pFromPlayer->getNumResourceAvailable(eResource, false);388			int iNumInRenewDeal = 0;389			int iNumInExistingDeal = 0;390391			if (pRenewDeal)392			{393				// count any that are in the renew deal394				TradedItemList::iterator it;395				for(it = pRenewDeal->m_TradedItems.begin(); it != pRenewDeal->m_TradedItems.end(); ++it)396				{397					if(it->m_eItemType == TRADE_ITEM_RESOURCES && it->m_eFromPlayer == ePlayer && (ResourceTypes)it->m_iData1 == eResource)398					{399						// credit the amount400						iNumInRenewDeal += it->m_iData2;401					}402				}403404				// remove any that are in this deal405				for(it = m_TradedItems.begin(); it != m_TradedItems.end(); ++it)406				{407					if(it->m_eItemType == TRADE_ITEM_RESOURCES && it->m_eFromPlayer == ePlayer && (ResourceTypes)it->m_iData1 == eResource)408					{409						iNumInExistingDeal += it->m_iData2;410					}411				}412			}413414			// Offering up more of a Resource than we have available415			if(iNumAvailable + iNumInRenewDeal - iNumInExistingDeal < iResourceQuantity)416				return false;417418			// Must be a Luxury or a Strategic Resource419			ResourceUsageTypes eUsage = GC.getResourceInfo(eResource)->getResourceUsage();420			if(eUsage != RESOURCEUSAGE_LUXURY && eUsage != RESOURCEUSAGE_STRATEGIC)421				return false;422423			if(eUsage == RESOURCEUSAGE_LUXURY)424			{425				// Can't trade Luxury if the other player already has one426				if(pToPlayer->getNumResourceAvailable(eResource) > MAX(iNumInRenewDeal - iNumInExistingDeal, 0))427				{428					return false;429				}430			}431432			// Can't trade them something they're already giving us in the deal433			if(IsResourceTrade(eToPlayer, eResource))434				return false;435436			// AI can't trade an obsolete resource437			if (!pFromTeam->isHuman() && pFromTeam->IsResourceObsolete(eResource))438			{439				return false;440			}441		}442	}443	// City444	else if(eItem == TRADE_ITEM_CITIES)445	{446		CvCity* pCity = NULL;447		CvPlot* pPlot = GC.getMap().plot(iData1, iData2);448		if(pPlot != NULL)449			pCity = pPlot->getPlotCity();450451		if(pCity != NULL)452		{453			// Can't trade someone else's city454			if(pCity->getOwner() != ePlayer)455				return false;456457			// Can't trade one's capital458			if(pCity->isCapital())459				return false;460461			// Can't trade a city to a human in an OCC game462			if(GC.getGame().isOption(GAMEOPTION_ONE_CITY_CHALLENGE) && GET_PLAYER(eToPlayer).isHuman())463				return false;464		}465		// Can't trade a null city466		else467			return false;468469		// Can't already have this city in the deal470		if(!bFinalizing && IsCityTrade(ePlayer, iData1, iData2))471			return false;472	}473	// Unit474	else if(eItem == TRADE_ITEM_UNITS)475	{476		return false;477	}478	// Embassy479	else if(eItem == TRADE_ITEM_ALLOW_EMBASSY)480	{481		// too few cities482		if (pToPlayer->getNumCities() < 1)483			return false;484		// Does not have tech for Embassy trading485		if(!pToTeam->isAllowEmbassyTradingAllowed())486			return false;487		// Already has embassy488		if(pToTeam->HasEmbassyAtTeam(eFromTeam))489			return false;490		// Same team491		if(eFromTeam == eToTeam)492			return false;493	}494	// Open Borders495	else if(eItem == TRADE_ITEM_OPEN_BORDERS)496	{497		// Neither of us yet has the Tech for OP498		if(!pFromTeam->isOpenBordersTradingAllowed() && !pToTeam->isOpenBordersTradingAllowed())499			return false;500		// Embassy has not been established501		if(!pFromTeam->HasEmbassyAtTeam(eToTeam))502			return false;503		504		bool bIgnoreExistingOP = true;505		if (pRenewDeal)506		{507			// count any that are in the renew deal508			int iEndingTurn = -1;509			TradedItemList::iterator it;510			for(it = pRenewDeal->m_TradedItems.begin(); it != pRenewDeal->m_TradedItems.end(); ++it)511			{512				if(it->m_eItemType == TRADE_ITEM_OPEN_BORDERS && (it->m_eFromPlayer == ePlayer || it->m_eFromPlayer == eToPlayer == ePlayer))513				{514					iEndingTurn = it->m_iFinalTurn;515				}516			}517518			if (iEndingTurn == GC.getGame().getGameTurn())519			{520				bIgnoreExistingOP = false;521			}522		}523524		// Already has OP525		if(pFromTeam->IsAllowsOpenBordersToTeam(eToTeam) && bIgnoreExistingOP)526			return false;527		// Same Team528		if(eFromTeam == eToTeam)529			return false;530	}531	// Defensive Pact532	else if(eItem == TRADE_ITEM_DEFENSIVE_PACT)533	{534		// Neither of us yet has the Tech for DP535		if(!pFromTeam->isDefensivePactTradingAllowed() && !pToTeam->isDefensivePactTradingAllowed())536			return false;537		// Embassy has not been established538		if(!pFromTeam->HasEmbassyAtTeam(eToTeam) || !pToTeam->HasEmbassyAtTeam(eFromTeam))539			return false;540		// Already has DP541		if(pFromTeam->IsHasDefensivePact(eToTeam))542			return false;543		// Same Team544		if(eFromTeam == eToTeam)545			return false;546547		// Check to see if the other player can trade this item to us as well.  If we can't, we can't trade it either548		if(bCheckOtherPlayerValidity)549		{550			if(!IsPossibleToTradeItem(eToPlayer, ePlayer, eItem, iData1, iData2, iData3, bFlag1, /*bCheckOtherPlayerValidity*/ false))551				return false;552		}553	}554	// Research Agreement555	else if(eItem == TRADE_ITEM_RESEARCH_AGREEMENT)556	{557		if(GC.getGame().isOption(GAMEOPTION_NO_SCIENCE))558			return false;559560		// Neither of us yet has the Tech for RA561		if(!pFromTeam->IsResearchAgreementTradingAllowed() && !pToTeam->IsResearchAgreementTradingAllowed())562			return false;563		// Embassy has not been established with this team564		if(!pFromTeam->HasEmbassyAtTeam(eToTeam) || !pToTeam->HasEmbassyAtTeam(eFromTeam))565			return false;566		// DoF has not been made with this player567		if(!pFromPlayer->GetDiplomacyAI()->IsDoFAccepted(eToPlayer) || !pToPlayer->GetDiplomacyAI()->IsDoFAccepted(ePlayer))568			return false;569		// Already has RA570		if(pFromTeam->IsHasResearchAgreement(eToTeam))571			return false;572		// Same Team573		if(eFromTeam == eToTeam)574			return false;575		// Someone already has all techs576		if(pFromTeam->GetTeamTechs()->HasResearchedAllTechs() || pToTeam->GetTeamTechs()->HasResearchedAllTechs())577			return false;578579		// Check to see if the other player can trade this item to us as well.  If we can't, we can't trade it either580		if(bCheckOtherPlayerValidity)581		{582			if(!IsPossibleToTradeItem(eToPlayer, ePlayer, eItem, iData1, iData2, iData3, bFlag1, /*bCheckOtherPlayerValidity*/ false))583				return false;584		}585	}586	// Trade Agreement587	else if(eItem == TRADE_ITEM_TRADE_AGREEMENT)588	{589		// Neither of us yet has the Tech for TA590		if(!pFromTeam->IsTradeAgreementTradingAllowed() && !pToTeam->IsTradeAgreementTradingAllowed())591			return false;592		// Already has TA593		if(pFromTeam->IsHasTradeAgreement(eToTeam))594			return false;595		// Same Team596		if(eFromTeam == eToTeam)597			return false;598599		// Check to see if the other player can trade this item to us as well.  If we can't, we can't trade it either600		if(bCheckOtherPlayerValidity)601		{602			if(!IsPossibleToTradeItem(eToPlayer, ePlayer, eItem, iData1, iData2, iData3, bFlag1, /*bCheckOtherPlayerValidity*/ false))603				return false;604		}605	}606	// Permanent Alliance607	else if(eItem == TRADE_ITEM_PERMANENT_ALLIANCE)608		return false;609	// Surrender610	else if(eItem == TRADE_ITEM_SURRENDER)611		return false;612	// Truce613	else if(eItem == TRADE_ITEM_TRUCE)614		return false;615	// Peace Treaty616	else if(eItem == TRADE_ITEM_PEACE_TREATY)617	{618		if(!pFromTeam->isAtWar(eToTeam))619			return false;620621		if(!pToTeam->isAtWar(eFromTeam))622			return false;623			624#if defined(MOD_EVENTS_WAR_AND_PEACE)625		if (MOD_EVENTS_WAR_AND_PEACE) {626			if (GAMEEVENTINVOKE_TESTALL(GAMEEVENT_IsAbleToMakePeace, ePlayer, eToTeam) == GAMEEVENTRETURN_FALSE) {627				return false;628			}629630			if (GAMEEVENTINVOKE_TESTALL(GAMEEVENT_PlayerCanMakePeace, ePlayer, eToTeam) == GAMEEVENTRETURN_FALSE) {631				return false;632			}633		} else {634#endif635		ICvEngineScriptSystem1* pkScriptSystem = gDLL->GetScriptSystem();636		if (pkScriptSystem)637		{638			// Construct and push in some event arguments.639			CvLuaArgsHandle args;640			args->Push(ePlayer);641			args->Push(eToTeam);642643			// Attempt to execute the game events.644			// Will return false if there are no registered listeners.645			bool bResult = false;646			if (LuaSupport::CallTestAll(pkScriptSystem, "IsAbleToMakePeace", args.get(), bResult)) 647			{648				// Check the result.649				if (bResult == false)650				{651					return false;652				}653			}654		}655#if defined(MOD_EVENTS_WAR_AND_PEACE)656		}657#endif658	}659	// Third Party Peace660	else if(eItem == TRADE_ITEM_THIRD_PARTY_PEACE)661	{662		TeamTypes eThirdTeam = (TeamTypes) iData1;663664		// Can't be the same team665		if(eFromTeam == eThirdTeam)666			return false;667668		// Can't ask teammates669		if(eToTeam == eFromTeam)670			return false;671672		// Must be alive673		if(!GET_TEAM(eThirdTeam).isAlive())674			return false;675676		// Player that wants Peace hasn't yet met the 3rd Team677		if(!pToTeam->isHasMet(eThirdTeam))678			return false;679		// Player that would go to Peace hasn't yet met the 3rd Team680		if(!pFromTeam->isHasMet(eThirdTeam))681			return false;682		// Player that would go to peace is already at peace with the 3rd Team683		if(!pFromTeam->isAtWar(eThirdTeam))684			return false;685686		// Can't already have this in the deal687		//if (IsThirdPartyPeaceTrade( ePlayer, GET_TEAM(eThirdTeam).getLeaderID() ))688		//	return false;689690		// If eThirdTeam is an AI then they have to want peace with ToTeam691		CvPlayer* pOtherPlayer = &GET_PLAYER(GET_TEAM(eThirdTeam).getLeaderID());692		// Minor civ693		if(pOtherPlayer->isMinorCiv())694		{695			// Minor at permanent war with this player696			if(pOtherPlayer->GetMinorCivAI()->IsPermanentWar(eFromTeam))697				return false;698699			// Minor's ally at war with this player?700			else if(pOtherPlayer->GetMinorCivAI()->IsPeaceBlocked(eFromTeam))701			{702				// If the ally is us, don't block peace here703				if(pOtherPlayer->GetMinorCivAI()->GetAlly() != eToPlayer)704					return false;705			}706		}707		// Major civ708		else709		{710			// Can't ask them to make peace with a human, because we have no way of knowing if the human wants peace711			if(pOtherPlayer->isHuman())712				return false;713714			// Player does not want peace with eOtherPlayer715			if(pFromPlayer->isHuman() || pFromPlayer->GetDiplomacyAI()->GetWarGoal(pOtherPlayer->GetID()) < WAR_GOAL_DAMAGE)716				return false;717718			// Other player does not want peace with eToPlayer719			if(!pOtherPlayer->GetDiplomacyAI()->IsWantsPeaceWithPlayer(ePlayer))720				return false;721		}722	}723	// Third Party War724	else if(eItem == TRADE_ITEM_THIRD_PARTY_WAR)725	{726		TeamTypes eThirdTeam = (TeamTypes) iData1;727728		// Can't be the same team729		if(eFromTeam == eThirdTeam)730			return false;731732		// Can't ask teammates733		if(eToTeam == eFromTeam)734			return false;735736		// Must be alive737		if(!GET_TEAM(eThirdTeam).isAlive())738			return false;739740		// Player that would go to war hasn't yet met the 3rd Team741		if(!pToTeam->isHasMet(eThirdTeam))742			return false;743		// Player that wants war not met this team744		if(!pFromTeam->isHasMet(eThirdTeam))745			return false;746747		// Player that would go to war is already at war with the 3rd Team748		if(pFromTeam->isAtWar(eThirdTeam))749			return false;750751		// Can this player actually declare war?752#if defined(MOD_EVENTS_WAR_AND_PEACE)753		if(!pFromTeam->canDeclareWar(eThirdTeam, ePlayer))754#else755		if(!pFromTeam->canDeclareWar(eThirdTeam))756#endif757			return false;758759		// Can't already have this in the deal760		//if (IsThirdPartyWarTrade( ePlayer, GET_TEAM(eThirdTeam).getLeaderID() ))761		//	return false;762763		// Can't ask a player to declare war on their ally764		if(GET_TEAM(eThirdTeam).isMinorCiv())765		{766			if(GET_PLAYER(GET_TEAM(eThirdTeam).getLeaderID()).GetMinorCivAI()->GetAlly() == ePlayer)767				return false;768		}769	}770	// Third Party Embargo771	else if(eItem == TRADE_ITEM_THIRD_PARTY_EMBARGO)772	{773		return false;774	}775	// Declaration of friendship776	else if(eItem == TRADE_ITEM_DECLARATION_OF_FRIENDSHIP)777	{778		// If we are at war, then we can't until we make peace779		if(pFromTeam->isAtWar(eToTeam))780			return false;781782		// Already have a DoF?783		if (pFromPlayer->GetDiplomacyAI()->IsDoFAccepted(eToPlayer) && pToPlayer->GetDiplomacyAI()->IsDoFAccepted(ePlayer))784			return false;785	}786	// Promise to Vote in upcoming league session787	else if (eItem == TRADE_ITEM_VOTE_COMMITMENT)788	{789		// If we are at war, then we can't until we make peace790		if(pFromTeam->isAtWar(eToTeam))791			return false;792793		int iID = iData1;794		//antonjs: todo: verify iChoice is valid as well:795		//int iChoice = iData2;796		int iNumVotes = iData3;797		bool bRepeal = bFlag1;798799		DEBUG_VARIABLE(iNumVotes);800801		if(GC.getGame().GetGameLeagues()->GetNumActiveLeagues() == 0)802			return false;803804		CvLeague* pLeague = GC.getGame().GetGameLeagues()->GetActiveLeague();805		if(pLeague == NULL)806			return false;807808		CvAssert(pLeague->IsProposed(iID, bRepeal));809		CvAssert(iNumVotes <= pLeague->GetCoreVotesForMember(ePlayer));810		811		// Can't already have a vote commitment in the deal812		if(!bFinalizing && IsVoteCommitmentTrade(ePlayer))813			return false;814815		// Must be a valid proposal816		if(!pLeague->IsProposed(iID, bRepeal))817			return false;818819		// This player must be allowed to820		if(!pFromPlayer->GetLeagueAI()->CanCommitVote(eToPlayer))821			return false;822	}823824	return true;825}

Calls

Called by

45 functions in 4 files