Utilities - ilikegoodfood/CommunityLib GitHub Wiki
The Community Library also includes a number of small utilities. These are detailed here.
bool checkIsElderTomb(Location location)
The base game assumes that the Elder Tomb is always a settlement of type Set_TombOfGods
, but this may not be the case for all modded Gods.
This function checks if the provided location is a Set_TombOfGods
, and if not, calls the Community Library's onEvent_IsLocationElderTomb
hook, allowing dependent mods to check for and report on the presence of their custom Elder Tombs.
bool checkIsWonder(Location location)
The base game does not group natural wonders (The Entrance, The Isles, and Primal Font) into an intermediate class, meaning that base game features and mods must manually check if a location contains a pre-defined, hard coded list of natural wonders. Continuously updating the code to account for new modded wonders is not viable.
The Community Library offers the following intermediate classes for natural wonders; Set_Wonder
and Sub_Wonder
.
If a modded natural wonder inherits from either of these types, and is in the case of Sub_Wonder
in an instance of Set_MinorOther
, the checkIsNaturalWonder function will automatically count it as a wonder. The Natural Wonder intermediates already inherit from these types and will, by extention, be detected.
The Community Library also allows mods to register classes that inherit from Settlement
or Subsettlement
as Wonder types. These registered types will also be detected by this function. See Collections > Wonder Types for details of registering your own modded wonder types.
No default behaviour has been linked to this function, as there are other mechanisms for mods to control these elements. This serves more as a way more mods to make sure that it is okay to destroy a location, of to check for locations with wonders.
bool checkIsNaturalWonder(Location location)
The base game does not group natural wonders (The Entrance, The Isles, and Primal Font) into an intermediate class, meaning that base game features and mods must manually check if a location contains a pre-defined, hard coded list of natural wonders. Continuously updating the code to account for new modded wonders is not viable.
The Community Library offers the following intermediate classes for natural wonders; Set_NaturalWonder
and Sub_NaturalWonder
.
If a modded natural wonder inherits from either of these types, and is in the case of Sub_NaturalWonder
in an instance of Set_MinorOther
, the checkIsNaturalWonder function will automatically count it as a wonder.
The Community Library also allows mods to register classes that inherit from Settlement
or Subsettlement
as Natural Wonder types. These registered types will also be detected by this function. See Collections > Natural Wonder Types for details of registering your own modded wonder types.
The base game's logic has been changed to make use of this function isntead of the original hard-coded list of three natural wonders, allowing the game to dynamically account for modded wonders.
bool checkIsVampire(Unit unit)
In the base game only units that are of the type UAEN_Vampire
are vampires, but this may not be the case for all mods. This function checks if the provided unit is of the type of UAEN_Vampire
or any type that has been registered by a mod.
NOTE: The Vampire registration system is currently only setup for unit types. This will be expanded if requested.
bool checkHasLocus(Location location)
The base game only has Geomantic Locii (type of Pr_GeomanticLocus
). Other mods have introduced new types of locii, such as the Abyssal Locus from Deep Ones Plus, or the Corrupted Locus from Escamrak.
This function checks the provided location for a property of type Pr_GeomanticLocus
, or any registered locus type.
bool checkKnowsMagic(Person person)
The base game has three different magic typoes, mastery of which is handled as a trait.
This function checks if the provided Person has any trait of any of the base game's three magic mastery types (T_MasteryBlood
, T_MasteryDeath
, and T_MastergyGeomancy
), or of any registered magic type.
bool checkKnownsMagic(Person person, out List<Trait> magicTraits)
This function gathers all traits that are of a base game magic type, or a registered modded magic type. It returns true if the person has any magic traits with level greater than 0. It also outputs all magic mastery traits that the Person has, allowing them to be processed in whatever way you wish.
This can be used to determine is a Person has any magic above a specific level, or below a specific level.
Note: Just after release it because obvious to me that this should just return the magic traits themselves. This wil be
bool checkIsUnitSubsumed(Unit u)
In the base game, a unit is marked as dead both if it is truly dead, and if it needs to not be processed. This can lead to issues such as a holy order believing that thir prophet has died because the agent was marked isDead to prvent processing, as a result of that agent being subsumed into another unit (a Warlord becoming a group of Orcish Raiders).
This function checks if the agent is dead, but their person is alive and associated with a new living unit. If this is the case, it asks all dependant mods if this is a situation where the agent is actually alive but not processing because it has been absorbed into another unit. If any mod claims that this is the case, it return true.
bool checkIsProphetPlayerAligned(HolyOrder order)
In the base game, a prophet is only considered to be player aligned, and therefor only gives elder influence over the holy order, if the prophet is dirctly controlled by the player. This fails to account for prophets from the Dark Empire, Ophanim's Theocracies, or for other modded entities that are player aligned.
The Community Library introduced a hook (OnCheckIsProphetPlayerAligned) that allows mods to specify if a particular prophet should be considered player aligned. It also offers a mod option (Dark Prophets) that tells the game to count prophets from The Dark Empire (if enshadowed) or one of Ophanim's Theocracies as player aligned.
The base game's logic has been modified to make use of this function.
The Community Librray includes a small but growing number of custom console commands (cheat codes) to make testing your mods faster and easier.
The gold [number]
console comand increases or decreases the gold of the selected agent, or the selected settlement's ruler, by the specified amount. This change will not reduce their gold below 0.
The influenceElder [number]
console comand can be used on any location with a holy order or any agent or unit belonging to a holy order.
When used without supplying a number, it sets the elder influence over that holy order to the maximum.
When used with a number, it increases, or decreases, the elder influence over that holy order by the number specified. This change will not go below 0 or above the maximum.
The influenceHuman [number]
console comand can be used on any location with a holy order or any agent or unit belonging to a holy order.
When used without supplying a number, it sets the human influence over that holy order to maximum.
When used with a number, it increases, or decreases, the human influence over that holy order by the number specified. This change will not go below 0 or above the maximum.
The testItem [name]
console command is a limited command designed for testing and devlopement. The [name]
can be replaced with one of two options:
blank
The blank
name will give the selected unit's person, if the unit has one, or the selected settlement's ruler, if it has one, a "Blank Test Item", which does nothing. It's foreground sprite is the standardBack
sprite. It can be used to optain a screenshot of the background sprite.
noDeath
The noDeath
name will give the selected unit's person, if the unit has one, or the selected settlement's ruler, if it has one, a "Potion of Perfect Healing". If a person holding this item dies, they will be saved from death.
The shipwreck
console comand will spawn a shipwreck at the selected location, if the location is ocean or coastal. If a shipwreck already exists at that location, it will increase the wreck's integrity instead.
As part of the AgentAI system, the Community Library has a store for random numbers. These numbers are stored by a UA, ChallengeData and string.
Dictionary<Unit, Dictionary<object, Dictionary<string, double>>> randStore;
It is accessed using a setRand
and tryGetRand
function in the Community Library's ModKernel. If you wish to have a random element to the profile, utility, or validity of an challenge, task or any other value associtaed with a unit, as is used by the UAEN_Vampire
AI, you can store the random variable created in the randStore. This prevents the variable from changing each time the agent is clicked on.
You will need a means of determining whether the function is being called for display purposes, or if it should be updated. The Community Library's Agent AI uses an aiRunning
variable for this purpose. You will need your own if it is being used in a different context.
Values in the randStore are persistant across saves.
Here is an example of it's use, from the utility tag logic included for ChallengeTags.PreferLocalRandom
:
case ChallengeTags.PreferLocalRandomized:
dist = ua.map.getStepDist(ua.location, challengeData.location);
dist -= ModCore.core.tryGetRand(ua, challengeData, "localRand", 1 + Eleven.random.Next(2) + Eleven.random.Next(2));
if (ModCore.core.GetAgentAI().isAIRunning())
{
ModCore.core.setRand(ua, challengeData, "localRand", 1 + Eleven.random.Next(2) + Eleven.random.Next(2));
}
val = dist * -10;
reasonMsgs?.Add(new ReasonMsg("Distance", val));
result += val;
break;
Here you can see that the vampire tries to get the random variable for that AIChallenge, which has been assigned the key "localRand", and offers a new value if one is not already defined. Once it has gathered the value, or assigned it if it was unpopulated, it then checks if the AgentAI is currently processing that challenge, and changes the random value for the next time the value will be looked up.
This ensures that the Utility breakdown in the challenge panel on the right hand side of the screen will always show the correct utility value for the next time the vampire chooses which challenge to perform.
The tasks presented in this section are not unique to the Community Library, and need not make use of any features unique to the Community Library. They are here simply so that any mod which is already dependant upon the Community Library, for its other features, don't have to waste time re-implementing a commonly needed task.
Task_AttackUnitWithCustomEscort(Unit self, Unit c, UM escort)
This task exactly mimics the behaviour of the base game's Task_AttackUnitWithEscort
. It allows an agent to chase down and attack another agent while escorted by a military unit. To function correctly, the escort must be present at the same location as the agent when it is given this task.
The base game does not automatically check what Minion type should be created when an agent reinforces from an escort, defaulting to a Knight (M_Knight
). To control this behaviour, your mod will need to use the onAgentBattle_ReinforceFromEscort
hook provided in the COmmunity Library.
Task_GoToPerformChallengeAtLocation(Challenge c, Location loc, bool safeMove = false)
Task_GoToPerformChallengeAtLocation(Challenge c, Location loc, Func<Location[], Location, Unit, bool> pathfindingDelegate)
This task combines the functionality of the Task_GoToLocation
and Task_GoToPerformChallenge
tasks from the base game. This alloows it to both direct an Agent to a location to perform a Ritual at that location, and to consider SafeMove requirements.
It will also cancel moving towards a challenge if it becomes inaccessible or unavailable for any reason.
If provided a pathfinding delegate, it will use the Community Librray's pathfinding solution with that delegate, otherwise it will use the base game's pathfinding solution.
Task_GoToWilderness(Location targetLocation, bool safeMove = false)
Task_GoToWilderness(bool goToLandOnly = false, int mapLayer = -1, bool safeMove = false)
Task_GoToWilderness(bool goToLandOnly = false, int[] mapLayers = null, bool safeMove = false)
This task can be used to navigate to a location that is Wilderness (owned by no social group).
If goToLand
is true
, it will navigate to the nearest land wilderness, ignoring oceans that may be closer.
If the DLC is enabled, the latter two constructors can be used to restrict the map layers that the task will navigate to.