---
# System prepended metadata

title: Job and Outfit code  guidelines

---

# 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.