Mods / Expanded Ai Tasks Code Library and Loader (AI API For Modders Only, Not a Mod)
Author: Grifthegnome
Side: Both
Created: Mar 28th 2022 at 12:30 AM
Last modified: Mar 27th at 1:18 AM
Downloads: 2853
Follow Unfollow 24
Latest file for v1.19.5:
expandedaitasks_1.1.1.zip
1-click install
If you find a bug, have a suggestion, have questions, or want to talk, feel free to join my Discord Server!
IMPORTANT NOTE: Please note that this mod is for modders to develop custom Ai, not to improve AI in the game generally. If you are not a modder, I would not download this as it doesn't do anything on its own. This mod is not a dependency for Outlaw Mod, as it is included natively in Outlaw Mod. Running mismatched versions of Outlaw Mod and ExpandedAiTasks Loader will make one or both mods fail to load.
This is a mod that makes the custom Ai Tasks used by Outlaw Mod available to the community.
This mod pack contains both the ExpandedAiTasks.dll and the ExpandedAiTasksLoader Mod.
If you are intrested in using this .dll for your mod, please read the include readme for implementation and compatibility details.
ExpandedAiTasks.dll
This contains all the currently available aiTasks written for Outlaw Mod. I use this in Outlaw Mod to make archer enemies that can lead their targets and engage the player at ranges greater than any current Ai in the vanilla game. As I add and test new aiTasks in Outlaw Mod, I will release them here so that anyone can use them.
At the moment, this libary contains the following behavior functionality:
Shoot Projectile
- Create AI that can shoot any any projectile in the game at a target, with support for leading targets, arcing shots properly over distance, accuracy fall off from range, time to zero new target, damage falloff over range, friendly fire prevention, Last Known Position Targeting, and much, much more.
Pursue, Engage, and Withdraw
- Create Ai that can pursue and engage targets. They will chase opponents at one speed, but then slow down to actually fight them. When they don't have a path to target, they will withdraw to a safe distance and wait for the opportunity to attack.
- You will find their responsiveness to hostiles is way more responsive than the base game and they can also switch targets rapidly mid-combat when they take damage.
- You can also have your AI make decisions as a pack and only attack targets they think they can overpower as a group. This allows you to make Ai that are only agressive when they have a numerical advantage.
- You can make the Ai persue their target's last known position so they advance on where the player was last seen, not where the player is currently.
Stay Near Herd/Squad
- You can make the your Ai travel the world in groups or evenn attempt to maintain group cohesion during combat.
- This system appoints a squad leader that acts as the anchor for a group of Ai.
- Members of the group will always return to the squad leader if they wander too far. Even if they get seperated by hundreds of blocks.
- When the squad leader is killed a new one is appointed from the surviving group members.
- When two underpowered squads with compatible members meet, they will merge into one squad to become a more effective fighting force.
Morale System
- You can make Ai that considers both group and individual morale when deciding when to run from a fight. This gives you a powerful interface for player vs Ai and Ai vs Ai encounters.
- The Ai will know whether their group is winning or losing the current fight.
- They consider things like group health, friendly and enemy losses, whether they are outnumbered or have a numerical advantage, and whether there are items or objects that frighten them present on the battlefield.
- This allows you to easily implement features such as making animals afriad of torches.
- You can make hero character who inspires their squad members in battle, making them less likely to run.
- You could make a vampire enemy who is afraid of garlic and crosses.
- You could also make an Ai that is more confident in battle when the player is holding a carrot in their hands, for some reason. The power is yours!
Guard Target
- Create Ai that guard another creature.
- This guard task handles attacks from other AI and players as well as players getting too close to the guard target.
- Because this task delegates its resolution to the Pursue, Engage, and Withdraw, Enhanced Melee, and Shoot Projectile tasks, you have a lot of power over how your Ai responds to a threat on its guard target.
Eat Dead Creatures
- You can make Ai that is attracted to dead creatures in the environment and then eats or harvests them down to a skeleton.
- You can make it so that the longer the creature has been dead, the farther the Ai can smell it from.
- You can even make horrible monsters that will eat their own dead squad members.
Enhanced Melee
- Enhanced Melee is currenly similar to the base-melee attack ai task, but it does have some useful features.
- It prevents creatures from attacking their squad members if they happen to take friendly-fire damage.
React To Projectiles
- Allows Ai to tell when they are getting shot at by projectiles (even if the projectile misses) and respond accordingly. It uses a special tracking algorithm that only monitors projectiles that are actively in-flight, which makes it less expensive than one might expect.
Full Stealth & Awareness System (Factored into all AiTasks in this package)
- The Ai take lighting conditions, including sunlight, blocklight, and dynamic light from held or dropped items that emit light when determining whether they can see a target. This is managed by an illumination manager that is written to minimize calculation overhead.
- The Ai have a properly occluded vision cone, they cannot see through leaves, plants, or water.
- The Ai has the ability to hear players based on their mode of movement.
- You can give Ai Nightvision so they can see in the dark.
- The Ai can only share information with squad members within their alert range, allowing for takedowns without alerting the group.
- Note: Sneak Attack Bonus Damage is an Outlaw Mod feature and not included in this AI package. If folks are intrested in how that was implemented, feel free to ask and I can explain my implementation.
LODRepulseAgents Entity Behavior (For Performance)
- This is a modified verson of "repulseagents" which can be added by replacing the "repulseagents" behavior in an Ai's json with "lodrepulseagents."
- This is the same behavior, but with LOD (Level of Detail) logic. Essentially, it runs less, or not at all, when players are not nearby.
- This makes EntityAgents interacting away from players much cheaper.
- LOD Repulse Agents does not run on entities that are dead.
- As players get closer to an entity running LODRepulseAgents the simulation increases in tick rate and fidelity until it matches "repulseagents" at close range.
- I recommend using this on any Ai that is running ExpandedAiTasks.
ExpandedAiTasksLoader Mod
- This is a simple mod, configured for people who aren't big on coding, that registers and loads the aiTasks so that you can use them in your ai files.
- Note that if you rely on this mod to load the aiTasks for you, players who play your mod will also need the loader mod.
If you have any questions about what this mod is, what it does, or how to get it working with your mod. Drop a comment here and I'll help as best I can.
If you want to see these ai tasks in action check out Outlaw Mod here: https://mods.vintagestory.at/brigandsandfootpads
If you want to see the source code look here: https://github.com/Grifthegnome/OutlawMod/tree/master/mods-dll/expandedaitasks
this is possibly a stupid question coming from somone with limited programming experience in general, but about the "Gaurd Target" features...
Is it possible to set the player as a target to defend?
Phoenicius
Good to know! Thanks for tracking that down.
Grifthegnome
You can easy; I've determined that these errors are caused by Rust and Rot. It's got nothing to do with Outlaws or Expanded AI tasks.
I noticed another user make the same post about this on the Rust and Rot mod page. So I tried playing without RnR, and the error diseappeard. To double check, I made a new world with only RnR, and the errors appeared again.
Phoenicius
Thanks for reporting this. Will take a look.
I'm getting these errors in my console using Outlaws version 1.2.3:
[Server Error] Exception: Object reference not set to an instance of an object.
at Vintagestory.API.Common.Entities.Entity.AfterInitialized_Patch1(Entity this, Boolean onFirstSpawn)
at Vintagestory.Server.ServerMain.SpawnEntity(Entity entity, EntityProperties type) in VintagestoryLib\Server\ServerMain.cs:line 2303
at Vintagestory.Server.ServerSystemEntitySimulation.UpdateEvery100ms(Single t1) in VintagestoryLib\Server\Systems\World\EntitySimulation.cs:line 202
It looks like a similar issue that someone else had previously? I'm not sure how to go about resolving it. Any suggestions?
If it helps, some of the mods we're using are Entities Interact and Entities Configuration. Idk if those have compatibility issues maybe?
1.1.0 is now live!
This is a code compatibility update for Vintage Story 1.19.4.
1.0.9 is now live!
Featuring bug fixes and a new AI Task.
TimSithis
Hi, thanks for reporting this! This is related to hitting an assert in the Entity Ledger system. It is already fixed in my local changes, and will be fixed in the next release. It occurs when an entity in a saved chunk is loaded and shares the same entity ID as an enitity already loaded in memory. Vintage Story remaps entity IDs at runtime when an entity with a duplicate ID is loaded from a world chunk. I was not aware of this when I first implemented the system, and I assumed all Entity IDs would be unique at all times. The crash is a safety assert that I added that triggers to catch when the same EntityID is added to the Entity Ledger twice, as no duplicate IDs should ever be added. The next version of expandedAITasks now accounts for Vintage Story's native entity ID remapping and fixes this crash.
24.1.2024 15:21:31 [Warning] Exception at client 1. Disconnecting client. 24.1.2024 15:21:31 [Notification] Last player disconnected, compacting large object heap... 24.1.2024 15:21:33 [Event] Player TimSithis got removed. Reason: Threw an exception at the server 24.1.2024 15:21:33 [Error] Exception: Object reference not set to an instance of an object. at ExpandedAiTasks.Managers.EntityLedger.AddEntityItemToLedger(Entity entity) at ExpandedAiTasks.AfterInitializedOverride.OverrideAfterInitialized(Entity __instance, Boolean onFirstSpawn) at Vintagestory.API.Common.Entities.Entity.AfterInitialized_Patch1(Entity this, Boolean onFirstSpawn) at Vintagestory.Server.ServerMain.SpawnEntity(Entity entity, EntityProperties type) in VintagestoryLib\Server\ServerMain.cs:line 2330 at Vintagestory.Server.ServerMain.SpawnEntity(Entity entity) in VintagestoryLib\Server\ServerMain.cs:line 2274 at Vintagestory.Server.ServerMain.SpawnItemEntity(ItemStack itemstack, Vec3d position, Vec3d velocity) in VintagestoryLib\Server\ServerMain.cs:line 2229 at Vintagestory.GameContent.BlockEntityBasketTrap.Interact(IPlayer player, BlockSelection blockSel) in VSSurvivalMod\BlockEntity\BEBasketTrap.cs:line 120 at Vintagestory.GameContent.BlockBasketTrap.OnBlockInteractStart(IWorldAccessor world, IPlayer byPlayer, BlockSelection blockSel) in VSSurvivalMod\Block\BlockBasketTrap.cs:line 47 at Vintagestory.Server.ServerSystemBlockSimulation.HandleBlockInteract(Packet_Client packet, ConnectedClient client) in VintagestoryLib\Server\Systems\World\BlockSimulation.cs:line 474 at Vintagestory.Server.ServerSystemInventory.HandleHandInteraction(Packet_Client packet, ConnectedClient client) in VintagestoryLib\Server\Systems\Inventory.cs:line 257 at Vintagestory.Server.ServerMain.ProcessNetMessage(NetIncomingMessage msg, NetServer mainSocket) in VintagestoryLib\Server\ServerMainNetworking.cs:line 138 24.1.2024 15:21:33 [Warning] Server overloaded. A tick took 1272ms to complete. 24.1.2024 15:21:33 [Notification] All clients disconnected, pausing game calendar.
Seems Like I get some Bugs..You think you know what's causing them?
Update 1.0.8 is now live!
This is the first version supporting Vintage Story 1.19x.
Update 1.0.7 is now live!
Please see change list for details.
Update 1.0.6 is now live!
Please see change list for details.
SeveredSkullz
Great question! You are absolutely correct that this teleport logic does not account for entities in unloaded chunks. At some point, I may add functionality for cross-world teleportation, but this teleport functionality is a simple extension of the existing Vintage Story AI teleport logic, which specifically intended to allow herd members who have been seperated from their herd locally during combat to return if they cannot find a path back. My only addition is making sure it doesn't happen while players are looking, nearby, or anyone is fighting the teleport target.
The herd system in Expanded Ai Tasks is currently non-persistent and dynamic, so survivors of a destroyed or greatly reduced herd will dynamically merge with other larger herds they encounter. Effectively, Expanded AI Tasks is piggybacking off of the Vintage Story HerdID system to layer a dynamic squad system on top of the existing system. It currently doesn't account for unloaded chunks because Ai infrequently end up hundreds of blocks away from their squad at runtime, and if they do, the straggler is likely a gonner or joins another herd.
I might add support for unloaded chunks in the future, but I would need to look into doing so efficiently, as starting to look through the parts of the world that aren't loaded has the potential to scale in performance cost as the world gets bigger, if I take the wrong approach. I also would need to look and see what data is available about unloaded entities, if they are unloaded I would imagine they aren't actively in memory and I would need to query them by their EntityId and do some special stuff to read them. The toughest one though is teleporting an entity of an unknown size to an arbitaray location, which is always a headache, because if the Ai doesn't fit in the teleport location (Maybe they are a bigger collision hull than the ally they are teleporting to) you quickly get into gnarly checks looking for an adjacent location to put them, which would require reading or loading the chunk in some fashion. I would love to take a crack at it at some point, but it might take me a bit to get sorted.
As for squad persistance, I'll likely add it if I start implementing AiTasks that require groups of Ai to perform organized overland travel. The current implementation makes a bunch of localized, combat-centric assumptions, and isn't robust enough to keep a herd together at all costs. Hopefully this helps add context.
Looking over the code, this looks to be very useful. One quick question though: How does the Herd logic account for unloaded chunks? I dont see any code/logic that accounts for entities being unloaded in a chunk, nor is there any persistence to these entity ids in the list. From what I can tell after looking at the code is that the teleport to herd logic would not work since we go and get the nearest entity contained in the herd ID, which wont exist since they are in an unloaded chunk. Teleport would then fail because they arent found, and then we wind up with an isolated member of the heard that now thinks they are the last one left. Am I missing something here, or is this just an edge case that isnt handled?
Hotfix 1.0.5 is now live!
Please see change list for details.
At some point I do plan to make Ai that can knock in doors. It may take some time to get that up and running, but it is doable. I want to get to a place where Outlaws can actually besiege player structures, on a Mod Config toggle of course :P.
If I could ask for one thing... Could you possibly make AI that prioritizes knocking down doors, specifically? Or breaking dirt/other possibly configurable blocks? Would that be possible? I want to make drifters... Actually scary and a real threat. I want bears that break into your house when they smell a meal on the fire... And wolves that seek you out in packs when they go hunting at night... Perhaps a warning system that sends a chat message, or better yet a fullscreen notification, stating "Something has spotted you from afar..." That could send shivers down your spine... Or even different AI depending on the moon phases... So many possibilities.
I'm excited to see what you come up with! My goal is to make this stuff publically available so that people can make whatever they want with it. I don't want to keep this stuff bound to Outlaw Mod when I know folks could be making cool stuff with it. Speaking of which, gonna add a link to the GitHub in the mod description in case people want to read source code.
Thanks for the detailed explaination on things! This library alone, if utilized correctly, can really make VS into a hardcore nightmare... You realize that, right? I'm already working on patching this AI into the game's land animals... Tehe 🙃 This should be fun. 😁
BraniyaKz
To answer your question about a list: Items Stacks, Blocks Stacks, EntityAgents, or POIs (Points of Intrest) that are registered through the Poi system in code are currently the supported sources of fear.
Some Details:
You can provide lists of sources of fear in an Ai's AiTaskMorale entry with the amount it affects the Ai's morale. Positive values hurt morale while negative values will bolster morale (Looking back on it, it's weird that it's not the other way around, but here we are :P ).
Below is an example of the sources of fear for a yeoman-archer in outlaw mod.
Grifthegnome - Looking at the AItasks in the outlaw mod, I can see that there are possible entity sources of fear, as well as itemstack and poi (block?) sources of fear, but are there any others? Can we possibly get a list?
Now this gives me ideas on a mod I want to make. Thank you for this!
Expanded Ai Tasks 1.0.4 is now live.
It contains fixes for 1.18 and a new behavior React to Projectiles.
Grifthegnome I would love to utilize this! I would be so grateful for an update to 1.18.2+. This is exactly some of the things I've been looking for.
Grifthegnome Please update for game version 1.18.2 and later. We made a breaking change in AiTaskBaseTargetable which has broken your mod because you have classes extending that. targetEntityCodesExact is now a string[] not a List<string> Simply re-compiling against the current game API (and in your case you'll need the source code for VSEssentials) might fix this already
Pls add quests system (it can be very simple, like walk&do&gimme loot).
Expanded Ai Tasks 1.0.2 is now live.
It contains a bug fix for a crash in the morale system caused by invalid item stacks.
A new verion of Expanded Ai Tasks Code Library and Loader is now available!
This version includes all the new Custom Ai Tasks added for the 1.1.1 version of outlaw mod.
The next version of ExpandedAITasks will be released along side Outlaw Mod 1.1.1. This will include several new Ai Tasks Including: PursueAndEngageEntity, EatDeadEntities, and StayCloseToHerd.
As a quick note: I realized that the README file for 1.0.0 of Expanded Ai Tasks is the Outlaw Mod Readme and Not the ExpandedAiTasks Readme, Sorry!
This is the intended readme for anyone intrested, the read me will be corrected in the next version of the mod:
Hi! Welcome to the Expanded Ai Tasks Loader Mod Readme and thanks for downloading.
This mod acts as a shared loader for the ExpandedAiTasks.dll that accompanies it.
The .dll adds aiTasks that I use to develop my mods that the base game doesn't support natively.
Getting Started:
========================================================================================================================
FOR PLAYERS:
1. Just put the zip file in your mods folder, like any other mod.
2. You're good to go!
========================================================================================================================
FOR MODDERS:
If you're planning on integrating tasks from ExpandedAiTasks.dll into your mod there are two ways of doing it:
1. Using this Loader Mod.
2. Doing your own .dll integration.
There are pros and cons to both approaches:
The Loader Mod Method:
In this method, you let this mod do the heavy lifting for you. You simply reference the AiTasks it registers.
Pros:
1. If you use this loader mod, you don't have to write any code, your mod can just reference the AiTasks in your .json files and it will work.
2. You don't have to worry about compatibility with any other mod that also uses the loader mod, since all the AiTasks are registered in the same place.
Cons:
1. Your mod won't work properly if players don't have the ExpandedAiTasksLoader mod installed. You'll have to point people to this mod and tell them to download it so
they will have the AiTasks registered when you reference them. (i.e. Your mod won't be a standalone mod).
Doing your own .dll integration:
In this method, You include the ExpandedAiTasks.dll in your project and register it's AiTasks in your Core ModSystem.
Pros:
1. You have total control over what is and is not registered from the .dll.
2. Your mod is totally self-contained and people won't need to download the loader for your mod to work.
Cons:
1. You are entirely responsible for compatibility between your mod and other mods that use these AiTasks.
That is to say, if two different mods register the same AiTask, they will crash the engine. So you have to make sure you don't double register.
========================================================================================================================
Integrating ExpandedAiTasks.dll into your mod
1. Add ExpandedAiTasks.dll as a reference to your project.
2. In your Core ModSystem .cs file include 'using ExpandedAiTasks;'
3. In your Core ModSystem class, on server and client start up:
a. Register the AiTasks you want to use.
b. Be sure to enclose each AiTask registration in a statement that checks whether or not this task has already been registered by another system.
c. Be sure to register your AiTask under the same key as is used by the loader mod. That way if the player has the loader mod present in their folder,
your mod will defer to its registration while still maintaining a self-contained and independent registration of the tasks.
Example:
if (!AiTaskRegistry.TaskTypes.ContainsKey("shootatentity") )
AiTaskRegistry.Register("shootatentity", typeof(AiTaskShootProjectileAtEntity));
4. At this point, you should now be able to reference this AiTask in your .json files.
5. When packaging your mod, do not forget to include ExpandedAiTasks.dll in your zip file (Not to be confused with ExpandedAiTasksLoader.dll)
========================================================================================================================
AI Tasks Documentation:
AiTaskShootProjectileAtEntity ( registered as "shootatentity"" )
This AiTask tells an Ai to shoot a specified projectile at a target with the specified settings.
json Settings
int durationMs: The duration of the ranged attack in milliseconds.
int releaseAtMs: The time at which the projectile is fired in milliseconds.
float minDist: The minimum distance at which the attack can occur (measured in blocks).
float maxDist: The maximum distance at which the attack can occur (measured in blocks).
float minRangeDistOffTarget: The projectile's maximum distance off target at minimum range (measured in blocks).
float maxRangeDistOffTarget: The projectile's maximum distance off target at maximum range (measured in blocks).
float maxVelocity: The absolute maximum velocity of the projectile.
float newTargetDistOffTarget: The projectile's maximum distance off target when the shooter has just acquired a new target (measured in blocks).
float newTargetZeroingTime: The time (in seconds) over which a shooter zeros his aim and newTargetDistOffTarget lerps to a value of 0.0.
float damage: How much damage the attack deals when the projectile hits its target.
float damageFalloffPercent: The percent of the damage value that is retained at damageFalloffEndDist.
float damageFalloffStartDist: The distance at which damage begins to falloff (measured in blocks).
float damageFalloffEndDist: The distance at which damage is fully reduced by damageFalloffPercent and will not falloff further (measured in blocks).
string projectileItem: The code of the projectile that this attack will fire.
bool projectileRemainsInWorld: Determines whether or not the projectile will remain in the world after impacting a surface.
float projectileBreakOnImpactChance: The percentage chance that a projectile will break when impacting a surface is projectileRemainInWorld is true.
Use Example from OutlawMod, yeoman-archer.json
{
code: "shootatentity",
entityCodes: ["player", "drifter-*", "wolf-male", "wolf-female", "hyena-male", "hyena-female", "locust-*", "bear-*", "looter"],
priority: 3.75,
priorityForCancel: 9,
mincooldown: 1000,
maxcooldown: 1500,
maxDist: 32,
minRangeDistOffTarget: 0.25,
maxRangeDistOffTarget: 0.75,
maxVelocity: 1.25,
newTargetDistOffTarget: 0.75,
newTargetZeroingTime: 5.0,
damage: 3.0,
damageFalloffPercent: 0.66,
damageFalloffStartDist: 18,
damageFalloffEndDist: 28,
projectileItem: "arrow-copper",
projectileRemainsInWorld: true,
projectileBreakOnImpactChance: 0.90,
durationMs: 2000,
releaseAtMs: 1000,
seekingRange: 15,
animationSpeed: 1.0,
animation: "bowattack"
},