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}