# Job and Outfit code guidelines
This is not a guide for balance but a guide to uphold code quality.
Currently the majority of jobs rely on outfits to add traits, stats, skills and so on. This goes against what an outfit is supposed to be, which is a datum for holding the clothes for a job.
Going forward outfits will only dictate visuals, and jobs will dictate stats, spells and so on.
## Jobs
Jobs have contained the majority of code required for this for a long time, but only now is it fully setup for ease of use.
Most importantly
jobstats - Associative list of STATKEY to value.
skills - Associate list of skill to value OR skill to list(value, max) for a clamped skill.
traits - List of traits to add.
You can also see there is a section for languages and combat mode music, these were common enough to warrant variables but other things should use...
job/after_spawn():
* For adding extra things to the mob such as honorary titles or item renaming.
* For changing skills/stats based on conditional values, this should be done through the regular adjust skill procs and `adjust_stat_modifier(STATMOD_JOB, stat_key, value)`.
* Do NOT modify values on the job, as jobs are singletons you will change the job for everyone that spawned with it after. (I h this mistake)
job/pre_outfit_equip():
* As it implies, for before the outfit is applied when applying the job.
* If you need to change something before equipping the outfit, such as patron, this is where you do it.
Example job:
```
/datum/job/migrant/inquisition_crusader
title = "Episcopal Crusader"
tutorial = "Crusader of the true faith, you came from Grenzelhoft under the command of the Inquisitor. Obey them as they lead you to smite the heathens."
allowed_races = RACES_PLAYER_GRENZ
is_recognized = TRUE
outfit = /datum/outfit/inquisition_crusader
jobstats = list(
STATKEY_END = 2,
STATKEY_CON = 2,
STATKEY_STR = 1,
)
skills = list(
/datum/skill/combat/crossbows = 2,
/datum/skill/combat/wrestling = 3,
/datum/skill/combat/unarmed = 3,
/datum/skill/combat/swords = 2,
/datum/skill/combat/knives = 2,
/datum/skill/combat/shields = 2,
/datum/skill/misc/swimming = 1,
/datum/skill/misc/climbing = 2,
/datum/skill/misc/riding = 4,
/datum/skill/misc/athletics = 3,
/datum/skill/misc/reading = 2,
/datum/skill/misc/sewing = 1,
/datum/skill/craft/cooking = 1,
)
traits = list(
TRAIT_STEELHEARTED,
TRAIT_HEAVYARMOR,
)
languages = list(/datum/language/oldpsydonic)
cmode_music = 'sound/music/cmode/church/CombatInquisitor.ogg'
voicepack_m = /datum/voicepack/male/knight
/datum/job/migrant/inquisition_crusader/after_spawn(mob/living/carbon/human/spawned, client/player_client)
. = ..()
if(spawned.gender == FEMALE)
spawned.adjust_skillrank(/datum/skill/combat/crossbows, 2)
spawned.adjust_skillrank(/datum/skill/combat/knives, 2)
else
spawned.adjust_skillrank(/datum/skill/combat/swords, 2)
spawned.adjust_skillrank(/datum/skill/combat/shields, 1)
spawned.set_patron(/datum/patron/psydon)
var/datum/species/species = spawned.dna?.species
if(!species)
return
species.native_language = "Old Psydonic"
species.accent_language = species.get_accent(species.native_language)
```
## Outfits
Outfits have always been a hack solution to changing stats, if you change stats/skills/etc. in an outfit you will be asked to move it to the job.
All outfits should have a name, preferably matching or related to its "parent" job.
Additionally `pre_equip()` has been abused, it should only be used if an outfit needs to be changed conditionally otherwise the variables should go straight on the subtype.
Example Outfit:
```
/datum/outfit/inquisition_crusader
name = "Episcopal Crusader"
head = /obj/item/clothing/head/helmet/heavy/crusader
neck = /obj/item/clothing/neck/coif/cloth
armor = /obj/item/clothing/armor/chainmail/hauberk
cloak = /obj/item/clothing/cloak/cape/crusader
gloves = /obj/item/clothing/gloves/chain
shirt = /obj/item/clothing/shirt/tunic/colored/random
pants = /obj/item/clothing/pants/chainlegs
shoes = /obj/item/clothing/shoes/boots/armor/light
backr = /obj/item/weapon/shield/tower/metal
belt = /obj/item/storage/belt/leather/plaquesilver
beltl = /obj/item/weapon/sword/silver
wrists = /obj/item/clothing/neck/psycross/silver
cloak = /obj/item/clothing/cloak/stabard/crusader
backpack_contents = list(/obj/item/storage/belt/pouch/coins/rich = 1)
/datum/outfit/inquisition_crusader/pre_equip(mob/living/carbon/human/equipped_human, visuals_only)
. = ..()
if(equipped_human.gender == FEMALE)
head = /obj/item/clothing/head/helmet/heavy/crusader/t
cloak = /obj/item/clothing/cloak/stabard/crusader/t
backl = /obj/item/storage/backpack/satchel/black
backr = /obj/item/gun/ballistic/revolver/grenadelauncher/crossbow
beltl = /obj/item/weapon/knife/dagger/silver
beltr = /obj/item/ammo_holder/quiver/bolts
```
## Additional Notes
#### Selectable Items
Its quite common for jobs to have random weapons, but if you want to have a random weapon AND adjust the stats for that weapon you must make a sacrifice. Either making the weapon selectable from the JOB in `after_spawn()` or making the stats and weapon static.
Below is the old method for selectable items.
One method for selectable items is to use `select_equippable()` proc with a (usually) static list of selections to typepath.
Checking "choice" allows for specific stat/skill mods.
```
var/static/list/selectable = list(
"Flail" = /obj/item/weapon/flail/sflail,
...
)
var/choice = human.select_equippable(human, selectable, message = "Choose Your Specialisation", title = "KNIGHT")
if(!choice)
return
switch(choice)
if("Flail")
human.clamped_adjust_skillrank(/datum/skill/combat/whipsflails, 2, 4, TRUE)
human.adjust_stat_modifier(STATMOD_JOB, STATKEY_END, 1)
...
```
There are job_pack datums which can do the same thing, just create a subtype and put in the job's job_pack list and it will appear as a selectable on spawn.
#### Stats
If you adjust stats in `after_spawn()`, such as the above example, `adjust_stat_modifier(STATMOD_JOB, stat_key, value)` must be used.
Additionally, this must be AFTER the parent call, which should always be first.