Hooks - ilikegoodfood/CommunityLib GitHub Wiki

Hooks

Using the Harmony Library, the Community Library inserts a number of new hooks for use by other mods. These hooks are listed and below below.

All of these hooks are within the CommunityLib.Hooks class. In order to make use of these hooks, create a class in your own mod that inherits from CommunityLib.Hooks, and override the hooks that you wish to use.

Once this is done, you will then need to register your new class instance with the Community Library. This must be done when a new game starts, in the beforeMapGen hook in the ModKernel, and when loading a game, in the afterLoading hook in the ModKernel.
To register your hooks class instance, call the RegisterHooks function in the CommunityLibrary's ModCore class, the Community Library's ModKernel.

Table of Contents

Map Generation
Graphical Updates
Events
Pathfinding
Unit Deaths
Raze Location
Settlement Destruction
Agent Battles
Army Battles (Battle Cycle)
Army Battles (Retreat and Victory)
Army Battles (Misc.)
Get Visible Units
Agent Recruitability
Agent Level Up
Agent Gains Items
Action Taking Monsters
Regional Actions
Challenges
Popup Holy Order
Tenets
UILeftLocation
UIScroll_Unit
AgentAI

Map Generation

The Community Library provides the following hooks that allow modification of the map generation system.

onMapGen_PlaceWonders

There are two different overrides of the onMapGen_PlaceWonders hook. If you are using oneof these hooks, you will want to use the other.

List<Type> onMapGen_PlaceWonders()

This hook is called when the map generation system is preparing to generate the natural wonders. It should return null, or a list containg the Types of all natural wonders that you wish to add to the spawn pool.

The map generation ssytem wil then pick a wonder at random from the wonder type pool, spawning them if they are from the base game, or calling the second version of the hook if they are not.

void onMapGen_PlaceWonders(Type t)

This second version of the hook will recieve the Type of natural wonder that the map generation system wants spawned (t). If that type matches one of the types provided by your mod, it should be spawned in this hook.

Graphical Updates

The Community Library provides the following hooks as part of the graphical updates system.

onGraphicalUnitUpdated

void onGraphicalUnitUpdated(GraphicalUnit graphicalUnit)

This hook fires just after a graphical unit has been updated. It receives the graphical unit (graphicalUnit).

onGraphicalLinkUpdated

void onGraphicalLinkUpdated(GraphicalLink graphicalLink)

This hook fires just after a graphical link has been updated. It receives the graphical link (graphicalLink).

NOTE: Graphical links are updated as part of Unity's Update() function, which is called every time a frame is generated. As such, this hook should not contan any logic for determining what type a hook is or how it should be handled. That should be done on link creation, and or in any of the mod kernel's turn tick hooks, i.e. onTurnStart or onTurnEnd.
In order to minimize the cost of checking if a link is of a particular type, it is highly recommended to store the pre-determined links in a HashSet<GraphicalLink>. These enumerators are a form of unordered list that are optimized for searching. See the example code below:

{
    HashSet<GraphicalLink> redLinks;
    HashSet<GraphicalLink> invisibleLinks;
    HashSet<GraphicalLink> greenLinks;

    public override void onGraphicalLinkUpdated(GraphicalLink graphicalLink)
        {
            if (redLinks.Contains(graphicalLink))
                {
                    // Do Stuff
                }
            else if (greenLinks.Contains(graphicalLink))
                {
                    // Do other stuff
                }
            // And so on.
        }
}

Events

The Community Library provides the following hooks that allow dependent mods to modify the processing of events.

onEvent_IsLocationElderTomb

bool onEvent_IsLocationElderTomb(Location location)

This hook fires when an event checks if a location is the location of the Elder Tomb. It only fires if the location's settlement is not an instance of Set_TombOfGods, or a subclass thereof. It recieves the Location beibng checked (location) and returns whether the location should be considered to be the elder tomb.

This hook is not called to determine whether a graphical hex should display a property overlay for an atypical Elder Tomb. If you wish your atypical Elder Tomb to not display a property overlay, of if you wish it to display a speciifc property overlay, use the base game's onGraphicalHexUpdated hook instead.

No hook after the first hook to return true will be called.

onRevivePerson_CreateAgent

UA onRevivePerson_CreateAgent(Person person, Location location)

This hook fires when the revivePerson function is attempting to determine what agent should be produced for a person who does not have an Agent (UA) assigned to them. It recieves the Person (person) that is being revived, and the Location (location) at which they should be revived. It should return the intended Agent for that person, or null.

Hooks after the first to return something other than null do not fire. If all mods return null, a new agent will be selected based on hard-coded defaults.

void onRevivePerson_EndOfProcess

void onRevivePerson_EndOfProcess(Person person, Location location)

This hook fires after the revivePerson function has revived a person. It recieves the Person that is being revived (person), and their current Location (location).

It is intended to provide dependent mods the opportunity to reset any values that the base function does not know exists.

Pathfinding

The Community Library offers the following hooks that interact with the A* pathfinding system that it replaces the vanilla pathfinding system with. For details of those hooks see Pathfinding: Hooks.

The Community Library also replaces the pathfinding system used to generate trade routes. For details of those hooks see Pathfinding: Trade Route Hooks.

This section also includes a hook for detecting when a unit has moved.

NOTE: If you plan on implementing an item, minion, trait or any other effect that changes a unit's max movements, or blocks or refunds movements in any way, it is imperrative that you use the onUnitAI_GetsDistanceToLocation hook included below. It will allow units to account for the changed tarvel time to a location in it's utility scores, and in the duration of distance-dependant tasks.

onMoveTaken

void onMoveTaken(Unit u, Location locA, Location locB)

This hook fires when a unit is taking a step to a new location. All base-game movement processing has already been completed, except for incerementing the unti's movesTaken value. It receives the unit moving (u), the unit's current location (locA), and the unit's new location (locB).

NOTE: The unit's int movesTaken value will not yet have been incremented, as that is done by the function that called for the movement to take place, not by the movment function itself. To refund a move taken, descrement the unit's movesTaken value by 1, even if that results in a temporariliy negative value.

NOTE 2: It is currently impossible to fully account for multiple mods refunding moves taken on the same move action. The Community Librray does perform some basic safety checks though, as it will not allow the final movesTaken value, after all mods have adjusted it, to be less than -1, which would indicate multiple mods refunding movement steps, or greater than the agent's max moves.

onUnitAI_GetsDistanceToLocation

int onUnitAI_GetsDistanceToLocation(Unit u, Location target, Location[] pathTo, int travelTime)

This hook fires when several key functions in the base game tries to get the shortest distance to a location. These functions are UA.distanceDivisor, Task_AttackArmy, Task_AttackUnit, Task_AttackUnitWithEscort, Task_Bodyguard, Task_DisruptUA, and CommunityLibrary.AgentAI.getDistanceDivisor.

It receives the unit (u), the target location (target), the path to the target location (pathTo), and the time it will take the agent to traverse it's path to the destination (travelTime). The travelTime is equal to the length of the pathTo, unles the PathTo is null, in which case it will be equal to Map.getStepDistance(u.location, loc) / u.getMaxSteps(), divided by the unit's max moves, rounded up. It returns the calculated travelTime.

If a mod that is loaded before yours has already altered the travel time, the travelTime passed into this hook will already include that change.

NOTE: It is impossible to properly account for an unit having multiple means of reducing their travel cost, such as the cursed boots from the Coven's Curses and Curios mod, and a hypothetical Camal minion that grants an extra movement step on arid and desert locations. This will lead to agents slightly under-estimating the time cost of paths that are effected in this way.
The Community Library caps the minimum time, for an intial distance greater than 0, to 1. This is to prevent negative values from edge-case interactions.

Unit Death

The Commonunity Library adds two new hooks that interact with Unit Death. These hooks will fire before the base game's Person Death hooks, and will fire even if the target is a person. Make sure to either use only the Unit Death hooks for your on-death logic, or to ignore agents in your Unit Death hooks.

unitIsSubsumed

bool isUnitSubsumed(Unit uOriginal, Unit uSubsuming)

This hook fires when a mod needs to check if a unit is subsumed (marked as dead but is actually alive as part of another unit). It recieves the original unit (uOriginal), and the current unit that is assigned to the person of the original unit (uSubsuming). It returns if the original unit is subsumed by the subsuming unit as a bool.

No instance of this hook is called after the first to retun true.

interceptUnitDeath

bool interceptUnitDeath(Unit u, string v, Person kiler = null)

This hook fires when a unit is instructed to die. It recieves the Unit (u), a string representation of the cause (v), and the person, if applicable, that casued their death (killer).

If this hook returns true, the rest of the death proccess will not happen. If you wish to keep the unit alive and prevent this check being performed multiple times per turn, make sure that their health is greater than 0, or their cause of death has been removed. The process which initially instructed the unit to die will still continue, so if you wish to keep the unit alive, make to sure to account for, and act in response to, the method of its death.

Instances of this hook will be called up to the first to return true, aborting the death process.

onUnitDeath_StartOfProcess

void onUnitDeath_StartOfProcess(Unit u, string v, Person killer)

This hook fires when a unit is instructed to die, but after the interceptUnitDeath hook. It recieves the Unit (u), a string representation of the cause (v), and the person, if applicable, that casued their death (killer).

Raze Location

The Community Library introduces the following hook for performing custom actions while a location is being razed.

onRazeLocation_StartOfProcess

void onRazeLocation_StartOfProcess(UM um)

This hook fires each turn while a military unit is razing a settlement, after validating that the task is still valid. It recieves the military unit that is performing the task (um).

onRazeLocation_EndOfProcess

void onRazeLocation_EndOfProcess(UM um)

This hook fires each turn while a military unit is razing a settlement, after the task's turnTick has occured. It will not fire if the task becomes invalid. It recieves the military unit that is performing the task (um).

If the settlement being razed was destroyed this turn, the task of the military unit (um) will equal null.

Settlement Destruction

The Community Library introduces the following hooks for interacting with the destruction of a settleemnt.

interceptSettlementFallIntoRuin

bool interceptSettlementFallIntoRuin(Settlement set, string v, object killer = null)

This hook fires when a settlement is destroyed. It recieves the settlement (set), a string representation of the cause (v), and the object, if applicable, that casued its destruction (killer).

If this hook returns true, the rest of the ruin proccess will not happen. If you wish to keep the settlement intact and prevent this check being performed multiple times per turn, make sure that their cause of destruction has been removed. The process which initially instructed the settlement to fall into ruin will still continue, so if you wish to keep the settlement intact, make to sure to account for, and act in response to, the method of its destruction.

All instances of this hook will run whenever a settlemnt is instructed to fall into ruin, even those after one which has returned true.

onSettlementFallIntoRuin_StartOfProcess

void onSettlementFallIntoRuin_StartOfProcess(Settlement set, string v, object killer = null)

This hook fires when a settlement is destroyed, but after the interceptSettlementFallIntoRuin hook. It recieves the settlement (set), a string representation of the cause (v), and the object, if applicable, that casued its destruction (killer).

onSettlementFallIntoRuin_EndOfProcess

void onSettlementFallIntoRuin_EndOfProcess(Settlement set, string v, object killer = null)

This hook fires when a settlement is destroyed, after all other processing has concluded. It recieves the settlement (set), a string representation of the cause (v), and the object, if applicable, that casued its destruction (killer).

Agent Battles

The Community Library provides the following additional hooks for interacting with AGent Battles:

onMinionAttackAboutToBePerformed

int onMinionAttackAboutToBePerformed(Minion attacker, UA other, PopupBattleAgent popup, BattleAgents battle, int dmg, int row)

This hook fires when a minion in a minion battle is about to make an attack. It receives the Minion that is about to attack (attacker), the enemy Agent (other), the Battle Popup Window (battle), which is null if history is generating or popups are otherwise disabled, the agent battle (battle), the damage that it si about to deal (dmg), and the row that it is attick down (row). It returns the damage that the minion will do.

The Row directly corrisponds to the index of the minions on both agents. If "other.minions[row]" is equal to null, then the damage will be dealt to the enemy agent.

If another mod has already modified the damage value using this hook, that change will be in the damage value that you receive.

onAgentBattle_ReceiveDamage

int onAgentBattle_ReceiveDamage(PopupBattleAgent popup, BattleAgents battle, UA defender, Minion minion, int dmg, int row)

This hook fires when an agent or one of their minions is about to take attack damage in an agent battle. It receives the popup battle window (battle), which is null if the history is generating or popups are otherwise disabled, the agent battle (battle), the agent whom the attack is directed towards (defender), the minion that is about to recieve the damge in the agent's stead (minion) if any, the damage they are about to receive (dmg), and the row that the attack is made down (row). It returns the damage that the victim will receive.

The Row directly corrisponds to the index of the minions on both agents. If minion is not null, it is stored in "defender.minion[row]".

If another mod has already modified the damage value using this hook, that change will be in the damage value that you receive.

onAgentBattle_ReinforceFromEscort

Minion onAgentBattle_ReinforceFromEscort(UA ua, UM escort)

This hook fires once for each dead minion or empty minion slot of each agent in the battle that has an escort. It recieves the agent who is attempting to reinforce (ua), and the military escort (escort). It returns the Minion that will fill the agent's minion slot.

No instance of this hook will fire after the first to return a result that is not null.

Army Battles (Battle Cycle)

The Community Library introduces a complete set of hooks for interacting with Army Battles. This fisr batch of hooks follow the standard battle cycle, in order of operations.

interceptArmyBattleCycle

bool interceptArmyBattleCycle(BattleArmy battle)

This hook fires at the beginning of a cycle of an army battle. It recieves the battle (battle) that is about to undergo its cycle and returns a boolean. If this hook returns true, the rest of the battle cycle proccess will not happen. This will not prevent processing in the AI of any units that are in the battle, or the player from ordering a controllable unit out of the battle. If you wish to do so, you will need to account for and act in response to those interactions. All instances of this hook will run whenever an army battle begins its cycle, even those after one which has returned true.

onArmyBattleCycle_StartOfProcess

void onArmyBattleCycle_StartOfProcess(BattleArmy battle)

This hook fires at the beginning of a cycle of an army battle, but after the interceptArmyBattleCycle hook. It recieves the battle (battle) that is about to undergo its cycle.

onArmyBattleCycle_ComputeAdvantag

double onArmyBattleCycle_ComputeAdvantage(BattleArmy battle, double advantage)

This hook fires when an army battle cycle computes which side has a command advantage. It recieves the army battle (battle), and the calculated advantage (advantage), pre-constraint. It returns the calculated advantage as a double, which is then constrained to a value between 2.0 and -2.0, inclusively.

onArmyBattleCycle_DamageCalculated

int onArmyBattleCycle_DamageCalculated(BattleArmy batle, int dmg, UM unit, UM target)

This hook fires when an army battle cycle calculates the damage that a unit will do to its target on the opposed side of the battle. It recieves the army battle (battle), the damage that will be dealt (dmg), the unit dealing the damage (unit), and the unit that will recieve the damage (target). It returns the damage that will be dealt.

onArmyBattleCycle_AllocateDamage

void onArmyBattleCycle_AllocateDamage(BattleArmy battle, List<UM> units, int[] dmgs)

This hook fires when an army battle has allocated damage to the military units fighting on a side, but before the damage is applied. It recieves the army battle (battle), the list of units (units) that are about to recieve damage, and an integer array of the total damage that the units are about to recieve (dmgs). These values are matched by index.

NOTE: The messages generated in the combat log, and the messages that are sent to the player, have already been genereated at this point. Only use this hook if you must change the total damage value, rather than the individual values, and add make sure to add a new message to the batle log that explains the discrepancy.
You may also wish to compile all of these changes locatlly, and, using the EndOfProcess, termination and Victory hooks, send an additional message to the player explaining the discrepancies.

onArmyBattleCycle_EndOfProcess

void onArmyBattleCycle_EndOfProcess(BattleArmy battle)

This hook fires at the end of a cycle of an ongoing army battle. It recieves the battle (battle) that has just undergone its cycle.

NOTE: If the battle has been won, battle.done will return true, and the onArmyBattleVictory hook will have already fired.

Army Battle (Retreat and Victory)

This second batch of hooks cover units fleeing the battle, and the battle being won or terminated.

onArmyBattleRetreatOrFlee

void onArmyBattleRetreatOrFlee(BattleArmy battle, Unit u)

This hook fires when a unit moves out of an army battle, before they are removed from the battle's data. It recieves the battle (battle), and the unit that fled (u).

onArmyBattleTerminated

void onArmyBattleTerminated(BattleArmy battle, List<UM> victorUnits, List<UA> victorComs, UM u)

This hook fires when a battle is ended as a consequence of the last military unit on one of the sides moving out of the battle, after the unit is removed from the battle's data. It recieves the battle (battle) that has just been terminated, a list of remaining military units (victorUnits), a list of remaining agents commanding the remaining side (victorComs), and the military unit who fled the battle (u).

If neither side has any surviving units, an error has occured, and the lists of surviving victorious units and agents (victorUnits and victorComs) will both be empty.

onArmyBattleVictory

void onArmyBattleVictory(BattleArmy battle, List<UM> victorUnits, List<UA> victorComs, List<UM> defeatedUnits, List<UA> defeatedComs)

This hook fires when an army battle has been won, by one side having zero remaining units. It recieves the battle (battle) that has just been won, a list of surviving military units on the winning side (victorUnits), a list of surviving agents commanding the winning side (victorComs), a list of military units of the defeated side that were alive and in battle at the start of the battle cycle (defeatedUnits), and a list of the agents commanding the defeated side that were alive and in battle at the start of the battle cycle (defeatedComs).

If a battle is won as a consequence of units being killed, or retreating, between cycles, the defeatedUnits and defeatedComs lists will be empty.

If neither side has any surviving units, the lists of surviving victorious units and agents (victorUnits and victorComs) will all be empty, and the list of defeated units and agents (defeatedUnits and defeatedComs) will contain all units and agents that were alive and in battle at the start of the battle cycle.

Army Battle (Misc.)

This batch of hooks covers miscellaneous cases. There is currently only one hook here.

onUnitReceivesArmyBattleDamage

int onUnitReceivesArmyBattleDamage(BattleArmy battle, UM u, int dmg)

This hook fires when a military unit is about to recieve damage in an army battle. It recieves the army battle (battle), the military unit (u), and the total damage it is about to recieve (dmg). It returns the damage the unit is about to recieve as an int.

The damage that the unit is about to recieve is the total of all damage sources being applied to that unit in that battle cycle. This hook does not fire for each individual damage source. If you wish to modify the damage sources individually, use the 'onArmyBattleCycle_DamageCalculated' hook.

Note: The messages generated in the combat log, and the messages that are sent to the player, have already been genereated at this point. Only use this hook if you must change the total damage value, rather than the individual values, and make sure to add a new message to the battle log that explains the discrepancy.

Get Visible Units

The Community Library provides the following hooks for modifying the list of units that a given unit can see.

interceptGetVisibleUnits

bool interceptGetVisibleUnits(UA ua, List<Unit> visibleUnits)

This hook fires when an agent tries to get visible units to test for unit interactions. It recieves the agent (ua), and the list of units that it considers visible (visibleUnits).

If this hook returns true, the base game's getVisibleUnits function will not run.

All instances of this hook will run whenever an AgentAI runs, even those after one which has returned true.

getVisibleUnits_EndOfProcess

List<Unit> getVisibleUnits_EndOfProcess(UA ua, List<Unit> visibleUnits)

This hook fires immediately after an agent has gathered visible units to test for unit interactions. It recieves the agent (ua), and the list of units that it considers visible (visibleUnits). It returns the list of visible units.

Agent Recruitability

The Community Library provides the following hooks that allow you to manage the recruitability of an agent.

onAgentIsRecruitable

bool onAgentIsRecruitable(UA ua, bool result)

This hook fires when the Recruit Agent menu is being populated, once for each agent on the map that is not already commandable. It recieves the agent being considered (ua), and the current determination on if it should be recruitable (result), including the base game's output and all previous instances of this hook, and returns if the should be reqruitable.

If you do not wish to change the recruitability of a given agent, simply return result.

Note: Returning true from this hook will result in a recruitement buttong being made for the agent. The button functions by changing the agent's corrupted boolean to true. If the agent's type's isCommandable() function does not return a result based on this value, clicking the button will not give the player control over the agent, but will still cost a recruitement point.
It is recommended that any agent type you create be given the same isCommandable() function as UAG.
The Community Library replaces the isCommandable() function for all base game agent types of UAEN (Cordyceps' UAEN_Drone, UAEN_DeepOne, UAEN_Ghast, UAEN_OrcUpstart, and UAEN_Vampire), allowing them to be recruited through the use of this hook.

Agent Level Up

The Community Library provides the following hooks that allow you to manipulate how an agent levels up.

onAgentLevelup_GetTraits

void onAgentLevelup_GetTraits(UA ua, List<Trait> availableTraits, bool startingTraits)

This hook fires when an agent gets the valid list of traits that they can choose from when levelling up, but before they have chosen one. It receives the agent (ua), the list of traits (availableTraits) and whether it is getting the starting traits for specific agent types (isStartingTraits)

The function that this hook fires after caches if the agent ua has any possible traits left to get, in the 'ua.person.cachedOutOfTraits' boolean. If adding new traits to the list, make sure to set 'cachedOutOfTraits' to false if your trait is still available. If removing traits, make sure to set 'cachedOutOfTraits' to true if trait other than the one you are removing are not available.

Agent Gains Items

The Community Library provides the following hook to manipulate agents gaining items.

interceptReplaceItem

bool interceptReplaceItem(Person person, Item item, Item newItem, bool obligateHold)

This hook fires when a non-commandable Agent is considering whether to swap an item in their inventory with a new item of higher level. It recieves the person (person) who is about to make the swap, the item (item) that they are about to get rid of, the item (newItem) that they are about to gain, and a boolean that determines if they must take the new item (obligateHold).

If this hook returns true, the person will not swap the item for the new item, and will instead test against the following item slots.

All instances of this hook will run whenever a non-commandable agent, even those after one which has returned true.

Action Taking Monsters

SG_ActionTakingMonsters is the parent class for DeepOne and Orc social groups. It contains code for choosing between national actions in the turnTick(), with the action list being populated in the subclasses.

The Community Library provides the following hooks for interacting with these action lists.

NOTE: Any mod that makes a subclass of SG_ActionTakingMonsters, and makes sure to use the base.turnTick() in its turnTick() function, will automatically be linked to these hooks.

populatingMonsterActions

void populatingMonsterActions(SG_ActionTakingMonster monster, List<MonsterAction> actions)

This hook fires immediately after an action taking monster social group populates it's list of possible actions (of Type MonsterAction). It recieves the action taking monster social group (monster), and the list of monster actions (actions).

populatingMonsterActions

void onActionTakingMonster_getUtility(SG_ActionTakingMonster monster, MonsterAction action, double utility, List<ReasonMsg> reasonMsgs)

This hook fires after an action taking monster social group gets the utility of a monster action. It recieves the action taking monster social group (monster), the monster action (action), the utility score (utility) and the list of reason messages (reasonMsgs), and returns the utility value.

Regional Action

National and Local Actions are actions that can be underttaken by the ruler of a location, or by the ruler of a society. Action Taking Monsters, such as Orc Hordes, have their own kind of National Action called a Monster Action.

The Community Library provides the following hooks for interacting with Regional Actions:

onSoveignAIDecision

void onSovereignAIDecision(Society society, Person sovereign)

This hook fires after a society social group with a sovereign starts a new national action. It recieves the society social group (society) and the sovereign (sovereign).

onActionTakingMonsterAIDecision

void onActionTakingMonsterAIDecision(SG_ActionTakingMonster actionTakingMonster)

This hook fires after an action taking monster social group starts a new monster action. It recieves the action taking monster social group (monster).

Challenges

Challenges are the static actions that an agent can perform at a location. These include things like Infiltrating a location, buying an item, learning an arcane secret, and most other actions that an agent can take. The Community Library offers the following hooks to modify how Challenges are processed.

onGetChallengeProgressComplete

double onGetChallengeProgressPerTurn(Challenge challenge, UA ua, List<ReasonMsg> reasons, double progress)

This hook fires after the Challenge.getProgressPerTurn function is called. It recieves the Challenge (challenge) for which it is being called, the agent that is or will be performing the challenge (ua), the list of reason messages that are displayed to the player (reasons), and the progress that will be made (progress). It returns the progress that will be mae after modification.

Popup Holy Order

The Popup Holy Order is the UI screen for holy orders. The Community Library implements modifications to the base game's handling of this screen in order to allow modification by mods.

Some of these changes are not hooks, but modifications to the way the game handles certain calls to the HolyOrder class. These changes are both detailed here, and in the Popup Holy Order page.

  • The Next and previous buttons will not display religions for which isGone() returns true.
  • The Popoup Holy Order will now check if the HolyOrder subclass has hidden the following inherited functions (using the new keyword), and call those preferentially: computeInfluenceDark, computeInfluenceHuman, and processIncome.

The following hooks allow a mod to recieve data about the religion UI, modify that data, and have it displayed in the appropriate panels of the UI.

onPlayerOpensReligionUI

void onPlayerOpensReligionUI(HolyOrder order)

This hook fires when the relgion UI is openned. It recieves the holy order that the ui has opened to. This hook does not fire when a player switches which religion they are viewing.

onPopupHolyOrder_DisplayPageText

string onPopupHolyOrder_DisplayPageText(HolyOrder order, string s, int pageIndex)

This hook fires when a religion is viewed in the religion screen. It recieves the holy order (order), the string (s) that will be displayed in the large central text box, and the index of the page that is being viewed (pageIndex). It returns the string that will be displayed in the large central text box for that page.

If any other mods have already mdofiied the string prior to yours, those changes will already be present in the argument s.

onPopupHolyOrder_DisplayInfluenceElder

string onPopupHolyOrder_DisplayInfluenceElder(HolyOrder order, string s, int infGain)

This hook fires when a religion is viewed in the religion screen. It recieves the holy order (order), the string (s) that will be dsiplayed, and the amount of influence that was gained by the player that turn (infGain). It returns a string, which is, after all instances of this hook have been run, then diplayed in the HolyOrder screen.

If any other mods have already mdofiied the string prior to yours, those changes will already be present in the argument s.

onPopupHolyOrder_DisplayInfluenceHuman

string onPopupHolyOrder_DisplayInfluenceHuman(HolyOrder order, string s, int infGain)

This hook fires when a religion is viewed in the religion screen. It recieves the holy order (order), the string (s) that will be displayed, and the amount of influence that was gained by the humans that turn (infGain). It returns a string, which is, after all instances of this hook have been run, then diplayed in the HolyOrder screen.

If any other mods have already mdofiied the string prior to yours, those changes will already be present in the argument s.

onPopupHolyOrder_DisplayBudget

void onPopupHolyOrder_DisplayBudget(HolyOrder order, List<ReasonMsg> msgs)

This hook fires when a religion is viewed in the religion screen. It recieves the holy order (order), and the list of reason messages (msgs) that is used to compile the output.

The list of reason message can contain both 'ReasonMsg' and 'CommunityLib.ReasonMsgMax'. If you want to display a singular value, as with 'Income', use a 'reasonMsg'. If you wish to dipslay a value out of a maximum value, as with 'Gold for Acolytes', use a 'CommunityLib.ReasonMsgMax'.

The message is displayed in the left hand panel of the budget screen, and the value and/or max value is displayed in the value column, in the same line as the message.

onPopupHolyOrder_DisplayStats

void onPopupHolyOrder_DisplayStats(HolyOrder order, List<ReasonMsg> msgs)

This hook fires when a relgiion is viewed in the religion screen. It recieves the holy order (order), and the list of reason messages (msgs) that is used to compile the stats displayed in the top left (acolytes, worshippers, etc.).

Tenets

The Community Librray provides the following hook for the HolyTenet System.

onPlayerInfluenceTenet

void onPlayerInfluenceTenet(HolyOrder order, HolyTenet tenet)

This hook fires just after a player influences a HolyTenet from the Holy Order UI. It recieves the holy order (order), and the holy tenet (tenet).

UILeftLocation

UILeftLocation is the UI panel that shows up on the left hand side of the screen, showing the information about the selected location.

The Community Library introduces the following hooks in order to allow modifications to that information:

onLocationViewFaithButton_GetHolyOrder

HolyOrder onLocationViewFaithButton_GetHolyOrder(Location loc)

This hook fires when a settlement without a default relgion source is selected. It recieves the location of the settlement (loc). It returns the holy order that the view holy order button should be linked to.

No hook after the first that does not return null, will be called.

UIScroll_Unit

UIScroll_Unit is the UI panel that shows up on the right hand side of the screen, showing the availables tasks and utility scores, of AI units, or the possible challenges and tasks that a commandable unit can perform.

The Community Library introduces the following hooks in order to allow new challenges and tasks to be assigned to commandable armies (UM). These hooks are dependant on the use of trwo structs, which are defined in the ComminityLib.Hooks class.

onUIScroll_Unit_populateUM

List<TaskData> onUIScroll_Unit_populateUM(UM um)

This hook fires when the UIScroll_Unit interface (the panel on the right that shows challenges and tasks available to the selected unit) attempts to populate tasks for a commandable military unit. It returns a list of TaskData structs, which are then used to create action buttons for the unit.

interceptChallengePopout

bool interceptChallengePopout(UM um, TaskData taskData, ref TaskData_Popout popoutData)

This hook fires when you hover your mouse over an action button in the UIScroll_Unit interface (the panel on the right that shows challenges and tasks available to the selected unit), excluding buttons for challenges, for a commandable military unit. It receives the military unit (um), a partial reconstruction of the TaskData object that could have been used to create it, not the original object. It does not include the onClick delegate, profile gain, or menace gain

If the partially reconstructed TaskData matches a task that your mod adds, populate the popoutData (TaskData_Popout) and return true. Otherwise, return false to allow another mod or the base game to handle the challenge popout screen for that action button.

The title, icon and icon background are pre-set in popoutData when it is passed into the hook, and the progressReasonMsgs are set to an empty list of ReasonMsg

No hook after the first hook to return true will be called.

TaskData

public struct TaskData
{
    public Challenge challenge;
    public Action<World, UM, UIE_Challenge> onClick;
    public string title;
    public Sprite icon;
    public int profileGain;
    public int menaceGain;
    public Color backColor;
    public bool enabled;
    public int special;
    public UA targetUA;
    public UM targetUM;
}

The TaskData struct is used to dynamically create and define an action button for a military unit. It contains variables for all of the data required to create a button.
If assigning a challenge, the button will be built from the data in the challenge class, rendering the other fields unnecessary.

The onClick field takes a delegate with no return type, and inputs matching the types listed in the Action defintion, in the order that they appear. To learn about Action delegates, read the official C# Documentation, or look at the code for my Orcs Plus mod, which contains examples.

TaskData_Popout

public struct TaskData_Popout
{
    public string title;
    public Sprite icon;
    public Sprite iconBackground;
    public string description;
    public string restrictions;
    public int profileGain;
    public int menaceGain;
    public Color backColor;
    public int complexity;
    public int progressPerTurn;
    public List<ReasonMsg> progressReasonMsgs;
}

The TaskData_Popout struct is used to dynamically populate the popout UI panel that appears when you hover your cursor over an action button in the UIScroll_Unit panel.

When passed into the interceptChallengePopout hook, it has already had the title, icon and iconBackground dynamically populated from the corrisponding fields on the action btton. The remaining fields should only be filled out as necessary.

Agent AI

The Community Library's Universal Agent AI does not call the base game's AI hooks. This is to prevent confusion, where a mod that didn't know of the COmmunity Library, modifies the Agent AIs outputs due to the expectation that it is the base game's AI.

Instead, it calls the following hooks:

interceptAgentAI

bool interceptAgentAI(UA ua, AgentAI.AIData aiData, List<AgentAI.ChallengeData> validChallengeData, List<AgentAI.TaskData> validTaskData, List<Unit> visibleUnits)

This hook fires when the Community Library's Agent AI beings processing an agent. It recieves the agent (ua), the AIData for its Agent AI (aiData), a list of AgentAI.ChallengeData structs (validChallengeData), a list of AgentAI.TaskData structs (validTaskData), and a list of Units (visibleUnits).

If this hook returns true, the rest of the AI process will not happen.

All instances of this hook will run whenever an AgentAI runs, even those after one which has returned true.

onAgentAI_StartOfProcess

void onAgentAI_StartOfProcess(UA ua, List<AgentAI.ChallengeData> validChallengeData, AgentAI.ControlParameters controlParams)

This hook fires when the Community Library's Agent AI has started processing an agent, immediately after the 'interceptAgentAI' hook. It recieves the agent (ua), the AIData for its Agent AI (aiData), a list of AgentAI.ChallengeData structs (validChallengeData), a list of AgentAI.TaskData structs (validTaskData), and a list of Units (visibleUnits).

onAgentAI_EndOfProcess

void onAgentAI_EndOfProcess(UA ua, AgentAI.AIData aiData, List<AgentAI.ChallengeData> validChallengeData, List<AgentAI.TaskData> validTaskData, List<Unit> visibleUnits)

This hook fires when the Community Library's Agent AI has finished processing an agent. It recieves the agent (ua), the AIData for its Agent AI (aiData), a list of AgentAI.ChallengeData structs (validChallengeData), a list of AgentAI.TaskData structs (validTaskData), and a list of Units (visibleUnits).

interceptAgentAI_GetChallengeUtility

bool interceptAgentAI_GetChallengeUtility(UA ua, AgentAI.AIData aiData, AgentAI.ChallengeData challengeData, ref double utility, List<ReasonMsg> reasonMsgs)

This hook fires when the Community Library's Agent AI beings processing processing the utility of a challenge for an agent. It recieves the agent (ua), the AIData for its Agent AI (aiData), the AgentAI.ChallengeData (challengeData), the utility (utility), and a list of ReasonMsgs (reasonMsgs).

If this hook returns true, the rest of the getChallengeutility process will not happen.

All instances of this hook will run whenever an AgentAI runs, even those after one which has returned true.

onAgentAI_GetChallengeUtility

double onAgentAI_GetChallengeUtility(UA ua, AgentAI.AIData aiData, AgentAI.ChallengeData challengeData, double utility, List<ReasonMsg> reasonMsgs)

This hook fires when the Community Library's Agent AI has finished processing the utility of a challenge for an agent. It recieves the agent (ua), the AIData for its Agent AI (aiData), the AgentAI.ChallengeData (challengeData), the utility (utility), and a list of ReasonMsgs (reasonMsgs), which may be null.

interceptAgentAI_GetTaskUtility

bool interceptAgentAI_GetTaskUtility(UA ua, AgentAI.AIData aiData, AgentAI.TaskData taskData, ref double utility, List<ReasonMsg> reasonMsgs)

This hook fires when the Community Library's Agent AI beings processing processing the utility of a task for an agent. It recieves the agent (ua), the AIData for its Agent AI (aiData), the AgentAI.TaskData (taskData), the utility (utility), and a list of ReasonMsgs (reasonMsgs).

If this hook returns true, the rest of the getTaskUtility process will not happen.

All instances of this hook will run whenever an AgentAI runs, even those after one which has returned true.

onAgentAI_GetTaskUtility

double onAgentAI_GetChallengeUtility(UA ua, AgentAI.AIData aiData, AgentAI.ChallengeData challengeData, double utility, List<ReasonMsg> reasonMsgs)

This hook fires when the Community Library's Agent AI has finished processing the utility of a challenge for an agent. It recieves the agent (ua), the AIData for its Agent AI (aiData), the AgentAI.ChallengeData (challengeData), the utility (utility), and a list of ReasonMsgs (reasonMsgs), which may be null.

⚠️ **GitHub.com Fallback** ⚠️