diff --git a/code/__DEFINES/misc.dm b/code/__DEFINES/misc.dm
index 11b0396cbd..c5d917ece4 100644
--- a/code/__DEFINES/misc.dm
+++ b/code/__DEFINES/misc.dm
@@ -456,3 +456,7 @@ GLOBAL_LIST_INIT(ghost_others_options, list(GHOST_OTHERS_SIMPLE, GHOST_OTHERS_DE
#define SECURITY_SAFE 1
#define SECURITY_ULTRASAFE 2
#define SECURITY_TRUSTED 3
+
+//Dummy mob reserve slots
+#define DUMMY_HUMAN_SLOT_PREFERENCES "dummy_preference_preview"
+#define DUMMY_HUMAN_SLOT_MANIFEST "dummy_manifest_generation"
diff --git a/code/__HELPERS/icons.dm b/code/__HELPERS/icons.dm
index 9b16644b4c..91bf127ab8 100644
--- a/code/__HELPERS/icons.dm
+++ b/code/__HELPERS/icons.dm
@@ -926,10 +926,10 @@ GLOBAL_LIST_EMPTY(friendly_animal_types)
return 0
//For creating consistent icons for human looking simple animals
-/proc/get_flat_human_icon(icon_id, datum/job/J, datum/preferences/prefs)
+/proc/get_flat_human_icon(icon_id, datum/job/J, datum/preferences/prefs, dummy_key)
var/static/list/humanoid_icon_cache = list()
if(!icon_id || !humanoid_icon_cache[icon_id])
- var/mob/living/carbon/human/dummy/body = new()
+ var/mob/living/carbon/human/dummy/body = generate_or_wait_for_human_dummy(dummy_key)
if(prefs)
prefs.copy_to(body)
@@ -956,14 +956,12 @@ GLOBAL_LIST_EMPTY(friendly_animal_types)
partial = getFlatIcon(body)
out_icon.Insert(partial,dir=EAST)
- qdel(body)
-
humanoid_icon_cache[icon_id] = out_icon
+ dummy_key? unset_busy_human_dummy(dummy_key) : qdel(body)
return out_icon
else
return humanoid_icon_cache[icon_id]
-
//Hook, override to run code on- wait this is images
//Images have dir without being an atom, so they get their own definition.
//Lame.
diff --git a/code/controllers/subsystem/ticker.dm b/code/controllers/subsystem/ticker.dm
index 9f2a03437e..2c41985678 100755
--- a/code/controllers/subsystem/ticker.dm
+++ b/code/controllers/subsystem/ticker.dm
@@ -243,10 +243,10 @@ SUBSYSTEM_DEF(ticker)
PostSetup()
- return 1
+ return TRUE
/datum/controller/subsystem/ticker/proc/PostSetup()
- set waitfor = 0
+ set waitfor = FALSE
mode.post_setup()
GLOB.start_state = new /datum/station_state()
GLOB.start_state.count(1)
diff --git a/code/datums/datacore.dm b/code/datums/datacore.dm
index 005c02c355..b20381ca85 100644
--- a/code/datums/datacore.dm
+++ b/code/datums/datacore.dm
@@ -1,287 +1,287 @@
-
-/datum/datacore
- var/medical[] = list()
- var/medicalPrintCount = 0
- var/general[] = list()
- var/security[] = list()
- var/securityPrintCount = 0
- var/securityCrimeCounter = 0
- //This list tracks characters spawned in the world and cannot be modified in-game. Currently referenced by respawn_character().
- var/locked[] = list()
-
-/datum/data
- var/name = "data"
-
-/datum/data/record
- name = "record"
- var/list/fields = list()
-
-/datum/data/record/Destroy()
- if(src in GLOB.data_core.medical)
- GLOB.data_core.medical -= src
- if(src in GLOB.data_core.security)
- GLOB.data_core.security -= src
- if(src in GLOB.data_core.general)
- GLOB.data_core.general -= src
- if(src in GLOB.data_core.locked)
- GLOB.data_core.locked -= src
- . = ..()
-
-/datum/data/crime
- name = "crime"
- var/crimeName = ""
- var/crimeDetails = ""
- var/author = ""
- var/time = ""
- var/dataId = 0
-
-/datum/datacore/proc/createCrimeEntry(cname = "", cdetails = "", author = "", time = "")
- var/datum/data/crime/c = new /datum/data/crime
- c.crimeName = cname
- c.crimeDetails = cdetails
- c.author = author
- c.time = time
- c.dataId = ++securityCrimeCounter
- return c
-
-/datum/datacore/proc/addMinorCrime(id = "", datum/data/crime/crime)
- for(var/datum/data/record/R in security)
- if(R.fields["id"] == id)
- var/list/crimes = R.fields["mi_crim"]
- crimes |= crime
- return
-
-/datum/datacore/proc/removeMinorCrime(id, cDataId)
- for(var/datum/data/record/R in security)
- if(R.fields["id"] == id)
- var/list/crimes = R.fields["mi_crim"]
- for(var/datum/data/crime/crime in crimes)
- if(crime.dataId == text2num(cDataId))
- crimes -= crime
- return
-
-/datum/datacore/proc/removeMajorCrime(id, cDataId)
- for(var/datum/data/record/R in security)
- if(R.fields["id"] == id)
- var/list/crimes = R.fields["ma_crim"]
- for(var/datum/data/crime/crime in crimes)
- if(crime.dataId == text2num(cDataId))
- crimes -= crime
- return
-
-/datum/datacore/proc/addMajorCrime(id = "", datum/data/crime/crime)
- for(var/datum/data/record/R in security)
- if(R.fields["id"] == id)
- var/list/crimes = R.fields["ma_crim"]
- crimes |= crime
- return
-
-/datum/datacore/proc/manifest()
- for(var/mob/dead/new_player/N in GLOB.player_list)
- if(ishuman(N.new_character))
- manifest_inject(N.new_character, N.client)
- CHECK_TICK
-
-/datum/datacore/proc/manifest_modify(name, assignment)
- var/datum/data/record/foundrecord = find_record("name", name, GLOB.data_core.general)
- if(foundrecord)
- foundrecord.fields["rank"] = assignment
-
-/datum/datacore/proc/get_manifest(monochrome, OOC)
- var/list/heads = list()
- var/list/sec = list()
- var/list/eng = list()
- var/list/med = list()
- var/list/sci = list()
- var/list/sup = list()
- var/list/civ = list()
- var/list/bot = list()
- var/list/misc = list()
- var/dat = {"
-
-
- | Name | Rank |
- "}
- var/even = 0
- // sort mobs
- for(var/datum/data/record/t in GLOB.data_core.general)
- var/name = t.fields["name"]
- var/rank = t.fields["rank"]
- var/department = 0
- if(rank in GLOB.command_positions)
- heads[name] = rank
- department = 1
- if(rank in GLOB.security_positions)
- sec[name] = rank
- department = 1
- if(rank in GLOB.engineering_positions)
- eng[name] = rank
- department = 1
- if(rank in GLOB.medical_positions)
- med[name] = rank
- department = 1
- if(rank in GLOB.science_positions)
- sci[name] = rank
- department = 1
- if(rank in GLOB.supply_positions)
- sup[name] = rank
- department = 1
- if(rank in GLOB.civilian_positions)
- civ[name] = rank
- department = 1
- if(rank in GLOB.nonhuman_positions)
- bot[name] = rank
- department = 1
- if(!department && !(name in heads))
- misc[name] = rank
- if(heads.len > 0)
- dat += "| Heads |
"
- for(var/name in heads)
- dat += "| [name] | [heads[name]] |
"
- even = !even
- if(sec.len > 0)
- dat += "| Security |
"
- for(var/name in sec)
- dat += "| [name] | [sec[name]] |
"
- even = !even
- if(eng.len > 0)
- dat += "| Engineering |
"
- for(var/name in eng)
- dat += "| [name] | [eng[name]] |
"
- even = !even
- if(med.len > 0)
- dat += "| Medical |
"
- for(var/name in med)
- dat += "| [name] | [med[name]] |
"
- even = !even
- if(sci.len > 0)
- dat += "| Science |
"
- for(var/name in sci)
- dat += "| [name] | [sci[name]] |
"
- even = !even
- if(sup.len > 0)
- dat += "| Supply |
"
- for(var/name in sup)
- dat += "| [name] | [sup[name]] |
"
- even = !even
- if(civ.len > 0)
- dat += "| Civilian |
"
- for(var/name in civ)
- dat += "| [name] | [civ[name]] |
"
- even = !even
- // in case somebody is insane and added them to the manifest, why not
- if(bot.len > 0)
- dat += "| Silicon |
"
- for(var/name in bot)
- dat += "| [name] | [bot[name]] |
"
- even = !even
- // misc guys
- if(misc.len > 0)
- dat += "| Miscellaneous |
"
- for(var/name in misc)
- dat += "| [name] | [misc[name]] |
"
- even = !even
-
- dat += "
"
- dat = replacetext(dat, "\n", "")
- dat = replacetext(dat, "\t", "")
- return dat
-
-
-/datum/datacore/proc/manifest_inject(mob/living/carbon/human/H, client/C)
- if(H.mind && (H.mind.assigned_role != H.mind.special_role))
- var/assignment
- if(H.mind.assigned_role)
- assignment = H.mind.assigned_role
- else if(H.job)
- assignment = H.job
- else
- assignment = "Unassigned"
-
- var/static/record_id_num = 1001
- var/id = num2hex(record_id_num++,6)
- if(!C)
- C = H.client
- var/image = get_id_photo(H, C)
- var/obj/item/photo/photo_front = new()
- var/obj/item/photo/photo_side = new()
- photo_front.photocreate(null, icon(image, dir = SOUTH))
- photo_side.photocreate(null, icon(image, dir = WEST))
-
- //These records should ~really~ be merged or something
- //General Record
- var/datum/data/record/G = new()
- G.fields["id"] = id
- G.fields["name"] = H.real_name
- G.fields["rank"] = assignment
- G.fields["age"] = H.age
- if(config.mutant_races)
- G.fields["species"] = H.dna.species.name
- G.fields["fingerprint"] = md5(H.dna.uni_identity)
- G.fields["p_stat"] = "Active"
- G.fields["m_stat"] = "Stable"
- G.fields["sex"] = H.gender
- G.fields["photo_front"] = photo_front
- G.fields["photo_side"] = photo_side
- general += G
-
- //Medical Record
- var/datum/data/record/M = new()
- M.fields["id"] = id
- M.fields["name"] = H.real_name
- M.fields["blood_type"] = H.dna.blood_type
- M.fields["b_dna"] = H.dna.unique_enzymes
- M.fields["mi_dis"] = "None"
- M.fields["mi_dis_d"] = "No minor disabilities have been declared."
- M.fields["ma_dis"] = "None"
- M.fields["ma_dis_d"] = "No major disabilities have been diagnosed."
- M.fields["alg"] = "None"
- M.fields["alg_d"] = "No allergies have been detected in this patient."
- M.fields["cdi"] = "None"
- M.fields["cdi_d"] = "No diseases have been diagnosed at the moment."
- M.fields["notes"] = "No notes."
- medical += M
-
- //Security Record
- var/datum/data/record/S = new()
- S.fields["id"] = id
- S.fields["name"] = H.real_name
- S.fields["criminal"] = "None"
- S.fields["mi_crim"] = list()
- S.fields["ma_crim"] = list()
- S.fields["notes"] = "No notes."
- security += S
-
- //Locked Record
- var/datum/data/record/L = new()
- L.fields["id"] = md5("[H.real_name][H.mind.assigned_role]") //surely this should just be id, like the others?
- L.fields["name"] = H.real_name
- L.fields["rank"] = H.mind.assigned_role
- L.fields["age"] = H.age
- L.fields["sex"] = H.gender
- L.fields["blood_type"] = H.dna.blood_type
- L.fields["b_dna"] = H.dna.unique_enzymes
- L.fields["enzymes"] = H.dna.struc_enzymes
- L.fields["identity"] = H.dna.uni_identity
- L.fields["species"] = H.dna.species.type
- L.fields["features"] = H.dna.features
- L.fields["image"] = image
- L.fields["reference"] = H
- locked += L
- return
-
-/datum/datacore/proc/get_id_photo(mob/living/carbon/human/H, client/C)
- var/datum/job/J = SSjob.GetJob(H.mind.assigned_role)
- var/datum/preferences/P
- if(!C)
- C = H.client
- if(C)
- P = C.prefs
- return get_flat_human_icon(null, J, P)
+/datum/datacore
+ var/medical[] = list()
+ var/medicalPrintCount = 0
+ var/general[] = list()
+ var/security[] = list()
+ var/securityPrintCount = 0
+ var/securityCrimeCounter = 0
+ //This list tracks characters spawned in the world and cannot be modified in-game. Currently referenced by respawn_character().
+ var/locked[] = list()
+
+/datum/data
+ var/name = "data"
+
+/datum/data/record
+ name = "record"
+ var/list/fields = list()
+
+/datum/data/record/Destroy()
+ if(src in GLOB.data_core.medical)
+ GLOB.data_core.medical -= src
+ if(src in GLOB.data_core.security)
+ GLOB.data_core.security -= src
+ if(src in GLOB.data_core.general)
+ GLOB.data_core.general -= src
+ if(src in GLOB.data_core.locked)
+ GLOB.data_core.locked -= src
+ . = ..()
+
+/datum/data/crime
+ name = "crime"
+ var/crimeName = ""
+ var/crimeDetails = ""
+ var/author = ""
+ var/time = ""
+ var/dataId = 0
+
+/datum/datacore/proc/createCrimeEntry(cname = "", cdetails = "", author = "", time = "")
+ var/datum/data/crime/c = new /datum/data/crime
+ c.crimeName = cname
+ c.crimeDetails = cdetails
+ c.author = author
+ c.time = time
+ c.dataId = ++securityCrimeCounter
+ return c
+
+/datum/datacore/proc/addMinorCrime(id = "", datum/data/crime/crime)
+ for(var/datum/data/record/R in security)
+ if(R.fields["id"] == id)
+ var/list/crimes = R.fields["mi_crim"]
+ crimes |= crime
+ return
+
+/datum/datacore/proc/removeMinorCrime(id, cDataId)
+ for(var/datum/data/record/R in security)
+ if(R.fields["id"] == id)
+ var/list/crimes = R.fields["mi_crim"]
+ for(var/datum/data/crime/crime in crimes)
+ if(crime.dataId == text2num(cDataId))
+ crimes -= crime
+ return
+
+/datum/datacore/proc/removeMajorCrime(id, cDataId)
+ for(var/datum/data/record/R in security)
+ if(R.fields["id"] == id)
+ var/list/crimes = R.fields["ma_crim"]
+ for(var/datum/data/crime/crime in crimes)
+ if(crime.dataId == text2num(cDataId))
+ crimes -= crime
+ return
+
+/datum/datacore/proc/addMajorCrime(id = "", datum/data/crime/crime)
+ for(var/datum/data/record/R in security)
+ if(R.fields["id"] == id)
+ var/list/crimes = R.fields["ma_crim"]
+ crimes |= crime
+ return
+
+/datum/datacore/proc/manifest()
+ for(var/mob/dead/new_player/N in GLOB.player_list)
+ if(ishuman(N.new_character))
+ manifest_inject(N.new_character, N.client)
+ CHECK_TICK
+
+/datum/datacore/proc/manifest_modify(name, assignment)
+ var/datum/data/record/foundrecord = find_record("name", name, GLOB.data_core.general)
+ if(foundrecord)
+ foundrecord.fields["rank"] = assignment
+
+/datum/datacore/proc/get_manifest(monochrome, OOC)
+ var/list/heads = list()
+ var/list/sec = list()
+ var/list/eng = list()
+ var/list/med = list()
+ var/list/sci = list()
+ var/list/sup = list()
+ var/list/civ = list()
+ var/list/bot = list()
+ var/list/misc = list()
+ var/dat = {"
+
+
+ | Name | Rank |
+ "}
+ var/even = 0
+ // sort mobs
+ for(var/datum/data/record/t in GLOB.data_core.general)
+ var/name = t.fields["name"]
+ var/rank = t.fields["rank"]
+ var/department = 0
+ if(rank in GLOB.command_positions)
+ heads[name] = rank
+ department = 1
+ if(rank in GLOB.security_positions)
+ sec[name] = rank
+ department = 1
+ if(rank in GLOB.engineering_positions)
+ eng[name] = rank
+ department = 1
+ if(rank in GLOB.medical_positions)
+ med[name] = rank
+ department = 1
+ if(rank in GLOB.science_positions)
+ sci[name] = rank
+ department = 1
+ if(rank in GLOB.supply_positions)
+ sup[name] = rank
+ department = 1
+ if(rank in GLOB.civilian_positions)
+ civ[name] = rank
+ department = 1
+ if(rank in GLOB.nonhuman_positions)
+ bot[name] = rank
+ department = 1
+ if(!department && !(name in heads))
+ misc[name] = rank
+ if(heads.len > 0)
+ dat += "| Heads |
"
+ for(var/name in heads)
+ dat += "| [name] | [heads[name]] |
"
+ even = !even
+ if(sec.len > 0)
+ dat += "| Security |
"
+ for(var/name in sec)
+ dat += "| [name] | [sec[name]] |
"
+ even = !even
+ if(eng.len > 0)
+ dat += "| Engineering |
"
+ for(var/name in eng)
+ dat += "| [name] | [eng[name]] |
"
+ even = !even
+ if(med.len > 0)
+ dat += "| Medical |
"
+ for(var/name in med)
+ dat += "| [name] | [med[name]] |
"
+ even = !even
+ if(sci.len > 0)
+ dat += "| Science |
"
+ for(var/name in sci)
+ dat += "| [name] | [sci[name]] |
"
+ even = !even
+ if(sup.len > 0)
+ dat += "| Supply |
"
+ for(var/name in sup)
+ dat += "| [name] | [sup[name]] |
"
+ even = !even
+ if(civ.len > 0)
+ dat += "| Civilian |
"
+ for(var/name in civ)
+ dat += "| [name] | [civ[name]] |
"
+ even = !even
+ // in case somebody is insane and added them to the manifest, why not
+ if(bot.len > 0)
+ dat += "| Silicon |
"
+ for(var/name in bot)
+ dat += "| [name] | [bot[name]] |
"
+ even = !even
+ // misc guys
+ if(misc.len > 0)
+ dat += "| Miscellaneous |
"
+ for(var/name in misc)
+ dat += "| [name] | [misc[name]] |
"
+ even = !even
+
+ dat += "
"
+ dat = replacetext(dat, "\n", "")
+ dat = replacetext(dat, "\t", "")
+ return dat
+
+
+/datum/datacore/proc/manifest_inject(mob/living/carbon/human/H, client/C)
+ set waitfor = FALSE
+ if(H.mind && (H.mind.assigned_role != H.mind.special_role))
+ var/assignment
+ if(H.mind.assigned_role)
+ assignment = H.mind.assigned_role
+ else if(H.job)
+ assignment = H.job
+ else
+ assignment = "Unassigned"
+
+ var/static/record_id_num = 1001
+ var/id = num2hex(record_id_num++,6)
+ if(!C)
+ C = H.client
+ var/image = get_id_photo(H, C)
+ var/obj/item/photo/photo_front = new()
+ var/obj/item/photo/photo_side = new()
+ photo_front.photocreate(null, icon(image, dir = SOUTH))
+ photo_side.photocreate(null, icon(image, dir = WEST))
+
+ //These records should ~really~ be merged or something
+ //General Record
+ var/datum/data/record/G = new()
+ G.fields["id"] = id
+ G.fields["name"] = H.real_name
+ G.fields["rank"] = assignment
+ G.fields["age"] = H.age
+ if(config.mutant_races)
+ G.fields["species"] = H.dna.species.name
+ G.fields["fingerprint"] = md5(H.dna.uni_identity)
+ G.fields["p_stat"] = "Active"
+ G.fields["m_stat"] = "Stable"
+ G.fields["sex"] = H.gender
+ G.fields["photo_front"] = photo_front
+ G.fields["photo_side"] = photo_side
+ general += G
+
+ //Medical Record
+ var/datum/data/record/M = new()
+ M.fields["id"] = id
+ M.fields["name"] = H.real_name
+ M.fields["blood_type"] = H.dna.blood_type
+ M.fields["b_dna"] = H.dna.unique_enzymes
+ M.fields["mi_dis"] = "None"
+ M.fields["mi_dis_d"] = "No minor disabilities have been declared."
+ M.fields["ma_dis"] = "None"
+ M.fields["ma_dis_d"] = "No major disabilities have been diagnosed."
+ M.fields["alg"] = "None"
+ M.fields["alg_d"] = "No allergies have been detected in this patient."
+ M.fields["cdi"] = "None"
+ M.fields["cdi_d"] = "No diseases have been diagnosed at the moment."
+ M.fields["notes"] = "No notes."
+ medical += M
+
+ //Security Record
+ var/datum/data/record/S = new()
+ S.fields["id"] = id
+ S.fields["name"] = H.real_name
+ S.fields["criminal"] = "None"
+ S.fields["mi_crim"] = list()
+ S.fields["ma_crim"] = list()
+ S.fields["notes"] = "No notes."
+ security += S
+
+ //Locked Record
+ var/datum/data/record/L = new()
+ L.fields["id"] = md5("[H.real_name][H.mind.assigned_role]") //surely this should just be id, like the others?
+ L.fields["name"] = H.real_name
+ L.fields["rank"] = H.mind.assigned_role
+ L.fields["age"] = H.age
+ L.fields["sex"] = H.gender
+ L.fields["blood_type"] = H.dna.blood_type
+ L.fields["b_dna"] = H.dna.unique_enzymes
+ L.fields["enzymes"] = H.dna.struc_enzymes
+ L.fields["identity"] = H.dna.uni_identity
+ L.fields["species"] = H.dna.species.type
+ L.fields["features"] = H.dna.features
+ L.fields["image"] = image
+ L.fields["mindref"] = H.mind
+ locked += L
+ return
+
+/datum/datacore/proc/get_id_photo(mob/living/carbon/human/H, client/C)
+ var/datum/job/J = SSjob.GetJob(H.mind.assigned_role)
+ var/datum/preferences/P
+ if(!C)
+ C = H.client
+ if(C)
+ P = C.prefs
+ return get_flat_human_icon(null, J, P, DUMMY_HUMAN_SLOT_MANIFEST)
diff --git a/code/modules/mob/dead/new_player/preferences_setup.dm b/code/modules/mob/dead/new_player/preferences_setup.dm
index 4810b666e7..33f04d33b9 100644
--- a/code/modules/mob/dead/new_player/preferences_setup.dm
+++ b/code/modules/mob/dead/new_player/preferences_setup.dm
@@ -1,100 +1,84 @@
-
- //The mob should have a gender you want before running this proc. Will run fine without H
-/datum/preferences/proc/random_character(gender_override)
- if(gender_override)
- gender = gender_override
- else
- gender = pick(MALE,FEMALE)
- skin_tone = random_skin_tone()
- hair_style = random_hair_style(gender)
- facial_hair_style = random_facial_hair_style(gender)
- hair_color = random_short_color()
- facial_hair_color = hair_color
- eye_color = random_eye_color()
- if(!pref_species)
- var/rando_race = pick(config.roundstart_races)
- pref_species = new rando_race()
- features = random_features()
- age = rand(AGE_MIN,AGE_MAX)
-
-/datum/preferences/proc/update_preview_icon(nude = 0)
- var/wide_icon = 0
- var/stamp_x = 0
- var/stamp_y = 1
- if(features["taur"] != "None")
- wide_icon = 1
- // Silicons only need a very basic preview since there is no customization for them.
- if(job_engsec_high)
- switch(job_engsec_high)
- if(AI_JF)
- preview_icon = icon('icons/mob/AI.dmi', "AI", SOUTH)
- preview_icon.Scale(64, 64)
- return
- if(CYBORG)
- preview_icon = icon('icons/mob/robots.dmi', "robot", SOUTH)
- preview_icon.Scale(64, 64)
- return
-
- // Set up the dummy for its photoshoot
- var/mob/living/carbon/human/dummy/mannequin = new()
- copy_to(mannequin)
-
- // Determine what job is marked as 'High' priority, and dress them up as such.
- var/datum/job/previewJob
- var/highRankFlag = job_civilian_high | job_medsci_high | job_engsec_high
-
- if(job_civilian_low & ASSISTANT)
- previewJob = SSjob.GetJob("Assistant")
- else if(highRankFlag)
- var/highDeptFlag
- if(job_civilian_high)
- highDeptFlag = CIVILIAN
- else if(job_medsci_high)
- highDeptFlag = MEDSCI
- else if(job_engsec_high)
- highDeptFlag = ENGSEC
-
- for(var/datum/job/job in SSjob.occupations)
- if(job.flag == highRankFlag && job.department_flag == highDeptFlag)
- previewJob = job
- break
-
- if(previewJob && !nude)
- mannequin.job = previewJob.title
- previewJob.equip(mannequin, TRUE)
- mannequin.update_body()
- CHECK_TICK
- preview_icon = icon('icons/effects/effects.dmi', "nothing")
- preview_icon.Scale((112), (32))
- CHECK_TICK
- mannequin.setDir(NORTH)
-
- var/icon/stamp = getFlatIcon(mannequin)
- CHECK_TICK
- if(wide_icon)
- stamp_x = 16
- else
- stamp_x = 32
- preview_icon.Blend(stamp, ICON_OVERLAY, stamp_x, stamp_y)
- CHECK_TICK
- mannequin.setDir(WEST)
- stamp = getFlatIcon(mannequin)
- CHECK_TICK
- if(wide_icon)
- stamp_x = 48
- else
- stamp_x = 64
- preview_icon.Blend(stamp, ICON_OVERLAY, stamp_x, stamp_y)
- CHECK_TICK
- mannequin.setDir(SOUTH)
- stamp = getFlatIcon(mannequin)
- CHECK_TICK
- if(wide_icon)
- stamp_x = -15
- else
- stamp_x = 1
- preview_icon.Blend(stamp, ICON_OVERLAY, stamp_x, stamp_y)
- CHECK_TICK
- preview_icon.Scale(preview_icon.Width() * 2, preview_icon.Height() * 2) // Scaling here to prevent blurring in the browser.
- CHECK_TICK
- qdel(mannequin)
\ No newline at end of file
+//The mob should have a gender you want before running this proc. Will run fine without H
+/datum/preferences/proc/random_character(gender_override)
+ if(gender_override)
+ gender = gender_override
+ else
+ gender = pick(MALE,FEMALE)
+ underwear = random_underwear(gender)
+ undershirt = random_undershirt(gender)
+ socks = random_socks()
+ skin_tone = random_skin_tone()
+ hair_style = random_hair_style(gender)
+ facial_hair_style = random_facial_hair_style(gender)
+ hair_color = random_short_color()
+ facial_hair_color = hair_color
+ eye_color = random_eye_color()
+ if(!pref_species)
+ var/rando_race = pick(config.roundstart_races)
+ pref_species = new rando_race()
+ features = random_features()
+ age = rand(AGE_MIN,AGE_MAX)
+
+/datum/preferences/proc/update_preview_icon()
+ // Silicons only need a very basic preview since there is no customization for them.
+ if(job_engsec_high)
+ switch(job_engsec_high)
+ if(AI_JF)
+ preview_icon = icon('icons/mob/ai.dmi', "AI", SOUTH)
+ preview_icon.Scale(64, 64)
+ return
+ if(CYBORG)
+ preview_icon = icon('icons/mob/robots.dmi', "robot", SOUTH)
+ preview_icon.Scale(64, 64)
+ return
+
+ // Set up the dummy for its photoshoot
+ var/mob/living/carbon/human/dummy/mannequin = generate_or_wait_for_human_dummy(DUMMY_HUMAN_SLOT_PREFERENCES)
+ copy_to(mannequin)
+
+ // Determine what job is marked as 'High' priority, and dress them up as such.
+ var/datum/job/previewJob
+ var/highRankFlag = job_civilian_high | job_medsci_high | job_engsec_high
+
+ if(job_civilian_low & ASSISTANT)
+ previewJob = SSjob.GetJob("Assistant")
+ else if(highRankFlag)
+ var/highDeptFlag
+ if(job_civilian_high)
+ highDeptFlag = CIVILIAN
+ else if(job_medsci_high)
+ highDeptFlag = MEDSCI
+ else if(job_engsec_high)
+ highDeptFlag = ENGSEC
+
+ for(var/datum/job/job in SSjob.occupations)
+ if(job.flag == highRankFlag && job.department_flag == highDeptFlag)
+ previewJob = job
+ break
+
+ if(previewJob)
+ mannequin.job = previewJob.title
+ previewJob.equip(mannequin, TRUE)
+ CHECK_TICK
+ preview_icon = icon('icons/effects/effects.dmi', "nothing")
+ preview_icon.Scale(48+32, 16+32)
+ CHECK_TICK
+ mannequin.setDir(NORTH)
+
+ var/icon/stamp = getFlatIcon(mannequin)
+ CHECK_TICK
+ preview_icon.Blend(stamp, ICON_OVERLAY, 25, 17)
+ CHECK_TICK
+ mannequin.setDir(WEST)
+ stamp = getFlatIcon(mannequin)
+ CHECK_TICK
+ preview_icon.Blend(stamp, ICON_OVERLAY, 1, 9)
+ CHECK_TICK
+ mannequin.setDir(SOUTH)
+ stamp = getFlatIcon(mannequin)
+ CHECK_TICK
+ preview_icon.Blend(stamp, ICON_OVERLAY, 49, 1)
+ CHECK_TICK
+ preview_icon.Scale(preview_icon.Width() * 2, preview_icon.Height() * 2) // Scaling here to prevent blurring in the browser.
+ CHECK_TICK
+ unset_busy_human_dummy(DUMMY_HUMAN_SLOT_PREFERENCES)
diff --git a/code/modules/mob/living/carbon/human/dummy.dm b/code/modules/mob/living/carbon/human/dummy.dm
new file mode 100644
index 0000000000..0492a0b5e6
--- /dev/null
+++ b/code/modules/mob/living/carbon/human/dummy.dm
@@ -0,0 +1,43 @@
+
+/mob/living/carbon/human/dummy
+ real_name = "Test Dummy"
+ status_flags = GODMODE|CANPUSH
+ var/in_use = FALSE
+
+INITIALIZE_IMMEDIATE(/mob/living/carbon/human/dummy)
+
+/mob/living/carbon/human/dummy/Destroy()
+ in_use = FALSE
+ return ..()
+
+/mob/living/carbon/human/dummy/Life()
+ return
+
+/mob/living/carbon/human/dummy/proc/wipe_state()
+ QDEL_LIST(contents)
+ cut_overlays(TRUE)
+
+//Inefficient pooling/caching way.
+GLOBAL_LIST_EMPTY(human_dummy_list)
+
+/proc/generate_or_wait_for_human_dummy(slotkey)
+ if(!slotkey)
+ return new /mob/living/carbon/human/dummy
+ var/mob/living/carbon/human/dummy/D = GLOB.human_dummy_list[slotkey]
+ if(istype(D))
+ UNTIL(!D.in_use)
+ else
+ pass()
+ if(QDELETED(D))
+ D = new
+ GLOB.human_dummy_list[slotkey] = D
+ D.in_use = TRUE
+ return D
+
+/proc/unset_busy_human_dummy(slotnumber)
+ if(!slotnumber)
+ return
+ var/mob/living/carbon/human/dummy/D = GLOB.human_dummy_list[slotnumber]
+ if(istype(D))
+ D.wipe_state()
+ D.in_use = FALSE
diff --git a/code/modules/mob/living/carbon/human/human.dm b/code/modules/mob/living/carbon/human/human.dm
index 0fd685e77c..58b0c673a7 100644
--- a/code/modules/mob/living/carbon/human/human.dm
+++ b/code/modules/mob/living/carbon/human/human.dm
@@ -5,15 +5,6 @@
icon = 'icons/mob/human.dmi'
icon_state = "caucasian_m"
-/mob/living/carbon/human/dummy
- real_name = "Test Dummy"
- status_flags = GODMODE|CANPUSH
-
-INITIALIZE_IMMEDIATE(/mob/living/carbon/human/dummy)
-
-/mob/living/carbon/human/dummy/Life()
- return
-
/mob/living/carbon/human/Initialize()
verbs += /mob/living/proc/mob_sleep
verbs += /mob/living/proc/lay_down
diff --git a/tgstation.dme b/tgstation.dme
index 1814739f42..c035d52d60 100755
--- a/tgstation.dme
+++ b/tgstation.dme
@@ -1641,6 +1641,7 @@
#include "code\modules\mob\living\carbon\alien\special\facehugger.dm"
#include "code\modules\mob\living\carbon\human\damage_procs.dm"
#include "code\modules\mob\living\carbon\human\death.dm"
+#include "code\modules\mob\living\carbon\human\dummy.dm"
#include "code\modules\mob\living\carbon\human\emote.dm"
#include "code\modules\mob\living\carbon\human\examine.dm"
#include "code\modules\mob\living\carbon\human\examine_vr.dm"