* Synchronise AI and Player basic mob melee behaviours (#78337) ## About The Pull Request I like for things that mobs do to be consistent regardless of whether they are controlled by a player or by the AI. One big offender of this is the melee behaviour cooldown. Basic mobs piloted by AI have arbitrary melee attack cooldowns which are not reflected when they are controlled by players who can generally attack much faster (but in _two_ instances, slower). To remedy this I added `melee_attack_cooldown` as a var on `living/basic` (sinful) and the ai now uses NextMove to not click too often, meaning that players can only bite things as often as the AI can and also that if you VV the cooldown it can speed the AI up (or slow it down) as well as a player. This also gets rid of a lot of subtypes of that datum, as we mostly made them to change the cooldown. I also hunted down a few places where there was behaviour placed inside an AI behaviour which wasn't easily replicable by a player piloting the same mob, preferably a player should be able to do everything that the AI can. Fixing this was largely a simple case of moving code from `ai_behaviour/melee_attack/perform` to `basic/mob_subtype/melee_attack` and also adding an element for one thing shared by three different mobs. Strictly speaking I didn't need the element that much because a player is perfectly capable of clicking on something they attack to drag it, but it's nice for it to be automatic? ## Why It's Good For The Game If you see a mob do something then you should also be able to do it. Mobs shouldn't have significantly different capabilities when controlled by a player (aside from usually being smarter). ## Changelog 🆑 balance: Player-controlled basic mobs attack as fast as those mobs can when controlled by the AI balance: Player-controlled Faithless can paralyse people they attack, like the AI does balance: Player-controlled Star Gazers (if an admin felt like making one) apply the star mark on attack and deal damage to everything around them, like the AI does /🆑 * Synchronise AI and Player basic mob melee behaviours --------- Co-authored-by: Jacquerel <hnevard@gmail.com>
AI controllers
Introduction
Our AI controller system is an attempt at making it possible to create modularized AI that stores its behavior in datums, while keeping state and decision making in a controller. This allows a more versatile way of creating AI that doesn't rely on OOP as much, and doesn't clutter up the Life() code in Mobs.
AI Controllers
A datum that can be added to any atom in the game. Similarly to components, they might only support a given subtype (e.g. /mob/living), but the idea is that theoretically, you could apply a specific AI controller to a big a group of different types as possible and it would still work.
These datums handle both the normal movement of mobs, but also their decision making, deciding which actions they will take based on the checks you put into their SelectBehaviors proc.
If behaviors are selected, and the AI is in range, it will try to perform them. It runs all the behaviors it currently has in parallel; allowing for it to for example screech at someone while trying to attack them. As long as it has behaviors running, it will not try to generate new plans, making it not waste CPU when it already has an active goal.
They also hold data for any of the actions they might need to use, such as cooldowns, whether or not they're currently fighting, etcetera this is stored in the blackboard, more information on that below.
Blackboard
The blackboard is an associated list keyed with strings and with values of whatever you want. These store information the mob has such as "Am I attacking someone", "Do I have a weapon". By using an associated list like this, no data needs to be stored on the actions themselves, and you could make actions that work on multiple ai controllers if you so pleased by making the key to use a variable.
AI Behavior
AI behaviors are the actions an AI can take. These can range from "Do an emote" to "Attack this target until he is dead". They are singletons and should contain nothing but static data. Any dynamic data should be stored in the blackboard, to allow different controllers to use the same behaviors.
Guides:
Making Your AI: Quickly runs through how to make an ai controller for anything with a step by step development of one.