4UC Integration: Non-database implementation coordination thread (COMPLETE)

azum4roll

Lost the game
Joined
Jul 17, 2018
Messages
4,795
Location
Somewhere
The proposal queue already has all the sponsors and completion status listed, but this thread will focus on implementation details as well as discussing any sponsor changes in case someone else wants to lift some burden off our shoulders.


Game mechanics​

Implemented by @Recursive

Accomplishments ✔​

Please implement this first, as a few tables depend on this.

New table: Accomplishments (ID, Type, Description) ✔
  • A type table that stores miscellaneous accomplishments like completing a policy tree of certain era, having an ideology, or having a certain belief class (pantheon, reformation, etc.)
  • Used solely as a reference type for other tables, and for descriptions in tooltips.
  • There will be an identical CLOSED enum (AccomplishmentTypes) in the DLL that's actually used for game logic. Modmodders should NOT modify this table (insert, update or delete), as it will change nothing.
  • Entries will be added as needed, as any new accomplishment requires additional DLL code to work. Next version will only have the ones needed for the new 4UC components.
  • For example, you can add a new accomplishment called WAR_VICTORY.
  • Note that since these are accomplishments, they can never be undone, i.e. you cannot nerf the Monolithic Church by conquering Ethiopia's holy city.
  • Each CvPlayer has an array storing its accomplishments that is only changed when things get achieved.
  • The entries:
    1. POLICY_ANCIENT (Ethiopia)
    2. POLICY_MEDIEVAL
    3. POLICY_INDUSTRIAL
    4. POLICY_IDEOLOGY
    5. BELIEF_PANTHEON
    6. BELIEF_FOUNDER
    7. BELIEF_FOLLOWER
    8. BELIEF_ENHANCER
    9. BELIEF_REFORMATION
    10. LONGCOUNT_GENERAL (Maya)
    11. LONGCOUNT_ADMIRAL
    12. LONGCOUNT_PROPHET
    13. LONGCOUNT_WRITER
    14. LONGCOUNT_ARTIST
    15. LONGCOUNT_MUSICIAN
    16. LONGCOUNT_ENGINEER
    17. LONGCOUNT_MERCHANT
    18. LONGCOUNT_SCIENTIST
    19. LONGCOUNT_DIPLOMAT
    20. ELIMINATE_PLAYER (Rome)
    21. DIPLOMATIC_MISSION (Greece)
  • Please also update the AI for each of these. Accomplishments currently can provide bonuses on player level, city level, and plot level (and probably unit level later on). If there are any bonuses for an accomplishment, AI should be more willing to work towards it.

Change to unit upgrade logic ✔

Units retain their original owner value when upgraded.


Traits​

Implemented by @Recursive

Columns​

  1. Unstack GPP modifier in capital with Traits.DiplomaticMarriage column ✔
    • Optional: implement a new Traits column for this
  2. New column: Traits.UnhappyUnitProductionMod
    • All cities gain this production modifier for units when empire is unhappy.
    • AI should be less willing to get happiness (if this is positive).
  3. New column: Traits.NoAvoidGrowth
    • Cities cannot avoid growth.
    • The checkbox on the UI should be disabled with a tooltip explaining why.
    • There should also be backend validation to ensure the function is disabled, in case CityView.lua is overridden (e.g. Improved City View).
  4. New column: Traits.RevoltTimerMod
    • Modifier for city revolution countdown timer.
    • AI should value happiness more if this is negative and empire is very unhappy (below 35% approval).

Tables​

  1. New table: Trait_YieldChangeFromCityGain (TraitType, YieldType, Yield)
    • All cities gain the specified per turn yields when acquiring a city (including the new city). PermanentYieldsDecreaseEveryEra will decrease this (apply modifier after adding up all sources) on era change (but China won't have it anymore).
    • AI settle/conquest logic should be considering the extra yields.
  2. New table: Trait_PermanentYieldChangeGoldenAge (TraitType, YieldType, Yield)
    • All cities gain the specified per turn yields when the empire enters a golden age. PermanentYieldsDecreaseEveryEra will decrease this (apply modifier after adding up all sources) on era change (but China won't have it anymore).
    • AI should be valuing golden ages more.
  3. New table: Trait_UnhappyYieldModifiers (TraitType, YieldType, Yield)
    • Empire gains the specified yield modifiers when unhappy.
    • Only works for gold, science, culture, faith, golden age points, and tourism. Top panel UI needs to be updated for each of these, plus the happiness tooltip.
    • AI should be less willing to get happiness (if this is positive).
  4. New table: Trait_ResourceYieldChangesFromGoldenAge (TraitType, ResourceType, YieldType, Yield, YieldCap)
    • Increase the yields of a resource type each time the empire enters a golden age. Increased yields cap at YieldCap.
    • Preferred container: vector<Firaxis::Array<int, NUM_YIELD_TYPES>>, whatever that is. Two each in CvTraitEntry, CvPlayerTraits, and CvPlayer.
    • AI should be going for golden ages more.
  5. Repurpose the Trait_FreeResourceFirstXCities table
    • So that it places the specified resources around the city instead of on the city tile.
    • If the spawned resource is RESOURCE_ARTIFACTS, also populate the site with artifact class ARTIFACT_SARCOPHAGUS (see CvGame:: PopulateDigSite()).
    • This obeys CvPlot::canHaveResource() validations, and I'll add the validation criteria for RESOURCE_ARTIFACTS via SQL.
    • The placement priority (random within each priority bracket):
      1. Owned or neutral tiles within new city's working range, no resource (including unrevealed)
      2. Owned tiles outside working range (including tiles owned by other cities), no resource (including unrevealed)
      3. Don't place it
    • Update CvGame::SpawnArchaeologySitesHistorically() to not count existing sites with ARTIFACT_SARCOPHAGUS class towards the antiquity site cap.
    • AI should account for the free resource when founding a city.
  6. New table: Trait_FreeResourceOnWonderCompletion (TraitType, ResourceType, ResourceQuantity)
    • Spawns the specified resources with ResourceQuantity on random tiles within owned territory on world wonder completion.
    • If the spawned resource is RESOURCE_ARTIFACTS, also populate the site with artifact class ARTIFACT_ANCIENT_RUIN.
    • This obeys CvPlot::canHaveResource() validations, and cannot replace existing resources.
    • AI should be more willing to build world wonders.
  7. New table: Trait_LuxuryYieldChanges (TraitType, YieldType, Yield)
    • Tiles with any luxury resource gain the specified yields.
    • Trait_ResourceYieldChanges exists, but this table is needed to keep the UI from exploding.
    • AI should score city sites and military targets with more nearby luxuries higher.
  8. New table: Trait_BonusFromGPBirth (TraitType, GreatPersonType, Heal, Experience)
    • All units heal X HP and gain Y experience when the specified great person is born.
    • This table can be expanded to have more bonuses like influence and WLTKD turns.
    • The Traits.XPBonusFromGGBirth column is obsoleted and removed (can be represented by Heal = 999 and Experience = 15).
    • AI should try to get more of these great people.


Projects​

Implemented by @Recursive
  1. New column: Projects.EmpireSizeModifierPerCityMod
    • Modifier to the EMPIRE_SIZE_NEED_MODIFIER_CITIES variable.
  2. New column: Projects.CivilizationType
    • The civilization that can exclusively work on this.
    • Also makes the project show up on civ info (pregame, loading, Civilopedia entry).
  3. New table: Project_UnitCombatProductionModifiersGlobal (ProjectType, UnitCombatType, Modifier)
    • Production modifier of units of specified combat classes in all cities.
  4. New table: Project_YieldFromConquestAllCities (ProjectType, YieldType, Yield)
    • Instant yields to all cities when the player conquers a city, scaling with era.
    • "All cities" includes the city that is being conquered.
For each of these new tables/columns, CvProjectProductionAI::CheckProjectBuildSanity() needs to be updated so the AI prioritizes these projects correctly.


Buildings​

Implemented by @axatin

Columns​

  1. New column: Buildings.GPRateModifierPerMarriage ✔
    • The city with this building gains +GPRateModPerMarriage% GPP per active marriage (not at war).
  2. New column: Buildings.GPPOnCitizenBirth ✔
    • Flat GPP towards the great person with most points (or most progress%, if implementation is easier that way), scaling with era.
    • AI should value population growth in this city more.
  3. New column: Buildings.GPRateModifierPerLocalTheme ✔
    • Modifier to GP rate per completed great work theme in the city.
    • AI should value themes in this city more.
  4. New column: Buildings.GlobalHappinessPerMajorWar ✔
    • +X global happiness per major civ currently at war with the player.
    • AI should be more likely to start wars and less likely to make peace.
  5. New column: Buildings.GlobalMilitaryProductionModPerMajorWar ✔
    • +X% production towards military units per major civ currently at war with the player.
    • AI should be more likely to start wars and less likely to make peace.
  6. New column: Buildings.NoStarvationNonSpecialist ✔
    • Non-specialists cannot consume more than the city's food per turn.
    • City governor needs to take this into account.
    • City view food tooltip needs to explain this.
  7. New column: Buildings.DefensePerXWonder ✔
    • Gain 1 city strength per X national/world wonder in the city.
    • Make sure this ability is stackable, using fraction.
    • AI should value building wonders more (very slightly).
  8. New column: Buildings.GarrisonRangedAttackModifier ✔
    • Modifier to the ranged attack strength of garrison in cities with this building.
    • Tactical AI needs to know about this and use ranged units as garrisons more.
  9. New column: Buildings.ExperiencePerGoldenAge, Buildings.ExperiencePerGoldenAgeCap
    • Units trained in cities with this building start with ExperiencePerGoldenAge more XP every time the empire enters a golden age after this building is built, capped at ExperiencePerGoldenAgeCap.
    • AI should be going for golden ages more.
  10. New column: Building_YieldFromVictoryGlobal.GoldenAgeOnly ✔
    • Self explanatory.
    • This will create 2 more arrays in CvCity if implemented similarly to IsEraScaling. Not ideal. It may be better to group (Yield, IsEraScaling, GoldenAgeOnly) into a struct?
  11. New column: Building_TechEnhancedYieldChanges.TechType
    • Specifies the tech required to boost the building. This allows multiple techs to boost the same building.
    • Nullable, will fall back to using Buildings.EnhancedYieldTech if so (backwards compatibility). If both are null, the row does nothing.
    • Preferred container: map<int (TechTypes), int* (yield array)> in CvBuildingEntry. Also handle the fallback here instead of all over the place in CvCity and CvTeam.
    • CityStrategyAIHelpers::GetBuildingYieldValue() needs to be updated. Currently it doesn't factor in the table at all.
    • Tech AI should value this tech more.
    • CityView.lua and EUI_tooltip_library.lua need to be updated to reflect the table changes. Maybe also make non-EUI show the updated yields?
    • Also use the same container for Buildings.TechEnhancedTourism if there's time.
  12. Fix Buildings.HappinessPerXPolicies so it can stack with the one from Prora instead of making it worse
    • While you're at it, fix Policies.ExtraHappinessPerXPolicies too. The new fraction class should be handy.

Tables​

  1. New table: Building_UnitClassTrainingAllowed (BuildingType, UnitClassType) ✔
    • This allows the specified unit classes to be trained in a city with this building.
    • Preferred container: set<UnitClassTypes> in CvBuildingEntry and CvCity
    • Unit's tooltip (EUI only?) should show that the building can unlock it.
  2. New table: Building_ResourceClaim (BuildingType, ResourceType, IncludeOwned) ✔
    • On construction, claim all tiles with specified resources within working range of the city, including owned tiles (not by you) if IncludeOwned is true.
    • Triggers instant yields from Trait_YieldFromTilePurchase.
    • Preferred container: set<pair<ResourceTypes, bool>> in CvBuildingEntry and CvCity
    • Neighbours should apply negative opinion modifiers as if the tiles are stolen by a culture bomb or Manifest Destiny (see CvUnit:: PerformCultureBomb() or CvCity::BuyPlot()).
    • AI should take neighbours' negative opinion modifiers into account when evaluating this building.
    • There should be notifications if tiles are claimed or owned tiles are stolen by this ability.
  3. New table: Building_LakePlotYieldChangesGlobal (BuildingType, YieldType, Yield) ✔
    • Boosts lakes globally.
  4. New table: Building_YieldFromGoldenAgeStart (BuildingType, YieldType, Yield) ✔
    • Instant yields to the city when the empire starts a golden age. Use YIELD_POPULATION for this.
    • Need to add a new InstantYieldType and corresponding CvPlayer::doInstantYield() logic.
  5. New table: Building_YieldChangesPerGoldenAge (BuildingType, YieldType, Yield, YieldCap) ✔
    • Yield changes to the building when the empire starts a golden age, capping at YieldCap.
    • Preferred container: 2 yield arrays each in CvBuildingEntry and CvCity
    • City view UI needs to have a new category on yields (from golden age). Currently there's only a %modifier version.
    • AI should be going for golden ages more.
  6. New table: Building_YieldFromPurchaseGlobal (BuildingType, YieldType, Yield) ✔
    • Similar to Building_YieldFromPurchase, but is triggered by all cities.
  7. New table: Building_GreatPersonPointFromConstruction (BuildingType, GreatPersonType, EraType, Value)
    • City gains Value% of production cost as the GPP of the specified great person on any building completion, if the building is unlocked on or later than EraType.
    • It can trigger off its own completion, like all other building completion bonuses on buildings.
    • Preferred container: map<pair<GreatPersonTypes, EraTypes>, int> in CvBuildingEntry and CvCity (I don't know why Building_GreatPersonProgressFromConstruction is using multimap<int, pair<int, int>> in CvBuildingEntry, but we don't have to follow that)
    • AI should value completing buildings (of relevant eras) more (as opposed to making units and using processes).
  8. New table: Building_YieldChangesPerLocalTheme (BuildingType, YieldType, Yield)
    • The building gets yield boosts from each completed great work theme in the city.
    • AI should value themes in this city more.
    • City view should put the yield boosts onto the building for display purposes.
  9. New table: Building_YieldFromUnitGiftGlobal (BuildingType, YieldType, Yield)
    • Instant yields to the city when any gifted unit from the player reaches the target city state.
    • Need to add a new InstantYieldType and corresponding CvPlayer::doInstantYield() logic.
    • AI should value unit gifts more.
  10. New table: Building_YieldChangesPerCityStrengthTimes100 (BuildingType, YieldType, Yield)
    • The building gains the specified yield boost per city strength.
    • AI should value city strength (and garrison) more.
    • City view should put the yield boosts onto the building for display purposes.
  11. New table: Building_YieldFromGPBirthScaledWithWriterBulb (BuildingType, YieldType, Yield)
    • Instant yield (of YieldType) to this city when a great person spawns there, equal to Yield% of the writer bulb of this great person.
    • It works on any great person that has a BaseCultureTurnsToCount value, but only great writers have that anyway.
    • The calls for CvPlayer::doInstantYield() for InstantYieldType INSTANT_YIELD_TYPE_GP_BORN should pass in the new unit.
    • The above instant yield type should grant the yields from this table.
  12. New table: Building_YieldFromGPBirthScaledWithArtistBulb (BuildingType, YieldType, Yield)
    • Instant yield (of YieldType) to this city when a great person spawns there, equal to Yield% of the artist bulb of this great person.
    • It works on any great person that has a BaseTurnsForGAPToCount value, but only great artists have that anyway.
    • The calls for CvPlayer::doInstantYield() for InstantYieldType INSTANT_YIELD_TYPE_GP_BORN should pass in the new unit.
    • The above instant yield type should grant the yields from this table.
  13. New table: Building_YieldFromGPBirthScaledWithPerTurnYield (BuildingType, GreatPersonType, YieldIn, YieldOut, Value)
    • Instant yield (of YieldOut) to this city when the specified great person spawns there, equal to Value% of YieldIn per turn of the empire.
    • Accounts for modifiers of YieldIn, unlike the Building_YieldFromYieldPercent table. This is actually more similar to the Building_GrowthExtraYield table, except YieldIn always equals YieldOut there and it counts local yields.
    • Preferred container: map<GreatPersonTypes, CvDoubleYieldInfo> in CvBuildingEntry and CvCity
    • The calls for CvPlayer::doInstantYield() for InstantYieldType INSTANT_YIELD_TYPE_GP_BORN should pass in the new unit.
    • The above instant yield type should grant the yields from this table.
  14. New table: Building_YieldFromTradeRouteEnd (BuildingType, YieldType, Yield, IsInternational)
    • Instant yield to this city when a trade route originated from this city is completed, scaling with era. Only counts international trade routes if IsInternational is true, and only counts internal trade routes otherwise.
    • Preferred container: two yield arrays each in CvBuildingEntry and CvCity
  15. New table: Building_YieldFromLongCount (BuildingType, YieldType, Yield)
    • Instant yields to the city with this building at the start of every bʼakʼtun, scaling with era.
  16. New table: Building_YieldChangesEraScalingTimes100 (BuildingType, YieldType, Yield)
    • The building gets the specified yield boosts scaling with era.
    • You could make the actual yields times100 if possible, like in Building_YieldChangesPerPop.
    • City view should put the yield boosts onto the building for display purposes.
  17. New table: Building_YieldChangesPerXBuilding (BuildingType, YieldType, Yield, NumRequired)
    • The building gets yield boosts from every NumRequired (non-dummy) buildings in the city.
    • Preferred container: fraction array with YieldTypes indices in CvBuildingEntry.
    • You could make the actual yields times100 if possible, like in Building_YieldChangesPerPop.
    • AI should value constructing buildings more.
    • City view should put the yield boosts onto the building for display purposes.
  18. New table: Building_YieldChangesFromMonopoly (BuildingType, YieldType, Yield)
    • The building gets yield boosts from every global monopoly owned by the player.
    • City view should put the yield boosts onto the building for display purposes.
  19. New table: Building_YieldChangesPerXTiles (BuildingType, YieldType, Yield, NumRequired)
    • The building gets yield boosts from every NumRequired tiles owned by the city.
    • Preferred container: fraction array with YieldTypes indices in CvBuildingEntry.
    • You could make the actual yields times100 if possible, like in Building_YieldChangesPerPop. We can just rebalance this later.
    • AI should value border expansions more.
    • City view should put the yield boosts onto the building for display purposes.
  20. New table: Building_YieldChangesFromXCityStateStrategicResource (BuildingType, YieldType, Yield, NumRequired)
    • The building gets yield boosts from every NumRequired strategic resource given by city state allies. Does not count the ones gained from policies.
    • Preferred container: fraction array with YieldTypes indices in CvBuildingEntry.
    • You could make the actual yields times100 if possible, like in Building_YieldChangesPerPop.
    • AI should prefer allying city states with more strategic resources.
    • City view should put the yield boosts onto the building for display purposes.
  21. New table: Building_YieldChangesFromPassingTR (BuildingType, YieldType, Yield)
    • The building gets yield boosts from every trade route that passes through the city.
    • AI should prefer trade routes that pass through own cities with this building (similar to villages/towns, if they're currently considered).
    • City view should put the yield boosts onto the building for display purposes.
  22. New table: Building_LuxuryYieldChanges (BuildingType, YieldType, Yield)
    • Tiles with any luxury resource owned by cities with this building gain the specified yields.
    • Building_ResourceYieldChanges exists, but this table is needed to keep the UI from exploding.
  23. New table: Building_YieldFromWLTKD (BuildingType, YieldType, Yield)
    • Instant yields to the city with this building when it gains WLTKD turns, scaling with era.
    • AI should value WLTKD more.
  24. New table: Building_WLTKDFromProject (BuildingType, ProjectType, Turns)
    • The city with this building gains WLTKD turns when it completes the specified project.
    • CvProjectProductionAI::CheckProjectBuildSanity() needs to be updated (higher score if the project gives WLTKD).
  25. New table: Building_YieldFromUnitLevelUpGlobal (BuildingType, YieldType, Yield)
    • The city with this building gains the specified yields when an owned unit levels up, scaling with original level (or new level - 1).
    • AI should focus on more XP gaining actions like building XP buildings, picking policies or beliefs with extra XP, training units in cities with more production XP, and doing combat with units.
  26. New table: Building_YieldChangesFromAccomplishments (BuildingType, AccomplishmentType, YieldType, Yield)
    • The building gets yield boosts from each specified accomplishment that the player has achieved.
    • Preferred container: map<int (AccomplishmentTypes), int* (yield array)> in CvBuildingEntry
    • AI should value completing these accomplishments more.
    • City view should put the yield boosts onto the building for display purposes.
  27. New table: Building_BonusFromAccomplishments (BuildingType, AccomplishmentType, Happiness, DomainType, DomainXP, UnitCombatType, UnitProductionModifier)
    • The building grants various bonuses (happiness, XP on units of specified domains, production modifier of units of specified combat classes) from each specified accomplishment that the player has achieved.
    • Preferred container: map<int (AccomplishmentTypes), BonusInfo> in CvBuildingEntry, where BonusInfo is a struct of the other columns
    • AI should value completing these accomplishments more.
    • City view should put the happiness onto the building for display purposes.
  28. New table: Building_ExtraPlayerInstancesFromAccomplishments (BuildingType, AccomplishmentType, ExtraInstances)
    • The building can be built ExtraInstances more times for every specified accomplishment achieved by the player, added on top of the building class limit.
    • This is a building table, but is not attached to any building instance like the others.
    • Preferred container: map<int (AccomplishmentTypes), int> in CvBuildingEntry
    • Change both CvPlayer::isProductionMaxedBuildingClass() and CvPlayer::isBuildingClassMaxedOut() to take a BuildingTypes instead of BuildingClassTypes parameter.
    • The Lua version of CvPlayer::isProductionMaxedBuildingClass() uses BasicLuaMethod, so it needs to be edited back to the original version (accepting BuildingClassTypes as the first parameter).
    • Use CvCivilizationInfo::getCivilizationBuildings() to get the corresponding BuildingTypes from BuildingClassTypes.
    • AI should value completing these accomplishments more.
For each of these new tables/columns, CvBuildingProductionAI::CheckBuildingBuildSanity() (and associated sub-functions) needs to be updated so the AI prioritizes these buildings correctly.
Changes to AI on how to use these abilities are already listed above.
For the bonus from accomplishment tables, leave the usage AI to the individual accomplishment implementers.


Units​

Implemented by @L. Vern
  1. New table: Unit_YieldOnCompletion (UnitType, YieldType, Yield)
    • Instant yields to the city that completes production or purchases this unit.
    • The calls for CvPlayer::doInstantYield() for InstantYieldType INSTANT_YIELD_TYPE_U_PROD, INSTANT_YIELD_TYPE_PURCHASE, and INSTANT_YIELD_TYPE_FAITH_PURCHASE should pass in the new unit.
    • The above 3 instant yield types should grant the yields from this table.
    • CvUnitProductionAI::CheckUnitBuildSanity() needs to be updated.
  2. New table: Unit_Bounties (UnitType, YieldType, Yield)
    • Instant yields to the city, or the origin city of the unit that defeats this unit.
    • The InstantYieldType INSTANT_YIELD_TYPE_VICTORY should grant the yields from this table (the defeated unit is already passed in).
  3. New column: Units.CopyYieldsFromExpendTile
    • When the unit is expended, the current yields from the tile (after factoring in the improvement that might be built by the unit) is added to the capital.
    • These yields are stored on the player instance, so will transfer to the new capital if the existing one is captured.
    • AI should prioritize a higher yield tile to expend this unit, and should value expending for an improvement more.
    • City view UI needs to have a new category on yields (from expending units).
  4. New column: Units.TileXPOnExpend
    • All units on the same tile gain XP when the unit is expended.
    • AI should try to stack at least one unit that can gain promotions before expending this unit (asking for the best unit is probably not viable...)
For each of these new tables, CvUnitProductionAI::CheckUnitBuildSanity() (and associated sub-functions) needs to be updated so the AI prioritizes these units correctly.


Promotions​

Implemented by @L. Vern

Columns​

  1. Existing unimplemented column: UnitPromotions.AdjacentCityDefenseMod ✔
    • For the sake of AI, garrisoned unit should also apply the modifier. It only works on city defense strength and is excluded from city strike strength.
    • The AI doesn't need to be taught to use this, but it would be nice if they factor this in.
  2. New column: UnitPromotions.BorderMod
    • The modifier is applied when the unit is on a border tile. Owner of the tile doesn't matter.
    • It considers the FROM plot for ranged attacks and TO plot for melee attacks.
  3. New columns: UnitPromotions.MarriageMod, UnitPromotions.MarriageModCap
    • The unit gains MarriageMod% combat strength per active marriage (not at war), and bonus is capped at MarriageModCap%.
    • Promotion picker AI update is optional. It's very unlikely that this ability becomes pickable.
  4. New column: UnitPromotions.CombatModPerLevel
    • +X% combat strength per level above 1.
    • No cap needed (even though it's in the proposal); it's unlikely that a unit can reach level 15. And if one does, it deserves the bonus.
  5. New column: UnitPromotions.DamageTakenMod
    • +X% damage taken from all sources. Can be positive to be used as a plague or negative to be used as a damage reduction promotion.
  6. New column: UnitPromotions.InfluenceFromCombatXpTimes100
    • When units with this promotion gains XP through combat, gain influence towards the nearest city state using this conversion rate.
  7. New column: UnitPromotions.FreeAttackMoves
    • Units with this promotion don't lose movement on attack, including from any terrain penalty or ZoC.
    • Tactical AI change is likely required so the AI can make use of this.
  8. New column: UnitPromotions.CapitalDefenseLimit
    • Used with CapitalDefenseModifier and CapitalDefenseFalloff.
    • All 3 can be any integer, but the unit won't have any near capital modifier if CapitalDefenseFalloff is 0 regardless of the other two values. Use the generic AttackMod and DefenseMod instead in this case.
    • Near capital modifier is no longer always positive and bottoms at 0. Instead, the modifier is set to CapitalDefenseLimit if this number is between CapitalDefenseModifier + (distance - 1) * CapitalDefenseFalloff and CapitalDefenseModifier + distance * CapitalDefenseFalloff.
    • No explicit check is needed to ensure CapitalDefenseLimit is applied - the modifier will simply be uncapped if the limit is never reached.
    • Promotion picker AI needs to be updated to handle the negative case.
    • Optional: also update military AI so units with bonus near capital are more likely to be assigned to operations near the capital, and vice versa.
  9. New column: UnitPromotions.VsUnhappyMod
    • +X% combat strength against units from unhappy empire.
  10. New column: UnitPromotions.PillageFortificationsOnKill
    • Units with this promotion pillage the target tile's fortifications when attacking and defeating a unit. No on pillage effects (heal, damage, XP, gold steal, instant yields) are triggered.
    • Make sure it works for all attacks (melee, ranged, air, nuke).
    • Tactical AI should be more willing to deal the killing blow on enemy units stationed on important tiles (strategic/luxury resources, citadels, etc.)
  11. New columns: UnitPromotions.AttackModPerSamePromotionAttack, UnitPromotions.AttackModPerSamePromotionAttackCap
    • +AttackModPerSamePromotionAttack% combat strength when attacking for every attack done by units with this promotion on the same turn, capped at AttackModPerSamePromotionAttackCap%.
    • Forget about updating promotion picker AI, they're better off not wasting a level on this.
  12. New column: UnitPromotions.CombatModPerCSAlliance
    • +X% combat strength for every city state alliance, capped at BALANCE_MAX_CS_ALLY_STRENGTH allies.
  13. New column: UnitPromotions.AoEHealOnPillage
    • +X HP to all adjacent owned units when pillaging improvements that do not block healing.
    • AI should factor in the area heal when determining whether it should pillage and which tile to pillage.
  14. New column: UnitPromotions.ExtraXPOnKill
    • Units with this promotion gain the specified amount of XP when defeating an enemy unit.
    • This counts as XP from combat, which means it doesn't scale with game speed, is affected by XP modifiers, triggers instant yields from combat experience, and contributes to great general/admiral generation.
  15. New column: UnitPromotions.XPFromPillaging
    • +X XP when pillaging an improvement.
    • This replaces the GainsXPFromPillaging boolean column.
  16. New column: UnitPromotions.CannotHeal
    • Units with this promotion cannot have their HP increased by any means (healing, pillaging, leveling up, AoE heal abilities, etc.)
    • Promotion picker AI needs to be updated to apply a big negative score.
    • Unit AI should value healing abilities at 0 for units with this promotion.
    • Tactical AI should not attempt to heal or assume it can be healed.
  17. New column: UnitPromotions.RequiresLeadership
    • If true, the promotion is only effective if the unit starts its turn affected by leadership aura (great general/admiral depending on domain).
    • Promotion picker AI needs to be updated to apply a (variable) multiplier depending on number of generals/admirals, aura radius, etc.
    • Tactical AI needs to know about this and try to keep these units within leadership aura.
  18. New column: UnitPromotions.FortifyEffectiveness
    • Percentage multiplier on fortify combat strength bonus. Default 100.
    • Tactical AI needs to know about this.
  19. New column: UnitPromotions.TileDamageIfNotMoved
    • The unit with this promotion deals X damage to all units on the target tile, if it hasn't moved before the attack.
    • Damage dealt this way is not modified by any damage reduction on the target(s), and should set off all on-kill triggers.
    • This counts as two damage instances on the target, if it matters for some future mechanics. There should be separate plot popup and military log messages.
    • The check is CvUnit::hasMoved(), so attacking also counts as having moved.
    • You'll need to somehow save the value before CvUnit::setMadeAttack() is called, which comes before CvUnitCombat::ResolveCombat(). Maybe as an extra boolean in CvCombatInfo?
    • Tactical AI needs to know about this.
  20. New column: UnitPromotions.CombatChange
    • +X base combat strength.
  21. New column: UnitPromotions.MinEffectiveHealth
    • This promotion is only effective when the unit starts its turn at or above this percentage of health.
    • AI should prioritize healing this unit when below the threshold if the promotion has positive effects, and de-prioritize healing if the promotion has negative effects.
  22. New columns: UnitPromotions_UnitCombatMods.Attack, UnitPromotions_UnitCombatMods.Defense
    • Just like UnitPromotions_Domains, it's desirable to separate attack and defense modifiers.

Tables​

  1. New table: UnitPromotions_YieldFromAncientRuins (PromotionType, YieldType, Yield)
    • Instant yields to the origin city of the unit with this promotion, when it picks up an ancient ruin.
  2. New table: UnitPromotions_YieldFromTRPlunder (PromotionType, YieldType, Yield)
    • Instant yields to the origin city of the unit with this promotion when it plunders a trade route.
  3. New table: UnitPromotions_Plagues (PromotionType, PlaguePromotionType, DomainType, ApplyOnAttack, ApplyOnDefense, ApplyChance)
    • Allows units with PromotionType to add PlaguePromotionType to enemy unit of DomainType (ALL domains if NULL) with ApplyChance% chance on attack or defense depending on the booleans ApplyOnAttack and ApplyOnDefense.
    • This table replaces all existing plague columns in the UnitPromotions table, except PlagueID and PlaguePriority.
      • Plague immunity is no longer determined by plague ID (see UnitPromotions_BlockedPromotions table below).
      • Higher priority plague with the same ID removes any existing lower priority plague promotions from the inflicted unit, and blocks them from being added to the inflicted unit (via CvUnit::setHasPromotion()).
        • This is different from the current behaviour where it's possible to gain a lower priority plague via non-plague ways!
    • Preferred container: map<PromotionTypes, PlagueInfo> in CvPromotionEntry and CvUnit, where PlagueInfo is a struct of the other columns
    • Tactical AI should factor in plagues and immunities.
  4. New table: UnitPromotions_BlockedPromotions (PromotionType, BlockedPromotionType)
    • Units with this promotion cannot obtain the specified blocked promotions by any means.
    • All existing blocked promotions are removed from the unit when it gains this promotion.
    • Preferred container: set<int (PromotionTypes)> in CvPromotionEntry and CvUnit
    • The UnitPromotions.NegatesPromotion column is not obsoleted by this - there could be a use case where you only want to negate a promotion from being gained via tile terrain/feature.
  5. New table: UnitPromotions_YieldFromCombatExperienceTimes100 (PromotionType, YieldType, Yield)
    • Units with this promotion gain the specified yields per experience point gained from combat.
  6. New table: UnitPromotions_TerrainModifiers (PromotionType, TerrainType, Attack, Defense)
    • +X% combat strength when attacking/defending on the specified terrains.
    • Counts the target tile when melee attacking, and the tile where the unit originally is otherwise.
    • This needs to work on TERRAIN_HILL, using the CvPlot::isHills() check.
    • All existing VP promotions will switch to use this table instead of UnitPromotions_Terrains for combat modifiers on terrain. (Highlander and Altitude Training)
Unless otherwise stated, CvUnit::AI_promotionValue() (and associated sub-functions) needs to be updated so the AI picks the correct promotion according to its needs.
Changes to AI on how to use these abilities are already listed above. Some may need @ilteroi's help.


Improvements​

Implemented by @KungCheops
  1. New column: Improvements.BlockTileSteal ✔
    • Blocks the tile from being stolen by any means. Disabled when pillaged.
  2. New table: Improvement_YieldPerXAdjacentTerrain (ImprovementType, TerrainType, YieldType, Yield, NumRequired) ✔
    • The tile with the improvement gains the specified yields for every NumRequired adjacent TerrainType.
    • Uses the new fraction class, and will be truncated only at the end of the CvPlot::calculateImprovementYield() function after adding all fractions.
    • Preferred container: 2D fraction array of TerrainTypes and YieldTypes indices in CvImprovementEntry
  3. New table: Improvement_DomainProductionModifier (ImprovementType, DomainType, Modifier) ✔
    • The city owning the tile with this improvement gains a production modifier towards units of the specified domain (can stack).
    • Preferred container: just use arrays
    • Not sure how to score this, but at least do a coastal sanity check i.e. +0 score if city is non-coastal and DomainType is DOMAIN_SEA.
    • City view UI needs to have a new category on production modifier (from improvements, or maybe from terrain?).
  4. New table: Improvement_DomainFreeExperience (ImprovementType, DomainType, Experience) ✔
    • The city owning the tile with this improvement gives bonus experience to trained units of the specified domain (can stack).
    • Preferred container: just use arrays
    • Not sure how to score this, but at least do a coastal sanity check i.e. +0 score if city is non-coastal and DomainType is DOMAIN_SEA.
  5. New column: Improvements.GreatPersonRateModifier ✔
    • The city working the tile with this improvement gains a modifier to great person points (can stack).
    • City governor need to be updated.
    • City view UI needs to have a new category on GPP modifier (from improvements).
  6. New table: Improvement_YieldFromAccomplishments (ImprovementType, AccomplishmentType, YieldType, Yield) ✔
    • The improvement gets yield boosts from each specified accomplishment that the player has achieved.
    • Preferred container: map<int (AccomplishmentTypes), int* (yield array)> in CvImprovementEntry
    • AI should value completing these accomplishments more.
    • EUI expanded tile tooltip should include the accomplishment boosts (shown like tech/building/policy/belief boosts, using the Description text in Accomplishments table).
  7. Check if TacticalAIHelpers::ExecuteUnitAssignments() needs to be updated to make Tersane buildable during war ✔
BuilderTaskingAI needs to be updated for each of the above. Some abilities may need additional implementation to teach AI how to use them (already listed).


General stuff that should be implemented at the very end by one sponsor each, to avoid conflicts:
  • New combat modifiers in combat simulator (EnemyUnitPanel.lua)
  • Civilopedia extended information panel (CivilopediaScreen.lua)
    • Current sponsor: none
  • City view new yield categories and display boosted building yields (CityView.lua)
Art assets will be asked for individually when needed, like new promotion icons.
Currently needed assets: None! All assets are in the repository now.


Note to all implementers:

"How the AI should use each ability" should be agnostic to the component type that provides the ability, e.g. it doesn't matter if a trait, building, or project give +20% production to the player while in a golden age.
Which means some of the above AI changes could be repeated. Please coordinate with other implementers if it is the case.
 
Last edited by a moderator:
Art assets will be asked for individually when needed, like new promotion icons.
Currently needed assets:
  • Promotion icon for Shock Cavalry
  • Promotion icon for Schützenkönig
  • Promotion icon for Elisha's Guile
  • Promotion icon for At the Gates!
  • Promotion icon for Sun Never Sets (will be used for both Redcoats and naval units)
  • Promotion icon for Rule Britannia
  • Promotion icon for Zemene Mesafint
  • Promotion icon for Sentinel of the Sun
Spoiler Proposition :
Global.png

For Shock Cavalry and Schützenkönig, I reused the existing icons, they were very good.
For Zemene Mesafint, I'm looking for a symbol of the "Era of the Princes" or may be a significant character of the Geʽez alphabet ?
 
Everything's sorted out! Implementation is currently under way.

As you can see, the list is huge and it's going to take some time before the implementation is done. And then there's testing and inevitable debugging.

Some of the AI may not be optimal. It'll have to wait for the big AI rework, where AI will know how much everything's worth.

Implementers, please re-read your part(s) and voice out any potential problems. The "Notes to all implementers" part is new.
 
Everything's sorted out! Implementation is currently under way.

As you can see, the list is huge and it's going to take some time before the implementation is done. And then there's testing and inevitable debugging.

Some of the AI may not be optimal. It'll have to wait for the big AI rework, where AI will know how much everything's worth.

Implementers, please re-read your part(s) and voice out any potential problems. The "Notes to all implementers" part is new.
What is the "big AI re-work"?
 
Currently AI scores decisions with arbitrary numbers + flavors, which differ between different AI. For example, policy AI and building production AI may have different numbers for the same "start a free golden age" ability.

The rework plans to unify all AI evaluation using the same base unit, e.g. a golden age is worth 10000 units while 1 instant production is worth 2 units.
It'll also score the future values of those, e.g. 50 turns later a golden age will be worth 30000 units while 1 instant production will only be worth 1.5 units.
Then we can more easily score more complex stuff like "+20% production during golden age" that lasts the entire game. The AI will be able to actually predict the future.

Of course, this is just a plan in my head. Absolutely nothing has been finalized.
 
Everything's sorted out! Implementation is currently under way.

As you can see, the list is huge and it's going to take some time before the implementation is done. And then there's testing and inevitable debugging.

Some of the AI may not be optimal. It'll have to wait for the big AI rework, where AI will know how much everything's worth.

Implementers, please re-read your part(s) and voice out any potential problems. The "Notes to all implementers" part is new.
This sounds incredible to be honest! Any idea how the AI will be once 4UC VP is released? Will they use all the new units and buildings would you say?
 
They'll have around the same intelligence as they have for the currently existing units/buildings. They'll use them, but not optimally.
 
They'll have around the same intelligence as they have for the currently existing units/buildings. They'll use them, but not optimally.
Holy crap so your potential new AI method is not referring to the new units and buildings, but the ENTIRE AI as a whole?
 
Currently AI scores decisions with arbitrary numbers + flavors, which differ between different AI. For example, policy AI and building production AI may have different numbers for the same "start a free golden age" ability.

The rework plans to unify all AI evaluation using the same base unit, e.g. a golden age is worth 10000 units while 1 instant production is worth 2 units.
It'll also score the future values of those, e.g. 50 turns later a golden age will be worth 30000 units while 1 instant production will only be worth 1.5 units.
Then we can more easily score more complex stuff like "+20% production during golden age" that lasts the entire game. The AI will be able to actually predict the future.

Of course, this is just a plan in my head. Absolutely nothing has been finalized.
Excellent idea to have the AI use utils+PV discounting.
 
Currently AI scores decisions with arbitrary numbers + flavors, which differ between different AI. For example, policy AI and building production AI may have different numbers for the same "start a free golden age" ability.

The rework plans to unify all AI evaluation using the same base unit, e.g. a golden age is worth 10000 units while 1 instant production is worth 2 units.
It'll also score the future values of those, e.g. 50 turns later a golden age will be worth 30000 units while 1 instant production will only be worth 1.5 units.
Then we can more easily score more complex stuff like "+20% production during golden age" that lasts the entire game. The AI will be able to actually predict the future.

Of course, this is just a plan in my head. Absolutely nothing has been finalized.
I've had similar ideas floating around in my head for a while. Currently, the worker AI part tries to evaluate everything in terms of GPT (1 GPT is 100 units). But it would be nice if everything was evaluated over time, e.g. now there's no good way to evaluate 50 instant production or +1 GPT for 20 turns.

Would be really cool to have a dynamic system for the AI to understand how things scale and priorities shift over time.
 
Changed the structure of the plague table.
Now PlagueID and PlaguePriority remain in the UnitPromotions table as they're properties of the plague promotion, not the inflicting promotion.
Plague immunity is no longer determined by plague ID, and plagues (and any promotions) are instead blocked by UnitPromotions_BlockedPromotions.
 
CopyYieldsFromExpendTile is now a Units column instead of a UnitPromotions column.

Which means it's tied to unit itself, like the expend action. Tadodaho no longer needs the Reciprocity promotion.

Same with TileXPOnExpend. InDuna will not have the Ibutho promotion.
 
Last edited:
Added two new columns: Buildings.ExperiencePerGoldenAge, Buildings.ExperiencePerGoldenAgeCap, which are needed for Telpochcalli.

(Its bonus being retroactive would make these columns unnecessary (use Accomplishments instead))
 
Added a new table for Riad: Building_YieldChangesEraScalingTimes100
 
Back
Top Bottom