From b1709bb93b749faaf73eecf375e231c3ce8c0b5c Mon Sep 17 00:00:00 2001
From: kyunkyunkyun <120701975+kyunkyunkyun@users.noreply.github.com>
Date: Sun, 25 May 2025 20:41:39 +0500
Subject: [PATCH] Fix improper skin tones and lots of DNA inconsistencies.
Improve mob spawners by a little (#29271)
* sane appearance
* updatepaths
* flip-vitiligo
* equal color options
* ...
* Update golems.dm
* typo
---
.../RandomRuins/SpaceRuins/sieged_lab.dmm | 4 +-
.../SpaceRuins/submaps/sieged_lab_submaps.dmm | 80 ++-----
code/__HELPERS/mob_helpers.dm | 65 ++++--
code/datums/diseases/advance/symptoms/skin.dm | 8 +-
code/datums/outfits/outfit_admin.dm | 2 +-
code/game/dna/dna2.dm | 53 +++--
code/game/dna/dna2_helpers.dm | 2 +-
code/game/dna/mutations/mutation_powers.dm | 2 +-
.../ghost_role_spawners/golems.dm | 35 ++--
.../ghost_role_spawners/oldstation_spawns.dm | 87 ++------
code/modules/awaymissions/mob_spawn.dm | 197 +++++++++++-------
.../mob/living/carbon/human/appearance.dm | 14 +-
code/modules/response_team/ert.dm | 9 +-
code/modules/response_team/ert_outfits.dm | 2 +-
.../ruins/lavalandruin_code/ash_walker_den.dm | 23 +-
.../modules/ruins/lavalandruin_code/hermit.dm | 20 +-
.../ruins/lavalandruin_code/seed_vault.dm | 11 +-
code/modules/ruins/syndicate_space_base.dm | 13 +-
code/modules/surgery/organs/organ_icon.dm | 4 +-
.../tgui/modules/appearance_changer.dm | 2 +-
.../Scripts/29271_mob_spawners.txt | 1 +
21 files changed, 301 insertions(+), 333 deletions(-)
create mode 100644 tools/UpdatePaths/Scripts/29271_mob_spawners.txt
diff --git a/_maps/map_files/RandomRuins/SpaceRuins/sieged_lab.dmm b/_maps/map_files/RandomRuins/SpaceRuins/sieged_lab.dmm
index f770dc49a15..efcfa584ed1 100644
--- a/_maps/map_files/RandomRuins/SpaceRuins/sieged_lab.dmm
+++ b/_maps/map_files/RandomRuins/SpaceRuins/sieged_lab.dmm
@@ -445,9 +445,7 @@
dir = 4
},
/obj/effect/decal/cleanable/blood/tracks/mapped,
-/obj/effect/mob_spawn/human/corpse/random_species/scientist{
- random = 1
- },
+/obj/effect/mob_spawn/human/corpse/random_species/scientist,
/obj/effect/spawner/random/blood/often,
/turf/simulated/floor/plasteel{
dir = 8;
diff --git a/_maps/map_files/RandomRuins/SpaceRuins/submaps/sieged_lab_submaps.dmm b/_maps/map_files/RandomRuins/SpaceRuins/submaps/sieged_lab_submaps.dmm
index 9c80cb0e358..a9dc8501a31 100644
--- a/_maps/map_files/RandomRuins/SpaceRuins/submaps/sieged_lab_submaps.dmm
+++ b/_maps/map_files/RandomRuins/SpaceRuins/submaps/sieged_lab_submaps.dmm
@@ -232,9 +232,7 @@
/area/template_noop)
"fQ" = (
/obj/effect/mapping_helpers/turfs/burn,
-/obj/effect/mob_spawn/human/corpse/random_species/scientist{
- random = 1
- },
+/obj/effect/mob_spawn/human/corpse/random_species/scientist,
/turf/simulated/floor/plating,
/area/template_noop)
"fU" = (
@@ -247,9 +245,7 @@
/turf/template_noop,
/area/template_noop)
"gd" = (
-/obj/effect/mob_spawn/human/corpse/random_species/scientist{
- random = 1
- },
+/obj/effect/mob_spawn/human/corpse/random_species/scientist,
/obj/effect/spawner/random/dirt/frequent,
/turf/template_noop,
/area/template_noop)
@@ -411,9 +407,7 @@
},
/area/template_noop)
"kr" = (
-/obj/effect/mob_spawn/human/corpse/random_species/scientist{
- random = 1
- },
+/obj/effect/mob_spawn/human/corpse/random_species/scientist,
/obj/effect/spawner/random/blood/often,
/turf/simulated/floor/plating/asteroid,
/area/template_noop)
@@ -593,9 +587,7 @@
/area/template_noop)
"mX" = (
/obj/effect/mapping_helpers/turfs/burn,
-/obj/effect/mob_spawn/human/corpse/random_species/doctor{
- random = 1
- },
+/obj/effect/mob_spawn/human/corpse/random_species/doctor,
/turf/simulated/floor/plating,
/area/template_noop)
"mY" = (
@@ -829,9 +821,7 @@
},
/area/template_noop)
"rN" = (
-/obj/effect/mob_spawn/human/corpse/random_species/scientist{
- random = 1
- },
+/obj/effect/mob_spawn/human/corpse/random_species/scientist,
/obj/effect/mapping_helpers/turfs/burn,
/turf/simulated/floor/plating,
/area/template_noop)
@@ -904,9 +894,7 @@
},
/area/template_noop)
"te" = (
-/obj/effect/mob_spawn/human/corpse/random_species/engineer{
- random = 1
- },
+/obj/effect/mob_spawn/human/corpse/random_species/engineer,
/obj/effect/mapping_helpers/turfs/burn,
/obj/effect/decal/cleanable/blood/tracks/mapped{
dir = 4
@@ -963,9 +951,7 @@
},
/area/template_noop)
"ue" = (
-/obj/effect/mob_spawn/human/corpse/random_species/scientist{
- random = 1
- },
+/obj/effect/mob_spawn/human/corpse/random_species/scientist,
/obj/effect/spawner/random/blood/often,
/turf/simulated/floor/plating,
/area/template_noop)
@@ -1107,9 +1093,7 @@
"xQ" = (
/obj/effect/spawner/themed_mess/engineering,
/obj/structure/chair,
-/obj/effect/mob_spawn/human/corpse/random_species/engineer{
- random = 1
- },
+/obj/effect/mob_spawn/human/corpse/random_species/engineer,
/obj/effect/spawner/random/blood/often,
/turf/simulated/floor/plasteel,
/area/template_noop)
@@ -1178,9 +1162,7 @@
/area/template_noop)
"zo" = (
/obj/machinery/firealarm/directional/south,
-/obj/effect/mob_spawn/human/corpse/random_species/security_officer{
- random = 1
- },
+/obj/effect/mob_spawn/human/corpse/random_species/security_officer,
/turf/template_noop,
/area/template_noop)
"zs" = (
@@ -1221,9 +1203,7 @@
/turf/template_noop,
/area/template_noop)
"zR" = (
-/obj/effect/mob_spawn/human/corpse/random_species/assistant{
- random = 1
- },
+/obj/effect/mob_spawn/human/corpse/random_species/assistant,
/obj/effect/decal/cleanable/blood,
/turf/template_noop,
/area/template_noop)
@@ -1234,9 +1214,7 @@
},
/area/template_noop)
"zV" = (
-/obj/effect/mob_spawn/human/corpse/random_species/engineer{
- random = 1
- },
+/obj/effect/mob_spawn/human/corpse/random_species/engineer,
/obj/item/trash/spentcasing/bullet,
/obj/effect/mapping_helpers/turfs/burn,
/obj/effect/spawner/random/blood/often,
@@ -1272,9 +1250,7 @@
/turf/simulated/floor/plating,
/area/template_noop)
"AW" = (
-/obj/effect/mob_spawn/human/corpse/random_species/scientist{
- random = 1
- },
+/obj/effect/mob_spawn/human/corpse/random_species/scientist,
/obj/item/trash/spentcasing/bullet,
/turf/simulated/floor/plating,
/area/template_noop)
@@ -1340,9 +1316,7 @@
/area/template_noop)
"BZ" = (
/obj/effect/spawner/random/blood/often,
-/obj/effect/mob_spawn/human/corpse/random_species/security_officer{
- random = 1
- },
+/obj/effect/mob_spawn/human/corpse/random_species/security_officer,
/turf/simulated/floor/plating,
/area/template_noop)
"Cj" = (
@@ -1398,9 +1372,7 @@
/area/template_noop)
"DK" = (
/obj/structure/chair,
-/obj/effect/mob_spawn/human/corpse/random_species/engineer{
- random = 1
- },
+/obj/effect/mob_spawn/human/corpse/random_species/engineer,
/obj/effect/spawner/random/blood/often,
/turf/simulated/floor/plasteel,
/area/template_noop)
@@ -1812,9 +1784,7 @@
/turf/template_noop,
/area/template_noop)
"MI" = (
-/obj/effect/mob_spawn/human/corpse/random_species/scientist{
- random = 1
- },
+/obj/effect/mob_spawn/human/corpse/random_species/scientist,
/obj/effect/decal/cleanable/blood,
/turf/simulated/floor/plating,
/area/template_noop)
@@ -1829,9 +1799,7 @@
/turf/simulated/floor/plating,
/area/template_noop)
"Na" = (
-/obj/effect/mob_spawn/human/corpse/random_species/security_officer{
- random = 1
- },
+/obj/effect/mob_spawn/human/corpse/random_species/security_officer,
/turf/template_noop,
/area/template_noop)
"Nb" = (
@@ -1946,9 +1914,7 @@
},
/area/template_noop)
"OM" = (
-/obj/effect/mob_spawn/human/corpse/random_species/scientist{
- random = 1
- },
+/obj/effect/mob_spawn/human/corpse/random_species/scientist,
/turf/template_noop,
/area/template_noop)
"Pa" = (
@@ -2068,9 +2034,7 @@
"SJ" = (
/obj/effect/mapping_helpers/turfs/burn,
/obj/effect/spawner/random/blood/often,
-/obj/effect/mob_spawn/human/corpse/random_species/assistant{
- random = 1
- },
+/obj/effect/mob_spawn/human/corpse/random_species/assistant,
/turf/template_noop,
/area/template_noop)
"SS" = (
@@ -2267,9 +2231,7 @@
"Yg" = (
/obj/effect/mapping_helpers/turfs/burn,
/obj/effect/spawner/random/dirt/often,
-/obj/effect/mob_spawn/human/corpse/random_species/scientist{
- random = 1
- },
+/obj/effect/mob_spawn/human/corpse/random_species/scientist,
/turf/simulated/floor/plating,
/area/template_noop)
"Yo" = (
@@ -2330,9 +2292,7 @@
/turf/template_noop,
/area/template_noop)
"ZI" = (
-/obj/effect/mob_spawn/human/corpse/random_species/scientist{
- random = 1
- },
+/obj/effect/mob_spawn/human/corpse/random_species/scientist,
/obj/effect/mapping_helpers/turfs/burn,
/obj/effect/decal/cleanable/blood/tracks/mapped,
/turf/template_noop,
diff --git a/code/__HELPERS/mob_helpers.dm b/code/__HELPERS/mob_helpers.dm
index 521bb3d0ba8..b8022082d3a 100644
--- a/code/__HELPERS/mob_helpers.dm
+++ b/code/__HELPERS/mob_helpers.dm
@@ -88,6 +88,45 @@
return f_style
+// it might be made species related, but it is pretty okay now
+/proc/random_hair_color(tint = TRUE, range)
+ if(prob(1))
+ return rand_hex_color() // sPaCe PuNk
+ var/list/color_options = list(
+ // gray, black, blue - 5 total
+ COLOR_GRAY15,
+ COLOR_GRAY40,
+ COLOR_SILVER,
+ COLOR_DARK_BLUE_GRAY,
+ COLOR_WALL_GUNMETAL,
+ // yellow, red, orange - 5 total
+ COLOR_YELLOW_GRAY,
+ COLOR_WARM_YELLOW,
+ COLOR_DARK_ORANGE,
+ COLOR_PALE_ORANGE,
+ COLOR_SUN,
+ // brownish. there is not much of them so they are repeated - 5 total
+ COLOR_CHESTNUT,
+ COLOR_CHESTNUT,
+ COLOR_BEASTY_BROWN,
+ COLOR_BEASTY_BROWN,
+ COLOR_BROWN_ORANGE,
+ )
+ if(tint) // returns a tint of selected color
+ return tint_color(pick(color_options), range)
+ return pick(color_options)
+
+/// Returns a purely random tint for specific color
+/proc/tint_color(color, range = 25)
+ if(!istext(color) || length(color) < 7 || copytext(color, 1, 2) != "#") // if it's not a hex color
+ return color // just leave it as it is
+
+ var/R = clamp(color2R(color) + rand(-range, range), 0, 255)
+ var/G = clamp(color2G(color) + rand(-range, range), 0, 255)
+ var/B = clamp(color2B(color) + rand(-range, range), 0, 255)
+
+ return rgb(R, G, B)
+
/proc/random_head_accessory(species = "Human")
var/ha_style = "None"
var/list/valid_head_accessories = list()
@@ -177,22 +216,18 @@
else
return current_species.get_random_name(gender)
+/// Randomises skin tone, specifically for each species that has a skin tone. Otherwise keeps a default of 1
/proc/random_skin_tone(species = "Human")
- if(species == "Human" || species == "Drask")
- switch(pick(60;"caucasian", 15;"afroamerican", 10;"african", 10;"latino", 5;"albino"))
- if("caucasian") . = -10
- if("afroamerican") . = -115
- if("african") . = -165
- if("latino") . = -55
- if("albino") . = 34
- else . = rand(-185, 34)
- return min(max(. + rand(-25, 25), -185), 34)
- else if(species == "Vox")
- . = rand(1, 6)
- else if(species == "Nian")
- . = rand(1, 4)
- else
- . = 1
+ switch(species)
+ if("Human")
+ return rand(1, 13)
+ if("Drask")
+ return rand(1, 220)
+ if("Nian")
+ return rand(1, 4)
+ if("Vox")
+ return rand(1, 8)
+ return 1
/proc/skintone2racedescription(tone, species = "Human")
if(species == "Human")
diff --git a/code/datums/diseases/advance/symptoms/skin.dm b/code/datums/diseases/advance/symptoms/skin.dm
index 22d2e3aecb9..b5c79f7ff4c 100644
--- a/code/datums/diseases/advance/symptoms/skin.dm
+++ b/code/datums/diseases/advance/symptoms/skin.dm
@@ -30,11 +30,11 @@ BONUS
var/mob/living/M = A.affected_mob
if(ishuman(M))
var/mob/living/carbon/human/H = M
- if(H.s_tone == -85)
+ if(H.s_tone == 85)
return
switch(A.stage)
if(5)
- H.change_skin_tone(-85)
+ H.change_skin_tone(85, TRUE)
else
H.visible_message("[H] looks a bit pale...", "Your skin suddenly appears lighter...")
@@ -73,11 +73,11 @@ BONUS
var/mob/living/M = A.affected_mob
if(ishuman(M))
var/mob/living/carbon/human/H = M
- if(H.s_tone == 85)
+ if(H.s_tone == -85)
return
switch(A.stage)
if(5)
- H.change_skin_tone(85)
+ H.change_skin_tone(-85, TRUE)
else
H.visible_message("[H] looks a bit dark...", "Your skin suddenly appears darker...")
diff --git a/code/datums/outfits/outfit_admin.dm b/code/datums/outfits/outfit_admin.dm
index c58f741a19c..c4a1e86f7e6 100644
--- a/code/datums/outfits/outfit_admin.dm
+++ b/code/datums/outfits/outfit_admin.dm
@@ -1593,7 +1593,7 @@
if(prob(50))
var/codename_prefix = pick("Exposed", "Unveiled", "Phantom", "Mirage", "Punished", "Invisible", "Swift")
codename = "[codename_prefix] [codename]"
- H.rename_character(null, codename)
+ H.rename_character(H.real_name, codename)
var/hair_color = "#361A00"
diff --git a/code/game/dna/dna2.dm b/code/game/dna/dna2.dm
index 4bef9732f15..e247c21eaf8 100644
--- a/code/game/dna/dna2.dm
+++ b/code/game/dna/dna2.dm
@@ -98,7 +98,7 @@ GLOBAL_LIST_EMPTY(bad_blocks)
/datum/dna/proc/ResetUIFrom(mob/living/carbon/human/character)
// INITIALIZE!
- ResetUI(1)
+ ResetUI(TRUE)
// Hair
// FIXME: Species-specific defaults pls
var/obj/item/organ/external/head/head = character.get_organ("head")
@@ -120,33 +120,33 @@ GLOBAL_LIST_EMPTY(bad_blocks)
head_traits_to_dna(character, head)
eye_color_to_dna(eyes_organ)
- SetUIValueRange(DNA_UI_SKIN_R, color2R(character.skin_colour), 255, 1)
- SetUIValueRange(DNA_UI_SKIN_G, color2G(character.skin_colour), 255, 1)
- SetUIValueRange(DNA_UI_SKIN_B, color2B(character.skin_colour), 255, 1)
+ SetUIValueRange(DNA_UI_SKIN_R, color2R(character.skin_colour), 255, TRUE)
+ SetUIValueRange(DNA_UI_SKIN_G, color2G(character.skin_colour), 255, TRUE)
+ SetUIValueRange(DNA_UI_SKIN_B, color2B(character.skin_colour), 255, TRUE)
- SetUIValueRange(DNA_UI_HEAD_MARK_R, color2R(character.m_colours["head"]), 255, 1)
- SetUIValueRange(DNA_UI_HEAD_MARK_G, color2G(character.m_colours["head"]), 255, 1)
- SetUIValueRange(DNA_UI_HEAD_MARK_B, color2B(character.m_colours["head"]), 255, 1)
+ SetUIValueRange(DNA_UI_HEAD_MARK_R, color2R(character.m_colours["head"]), 255, TRUE)
+ SetUIValueRange(DNA_UI_HEAD_MARK_G, color2G(character.m_colours["head"]), 255, TRUE)
+ SetUIValueRange(DNA_UI_HEAD_MARK_B, color2B(character.m_colours["head"]), 255, TRUE)
- SetUIValueRange(DNA_UI_BODY_MARK_R, color2R(character.m_colours["body"]), 255, 1)
- SetUIValueRange(DNA_UI_BODY_MARK_G, color2G(character.m_colours["body"]), 255, 1)
- SetUIValueRange(DNA_UI_BODY_MARK_B, color2B(character.m_colours["body"]), 255, 1)
+ SetUIValueRange(DNA_UI_BODY_MARK_R, color2R(character.m_colours["body"]), 255, TRUE)
+ SetUIValueRange(DNA_UI_BODY_MARK_G, color2G(character.m_colours["body"]), 255, TRUE)
+ SetUIValueRange(DNA_UI_BODY_MARK_B, color2B(character.m_colours["body"]), 255, TRUE)
- SetUIValueRange(DNA_UI_TAIL_MARK_R, color2R(character.m_colours["tail"]), 255, 1)
- SetUIValueRange(DNA_UI_TAIL_MARK_G, color2G(character.m_colours["tail"]), 255, 1)
- SetUIValueRange(DNA_UI_TAIL_MARK_B, color2B(character.m_colours["tail"]), 255, 1)
+ SetUIValueRange(DNA_UI_TAIL_MARK_R, color2R(character.m_colours["tail"]), 255, TRUE)
+ SetUIValueRange(DNA_UI_TAIL_MARK_G, color2G(character.m_colours["tail"]), 255, TRUE)
+ SetUIValueRange(DNA_UI_TAIL_MARK_B, color2B(character.m_colours["tail"]), 255, TRUE)
- SetUIValueRange(DNA_UI_SKIN_TONE, 35-character.s_tone, 220, 1) // Value can be negative.
+ SetUIValueRange(DNA_UI_SKIN_TONE, abs(35 - character.s_tone), 220, TRUE)
- SetUIValueRange(DNA_UI_HEAD_MARK_STYLE, head_marks, length(GLOB.marking_styles_list), 1)
- SetUIValueRange(DNA_UI_BODY_MARK_STYLE, body_marks, length(GLOB.marking_styles_list), 1)
- SetUIValueRange(DNA_UI_TAIL_MARK_STYLE, tail_marks, length(GLOB.marking_styles_list), 1)
+ SetUIValueRange(DNA_UI_HEAD_MARK_STYLE, head_marks, length(GLOB.marking_styles_list), TRUE)
+ SetUIValueRange(DNA_UI_BODY_MARK_STYLE, body_marks, length(GLOB.marking_styles_list), TRUE)
+ SetUIValueRange(DNA_UI_TAIL_MARK_STYLE, tail_marks, length(GLOB.marking_styles_list), TRUE)
- SetUIValueRange(DNA_UI_PHYSIQUE, GLOB.character_physiques.Find(character.physique), length(GLOB.character_physiques), 1)
- SetUIValueRange(DNA_UI_HEIGHT, GLOB.character_heights.Find(character.height), length(GLOB.character_heights), 1)
+ SetUIValueRange(DNA_UI_PHYSIQUE, GLOB.character_physiques.Find(character.physique), length(GLOB.character_physiques), TRUE)
+ SetUIValueRange(DNA_UI_HEIGHT, GLOB.character_heights.Find(character.height), length(GLOB.character_heights), TRUE)
var/list/bodyacc = GLOB.body_accessory_by_name.Find(character.body_accessory?.name || "None")
- SetUIValueRange(DNA_UI_BACC_STYLE, bodyacc, length(GLOB.body_accessory_by_name), 1)
+ SetUIValueRange(DNA_UI_BACC_STYLE, bodyacc, length(GLOB.body_accessory_by_name), TRUE)
switch(character.body_type)
if(FEMALE)
@@ -157,16 +157,15 @@ GLOBAL_LIST_EMPTY(bad_blocks)
//Set the Gender
switch(character.gender)
if(FEMALE)
- SetUITriState(DNA_UI_GENDER, DNA_GENDER_FEMALE, 1)
+ SetUITriState(DNA_UI_GENDER, DNA_GENDER_FEMALE, TRUE)
if(MALE)
- SetUITriState(DNA_UI_GENDER, DNA_GENDER_MALE, 1)
+ SetUITriState(DNA_UI_GENDER, DNA_GENDER_MALE, TRUE)
if(PLURAL)
- SetUITriState(DNA_UI_GENDER, DNA_GENDER_PLURAL, 1)
+ SetUITriState(DNA_UI_GENDER, DNA_GENDER_PLURAL, TRUE)
- if(head)
- head.dna.UI = character.dna.UI
- if(eyes_organ)
- eyes_organ.dna.UI = character.dna.UI
+ // updates DNA for our external and internal organs
+ for(var/obj/item/organ/organ in (character.bodyparts + character.internal_organs))
+ organ.dna.UI = character.dna.UI
UpdateUI()
diff --git a/code/game/dna/dna2_helpers.dm b/code/game/dna/dna2_helpers.dm
index 73973a1944d..7dfd4151d28 100644
--- a/code/game/dna/dna2_helpers.dm
+++ b/code/game/dna/dna2_helpers.dm
@@ -152,7 +152,7 @@
H.m_colours["body"] = rgb(dna.GetUIValueRange(DNA_UI_BODY_MARK_R, 255), dna.GetUIValueRange(DNA_UI_BODY_MARK_G, 255), dna.GetUIValueRange(DNA_UI_BODY_MARK_B, 255))
H.m_colours["tail"] = rgb(dna.GetUIValueRange(DNA_UI_TAIL_MARK_R, 255), dna.GetUIValueRange(DNA_UI_TAIL_MARK_G, 255), dna.GetUIValueRange(DNA_UI_TAIL_MARK_B, 255))
- H.s_tone = 35 - dna.GetUIValueRange(DNA_UI_SKIN_TONE, 220) // Value can be negative.
+ H.s_tone = 35 - dna.GetUIValueRange(DNA_UI_SKIN_TONE, 220)
switch(dna.GetUIState(DNA_UI_BODY_TYPE))
if(DNA_GENDER_FEMALE)
diff --git a/code/game/dna/mutations/mutation_powers.dm b/code/game/dna/mutations/mutation_powers.dm
index 9f9f4ad2252..9d069526cff 100644
--- a/code/game/dna/mutations/mutation_powers.dm
+++ b/code/game/dna/mutations/mutation_powers.dm
@@ -939,7 +939,7 @@
if(!new_tone)
new_tone = 35
else
- new_tone = 35 - max(min(round(text2num(new_tone)), 220), 1)
+ new_tone = max(min(round(text2num(new_tone)), 220), 1)
M.change_skin_tone(new_tone)
if(M.dna.species.bodyflags & HAS_ICON_SKIN_TONE)
diff --git a/code/modules/awaymissions/mission_code/ghost_role_spawners/golems.dm b/code/modules/awaymissions/mission_code/ghost_role_spawners/golems.dm
index c77e7fb2e03..565b092e285 100644
--- a/code/modules/awaymissions/mission_code/ghost_role_spawners/golems.dm
+++ b/code/modules/awaymissions/mission_code/ghost_role_spawners/golems.dm
@@ -59,25 +59,25 @@
/obj/effect/mob_spawn/human/alive/golem
name = "inert free golem shell"
desc = "A humanoid shape, empty, lifeless, and full of potential."
- mob_name = "a free golem"
+ role_name = "free golem"
icon = 'icons/obj/wizard.dmi'
icon_state = "construct"
- mob_species = /datum/species/golem
- roundstart = FALSE
- death = FALSE
- anchored = FALSE
- move_resist = MOVE_FORCE_NORMAL
- density = FALSE
- death_cooldown = 300 SECONDS
- STATIC_COOLDOWN_DECLARE(ghost_flash_cooldown)
- var/has_owner = FALSE
- var/can_transfer = TRUE //if golems can switch bodies to this new shell
- var/mob/living/owner = null //golem's owner if it has one
important_info = "You are not an antagonist. Do not create AIs without explicit admin permission. Do not involve yourself with the main station, boarding the main station requires explicit admin permission."
description = "As a Free Golem on lavaland, you are unable to use most weapons, but you can mine, research and make more of your kind. Earn enough mining points and you can even move your shuttle out of there. Your goal is to survive on lavaland with your kin, not to become crew on the primary station."
flavour_text = "You are a Free Golem. Your family worships The Liberator. In his infinite and divine wisdom, he set your clan free to \
travel the stars with a single declaration: \"Yeah go do whatever.\" Though you are bound to the one who created you, it is customary in your society to repeat those same words to newborn \
golems, so that no golem may ever be forced to serve again."
+ density = FALSE
+ anchored = FALSE
+ move_resist = MOVE_FORCE_NORMAL
+ death_cooldown = 300 SECONDS
+ mob_species = /datum/species/golem
+ var/has_owner = FALSE
+ /// If golems can switch bodies to this new shell
+ var/can_transfer = TRUE
+ /// Golem's owner if it has one
+ var/mob/living/owner
+ STATIC_COOLDOWN_DECLARE(ghost_flash_cooldown)
/obj/effect/mob_spawn/human/alive/golem/Initialize(mapload, datum/species/golem/species = null, mob/creator = null)
if(species) //spawners list uses object name to register so this goes before ..()
@@ -98,7 +98,7 @@
Serve [creator], and assist [creator.p_them()] in completing [creator.p_their()] goals at any cost."
owner = creator
-/obj/effect/mob_spawn/human/alive/golem/special(mob/living/new_spawn, name)
+/obj/effect/mob_spawn/human/alive/golem/special(mob/living/new_spawn)
var/datum/species/golem/X = mob_species
to_chat(new_spawn, "[initial(X.info_text)]")
if(!owner)
@@ -130,10 +130,6 @@
if(has_owner)
var/datum/species/golem/G = H.dna.species
G.owner = owner
- if(!name)
- H.rename_character(null, H.dna.species.get_random_name())
- else
- H.rename_character(null, name)
if(is_species(H, /datum/species/golem/tranquillite) && H.mind)
H.mind.AddSpell(new /datum/spell/aoe/conjure/build/mime_wall(null))
H.mind.AddSpell(new /datum/spell/mime/speak(null))
@@ -198,7 +194,7 @@
/obj/effect/mob_spawn/human/alive/golem/servant
has_owner = TRUE
name = "inert servant golem shell"
- mob_name = "a servant golem"
+ role_name = "servant golem"
/obj/effect/mob_spawn/human/alive/golem/servant/handle_becoming_golem(obj/item/I, mob/living/carbon/user)
if(!isgolem(user))
@@ -208,7 +204,6 @@
/obj/effect/mob_spawn/human/alive/golem/adamantine
name = "dust-caked free golem shell"
desc = "A humanoid shape, empty, lifeless, and full of potential."
- mob_name = "a free golem"
+ assignedrole = "Free Golem"
can_transfer = FALSE
mob_species = /datum/species/golem/adamantine
- assignedrole = "Free Golem"
diff --git a/code/modules/awaymissions/mission_code/ghost_role_spawners/oldstation_spawns.dm b/code/modules/awaymissions/mission_code/ghost_role_spawners/oldstation_spawns.dm
index 5d6cfe1fdd9..5ccf6295311 100644
--- a/code/modules/awaymissions/mission_code/ghost_role_spawners/oldstation_spawns.dm
+++ b/code/modules/awaymissions/mission_code/ghost_role_spawners/oldstation_spawns.dm
@@ -1,107 +1,54 @@
//Ancient cryogenic sleepers. Players become NT crewmen from a hundred year old space station, now on the verge of collapse.
-/obj/effect/mob_spawn/human/alive/old/sec
+/obj/effect/mob_spawn/human/alive/old
name = "old cryogenics pod"
desc = "A humming cryo pod. You can barely recognise a security uniform underneath the built up ice. The machine is attempting to wake up its occupant."
- mob_name = "a security officer"
icon = 'icons/obj/cryogenic2.dmi'
icon_state = "sleeper"
- roundstart = FALSE
- death = FALSE
- random = TRUE
- mob_species = /datum/species/human
description = "Work as a team with your fellow survivors aboard a ruined, ancient space station."
- important_info = ""
- flavour_text = "You are a security officer working for Nanotrasen, stationed onboard a state of the art research station. You vaguely recall rushing into a \
+ assignedrole = "Ancient Crew"
+ allow_gender_pick = TRUE
+
+/obj/effect/mob_spawn/human/alive/old/Initialize(mapload)
+ flavour_text = "You are \a [role_name] working for Nanotrasen, stationed onboard a state of the art research station. You vaguely recall rushing into a \
cryogenics pod due to an oncoming radiation storm. The last thing you remember is the station's Artificial Program telling you that you would only be asleep for eight hours. As you open \
your eyes, everything seems rusted and broken, a dark feeling swells in your gut as you climb out of your pod."
+ return ..()
+
+/obj/effect/mob_spawn/human/alive/old/Destroy()
+ new /obj/structure/showcase/machinery/oldpod/used(drop_location())
+ return ..()
+
+/obj/effect/mob_spawn/human/alive/old/sec
+ role_name = "security officer"
uniform = /obj/item/clothing/under/retro/security
shoes = /obj/item/clothing/shoes/jackboots
id = /obj/item/card/id/away/old/sec
r_pocket = /obj/item/restraints/handcuffs
l_pocket = /obj/item/flash
- assignedrole = "Ancient Crew"
-
-/obj/effect/mob_spawn/human/alive/old/sec/Destroy()
- new /obj/structure/showcase/machinery/oldpod/used(drop_location())
- return ..()
/obj/effect/mob_spawn/human/alive/old/med
- name = "old cryogenics pod"
- desc = "A humming cryo pod. You can barely recognise a medical uniform underneath the built up ice. The machine is attempting to wake up its occupant."
- mob_name = "a medical doctor"
- icon = 'icons/obj/cryogenic2.dmi'
- icon_state = "sleeper"
- roundstart = FALSE
- death = FALSE
- random = TRUE
- mob_species = /datum/species/human
- description = "Work as a team with your fellow survivors aboard a ruined, ancient space station."
- important_info = ""
- flavour_text = "You are a medical doctor working for Nanotrasen, stationed onboard a state of the art research station. You vaguely recall rushing into a \
- cryogenics pod due to an oncoming radiation storm. The last thing you remember is the station's Artificial Program telling you that you would only be asleep for eight hours. As you open \
- your eyes, everything seems rusted and broken, a dark feeling swells in your gut as you climb out of your pod."
+ role_name = "medical doctor"
uniform = /obj/item/clothing/under/retro/medical
shoes = /obj/item/clothing/shoes/black
id = /obj/item/card/id/away/old/med
l_pocket = /obj/item/stack/medical/ointment
r_pocket = /obj/item/stack/medical/ointment
- assignedrole = "Ancient Crew"
-
-/obj/effect/mob_spawn/human/alive/old/med/Destroy()
- new /obj/structure/showcase/machinery/oldpod/used(drop_location())
- return ..()
/obj/effect/mob_spawn/human/alive/old/eng
- name = "old cryogenics pod"
- desc = "A humming cryo pod. You can barely recognise an engineering uniform underneath the built up ice. The machine is attempting to wake up its occupant."
- mob_name = "an engineer"
- icon = 'icons/obj/cryogenic2.dmi'
- icon_state = "sleeper"
- roundstart = FALSE
- death = FALSE
- random = TRUE
- mob_species = /datum/species/human
- description = "Work as a team with your fellow survivors aboard a ruined, ancient space station."
- important_info = ""
- flavour_text = "You are an engineer working for Nanotrasen, stationed onboard a state of the art research station. You vaguely recall rushing into a \
- cryogenics pod due to an oncoming radiation storm. The last thing you remember is the station's Artificial Program telling you that you would only be asleep for eight hours. As you open \
- your eyes, everything seems rusted and broken, a dark feeling swells in your gut as you climb out of your pod."
+ role_name = "engineer"
uniform = /obj/item/clothing/under/retro/engineering
shoes = /obj/item/clothing/shoes/workboots
id = /obj/item/card/id/away/old/eng
gloves = /obj/item/clothing/gloves/color/fyellow/old
l_pocket = /obj/item/tank/internals/emergency_oxygen
- assignedrole = "Ancient Crew"
-
-/obj/effect/mob_spawn/human/alive/old/eng/Destroy()
- new /obj/structure/showcase/machinery/oldpod/used(drop_location())
- return ..()
/obj/effect/mob_spawn/human/alive/old/sci
- name = "old cryogenics pod"
- desc = "A humming cryo pod. You can barely recognise a science uniform underneath the built up ice. The machine is attempting to wake up its occupant."
- mob_name = "a scientist"
- icon = 'icons/obj/cryogenic2.dmi'
- icon_state = "sleeper"
- roundstart = FALSE
- death = FALSE
- random = TRUE
- mob_species = /datum/species/human
- description = "Work as a team with your fellow survivors aboard a ruined, ancient space station."
- important_info = ""
- flavour_text = "You are a scientist working for Nanotrasen, stationed onboard a state of the art research station. You vaguely recall rushing into a \
- cryogenics pod due to an oncoming radiation storm. The last thing you remember is the station's Artificial Program telling you that you would only be asleep for eight hours. As you open \
- your eyes, everything seems rusted and broken, a dark feeling swells in your gut as you climb out of your pod."
+ role_name = "scientist"
uniform = /obj/item/clothing/under/retro/science
shoes = /obj/item/clothing/shoes/laceup
id = /obj/item/card/id/away/old/sci
l_pocket = /obj/item/stack/medical/bruise_pack
- assignedrole = "Ancient Crew"
-
-/obj/effect/mob_spawn/human/alive/old/sci/Destroy()
- new /obj/structure/showcase/machinery/oldpod/used(drop_location())
- return ..()
/obj/structure/showcase/machinery/oldpod
name = "damaged cryogenic pod"
diff --git a/code/modules/awaymissions/mob_spawn.dm b/code/modules/awaymissions/mob_spawn.dm
index 22b0b10b3db..ce163becb68 100644
--- a/code/modules/awaymissions/mob_spawn.dm
+++ b/code/modules/awaymissions/mob_spawn.dm
@@ -1,3 +1,5 @@
+#define HAIR_TINT_RANGE 10 // range of available tint for our hair
+
//These are meant for spawning on maps, namely Away Missions.
//If someone can do this in a neater way, be my guest-Kor
@@ -10,41 +12,57 @@
anchored = TRUE
icon = 'icons/effects/blood.dmi'
icon_state = "remains"
- var/mob_type = null
- var/mob_name = "unidentified entity"
- var/mob_gender = null
- var/death = TRUE //Kill the mob
- var/roundstart = TRUE //fires on initialize
- var/instant = FALSE //fires on New
- var/flavour_text = "" //flavour/fluff about the role, optional.
- var/description = "A description for this has not been set. This is either an oversight or an admin-spawned spawner not in normal use." //intended as OOC info about the role
- var/important_info = "" //important info such as rules that apply to you, etc. Optional.
- var/faction = null
- var/permanent = FALSE //If true, the spawner will not disappear upon running out of uses.
- var/random = FALSE //Don't set a name or gender, just go random
- var/objectives = null
- var/uses = 1 //how many times can we spawn from it. set to -1 for infinite.
+ var/mob_type
+ /// Overrides name given to our mob
+ var/mob_name
+ /// Who do we gonna play for
+ var/role_name
+ /// Kill the mob
+ var/death = TRUE
+ /// Fires on initialize
+ var/roundstart = TRUE
+ /// Fires on New
+ var/instant = FALSE
+ /// Flavour/fluff about the role, optional.
+ var/flavour_text = ""
+ /// Intended as OOC info about the role
+ var/description = "A description for this has not been set. This is either an oversight or an admin-spawned spawner not in normal use."
+ /// Important info such as rules that apply to you, etc. Optional.
+ var/important_info = ""
+ /// List of additional factions for our mob
+ var/list/faction = list()
+ /// If true, the spawner will not disappear upon running out of uses.
+ var/permanent = FALSE
+ var/objectives
+ /// How many times can we spawn from it. Set to -1 for infinite.
+ var/uses = 1
var/brute_damage = 0
var/oxy_damage = 0
var/burn_damage = 0
- var/datum/disease/disease = null //Do they start with a pre-spawned disease?
- var/mob_color //Change the mob's color
+ /// Do they start with a pre-spawned disease?
+ var/datum/disease/disease
+ /// Change the mob's color
+ var/mob_color
var/assignedrole
- var/banType = ROLE_GHOST
+ var/ban_type = ROLE_GHOST
var/ghost_usable = TRUE
- var/offstation_role = TRUE // If set to true, the role of the user's mind will be set to offstation
- var/death_cooldown = 0 // How long you have to wait after dying before using it again, in deciseconds. People that join as observers are not included.
- ///If antagbanned people are prevented from using it, only false for the ghost bar spawner.
+ /// If set to true, the role of the user's mind will be set to offstation
+ var/offstation_role = TRUE
+ /// How long you have to wait after dying before using it again. People that join as observers are not included.
+ var/death_cooldown = 0
+ /// If antagbanned people are prevented from using it, only false for the ghost bar spawner.
var/restrict_antagban = TRUE
/obj/effect/mob_spawn/attack_ghost(mob/user)
if(!valid_to_spawn(user))
return
- var/ghost_role = tgui_alert(user, "Become [mob_name]? (Warning, You can no longer be cloned!)", "Respawn", list("Yes", "No"))
+ var/ghost_role = tgui_alert(user, "Become \a [role_name]? (Warning, You can no longer be cloned!)", "Respawn", list("Yes", "No"))
if(ghost_role != "Yes")
return
if(!species_prompt(user))
return
+ if(!gender_prompt(user))
+ return
if(!loc || !uses && !permanent || QDELETED(src) || QDELETED(user))
to_chat(user, "The [name] is no longer usable!")
return
@@ -71,6 +89,9 @@
/obj/effect/mob_spawn/proc/species_prompt()
return TRUE
+/obj/effect/mob_spawn/proc/gender_prompt()
+ return TRUE
+
/obj/effect/mob_spawn/proc/special(mob/M)
return
@@ -83,7 +104,7 @@
if(!uses && !permanent)
to_chat(user, "This spawner is out of charges!")
return FALSE
- if((jobban_isbanned(user, banType) || (restrict_antagban && jobban_isbanned(user, ROLE_SYNDICATE))))
+ if((jobban_isbanned(user, ban_type) || (restrict_antagban && jobban_isbanned(user, ROLE_SYNDICATE))))
to_chat(user, "You are jobanned!")
return FALSE
if(!HAS_TRAIT(user, TRAIT_RESPAWNABLE))
@@ -125,13 +146,10 @@
/obj/effect/mob_spawn/proc/create(ckey, flavour = TRUE, name, mob/user = usr)
log_game("[ckey] became [mob_name]")
var/mob/living/M = new mob_type(get_turf(src)) //living mobs only
- if(!random)
- M.real_name = mob_name ? mob_name : M.name
- if(!mob_gender)
- mob_gender = pick(MALE, FEMALE)
- M.gender = mob_gender
+ if(mob_name)
+ M.rename_character(M.real_name, mob_name)
if(faction)
- M.faction = list(faction)
+ M.faction |= faction
if(disease)
M.ForceContractDisease(new disease)
if(death)
@@ -141,7 +159,7 @@
M.adjustBruteLoss(brute_damage)
M.adjustFireLoss(burn_damage)
M.color = mob_color
- equip(M, TRUE)
+ equip(M)
if(ckey)
M.ckey = ckey
@@ -169,19 +187,33 @@
/obj/effect/mob_spawn/human
mob_type = /mob/living/carbon/human
//Human specific stuff.
- var/mob_species = null //Set species
+ /// Species of our mob. Default is human
+ var/mob_species
+ /// Gender of our mob. Default will randomise between male and female
+ var/mob_gender
+ /// Allows ghost to select a species on mob creation
var/allow_species_pick = FALSE
+ /// List of available species to be picked by ghost
var/list/pickable_species = list("Human", "Vulpkanin", "Tajaran", "Unathi", "Skrell", "Diona", "Nian")
- var/datum/outfit/outfit = /datum/outfit //If this is a path, it will be instanced in Initialize()
+ /// Allows ghost to select a gender on mob creation
+ var/allow_gender_pick = FALSE
+ /// List of available genders to be picked by ghost
+ var/list/pickable_genders = list(MALE, FEMALE)
+ /// If this is a path, it will be instanced in Initialize()
+ var/datum/outfit/outfit = /datum/outfit
var/disable_pda = TRUE
var/disable_sensors = TRUE
+
//All of these only affect the ID that the outfit has placed in the ID slot
- var/id_job = null //Such as "Clown" or "Chef." This just determines what the ID reads as, not their access
- var/id_access = null //This is for access. See access.dm for which jobs give what access. Use "Captain" if you want it to be all access.
- var/id_access_list = null //Allows you to manually add access to an ID card.
+ /// Such as "Clown" or "Chef." This just determines what the ID reads as, not their access
+ var/id_job
+ /// This is for access. See access.dm for which jobs give what access. Use "Captain" if you want it to be all access.
+ var/id_access
+ /// Allows you to manually add access to an ID card.
+ var/id_access_list
assignedrole = "Ghost Role"
- var/husk = null
+ var/husk
/// Should we fully dna-scramble these humans?
var/dna_scrambled = FALSE
//these vars are for lazy mappers to override parts of the outfit
@@ -209,6 +241,7 @@
var/facial_hair_style
var/hair_color
var/facial_hair_color
+ /// If set, should be a value between -185 and 220. Go to `random_skin_tone()` for species-specific numbers' range you'd like to use
var/skin_tone
var/eyes_color
@@ -227,16 +260,31 @@
if(allow_species_pick)
var/selected_species = tgui_input_list(user, "Select a species", "Species Selection", pickable_species)
if(!selected_species)
- return TRUE // You didn't pick, so just continue on with the spawning process as a human
+ return FALSE
var/datum/species/S = GLOB.all_species[selected_species]
mob_species = S.type
return TRUE
+/obj/effect/mob_spawn/human/gender_prompt(mob/user)
+ if(allow_gender_pick)
+ var/selected_gender = tgui_input_list(user, "Select a gender", "Gender Selection", pickable_genders)
+ if(!selected_gender)
+ return FALSE
+ mob_gender = selected_gender
+ return TRUE
+
/obj/effect/mob_spawn/human/equip(mob/living/carbon/human/H)
if(mob_species)
H.set_species(mob_species)
- if(random)
- H.real_name = random_name(H.gender, H.dna.species.name)
+ if(mob_gender)
+ H.change_gender(mob_gender)
+ if(mob_gender == FEMALE)
+ H.change_body_type(FEMALE)
+ else if(prob(50))
+ H.change_gender(FEMALE)
+ H.change_body_type(FEMALE)
+ if(!mob_name) // randomise our name if it's not yet overriden
+ H.rename_character(H.real_name, random_name(H.gender, H.dna.species.name))
if(husk)
H.Drain()
@@ -248,37 +296,47 @@
var/obj/item/organ/external/head/D = H.get_organ("head")
if(istype(D))
if(eyes_color)
- H.change_eye_color(eyes_color)
+ H.change_eye_color(eyes_color, FALSE)
+
if(hair_style)
D.h_style = hair_style
else
- D.h_style = random_hair_style(gender, D.dna.species.name)
- if(hair_color)
- D.hair_colour = hair_color
- D.sec_hair_colour = hair_color
- else
- D.hair_colour = rand_hex_color()
- D.sec_hair_colour = D.hair_colour
+ D.h_style = random_hair_style(H.gender, D.dna.species.name)
+
if(facial_hair_style)
D.f_style = facial_hair_style
+ else if(H.gender != FEMALE) // no beard for women
+ D.f_style = random_facial_hair_style(H.gender, D.dna.species.name)
+
+ if(hair_color)
+ D.hair_colour = hair_color
+ D.sec_hair_colour = tint_color(hair_color, HAIR_TINT_RANGE)
else
- D.f_style = random_facial_hair_style(gender, D.dna.species.name)
+ D.hair_colour = random_hair_color(range = HAIR_TINT_RANGE)
+ D.sec_hair_colour = tint_color(D.hair_colour, HAIR_TINT_RANGE)
+
if(facial_hair_color)
D.facial_colour = facial_hair_color
- D.sec_facial_colour = facial_hair_color
+ D.sec_facial_colour = tint_color(facial_hair_color, HAIR_TINT_RANGE)
else
- D.facial_colour = rand_hex_color()
- D.sec_facial_colour = D.facial_colour
- if(skin_tone)
- H.s_tone = skin_tone
+ D.facial_colour = tint_color(D.hair_colour, HAIR_TINT_RANGE)
+ D.sec_facial_colour = tint_color(D.hair_colour, HAIR_TINT_RANGE)
+
+ if(!isnull(skin_tone))
+ H.change_skin_tone(skin_tone)
else
- H.s_tone = random_skin_tone()
- H.skin_colour = rand_hex_color()
+ H.change_skin_tone(random_skin_tone(H.dna.species.name))
+
+ if(istype(D))
+ H.change_skin_color(tint_color(D.hair_colour))
+ else
+ H.change_skin_color(random_hair_color())
if(dna_scrambled)
H.get_dna_scrambled()
- H.update_body(rebuild_base = TRUE)
+ H.update_dna() // saves everything we've set above
+ H.regenerate_icons()
if(outfit)
var/static/list/slots = list("uniform", "r_hand", "l_hand", "suit", "shoes", "gloves", "ears", "glasses", "mask", "head", "belt", "r_pocket", "l_pocket", "back", "id", "neck", "backpack_contents", "suit_store")
@@ -325,30 +383,23 @@
/obj/effect/mob_spawn/human/corpse
roundstart = FALSE
instant = TRUE
-
-/obj/effect/mob_spawn/human/corpse/create(ckey, flavour, name, mob/user)
- var/mob/corpse = ..()
- corpse.faction |= "spawned_corpse"
- return corpse
+ faction = list("spawned_corpse")
/obj/effect/mob_spawn/human/corpse/damaged
brute_damage = 1000
-
/obj/effect/mob_spawn/human/alive
icon = 'icons/obj/cryogenic2.dmi'
icon_state = "sleeper"
death = FALSE
roundstart = FALSE //you could use these for alive fake humans on roundstart but this is more common scenario
-
//////////Alive ones, used as "core" for ghost roles now and in future.//////////
//Space(?) Bar Patron (ghost role).
/obj/effect/mob_spawn/human/alive/space_bar_patron
name = "Bar cryogenics"
mob_name = "Bar patron"
- random = TRUE
permanent = TRUE
uses = -1
outfit = /datum/outfit/spacebartender
@@ -369,24 +420,6 @@
suit = /obj/item/clothing/suit/armor/vest
glasses = /obj/item/clothing/glasses/sunglasses/reagent
-//Lavaland Animal Doctor (ghost role).
-/obj/effect/mob_spawn/human/alive/doctor
- random = TRUE
- name = "sleeper"
- icon = 'icons/obj/cryogenic2.dmi'
- icon_state = "sleeper"
- flavour_text = "You are a space doctor!"
- assignedrole = "Space Doctor"
- outfit = /datum/outfit/job/doctor
-
-/obj/effect/mob_spawn/human/alive/doctor/equip(mob/living/carbon/human/H)
- ..()
- // Remove radio and PDA so they wouldn't annoy station crew.
- var/list/del_types = list(/obj/item/pda, /obj/item/radio/headset)
- for(var/del_type in del_types)
- var/obj/item/I = locate(del_type) in H
- qdel(I)
-
//Spooky Scary Skeleton...
/obj/effect/mob_spawn/human/alive/skeleton
icon = 'icons/mob/simple_human.dmi'
@@ -759,3 +792,5 @@
icon = 'icons/mob/lavaland/lavaland_monsters.dmi'
icon_state = "goliath_dead"
pixel_x = -12
+
+#undef HAIR_TINT_RANGE
diff --git a/code/modules/mob/living/carbon/human/appearance.dm b/code/modules/mob/living/carbon/human/appearance.dm
index afff179cc2f..9e6056afb98 100644
--- a/code/modules/mob/living/carbon/human/appearance.dm
+++ b/code/modules/mob/living/carbon/human/appearance.dm
@@ -327,14 +327,20 @@
force_update_limbs()
return TRUE
-/mob/living/carbon/human/proc/change_skin_tone(tone)
+/// Tone must be between -185 and 220. commonly used in 1 to 220, see `random_skin_tone()` for species-specific values
+/mob/living/carbon/human/proc/change_skin_tone(tone, override = FALSE)
if(s_tone == tone || !((dna.species.bodyflags & HAS_SKIN_TONE) || (dna.species.bodyflags & HAS_ICON_SKIN_TONE)))
return
- s_tone = tone
+ if(tone in -185 to 220)
+ if(dna.species.bodyflags & HAS_ICON_SKIN_TONE || override)
+ s_tone = tone
+ else
+ s_tone = 35 - tone
+ force_update_limbs()
+ return TRUE
- force_update_limbs()
- return TRUE
+ CRASH("Skin tone values must be between -185 and 220!")
/mob/living/carbon/human/proc/change_hair_gradient(style, offset_raw, color, alpha)
var/obj/item/organ/external/head/H = get_organ("head")
diff --git a/code/modules/response_team/ert.dm b/code/modules/response_team/ert.dm
index dc3574238b7..5dc233e42ba 100644
--- a/code/modules/response_team/ert.dm
+++ b/code/modules/response_team/ert.dm
@@ -172,7 +172,6 @@ GLOBAL_LIST_EMPTY(ert_request_messages)
M.overeatduration = 0
var/obj/item/organ/external/head/head_organ = M.get_organ("head")
var/eye_c = pick("#000000", "#8B4513", "#1E90FF", "#8c00ff", "#a80c0c", "#2fdb63") // Black, brown, blue, purple, red, green
- var/skin_tone = random_skin_tone(new_species) // randomise skin tone depending on mob's species
switch(new_species) //Diona not included as they don't use the hair colours, kidan use accessory, drask are skin tone Grey not included as they are BALD
if("Human", "Tajaran", "Vulpkanin", "Nian")
@@ -195,17 +194,17 @@ GLOBAL_LIST_EMPTY(ert_request_messages)
M.skin_colour = pick(su) //Pick a diffrent colour for body.
- M.change_eye_color(eye_c)
- M.s_tone = skin_tone
+ M.change_eye_color(eye_c, FALSE)
+ M.change_skin_tone(random_skin_tone(M.dna.species.name))
head_organ.headacc_colour = pick("#1f138b", "#272525", "#07a035", "#8c00ff", "#a80c0c")
head_organ.h_style = random_hair_style(M.gender, head_organ.dna.species.name)
if(M.gender != FEMALE) // no beard for women pls
head_organ.f_style = random_facial_hair_style(M.gender, head_organ.dna.species.name)
- M.rename_character(null, "[pick("Corporal", "Sergeant", "Staff Sergeant", "Sergeant First Class", "Master Sergeant", "Sergeant Major")] [pick(GLOB.last_names)]")
+ M.rename_character(M.real_name, "[pick("Corporal", "Sergeant", "Staff Sergeant", "Sergeant First Class", "Master Sergeant", "Sergeant Major")] [pick(GLOB.last_names)]")
M.age = rand(23,35)
+ M.update_dna()
M.regenerate_icons()
- M.update_body()
//Creates mind stuff.
M.mind = new
diff --git a/code/modules/response_team/ert_outfits.dm b/code/modules/response_team/ert_outfits.dm
index e2e448b0778..134415ac136 100644
--- a/code/modules/response_team/ert_outfits.dm
+++ b/code/modules/response_team/ert_outfits.dm
@@ -45,7 +45,7 @@
/datum/outfit/job/response_team/commander/pre_equip(mob/living/carbon/human/H, visualsOnly = FALSE)
. = ..()
- H.rename_character(null, "[pick("Lieutenant", "Captain", "Major")] [pick(GLOB.last_names)]")
+ H.rename_character(H.real_name, "[pick("Lieutenant", "Captain", "Major")] [pick(GLOB.last_names)]")
H.age = rand(35, 45)
/datum/outfit/job/response_team/commander/amber
diff --git a/code/modules/ruins/lavalandruin_code/ash_walker_den.dm b/code/modules/ruins/lavalandruin_code/ash_walker_den.dm
index 1e20e885347..a8d8877df95 100644
--- a/code/modules/ruins/lavalandruin_code/ash_walker_den.dm
+++ b/code/modules/ruins/lavalandruin_code/ash_walker_den.dm
@@ -13,7 +13,6 @@
resistance_flags = FIRE_PROOF | LAVA_PROOF
max_integrity = 200
- var/faction = list("ashwalker")
var/meat_counter = 6
/obj/structure/lavaland/ash_walker/Initialize(mapload)
@@ -57,28 +56,24 @@
/obj/effect/mob_spawn/human/alive/ash_walker
name = "ash walker egg"
desc = "A man-sized yellow egg, spawned from some unfathomable creature. A humanoid silhouette lurks within."
- mob_name = "an ash walker"
+ role_name = "ash walker"
icon = 'icons/mob/lavaland/lavaland_monsters.dmi'
icon_state = "large_egg"
- mob_species = /datum/species/unathi/ashwalker
- outfit = /datum/outfit/ashwalker
- roundstart = FALSE
- death = FALSE
- anchored = FALSE
- move_resist = MOVE_FORCE_NORMAL
- density = FALSE
- death_cooldown = 300 SECONDS
important_info = "Do not leave Lavaland without admin permission. Do not attack the mining outpost without being provoked."
description = "You are an ashwalker, a native inhabitant of Lavaland. Try to survive with nothing but spears and other tribal technology. Bring dead bodies back to your tendril to create more of your kind. You are free to attack miners and other outsiders."
flavour_text = "Your tribe worships the Necropolis. The wastes are sacred ground, its monsters a blessed bounty. \
You have seen lights in the distance... they foreshadow the arrival of outsiders that seek to tear apart the Necropolis and its domain. Fresh sacrifices for your nest. \
Keep in mind - your speed is given to you by the power of the Necropolis, leaving the planet will make your body more lethargic!"
assignedrole = "Ash Walker"
+ density = FALSE
+ anchored = FALSE
+ move_resist = MOVE_FORCE_NORMAL
+ death_cooldown = 300 SECONDS
+ allow_gender_pick = TRUE
+ mob_species = /datum/species/unathi/ashwalker
+ outfit = /datum/outfit/ashwalker
/obj/effect/mob_spawn/human/alive/ash_walker/special(mob/living/carbon/human/new_spawn)
- new_spawn.rename_character(new_spawn.real_name, new_spawn.dna.species.get_random_name(new_spawn.gender))
- new_spawn.mind.offstation_role = TRUE
-
to_chat(new_spawn, "Drag the corpses of men and beasts to your nest. It will absorb them to create more of your kind. Glory to the Necropolis!")
to_chat(new_spawn, "For more information, check the wiki page: ([GLOB.configuration.url.wiki_url]/index.php/Ash_Walker)")
@@ -89,7 +84,7 @@
notify_ghosts("An ash walker egg is ready to hatch in \the [A.name].", source = src, action = NOTIFY_ATTACK, flashwindow = FALSE)
/datum/outfit/ashwalker
- name ="Ashwalker"
+ name = "Ashwalker"
head = /obj/item/clothing/head/helmet/gladiator
uniform = /obj/item/clothing/under/costume/gladiator/ash_walker
diff --git a/code/modules/ruins/lavalandruin_code/hermit.dm b/code/modules/ruins/lavalandruin_code/hermit.dm
index 021fb4290ea..9b93ead60f7 100644
--- a/code/modules/ruins/lavalandruin_code/hermit.dm
+++ b/code/modules/ruins/lavalandruin_code/hermit.dm
@@ -2,27 +2,21 @@
/obj/effect/mob_spawn/human/alive/hermit
name = "malfunctioning cryostasis sleeper"
desc = "A humming sleeper with a silhouetted occupant inside. Its stasis function is broken and it's likely being used as a bed."
- mob_name = "a stranded hermit"
+ role_name = "stranded hermit"
icon = 'icons/obj/lavaland/spawners.dmi'
icon_state = "cryostasis_sleeper"
- roundstart = FALSE
- death = FALSE
- random = TRUE
- allow_species_pick = TRUE
- mob_species = /datum/species/human
description = "You are a single survivor stranded on lavaland in a makeshift shelter. Try to survive with barely any equipment. For when miner is just too boring."
flavour_text = "You've been stranded in this godless prison of a planet for longer than you can remember. Each day you barely scrape by, and between the terrible \
conditions of your makeshift shelter, the hostile creatures, and the ash drakes swooping down from the cloudless skies, all you can wish for is the feel of soft grass between your toes and \
the fresh air of Earth. These thoughts are dispelled by yet another recollection of how you got here... "
assignedrole = "Hermit"
+ allow_species_pick = TRUE
+ allow_gender_pick = TRUE
+ outfit = /datum/outfit/hermit
/obj/effect/mob_spawn/human/alive/hermit/Initialize(mapload)
. = ..()
var/arrpee = rand(1,4)
- outfit.suit = /obj/item/clothing/suit/space/syndicate/orange
- outfit.head = /obj/item/clothing/head/helmet/space/syndicate/orange
- outfit.shoes = /obj/item/clothing/shoes/black
- outfit.back = /obj/item/storage/backpack
switch(arrpee)
if(1)
flavour_text += "you were a [pick("arms dealer", "shipwright", "docking manager")]'s assistant on a small trading station several sectors from here. Raiders attacked, and there was \
@@ -49,3 +43,9 @@
/obj/effect/mob_spawn/human/alive/hermit/Destroy()
new/obj/structure/fluff/empty_cryostasis_sleeper(get_turf(src))
return ..()
+
+/datum/outfit/hermit
+ suit = /obj/item/clothing/suit/space/syndicate/orange
+ head = /obj/item/clothing/head/helmet/space/syndicate/orange
+ shoes = /obj/item/clothing/shoes/black
+ back = /obj/item/storage/backpack
diff --git a/code/modules/ruins/lavalandruin_code/seed_vault.dm b/code/modules/ruins/lavalandruin_code/seed_vault.dm
index af0e83e81f7..bde7ca88cdc 100644
--- a/code/modules/ruins/lavalandruin_code/seed_vault.dm
+++ b/code/modules/ruins/lavalandruin_code/seed_vault.dm
@@ -1,6 +1,5 @@
/obj/effect/spawner/random/seed_vault
name = "seed vault seeds"
-
loot = list(
/obj/item/food/grown/mushroom/glowshroom/glowcap = 10,
/obj/item/seeds/cherry/bomb = 10,
@@ -11,7 +10,7 @@
/obj/effect/mob_spawn/human/alive/seed_vault
name = "preserved terrarium"
desc = "An ancient machine that seems to be used for storing plant matter. The glass is obstructed by a mat of vines."
- mob_name = "a lifebringer"
+ role_name = "lifebringer"
icon = 'icons/obj/lavaland/spawners.dmi'
icon_state = "terrarium"
density = TRUE
@@ -24,10 +23,10 @@
for contact from your creators. Estimated time of last contact: Deployment, 5x10^3 millennia ago."
assignedrole = "Seed Vault Diona"
-/obj/effect/mob_spawn/human/alive/seed_vault/special(mob/living/new_spawn)
- var/plant_name = pick("Tomato", "Potato", "Broccoli", "Carrot", "Ambrosia", "Pumpkin", "Ivy", "Kudzu", "Banana", "Moss", "Flower", "Bloom", "Root", "Bark", "Glowshroom", "Petal", "Leaf", \
- "Venus", "Sprout","Cocoa", "Strawberry", "Citrus", "Oak", "Cactus", "Pepper", "Juniper")
- new_spawn.rename_character(null, plant_name)
+/obj/effect/mob_spawn/human/alive/seed_vault/Initialize(mapload)
+ mob_name = pick("Tomato", "Potato", "Broccoli", "Carrot", "Ambrosia", "Pumpkin", "Ivy", "Kudzu", "Banana", "Moss", "Flower", "Bloom", "Root", "Bark", "Glowshroom", "Petal", "Leaf", \
+ "Venus", "Sprout", "Cocoa", "Strawberry", "Citrus", "Oak", "Cactus", "Pepper", "Juniper")
+ return ..()
/obj/effect/mob_spawn/human/alive/seed_vault/Destroy()
new/obj/structure/fluff/empty_terrarium(get_turf(src))
diff --git a/code/modules/ruins/syndicate_space_base.dm b/code/modules/ruins/syndicate_space_base.dm
index b2a6902ed1e..ed93a141da1 100644
--- a/code/modules/ruins/syndicate_space_base.dm
+++ b/code/modules/ruins/syndicate_space_base.dm
@@ -24,9 +24,7 @@
// Spawners
/obj/effect/mob_spawn/human/alive/spacebase_syndicate
name = "Syndicate Researcher sleeper"
- mob_name = "Syndicate Researcher"
- roundstart = FALSE
- death = FALSE
+ role_name = "syndicate researcher"
icon = 'icons/obj/cryogenic2.dmi'
icon_state = "sleeper_s"
important_info = "Do not work against traitors or nukies. Do not leave the base."
@@ -36,7 +34,9 @@
assignedrole = "Syndicate Researcher"
del_types = list() // Necessary to prevent del_types from removing radio!
allow_species_pick = TRUE
+ allow_gender_pick = TRUE
skin_tone = 2
+ faction = list("syndicate")
/obj/effect/mob_spawn/human/alive/spacebase_syndicate/Destroy()
var/obj/structure/fluff/empty_sleeper/syndicate/S = new /obj/structure/fluff/empty_sleeper/syndicate(get_turf(src))
@@ -49,7 +49,7 @@
suit = /obj/item/clothing/suit/storage/labcoat
shoes = /obj/item/clothing/shoes/combat
gloves = /obj/item/clothing/gloves/combat
- r_ear = /obj/item/radio/headset/syndicate/alt/nocommon // See del_types above
+ l_ear = /obj/item/radio/headset/syndicate/alt/nocommon // See del_types above
back = /obj/item/storage/backpack
belt = /obj/item/storage/belt/utility/syndi_researcher
r_pocket = /obj/item/gun/projectile/automatic/pistol
@@ -63,9 +63,6 @@
/datum/outfit/spacebase_syndicate/post_equip(mob/living/carbon/human/H)
. = ..()
- H.faction |= "syndicate"
- var/random_name = random_name(pick(MALE,FEMALE), H.dna.species.name)
- H.rename_character(H.real_name, random_name)
H.job = "Syndi Researcher" // ensures they show up right in player panel for admins
if(isunathi(H) || isvulpkanin(H) || istajaran(H) || isskrell(H))
H.change_skin_color("#B2B2B2")
@@ -74,3 +71,5 @@
H.change_markings("White Fly Markings", "body")
H.change_head_accessory("White Fly Antennae")
H.change_body_accessory("White Fly Wings")
+ H.update_dna()
+ H.regenerate_icons()
diff --git a/code/modules/surgery/organs/organ_icon.dm b/code/modules/surgery/organs/organ_icon.dm
index ac9808d5bcb..9b3c239993e 100644
--- a/code/modules/surgery/organs/organ_icon.dm
+++ b/code/modules/surgery/organs/organ_icon.dm
@@ -45,10 +45,10 @@
return
if(!isnull(dna.GetUIValue(DNA_UI_SKIN_TONE)) && ((dna.species.bodyflags & HAS_SKIN_TONE) || (dna.species.bodyflags & HAS_ICON_SKIN_TONE)))
s_col = null
- s_tone = dna.GetUIValue(DNA_UI_SKIN_TONE)
+ s_tone = 35 - dna.GetUIValueRange(DNA_UI_SKIN_TONE, 220)
if(dna.species.bodyflags & HAS_SKIN_COLOR)
s_tone = null
- s_col = rgb(dna.GetUIValue(DNA_UI_SKIN_R), dna.GetUIValue(DNA_UI_SKIN_G), dna.GetUIValue(DNA_UI_SKIN_B))
+ s_col = rgb(dna.GetUIValueRange(DNA_UI_SKIN_R, 255), dna.GetUIValueRange(DNA_UI_SKIN_G, 255), dna.GetUIValueRange(DNA_UI_SKIN_B, 255))
/obj/item/organ/external/head/sync_colour_to_human(mob/living/carbon/human/H)
..()
diff --git a/code/modules/tgui/modules/appearance_changer.dm b/code/modules/tgui/modules/appearance_changer.dm
index cacf106a791..435a238e619 100644
--- a/code/modules/tgui/modules/appearance_changer.dm
+++ b/code/modules/tgui/modules/appearance_changer.dm
@@ -51,7 +51,7 @@
if(owner.dna.species.bodyflags & HAS_SKIN_TONE)
new_s_tone = input(usr, "Choose your character's skin tone:\n(Light 1 - 220 Dark)", "Skin Tone", owner.s_tone) as num|null
if(isnum(new_s_tone) && (!..()))
- new_s_tone = 35 - max(min(round(new_s_tone), 220),1)
+ new_s_tone = max(min(round(new_s_tone), 220),1)
else if(owner.dna.species.bodyflags & HAS_ICON_SKIN_TONE)
var/const/MAX_LINE_ENTRIES = 4
var/prompt = "Choose your character's skin tone: 1-[length(owner.dna.species.icon_skin_tones)]\n("
diff --git a/tools/UpdatePaths/Scripts/29271_mob_spawners.txt b/tools/UpdatePaths/Scripts/29271_mob_spawners.txt
new file mode 100644
index 00000000000..9d336dd5865
--- /dev/null
+++ b/tools/UpdatePaths/Scripts/29271_mob_spawners.txt
@@ -0,0 +1 @@
+/obj/effect/mob_spawn/@SUBTYPES : /obj/effect/mob_spawn/@SUBTYPES{@OLD;random=@SKIP}