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