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