# The Mobbening: A how-to guide
## Introduction
We're making all the nasty `/obj/critter` in `/mob/living/critter`. Why? ~~because fuck you thats why~~ because `/obj/critter` tries to replicate a lot of mob-like behaviour, which results in duplicated unmaintainable code, and is just bad OOP practice.
I made some stuff to make it easier, which you can find in [this PR](https://github.com/goonstation/goonstation/pull/10092) and this tutorial will show you how to use it, by example.
There's a few bits to this. Obviously first thing, we need to create a mob. Then we need to add AI to that mob. Then we need to replicate any special behaviour the `/obj/critter` had. Then we need to replace any old references to the `/obj/critter` with the new `/mob/living/critter`
Creating mobs is pretty easy.
Adding the AI is a little more difficult.
Special behaviour can be a pain, but can also be easy.
Replacing is like 99% easy.
## Key Concepts
### The AI system
The new(ish) mobAI system works very differently from the chain-of-if-statements that `/obj/critter` generally uses.
Essentially, at each tick the AI system does the following:
1. Is there a task running?
2. Yep, k, lets keep ticking that task
3. Nope? Okay, evaluate the preconditions of each task (usually stuff like "am I off cooldown?" or "do I have enough energy?")
4. For the tasks that pass the precondition check, evaluate and score possible targets (like, get humans in range, and score them based on how close they are)
5. multiply that score by the task weight (some tasks are more important than others)
6. choose the best scoring task, and start it
## Example - sneks
You can view the code for this example in this PR: https://github.com/goonstation/goonstation/pull/11129
Alright, to start, we find the object definition. In this case, it's in `/code/obj/critter/misc.dm`

Next, find all references to `/obj/critter/snake` (in vscode, that's just right click -> find all references)

This tells us what we're gonna need to modify, and any special behaviour it might have. Unsuprisingly, snakes have the special behaviour of being used for the "Sticks to snakes" spell. We'll get to that.
### Making it a mob
Go to `/code/mob/living/critter/` and create a new file. This one is going to be `snake.dm`. Make sure it says "ticked" in the bottom right corner of vscode.
Now create the path and add some appropriate parameters. We can copy/paste a good amount of this from the `/obj/critter` definition.
We can also use the `/small_animal` class to get some easy stuff out of the way, like health holders.

Congrats, now you have snake mob! You can instantly posess it and walk around as a snake! Isn't class inheritance great?

Let's set some simple properties so we don't accidentally affect balance. We can copy most of these from the `/small_animal` class and modify them to match the `/obj/critter` values

##### UPDATE:
In an effort to standardise mob attacks, we prefer mobs to use limbs. Snakes have a mouth, which is a type of limb, so we have to set `hand_count` to `1` and add a simple `setup_hands()` proc like this:

### Time for AI
Lets make our snake do stuff. First we have to create it a brain.
If you look under `/code/mob/living/critter/ai` you will find th `generic_critter.dm` file, which contains the basic critter behaviour. We'll be using this to add AI to the snake.
In that same folder, I'll create a `snake.dm` file which will contain our AI definition. As it says in the `generic_critter.dm` file, we do that by creating an AI holder for our critter, and subclassing `/datum/aiTask/prioritizer/critter` like so:

We'll add a couple of basic tasks: wander and attack.

And set the `ai_type` in our mob critter and set `is_npc = TRUE`

Hooray, now our snake does stuff! It will chase you, and try to bite you (as snakes frequently do in the wild). Snakes have simple attacks, and so the defaults are enough. Just give it a mouth limb, and it'll try to use it. Some mobs have special attack behaviour, which you will need to implement by adding your own `critter_attack(var/mob/target)` proc, which was specifically added just for this problem! You can see an example of this in `/mob/living/critter/spider`
Often you can just copy and paste some parts of `/obj/critter`'s `CritterAttack()` function - wow! It's almost like that was done on purpose to make this easier! You can see other procs that were added for this in `code/mob/living/critter.dm`
We can test our snake in game, and see that it will attack us properly:

The `/obj/critter/snake` does have some special targetting restrictions, and we can use those here with one of the helper-procs from `code/mob/living/critter.dm`
We can use `seek_target(var/range)` to return a list of valid targets within range that the critter AI will use. We can't quite copy and paste this from the `/obj/critter`, but it's not that different. The main difference is that `/obj/critter/SeekTarget()` returns a single target and sets the task, where `/mob/living/critter/seek_target()` returns a list of potential targets, and the AI task scores them instead.
Also, snakes hiss when they go after a target, so let's include that here as well - with a `prob()`, just to avoid spam.

Hooray!


### Special Behaviour
This particular critter is created by the "Sticks to Snakes" wizard spell, and we need to replicate that behaviour.
Fortunately, most of this is just a copy/paste job, since it basically just sets icon state and name appropriately, and stores the converted object inside the critter to be dropped on death. We'll need to make some modifications to handle the "on death" part. We also need to replace references to `/obj/critter/snake` with `/mob/living/critter/small_animal/snake` in the special behaviour procs, and throughout the rest of the code.
Some tips:
* replace `src.alive` with `!isdead(src)` because `isalive()` returns false when the mob is unconcious.
* `CritterDeath()` can just be replaced with `death()` it does basically the same stuff
* Aggressive vs Peaceful AI: there are a few ways to do this. The way I've been doing it is to create a peaceful AI holder that doesn't have attack tasks, but you could also just have `seek_targets()` return an empty list. It's less efficient, but it works in a pinch.
### Retaliation
You might want your mob to respond when attacked. You can that easily by just setting a few variables.

Setting `ai_retaliates` to `TRUE` will make it respond to being harmed.
Setting `ai_retaliates_patience` will determine how many hits it takes before this mob will attack back. `0` means it will attack immediately upon being harmed.
`ai_retaliates_persistence` determines how aggressively the mob should retaliate. There are three settings:
* `RETALIATE_UNTIL_DEAD` will keep attacking the attacker until the attacker dies.
* `RETALIATE_UNTIL_INCAP` will keep attacking the attacker until they are knocked down or otherwise incapacitated
* `RETALIATE_ONCE` will hit back only once
Note that if a mob retaliates, it will interupt whatever other task it is doing.
### Weird bugs
So when testing this, it didn't work first time - converting things into snakes dropped their brain on the floor, so I replace the contents check with a direct reference instead, which makes more sense anyway.
Also, the sticks to snakes spell allows conversion of snakes into double snakes, but the `/mob` check was first, so I had to move the double snake check up.
## Conclusion
And that's it - we now have a mob snake, so you can suplex snakes when wizards are about! Plus all the usual mob behaviour, including posession. You can play the game as a baton-snake if you want now!
