From 65d32eabd631e8e0d1d5304e9a7142899ebdb6f4 Mon Sep 17 00:00:00 2001 From: Matt Atlas Date: Fri, 5 Jan 2024 18:48:13 +0100 Subject: [PATCH] Random spawn mobs now have random cultures, hair, and skin tone. (#18120) * Random spawn mobs now have random cultures, hair, and skin tone. * fixes + trioxin --------- Co-authored-by: Matt Atlas --- code/_helpers/mobs.dm | 10 +++-- code/datums/mind.dm | 13 ++++++ code/game/dna/dna2.dm | 31 +++++++------ code/game/objects/effects/portals.dm | 8 +++- code/modules/background/origins/_origins.dm | 13 ++++++ code/modules/client/preferences.dm | 7 ++- .../modules/ghostroles/spawner/human/human.dm | 4 +- .../abstract/new_player/preferences_setup.dm | 4 +- code/modules/mob/living/carbon/human/human.dm | 34 +++++++++++--- code/modules/mob/living/carbon/slime/items.dm | 4 +- code/modules/nano/modules/human_appearance.dm | 8 ++-- .../reagent_containers/glass/bottle.dm | 6 +++ html/changelogs/mattatlas-admingoodies.yml | 45 +++++++++++++++++++ 13 files changed, 145 insertions(+), 42 deletions(-) create mode 100644 html/changelogs/mattatlas-admingoodies.yml diff --git a/code/_helpers/mobs.dm b/code/_helpers/mobs.dm index 3bc377db228..98f6272052c 100644 --- a/code/_helpers/mobs.dm +++ b/code/_helpers/mobs.dm @@ -19,7 +19,8 @@ . += AM.get_mob() -/proc/random_hair_style(gender, species = SPECIES_HUMAN) +/// Species must be a datum. +/proc/random_hair_style(gender, species = /datum/species/human) var/h_style = "Bald" var/list/valid_hairstyles = list() @@ -29,7 +30,7 @@ continue if(gender == FEMALE && S.gender == MALE) continue - if( !(species in S.species_allowed)) + if(!(species in S.species_allowed)) continue valid_hairstyles[hairstyle] = GLOB.hair_styles_list[hairstyle] @@ -38,7 +39,8 @@ return h_style -/proc/random_facial_hair_style(gender, species = SPECIES_HUMAN) +/// Species must be a datum. +/proc/random_facial_hair_style(gender, species = /datum/species/human) var/f_style = "Shaved" var/list/valid_facialhairstyles = list() @@ -48,7 +50,7 @@ continue if(gender == FEMALE && S.gender == MALE) continue - if( !(species in S.species_allowed)) + if(!(species in S.species_allowed)) continue valid_facialhairstyles[facialhairstyle] = GLOB.facial_hair_styles_list[facialhairstyle] diff --git a/code/datums/mind.dm b/code/datums/mind.dm index 9a6163e70ab..e1cfffaf730 100644 --- a/code/datums/mind.dm +++ b/code/datums/mind.dm @@ -137,6 +137,19 @@ output += "Objective #[obj_count]: [objective.explanation_text]" obj_count++ + /// Culture and origin may have been set while there was no mob. + if(ishuman(recipient)) + var/mob/living/carbon/human/H = recipient + output += "
Culture Information:
" + if(H.culture) + output += "Your culture is [H.culture.name].
" + if(H.origin) + output += "Your origin is [H.origin.name].
" + if(H.religion) + output += "Your religion is [H.religion].
" + if(H.accent) + output += "Your accent is [H.accent].
" + var/datum/browser/memory_win = new(recipient, "memory") memory_win.set_content(output) memory_win.open() diff --git a/code/game/dna/dna2.dm b/code/game/dna/dna2.dm index 0dbe1577f09..e1f42e4fb4f 100644 --- a/code/game/dna/dna2.dm +++ b/code/game/dna/dna2.dm @@ -127,27 +127,27 @@ var/global/list/datum/dna/gene/dna_genes[0] character.f_style = "Shaved" var/beard = GLOB.facial_hair_styles_list.Find(character.f_style) - SetUIValueRange(DNA_UI_HAIR_R, character.r_hair, 255, 1) - SetUIValueRange(DNA_UI_HAIR_G, character.g_hair, 255, 1) - SetUIValueRange(DNA_UI_HAIR_B, character.b_hair, 255, 1) + SetUIValueRange(DNA_UI_HAIR_R, character.r_hair, 255, 1) + SetUIValueRange(DNA_UI_HAIR_G, character.g_hair, 255, 1) + SetUIValueRange(DNA_UI_HAIR_B, character.b_hair, 255, 1) - SetUIValueRange(DNA_UI_BEARD_R, character.r_facial, 255, 1) - SetUIValueRange(DNA_UI_BEARD_G, character.g_facial, 255, 1) - SetUIValueRange(DNA_UI_BEARD_B, character.b_facial, 255, 1) + SetUIValueRange(DNA_UI_BEARD_R, character.r_facial, 255, 1) + SetUIValueRange(DNA_UI_BEARD_G, character.g_facial, 255, 1) + SetUIValueRange(DNA_UI_BEARD_B, character.b_facial, 255, 1) - SetUIValueRange(DNA_UI_EYES_R, character.r_eyes, 255, 1) - SetUIValueRange(DNA_UI_EYES_G, character.g_eyes, 255, 1) - SetUIValueRange(DNA_UI_EYES_B, character.b_eyes, 255, 1) + SetUIValueRange(DNA_UI_EYES_R, character.r_eyes, 255, 1) + SetUIValueRange(DNA_UI_EYES_G, character.g_eyes, 255, 1) + SetUIValueRange(DNA_UI_EYES_B, character.b_eyes, 255, 1) - SetUIValueRange(DNA_UI_SKIN_R, character.r_skin, 255, 1) - SetUIValueRange(DNA_UI_SKIN_G, character.g_skin, 255, 1) - SetUIValueRange(DNA_UI_SKIN_B, character.b_skin, 255, 1) + SetUIValueRange(DNA_UI_SKIN_R, character.r_skin, 255, 1) + SetUIValueRange(DNA_UI_SKIN_G, character.g_skin, 255, 1) + SetUIValueRange(DNA_UI_SKIN_B, character.b_skin, 255, 1) - SetUIValueRange(DNA_UI_SKIN_TONE, 35-character.s_tone, 220, 1) // Value can be negative. + SetUIValueRange(DNA_UI_SKIN_TONE, character.s_tone, 220, 1) - SetUIState(DNA_UI_GENDER, character.gender!=MALE, 1) + SetUIState(DNA_UI_GENDER, character.gender != MALE, 1) - SetUIValueRange(DNA_UI_HAIR_STYLE, hair, GLOB.hair_styles_list.len, 1) + SetUIValueRange(DNA_UI_HAIR_STYLE, hair, GLOB.hair_styles_list.len, 1) SetUIValueRange(DNA_UI_BEARD_STYLE, beard, GLOB.facial_hair_styles_list.len,1) body_markings.Cut() @@ -160,7 +160,6 @@ var/global/list/datum/dna/gene/dna_genes[0] // Set a DNA UI block's raw value. /datum/dna/proc/SetUIValue(var/block,var/value,var/defer=0) if (block<=0) return - ASSERT(value>0) ASSERT(value<=4095) UI[block]=value dirtyUI=1 diff --git a/code/game/objects/effects/portals.dm b/code/game/objects/effects/portals.dm index 2558d247ebf..919045b5158 100644 --- a/code/game/objects/effects/portals.dm +++ b/code/game/objects/effects/portals.dm @@ -5,6 +5,9 @@ icon_state = "portal" density = TRUE unacidable = TRUE //Can't destroy energy portals. + mouse_opacity = MOUSE_OPACITY_ICON + anchored = TRUE + var/does_teleport = TRUE // Some portals might just be visual var/has_lifespan = TRUE // Whether we want to directly control the lifespan or not var/failchance = 5 @@ -12,7 +15,6 @@ var/obj/target var/creator var/precision = 1 - anchored = TRUE /obj/effect/portal/Initialize(mapload, turf/set_target, set_creator, lifespan = 300, precise = 1) . = ..() @@ -281,6 +283,10 @@ light_color = color update_light() +/// Mainly for admin events. +/obj/effect/portal/permanent + has_lifespan = FALSE + #undef COLOR_STAGE_FIVE #undef COLOR_STAGE_FOUR #undef COLOR_STAGE_THREE diff --git a/code/modules/background/origins/_origins.dm b/code/modules/background/origins/_origins.dm index 9783564c53f..c5e57541752 100644 --- a/code/modules/background/origins/_origins.dm +++ b/code/modules/background/origins/_origins.dm @@ -20,3 +20,16 @@ /singleton/origin_item/proc/on_apply(var/mob/living/carbon/human/H) for(var/trait in origin_traits) ADD_TRAIT(H, trait, CULTURE_TRAIT) + +/mob/living/carbon/human/proc/set_culture(var/singleton/origin_item/OI) + if(!istype(OI)) + crash_with("Invalid culture supplied: [OI]!") + culture = OI + OI.on_apply(src) + +/mob/living/carbon/human/proc/set_origin(var/singleton/origin_item/OI) + if(!istype(OI)) + crash_with("Invalid origin supplied: [OI]!") + origin = OI + OI.on_apply(src) + diff --git a/code/modules/client/preferences.dm b/code/modules/client/preferences.dm index 630ed4efaa2..5d35c8763cd 100644 --- a/code/modules/client/preferences.dm +++ b/code/modules/client/preferences.dm @@ -457,10 +457,9 @@ var/list/preferences_datums = list() character.employer_faction = faction character.religion = religion character.accent = accent - character.origin = GET_SINGLETON(text2path(origin)) - character.culture = GET_SINGLETON(text2path(culture)) - character.origin.on_apply(character) - character.culture.on_apply(character) + character.set_culture(GET_SINGLETON(text2path(culture))) + character.set_origin(GET_SINGLETON(text2path(origin))) + // Destroy/cyborgize organs & setup body markings character.sync_organ_prefs_to_mob(src) diff --git a/code/modules/ghostroles/spawner/human/human.dm b/code/modules/ghostroles/spawner/human/human.dm index 7fa32c575b0..75601a9c611 100644 --- a/code/modules/ghostroles/spawner/human/human.dm +++ b/code/modules/ghostroles/spawner/human/human.dm @@ -156,14 +156,14 @@ for(var/culture in culture_restriction) var/singleton/origin_item/culture/CL = GET_SINGLETON(culture) if(CL.type in M.species.possible_cultures) - M.culture = CL + M.set_culture(CL) break for(var/origin in M.culture.possible_origins) var/singleton/origin_item/origin/OI = GET_SINGLETON(origin) if(length(origin_restriction)) if(!(OI.type in origin_restriction)) continue - M.origin = OI + M.set_origin(OI) M.accent = pick(OI.possible_accents) break diff --git a/code/modules/mob/abstract/new_player/preferences_setup.dm b/code/modules/mob/abstract/new_player/preferences_setup.dm index 5ac652cf0f3..47c9dce0d6f 100644 --- a/code/modules/mob/abstract/new_player/preferences_setup.dm +++ b/code/modules/mob/abstract/new_player/preferences_setup.dm @@ -26,11 +26,11 @@ pda_choice = 2 age = rand(getMinAge(),getMaxAge()) if(length(culture_restriction)) - H.culture = GET_SINGLETON(pick(culture_restriction)) + H.set_culture(GET_SINGLETON(pick(culture_restriction))) if(length(origin_restriction)) for(var/O in origin_restriction) if(O in culture_restriction) - H.origin = GET_SINGLETON(O) + H.set_origin(GET_SINGLETON(O)) break if(!H.origin) crash_with("Invalid origin restrictions [english_list(origin_restriction)] for culture restrictions [english_list(culture_restriction)]!") diff --git a/code/modules/mob/living/carbon/human/human.dm b/code/modules/mob/living/carbon/human/human.dm index 4332019e5b8..cba73950c42 100644 --- a/code/modules/mob/living/carbon/human/human.dm +++ b/code/modules/mob/living/carbon/human/human.dm @@ -24,7 +24,7 @@ if(!species) if(new_species) - set_species(new_species,1) + set_species(new_species, 1) else set_species() @@ -1481,10 +1481,21 @@ if(typing_indicator) adjust_typing_indicator_offsets(typing_indicator) - fill_out_culture_data() - if(change_hair) - species.set_default_hair(src) + h_style = random_hair_style(gender, species.type) + + if(prob(10)) + f_style = random_facial_hair_style(gender, species.type) + + if(length(species.character_color_presets) && !default_colour) + var/preset_name = pick(species.character_color_presets) + var/preset_colour = species.character_color_presets[preset_name] + r_skin = GetRedPart(preset_colour) + g_skin = GetGreenPart(preset_colour) + b_skin = GetBluePart(preset_colour) + change_skin_tone(35 - rand(30, 220)) + + fill_random_culture_data() species.set_default_tail(src) @@ -1505,12 +1516,23 @@ /mob/living/carbon/human/proc/fill_out_culture_data() - culture = GET_SINGLETON(species.possible_cultures[1]) - origin = GET_SINGLETON(culture.possible_origins[1]) + set_culture(GET_SINGLETON(species.possible_cultures[1])) + set_origin(GET_SINGLETON(culture.possible_origins[1])) accent = pick(origin.possible_accents) citizenship = origin.possible_citizenships[1] religion = origin.possible_religions[1] +/mob/living/carbon/human/proc/fill_random_culture_data() + var/new_culture_type = pick(species.possible_cultures) + var/culture_singleton = GET_SINGLETON(new_culture_type) + set_culture(culture_singleton) + var/new_origin = pick(culture.possible_origins) + var/origin_singleton = GET_SINGLETON(new_origin) + set_origin(origin_singleton) + accent = pick(origin.possible_accents) + citizenship = pick(origin.possible_citizenships) + religion = pick(origin.possible_religions) + /mob/living/carbon/human/proc/bloody_doodle() set category = "IC" set name = "Write in blood" diff --git a/code/modules/mob/living/carbon/slime/items.dm b/code/modules/mob/living/carbon/slime/items.dm index 9bd71502b8a..a49c39cb98c 100644 --- a/code/modules/mob/living/carbon/slime/items.dm +++ b/code/modules/mob/living/carbon/slime/items.dm @@ -321,8 +321,8 @@ G.set_species(golem_type) G.name = G.species.get_random_name() G.real_name = G.name - G.culture = GET_SINGLETON(/singleton/origin_item/culture/golem) - G.origin = GET_SINGLETON(/singleton/origin_item/origin/golem) + G.set_culture(GET_SINGLETON(/singleton/origin_item/culture/golem)) + G.set_origin(GET_SINGLETON(/singleton/origin_item/origin/golem)) G.accent = G.origin.possible_accents[1] G.citizenship = G.origin.possible_citizenships[1] G.religion = G.origin.possible_religions[1] diff --git a/code/modules/nano/modules/human_appearance.dm b/code/modules/nano/modules/human_appearance.dm index fe67ec09e3b..57f696513f6 100644 --- a/code/modules/nano/modules/human_appearance.dm +++ b/code/modules/nano/modules/human_appearance.dm @@ -142,10 +142,9 @@ var/new_culture_id = params["culture"] if(new_culture_id in valid_cultures) var/singleton/origin_item/culture/new_culture = culture_map[new_culture_id] - owner.culture = new_culture - owner.culture.on_apply(owner) + owner.set_culture(new_culture) if(!(owner.origin in new_culture.possible_origins)) - owner.origin = GET_SINGLETON(pick(new_culture.possible_origins)) + owner.set_origin(GET_SINGLETON(pick(new_culture.possible_origins))) clear_and_generate_data() . = TRUE if("origin") @@ -153,8 +152,7 @@ var/new_origin_id = params["origin"] if(new_origin_id in valid_origins) var/singleton/origin_item/origin/new_origin = origin_map[new_origin_id] - owner.origin = new_origin - owner.origin.on_apply(owner) + owner.set_origin(new_origin) if(!(owner.accent in new_origin.possible_accents)) owner.accent = new_origin.possible_accents[1] if(!(owner.religion in new_origin.possible_religions)) diff --git a/code/modules/reagents/reagent_containers/glass/bottle.dm b/code/modules/reagents/reagent_containers/glass/bottle.dm index e51b5096cff..6d4b7838264 100644 --- a/code/modules/reagents/reagent_containers/glass/bottle.dm +++ b/code/modules/reagents/reagent_containers/glass/bottle.dm @@ -227,6 +227,12 @@ icon_state = "bottle-4" reagents_to_add = list(/singleton/reagent/hyronalin = 60) +/obj/item/reagent_containers/glass/bottle/trioxin + name = "trioxin bottle" + desc = "A small bottle. Contains a swirling, green liquid." + icon_state = "bottle-1" + reagents_to_add = list(/singleton/reagent/toxin/trioxin = 60) + //syrups /obj/item/reagent_containers/glass/bottle/syrup diff --git a/html/changelogs/mattatlas-admingoodies.yml b/html/changelogs/mattatlas-admingoodies.yml new file mode 100644 index 00000000000..30ee94cd5a3 --- /dev/null +++ b/html/changelogs/mattatlas-admingoodies.yml @@ -0,0 +1,45 @@ +################################ +# Example Changelog File +# +# Note: This file, and files beginning with ".", and files that don't end in ".yml" will not be read. If you change this file, you will look really dumb. +# +# Your changelog will be merged with a master changelog. (New stuff added only, and only on the date entry for the day it was merged.) +# When it is, any changes listed below will disappear. +# +# Valid Prefixes: +# bugfix +# wip (For works in progress) +# tweak +# soundadd +# sounddel +# rscadd (general adding of nice things) +# rscdel (general deleting of nice things) +# imageadd +# imagedel +# maptweak +# spellcheck (typo fixes) +# experiment +# balance +# admin +# backend +# security +# refactor +################################# + +# Your name. +author: MattAtlas + +# Optional: Remove this file after generating master changelog. Useful for PR changelogs that won't get used again. +delete-after: True + +# Any changes you've made. See valid prefix list above. +# INDENT WITH TWO SPACES. NOT TABS. SPACES. +# SCREW THIS UP AND IT WON'T WORK. +# Also, all entries are changed into a single [] after a master changelog generation. Just remove the brackets when you add new entries. +# Please surround your changes in double quotes ("), as certain characters otherwise screws up compiling. The quotes will not show up in the changelog. +changes: + - rscadd: "Human mobs will now have random appearances, cultures, origins and accents when spawning." + - rscadd: "The Notes verb will now show your culture data." + - bugfix: "Fixed a DNA runtime." + - rscadd: "Added a portal subtype that doesn't run out for admins to use." + - rscadd: "Added a trioxin bottle that can be spawned."