From fc09967ca8f3a187076800fafcdca868e3ca72e1 Mon Sep 17 00:00:00 2001 From: monster860 Date: Sun, 17 Apr 2016 17:14:46 -0400 Subject: [PATCH 001/343] telecomms concurrency fix --- code/game/machinery/telecomms/broadcaster.dm | 3 ++- .../game/objects/items/devices/radio/radio.dm | 9 ++++--- .../scripting/Implementations/Telecomms.dm | 27 ++++++++++++++++++- .../scripting/Implementations/_Logic.dm | 5 ---- 4 files changed, 34 insertions(+), 10 deletions(-) diff --git a/code/game/machinery/telecomms/broadcaster.dm b/code/game/machinery/telecomms/broadcaster.dm index 15b8b621b0c..5d6aa95b56f 100644 --- a/code/game/machinery/telecomms/broadcaster.dm +++ b/code/game/machinery/telecomms/broadcaster.dm @@ -621,7 +621,8 @@ var/message_delay = 0 // To make sure restarting the recentmessages list is kept //#### Sending the signal to all subspace receivers ####// for(var/obj/machinery/telecomms/receiver/R in telecomms_list) - R.receive_signal(signal) + spawn(0) + R.receive_signal(signal) if(do_sleep) sleep(rand(10,25)) diff --git a/code/game/objects/items/devices/radio/radio.dm b/code/game/objects/items/devices/radio/radio.dm index d2fe7d2b319..ab5782afcae 100644 --- a/code/game/objects/items/devices/radio/radio.dm +++ b/code/game/objects/items/devices/radio/radio.dm @@ -402,11 +402,13 @@ var/global/list/default_medbay_channels = list( //#### Sending the signal to all subspace receivers ####// for(var/obj/machinery/telecomms/receiver/R in telecomms_list) - R.receive_signal(signal) + spawn(0) + R.receive_signal(signal) // Allinone can act as receivers. for(var/obj/machinery/telecomms/allinone/R in telecomms_list) - R.receive_signal(signal) + spawn(0) + R.receive_signal(signal) // Receiving code can be located in Telecommunications.dm return signal.data["done"] && position.z in signal.data["level"] @@ -455,7 +457,8 @@ var/global/list/default_medbay_channels = list( signal.frequency = connection.frequency // Quick frequency set for(var/obj/machinery/telecomms/receiver/R in telecomms_list) - R.receive_signal(signal) + spawn(0) + R.receive_signal(signal) sleep(rand(10,25)) // wait a little... diff --git a/code/modules/scripting/Implementations/Telecomms.dm b/code/modules/scripting/Implementations/Telecomms.dm index e06a5f9a18d..a4dbfb8f127 100644 --- a/code/modules/scripting/Implementations/Telecomms.dm +++ b/code/modules/scripting/Implementations/Telecomms.dm @@ -60,6 +60,9 @@ return interpreter.container = src + + interpreter.CreateGlobalScope() // Reset the variables. + interpreter.curScope = interpreter.globalScope interpreter.SetVar("PI", 3.141592653) // value of pi interpreter.SetVar("E", 2.718281828) // value of e @@ -127,7 +130,7 @@ @param time: time to sleep in deciseconds (1/10th second) */ - interpreter.SetProc("sleep", /proc/delay) + interpreter.SetProc("sleep", "delay", signal, list("time")) /* -> Replaces a string with another string @@ -255,6 +258,28 @@ signal.data["reject"] = 1 /* -- Actual language proc code -- */ +/datum/signal/proc/delay(var/time) + var/obj/machinery/telecomms/server/S = data["server"] + var/datum/n_Interpreter/TCS_Interpreter/interpreter = S.Compiler.interpreter + // Backup the scope + var/datum/scope/globalScope = interpreter.globalScope + var/datum/scope/curScope = interpreter.curScope + var/list/scopes = interpreter.scopes.stack.Copy() + var/list/functions = interpreter.functions.stack.Copy() + var/datum/node/statement/FunctionDefinition/curFunction = interpreter.curFunction + var/status = interpreter.status + var/returnVal = interpreter.returnVal + // Sleep + sleep(time) + // Restore the scope + interpreter.returnVal = returnVal + interpreter.status = status + interpreter.curFunction = curFunction + interpreter.functions.stack = functions + interpreter.scopes.stack = scopes + interpreter.curScope = curScope + interpreter.globalScope = globalScope + /datum/signal/proc/mem(var/address, var/value) if(istext(address)) var/obj/machinery/telecomms/server/S = data["server"] diff --git a/code/modules/scripting/Implementations/_Logic.dm b/code/modules/scripting/Implementations/_Logic.dm index a97fc320e0e..43d75f8c75d 100644 --- a/code/modules/scripting/Implementations/_Logic.dm +++ b/code/modules/scripting/Implementations/_Logic.dm @@ -99,11 +99,6 @@ // --- Miscellaneous functions --- -// Clone of sleep() -/proc/delay(var/time) - //writepanic("[__FILE__].[__LINE__] (no type)([usr ? usr.ckey : ""]) \\/proc/delay() called tick#: [world.time]") - sleep(time) - // Clone of rand() /proc/rand_chance(var/low = 0, var/high) //writepanic("[__FILE__].[__LINE__] (no type)([usr ? usr.ckey : ""]) \\/proc/rand_chance() called tick#: [world.time]") From f95655419c410307b7593a9b76c9c985075dd801 Mon Sep 17 00:00:00 2001 From: KasparoVy Date: Sat, 30 Apr 2016 08:12:41 -0400 Subject: [PATCH 002/343] Refactors Hair so it's on the Head + Adds a Vox Hairstyle + Adjusts Vox Hairstyle Names for Consistency -- PASS 1 Also fixes a typo or two. TO DO: FULLY TEST AND SWEEP FOR BUGS, ERRORS AND RUNTIMES --- code/datums/datacore.dm | 19 +++--- .../datums/diseases/advance/symptoms/beard.dm | 13 ++-- .../diseases/advance/symptoms/shedding.dm | 11 ++-- code/game/dna/dna2.dm | 37 ++++++----- code/game/dna/dna2_helpers.dm | 25 +++---- code/game/dna/genes/vg_powers.dm | 25 +++---- code/game/gamemodes/blob/blobs/blob_mobs.dm | 3 +- code/game/gamemodes/heist/heist.dm | 5 +- code/game/gamemodes/nuclear/nuclear.dm | 18 ++--- code/game/objects/items/weapons/cosmetics.dm | 18 ++--- code/game/objects/items/weapons/scissors.dm | 22 +++---- code/game/response_team.dm | 17 ++--- code/modules/admin/verbs/one_click_antag.dm | 5 +- code/modules/client/preferences.dm | 31 +++++---- code/modules/clothing/head/misc_special.dm | 7 +- .../mob/living/carbon/human/appearance.dm | 62 ++++++++++-------- code/modules/mob/living/carbon/human/death.dm | 18 ++--- code/modules/mob/living/carbon/human/human.dm | 56 ++++++++++------ .../mob/living/carbon/human/human_defines.dm | 18 ----- .../mob/living/carbon/human/species/apollo.dm | 5 +- .../living/carbon/human/species/station.dm | 4 +- .../mob/living/carbon/human/update_icons.dm | 43 ++++++------ code/modules/mob/living/carbon/superheroes.dm | 5 +- .../mob/new_player/sprite_accessories.dm | 9 ++- code/modules/nano/modules/human_appearance.dm | 10 +-- code/modules/reagents/newchem/other.dm | 23 ++++--- code/modules/surgery/limb_reattach.dm | 6 +- code/modules/surgery/organs/organ_icon.dm | 29 ++++---- code/modules/surgery/organs/organ_internal.dm | 23 +++---- .../surgery/organs/subtypes/standard.dm | 18 +++++ icons/mob/human_face.dmi | Bin 71587 -> 71902 bytes 31 files changed, 322 insertions(+), 263 deletions(-) diff --git a/code/datums/datacore.dm b/code/datums/datacore.dm index a70875a7090..d07b6e3eb73 100644 --- a/code/datums/datacore.dm +++ b/code/datums/datacore.dm @@ -126,6 +126,7 @@ proc/get_id_photo(var/mob/living/carbon/human/H) var/icon/preview_icon = null + var/obj/item/organ/external/head/head_organ = H.get_organ("head") var/g = "m" if (H.gender == FEMALE) @@ -170,32 +171,32 @@ proc/get_id_photo(var/mob/living/carbon/human/H) eyes_s.Blend(rgb(H.r_eyes, H.g_eyes, H.b_eyes), ICON_ADD) face_s.Blend(eyes_s, ICON_OVERLAY) - var/datum/sprite_accessory/hair_style = hair_styles_list[H.h_style] + var/datum/sprite_accessory/hair_style = hair_styles_list[head_organ.h_style] if(hair_style) var/icon/hair_s = new/icon("icon" = hair_style.icon, "icon_state" = "[hair_style.icon_state]_s") // I'll want to make a species-specific proc for this sooner or later // But this'll do for now - if(H.get_species() == "Slime People") + if(head_organ.species.name == "Slime People") hair_s.Blend(rgb(H.r_skin, H.g_skin, H.b_skin, 160), ICON_ADD) else - hair_s.Blend(rgb(H.r_hair, H.g_hair, H.b_hair), ICON_ADD) + hair_s.Blend(rgb(head_organ.r_hair, head_organ.g_hair, head_organ.b_hair), ICON_ADD) face_s.Blend(hair_s, ICON_OVERLAY) //Head Accessory - if(H.species.bodyflags & HAS_HEAD_ACCESSORY) - var/datum/sprite_accessory/head_accessory_style = head_accessory_styles_list[H.ha_style] + if(head_organ.species.bodyflags & HAS_HEAD_ACCESSORY) + var/datum/sprite_accessory/head_accessory_style = head_accessory_styles_list[head_organ.ha_style] if(head_accessory_style && head_accessory_style.species_allowed) var/icon/head_accessory_s = new/icon("icon" = head_accessory_style.icon, "icon_state" = "[head_accessory_style.icon_state]_s") - head_accessory_s.Blend(rgb(H.r_headacc, H.g_headacc, H.b_headacc), ICON_ADD) + head_accessory_s.Blend(rgb(head_organ.r_headacc, head_organ.g_headacc, head_organ.b_headacc), ICON_ADD) face_s.Blend(head_accessory_s, ICON_OVERLAY) - var/datum/sprite_accessory/facial_hair_style = facial_hair_styles_list[H.f_style] + var/datum/sprite_accessory/facial_hair_style = facial_hair_styles_list[head_organ.f_style] if(facial_hair_style && facial_hair_style.species_allowed) var/icon/facial_s = new/icon("icon" = facial_hair_style.icon, "icon_state" = "[facial_hair_style.icon_state]_s") - if(H.get_species() == "Slime People") + if(head_organ.species.name == "Slime People") facial_s.Blend(rgb(H.r_skin, H.g_skin, H.b_skin, 160), ICON_ADD) else - facial_s.Blend(rgb(H.r_facial, H.g_facial, H.b_facial), ICON_ADD) + facial_s.Blend(rgb(head_organ.r_facial, head_organ.g_facial, head_organ.b_facial), ICON_ADD) face_s.Blend(facial_s, ICON_OVERLAY) //Markings diff --git a/code/datums/diseases/advance/symptoms/beard.dm b/code/datums/diseases/advance/symptoms/beard.dm index 1dda9b46f7f..b773d25cf9a 100644 --- a/code/datums/diseases/advance/symptoms/beard.dm +++ b/code/datums/diseases/advance/symptoms/beard.dm @@ -30,20 +30,21 @@ BONUS var/mob/living/M = A.affected_mob if(istype(M, /mob/living/carbon/human)) var/mob/living/carbon/human/H = M + var/obj/item/organ/external/head/head_organ = H.get_organ("head") switch(A.stage) if(1, 2) to_chat(H, "Your chin itches.") - if(H.f_style == "Shaved") - H.f_style = "Jensen Beard" + if(head_organ.f_style == "Shaved") + head_organ.f_style = "Jensen Beard" H.update_hair() if(3, 4) to_chat(H, "You feel tough.") - if(!(H.f_style == "Dwarf Beard") && !(H.f_style == "Very Long Beard") && !(H.f_style == "Full Beard")) - H.f_style = "Full Beard" + if(!(head_organ.f_style == "Dwarf Beard") && !(head_organ.f_style == "Very Long Beard") && !(head_organ.f_style == "Full Beard")) + head_organ.f_style = "Full Beard" H.update_hair() else to_chat(H, "You feel manly!") - if(!(H.f_style == "Dwarf Beard") && !(H.f_style == "Very Long Beard")) - H.f_style = pick("Dwarf Beard", "Very Long Beard") + if(!(head_organ.f_style == "Dwarf Beard") && !(head_organ.f_style == "Very Long Beard")) + head_organ.f_style = pick("Dwarf Beard", "Very Long Beard") H.update_hair() return \ No newline at end of file diff --git a/code/datums/diseases/advance/symptoms/shedding.dm b/code/datums/diseases/advance/symptoms/shedding.dm index f7f52984c0b..dd1fc5183a6 100644 --- a/code/datums/diseases/advance/symptoms/shedding.dm +++ b/code/datums/diseases/advance/symptoms/shedding.dm @@ -31,18 +31,19 @@ BONUS to_chat(M, "[pick("Your scalp itches.", "Your skin feels flakey.")]") if(istype(M, /mob/living/carbon/human)) var/mob/living/carbon/human/H = M + var/obj/item/organ/external/head/head_organ = H.get_organ("head") switch(A.stage) if(3, 4) - if(!(H.h_style == "Bald") && !(H.h_style == "Balding Hair")) + if(!(head_organ.h_style == "Bald") && !(head_organ.h_style == "Balding Hair")) to_chat(H, "Your hair starts to fall out in clumps...") spawn(50) - H.h_style = "Balding Hair" + head_organ.h_style = "Balding Hair" H.update_hair() if(5) - if(!(H.f_style == "Shaved") || !(H.h_style == "Bald")) + if(!(head_organ.f_style == "Shaved") || !(head_organ.h_style == "Bald")) to_chat(H, "Your hair starts to fall out in clumps...") spawn(50) - H.f_style = "Shaved" - H.h_style = "Bald" + head_organ.f_style = "Shaved" + head_organ.h_style = "Bald" H.update_hair() return \ No newline at end of file diff --git a/code/game/dna/dna2.dm b/code/game/dna/dna2.dm index a15170a3956..93d7cc473dc 100644 --- a/code/game/dna/dna2.dm +++ b/code/game/dna/dna2.dm @@ -133,19 +133,20 @@ var/global/list/bad_blocks[0] ResetUI(1) // Hair // FIXME: Species-specific defaults pls - if(!character.h_style) - character.h_style = "Skinhead" - var/hair = hair_styles_list.Find(character.h_style) + var/obj/item/organ/external/head/H = character.get_organ("head") + if(!H.h_style) + H.h_style = "Skinhead" + var/hair = hair_styles_list.Find(H.h_style) // Facial Hair - if(!character.f_style) - character.f_style = "Shaved" - var/beard = facial_hair_styles_list.Find(character.f_style) + if(!H.f_style) + H.f_style = "Shaved" + var/beard = facial_hair_styles_list.Find(H.f_style) // Head Accessory - if(!character.ha_style) - character.ha_style = "None" - var/headacc = head_accessory_styles_list.Find(character.ha_style) + if(!H.ha_style) + H.ha_style = "None" + var/headacc = head_accessory_styles_list.Find(H.ha_style) /*// Body Accessory if(!character.body_accessory) @@ -157,13 +158,13 @@ var/global/list/bad_blocks[0] character.m_style = "None" var/marks = marking_styles_list.Find(character.m_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, H.r_hair, 255, 1) + SetUIValueRange(DNA_UI_HAIR_G, H.g_hair, 255, 1) + SetUIValueRange(DNA_UI_HAIR_B, H.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, H.r_facial, 255, 1) + SetUIValueRange(DNA_UI_BEARD_G, H.g_facial, 255, 1) + SetUIValueRange(DNA_UI_BEARD_B, H.b_facial, 255, 1) SetUIValueRange(DNA_UI_EYES_R, character.r_eyes, 255, 1) SetUIValueRange(DNA_UI_EYES_G, character.g_eyes, 255, 1) @@ -173,9 +174,9 @@ var/global/list/bad_blocks[0] SetUIValueRange(DNA_UI_SKIN_G, character.g_skin, 255, 1) SetUIValueRange(DNA_UI_SKIN_B, character.b_skin, 255, 1) - SetUIValueRange(DNA_UI_HACC_R, character.r_headacc, 255, 1) - SetUIValueRange(DNA_UI_HACC_G, character.g_headacc, 255, 1) - SetUIValueRange(DNA_UI_HACC_B, character.b_headacc, 255, 1) + SetUIValueRange(DNA_UI_HACC_R, H.r_headacc, 255, 1) + SetUIValueRange(DNA_UI_HACC_G, H.g_headacc, 255, 1) + SetUIValueRange(DNA_UI_HACC_B, H.b_headacc, 255, 1) SetUIValueRange(DNA_UI_MARK_R, character.r_markings, 255, 1) SetUIValueRange(DNA_UI_MARK_G, character.g_markings, 255, 1) diff --git a/code/game/dna/dna2_helpers.dm b/code/game/dna/dna2_helpers.dm index 781c3a1d230..53f248d1e91 100644 --- a/code/game/dna/dna2_helpers.dm +++ b/code/game/dna/dna2_helpers.dm @@ -131,13 +131,14 @@ src.dna.UpdateUI() dna.check_integrity() var/mob/living/carbon/human/H = src - H.r_hair = dna.GetUIValueRange(DNA_UI_HAIR_R, 255) - H.g_hair = dna.GetUIValueRange(DNA_UI_HAIR_G, 255) - H.b_hair = dna.GetUIValueRange(DNA_UI_HAIR_B, 255) + var/obj/item/organ/external/head/head_organ = H.get_organ("head") + head_organ.r_hair = dna.GetUIValueRange(DNA_UI_HAIR_R, 255) + head_organ.g_hair = dna.GetUIValueRange(DNA_UI_HAIR_G, 255) + head_organ.b_hair = dna.GetUIValueRange(DNA_UI_HAIR_B, 255) - H.r_facial = dna.GetUIValueRange(DNA_UI_BEARD_R, 255) - H.g_facial = dna.GetUIValueRange(DNA_UI_BEARD_G, 255) - H.b_facial = dna.GetUIValueRange(DNA_UI_BEARD_B, 255) + head_organ.r_facial = dna.GetUIValueRange(DNA_UI_BEARD_R, 255) + head_organ.g_facial = dna.GetUIValueRange(DNA_UI_BEARD_G, 255) + head_organ.b_facial = dna.GetUIValueRange(DNA_UI_BEARD_B, 255) H.r_skin = dna.GetUIValueRange(DNA_UI_SKIN_R, 255) H.g_skin = dna.GetUIValueRange(DNA_UI_SKIN_G, 255) @@ -147,9 +148,9 @@ H.g_eyes = dna.GetUIValueRange(DNA_UI_EYES_G, 255) H.b_eyes = dna.GetUIValueRange(DNA_UI_EYES_B, 255) - H.r_headacc = dna.GetUIValueRange(DNA_UI_HACC_R, 255) - H.g_headacc = dna.GetUIValueRange(DNA_UI_HACC_G, 255) - H.b_headacc = dna.GetUIValueRange(DNA_UI_HACC_B, 255) + head_organ.r_headacc = dna.GetUIValueRange(DNA_UI_HACC_R, 255) + head_organ.g_headacc = dna.GetUIValueRange(DNA_UI_HACC_G, 255) + head_organ.b_headacc = dna.GetUIValueRange(DNA_UI_HACC_B, 255) H.r_markings = dna.GetUIValueRange(DNA_UI_MARK_R, 255) H.g_markings = dna.GetUIValueRange(DNA_UI_MARK_G, 255) @@ -168,17 +169,17 @@ //Hair var/hair = dna.GetUIValueRange(DNA_UI_HAIR_STYLE,hair_styles_list.len) if((0 < hair) && (hair <= hair_styles_list.len)) - H.h_style = hair_styles_list[hair] + head_organ.h_style = hair_styles_list[hair] //Facial Hair var/beard = dna.GetUIValueRange(DNA_UI_BEARD_STYLE,facial_hair_styles_list.len) if((0 < beard) && (beard <= facial_hair_styles_list.len)) - H.f_style = facial_hair_styles_list[beard] + head_organ.f_style = facial_hair_styles_list[beard] //Head Accessories var/headacc = dna.GetUIValueRange(DNA_UI_HACC_STYLE,head_accessory_styles_list.len) if((0 < headacc) && (headacc <= head_accessory_styles_list.len)) - H.ha_style = head_accessory_styles_list[headacc] + head_organ.ha_style = head_accessory_styles_list[headacc] //Markings var/marks = dna.GetUIValueRange(DNA_UI_MARK_STYLE,marking_styles_list.len) diff --git a/code/game/dna/genes/vg_powers.dm b/code/game/dna/genes/vg_powers.dm index 8a854c7980d..5511642e53e 100644 --- a/code/game/dna/genes/vg_powers.dm +++ b/code/game/dna/genes/vg_powers.dm @@ -37,18 +37,19 @@ to_chat(usr, "\red You can't change your appearance right now!") return var/mob/living/carbon/human/M=usr + var/obj/item/organ/external/head/head_organ = M.get_organ("head") - var/new_facial = input("Please select facial hair color.", "Character Generation",rgb(M.r_facial,M.g_facial,M.b_facial)) as null|color + var/new_facial = input("Please select facial hair color.", "Character Generation",rgb(head_organ.r_facial, head_organ.g_facial, head_organ.b_facial)) as null|color if(new_facial) - M.r_facial = hex2num(copytext(new_facial, 2, 4)) - M.g_facial = hex2num(copytext(new_facial, 4, 6)) - M.b_facial = hex2num(copytext(new_facial, 6, 8)) + head_organ.r_facial = hex2num(copytext(new_facial, 2, 4)) + head_organ.g_facial = hex2num(copytext(new_facial, 4, 6)) + head_organ.b_facial = hex2num(copytext(new_facial, 6, 8)) - var/new_hair = input("Please select hair color.", "Character Generation",rgb(M.r_hair,M.g_hair,M.b_hair)) as null|color + var/new_hair = input("Please select hair color.", "Character Generation",rgb(head_organ.r_hair, head_organ.g_hair, head_organ.b_hair)) as null|color if(new_facial) - M.r_hair = hex2num(copytext(new_hair, 2, 4)) - M.g_hair = hex2num(copytext(new_hair, 4, 6)) - M.b_hair = hex2num(copytext(new_hair, 6, 8)) + head_organ.r_hair = hex2num(copytext(new_hair, 2, 4)) + head_organ.g_hair = hex2num(copytext(new_hair, 4, 6)) + head_organ.b_hair = hex2num(copytext(new_hair, 6, 8)) var/new_eyes = input("Please select eye color.", "Character Generation",rgb(M.r_eyes,M.g_eyes,M.b_eyes)) as null|color if(new_eyes) @@ -73,11 +74,11 @@ hairs.Add(H.name) // add hair name to hairs qdel(H) // delete the hair after it's all done - var/new_style = input("Please select hair style", "Character Generation",M.h_style) as null|anything in hairs + var/new_style = input("Please select hair style", "Character Generation", head_organ.h_style) as null|anything in hairs // if new style selected (not cancel) if (new_style) - M.h_style = new_style + head_organ.h_style = new_style // facial hair var/list/all_fhairs = subtypesof(/datum/sprite_accessory/facial_hair) @@ -88,10 +89,10 @@ fhairs.Add(H.name) qdel(H) - new_style = input("Please select facial style", "Character Generation",M.f_style) as null|anything in fhairs + new_style = input("Please select facial style", "Character Generation", head_organ.f_style) as null|anything in fhairs if(new_style) - M.f_style = new_style + head_organ.f_style = new_style var/new_gender = alert(usr, "Please select gender.", "Character Generation", "Male", "Female") if (new_gender) diff --git a/code/game/gamemodes/blob/blobs/blob_mobs.dm b/code/game/gamemodes/blob/blobs/blob_mobs.dm index a35505470fa..229b35660a3 100644 --- a/code/game/gamemodes/blob/blobs/blob_mobs.dm +++ b/code/game/gamemodes/blob/blobs/blob_mobs.dm @@ -68,6 +68,7 @@ ..() /mob/living/simple_animal/hostile/blob/blobspore/proc/Zombify(var/mob/living/carbon/human/H) + var/obj/item/organ/external/head/head_organ = H.get_organ("head") is_zombie = 1 if(H.wear_suit) var/obj/item/clothing/suit/armor/A = H.wear_suit @@ -82,7 +83,7 @@ icon = H.icon speak_emote = list("groans") icon_state = "zombie2_s" - H.h_style = null + head_organ.h_style = null H.update_hair() human_overlays = H.overlays update_icons() diff --git a/code/game/gamemodes/heist/heist.dm b/code/game/gamemodes/heist/heist.dm index 057c43345f8..85244067c54 100644 --- a/code/game/gamemodes/heist/heist.dm +++ b/code/game/gamemodes/heist/heist.dm @@ -95,6 +95,7 @@ var/global/list/obj/cortical_stacks = list() //Stacks for 'leave nobody behind' newname += pick(list("ti","hi","ki","ya","ta","ha","ka","ya","chi","cha","kah")) var/mob/living/carbon/human/vox = newraider.current + var/obj/item/organ/external/head/head_organ = vox.get_organ("head") vox.real_name = capitalize(newname) vox.name = vox.real_name @@ -106,8 +107,8 @@ var/global/list/obj/cortical_stacks = list() //Stacks for 'leave nobody behind' vox.add_language("Vox-pidgin") vox.add_language("Galactic Common") vox.add_language("Tradeband") - vox.h_style = "Short Vox Quills" - vox.f_style = "Shaved" + head_organ.h_style = "Short Vox Quills" + head_organ.f_style = "Shaved" for(var/obj/item/organ/external/limb in vox.organs) limb.status &= ~(ORGAN_DESTROYED | ORGAN_ROBOT) diff --git a/code/game/gamemodes/nuclear/nuclear.dm b/code/game/gamemodes/nuclear/nuclear.dm index f2d05507da1..3ba413027e1 100644 --- a/code/game/gamemodes/nuclear/nuclear.dm +++ b/code/game/gamemodes/nuclear/nuclear.dm @@ -134,6 +134,8 @@ proc/issyndicate(mob/living/M as mob) /datum/game_mode/proc/create_syndicate(var/datum/mind/synd_mind) // So we don't have inferior species as ops - randomize a human var/mob/living/carbon/human/M = synd_mind.current + var/obj/item/organ/external/head/head_organ = M.get_organ("head") + M.set_species("Human",1) M.dna.ready_dna(M) // Quadriplegic Nuke Ops won't be participating in the paralympics @@ -150,18 +152,18 @@ proc/issyndicate(mob/living/M as mob) if(prob(5)) facial_hair_style = pick(facial_hair_styles_list) - M.r_facial = hex2num(copytext(hair_c, 2, 4)) - M.g_facial = hex2num(copytext(hair_c, 4, 6)) - M.b_facial = hex2num(copytext(hair_c, 6, 8)) - M.r_hair = hex2num(copytext(hair_c, 2, 4)) - M.g_hair = hex2num(copytext(hair_c, 4, 6)) - M.b_hair = hex2num(copytext(hair_c, 6, 8)) + head_organ.r_facial = hex2num(copytext(hair_c, 2, 4)) + head_organ.g_facial = hex2num(copytext(hair_c, 4, 6)) + head_organ.b_facial = hex2num(copytext(hair_c, 6, 8)) + head_organ.r_hair = hex2num(copytext(hair_c, 2, 4)) + head_organ.g_hair = hex2num(copytext(hair_c, 4, 6)) + head_organ.b_hair = hex2num(copytext(hair_c, 6, 8)) M.r_eyes = hex2num(copytext(eye_c, 2, 4)) M.g_eyes = hex2num(copytext(eye_c, 4, 6)) M.b_eyes = hex2num(copytext(eye_c, 6, 8)) M.s_tone = skin_tone - M.h_style = hair_style - M.f_style = facial_hair_style + head_organ.h_style = hair_style + head_organ.f_style = facial_hair_style M.body_accessory = null /datum/game_mode/proc/prepare_syndicate_leader(var/datum/mind/synd_mind, var/nuke_code) diff --git a/code/game/objects/items/weapons/cosmetics.dm b/code/game/objects/items/weapons/cosmetics.dm index 3e2448fa8fe..89a8b52b8da 100644 --- a/code/game/objects/items/weapons/cosmetics.dm +++ b/code/game/objects/items/weapons/cosmetics.dm @@ -91,16 +91,16 @@ /obj/item/weapon/razor/attack(mob/living/carbon/M as mob, mob/user as mob) if(ishuman(M)) var/mob/living/carbon/human/H = M - var/obj/item/organ/external/head/C = H.organs_by_name["head"] + var/obj/item/organ/external/head/C = H.get_organ("head") var/datum/robolimb/robohead = all_robolimbs[C.model] if(user.zone_sel.selecting == "mouth") if(!get_location_accessible(H, "mouth")) to_chat(user, "The mask is in the way.") return - if((H.species && H.species.flags & ALL_RPARTS) && robohead.is_monitor) //If the target is of a species that can have prosthetic heads, but the head doesn't support human hair 'wigs'... + if((C.species && C.species.flags & ALL_RPARTS) && robohead.is_monitor) //If the target is of a species that can have prosthetic heads, but the head doesn't support human hair 'wigs'... to_chat(user, "You find yourself disappointed at the appalling lack of facial hair.") return - if(H.f_style == "Shaved") + if(C.f_style == "Shaved") to_chat(user, "Already clean-shaven.") return if(H == user) //shaving yourself @@ -109,7 +109,7 @@ if(do_after(user, 50, target = H)) user.visible_message("[user] shaves his facial hair clean with the [src].", \ "You finish shaving with the [src]. Fast and clean!") - H.f_style = "Shaved" + C.f_style = "Shaved" H.update_fhair() playsound(src.loc, 'sound/items/Welder2.ogg', 20, 1) else @@ -121,17 +121,17 @@ if(user_loc == user.loc && H_loc == H.loc) user.visible_message("[user] shaves off [H]'s facial hair with \the [src].", \ "You shave [H]'s facial hair clean off.") - H.f_style = "Shaved" + C.f_style = "Shaved" H.update_fhair() playsound(src.loc, 'sound/items/Welder2.ogg', 20, 1) if(user.zone_sel.selecting == "head") if(!get_location_accessible(H, "head")) to_chat(user, "The headgear is in the way.") return - if((H.species && H.species.flags & ALL_RPARTS) && robohead.is_monitor) //If the target is of a species that can have prosthetic heads, but the head doesn't support human hair 'wigs'... + if((C.species && C.species.flags & ALL_RPARTS) && robohead.is_monitor) //If the target is of a species that can have prosthetic heads, but the head doesn't support human hair 'wigs'... to_chat(user, "You find yourself disappointed at the appalling lack of hair.") return - if(H.h_style == "Bald" || H.h_style == "Balding Hair" || H.h_style == "Skinhead") + if(C.h_style == "Bald" || C.h_style == "Balding Hair" || C.h_style == "Skinhead") to_chat(user, "There is not enough hair left to shave...") return if(H == user) //shaving yourself @@ -140,7 +140,7 @@ if(do_after(user, 50, target = H)) user.visible_message("[user] shaves his head with the [src].", \ "You finish shaving with the [src].") - H.h_style = "Skinhead" + C.h_style = "Skinhead" H.update_hair() playsound(src.loc, 'sound/items/Welder2.ogg', 40, 1) else @@ -152,7 +152,7 @@ if(user_loc == user.loc && H_loc == H.loc) user.visible_message("[user] shaves [H]'s head bald with \the [src]!", \ "You shave [H]'s head bald.") - H.h_style = "Skinhead" + C.h_style = "Skinhead" H.update_hair() playsound(src.loc, 'sound/items/Welder2.ogg', 40, 1) else diff --git a/code/game/objects/items/weapons/scissors.dm b/code/game/objects/items/weapons/scissors.dm index a5e0081e723..343c3788bdc 100644 --- a/code/game/objects/items/weapons/scissors.dm +++ b/code/game/objects/items/weapons/scissors.dm @@ -30,21 +30,21 @@ //this is largely copypasted from there. //handle facial hair (if necessary) var/list/species_facial_hair = list() - var/obj/item/organ/external/head/C = H.organs_by_name["head"] + var/obj/item/organ/external/head/C = H.get_organ("head") var/datum/robolimb/robohead = all_robolimbs[C.model] if(H.gender == MALE || H.get_species() == "Vulpkanin") - if(H.species) + if(C.species) for(var/i in facial_hair_styles_list) var/datum/sprite_accessory/facial_hair/tmp_facial = facial_hair_styles_list[i] - if(H.species.name in tmp_facial.species_allowed) //If the species is allowed to have the style, add the style to the list. Or, if the character has a prosthetic head, give them the human hair styles. - if(H.species.flags & ALL_RPARTS) //If the character is of a species that can have full body prosthetics and their head doesn't suport human hair 'wigs', don't add the style to the list. + if(C.species.name in tmp_facial.species_allowed) //If the species is allowed to have the style, add the style to the list. Or, if the character has a prosthetic head, give them the human hair styles. + if(C.species.flags & ALL_RPARTS) //If the character is of a species that can have full body prosthetics and their head doesn't suport human hair 'wigs', don't add the style to the list. if(robohead.is_monitor) to_chat(user, "You are unable to find anything on [H]'s face worth cutting. How disappointing.") return continue //If the head DOES support human hair wigs, make sure they don't get monitor-oriented styles. species_facial_hair += i else - if(H.species.flags & ALL_RPARTS) //If the target is of a species that can have prosthetic heads, and the head supports human hair 'wigs' AND the hair-style is human-suitable, add it to the list. + if(C.species.flags & ALL_RPARTS) //If the target is of a species that can have prosthetic heads, and the head supports human hair 'wigs' AND the hair-style is human-suitable, add it to the list. if(!robohead.is_monitor) if("Human" in tmp_facial.species_allowed) species_facial_hair += i @@ -56,18 +56,18 @@ var/f_new_style = input(user, "Select a facial hair style", "Grooming") as null|anything in species_facial_hair //handle normal hair var/list/species_hair = list() - if(H.species) + if(C.species) for(var/i in hair_styles_list) var/datum/sprite_accessory/hair/tmp_hair = hair_styles_list[i] - if(H.species.name in tmp_hair.species_allowed) //If the species is allowed to have the style, add the style to the list. Or, if the character has a prosthetic head, give them the human facial hair styles. - if(H.species.flags & ALL_RPARTS) //If the character is of a species that can have full body prosthetics and their head doesn't suport human hair 'wigs', don't add the style to the list. + if(C.species.name in tmp_hair.species_allowed) //If the species is allowed to have the style, add the style to the list. Or, if the character has a prosthetic head, give them the human facial hair styles. + if(C.species.flags & ALL_RPARTS) //If the character is of a species that can have full body prosthetics and their head doesn't suport human hair 'wigs', don't add the style to the list. if(robohead.is_monitor) to_chat(user, "You are unable to find anything on [H]'s head worth cutting. How disappointing.") return continue //If the head DOES support human hair wigs, make sure they don't get monitor-oriented styles. species_hair += i else - if(H.species.flags & ALL_RPARTS) //If the target is of a species that can have prosthetic heads, and the head supports human hair 'wigs' AND the hair-style is human-suitable, add it to the list. + if(C.species.flags & ALL_RPARTS) //If the target is of a species that can have prosthetic heads, and the head supports human hair 'wigs' AND the hair-style is human-suitable, add it to the list. if(!robohead.is_monitor) if("Human" in tmp_hair.species_allowed) species_hair += i @@ -84,9 +84,9 @@ user.visible_message("[user] stops cutting [M]'s hair.", "You stop cutting [M]'s hair.") return if(f_new_style) - H.f_style = f_new_style + C.f_style = f_new_style if(h_new_style) - H.h_style = h_new_style + C.h_style = h_new_style H.update_hair() user.visible_message("[user] finishes cutting [M]'s hair!") diff --git a/code/game/response_team.dm b/code/game/response_team.dm index 14bf44ff7b5..241e317c24b 100644 --- a/code/game/response_team.dm +++ b/code/game/response_team.dm @@ -148,6 +148,7 @@ var/send_emergency_team /client/proc/create_response_team(obj/spawn_location) var/mob/living/carbon/human/M = new(null) + var/obj/item/organ/external/head/head_organ = M.get_organ("head") response_team_members |= M var/new_gender = alert(usr, "Please select your gender.", "Character Generation", "Male", "Female") @@ -173,18 +174,18 @@ var/send_emergency_team if(prob(5)) facial_hair_style = pick(facial_hair_styles_list) - M.r_facial = hex2num(copytext(hair_c, 2, 4)) - M.g_facial = hex2num(copytext(hair_c, 4, 6)) - M.b_facial = hex2num(copytext(hair_c, 6, 8)) - M.r_hair = hex2num(copytext(hair_c, 2, 4)) - M.g_hair = hex2num(copytext(hair_c, 4, 6)) - M.b_hair = hex2num(copytext(hair_c, 6, 8)) + head_organ.r_facial = hex2num(copytext(hair_c, 2, 4)) + head_organ.g_facial = hex2num(copytext(hair_c, 4, 6)) + head_organ.b_facial = hex2num(copytext(hair_c, 6, 8)) + head_organ.r_hair = hex2num(copytext(hair_c, 2, 4)) + head_organ.g_hair = hex2num(copytext(hair_c, 4, 6)) + head_organ.b_hair = hex2num(copytext(hair_c, 6, 8)) M.r_eyes = hex2num(copytext(eye_c, 2, 4)) M.g_eyes = hex2num(copytext(eye_c, 4, 6)) M.b_eyes = hex2num(copytext(eye_c, 6, 8)) M.s_tone = skin_tone - M.h_style = hair_style - M.f_style = facial_hair_style + head_organ.h_style = hair_style + head_organ.f_style = facial_hair_style M.real_name = "[pick("Corporal", "Sergeant", "Staff Sergeant", "Sergeant First Class", "Master Sergeant", "Sergeant Major")] [pick(last_names)]" M.name = M.real_name diff --git a/code/modules/admin/verbs/one_click_antag.dm b/code/modules/admin/verbs/one_click_antag.dm index f2d76051a37..2d41cd1d202 100644 --- a/code/modules/admin/verbs/one_click_antag.dm +++ b/code/modules/admin/verbs/one_click_antag.dm @@ -498,6 +498,7 @@ client/proc/one_click_antag() /datum/admins/proc/create_vox_raider(obj/spawn_location, leader_chosen = 0) var/mob/living/carbon/human/new_vox = new(spawn_location.loc, "Vox") + var/obj/item/organ/external/head/head_organ = new_vox.get_organ("head") var/sounds = rand(2,8) var/i = 0 @@ -516,8 +517,8 @@ client/proc/one_click_antag() new_vox.add_language("Vox-pidgin") new_vox.add_language("Galactic Common") new_vox.add_language("Tradeband") - new_vox.h_style = "Short Vox Quills" - new_vox.f_style = "Shaved" + head_organ.h_style = "Short Vox Quills" + head_organ.f_style = "Shaved" for(var/obj/item/organ/external/limb in new_vox.organs) limb.status &= ~(ORGAN_DESTROYED | ORGAN_ROBOT) diff --git a/code/modules/client/preferences.dm b/code/modules/client/preferences.dm index e53af9a5014..06e26861b6d 100644 --- a/code/modules/client/preferences.dm +++ b/code/modules/client/preferences.dm @@ -1631,7 +1631,7 @@ var/global/list/special_role_times = list( //minimum age (in days) for accounts if("nanoui") nanoui_fancy = !nanoui_fancy - if("ghost_att_anim") + if("ghost_att_anim") show_ghostitem_attack = !show_ghostitem_attack if("UIcolor") @@ -1753,13 +1753,19 @@ var/global/list/special_role_times = list( //minimum age (in days) for accounts character.g_eyes = g_eyes character.b_eyes = b_eyes - character.r_hair = r_hair - character.g_hair = g_hair - character.b_hair = b_hair + //Head-specific + var/obj/item/organ/external/head/H = character.get_organ("head") + H.r_hair = r_hair + H.g_hair = g_hair + H.b_hair = b_hair - character.r_facial = r_facial - character.g_facial = g_facial - character.b_facial = b_facial + H.r_facial = r_facial + H.g_facial = g_facial + H.b_facial = b_facial + + H.h_style = h_style + H.f_style = f_style + //End of head-specific. character.r_skin = r_skin character.g_skin = g_skin @@ -1767,9 +1773,6 @@ var/global/list/special_role_times = list( //minimum age (in days) for accounts character.s_tone = s_tone - character.h_style = h_style - character.f_style = f_style - // Destroy/cyborgize organs for(var/name in organ_data) @@ -1846,10 +1849,10 @@ var/global/list/special_role_times = list( //minimum age (in days) for accounts character.socks = socks if(character.species.bodyflags & HAS_HEAD_ACCESSORY) - character.r_headacc = r_headacc - character.g_headacc = g_headacc - character.b_headacc = b_headacc - character.ha_style = ha_style + H.r_headacc = r_headacc + H.g_headacc = g_headacc + H.b_headacc = b_headacc + H.ha_style = ha_style if(character.species.bodyflags & HAS_MARKINGS) character.r_markings = r_markings character.g_markings = g_markings diff --git a/code/modules/clothing/head/misc_special.dm b/code/modules/clothing/head/misc_special.dm index 071c6032722..13b7a948119 100644 --- a/code/modules/clothing/head/misc_special.dm +++ b/code/modules/clothing/head/misc_special.dm @@ -176,9 +176,11 @@ /obj/item/clothing/head/kitty/update_icon(var/mob/living/carbon/human/user) if(!istype(user)) return + var/obj/item/organ/external/head/head_organ = user.get_organ("head") + mob = new/icon("icon" = 'icons/mob/head.dmi', "icon_state" = "kitty") // mob2 = new/icon("icon" = 'icons/mob/head.dmi', "icon_state" = "kitty2") - Commented out because it seemingly does nothing. - mob.Blend(rgb(user.r_hair, user.g_hair, user.b_hair), ICON_ADD) + mob.Blend(rgb(head_organ.r_hair, head_organ.g_hair, head_organ.b_hair), ICON_ADD) // mob2.Blend(rgb(user.r_hair, user.g_hair, user.b_hair), ICON_ADD) - Commented out because it seemingly does nothing. var/icon/earbit = new/icon("icon" = 'icons/mob/head.dmi', "icon_state" = "kittyinner") @@ -201,8 +203,9 @@ /obj/item/clothing/head/kitty/mouse/update_icon(var/mob/living/carbon/human/user) if(!istype(user)) return + var/obj/item/organ/external/head/head_organ = user.get_organ("head") mob = new/icon("icon" = 'icons/mob/head.dmi', "icon_state" = "mousey") - mob.Blend(rgb(user.r_hair, user.g_hair, user.b_hair), ICON_ADD) + mob.Blend(rgb(head_organ.r_hair, head_organ.g_hair, head_organ.b_hair), ICON_ADD) var/icon/earbit = new/icon("icon" = 'icons/mob/head.dmi', "icon_state" = "mouseyinner") mob.Blend(earbit, ICON_OVERLAY) diff --git a/code/modules/mob/living/carbon/human/appearance.dm b/code/modules/mob/living/carbon/human/appearance.dm index 8264db804fd..2822fa99933 100644 --- a/code/modules/mob/living/carbon/human/appearance.dm +++ b/code/modules/mob/living/carbon/human/appearance.dm @@ -18,16 +18,17 @@ return 1 /mob/living/carbon/human/proc/change_gender(var/gender, var/update_dna = 1) + var/obj/item/organ/external/head/H = organs_by_name["head"] if(src.gender == gender) return src.gender = gender - var/datum/sprite_accessory/hair/current_hair = hair_styles_list[h_style] + var/datum/sprite_accessory/hair/current_hair = hair_styles_list[H.h_style] if(current_hair.gender != NEUTER && current_hair.gender != src.gender) reset_head_hair() - var/datum/sprite_accessory/hair/current_fhair = facial_hair_styles_list[f_style] + var/datum/sprite_accessory/hair/current_fhair = facial_hair_styles_list[H.f_style] if(current_fhair.gender != NEUTER && current_fhair.gender != src.gender) reset_facial_hair() @@ -38,31 +39,33 @@ return 1 /mob/living/carbon/human/proc/change_hair(var/hair_style) + var/obj/item/organ/external/head/H = get_organ("head") if(!hair_style) return - if(h_style == hair_style) + if(H.h_style == hair_style) return if(!(hair_style in hair_styles_list)) return - h_style = hair_style + H.h_style = hair_style update_hair() return 1 /mob/living/carbon/human/proc/change_facial_hair(var/facial_hair_style) + var/obj/item/organ/external/head/H = get_organ("head") if(!facial_hair_style) return - if(f_style == facial_hair_style) + if(H.f_style == facial_hair_style) return if(!(facial_hair_style in facial_hair_styles_list)) return - f_style = facial_hair_style + H.f_style = facial_hair_style update_fhair() return 1 @@ -72,23 +75,24 @@ reset_facial_hair() /mob/living/carbon/human/proc/reset_head_hair() + var/obj/item/organ/external/head/H = get_organ("head") var/list/valid_hairstyles = generate_valid_hairstyles() - if(valid_hairstyles.len) - h_style = pick(valid_hairstyles) + H.h_style = pick(valid_hairstyles) else //this shouldn't happen - h_style = "Bald" + H.h_style = "Bald" update_hair() /mob/living/carbon/human/proc/reset_facial_hair() + var/obj/item/organ/external/head/H = get_organ("head") var/list/valid_facial_hairstyles = generate_valid_facial_hairstyles() if(valid_facial_hairstyles.len) - f_style = pick(valid_facial_hairstyles) + H.f_style = pick(valid_facial_hairstyles) else //this shouldn't happen - f_style = "Shaved" + H.f_style = "Shaved" update_fhair() /mob/living/carbon/human/proc/change_eye_color(var/red, var/green, var/blue) @@ -104,23 +108,25 @@ return 1 /mob/living/carbon/human/proc/change_hair_color(var/red, var/green, var/blue) - if(red == r_eyes && green == g_eyes && blue == b_eyes) + var/obj/item/organ/external/head/H = get_organ("head") + if(red == H.r_hair && green == H.g_hair && blue == H.b_hair) return - r_hair = red - g_hair = green - b_hair = blue + H.r_hair = red + H.g_hair = green + H.b_hair = blue update_hair() return 1 /mob/living/carbon/human/proc/change_facial_hair_color(var/red, var/green, var/blue) - if(red == r_facial && green == g_facial && blue == b_facial) + var/obj/item/organ/external/head/H = get_organ("head") + if(red == H.r_facial && green == H.g_facial && blue == H.b_facial) return - r_facial = red - g_facial = green - b_facial = blue + H.r_facial = red + H.g_facial = green + H.b_facial = blue update_fhair() return 1 @@ -172,17 +178,17 @@ var/list/valid_hairstyles = new() for(var/hairstyle in hair_styles_list) var/datum/sprite_accessory/S = hair_styles_list[hairstyle] + var/obj/item/organ/external/head/H = organs_by_name["head"] if(gender == MALE && S.gender == FEMALE) continue if(gender == FEMALE && S.gender == MALE) continue - if(species.flags & ALL_RPARTS) //If the user is a species who can have a robotic head... - var/obj/item/organ/external/head/H = organs_by_name["head"] + if(H.species.flags & ALL_RPARTS) //If the user is a species who can have a robotic head... var/datum/robolimb/robohead = all_robolimbs[H.model] if(!H) return - if(species.name in S.species_allowed) //If this is a hairstyle native to the user's species... + if(H.species.name in S.species_allowed) //If this is a hairstyle native to the user's species... if(robohead.is_monitor && (robohead.company in S.models_allowed)) //Check to see if they have a head with an ipc-style screen and that the head's company is in the screen style's allowed models list. valid_hairstyles += hairstyle //Give them their hairstyles if they do. continue @@ -195,8 +201,8 @@ if("Human" in S.species_allowed) //If the user has a robotic head and the hairstyle can fit humans, let them use it as a wig for their humanoid robot head. valid_hairstyles += hairstyle continue - else - if(!(species.name in S.species_allowed)) //If the user is not a species who can have robotic heads, use the default handling. + else //If the user is not a species who can have robotic heads, use the default handling. + if(!(H.species.name in S.species_allowed)) //If the user's head is not of a species the hair style allows, skip it. Otherwise, add it to the list. continue valid_hairstyles += hairstyle @@ -206,17 +212,17 @@ var/list/valid_facial_hairstyles = new() for(var/facialhairstyle in facial_hair_styles_list) var/datum/sprite_accessory/S = facial_hair_styles_list[facialhairstyle] + var/obj/item/organ/external/head/H = organs_by_name["head"] if(gender == MALE && S.gender == FEMALE) continue if(gender == FEMALE && S.gender == MALE) continue - if(species.flags & ALL_RPARTS) //If the user is a species who can have a robotic head... - var/obj/item/organ/external/head/H = organs_by_name["head"] + if(H.species.flags & ALL_RPARTS) //If the user is a species who can have a robotic head... var/datum/robolimb/robohead = all_robolimbs[H.model] if(!H) continue // No head, no hair - if(species.name in S.species_allowed) //If this is a facial hair style native to the user's species... + if(H.species.name in S.species_allowed) //If this is a facial hair style native to the user's species... if(robohead.is_monitor && (robohead.company in S.models_allowed)) //Check to see if they have a head with an ipc-style screen and that the head's company is in the screen style's allowed models list. valid_facial_hairstyles += facialhairstyle //Give them their facial hair styles if they do. continue @@ -231,7 +237,7 @@ valid_facial_hairstyles += facialhairstyle continue else //If the user is not a species who can have robotic heads, use the default handling. - if(!(species.name in S.species_allowed)) + if(!(H.species.name in S.species_allowed)) //If the user's head is not of a species the facial hair style allows, skip it. Otherwise, add it to the list. continue valid_facial_hairstyles += facialhairstyle diff --git a/code/modules/mob/living/carbon/human/death.dm b/code/modules/mob/living/carbon/human/death.dm index aa31c912841..fce12362d73 100644 --- a/code/modules/mob/living/carbon/human/death.dm +++ b/code/modules/mob/living/carbon/human/death.dm @@ -145,12 +145,13 @@ return ..(gibbed) /mob/living/carbon/human/proc/makeSkeleton() + var/obj/item/organ/external/head/H = get_organ("head") if(SKELETON in src.mutations) return - if(f_style) - f_style = "Shaved" - if(h_style) - h_style = "Bald" + if(H.f_style) + H.f_style = "Shaved" + if(H.h_style) + H.h_style = "Bald" update_fhair(0) update_hair(0) @@ -162,12 +163,13 @@ return /mob/living/carbon/human/proc/ChangeToHusk() + var/obj/item/organ/external/head/H = organs_by_name["head"] if(HUSK in mutations) return - if(f_style) - f_style = "Shaved" //we only change the icon_state of the hair datum, so it doesn't mess up their UI/UE - if(h_style) - h_style = "Bald" + if(H.f_style) + H.f_style = "Shaved" //we only change the icon_state of the hair datum, so it doesn't mess up their UI/UE + if(H.h_style) + H.h_style = "Bald" update_fhair(0) update_hair(0) diff --git a/code/modules/mob/living/carbon/human/human.dm b/code/modules/mob/living/carbon/human/human.dm index 3e5cb90f380..f78a80a3c3c 100644 --- a/code/modules/mob/living/carbon/human/human.dm +++ b/code/modules/mob/living/carbon/human/human.dm @@ -74,38 +74,46 @@ status_flags = GODMODE|CANPUSH /mob/living/carbon/human/skrell/New(var/new_loc) - h_style = "Skrell Male Tentacles" + var/obj/item/organ/external/head/H = get_organ("head") + H.h_style = "Skrell Male Tentacles" ..(new_loc, "Skrell") /mob/living/carbon/human/tajaran/New(var/new_loc) - ha_style = "Tajaran Ears" + var/obj/item/organ/external/head/H = get_organ("head") + H.ha_style = "Tajaran Ears" ..(new_loc, "Tajaran") /mob/living/carbon/human/vulpkanin/New(var/new_loc) - h_style = "Bald" + var/obj/item/organ/external/head/H = get_organ("head") + H.h_style = "Bald" ..(new_loc, "Vulpkanin") /mob/living/carbon/human/unathi/New(var/new_loc) - h_style = "Unathi Horns" + var/obj/item/organ/external/head/H = get_organ("head") + H.h_style = "Unathi Horns" ..(new_loc, "Unathi") /mob/living/carbon/human/vox/New(var/new_loc) - h_style = "Short Vox Quills" + var/obj/item/organ/external/head/H = get_organ("head") + H.h_style = "Short Vox Quills" ..(new_loc, "Vox") /mob/living/carbon/human/voxarmalis/New(var/new_loc) - h_style = "Bald" + var/obj/item/organ/external/head/H = get_organ("head") + H.h_style = "Bald" ..(new_loc, "Vox Armalis") /mob/living/carbon/human/skeleton/New(var/new_loc) - h_style = "Bald" + var/obj/item/organ/external/head/H = get_organ("head") + H.h_style = "Bald" ..(new_loc, "Skeleton") /mob/living/carbon/human/kidan/New(var/new_loc) ..(new_loc, "Kidan") /mob/living/carbon/human/plasma/New(var/new_loc) - h_style = "Bald" + var/obj/item/organ/external/head/H = get_organ("head") + H.h_style = "Bald" ..(new_loc, "Plasmaman") /mob/living/carbon/human/slime/New(var/new_loc) @@ -121,31 +129,38 @@ ..(new_loc, "Human") /mob/living/carbon/human/diona/New(var/new_loc) - h_style = "Bald" + var/obj/item/organ/external/head/H = get_organ("head") + H.h_style = "Bald" ..(new_loc, "Diona") /mob/living/carbon/human/machine/New(var/new_loc) - h_style = "blue IPC screen" + var/obj/item/organ/external/head/H = get_organ("head") + H.h_style = "Blue IPC Screen" ..(new_loc, "Machine") /mob/living/carbon/human/shadow/New(var/new_loc) - h_style = "Bald" + var/obj/item/organ/external/head/H = get_organ("head") + H.h_style = "Bald" ..(new_loc, "Shadow") /mob/living/carbon/human/golem/New(var/new_loc) - h_style = "Bald" + var/obj/item/organ/external/head/H = get_organ("head") + H.h_style = "Bald" ..(new_loc, "Golem") /mob/living/carbon/human/wryn/New(var/new_loc) - h_style = "Antennae" + var/obj/item/organ/external/head/H = get_organ("head") + H.h_style = "Antennae" ..(new_loc, "Wryn") /mob/living/carbon/human/nucleation/New(var/new_loc) - h_style = "Nucleation Crystals" + var/obj/item/organ/external/head/H = get_organ("head") + H.h_style = "Nucleation Crystals" ..(new_loc, "Nucleation") /mob/living/carbon/human/drask/New(var/new_loc) - h_style = "Bald" + var/obj/item/organ/external/head/H = get_organ("head") + H.h_style = "Bald" ..(new_loc, "Drask") /mob/living/carbon/human/monkey/New(var/new_loc) @@ -1601,9 +1616,8 @@ return if(species.flags & ALL_RPARTS) //If they can have a fully cybernetic body... - var/obj/item/organ/external/head/H = organs_by_name["head"] - var/datum/robolimb/robohead = all_robolimbs[H.model] - if(!H) + var/datum/robolimb/robohead = all_robolimbs[head_organ.model] + if(!head_organ) return if(!robohead.is_monitor) //If they've got a prosthetic head and it isn't a monitor, they've no screen to adjust. Instead, let them change the colour of their optics! var/optic_colour = input(src, "Select optic colour", rgb(r_markings, g_markings, b_markings)) as color|null @@ -1620,15 +1634,15 @@ var/list/hair = list() for(var/i in hair_styles_list) var/datum/sprite_accessory/hair/tmp_hair = hair_styles_list[i] - if((species.name in tmp_hair.species_allowed) && (robohead.company in tmp_hair.models_allowed)) //Populate the list of available monitor styles only with styles that the monitor-head is allowed to use. + if((head_organ.species.name in tmp_hair.species_allowed) && (robohead.company in tmp_hair.models_allowed)) //Populate the list of available monitor styles only with styles that the monitor-head is allowed to use. hair += i - var/new_style = input(src, "Select a monitor display", "Monitor Display", h_style) as null|anything in hair + var/new_style = input(src, "Select a monitor display", "Monitor Display", head_organ.h_style) as null|anything in hair if(incapacitated()) to_chat(src, "You were interrupted while changing your monitor display.") return if(new_style) - h_style = new_style + head_organ.h_style = new_style update_hair() diff --git a/code/modules/mob/living/carbon/human/human_defines.dm b/code/modules/mob/living/carbon/human/human_defines.dm index e2ebed386b3..6f106f5e125 100644 --- a/code/modules/mob/living/carbon/human/human_defines.dm +++ b/code/modules/mob/living/carbon/human/human_defines.dm @@ -9,24 +9,6 @@ var/global/default_martial_art = new/datum/martial_art var/b_markings = 0 var/m_style = "None" - //Hair colour and style - var/r_hair = 0 - var/g_hair = 0 - var/b_hair = 0 - var/h_style = "Bald" - - //Head accessory colour and style - var/r_headacc = 0 - var/g_headacc = 0 - var/b_headacc = 0 - var/ha_style = "None" - - //Facial hair colour and style - var/r_facial = 0 - var/g_facial = 0 - var/b_facial = 0 - var/f_style = "Shaved" - //Eye colour var/r_eyes = 0 var/g_eyes = 0 diff --git a/code/modules/mob/living/carbon/human/species/apollo.dm b/code/modules/mob/living/carbon/human/species/apollo.dm index a7735a00db9..ed02ee5465a 100644 --- a/code/modules/mob/living/carbon/human/species/apollo.dm +++ b/code/modules/mob/living/carbon/human/species/apollo.dm @@ -54,6 +54,7 @@ to_chat(C, "It feels like part of you has died.") /datum/species/wryn/handle_attack_hand(var/mob/living/carbon/human/H, var/mob/living/carbon/human/M) + var/obj/item/organ/external/head/head_organ = H.get_organ("head") if(M.a_intent == I_HARM) if(H.handcuffed) if(!H.get_int_organ(/obj/item/organ/internal/wryn/hivenode)) return @@ -71,7 +72,7 @@ to_chat(M, "You hear a loud crunch as you mercilessly pull off [H]'s antennae.") to_chat(H, "You hear a loud crunch as your antennae is ripped off your head by [M].") to_chat(H, "It's so quiet...") - H.h_style = "Bald" + head_organ.h_style = "Bald" H.update_hair() M.attack_log += text("\[[time_stamp()]\] removed antennae [H.name] ([H.ckey])") @@ -87,7 +88,7 @@ blurb = "A sub-race of unforunates who have been exposed to too much supermatter radiation. As a result, \ supermatter crystal clusters have begun to grow across their bodies. Research to find a cure for this ailment \ has been slow, and so this is a common fate for veteran engineers. The supermatter crystals produce oxygen, \ - negating the need for the individual to breath. Their massive change in biology, however, renders most medicines \ + negating the need for the individual to breathe. Their massive change in biology, however, renders most medicines \ obselete. Ionizing radiation seems to cause resonance in some of their crystals, which seems to encourage regeneration \ and produces a calming effect on the individual. Nucleations are highly stigmatized, and are treated much in the same \ way as lepers were back on Earth." diff --git a/code/modules/mob/living/carbon/human/species/station.dm b/code/modules/mob/living/carbon/human/species/station.dm index 26c6ddb0c57..cce8b5c46ec 100644 --- a/code/modules/mob/living/carbon/human/species/station.dm +++ b/code/modules/mob/living/carbon/human/species/station.dm @@ -791,6 +791,8 @@ ) /datum/species/machine/handle_death(var/mob/living/carbon/human/H) - H.h_style = "" + var/obj/item/organ/external/head/head_organ = H.get_organ("head") + head_organ.h_style = "Bald" + head_organ.f_style = "Shaved" spawn(100) if(H) H.update_hair() \ No newline at end of file diff --git a/code/modules/mob/living/carbon/human/update_icons.dm b/code/modules/mob/living/carbon/human/update_icons.dm index 004f54a45ba..c885793f82c 100644 --- a/code/modules/mob/living/carbon/human/update_icons.dm +++ b/code/modules/mob/living/carbon/human/update_icons.dm @@ -393,13 +393,13 @@ var/global/list/damage_icon_parts = list() //base icons var/icon/head_accessory_standing = new /icon('icons/mob/body_accessory.dmi',"accessory_none_s") - if(ha_style && (src.species.bodyflags & HAS_HEAD_ACCESSORY)) - var/datum/sprite_accessory/head_accessory_style = head_accessory_styles_list[ha_style] + if(head_organ.ha_style && (head_organ.species.bodyflags & HAS_HEAD_ACCESSORY)) + var/datum/sprite_accessory/head_accessory_style = head_accessory_styles_list[head_organ.ha_style] if(head_accessory_style && head_accessory_style.species_allowed) - if(src.species.name in head_accessory_style.species_allowed) + if(head_organ.species.name in head_accessory_style.species_allowed) var/icon/head_accessory_s = new/icon("icon" = head_accessory_style.icon, "icon_state" = "[head_accessory_style.icon_state]_s") if(head_accessory_style.do_colouration) - head_accessory_s.Blend(rgb(r_headacc, g_headacc, b_headacc), ICON_ADD) + head_accessory_s.Blend(rgb(head_organ.r_headacc, head_organ.g_headacc, head_organ.b_headacc), ICON_ADD) head_accessory_standing = head_accessory_s //head_accessory_standing.Blend(head_accessory_s, ICON_OVERLAY) //Having it this way preserves animations. Useful for animated antennae. else @@ -429,17 +429,17 @@ var/global/list/damage_icon_parts = list() var/icon/hair_standing = new /icon('icons/mob/human_face.dmi',"bald_s") //var/icon/debrained_s = new /icon("icon"='icons/mob/human_face.dmi', "icon_state" = "debrained_s") - if(h_style && !(head && (head.flags & BLOCKHEADHAIR) && !(isSynthetic()))) - var/datum/sprite_accessory/hair_style = hair_styles_list[h_style] + if(head_organ.h_style && !(head && (head.flags & BLOCKHEADHAIR) && !(isSynthetic()))) + var/datum/sprite_accessory/hair_style = hair_styles_list[head_organ.h_style] //if(!src.get_int_organ(/obj/item/organ/internal/brain) && src.get_species() != "Machine" )//make it obvious we have NO BRAIN // hair_standing.Blend(debrained_s, ICON_OVERLAY) if(hair_style && hair_style.species_allowed) - if((src.species.name in hair_style.species_allowed) || (src.species.flags & ALL_RPARTS)) + if((head_organ.species.name in hair_style.species_allowed) || (head_organ.species.flags & ALL_RPARTS)) //If the head's species is in the list of allowed species for the hairstyle, or the head's species is one flagged to have bodies comprised wholly of cybernetics... var/icon/hair_s = new/icon("icon" = hair_style.icon, "icon_state" = "[hair_style.icon_state]_s") - if(src.get_species() == "Slime People") // I am el worstos + if(head_organ.species.name == "Slime People") // I am el worstos hair_s.Blend(rgb(r_skin, g_skin, b_skin, 160), ICON_AND) else if(hair_style.do_colouration) - hair_s.Blend(rgb(r_hair, g_hair, b_hair), ICON_ADD) + hair_s.Blend(rgb(head_organ.r_hair, head_organ.g_hair, head_organ.b_hair), ICON_ADD) hair_standing = hair_s //hair_standing.Blend(hair_s, ICON_OVERLAY) //Having it this way preserves animations. Useful for IPC screens. @@ -470,15 +470,15 @@ var/global/list/damage_icon_parts = list() //base icons var/icon/face_standing = new /icon('icons/mob/human_face.dmi',"bald_s") - if(f_style) - var/datum/sprite_accessory/facial_hair_style = facial_hair_styles_list[f_style] + if(head_organ.f_style) + var/datum/sprite_accessory/facial_hair_style = facial_hair_styles_list[head_organ.f_style] if(facial_hair_style && facial_hair_style.species_allowed) - if((src.species.name in facial_hair_style.species_allowed) || (src.species.flags & ALL_RPARTS)) + if((head_organ.species.name in facial_hair_style.species_allowed) || (head_organ.species.flags & ALL_RPARTS)) //If the head's species is in the list of allowed species for the hairstyle, or the head's species is one flagged to have bodies comprised wholly of cybernetics... var/icon/facial_s = new/icon("icon" = facial_hair_style.icon, "icon_state" = "[facial_hair_style.icon_state]_s") - if(src.get_species() == "Slime People") // I am el worstos + if(head_organ.species.name == "Slime People") // I am el worstos facial_s.Blend(rgb(r_skin, g_skin, b_skin, 160), ICON_AND) else if(facial_hair_style.do_colouration) - facial_s.Blend(rgb(r_facial, g_facial, b_facial), ICON_ADD) + facial_s.Blend(rgb(head_organ.r_facial, head_organ.g_facial, head_organ.b_facial), ICON_ADD) face_standing.Blend(facial_s, ICON_OVERLAY) else //warning("Invalid f_style for [species.name]: [f_style]") @@ -1266,22 +1266,23 @@ var/global/list/damage_icon_parts = list() //gender no longer matters for the mouth, although there should probably be seperate base head icons. // var/g = "m" // if (gender == FEMALE) g = "f" - + var/obj/item/organ/external/head/H = get_organ("head") //base icons var/icon/face_lying = new /icon('icons/mob/human_face.dmi',"bald_l") - if(f_style) - var/datum/sprite_accessory/facial_hair_style = facial_hair_styles_list[f_style] + + if(H.f_style) + var/datum/sprite_accessory/facial_hair_style = facial_hair_styles_list[H.f_style] if(facial_hair_style) var/icon/facial_l = new/icon("icon" = facial_hair_style.icon, "icon_state" = "[facial_hair_style.icon_state]_l") - facial_l.Blend(rgb(r_facial, g_facial, b_facial), ICON_ADD) + facial_l.Blend(rgb(H.r_facial, H.g_facial, H.b_facial), ICON_ADD) face_lying.Blend(facial_l, ICON_OVERLAY) - if(h_style) - var/datum/sprite_accessory/hair_style = hair_styles_list[h_style] + if(H.h_style) + var/datum/sprite_accessory/hair_style = hair_styles_list[H.h_style] if(hair_style) var/icon/hair_l = new/icon("icon" = hair_style.icon, "icon_state" = "[hair_style.icon_state]_l") - hair_l.Blend(rgb(r_hair, g_hair, b_hair), ICON_ADD) + hair_l.Blend(rgb(H.r_hair, H.g_hair, H.b_hair), ICON_ADD) face_lying.Blend(hair_l, ICON_OVERLAY) //Eyes diff --git a/code/modules/mob/living/carbon/superheroes.dm b/code/modules/mob/living/carbon/superheroes.dm index 08f5089a200..1ad57bd787d 100644 --- a/code/modules/mob/living/carbon/superheroes.dm +++ b/code/modules/mob/living/carbon/superheroes.dm @@ -148,6 +148,7 @@ /obj/effect/proc_holder/spell/targeted/recruit/cast(list/targets) for(var/mob/living/carbon/human/target in targets) + var/obj/item/organ/external/head/head_organ = target.get_organ("head") if(ticker.mode.greyshirts.len >= 3) to_chat(usr, "You have already recruited the maximum number of henchmen.") if(!in_range(usr, target)) @@ -210,8 +211,8 @@ to_chat(target, "You may not harm other Greyshirt or [usr]. However, you do not need to obey other Greyshirts.") ticker.mode.greyshirts += target.mind target.set_species("Human") - target.h_style = "Bald" - target.f_style = "Shaved" + head_organ.h_style = "Bald" + head_organ.f_style = "Shaved" target.s_tone = 35 target.r_eyes = 1 target.b_eyes = 1 diff --git a/code/modules/mob/new_player/sprite_accessories.dm b/code/modules/mob/new_player/sprite_accessories.dm index e0fbfcdf91b..15452598ed5 100644 --- a/code/modules/mob/new_player/sprite_accessories.dm +++ b/code/modules/mob/new_player/sprite_accessories.dm @@ -886,12 +886,12 @@ species_allowed = list("Vox") vox_quills_fluff - name = "Fluffy Quills" + name = "Fluffy Vox Quills" icon_state = "vox_afro" species_allowed = list("Vox") vox_quills_mohawk - name = "Quill Mohawk" + name = "Vox Quill Mohawk" icon_state = "vox_mohawk" species_allowed = list("Vox") @@ -910,6 +910,11 @@ icon_state = "vox_nights" species_allowed = list("Vox") + vox_razor + name = "Vox Razorback" + icon_state = "vox_razor" + species_allowed = list("Vox") + // Apollo-specific //Wryn antennae diff --git a/code/modules/nano/modules/human_appearance.dm b/code/modules/nano/modules/human_appearance.dm index 606dcade9c9..4868bfdc7c5 100644 --- a/code/modules/nano/modules/human_appearance.dm +++ b/code/modules/nano/modules/human_appearance.dm @@ -2,6 +2,7 @@ name = "Appearance Editor" var/flags = APPEARANCE_ALL_HAIR var/mob/living/carbon/human/owner = null + var/obj/item/organ/external/head/head_organ = null var/list/valid_species = list() var/list/valid_hairstyles = list() var/list/valid_facial_hairstyles = list() @@ -13,6 +14,7 @@ /datum/nano_module/appearance_changer/New(var/location, var/mob/living/carbon/human/H, var/check_species_whitelist = 1, var/list/species_whitelist = list(), var/list/species_blacklist = list()) ..() owner = H + head_organ = owner.get_organ("head") src.check_whitelist = check_species_whitelist src.whitelist = species_whitelist src.blacklist = species_blacklist @@ -54,7 +56,7 @@ return 1 if(href_list["hair_color"]) if(can_change(APPEARANCE_HAIR_COLOR)) - var/new_hair = input("Please select hair color.", "Hair Color", rgb(owner.r_hair, owner.g_hair, owner.b_hair)) as color|null + var/new_hair = input("Please select hair color.", "Hair Color", rgb(head_organ.r_hair, head_organ.g_hair, head_organ.b_hair)) as color|null if(new_hair && can_still_topic(state)) var/r_hair = hex2num(copytext(new_hair, 2, 4)) var/g_hair = hex2num(copytext(new_hair, 4, 6)) @@ -69,7 +71,7 @@ return 1 if(href_list["facial_hair_color"]) if(can_change(APPEARANCE_FACIAL_HAIR_COLOR)) - var/new_facial = input("Please select facial hair color.", "Facial Hair Color", rgb(owner.r_facial, owner.g_facial, owner.b_facial)) as color|null + var/new_facial = input("Please select facial hair color.", "Facial Hair Color", rgb(head_organ.r_facial, head_organ.g_facial, head_organ.b_facial)) as color|null if(new_facial && can_still_topic(state)) var/r_facial = hex2num(copytext(new_facial, 2, 4)) var/g_facial = hex2num(copytext(new_facial, 4, 6)) @@ -113,7 +115,7 @@ for(var/hair_style in valid_hairstyles) hair_styles[++hair_styles.len] = list("hairstyle" = hair_style) data["hair_styles"] = hair_styles - data["hair_style"] = owner.h_style + data["hair_style"] = head_organ.h_style data["change_facial_hair"] = can_change(APPEARANCE_FACIAL_HAIR) if(data["change_facial_hair"]) @@ -121,7 +123,7 @@ for(var/facial_hair_style in valid_facial_hairstyles) facial_hair_styles[++facial_hair_styles.len] = list("facialhairstyle" = facial_hair_style) data["facial_hair_styles"] = facial_hair_styles - data["facial_hair_style"] = owner.f_style + data["facial_hair_style"] = head_organ.f_style data["change_hair_color"] = can_change(APPEARANCE_HAIR_COLOR) data["change_facial_hair_color"] = can_change(APPEARANCE_FACIAL_HAIR_COLOR) diff --git a/code/modules/reagents/newchem/other.dm b/code/modules/reagents/newchem/other.dm index c26d8bbe983..4fe016f49ba 100644 --- a/code/modules/reagents/newchem/other.dm +++ b/code/modules/reagents/newchem/other.dm @@ -198,12 +198,13 @@ datum/reagent/hair_dye datum/reagent/hair_dye/reaction_mob(var/mob/living/M, var/volume) if(M && ishuman(M)) var/mob/living/carbon/human/H = M - H.r_facial = rand(0,255) - H.g_facial = rand(0,255) - H.b_facial = rand(0,255) - H.r_hair = rand(0,255) - H.g_hair = rand(0,255) - H.b_hair = rand(0,255) + var/obj/item/organ/external/head/head_organ = H.organs_by_name["head"] + head_organ.r_facial = rand(0,255) + head_organ.g_facial = rand(0,255) + head_organ.b_facial = rand(0,255) + head_organ.r_hair = rand(0,255) + head_organ.g_hair = rand(0,255) + head_organ.b_hair = rand(0,255) H.update_hair() H.update_fhair() ..() @@ -228,8 +229,9 @@ datum/reagent/hairgrownium datum/reagent/hairgrownium/reaction_mob(var/mob/living/M, var/volume) if(M && ishuman(M)) var/mob/living/carbon/human/H = M - H.h_style = random_hair_style(H.gender, H.species) - H.f_style = random_facial_hair_style(H.gender, H.species) + var/obj/item/organ/external/head/head_organ = H.get_organ("head") + head_organ.h_style = random_hair_style(H.gender, head_organ.species) + head_organ.f_style = random_facial_hair_style(H.gender, head_organ.species) H.update_hair() H.update_fhair() ..() @@ -256,8 +258,9 @@ datum/reagent/super_hairgrownium/on_mob_life(var/mob/living/M as mob) if(!M) M = holder.my_atom if(M && ishuman(M)) var/mob/living/carbon/human/H = M - H.h_style = "Very Long Hair" - H.f_style = "Very Long Beard" + var/obj/item/organ/external/head/head_organ = H.get_organ("head") + head_organ.h_style = "Very Long Hair" + head_organ.f_style = "Very Long Beard" H.update_hair() H.update_fhair() if(!H.wear_mask || H.wear_mask && !istype(H.wear_mask, /obj/item/clothing/mask/fakemoustache)) diff --git a/code/modules/surgery/limb_reattach.dm b/code/modules/surgery/limb_reattach.dm index 3386f4b9366..90f2d9afed0 100644 --- a/code/modules/surgery/limb_reattach.dm +++ b/code/modules/surgery/limb_reattach.dm @@ -97,10 +97,12 @@ E.forceMove(target) if(target.get_species() == "Machine")//as this is the only step needed for ipc put togethers if(target_zone == "head") - var/obj/item/organ/external/head/H = target.organs_by_name["head"] + var/obj/item/organ/external/head/H = target.get_organ("head") var/datum/robolimb/robohead = all_robolimbs[H.model] if(robohead.is_monitor) //Ensures that if an IPC gets a head that's got a human hair wig attached to their body, the hair won't wipe. - target.h_style = "" + H.h_style = "" + H.f_style = "" + target.m_style = "" E.status &= ~ORGAN_DESTROYED if(E.children) for(var/obj/item/organ/external/C in E.children) diff --git a/code/modules/surgery/organs/organ_icon.dm b/code/modules/surgery/organs/organ_icon.dm index db6ffd81a2a..0488d768adf 100644 --- a/code/modules/surgery/organs/organ_icon.dm +++ b/code/modules/surgery/organs/organ_icon.dm @@ -54,6 +54,7 @@ var/global/list/limb_icon_cache = list() overlays.Cut() if(!owner) return + var/obj/item/organ/external/head/H = owner.get_organ("head") if(species.has_organ["eyes"]) var/obj/item/organ/internal/eyes/eyes = owner.get_int_organ(/obj/item/organ/internal/eyes)//owner.internal_organs_by_name["eyes"] @@ -79,32 +80,32 @@ var/global/list/limb_icon_cache = list() markings_s.Blend(rgb(owner.r_markings, owner.g_markings, owner.b_markings), ICON_ADD) overlays |= markings_s - if(owner.ha_style) - var/datum/sprite_accessory/head_accessory_style = head_accessory_styles_list[owner.ha_style] - if(head_accessory_style && head_accessory_style.species_allowed && (species.name in head_accessory_style.species_allowed)) + if(H.ha_style) + var/datum/sprite_accessory/head_accessory_style = head_accessory_styles_list[H.ha_style] + if(head_accessory_style && head_accessory_style.species_allowed && (H.species.name in head_accessory_style.species_allowed)) var/icon/head_accessory_s = new/icon("icon" = head_accessory_style.icon, "icon_state" = "[head_accessory_style.icon_state]_s") if(head_accessory_style.do_colouration) - head_accessory_s.Blend(rgb(owner.r_headacc, owner.g_headacc, owner.b_headacc), ICON_ADD) + head_accessory_s.Blend(rgb(H.r_headacc, H.g_headacc, H.b_headacc), ICON_ADD) overlays |= head_accessory_s - if(owner.f_style) - var/datum/sprite_accessory/facial_hair_style = facial_hair_styles_list[owner.f_style] - if(facial_hair_style && ((facial_hair_style.species_allowed && (species.name in facial_hair_style.species_allowed)) || (src.species.flags & ALL_RPARTS))) + if(H.f_style) + var/datum/sprite_accessory/facial_hair_style = facial_hair_styles_list[H.f_style] + if(facial_hair_style && ((facial_hair_style.species_allowed && (H.species.name in facial_hair_style.species_allowed)) || (src.species.flags & ALL_RPARTS))) var/icon/facial_s = new/icon("icon" = facial_hair_style.icon, "icon_state" = "[facial_hair_style.icon_state]_s") - if(species.name == "Slime People") // I am el worstos + if(H.species.name == "Slime People") // I am el worstos facial_s.Blend(rgb(owner.r_skin, owner.g_skin, owner.b_skin, 160), ICON_AND) else if(facial_hair_style.do_colouration) - facial_s.Blend(rgb(owner.r_facial, owner.g_facial, owner.b_facial), ICON_ADD) + facial_s.Blend(rgb(H.r_facial, H.g_facial, H.b_facial), ICON_ADD) overlays |= facial_s - if(owner.h_style && !(owner.head && (owner.head.flags & BLOCKHEADHAIR))) - var/datum/sprite_accessory/hair_style = hair_styles_list[owner.h_style] - if(hair_style && ((species.name in hair_style.species_allowed) || (src.species.flags & ALL_RPARTS))) + if(H.h_style && !(owner.head && (owner.head.flags & BLOCKHEADHAIR))) + var/datum/sprite_accessory/hair_style = hair_styles_list[H.h_style] + if(hair_style && ((H.species.name in hair_style.species_allowed) || (src.species.flags & ALL_RPARTS))) var/icon/hair_s = new/icon("icon" = hair_style.icon, "icon_state" = "[hair_style.icon_state]_s") - if(species.name == "Slime People") // I am el worstos + if(H.species.name == "Slime People") // I am el worstos hair_s.Blend(rgb(owner.r_skin, owner.g_skin, owner.b_skin, 160), ICON_AND) else if(hair_style.do_colouration) - hair_s.Blend(rgb(owner.r_hair, owner.g_hair, owner.b_hair), ICON_ADD) + hair_s.Blend(rgb(H.r_hair, H.g_hair, H.b_hair), ICON_ADD) overlays |= hair_s return mob_icon diff --git a/code/modules/surgery/organs/organ_internal.dm b/code/modules/surgery/organs/organ_internal.dm index 248da9d1154..fd61410bdef 100644 --- a/code/modules/surgery/organs/organ_internal.dm +++ b/code/modules/surgery/organs/organ_internal.dm @@ -499,18 +499,19 @@ if(istype(owner, /mob/living/carbon/human)) var/mob/living/carbon/human/H = owner - if(!(H.h_style == "Very Long Hair" || H.h_style == "Mowhawk")) + var/obj/item/organ/external/head/head_organ = H.get_organ("head") + if(!(head_organ.h_style == "Very Long Hair" || head_organ.h_style == "Mowhawk")) if(prob(10)) - H.h_style = "Mohawk" + head_organ.h_style = "Mohawk" else - H.h_style = "Very Long Hair" - H.r_hair = 216 - H.g_hair = 192 - H.b_hair = 120 + head_organ.h_style = "Very Long Hair" + head_organ.r_hair = 216 + head_organ.g_hair = 192 + head_organ.b_hair = 120 H.update_hair() - if(!(H.f_style == "Very Long Beard")) - H.f_style = "Very Long Beard" - H.r_facial = 216 - H.g_facial = 192 - H.b_facial = 120 + if(!(head_organ.f_style == "Very Long Beard")) + head_organ.f_style = "Very Long Beard" + head_organ.r_facial = 216 + head_organ.g_facial = 192 + head_organ.b_facial = 120 H.update_fhair() \ No newline at end of file diff --git a/code/modules/surgery/organs/subtypes/standard.dm b/code/modules/surgery/organs/subtypes/standard.dm index c9cbbb17906..d481ba1b7ae 100644 --- a/code/modules/surgery/organs/subtypes/standard.dm +++ b/code/modules/surgery/organs/subtypes/standard.dm @@ -141,6 +141,24 @@ encased = "skull" var/can_intake_reagents = 1 + //Hair colour and style + var/r_hair = 0 + var/g_hair = 0 + var/b_hair = 0 + var/h_style = "Bald" + + //Head accessory colour and style + var/r_headacc = 0 + var/g_headacc = 0 + var/b_headacc = 0 + var/ha_style = "None" + + //Facial hair colour and style + var/r_facial = 0 + var/g_facial = 0 + var/b_facial = 0 + var/f_style = "Shaved" + /obj/item/organ/external/head/remove() if(owner) if(!istype(dna)) diff --git a/icons/mob/human_face.dmi b/icons/mob/human_face.dmi index 3cd59fe3f741bfa74563dddbfb8cde1a2e8feb77..f140d02be968f598ea4466a99a043eaf7619229e 100644 GIT binary patch delta 27468 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 Fe*+S}khcH; delta 27463 zcmdSBcT`hfw=Nt+MNpc6AVm-nRFtMj6QT$L(nUd~1f)xoE+yG0C@4(?lqv{FF9Omb zQIrnS2@oLCJE0|kge2dNzxSN`$9LXw&mH%EcZ`oQke!{iSD9ROo6TKCamv~AHJrL`0FY3Y#$3wW;Bf#dhpB?NP8`wy}9=6z!z zkNV#|eeqUnhLLz@dePjkK-&S+>)IyJ`EE^#t%#Z$PaNxh_Y@a3SOppKM=P3Z)k^1r zqa^d#y&P-Ht!L#z)BKJ4@z3)^&nR`gN^;R@)8Sk7$^)2&-y5)vdtuafCR7%Oy_U^B zU$(qLZnD#qY+Ahj{`uM!5!HaThI+kp=PHXUFMDegR3+EV42$r#-c+3WT|53$4n5MS z^Kj?ih~M*@13~_9@wqgo(5gUHUBmp&7h8>x|*0iE_XcptA_%B1o4>BZd|@3^xA%^3Vn!3@G5^GbD%^t2Q?2A@?oFlpCnCpCY(X!2oI*f)gn_pkLw@~&}1NS6`by7YR! z-IXJ|%VNe;hLKWx+?h)gSa~9ExK~H3T^5^`GM2nmk-bP-THd&OBWl=DMtvUzvT9%@3;0Byw=qa zZ`A3BXkkxH)NmCNYp*_2-xNA^vGQdg?=}BYb(5A;N8OI}o3dG9?k3F0IDF;*F0JvD zaa!wGX66P?IJ~z*LWP``7QaTEQW@(Fmy}G4uf=BU?56?n3TWBR82R9yTGc|fn_Fg^C(@+6iwwDWMJrG@-}w< zB>Z#TSTTG(h#{%D&rGH(B^kVz4Gcw(r?>0rKLNSs6SDS+DJaT{vGl3GS!2wNIRg} z%!8LRjv3Z8NhE-6-s>=+%TP|C0M`Xw)(r{WUVF<0b2-v2bfa#;=i)W1nj(U?*R+tgKlofnW>%ZlIb&$gX!R*C71QSG`7NF`DE z9uR3AFBnzq2Xc~EBu_f%Q6$iMH@e}Dv2Zj6iXwe6BK;Y6?wSND7uDjKEu{IVJg1fX zLVb|_ubyMRv{;1BP(o3hJ&QqVcke)xlz7Ct{in0H&433R$gMk_7f(|%RpxbR`t?s~ z#_)`qFJ|?>yoYszC*#1Y%e~HL;@B`0iOML~pD;#sKfX=Q zv?CJ$z)NjEraiAMBVo%UHqNl5?gFKBLcnou!1J7Xazqm-?EPJ|LKoe1gn~Y(WL#F| z)!7sELPCFMyuE*8MeFm>ZcvTKXcFMtyb>BK-DvezT<~Pv?xjp@)4|s?<$5D7#o3>M&A_6!^{a*Vmv%mV8sNDC>5o+=|-xwQ#D zyB14Z_?^Bw<=v~gVTjm{F9vKk>K4zKt)__OBC0oAio^Pm;%}EjWuDIeJo6FAH$C*K zBTU*svz1qs=prl03K~>mBgH0FkenlVD(~~?bQf`OIx$gs#DG+$jlmuIXqv^vlCuQw?>skF>CRGN>g~ zoA@?@@x2uf*KQ$q<-qq+2~n@jd98EiM{J2iI+}8PXnHOfHx~YXB^D6NtaY# z@_@!`jyuWOF*NubIgb&qG~BC_#Hua%Ll_|t$W81-owp@Q2T@H9e@yx6GOyd9?{G2@ z>^DgN>w1TEUp%aVAhwLC!3MFsRk|`4au~``!^l@Tb2BGs_(iMjMx+o+lnRhRyp}Fv z7~R41)#)`L?HBE$2LG}~wa$o$u-I9aw4c-D?JDpVCe(TmnaKA)0cbXqa^*n#-a*TG zuipr9jK;(~K z5=m6mkodLixF`d9tw>c=wTx&pZfl^z?Td=Fv$W-HRL2tm;lnCOLB z%n0~}HL-N!#-V4Qu2g6}pme;|*x zIrmcde}tx$**=9&n_XNyj=HO)^}FWQPPwD46mrEa)_Kv$E}TVv@s#q^uv7{IpxsmV zDu!9PyUjx@;EIS!uGZyltfER<_^=Fpsv%ZuMnA$tr^we_T#g9b zV$O~p6W=q2bNdhJ9phS<1=uUZ8BWj}{_2yio=U{qzQ!hO7(QXv9kq$5`P6h$!j-Th z?2#(!WRRuFsdnT+eB|aKu=Pzn`-Z-Pg(F6@8&IUl#%rNq4P&m`?EiEH36V3nMQ;Ux z7~T12e;}DrkfVR^+&ulCjleYmfA87c0NH&q18@?K11vNFnRu3f;8#?{#46*``kTa>dgG%gW6<3Du?nIr zEY{r&*mFWfc3lrv?WR;B?JPU8EArRb>MHl7IQvzP?G||;!;N8LLV**Hf4DWkL}vHw#XB(*%QLSBbVD zKK36gLR5b}Z_bgUboOi85A#8R#)!jQ$Wh-NX89C_2lf23!uFKlr>}+f01mmccNv+5 zUaQ07HqiWWRN8unN=O07fLz!JF=@-)VN&8JWQjP%oe!P2G7Es+37vgPhblPp!tUOU z%Sc`1cCxb^A*;9DTPt;#O=ALSP-iH0; z6M$p4J!s?B)3pVH4{ z*OVXQIsD<>#~(R<0n-=g&2M?-$$-*~^IfvT5I$V#xq0_&SaLFxQgjdGFe z$rov&=B1A%diC}{o*@E3uFik(nt@32W8WpJ9xOsTR_4Ox++1g^;m_o&&>bm#;R~n^ zGdl3>19CWIjDVFG2(pi>ke<5}9cQr795X;C#9%D!N?*kZY3L9GX8~(Bwo$MBJe44*u3xn9Nc8y>N3t z(1`^4@%Q_W`lhvzc>PI{RcQIPX-$C17Yxu?FhDoT%LRx5SvQ&W&5`~T?w}f%m2tOn z!`pOQB$WvAA2Vqapzf6*`@cHU3W{eR*Jt+kmu5rd-Hi2o( z4b`!O(aq~7T3wsJHwvzNzc@k7x_2WV$G({FhyO6U5!mko_A7+Vj+=(1kDdnWO< zq^X_hIcK3T$DnY`r!Z&bzzsWxv?hae@>jIo2z|SzLDV)v4OP5x78pAm6Ja^IHLGmHaM%{rv|M(~} zhrPb%W1TdbCHcij4d&gIDA}6OLL94w9)~S5OYKOG&#i3RnznDf-xS()>QB2gNQ2Ag zRKQF;!XpkYzla<&;KtQ?7#(!xK&2b7m5)#ox*H0s z}TcSI_u1&KJIgb9q@J&!8~#ZRM;$$@Ny7gX|A; z6qp!%1&C9kv&HX@x3`3`j9JmD7@dQ@ zL{b8A#G^07$+#DfPLE;XayW=MTMBhX_7TYnsPfqSy4&>BnH1SJ^t2ZQ$!iwn>KYoL zzt@j}5AZ}XkHuY0_gafD?cS%cniU%zx0$g9d5MNb&demn9+U(9Z_tGBYsFZakz;Hn zoMg;5>mgp_d4~3b0>SSz6w&yU!fW;XhZ5r8`3S}s{8QVw*?iof8gr|Y$33j+#N=j>#5E@Z9yU`! zYS}D($+?Ac^6cy036aT^@VLnnR(nKxeqL32>rYd<4?l&|R~W-f`rTUmuD{SDT#B&T zG}3~lBqiP?T+C+-XzEb`LY7w#s1{wjp?1w5OJku+TbADE-@-rJlzshON9-KNF5E8= zi3R}zbbXzH@bsZ5%>;}59TU-> zRjo1?7xN%4nnrh2#uy>h4F$Bs03S_pjrQ7~7JFBa2(TK*0x05cHa)1KkL{Z=aw*@{ zMpv*6c8+hnF`%+CV8=ni{FwJr-{)@JVXKL!q1wvNKxuUbvu9KBXc#W$jH>eLdVbUy z)%v!#ytwtuxghJJ0LTQoj+(;oPT@~Ka!O0>V4P#5;d}d)r3Vjhxk(-?xZkTQ_1r@u z{SKfp2DFL$EJ^xYN2@U_L#oT_o{XXeD`7-=!_bqCyEDg`{An=9D$kJ|u@7T!-Q3p2Y{yRDcB)x)Gte?oK{TZRRU z=lG=R$?R&kU6Q46i+Km?sF6`4d4J~Wso|Uphi^EOfrMF@xBKTEa(vJ>X%d?;!PP1M z2=rzt6-NYZ;M}{Fy=tpB$ZM4bK|u|p*s4_&s7AjB4Wa8v&wfsf6eq{#Wgy070ZFS; z(8$n8p>M&ZKRz3yyVU-SSW!gZBP{4##rw0_4iEkkABvE)DyK0f1-Y$tRr4`V}g|jZt~C3AvUlWAydQTd64zG$4-JFjUtGvl1tsV9Jlhxf zg&$8xYU3i;NF^bg$k(Y+>*t;0Js)1o7Iak?1^B25xdW z)DLs2Rnw!%%aZ${hCeha(lG-*QjQAOl$GotksIo_m{rLIdb*^fNx~{1$bV ze#~b#mbO0THLR@Um1|O1+~*SPSciGm!a`>VmrpX6sM?hOOav*yInY#vt~rHCPX#6e zkr82h_0N-sq2eJYbz)I)^PjcTnxc;1fa;AhFo?*rx?YP8CUvR-W-ce)%lu?8Wgl5L zk_@Bo5_JxPG%NwkU#z(&G7TQo2-`;21;qbkZ1uxkPB zmtUKCA=-ucW;aQ%Zq`Y$LHW3YIj3CF>iwkMbLWJbCx&My4LFy#*z)fHdr#;b^}bL& zs;!gGtvfBEWV;P-*H`Y9b~Du0s7_r!+EILCi_GV>{syQfgjx2MI+y)oPE`ora)Bj% zlh)?PvqZS&1!(xnnpV=t{V8Foi6RK$+d?gckr!417&Gz>G`C+%Bi0#TpWKnUkkQNt z>6oSbQbm!O;$ND62Q*5E4e3SdaHiegPdsOXLok)mMfXh|?Na|}$#2D`VDF}Vet4B_ z=IbHR4Km74z#D#|%Ctu@awb5Q?^9&RQ8hRd}LXt%b}+$drdn6dHy%` zQ#IZTL};9Si*yLie#9`{B!s32Pru3PJ?#iaWj{J}zT7)PVF&QM`>34{>r}CbnR1Cb z6sHh@HZ@A4hdguHfBqFRL0+96$`kn~3_5Z2|7fiAH~#uxi@F}64kbyLPOYSrWeOaI zzyqGlm$>ibcD7rEW|iXHx{j}Y2pfs1y|Ix)XKyLeoN=$m>psW6Dp+>Y<p0zi-d-*wkb|fdMj|)Ko z=Rf!%6BY@I+aB$TTY3))cmv7UW=Dv6v%)a3cACo``@)t!vKww`1-}vOo_S6HoMB?4~Nj{a}u}UbV4FO8JkO@W)vn}sY>=qd8 zRrYEyrXW|BrD3hhGCTy`~rEx09T8!4oo7l<&I@ z+Sg*ydYcQ_>XEU7y(cx5I|LMvP|Z$-fGF7>(sH;(D0`zeEtb;fX*rv+O;=hJTTRtSf}c{ZNCDB zuJ8sSao3BN_>&7J#{%w-tJLQdx)rd2eSlHtoXf9rk#6 zC{_}!CzMNQ^Z<7&WwC-8{+I|xD646d6gz}F4azvi3u*!S4C;CkrN5C42WsLx9_xx} zTu4Tzy2e5;EO;*N2wo+>x`WbsfGtyXC`KOymqq0KJY5oq(A%rr1<0CPZA%b{2t-HY z)_oJX-Zz=TI}2^R4O40g09j9!?C~CpW1I86Xb#`0@t9b$@tWHkD+b6r1sVPjTk$kP zA=6a`mRai?=s9SVwa5yI(HUz!ihy-Dkh7uQae~kQ1FFxQYc8w9ljr-jHlm`JxQsmD zJChT6mRPow#ybG8kk!Yoo(d)f#>Pdn6gVqyLv~2ERG~Y5rp#94O9XDVI?#ZdyPmv`C_ppc(zTxH5KGvJS}lWzCZw8VBHBr2M+C9iVI zxE%|8^3>4Jdw58B=^Di&T)5Ivulry^ZBK#e4*#qN8tBDadLQ&KWctsX7foLLqPj{Fy3-mhx7r`tRYgn9VA|TN9OjKXWAn|FV&V2R)OzP}CTDZdPk)>m4xO8M`{oXR z+A7{2*qM#AEJ07@uLdRmxpnnfY&|Q2A(#2ky4rO~&!%3Y2;)N!co1-{O_NfPVFs~n z=8an`vi>GcArN{{`s?&8R^9kHxvx5LF!;{~OO*A~O#F^phWY-9=-*? zq!$rm64@*^jg-%v>OqVrc7TbUAcJJeFEaVoQ5gcuH58A`6o+yKDZrAk74coSFvEwi z1|62<=>How>p3;zYE#HP^b7$!<%PlPgB4;Gn9f*yVyKv>er)QJ>W0=-m|XQErD(^ zQo;(C2TWie?n9R?)ZCNkx4>DP2l4wVLsF~8cQ%IZ)pu}}rNI4fZGFK)yS6y*g#hd3 zk0NEvv#d>YH?bh!R(6FSbhEWud-v!F9A8R@a*)!eduE5zH|;d+#-&XcV<3qnzT^zL z2~OlUf1i%HS;u)0|L(6~=xI8-MJYiP?S|5`pQp#xzIwm*Q@ddk7?a^MH=*=%6 z%3gK%39O0^DCw%E!IYf!9G={NP&0hGy-H_|l#9}bS9bP)3LC@sXt-vg?{o|^m2D_r z0FhnJefMi0m{jk$Q95>YAn$XPzYqQ)1OI(m5U}p9ni@dCTP?N<9CiA-im|bKFlpMx zrrumHHKb4~llXWtTuN7x??jj>=j*(%#7+>%s^l%EM^N6Y7lF=U z=&knQHXFU*o*cRdeS{rGA^N$Jb!_^IjJgS+D(Hc~#b}mem7;fwkXr-sHFflD>}q3; z@6V{az(v*Q_%^%kx%_5J*KjJA+DLpI#s7KM+U6xMSM}%*ACBJJT(zT^>t#$fc;W$O zM0p`yjm-X4bzhE)E80H?(5IOB3$4j-RY`mXg_Tc@c~0L=i@odJ4-~F@Z`vOc@xEnU z0{I^0R{G$2&3(6LpxzWg`62U6UQ@O% ze`>YTf`=hD-KT>LCx-ag=XN5qd1IUZ*ha6`E#B#>TGQ-ImPFTGdl>%hmIWxRrTzLWsxlfbm9Y~QWB+YfD=vH{(AyClhM zS}3mpK78!UDmw37AGZODzqb=Dub24Gc0a_RUzDR_rOzY=NI9hdn8%KwX9s!Lc}>l8 zSMkkO4Ch5v$7O=(khWK{CsSlB`t;<{azt5(Y%@^1_vMQDfWVzYf_Rpw z;1y>=D7N}1n1Z>QLA7oE=p3)*a47k63Mo4ke%2~(Q>r$-2*Xn6(dt7J2|uwaM$Ejf7Vbq4^+>+tIn5OqrdWvHb)gW!1O%Jj)b=v|Npsr8OxP_OoFoG*LJthFUDf?1g{hZ|=wOgb?Jhlvz$X^1bgic(Ql%#W5?0$mumh zEx8)~c6!Lcx|;om;RNe{2B{>MWdDjW>6N+a4q@>j7-Hn9Uktb6yb z-2)?z>qCBjR~YiyeyqYCY_c+3#Ms5h@|aScJ9yoZ z9-N(P>%B`4c~c60iWPIThDn2=!rw3z{GyW%^>jZ!u!e#m<1QMGHbicRz3WEmUvOiYhTi1Q?E(TeEn_X*5R)8is=7sLz5F;AN3}8<2L??jWCV@^xY^)e_!L9&r-QlB)!PWac>oH!$UL+kB`dXC+*@k-!DZ_Oy8Yx5BDB<-<4^E2oOhp4$@nYXluX3@&$MHW9pV)I$=~L>sB)L$# zV3N_@_9S(+H#2q8kg`u(#{B3Bwu290ARKBt0O^Y85!7ol({4{qv2TWEmxp>3uxsEZ zsxJE8djHzw-8*hVj>>Xx+gDF`$M3(9*q2_f!<>);xUP8z}V&ZC{3rnu6Go#S;! z>jymY%iAuuZ{-0Dkncv{<*hkt!I)iu8zXq^>S^nHf6Bm-KVbMH=-N$R2l!=Iai>f? z4$K-AhChQJVK-(<08LU5Eb@@FIr_wZ^^r3USb9&lEzkhY0Z|Wp&4nrt-4PSwxOUym z`?=7PDM)Ua0}qyA5Qxluj_)TzlEXerRLY6vuhYdl>jT+fJv?)gwUVR zgWc}8R@r_5qb4$#(CGy6D)=NOfSy*k@<2ea@~)joS)7ArY*SCIOr8+Xvg~`&K+lNh z*WO?o1Y&(*nmdOf!dxcg*>gjD1Zjv}Bh-@#)JUUa|B2aYFAsw^ApfqSMIFX} z4aa};kN>7NzJHB2*2*{Fi{n35Qyj2FD}D9>SUK6&8R4&gdkbgc=9pD z%qpNIdVA{-2qo*y`2u~y0GGJlJK|K3^oj$hODX4dKPZ+pZodth^hGNzAnDC5E9~CH zuhIlA;hXf_xZdg|%W1AvAF*`7O*P5ccXDG9kjzCSd7~@r6T9lJQ8A(6E5_8)GQFV2 zYreCOoRyU&YJw^#xM*t2aN^X9qcY%l9C5oWiNi%^MQaINz=tc|5_(A@;BBK4(4S7M zO*WX7Hf+=v*MtYcJySGd8kO{oo2@x?zB`c* ztae#_8!`U&W9>*;aj}oNxw-wyP{9)<4(anDYL8+fDk|r@a{si7pQ{MhEP11$S2b`q z|66r6Si`bhHX(`@L|8WB!KZE?Kh!Oz*h#Y4g_n}1$jv8gI=i|ib*1Vw4AK-ifxFn$ z&6cn;AJ0(Bpa1+gFfh>VUxKW`*wnOz$%IQc$V^@4><5e!VAHBH; z-l(pr=}J@bwww9&W_zp`VLAoS;KL;GO-{~$E5qRCZ zcjs1Nw7`YxJLc{viXU-6S9%?g?IJC5>*^JyA z85#;3I4v(P&o+G=BBImCMg7Vc(iB8oXcYReBY96$bgNNxuqC|<2`Y>q@rSghx4M8R7?&M#u|<6ZFL3EdQ@Fq-7nw1 zT}x{)mVuFx56*cX+Rg-ZD+TX8izPR+K=t4re~it{7Q-x2 zrKP22P>t!$>7P%=2Q$=+_PND+tnKhC!!ZhT1!ZOatE;QG8!lLl;v1`u*9k*HGC>xnG;T+CKz%HD;)*$4t?LoTLv=@+z(+~Pan(9(xZTor~QqtE} z>S202IZ;jACq>z}Fpy$#CUEI2sM<;?lCjPCaa|N57H7~n^Hy)utCt;EDz>N_I4%1` z!wIjcp@uK`GzheU;wd~LLRk6eKNX;*k)!p!e|Y%3q-pUp)8dEI2?+`LuW!;VPDe*4 z*UHSyY{4;CKQ}t%MUsD(u<0JB0>Z{9>E*FcM=5PasegWi$)()VNUHK0#^HJyAbb(| zW`D$z;q~Fk$5J@NPuRA_^yrb+JAjAafy<{!_Ho}P0FHBu6elZ7h@X(5xx2fY!d~=G zOr+t6hP;yFE;C~2nL3#A2@4L-S+ z45_HDHf00V*v-xD>Dj19&QJ8x6lHgCTeEGB)TSpbELuCOrxlp~bWQzp#CXZ2!ci?+E8EZB{)@{Brs&F= zh&UV9%!M&@NdLRl$6(dRd@145iAoBWgu!ktc4Fkjr;4icY|T%*z%8&JA1bJD9jmbF zePNt^$6iXK=u1IChqH?dz{MFSq~h03L=sg4)~nDOVnXj+Cu(IkDWKEpkbMygQg2Zc zasAF>xi>Smwfa4DYfjLK4{Y3rgYwZaGvgKRjaFlQ1G$sqD3T?6x_=6R)H`OY`($s1 zb#hI*BxP(x48ASEYjar4^O%jEK)1IHo7>yBO}OL`jU7A|V0%7_0p7B1$7Zuf&C0CSU1^iJ;IeXOSgb}@w8B)+9>un43tcsCtH518O2MT?|Ap zjtEL~Nc^_h^3_n`xUK7f>0`~Rlb6tLC*Ym|SKfxoKm(+sly6FnN&R{nC8Tow-Rk=r zyM4C}0s`t(K(3$^xa$7al9TVQ;&&Xrf^RjC+^9k|obYORQGcaf>C zGoo#>)82V&##AeY33@s)9+jqZ-jK5*Z*JWjdOxyAXuB2uK>FJg#%oFA${f)B4#SgM ziVRmkxOrR8`j@OiZu3i8|8w=r5Yn7!0C*n_4V~*?xcg<5AY}LE+e6-YH;OSH(zr1rY@$G<)DSN z1*EzcKVG_YiS13qHFSS2hK?W8qCAC`T+ItjW&xD`&(QUenj zUl3~RZ|*&e9lK$L3amq1=U#DiF?@)xV9o~5AL9*aE_yGsN;8U7J^5%~&v++Lgna>u z>$*PtgHh=L)_2dD%P8XhDoLr+kw755z(zlnm+j&3G3wS+z|*=KRbF` zcdIdAqibZntS5ER&voqNIKp}b(AThv$wy-06zAKwB(1wOP$;Nye*UU}Lxq58lST81 z(5www{;HOx^xNxuuLPz-*-+$A7C?f2e*5XG1i5b1<{hD-7p`hmVtr|aL~%3Z`zGuS zTFh$tb30qGAczLm2*ZN5*JEWy36qq+YQd`;XZ!Uy@E`#ChjyuZuByG+vhKKaZ8FljW9>vGs^i4353$ z`g}t(_(I^_A-wnS+rX1&OjWiEvd2DvD}5x{393N(&ngM4{SDy3g9l!qgJG-HH%1d( zVzp!aQ*C9bfP-i*K4~YQ(a-#)E4Zg*%qN*Jd{WQd<0yz&Mg|jD#ZE#4>uqDgo~~T4 zKgFW(CG(=9ydV+vB2#Aqb|(DLB?36bs&Pr<#v+fXvNzg%Mb>MOm6wYduumn1+ry6F z5i;fCO=EOyg@MI5C!T&uEIRi-Z3_yMTzn6hub;0oMk~l`WI;CxEUSO6F3$=(q^mns zcd!YOR)A;`@JxG(U$p*(*4bv3FukRBpccKpX*>+}ak6ZSebz&`j5e*>yPepJ6+qhln^j@r&)bOZG$oUl8sH+cG7oVC8ae1144>N&w zJ~pm7x5DEDR+K-GWS-6N04s+!TfPYCaOH8RtyNDv`^j3$d|FRt6CCMRmUOcN?D=zW zXgTi%Jx*pdK3U&2etzGhz;SXywoDoA36s>V!v_CgPe|I@pR)yLL#8Ra5+&4QMZc}B z4Je$;v}Gt`fzW;Ze<2lzir?l8k0}S29mJ&XU)4#1sYz=8QA+@EstjdUfz+neRSs%pH%blzhL@Ay8Zaf zofka+ocoHj@P1-Z(m-y#3JfAYWmj>&(W+n|s6U!*oFj+4pIQy|if*QitjuAWDy1nDgy zA)oVL3{eWfvP8~ikrNHSEtfZL$f)}X@tqYFO+*XDo#tJit&tXRr;Zj^Rqe%{{w(w9nU zC-;U-zppgM#Dpy%1F?U)pm8H&4IB$mpPjS?mA*KOYl_`6)NS6v=2uM3Vyn`(cy)-; zrZDiiKELO<$lDF1Y#4)H!|F)WykZpr4vT-Lp0u*^)J(%}zBAFFl>DClcC4qS2I62= zIDC8WXX)YtO3xcrk1h?JF9gm0gi+@L0Vz4hO}7SsLo!b&AzekQz0`7%v9|LZXUzpQ zM9}`V{TJ8R>)m*>zPQ(ZYv1g4BhcJ+KT>Us+#5IsfuK7M-HO8B*ZF@?Js#C<|H+*2 zyEPK=t^HZSsa3^4O#Si_2JhvlgLxToot@_@ycdt{FB?XlrtQ3cc2Lv0sP-D_7QKXj zwNQQB251GMXWQ>7q__O~Y)R=abNOzud9c%k62IpNGzt221y8_IP0Z>#6$X^V5*x`oOG% z-Mp580Xd7uk6-Kh;(sA&d0|ck0#iikmS-5?l?<7(yX+`e#;8qRpC3FrUkzrvz_;fc3 z&N&rx#r#7mPRP9aGA%{h(z>K`COcN`eXJTu8!SfF5{8S3f~ygenKnr}3v{;$18D^U zJX8o-x08X7Aq^!a7{dA8{$m(qqr8pUXDk2PHnzpq-at^y<_I@~g`W-|aHw|ez1M++ z`my-?E`pBjQE-%Wv*dd=*xSV(b9eP55SCv){a6MLG*kyBW-P(;XEoB&xq#h%t?<@- zZtLN~2fr=-C+8dFv?GCns;9$++N2=Dnx$8d{PM0h(Ov75^qB)4C!_bzAlCzT1-7Sx zM16flMTO)7uQ6HQ@vWL#Rs>c5*HXVn`>5DoP|NWXuHr~S1Wb)@D4jIJn*V}IY% zgM8;`HV^-6#*ofK=Klg52v8gX9wC4~|MulIkpKQ);C_&Q`#v2#|N38G)PIYPHpnco z#$1y0Zm9O~e>qi3s6Or%zE8Z|7KgSpo9Qc6)E?gx@N_a0l%aOC?n#*6YsDT+D*XMT zb1#UFA~Pb)z%0zlYGG=Hib}>9D$^d^D_FwtFo8f-`WJ3Ex;}oa6w9E%mn`LIS*X7Acmb1a0!D@&4S`ZnQqNLUURiUFv(u??fb8g`jIOj*ir%GiZ z;Am2rQcargIH4MwFP0JTb4Te+Iz>$9b5d0H8wl@Ae4HX1GQH73ZHEbah!c?>`|54Pxi` zWfsrR^UGYpAd~A<;lCp-7#AAFz<+REt3gdvTG@Sl)Hu)cf4$)u@~QUd|8g`#*S~*j z9RC+=gFgPhHIDz8ZQPa$**D%_-LRhUJBzqatzV_Qt=IRA3){k)RJY*~nv>$^R;ryw zVoBwv4U%V-?PJVMO&3xCtx56h;$qkK7+@$C=((U`wh)NQayPL6HNb*Yw`P%SZfdnL zj?D&di9I=hQqunE_wyL9=dxofRHYR$&iizV+O7eBavWB)lRUod5frBUED`&gk)-#u9k4bp0 zc=)ffib~%|qQSvh)mJ^ve9C&&~Ys)7Gk03qqG1f)GQCqo23@y1Qx z{)QNeU2lYw2Nu<9&FW{?BF!%Rc`J#r5AtC(63hnLg;UE17m=tFO*~uQOm<1?-k4XT z7e#d~uX`$VuX&nF#gr;}&bTKP5Lim;)?fPU7e9AA7`#S&RlDXG z1^9)!{`C)Qr~U!`zMt<@=xG!1N5uW#MDzc@*8l%^ssb+=a*@32T}qT(dd+J37v;`8 zFkSdS+p?-Th$Yr%cXmz~+uN6eUg58{Cj(o(F==)J#3)wV-yclw7a)`?6=v zR3EnIgen>;QqklBGERu@N2HWlw%6z!0-7;s5qBdW2;ez@ zCi+fbR@+^IwxF^n-fsw$Ap1bP=%kGX9hd;XX?Vj-CS5d-;l^rD!cvvt%G(Hsf44Ri z>|X&AWV@}+=%29We=B;S>)(GfRrSA&?O@mcQ)vH-zyGb%Vn3U+s2hdF-RtAX$^NH$ zXV;Ue96m%uG$MC>IXT~eWa6fG6d!Hx|0(WDpqfg$G-xY!+k&`3H=AM$v;q-jQ(0U< zx>ZzM2wM^a0a+tr*u&GN6_8B^B`mTCvM-T+Cn`&nRhAGiKm>%y8nzHZmNymrXU;$8 z|IbX%%$YOiEU`Fs+Y^feiuA(}hH-B7_YK`%9MuJ$GH*qUQtDm4Jiwm|h zDn;1!bkzx*2!Hb7VJD+WD`6wUJ!P95p{X9KaRrv@a`DVumEGl&3n$A8kqwQ43psQ-4ReE%ODOhkJO$w!dyQk#{=(&=!kQ$2jPH;qhJ_kK{wH z{h_?i2>91e=bM|Bteq}gaHbW@z{~cCcWW|XKfx5mHixYDoL)s~xC{hK1u4(v10-AM z2Z6KkFzHhZMRYWTT_llc2NYqoY4fJ*yILTsx+JFrZ*oH|EENS#lvdB3ZJO|tHu-%3 zrqAt+QLyxBdWGUcqabrp4ozqy0mtFhj`izLzg>?-{nLCA8rX^2r{HvLoWHAUi<|2E=bF zwLZ_dnF#!^%QwB5Il`)jl}tqL#+=r(jF%H&5@0zwbBEI{teU?=rI~0|qCzt!Oi)Z@ zpZk;T8b7 zd$7wMK;atBXp;x~T&K+GBluHV`mIWUWwuk*vgDU(C20Ry*C;_SuVQ`nL1m+s?E`@? z-qGK$M1D_R!t(-{b%DyaT&`&N9-$kxIWXcy&Zy3Ym8ydZ1E-OV9gFe8d0>V zr65OU=eb1uu2O+u=6Pef$0o&HMr(@cuQyE&N2OItcY+@i7y7;=$6E3Vc1I7Gx^y7; zHm{r$q4(8zMJ!tNTCvHiTY-HYPaf&e1HFW+90)X3C9?~U@lF{!n5o>L(m@wg^P1tq z;Wd`UPyalW!)&bu%ZLk0v@aoT3Lu5p)Vm*~!EcNsT)ZGITse6cK?2S+06B7VMmSee zlvjS&66;8B%A}i~GAQ-PeqpmGRp${j_IVEHpYaMvp^jzlue4;y2&>ym`2F`wb(sSP zz%=_$XEIzq@iQlN*<0d{HQ4L;A?^2X2z?LOVc)L)7Y<~@{{PR@zQn_%`cpr|7nSLnB;e7 zo}vHvr5ze-COm#PD0Zf#_u#C#zV2P+ig?Q*t-GV=W$!pgC~5S%D#e#dB=_dtKb+XP zLhPI}NR`-wLbY<>8TKj0jbtpGFHCgv^wP#8=)eC5`lmO#^=>(8Y<5G&ljdr+$N1(R zV;rEqbx_A*Dbdm22P^$(wl z?sbS<17VAA1z`Bzviy)Nrx>h@OWxG4ANTW_6*aK1_);@QCdE{zY^uC@k?u}5Wj_~0@crAKyMgex7DAsPz-;u(_80JI?8WnW#Fw(I9v0wQa zWE4z^F299#|5z@d5;wcYBV}%{sw|f~sL8@Q)aT=LE~&c?o~elR=3#3@AYoFXGhIk;zt5Q&KI_wr{`i#s;ae(&5%$f0jVZF!B2UgloShko{-?vQ!yMTAkO2VNw1MR z#{&A|PD-#z4P7Pe^5umv8pb~JQ!UHv#L+{#HmkPHnpscR)v(=9Aj;obxq8wR&Lk!# zT2*)JU%!6clUEA$z~XsVj^#tUJQqHX?5LhA|2ZXG;6oVkxt`Q%?B0`EDbky17VOJwM2N2*gMk}vzec4OE>tht(W4oPpocZ9P_>E0qu3wscejqaQ5BZut`M>Y(umbV7}<_OcSF=`l%43Rk8OBlzTNfnOE z8Ss>)lc$Eb;6c;y({lNY`XEy3aX^Ir`XD_%XKQeHeHKIXbS=jzM^xl9c7LGgXLI3{ zl<-AN^k+HkuxQxFQcGXR^t9C!ZC5IuF!jDOuOgp}ASAr0Zjw8_Du}9 zZt1uI%*e{_`?+2Yj;~y-=;OF_5or<@aRbmnoCgUQSL}OtAIf9?ww|}a0SD9drM5&6 z1U}ZoP!aXf_{;5Gi{1|XS!(2=_V!bqu$(!c1~tqpQ}5?0tp+b%bF#q5Xg^qNaV@K; z`@K_p2rkldD$3;&*~6J^oz{Zilh9ttFqvqIo9FYH>1;O1)&FPB_XZ+vw_SgLY%izi zC1^!!o$$SjeWB-f41BG=m+EjupJnx_g0{5Pt%@loF>i_on4T>D7&q=#1qEgS2E`ubX+Zt@4=k;$^7;dk$^mKikUPzF z@!fXBjqTgF11&i#bYCvs-W7Y7U4j8wHH%{B;Zd{~mjZ-s&fIL;m8*6vpzQVQkG{!H zPEN=u&L}=@%CFqmQSBJUx<6gD&4pDsb)vi(WI!aCho{0kMq!RnZGili1X%LRa};RW zy4TAkJghOK*ChrR0Nt|jtKW2N?2#I*U$`#;*r0PE-Z%2G!rod36~7f_W@fsu=DaJ* z=SAB&%M5Bj>=D5df%M8fiRHOEJGi6Tz2C$!8mL@v1wP*ZWK#it%>_8BKzGY zy%^>mszSoASh(<27bYf;ahZG!mrv&^>wKxOR9+6#ZynN}84H#W3_k|QOV;(Y zn^>*<%Hr}_36eneA_qC*v7`K=*sB6DC`o-o=GtQwR6A$qTr0dQ@DMLI0u7)z1P8O{ zyF>ERRr2jB3Z9g>H3Ji%8eV1v%zCMVS>cG7&?~h&u96Pn3{d+h(?H}v#8d5p%2%Dn zmgf2FhgpoieF==Oz;Fk30BzjxVksHNr|Sl#{x}b|ZYAx7XV#}S#eah&kzyaM?>&4a z4wngQ@qzzZCo(g@wTOt@CGe_KPXIBlYTL}wdS=D?TBU-B$eWe}4+cL27I625#=r>7-Ce|G6tUg z>cTSk2y9^bi}y36lVBys&BjMlU(|M7rLDyO>sv9bFK?JV5*|dNyV_nTyc*Z`*4leV zi&kgHp6qZJK|<(q zUAmC`x&fvKtlXNO2wKCJ&~l(wtz&e$7{hL8pic^@U7MVOlE2nj6igGw; z#j$BIbfDgFtUXDxS8|cd*Qi>S8lHntgr<`b_7T{nWW#5a`C9u-2CL!jq+63o^nErT z@~kPaI|;=_cW|-w;y}j>KGZVneHshfrmx=i_xGO&>eub2zZg1v4@I5EpYyygqjfCM?Zc_Z^BY_MF2ORh*2?RTiuf=B3AMdt3Mxuoj z_=5_}ym4|g_K8NrWj?k3gT15%G`GWv0I$n=mW%gtuy0DqYf8afv3h^rdODOp1M!O@ zGZ3a?a=28a*k#l_yx{rtC!-&!wYhJ`?Vyj=ehsYY?5)V#yY*>f-+o;rVgcFW`sQ;dX2tu;d^C{F*5Dw7H#2%T zb{Nes3%Ccjss)iM_UA!VCY!2fYxeA>-fl_q!6=ix%aWdHjmn>I8Jn30pXvN?r$RMP zyRZ6%O1{f6J70w=(iUKv@1+;4OL?tBHL8bkATAz=_c*e#fBCtevuzj9_0z{TRv-Vu zALuW%`M+!e{l_;gIn}>pD3#rIIP2h;Z_{T%5W@K~#xUd}(cEd09x?1=(&u%;OWTh9 zMIb%I2|qvCx0TL0XE`Tu0E(b!;Qvdu&bah=(jEf35MaS`a<-i8O_!6btsRD+k1Hvs(ah@#COZ&vKU`232+UK!wNf z&j=Fl-UYcR*%R0BoC!iPp1bP1*eoTJ%L4rUyz1&|>2ir#S|zcRpPHDM=RNmnuavrt zFyel8QdZCR^`{1WKp=0Cyx1ax)x0(X+E0%JFeA;lZys(IgHF<5Py&3eHn{P*x0?ZA z?o+^4zpR+J?44PQB;a|cm-*B9&r{i{^KLN4e=2kOt(Zc@;NW1Hy%(4Up1k|{bR9St zv)G0al*CxU(@0X@W6W|0`yt4O<=x1F+>h915fBYsFHjBAR}y=vr%D4weF2=L8k!Px zAen^AGJCSyT-d{so;(-nnA<`;pX0;bNs_f}qF&d@z%T_INH00*qLSbz`(tGH4H&X& zxY`ltpk=KdjiJNNoU_Nd_S<=7fiJC4gdZErJ@Q6E+6MDfB#_2_RZl{5m7QmdyDXE(Bv|sFv|0RClK&mJC_>1@cOrqah0J!%>@=tWELA zbuoVl6h4J$)O1dxddYY9vUB*qR~|HpS~-v6`S`Ie67&|{Y_2zxf>CIG&mr#W+zbeZ zrymP8>ST5A+J0H2Pf!pjVFFUNqZ2leSuBYp85ymt^MiW5gq~=iFYtTB-%u)CR{6ig z*MEf9KYj!K|Bt%|V0AqQPGuCT+f?n8Fj%t{f}j#jlLI0}f}=tK8%O~;y|1;bDG4(~ zmJ6{4*ugLK1GF1pK9f8&1la^GycOGk#<6Ve`2P$)kraQR?*40|A@+R+cfY)k>0E_5 zj8vkqck4=zNCGD4M5ee&lx%JTZ>ennpso(YPmz88!njjGz~aluLtknG#)e#pxC;1` zxLls1q5xVTGRY(;KlNG&yzFbKzcj2bDH%yw{}^?S!iAT7bo3e+A(&=YMhy){7VW>`F|Y@qi`fEaqVe`B1^b zGnZkfa2HTxY@}&EQ=*!eqo^qVWVMlHg@>_&I^SGLSFWN8jMa8amA_M+DmJm3h=Koyd`KN%=xbaX%+k@Zrh z5g+b=8TtnH`sF$EDKZ`?ZP|v~{bMoA`LL6`JhIz6@Jn$ZHhA1fXt$c>j3UiKFsyjf zfo1Y_ouL{x-M|k8%_)W{PlSzSE2rY4zZx6W$<)V3=n-FZ-2!{t-x^xRft+ z=RS{xD7PX100QtdNEj>venb%n7pHy|*-^YnxRA9!LCBGm`OPx!CW+3}(wAr;O}&X=OlY$4LdF%;Owb>ode` z>KI6{NlYy80}r!|qX5FzUT|m-GX#zy9*K^G0(ha)+%=Z0_xw=x5;soG+76IQ7r|U8 zt828|M4=Fr|72a^X6fe!%A?NNb_h3%Wln?tHbjTSFCwh<5}MopO)3Fa;H>z>;RIG!rV+l05~E7>1?KiuV! zrP6vhB@DRb6&Wb;y38I2OXHiF>`av>hyClNHOszKeFIt!em{4J>c|qp17Tv9^1m<&CKaoE~{BrG=Xy} zV<2NE>U+@^xowp3enYY|ZtYr9Qqqh*Bv>1#=(C4nwO7HvyHoM2mhBxKC?wNgy)plu zNW+IL3(@P(9B>7R5dbwMs=MG#C9(~&`AP(OsLrT`(Ipcjq7=(33T@O>8+j>v$CJU5 zycrGa%dc3O;+S-*wS1{)eLOD_pO*B*j+3tIUqA8S7xxzv3x~3ZQG=mASg1kb{tZjn zqG|uzDTJAYLs2NX((jR7EMO~&4u_}b&BXYjiy8^&OXwZ%TClzoZ8`MXtS|=sb_W8} zAe$Pr?p()TrGYgnx=c!AQ&Uq_wpX%egyG@9T-SwuYb*<#|LSQ$TUkA+9PxLZsFD$2 zSr?=qSeO60Dc%zm+BXVa#7p-7`8Ex}W|1;Mkr=PpSzW{?_dMoU@!uZ#JBV#Y&EOG< z)t^xYo!B}N=F)VC%yi5|&4|u!Up5zP?e5IV-RoBfz-ak6fNook#PD!hfw@|Xyd>#T z!AML}Bpy&&izA@pgX1Pmrj3M8Scpq2Yk&$yR&#c4{cO(qH~)Lycea?EhsDoWAIU%Z zSYId~poL>|mGsNo_fIb(&~?6zP*Qw+=gJ zTI{x<0UMxfXc|%LZnx#Pq=@l0h;~%zb+vFwF>T^J{=3|^M8URQZ{~!Y?9<_3{a_>~ z94-ptO*pdNdjsfp_RCr*Y*4=++!kuVijV_+@}+89R Date: Sat, 30 Apr 2016 20:15:53 -0400 Subject: [PATCH 003/343] Fixes Runtime When Creating new Humans It runtimed because when there was /mob/living/carbon/human/vulpkanin/New(var/new_loc) >>>>>var/obj/item/organ/external/head/H = get_organ("head") >>>>>H.h_style = "Bald" >>>>>..(new_loc, "Vulpkanin") in human/human.dm, it'd error out because the mob doesn't have those organs at this point-- so I just moved the definition of what hair/head accessory styles these basic default mobs get to the species definition, where it'll accomplish the same thing as it used to while still using the head-hair system appropriately --- code/modules/mob/living/carbon/human/human.dm | 39 +++++-------------- .../mob/living/carbon/human/species/apollo.dm | 5 +++ .../living/carbon/human/species/species.dm | 6 ++- .../living/carbon/human/species/station.dm | 10 +++++ 4 files changed, 29 insertions(+), 31 deletions(-) diff --git a/code/modules/mob/living/carbon/human/human.dm b/code/modules/mob/living/carbon/human/human.dm index f78a80a3c3c..90fed057057 100644 --- a/code/modules/mob/living/carbon/human/human.dm +++ b/code/modules/mob/living/carbon/human/human.dm @@ -74,46 +74,30 @@ status_flags = GODMODE|CANPUSH /mob/living/carbon/human/skrell/New(var/new_loc) - var/obj/item/organ/external/head/H = get_organ("head") - H.h_style = "Skrell Male Tentacles" ..(new_loc, "Skrell") /mob/living/carbon/human/tajaran/New(var/new_loc) - var/obj/item/organ/external/head/H = get_organ("head") - H.ha_style = "Tajaran Ears" ..(new_loc, "Tajaran") /mob/living/carbon/human/vulpkanin/New(var/new_loc) - var/obj/item/organ/external/head/H = get_organ("head") - H.h_style = "Bald" ..(new_loc, "Vulpkanin") /mob/living/carbon/human/unathi/New(var/new_loc) - var/obj/item/organ/external/head/H = get_organ("head") - H.h_style = "Unathi Horns" ..(new_loc, "Unathi") /mob/living/carbon/human/vox/New(var/new_loc) - var/obj/item/organ/external/head/H = get_organ("head") - H.h_style = "Short Vox Quills" ..(new_loc, "Vox") /mob/living/carbon/human/voxarmalis/New(var/new_loc) - var/obj/item/organ/external/head/H = get_organ("head") - H.h_style = "Bald" ..(new_loc, "Vox Armalis") /mob/living/carbon/human/skeleton/New(var/new_loc) - var/obj/item/organ/external/head/H = get_organ("head") - H.h_style = "Bald" ..(new_loc, "Skeleton") /mob/living/carbon/human/kidan/New(var/new_loc) ..(new_loc, "Kidan") /mob/living/carbon/human/plasma/New(var/new_loc) - var/obj/item/organ/external/head/H = get_organ("head") - H.h_style = "Bald" ..(new_loc, "Plasmaman") /mob/living/carbon/human/slime/New(var/new_loc) @@ -129,38 +113,24 @@ ..(new_loc, "Human") /mob/living/carbon/human/diona/New(var/new_loc) - var/obj/item/organ/external/head/H = get_organ("head") - H.h_style = "Bald" ..(new_loc, "Diona") /mob/living/carbon/human/machine/New(var/new_loc) - var/obj/item/organ/external/head/H = get_organ("head") - H.h_style = "Blue IPC Screen" ..(new_loc, "Machine") /mob/living/carbon/human/shadow/New(var/new_loc) - var/obj/item/organ/external/head/H = get_organ("head") - H.h_style = "Bald" ..(new_loc, "Shadow") /mob/living/carbon/human/golem/New(var/new_loc) - var/obj/item/organ/external/head/H = get_organ("head") - H.h_style = "Bald" ..(new_loc, "Golem") /mob/living/carbon/human/wryn/New(var/new_loc) - var/obj/item/organ/external/head/H = get_organ("head") - H.h_style = "Antennae" ..(new_loc, "Wryn") /mob/living/carbon/human/nucleation/New(var/new_loc) - var/obj/item/organ/external/head/H = get_organ("head") - H.h_style = "Nucleation Crystals" ..(new_loc, "Nucleation") /mob/living/carbon/human/drask/New(var/new_loc) - var/obj/item/organ/external/head/H = get_organ("head") - H.h_style = "Bald" ..(new_loc, "Drask") /mob/living/carbon/human/monkey/New(var/new_loc) @@ -1520,6 +1490,15 @@ species.create_organs(src) + //Handle default hair/head accessories for created mobs. + var/obj/item/organ/external/head/H = get_organ("head") + if(species.default_hair) + H.h_style = species.default_hair + if(species.default_fhair) + H.f_style = species.default_fhair + if(species.default_headacc) + H.ha_style = species.default_headacc + if(!dna) dna = new /datum/dna(null) dna.species = species.name diff --git a/code/modules/mob/living/carbon/human/species/apollo.dm b/code/modules/mob/living/carbon/human/species/apollo.dm index ed02ee5465a..5642eedbcbe 100644 --- a/code/modules/mob/living/carbon/human/species/apollo.dm +++ b/code/modules/mob/living/carbon/human/species/apollo.dm @@ -45,6 +45,8 @@ base_color = "#704300" flesh_color = "#704300" blood_color = "#FFFF99" + //Default styles for created mobs. + default_hair = "Antennae" /datum/species/wryn/handle_death(var/mob/living/carbon/human/H) @@ -98,6 +100,9 @@ flags = IS_WHITELISTED | NO_BREATHE | NO_BLOOD | NO_PAIN | HAS_LIPS | NO_SCAN dietflags = DIET_OMNI //still human at their core, so they maintain their eating habits and diet + //Default styles for created mobs. + default_hair = "Nucleation Crystals" + reagent_tag = PROCESS_ORG has_organ = list( "heart" = /obj/item/organ/internal/heart, diff --git a/code/modules/mob/living/carbon/human/species/species.dm b/code/modules/mob/living/carbon/human/species/species.dm index 03091a7e50f..7430dde4331 100644 --- a/code/modules/mob/living/carbon/human/species/species.dm +++ b/code/modules/mob/living/carbon/human/species/species.dm @@ -118,6 +118,11 @@ var/male_scream_sound = 'sound/goonstation/voice/male_scream.ogg' var/female_scream_sound = 'sound/goonstation/voice/female_scream.ogg' + //Default hair/headacc style vars. + var/default_hair = "Bald" //Default hair style for newly created humans unless otherwise set. + var/default_fhair = "Shaved" //Default facial hair style for newly created humans unless otherwise set. + var/default_headacc = "None" //Default head accessory style for newly created humans unless otherwise set. + // Determines the organs that the species spawns with and var/list/has_organ = list( // which required-organ checks are conducted. "heart" = /obj/item/organ/internal/heart, @@ -158,7 +163,6 @@ /datum/species/proc/create_organs(var/mob/living/carbon/human/H) //Handles creation of mob organs. - for(var/obj/item/organ/internal/iorgan in H.internal_organs) if(iorgan in H.internal_organs) qdel(iorgan) diff --git a/code/modules/mob/living/carbon/human/species/station.dm b/code/modules/mob/living/carbon/human/species/station.dm index cce8b5c46ec..6755ad5e8ef 100644 --- a/code/modules/mob/living/carbon/human/species/station.dm +++ b/code/modules/mob/living/carbon/human/species/station.dm @@ -55,6 +55,8 @@ flesh_color = "#34AF10" reagent_tag = PROCESS_ORG base_color = "#066000" + //Default styles for created mobs. + default_hair = "Unathi Horns" allowed_consumed_mobs = list(/mob/living/simple_animal/mouse, /mob/living/simple_animal/lizard, /mob/living/simple_animal/chick, /mob/living/simple_animal/chicken, /mob/living/simple_animal/crab, /mob/living/simple_animal/butterfly, /mob/living/simple_animal/parrot, /mob/living/simple_animal/tribble) @@ -109,6 +111,8 @@ reagent_tag = PROCESS_ORG flesh_color = "#AFA59E" base_color = "#333333" + //Default styles for created mobs. + default_headacc = "Tajaran Ears" allowed_consumed_mobs = list(/mob/living/simple_animal/mouse, /mob/living/simple_animal/chick, /mob/living/simple_animal/butterfly, /mob/living/simple_animal/parrot, /mob/living/simple_animal/tribble) @@ -189,6 +193,8 @@ dietflags = DIET_HERB flesh_color = "#8CD7A3" blood_color = "#1D2CBF" + //Default styles for created mobs. + default_hair = "Skrell Male Tentacles" reagent_tag = PROCESS_ORG suicide_messages = list( @@ -251,6 +257,8 @@ blood_color = "#2299FC" flesh_color = "#808D11" + //Default styles for created mobs. + default_hair = "Short Vox Quills" reagent_tag = PROCESS_ORG scream_verb = "shrieks" @@ -751,6 +759,8 @@ dietflags = 0 //IPCs can't eat, so no diet blood_color = "#1F181F" flesh_color = "#AAAAAA" + //Default styles for created mobs. + default_hair = "Blue IPC Screen" virus_immune = 1 can_revive_by_healing = 1 reagent_tag = PROCESS_SYN From 73dbbed70e14af79894a34b10ffda8ec7d6ee319 Mon Sep 17 00:00:00 2001 From: KasparoVy Date: Sat, 30 Apr 2016 20:48:58 -0400 Subject: [PATCH 004/343] Cutting Someone's Facial Hair will now Update Facial Hair --- code/game/objects/items/weapons/scissors.dm | 1 + 1 file changed, 1 insertion(+) diff --git a/code/game/objects/items/weapons/scissors.dm b/code/game/objects/items/weapons/scissors.dm index 343c3788bdc..626e1576623 100644 --- a/code/game/objects/items/weapons/scissors.dm +++ b/code/game/objects/items/weapons/scissors.dm @@ -89,6 +89,7 @@ C.h_style = h_new_style H.update_hair() + H.update_fhair() user.visible_message("[user] finishes cutting [M]'s hair!") /obj/item/weapon/scissors/safety //Totally safe, I assure you. From 7205d3a0e39478baeee7bcf49146025b52adfef6 Mon Sep 17 00:00:00 2001 From: KasparoVy Date: Sat, 30 Apr 2016 22:05:57 -0400 Subject: [PATCH 005/343] Hairgrownium and Super Hairgrownium now work on All Species, refactored so if it produces random hair styles for a non-human, it won't do so repeatedly until the reagent is depleted. Also means that species that need breath masks to live won't be killed by infinite fake moustaches. --- code/__HELPERS/mobs.dm | 2 +- code/modules/reagents/newchem/other.dm | 22 +++++++++++++++------- 2 files changed, 16 insertions(+), 8 deletions(-) diff --git a/code/__HELPERS/mobs.dm b/code/__HELPERS/mobs.dm index f8980d61ddd..3d1648fa77a 100644 --- a/code/__HELPERS/mobs.dm +++ b/code/__HELPERS/mobs.dm @@ -52,7 +52,7 @@ proc/random_hair_style(var/gender, species = "Human") if(valid_hairstyles.len) h_style = pick(valid_hairstyles) - return h_style + return h_style proc/GetOppositeDir(var/dir) switch(dir) diff --git a/code/modules/reagents/newchem/other.dm b/code/modules/reagents/newchem/other.dm index 4fe016f49ba..0fa7c579041 100644 --- a/code/modules/reagents/newchem/other.dm +++ b/code/modules/reagents/newchem/other.dm @@ -198,7 +198,7 @@ datum/reagent/hair_dye datum/reagent/hair_dye/reaction_mob(var/mob/living/M, var/volume) if(M && ishuman(M)) var/mob/living/carbon/human/H = M - var/obj/item/organ/external/head/head_organ = H.organs_by_name["head"] + var/obj/item/organ/external/head/head_organ = H.get_organ("head") head_organ.r_facial = rand(0,255) head_organ.g_facial = rand(0,255) head_organ.b_facial = rand(0,255) @@ -230,8 +230,8 @@ datum/reagent/hairgrownium/reaction_mob(var/mob/living/M, var/volume) if(M && ishuman(M)) var/mob/living/carbon/human/H = M var/obj/item/organ/external/head/head_organ = H.get_organ("head") - head_organ.h_style = random_hair_style(H.gender, head_organ.species) - head_organ.f_style = random_facial_hair_style(H.gender, head_organ.species) + head_organ.h_style = random_hair_style(H.gender, head_organ.species.name) + head_organ.f_style = random_facial_hair_style(H.gender, head_organ.species.name) H.update_hair() H.update_fhair() ..() @@ -254,13 +254,21 @@ datum/reagent/super_hairgrownium result_amount = 3 mix_message = "The liquid becomes amazingly furry and smells peculiar." -datum/reagent/super_hairgrownium/on_mob_life(var/mob/living/M as mob) - if(!M) M = holder.my_atom +datum/reagent/super_hairgrownium/reaction_mob(var/mob/living/M, var/volume) if(M && ishuman(M)) var/mob/living/carbon/human/H = M var/obj/item/organ/external/head/head_organ = H.get_organ("head") - head_organ.h_style = "Very Long Hair" - head_organ.f_style = "Very Long Beard" + var/datum/sprite_accessory/tmp_hair_style = hair_styles_list["Very Long Hair"] + var/datum/sprite_accessory/tmp_facial_hair_style = facial_hair_styles_list["Very Long Beard"] + + if(head_organ.species.name in tmp_hair_style.species_allowed) //If 'Very Long Hair' is a style the person's species can have, give it to them. + head_organ.h_style = "Very Long Hair" + else //Otherwise, give them a random hair style. + head_organ.h_style = random_hair_style(H.gender, head_organ.species.name) + if(head_organ.species.name in tmp_facial_hair_style.species_allowed) //If 'Very Long Beard' is a style the person's species can have, give it to them. + head_organ.f_style = "Very Long Beard" + else //Otherwise, give them a random facial hair style. + head_organ.f_style = random_facial_hair_style(H.gender, head_organ.species.name) H.update_hair() H.update_fhair() if(!H.wear_mask || H.wear_mask && !istype(H.wear_mask, /obj/item/clothing/mask/fakemoustache)) From 8cca627918484789c0374b941ade9cea87db2f91 Mon Sep 17 00:00:00 2001 From: KasparoVy Date: Sun, 1 May 2016 18:40:50 -0400 Subject: [PATCH 006/343] Fixes Bug where Facial Hair Wouldn't Update on Death. --- code/modules/mob/living/carbon/human/species/station.dm | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/code/modules/mob/living/carbon/human/species/station.dm b/code/modules/mob/living/carbon/human/species/station.dm index 6755ad5e8ef..8bd4386c3f8 100644 --- a/code/modules/mob/living/carbon/human/species/station.dm +++ b/code/modules/mob/living/carbon/human/species/station.dm @@ -805,4 +805,6 @@ head_organ.h_style = "Bald" head_organ.f_style = "Shaved" spawn(100) - if(H) H.update_hair() \ No newline at end of file + if(H) + H.update_hair() + H.update_fhair() \ No newline at end of file From 9015f11f41622b0252b35d93100bcfc66b5860d6 Mon Sep 17 00:00:00 2001 From: KasparoVy Date: Mon, 2 May 2016 18:13:31 -0400 Subject: [PATCH 007/343] Fixes Morph Being Borked + Additional Features for Morph and C.M.A. Before it wouldn't update skin colour or eye colour, and ended up breaking the sprite such that C.M.A wouldn't have an effect on it after. Now it works perfectly fine, C.M.A works just fine too before and after STAGE 2: Refactors Morph So you change gender first and thus can actually access male beard styles, then you choose hair style and hair colour, then beard style and beard colour, then skin tone or body colour at the very end. STAGE 3 Adds Head Accessory, Head Accessory colour, marking style and body accessory to Morph and C.M.A. --- code/__DEFINES/mob.dm | 6 +- code/game/dna/genes/vg_powers.dm | 142 +++++++++++------- code/game/objects/structures/mirror.dm | 1 + .../mob/living/carbon/human/appearance.dm | 123 ++++++++++++++- .../mob/new_player/sprite_accessories.dm | 8 +- code/modules/nano/modules/human_appearance.dm | 89 ++++++++++- nano/templates/appearance_changer.tmpl | 47 +++++- 7 files changed, 350 insertions(+), 66 deletions(-) diff --git a/code/__DEFINES/mob.dm b/code/__DEFINES/mob.dm index 2bdb3432f69..78439abcb07 100644 --- a/code/__DEFINES/mob.dm +++ b/code/__DEFINES/mob.dm @@ -76,7 +76,11 @@ #define APPEARANCE_FACIAL_HAIR_COLOR 128 #define APPEARANCE_EYE_COLOR 256 #define APPEARANCE_ALL_HAIR APPEARANCE_HAIR|APPEARANCE_HAIR_COLOR|APPEARANCE_FACIAL_HAIR|APPEARANCE_FACIAL_HAIR_COLOR -#define APPEARANCE_ALL 511 +#define APPEARANCE_HEAD_ACCESSORY 512 +#define APPEARANCE_MARKINGS 1024 +#define APPEARANCE_BODY_ACCESSORY 2048 +#define APPEARANCE_ALL_BODY APPEARANCE_ALL_HAIR|APPEARANCE_HEAD_ACCESSORY|APPEARANCE_MARKINGS|APPEARANCE_BODY_ACCESSORY +#define APPEARANCE_ALL 4095 // Intents #define I_HELP "help" diff --git a/code/game/dna/genes/vg_powers.dm b/code/game/dna/genes/vg_powers.dm index 5511642e53e..13f334c010b 100644 --- a/code/game/dna/genes/vg_powers.dm +++ b/code/game/dna/genes/vg_powers.dm @@ -39,69 +39,99 @@ var/mob/living/carbon/human/M=usr var/obj/item/organ/external/head/head_organ = M.get_organ("head") - var/new_facial = input("Please select facial hair color.", "Character Generation",rgb(head_organ.r_facial, head_organ.g_facial, head_organ.b_facial)) as null|color - if(new_facial) - head_organ.r_facial = hex2num(copytext(new_facial, 2, 4)) - head_organ.g_facial = hex2num(copytext(new_facial, 4, 6)) - head_organ.b_facial = hex2num(copytext(new_facial, 6, 8)) - - var/new_hair = input("Please select hair color.", "Character Generation",rgb(head_organ.r_hair, head_organ.g_hair, head_organ.b_hair)) as null|color - if(new_facial) - head_organ.r_hair = hex2num(copytext(new_hair, 2, 4)) - head_organ.g_hair = hex2num(copytext(new_hair, 4, 6)) - head_organ.b_hair = hex2num(copytext(new_hair, 6, 8)) - - var/new_eyes = input("Please select eye color.", "Character Generation",rgb(M.r_eyes,M.g_eyes,M.b_eyes)) as null|color - if(new_eyes) - M.r_eyes = hex2num(copytext(new_eyes, 2, 4)) - M.g_eyes = hex2num(copytext(new_eyes, 4, 6)) - M.b_eyes = hex2num(copytext(new_eyes, 6, 8)) - - var/new_tone = input("Please select skin tone level: 1-220 (1=albino, 35=caucasian, 150=black, 220='very' black)", "Character Generation", "[35-M.s_tone]") as null|text - - if (!new_tone) - new_tone = 35 - M.s_tone = max(min(round(text2num(new_tone)), 220), 1) - M.s_tone = -M.s_tone + 35 - - // hair - var/list/all_hairs = subtypesof(/datum/sprite_accessory/hair) - var/list/hairs = list() - - // loop through potential hairs - for(var/x in all_hairs) - var/datum/sprite_accessory/hair/H = new x // create new hair datum based on type x - hairs.Add(H.name) // add hair name to hairs - qdel(H) // delete the hair after it's all done - - var/new_style = input("Please select hair style", "Character Generation", head_organ.h_style) as null|anything in hairs - - // if new style selected (not cancel) - if (new_style) - head_organ.h_style = new_style - - // facial hair - var/list/all_fhairs = subtypesof(/datum/sprite_accessory/facial_hair) - var/list/fhairs = list() - - for(var/x in all_fhairs) - var/datum/sprite_accessory/facial_hair/H = new x - fhairs.Add(H.name) - qdel(H) - - new_style = input("Please select facial style", "Character Generation", head_organ.f_style) as null|anything in fhairs - - if(new_style) - head_organ.f_style = new_style - var/new_gender = alert(usr, "Please select gender.", "Character Generation", "Male", "Female") if (new_gender) if(new_gender == "Male") M.change_gender(MALE) else M.change_gender(FEMALE) + + var/new_eyes = input("Please select eye color.", "Character Generation", rgb(M.r_eyes,M.g_eyes,M.b_eyes)) as null|color + if(new_eyes) + M.r_eyes = hex2num(copytext(new_eyes, 2, 4)) + M.g_eyes = hex2num(copytext(new_eyes, 4, 6)) + M.b_eyes = hex2num(copytext(new_eyes, 6, 8)) + M.change_eye_color(M.r_eyes, M.g_eyes, M.b_eyes) + + // hair + var/list/valid_hairstyles = M.generate_valid_hairstyles() + var/new_style = input("Please select hair style", "Character Generation", head_organ.h_style) as null|anything in valid_hairstyles + + // if new style selected (not cancel) + if (new_style) + head_organ.h_style = new_style + + var/new_hair = input("Please select hair color.", "Character Generation", rgb(head_organ.r_hair, head_organ.g_hair, head_organ.b_hair)) as null|color + if(new_hair) + head_organ.r_hair = hex2num(copytext(new_hair, 2, 4)) + head_organ.g_hair = hex2num(copytext(new_hair, 4, 6)) + head_organ.b_hair = hex2num(copytext(new_hair, 6, 8)) + + // facial hair + var/list/valid_facial_hairstyles = M.generate_valid_facial_hairstyles() + new_style = input("Please select facial style", "Character Generation", head_organ.f_style) as null|anything in valid_facial_hairstyles + + if(new_style) + head_organ.f_style = new_style + + var/new_facial = input("Please select facial hair color.", "Character Generation", rgb(head_organ.r_facial, head_organ.g_facial, head_organ.b_facial)) as null|color + if(new_facial) + head_organ.r_facial = hex2num(copytext(new_facial, 2, 4)) + head_organ.g_facial = hex2num(copytext(new_facial, 4, 6)) + head_organ.b_facial = hex2num(copytext(new_facial, 6, 8)) + + //Head accessory. + if(head_organ.species.bodyflags & HAS_HEAD_ACCESSORY) + var/list/valid_head_accessories = M.generate_valid_head_accessories() + var/new_head_accessory = input("Please select head accessory style", "Character Generation", head_organ.ha_style) as null|anything in valid_head_accessories + if(new_head_accessory) + head_organ.ha_style = new_head_accessory + + var/new_head_accessory_colour = input("Please select head accessory colour.", "Character Generation", rgb(head_organ.r_headacc, head_organ.g_headacc, head_organ.b_headacc)) as null|color + if(new_head_accessory_colour) + head_organ.r_headacc = hex2num(copytext(new_head_accessory_colour, 2, 4)) + head_organ.g_headacc = hex2num(copytext(new_head_accessory_colour, 4, 6)) + head_organ.b_headacc = hex2num(copytext(new_head_accessory_colour, 6, 8)) + + //Body markings. + if(M.species.bodyflags & HAS_MARKINGS) + var/list/valid_markings = M.generate_valid_markings() + var/new_marking = input("Please select marking style", "Character Generation", M.m_style) as null|anything in valid_markings + if(new_marking) + M.m_style = new_marking + + var/new_marking_colour = input("Please select marking colour.", "Character Generation", rgb(M.r_markings, M.g_markings, M.b_markings)) as null|color + if(new_marking_colour) + M.r_markings = hex2num(copytext(new_marking_colour, 2, 4)) + M.g_markings = hex2num(copytext(new_marking_colour, 4, 6)) + M.b_markings = hex2num(copytext(new_marking_colour, 6, 8)) + + //Body accessory. + if(M.species.tail && M.species.bodyflags & HAS_TAIL) + var/list/valid_body_accessories = M.generate_valid_body_accessories() + if(valid_body_accessories.len > 1) //By default valid_body_accessories will always have at the very least a 'none' entry populating the list, even if the user's species is not present in any of the list items. + var/new_body_accessory = input("Please select body accessory style", "Character Generation", M.body_accessory) as null|anything in valid_body_accessories + if(new_body_accessory) + M.body_accessory = body_accessory_by_name[new_body_accessory] + + //Skin tone. + if(M.species.bodyflags & HAS_SKIN_TONE) + var/new_tone = input("Please select skin tone level: 1-220 (1=albino, 35=caucasian, 150=black, 220='very' black)", "Character Generation", "[M.s_tone]") as null|text + if (!new_tone) + new_tone = 35 + M.s_tone = 35 - max(min(round(text2num(new_tone)), 220), 1) + + //Skin colour. + if(M.species.bodyflags & HAS_SKIN_COLOR) + var/new_body_colour = input("Please select body colour.", "Character Generation", rgb(M.r_skin, M.g_skin, M.b_skin)) as null|color + if(new_body_colour) + M.r_skin = hex2num(copytext(new_body_colour, 2, 4)) + M.g_skin = hex2num(copytext(new_body_colour, 4, 6)) + M.b_skin = hex2num(copytext(new_body_colour, 6, 8)) + + M.force_update_limbs() M.regenerate_icons() - M.check_dna() + M.update_dna() M.visible_message("\blue \The [src] morphs and changes [M.get_visible_gender() == MALE ? "his" : M.get_visible_gender() == FEMALE ? "her" : "their"] appearance!", "\blue You change your appearance!", "\red Oh, god! What the hell was that? It sounded like flesh getting squished and bone ground into a different shape!") diff --git a/code/game/objects/structures/mirror.dm b/code/game/objects/structures/mirror.dm index 699f5ac85aa..d0e8d4c9c85 100644 --- a/code/game/objects/structures/mirror.dm +++ b/code/game/objects/structures/mirror.dm @@ -17,6 +17,7 @@ if(!AC) AC = new(src, user) AC.name = "SalonPro Nano-Mirror™" + AC.flags = APPEARANCE_ALL_BODY ui_users[user] = AC AC.ui_interact(user) diff --git a/code/modules/mob/living/carbon/human/appearance.dm b/code/modules/mob/living/carbon/human/appearance.dm index 2822fa99933..ce20923369d 100644 --- a/code/modules/mob/living/carbon/human/appearance.dm +++ b/code/modules/mob/living/carbon/human/appearance.dm @@ -70,6 +70,57 @@ update_fhair() return 1 +/mob/living/carbon/human/proc/change_head_accessory(var/head_accessory_style) + var/obj/item/organ/external/head/H = get_organ("head") + if(!head_accessory_style) + return + + if(H.ha_style == head_accessory_style) + return + + if(!(head_accessory_style in head_accessory_styles_list)) + return + + H.ha_style = head_accessory_style + + update_head_accessory() + return 1 + +/mob/living/carbon/human/proc/change_markings(var/marking_style) + if(!marking_style) + return + + if(src.m_style == marking_style) + return + + if(!(marking_style in marking_styles_list)) + return + + src.m_style = marking_style + + update_markings() + return 1 + +/mob/living/carbon/human/proc/change_body_accessory(var/body_accessory_style) + var/found + if(!body_accessory_style) + return + + if(src.body_accessory) + if(src.body_accessory.name == body_accessory_style) + return + + for(var/B in body_accessory_by_name) + if(B == body_accessory_style) + src.body_accessory = body_accessory_by_name[body_accessory_style] + found = 1 + + if(!found) + return + + update_tail_layer() + return 1 + /mob/living/carbon/human/proc/reset_hair() reset_head_hair() reset_facial_hair() @@ -131,6 +182,30 @@ update_fhair() return 1 +/mob/living/carbon/human/proc/change_head_accessory_color(var/red, var/green, var/blue) + var/obj/item/organ/external/head/H = get_organ("head") + if(red == H.r_headacc && green == H.g_headacc && blue == H.b_headacc) + return + + H.r_headacc = red + H.g_headacc = green + H.b_headacc = blue + + update_head_accessory() + return 1 + +/mob/living/carbon/human/proc/change_marking_color(var/red, var/green, var/blue) + if(red == r_markings && green == g_markings && blue == b_markings) + return + + r_markings = red + g_markings = green + b_markings = blue + + update_markings() + return 1 + + /mob/living/carbon/human/proc/change_skin_color(var/red, var/green, var/blue) if(red == r_skin && green == g_skin && blue == b_skin || !(species.bodyflags & HAS_SKIN_COLOR)) return @@ -176,9 +251,9 @@ /mob/living/carbon/human/proc/generate_valid_hairstyles() var/list/valid_hairstyles = new() + var/obj/item/organ/external/head/H = get_organ("head") for(var/hairstyle in hair_styles_list) var/datum/sprite_accessory/S = hair_styles_list[hairstyle] - var/obj/item/organ/external/head/H = organs_by_name["head"] if(gender == MALE && S.gender == FEMALE) continue @@ -210,9 +285,9 @@ /mob/living/carbon/human/proc/generate_valid_facial_hairstyles() var/list/valid_facial_hairstyles = new() + var/obj/item/organ/external/head/H = get_organ("head") for(var/facialhairstyle in facial_hair_styles_list) var/datum/sprite_accessory/S = facial_hair_styles_list[facialhairstyle] - var/obj/item/organ/external/head/H = organs_by_name["head"] if(gender == MALE && S.gender == FEMALE) continue @@ -242,3 +317,47 @@ valid_facial_hairstyles += facialhairstyle return valid_facial_hairstyles + +/mob/living/carbon/human/proc/generate_valid_head_accessories() + var/list/valid_head_accessories = new() + var/obj/item/organ/external/head/H = get_organ("head") + for(var/head_accessory in head_accessory_styles_list) + var/datum/sprite_accessory/S = head_accessory_styles_list[head_accessory] + + if(!(H.species.name in S.species_allowed)) //If the user's head is not of a species the head accessory style allows, skip it. Otherwise, add it to the list. + continue + valid_head_accessories += head_accessory + + return valid_head_accessories + +/mob/living/carbon/human/proc/generate_valid_markings() + var/list/valid_markings = new() + var/obj/item/organ/external/head/H = get_organ("head") + for(var/marking in marking_styles_list) + var/datum/sprite_accessory/S = marking_styles_list[marking] + + if(!(species.name in S.species_allowed)) //If the user's head is not of a species the marking style allows, skip it. Otherwise, add it to the list. + continue + if(H.species.flags & ALL_RPARTS) //If the user is a species that can have a robotic head... + var/datum/robolimb/robohead = all_robolimbs[H.model] + if(!(S.models_allowed && (robohead.company in S.models_allowed))) //Make sure they don't get markings incompatible with their head. + continue + valid_markings += marking + + return valid_markings + +/mob/living/carbon/human/proc/generate_valid_body_accessories() + var/list/valid_body_accessories = new() + for(var/B in body_accessory_by_name) + var/datum/body_accessory/A = body_accessory_by_name[B] + if(check_rights(R_ADMIN, 1, src)) + valid_body_accessories = body_accessory_by_name.Copy() + else + if(!istype(A)) + valid_body_accessories += "None" //The only null entry should be the "None" option. + continue + if(!(species.name in A.allowed_species)) //If the user is not of a species the body accessory style allows, skip it. Otherwise, add it to the list. + continue + valid_body_accessories += B + + return valid_body_accessories diff --git a/code/modules/mob/new_player/sprite_accessories.dm b/code/modules/mob/new_player/sprite_accessories.dm index 15452598ed5..93797b5bb17 100644 --- a/code/modules/mob/new_player/sprite_accessories.dm +++ b/code/modules/mob/new_player/sprite_accessories.dm @@ -1898,22 +1898,22 @@ icon_state = "markings_tiger" /datum/sprite_accessory/body_markings/tigerhead - name = "Tiger Body + Head" + name = "Tiger Body and Head" species_allowed = list("Unathi", "Tajaran", "Vulpkanin") icon_state = "markings_tigerhead" /datum/sprite_accessory/body_markings/tigerheadface_taj - name = "Tajaran Tiger Body + Head + Face" + name = "Tajaran Tiger Body, Head and Face" species_allowed = list("Tajaran") icon_state = "markings_tigerheadface_taj" /datum/sprite_accessory/body_markings/tigerheadface_vulp - name = "Vulpkanin Tiger Body + Head + Face" + name = "Vulpkanin Tiger Body, Head and Face" species_allowed = list("Vulpkanin") icon_state = "markings_tigerheadface_vulp" /datum/sprite_accessory/body_markings/tigerheadface_una - name = "Unathi Tiger Body + Head + Face" + name = "Unathi Tiger Body, Head and Face" species_allowed = list("Unathi") icon_state = "markings_tigerheadface_una" diff --git a/code/modules/nano/modules/human_appearance.dm b/code/modules/nano/modules/human_appearance.dm index 4868bfdc7c5..583b68b3dc6 100644 --- a/code/modules/nano/modules/human_appearance.dm +++ b/code/modules/nano/modules/human_appearance.dm @@ -6,6 +6,9 @@ var/list/valid_species = list() var/list/valid_hairstyles = list() var/list/valid_facial_hairstyles = list() + var/list/valid_head_accessories = list() + var/list/valid_marking_styles = list() + var/list/valid_body_accessories = list() var/check_whitelist var/list/whitelist @@ -89,6 +92,41 @@ if(owner.change_eye_color(r_eyes, g_eyes, b_eyes)) update_dna() return 1 + if(href_list["head_accessory"]) + if(can_change_head_accessory() && (href_list["head_accessory"] in valid_head_accessories)) + if(owner.change_head_accessory(href_list["head_accessory"])) + update_dna() + return 1 + if(href_list["head_accessory_color"]) + if(can_change_head_accessory()) + var/new_head_accessory = input("Please select head accessory color.", "Head Accessory Color", rgb(head_organ.r_headacc, head_organ.g_headacc, head_organ.b_headacc)) as color|null + if(new_head_accessory && can_still_topic(state)) + var/r_headacc = hex2num(copytext(new_head_accessory, 2, 4)) + var/g_headacc = hex2num(copytext(new_head_accessory, 4, 6)) + var/b_headacc = hex2num(copytext(new_head_accessory, 6, 8)) + if(owner.change_head_accessory_color(r_headacc, g_headacc, b_headacc)) + update_dna() + return 1 + if(href_list["marking"]) + if(can_change_markings() && (href_list["marking"] in valid_marking_styles)) + if(owner.change_markings(href_list["marking"])) + update_dna() + return 1 + if(href_list["marking_color"]) + if(can_change_markings()) + var/new_markings = input("Please select marking color.", "Marking Color", rgb(owner.r_markings, owner.g_markings, owner.b_markings)) as color|null + if(new_markings && can_still_topic(state)) + var/r_markings = hex2num(copytext(new_markings, 2, 4)) + var/g_markings = hex2num(copytext(new_markings, 4, 6)) + var/b_markings = hex2num(copytext(new_markings, 6, 8)) + if(owner.change_marking_color(r_markings, g_markings, b_markings)) + update_dna() + return 1 + if(href_list["body_accessory"]) + if(can_change_body_accessory() && (href_list["body_accessory"] in valid_body_accessories)) + if(owner.change_body_accessory(href_list["body_accessory"])) + update_dna() + return 1 return 0 @@ -109,6 +147,14 @@ data["change_skin_tone"] = can_change_skin_tone() data["change_skin_color"] = can_change_skin_color() data["change_eye_color"] = can_change(APPEARANCE_EYE_COLOR) + data["change_head_accessory"] = can_change_head_accessory() + if(data["change_head_accessory"]) + var/head_accessory_styles[0] + for(var/head_accessory_style in valid_head_accessories) + head_accessory_styles[++head_accessory_styles.len] = list("headaccessorystyle" = head_accessory_style) + data["head_accessory_styles"] = head_accessory_styles + data["head_accessory_style"] = head_organ.ha_style + data["change_hair"] = can_change(APPEARANCE_HAIR) if(data["change_hair"]) var/hair_styles[0] @@ -125,8 +171,29 @@ data["facial_hair_styles"] = facial_hair_styles data["facial_hair_style"] = head_organ.f_style + data["change_markings"] = can_change_markings() + if(data["change_markings"]) + var/marking_styles[0] + for(var/marking_style in valid_marking_styles) + marking_styles[++marking_styles.len] = list("markingstyle" = marking_style) + data["marking_styles"] = marking_styles + data["marking_style"] = owner.m_style + + data["change_body_accessory"] = can_change_body_accessory() + if(data["change_body_accessory"]) + var/body_accessory_styles[0] + for(var/body_accessory_style in valid_body_accessories) + body_accessory_styles[++body_accessory_styles.len] = list("bodyaccessorystyle" = body_accessory_style) + data["body_accessory_styles"] = body_accessory_styles + var/datum/body_accessory/BA + if(owner.body_accessory) + BA = owner.body_accessory.name + data["body_accessory_style"] = BA + + data["change_head_accessory_color"] = can_change_head_accessory() data["change_hair_color"] = can_change(APPEARANCE_HAIR_COLOR) data["change_facial_hair_color"] = can_change(APPEARANCE_FACIAL_HAIR_COLOR) + data["change_marking_color"] = can_change_markings() ui = nanomanager.try_update_ui(user, src, ui_key, ui, data, force_open) if (!ui) ui = new(user, src, ui_key, "appearance_changer.tmpl", "[src]", 800, 450, state = state) @@ -147,10 +214,22 @@ /datum/nano_module/appearance_changer/proc/can_change_skin_color() return owner && (flags & APPEARANCE_SKIN) && (owner.species.bodyflags & HAS_SKIN_COLOR) +/datum/nano_module/appearance_changer/proc/can_change_head_accessory() + return owner && (flags & APPEARANCE_HEAD_ACCESSORY) && (head_organ.species.bodyflags & HAS_HEAD_ACCESSORY) + +/datum/nano_module/appearance_changer/proc/can_change_markings() + return owner && (flags & APPEARANCE_MARKINGS) && (owner.species.bodyflags & HAS_MARKINGS) + +/datum/nano_module/appearance_changer/proc/can_change_body_accessory() + return owner && (flags & APPEARANCE_BODY_ACCESSORY) && (owner.species.bodyflags & HAS_TAIL) + /datum/nano_module/appearance_changer/proc/cut_and_generate_data() // Making the assumption that the available species remain constant + valid_hairstyles.Cut() valid_facial_hairstyles.Cut() - valid_facial_hairstyles.Cut() + valid_head_accessories.Cut() + valid_marking_styles.Cut() + valid_body_accessories.Cut() generate_data() /datum/nano_module/appearance_changer/proc/generate_data() @@ -160,4 +239,10 @@ valid_species = owner.generate_valid_species(check_whitelist, whitelist, blacklist) if(!valid_hairstyles.len || !valid_facial_hairstyles.len) valid_hairstyles = owner.generate_valid_hairstyles() - valid_facial_hairstyles = owner.generate_valid_facial_hairstyles() \ No newline at end of file + valid_facial_hairstyles = owner.generate_valid_facial_hairstyles() + if(!valid_head_accessories.len) + valid_head_accessories = owner.generate_valid_head_accessories() + if(!valid_marking_styles.len) + valid_marking_styles = owner.generate_valid_markings() + if(!valid_body_accessories.len) + valid_body_accessories = owner.generate_valid_body_accessories() diff --git a/nano/templates/appearance_changer.tmpl b/nano/templates/appearance_changer.tmpl index 19e7fd4759b..886076f21d2 100644 --- a/nano/templates/appearance_changer.tmpl +++ b/nano/templates/appearance_changer.tmpl @@ -23,7 +23,7 @@ {{/if}} -{{if data.change_eye_color || data.change_skin_tone || data.change_skin_color || data.change_hair_color || data.change_facial_hair_color}} +{{if data.change_eye_color || data.change_skin_tone || data.change_skin_color || data.change_head_accessory_color || data.change_hair_color || data.change_facial_hair_color || data.change_marking_color}}
Colors: @@ -38,12 +38,31 @@ {{if data.change_skin_color}} {{:helper.link('Change skin color', null, { 'skin_color' : 1})}} {{/if}} + {{if data.change_head_accessory_color}} + {{:helper.link('Change head accessory color', null, { 'head_accessory_color' : 1})}} + {{/if}} {{if data.change_hair_color}} {{:helper.link('Change hair color', null, { 'hair_color' : 1})}} {{/if}} {{if data.change_facial_hair_color}} {{:helper.link('Change facial hair color', null, { 'facial_hair_color' : 1})}} {{/if}} + {{if data.change_marking_color}} + {{:helper.link('Change marking color', null, { 'marking_color' : 1})}} + {{/if}} +
+
+{{/if}} + +{{if data.change_head_accessory}} +
+
+ Head accessory styles: +
+
+ {{for data.head_accessory_styles}} + {{:helper.link(value.headaccessorystyle, null, { 'head_accessory' : value.headaccessorystyle}, null, data.head_accessory_style == value.headaccessorystyle ? 'selected' : null)}} + {{/for}}
{{/if}} @@ -73,3 +92,29 @@ {{/if}} + +{{if data.change_markings}} +
+
+ Marking styles: +
+
+ {{for data.marking_styles}} + {{:helper.link(value.markingstyle, null, { 'marking' : value.markingstyle}, null, data.marking_style == value.markingstyle ? 'selected' : null)}} + {{/for}} +
+
+{{/if}} + +{{if data.change_body_accessory}} +
+
+ Body accessory styles: +
+
+ {{for data.body_accessory_styles}} + {{:helper.link(value.bodyaccessorystyle, null, { 'body_accessory' : value.bodyaccessorystyle}, null, data.body_accessory_style == value.bodyaccessorystyle ? 'selected' : null)}} + {{/for}} +
+
+{{/if}} From b1001910b9b88723f839f13c4313021f0c2bc12d Mon Sep 17 00:00:00 2001 From: KasparoVy Date: Tue, 3 May 2016 19:59:31 -0400 Subject: [PATCH 008/343] Typo. --- code/modules/surgery/organs/organ_internal.dm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/modules/surgery/organs/organ_internal.dm b/code/modules/surgery/organs/organ_internal.dm index fd61410bdef..8c80b58519a 100644 --- a/code/modules/surgery/organs/organ_internal.dm +++ b/code/modules/surgery/organs/organ_internal.dm @@ -500,7 +500,7 @@ if(istype(owner, /mob/living/carbon/human)) var/mob/living/carbon/human/H = owner var/obj/item/organ/external/head/head_organ = H.get_organ("head") - if(!(head_organ.h_style == "Very Long Hair" || head_organ.h_style == "Mowhawk")) + if(!(head_organ.h_style == "Very Long Hair" || head_organ.h_style == "Mohawk")) if(prob(10)) head_organ.h_style = "Mohawk" else From a5b32d819d3c29a5bbeab1d193d744c9c971b50b Mon Sep 17 00:00:00 2001 From: KasparoVy Date: Wed, 4 May 2016 02:48:05 -0400 Subject: [PATCH 009/343] Fixes Bugs where Alopecia and Facial Hypertrichosis Wouldn't Update Sprite Correctly --- code/datums/diseases/advance/symptoms/beard.dm | 6 +++--- code/datums/diseases/advance/symptoms/shedding.dm | 1 + 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/code/datums/diseases/advance/symptoms/beard.dm b/code/datums/diseases/advance/symptoms/beard.dm index b773d25cf9a..2ce411367f8 100644 --- a/code/datums/diseases/advance/symptoms/beard.dm +++ b/code/datums/diseases/advance/symptoms/beard.dm @@ -36,15 +36,15 @@ BONUS to_chat(H, "Your chin itches.") if(head_organ.f_style == "Shaved") head_organ.f_style = "Jensen Beard" - H.update_hair() + H.update_fhair() if(3, 4) to_chat(H, "You feel tough.") if(!(head_organ.f_style == "Dwarf Beard") && !(head_organ.f_style == "Very Long Beard") && !(head_organ.f_style == "Full Beard")) head_organ.f_style = "Full Beard" - H.update_hair() + H.update_fhair() else to_chat(H, "You feel manly!") if(!(head_organ.f_style == "Dwarf Beard") && !(head_organ.f_style == "Very Long Beard")) head_organ.f_style = pick("Dwarf Beard", "Very Long Beard") - H.update_hair() + H.update_fhair() return \ No newline at end of file diff --git a/code/datums/diseases/advance/symptoms/shedding.dm b/code/datums/diseases/advance/symptoms/shedding.dm index dd1fc5183a6..e79b87d1d4b 100644 --- a/code/datums/diseases/advance/symptoms/shedding.dm +++ b/code/datums/diseases/advance/symptoms/shedding.dm @@ -46,4 +46,5 @@ BONUS head_organ.f_style = "Shaved" head_organ.h_style = "Bald" H.update_hair() + H.update_fhair() return \ No newline at end of file From c2ce4d1a95fe340cebf069a9750b42455e1627dd Mon Sep 17 00:00:00 2001 From: Matt Date: Thu, 5 May 2016 19:29:01 +0200 Subject: [PATCH 010/343] Adds unread changes notification --- SQL/paradise_schema.sql | 1 + SQL/paradise_schema_prefixed.sql | 1 + code/_globalvars/configuration.dm | 4 ++-- code/modules/client/client procs.dm | 5 +++++ code/modules/client/preferences.dm | 2 +- code/modules/client/preferences_mysql.dm | 21 +++++++++++++++++---- code/modules/mob/new_player/login.dm | 5 ++++- interface/interface.dm | 5 +++++ 8 files changed, 36 insertions(+), 8 deletions(-) diff --git a/SQL/paradise_schema.sql b/SQL/paradise_schema.sql index 750e15488b5..badefaf8999 100644 --- a/SQL/paradise_schema.sql +++ b/SQL/paradise_schema.sql @@ -248,6 +248,7 @@ CREATE TABLE `player` ( `volume` smallint(4) DEFAULT '100', `nanoui_fancy` smallint(4) DEFAULT '1', `show_ghostitem_attack` smallint(4) DEFAULT '1', + `lastchangelog` varchar(32) NOT NULL, PRIMARY KEY (`id`), UNIQUE KEY `ckey` (`ckey`) ) ENGINE=InnoDB AUTO_INCREMENT=32446 DEFAULT CHARSET=latin1; diff --git a/SQL/paradise_schema_prefixed.sql b/SQL/paradise_schema_prefixed.sql index 8af09a45737..4f184355e5e 100644 --- a/SQL/paradise_schema_prefixed.sql +++ b/SQL/paradise_schema_prefixed.sql @@ -248,6 +248,7 @@ CREATE TABLE `SS13_player` ( `volume` smallint(4) DEFAULT '100', `nanoui_fancy` smallint(4) DEFAULT '1', `show_ghostitem_attack` smallint(4) DEFAULT '1', + `lastchangelog` varchar(32) NOT NULL, PRIMARY KEY (`id`), UNIQUE KEY `ckey` (`ckey`) ) ENGINE=InnoDB AUTO_INCREMENT=32446 DEFAULT CHARSET=latin1; diff --git a/code/_globalvars/configuration.dm b/code/_globalvars/configuration.dm index 4cfa038cd1e..5b41171d557 100644 --- a/code/_globalvars/configuration.dm +++ b/code/_globalvars/configuration.dm @@ -4,7 +4,7 @@ var/host = null var/join_motd = null var/station_name = "NSS Cyberiad" var/game_version = "Custom ParaCode" -var/changelog_hash = "" +var/changelog_hash = md5('html/changelog.html') //used to check if the CL changed var/game_year = (text2num(time2text(world.realtime, "YYYY")) + 544) var/aliens_allowed = 1 @@ -35,4 +35,4 @@ var/MAX_EX_FLAME_RANGE = 14 var/eventchance = 10 //% per 5 mins var/event = 0 var/hadevent = 0 -var/blobevent = 0 \ No newline at end of file +var/blobevent = 0 diff --git a/code/modules/client/client procs.dm b/code/modules/client/client procs.dm index 57b7487cbe5..54ec74baf63 100644 --- a/code/modules/client/client procs.dm +++ b/code/modules/client/client procs.dm @@ -308,6 +308,11 @@ send_resources() + if(prefs.lastchangelog != changelog_hash) //bolds the changelog button on the interface so we know there are updates. -CP + winset(src, "rpane.changelog", "background-color=#f4aa94;font-style=bold") + prefs.SetChangelog(src,changelog_hash) + src << "Changelog has changed since your last visit." + if(!void) void = new() diff --git a/code/modules/client/preferences.dm b/code/modules/client/preferences.dm index 3ece1b8f059..159963767d3 100644 --- a/code/modules/client/preferences.dm +++ b/code/modules/client/preferences.dm @@ -77,7 +77,7 @@ var/global/list/special_role_times = list( //minimum age (in days) for accounts var/last_id //game-preferences -// var/lastchangelog = "" //Saved changlog filesize to detect if there was a change + var/lastchangelog = "" //Saved changelog filesize to detect if there was a change var/ooccolor = "#b82e00" var/be_special = list() //Special role selection var/UI_style = "Midnight" diff --git a/code/modules/client/preferences_mysql.dm b/code/modules/client/preferences_mysql.dm index cb2e3116526..2638fc60992 100644 --- a/code/modules/client/preferences_mysql.dm +++ b/code/modules/client/preferences_mysql.dm @@ -12,7 +12,8 @@ randomslot, volume, nanoui_fancy, - show_ghostitem_attack + show_ghostitem_attack, + lastchangelog FROM [format_table_name("player")] WHERE ckey='[C.ckey]'"} ) @@ -38,10 +39,10 @@ volume = text2num(query.item[10]) nanoui_fancy = text2num(query.item[11]) show_ghostitem_attack = text2num(query.item[12]) + lastchangelog = query.item[13] //Sanitize ooccolor = sanitize_hexcolor(ooccolor, initial(ooccolor)) -// lastchangelog = sanitize_text(lastchangelog, initial(lastchangelog)) UI_style = sanitize_inlist(UI_style, list("White", "Midnight"), initial(UI_style)) default_slot = sanitize_integer(default_slot, 1, max_save_slots, initial(default_slot)) toggles = sanitize_integer(toggles, 0, 65535, initial(toggles)) @@ -52,6 +53,7 @@ volume = sanitize_integer(volume, 0, 100, initial(volume)) nanoui_fancy = sanitize_integer(nanoui_fancy, 0, 1, initial(nanoui_fancy)) show_ghostitem_attack = sanitize_integer(show_ghostitem_attack, 0, 1, initial(show_ghostitem_attack)) + lastchangelog = sanitize_text(lastchangelog, initial(lastchangelog)) return 1 /datum/preferences/proc/save_preferences(client/C) @@ -75,7 +77,8 @@ randomslot='[randomslot]', volume='[volume]', nanoui_fancy='[nanoui_fancy]', - show_ghostitem_attack='[show_ghostitem_attack]' + show_ghostitem_attack='[show_ghostitem_attack]', + lastchangelog='[lastchangelog]', WHERE ckey='[C.ckey]'"} ) @@ -449,4 +452,14 @@ load_character(C) return 0 load_character(C,pick(saves)) - return 1*/ \ No newline at end of file + return 1*/ + +/datum/preferences/proc/SetChangelog(client/C,hash) + lastchangelog=hash + var/DBQuery/query = dbcon.NewQuery("UPDATE client SET lastchangelog='[lastchangelog]' WHERE ckey='[C.ckey]'") + if(!query.Execute()) + var/err = query.ErrorMsg() + log_game("SQL ERROR during lastchangelog updating. Error : \[[err]\]\n") + message_admins("SQL ERROR during lastchangelog updating. Error : \[[err]\]\n") + return + return 1 diff --git a/code/modules/mob/new_player/login.dm b/code/modules/mob/new_player/login.dm index f6e2441e876..bbb0211ce67 100644 --- a/code/modules/mob/new_player/login.dm +++ b/code/modules/mob/new_player/login.dm @@ -34,6 +34,10 @@ verbs += /client/proc/readmin spawn(40) if(client) + if(client.prefs.lastchangelog != changelog_hash) //bolds the changelog button on the interface so we know there are updates. -CP + winset(client, "rpane.changelog", "background-color=#f4aa94;font-style=bold") + client.prefs.SetChangelog(client,changelog_hash) + to_chat(src, "Changelog has changed since your last visit.") client.playtitlemusic() if(config.player_overflow_cap && config.overflow_server_url) //Overflow rerouting, if set, forces players to be moved to a different server once a player cap is reached. Less rough than a pure kick. @@ -44,4 +48,3 @@ tally++ if(tally > config.player_overflow_cap) src << link(config.overflow_server_url) - diff --git a/interface/interface.dm b/interface/interface.dm index 44f74a20e59..b6a531bad2f 100644 --- a/interface/interface.dm +++ b/interface/interface.dm @@ -39,6 +39,11 @@ ) src << browse('html/changelog.html', "window=changes;size=675x650") + if(prefs.lastchangelog != changelog_hash) //if it's already opened, no need to tell them they have unread changes + prefs.lastchangelog = changelog_hash + prefs.save_preferences() + winset(src, "rpane.changelog", "background-color=none;font-style=") + /client/verb/forum() set name = "forum" set desc = "Visit the forum." From 3ce6965599582fb9994a2f5162e5404b2922e9c8 Mon Sep 17 00:00:00 2001 From: Matt Date: Thu, 5 May 2016 20:04:59 +0200 Subject: [PATCH 011/343] Quick fixes --- code/modules/client/preferences_mysql.dm | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/code/modules/client/preferences_mysql.dm b/code/modules/client/preferences_mysql.dm index 2638fc60992..07db4bf7128 100644 --- a/code/modules/client/preferences_mysql.dm +++ b/code/modules/client/preferences_mysql.dm @@ -78,7 +78,7 @@ volume='[volume]', nanoui_fancy='[nanoui_fancy]', show_ghostitem_attack='[show_ghostitem_attack]', - lastchangelog='[lastchangelog]', + lastchangelog='[lastchangelog]' WHERE ckey='[C.ckey]'"} ) @@ -456,7 +456,7 @@ /datum/preferences/proc/SetChangelog(client/C,hash) lastchangelog=hash - var/DBQuery/query = dbcon.NewQuery("UPDATE client SET lastchangelog='[lastchangelog]' WHERE ckey='[C.ckey]'") + var/DBQuery/query = dbcon.NewQuery("UPDATE [format_table_name("player")] SET lastchangelog='[lastchangelog]' WHERE ckey='[C.ckey]'") if(!query.Execute()) var/err = query.ErrorMsg() log_game("SQL ERROR during lastchangelog updating. Error : \[[err]\]\n") From 24d5a2cf4e1b1b5349cd1bd01290ab18c7a8e773 Mon Sep 17 00:00:00 2001 From: Matt Date: Thu, 5 May 2016 23:20:03 +0200 Subject: [PATCH 012/343] Whoops --- code/modules/client/client procs.dm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/modules/client/client procs.dm b/code/modules/client/client procs.dm index 54ec74baf63..b3300a3cee1 100644 --- a/code/modules/client/client procs.dm +++ b/code/modules/client/client procs.dm @@ -311,7 +311,7 @@ if(prefs.lastchangelog != changelog_hash) //bolds the changelog button on the interface so we know there are updates. -CP winset(src, "rpane.changelog", "background-color=#f4aa94;font-style=bold") prefs.SetChangelog(src,changelog_hash) - src << "Changelog has changed since your last visit." + to_chat(src, "Changelog has changed since your last visit.") if(!void) void = new() From b8d85287a8a0b3d21a840f5b9a3520b7a9cf5936 Mon Sep 17 00:00:00 2001 From: monster860 Date: Fri, 6 May 2016 14:30:35 -0400 Subject: [PATCH 013/343] window rcd --- code/game/objects/items/weapons/RCD.dm | 78 +++++++++++++++++++++++++- 1 file changed, 77 insertions(+), 1 deletion(-) diff --git a/code/game/objects/items/weapons/RCD.dm b/code/game/objects/items/weapons/RCD.dm index 7bd8f6e1207..d00e456d3e8 100644 --- a/code/game/objects/items/weapons/RCD.dm +++ b/code/game/objects/items/weapons/RCD.dm @@ -74,6 +74,12 @@ RCD src.spark_system.start() return if(3) + mode = 4 + to_chat(user, "Changed mode to 'Windows'") + if(prob(20)) + src.spark_system.start() + return + if(4) mode = 1 to_chat(user, "Changed mode to 'Floor & Walls'") if(prob(20)) @@ -88,7 +94,7 @@ RCD if(!proximity) return if(istype(A,/area/shuttle)||istype(A,/turf/space/transit)) return 0 - if(!(istype(A, /turf) || istype(A, /obj/machinery/door/airlock))) + if(!(istype(A, /turf) || istype(A, /obj/machinery/door/airlock) || istype(A, /obj/structure/grille) || istype(A, /obj/structure/window))) return 0 switch(mode) @@ -161,7 +167,77 @@ RCD qdel(A) return 1 return 0 + + if(istype(A, /obj/structure/window)) // You mean the grille of course, do you? + A = locate(/obj/structure/grille) in A.loc + + if(istype(A, /obj/structure/grille)) + if(!checkResource(2, user)) + return 0 + to_chat(user, "Deconstructing window...") + playsound(src.loc, 'sound/machines/click.ogg', 50, 1) + if(!do_after(user, 20, target = A)) + return 0 + if(locate(/obj/structure/window/full/shuttle) in A.contents) + return 0 // Let's not give shuttle-griefers an easy time. + if(!useResource(2, user)) + return 0 + activate() + var/turf/T1 = get_turf(A) + qdel(A) + A = null + for(var/obj/structure/window/W in T1.contents) + W.disassembled = 1 + W.density = 0 + qdel(W) + for(var/cdir in cardinal) + var/turf/T2 = get_step(T1, cdir) + if(locate(/obj/structure/window/full/shuttle) in T2.contents) + continue // Shuttle windows? Nah. We don't need extra windows there. + if(!(locate(/obj/structure/grille) in T2.contents)) + continue + for(var/obj/structure/window/W in T2.contents) + if(W.dir == turn(cdir, 180)) + W.disassembled = 1 + W.density = 0 + qdel(W) + var/obj/structure/window/reinforced/W = new(T2) + W.dir = turn(cdir, 180) + return 1 return 0 + if(4) + if(istype(A, /turf/simulated/floor)) + if(locate(/obj/structure/grille) in contents) + return 0 // We already have window + if(!checkResource(2, user)) + return 0 + to_chat(user, "Constructing window...") + playsound(src.loc, 'sound/machines/click.ogg', 50, 1) + if(!do_after(user, 20, target = A)) + return 0 + if(locate(/obj/structure/grille) in A.contents) + return 0 // We already have window + if(!useResource(2, user)) + return 0 + activate() + new /obj/structure/grille(A) + for(var/obj/structure/window/W in contents) + W.disassembled = 1 // Prevent that annoying glass breaking sound + W.density = 0 + qdel(W) + for(var/cdir in cardinal) + var/turf/T = get_step(A, cdir) + if(locate(/obj/structure/grille) in T.contents) + for(var/obj/structure/window/W in T.contents) + if(W.dir == turn(cdir, 180)) + W.disassembled = 1 + W.density = 0 + qdel(W) + else // Build a window! + var/obj/structure/window/reinforced/W = new(A) + W.dir = cdir + A:ChangeTurf(/turf/simulated/floor/plating) // Platings go under windows. + return 1 else to_chat(user, "ERROR: RCD in MODE: [mode] attempted use by [user]. Send this text #coderbus or an admin.") return 0 From 8104a69a512f83571aea14c9e6814aabe0e33712 Mon Sep 17 00:00:00 2001 From: IK3I Date: Sat, 7 May 2016 03:19:27 -0500 Subject: [PATCH 014/343] Moves pod code to modules where it belongs. --- .../vehicles => modules}/spacepods/construction.dm | 0 code/{game/vehicles => modules}/spacepods/equipment.dm | 0 code/{game/vehicles => modules}/spacepods/parts.dm | 0 .../vehicles => modules}/spacepods/pod_fabricator.dm | 0 code/{game/vehicles => modules}/spacepods/spacepod.dm | 0 paradise.dme | 10 +++++----- 6 files changed, 5 insertions(+), 5 deletions(-) rename code/{game/vehicles => modules}/spacepods/construction.dm (100%) rename code/{game/vehicles => modules}/spacepods/equipment.dm (100%) rename code/{game/vehicles => modules}/spacepods/parts.dm (100%) rename code/{game/vehicles => modules}/spacepods/pod_fabricator.dm (100%) rename code/{game/vehicles => modules}/spacepods/spacepod.dm (100%) diff --git a/code/game/vehicles/spacepods/construction.dm b/code/modules/spacepods/construction.dm similarity index 100% rename from code/game/vehicles/spacepods/construction.dm rename to code/modules/spacepods/construction.dm diff --git a/code/game/vehicles/spacepods/equipment.dm b/code/modules/spacepods/equipment.dm similarity index 100% rename from code/game/vehicles/spacepods/equipment.dm rename to code/modules/spacepods/equipment.dm diff --git a/code/game/vehicles/spacepods/parts.dm b/code/modules/spacepods/parts.dm similarity index 100% rename from code/game/vehicles/spacepods/parts.dm rename to code/modules/spacepods/parts.dm diff --git a/code/game/vehicles/spacepods/pod_fabricator.dm b/code/modules/spacepods/pod_fabricator.dm similarity index 100% rename from code/game/vehicles/spacepods/pod_fabricator.dm rename to code/modules/spacepods/pod_fabricator.dm diff --git a/code/game/vehicles/spacepods/spacepod.dm b/code/modules/spacepods/spacepod.dm similarity index 100% rename from code/game/vehicles/spacepods/spacepod.dm rename to code/modules/spacepods/spacepod.dm diff --git a/paradise.dme b/paradise.dme index 6e79b17f2d0..b609a2fc55f 100644 --- a/paradise.dme +++ b/paradise.dme @@ -977,11 +977,6 @@ #include "code\game\turfs\unsimulated\beach.dm" #include "code\game\turfs\unsimulated\floor.dm" #include "code\game\turfs\unsimulated\walls.dm" -#include "code\game\vehicles\spacepods\construction.dm" -#include "code\game\vehicles\spacepods\equipment.dm" -#include "code\game\vehicles\spacepods\parts.dm" -#include "code\game\vehicles\spacepods\pod_fabricator.dm" -#include "code\game\vehicles\spacepods\spacepod.dm" #include "code\game\verbs\ooc.dm" #include "code\game\verbs\suicide.dm" #include "code\game\verbs\who.dm" @@ -1970,6 +1965,11 @@ #include "code\modules\shuttle\supply.dm" #include "code\modules\shuttle\syndicate.dm" #include "code\modules\space_transition\space_transition.dm" +#include "code\modules\spacepods\construction.dm" +#include "code\modules\spacepods\equipment.dm" +#include "code\modules\spacepods\parts.dm" +#include "code\modules\spacepods\pod_fabricator.dm" +#include "code\modules\spacepods\spacepod.dm" #include "code\modules\store\items.dm" #include "code\modules\store\store.dm" #include "code\modules\surgery\bones.dm" From 6d8c7f67772d1200d9e00a8136d3e40c8e7ab405 Mon Sep 17 00:00:00 2001 From: IK3I Date: Sat, 7 May 2016 15:56:59 -0500 Subject: [PATCH 015/343] Cleans references to Occupant2 Prepares for list based occupancy --- code/modules/spacepods/spacepod.dm | 136 +++++------------------------ 1 file changed, 23 insertions(+), 113 deletions(-) diff --git a/code/modules/spacepods/spacepod.dm b/code/modules/spacepods/spacepod.dm index 707b8912460..01f9a82ae39 100644 --- a/code/modules/spacepods/spacepod.dm +++ b/code/modules/spacepods/spacepod.dm @@ -15,7 +15,6 @@ infra_luminosity = 15 var/mob/living/carbon/occupant - var/mob/living/carbon/occupant2 //two seaters var/datum/spacepod/equipment/equipment_system @@ -94,9 +93,6 @@ if(occupant) occupant.forceMove(get_turf(src)) occupant = null - if(occupant2) - occupant2.forceMove(get_turf(src)) - occupant2 = null spacepods_list -= src return ..() @@ -161,28 +157,19 @@ S.channel = 0 //Any channel S.volume = 50 to_chat(occupant, S) - if(occupant2) - to_chat(occupant2, S) if(occupant && oldhealth > health && !health) var/sound/S = sound('sound/effects/engine_alert1.ogg') S.wait = 0 S.channel = 0 S.volume = 50 to_chat(occupant, S) - if(occupant2) - to_chat(occupant2, S) if(!health) spawn(0) if(occupant) to_chat(occupant, "Critical damage to the vessel detected, core explosion imminent!") - if(occupant2) - to_chat(occupant2, "Critical damage to the vessel detected, core explosion imminent!") - for(var/i = 10, i >= 0; --i) if(occupant) to_chat(occupant, "[i]") - if(occupant2) - to_chat(occupant2, "[i]") if(i == 0) explosion(loc, 2, 4, 8) qdel(src) @@ -201,15 +188,10 @@ switch(severity) if(1) var/mob/living/carbon/human/H = occupant - var/mob/living/carbon/human/H2 = occupant2 if(H) H.forceMove(get_turf(src)) H.ex_act(severity + 1) to_chat(H, "You are forcefully thrown from \the [src]!") - if(H2) - H2.forceMove(get_turf(src)) - H2.ex_act(severity + 1) - to_chat(H2, "You are forcefully thrown from \the [src]!") qdel(ion_trail) qdel(src) if(2) @@ -224,8 +206,6 @@ if(1) if(occupant) to_chat(occupant, "The pod console flashes 'Heavy EMP WAVE DETECTED'.")//warn the occupants - if(occupant2) - to_chat(occupant2, "The pod console flashes 'Heavy EMP WAVE DETECTED'.")//warn the occupants if(battery) @@ -238,8 +218,6 @@ if(2) if(occupant) to_chat(occupant, "The pod console flashes 'EMP WAVE DETECTED'.")//warn the occupants - if(occupant2) - to_chat(occupant2, "The pod console flashes 'EMP WAVE DETECTED'.")//warn the occupants deal_damage(40) if(battery) @@ -544,6 +522,7 @@ . = t_air.return_temperature() return +/* Save for cargo refactor /obj/spacepod/proc/moved_other_inside(var/mob/living/carbon/human/H as mob) occupant_sanity_check() if(!occupant2) @@ -553,6 +532,7 @@ H.forceMove(src) playsound(src, 'sound/machines/windowdoor.ogg', 50, 1) return 1 +*/ /obj/spacepod/MouseDrop_T(atom/A, mob/user) if(istype(A,/mob)) @@ -562,6 +542,7 @@ occupant_sanity_check() +/* save for cargo refactor if(M != user && M.stat == DEAD && allow2enter) if(occupant2 && !occupant) to_chat(usr, "You can't put a corpse into the driver's seat!") @@ -570,6 +551,7 @@ visible_message("[user.name] starts loading [M.name] into the pod!") sleep(10) moved_other_inside(M) +*/ if(M == user) if(!equipment_system.lock_system || allow2enter) @@ -645,24 +627,10 @@ to_chat(user, "[occupant] was faster. Try better next time, loser.") else to_chat(user, "You stop entering \the [src].") - - else if(!occupant2) - visible_message("[user] starts to climb into \the [src].") - if(do_after(user, 40, target = src)) - if(!occupant2) - user.stop_pulling() - occupant2 = user - user.forceMove(src) - add_fingerprint(user) - playsound(src, 'sound/machines/windowdoor.ogg', 50, 1) - else - to_chat(user, "[occupant] was faster. Try better next time, loser.") - else - to_chat(user, "You stop entering \the [src].") else to_chat(user, "You can't fit in \the [src], it's full!") -/obj/spacepod/proc/occupant_sanity_check() +/obj/spacepod/proc/occupant_sanity_check() // going to have to adjust this later for cargo refactor if(occupant) if(!ismob(occupant)) occupant.forceMove(get_turf(src)) @@ -671,14 +639,6 @@ else if(occupant.loc != src) log_debug("##SPACEPOD WARNING: OCCUPANT [occupant] ESCAPED, TURF [get_turf(src)] | AREA [get_area(src)] | COORDS [x], [y], [z]") occupant = null - if(occupant2) - if(!ismob(occupant2)) - occupant2.forceMove(get_turf(src)) - log_debug("##SPACEPOD WARNING: NON-MOB OCCUPANT [occupant2], TURF [get_turf(src)] | AREA [get_area(src)] | COORDS [x], [y], [z]") - occupant2 = null - else if(occupant2.loc != src) - log_debug("##SPACEPOD WARNING: OCCUPANT [occupant2] ESCAPED, TURF [get_turf(src)] | AREA [get_area(src)] | COORDS [x], [y], [z]") - occupant2 = null /obj/spacepod/verb/exit_pod() set name = "Exit pod" @@ -693,55 +653,19 @@ occupant_sanity_check() if(occupant == user) spos = 1 - if(occupant2 == user) spos = 2 switch(spos) if(0) return if(1) - if(occupant2) - to_chat(occupant2, "[occupant.name] climbs out of the pod!") occupant.forceMove(src.loc) occupant = null to_chat(user, "You climb out of \the [src].") - if(2) - if(occupant) - to_chat(occupant, "[occupant2.name] climbs out of the pod!") - occupant2.forceMove(src.loc) - occupant2 = null - to_chat(user, "You climb out of \the [src].") - -/obj/spacepod/verb/exit_pod2() - set name = "Eject Secondary Seat" - set category = "Spacepod" - set src = usr.loc - - occupant_sanity_check() - - if(!occupant2) - to_chat(usr, "There is no one in the second seat.") - return - - if(usr == occupant2) - to_chat(usr, "How do you plan to do that? The eject button is out of reach.") - return - - if(usr == occupant) - to_chat(usr, "You eject [occupant2.name].") - to_chat(occupant2, "\The [src] ejects you forcefully!") - inertia_dir = 0 - occupant2.forceMove(src.loc) - occupant2 = null /obj/spacepod/verb/locksecondseat() set name = "Lock Doors" set category = "Spacepod" set src = usr.loc - if(CheckIfOccupant2(usr)) - if(!allow2enter) - to_chat(usr, "You can't [allow2enter ? "lock" : "unlock"] the doors from your seat.") - return - allow2enter = !allow2enter to_chat(usr, "You [allow2enter ? "unlock" : "lock"] the doors.") @@ -751,7 +675,6 @@ set category = "Spacepod" set src = usr.loc - if(CheckIfOccupant2(usr)) return for(var/obj/machinery/door/poddoor/multi_tile/P in orange(3,src)) var/mob/living/carbon/human/L = usr if(P.check_access(L.get_active_hand()) || P.check_access(L.wear_id)) @@ -769,33 +692,30 @@ /obj/spacepod/verb/fireWeapon() - if(!CheckIfOccupant2(usr)) - set name = "Fire Pod Weapons" - set desc = "Fire the weapons." - set category = "Spacepod" - set src = usr.loc - if(!equipment_system.weapon_system) - to_chat(usr, "\The [src] has no weapons!") - return - equipment_system.weapon_system.fire_weapons() + set name = "Fire Pod Weapons" + set desc = "Fire the weapons." + set category = "Spacepod" + set src = usr.loc + if(!equipment_system.weapon_system) + to_chat(usr, "\The [src] has no weapons!") + return + equipment_system.weapon_system.fire_weapons() /obj/spacepod/verb/unload() - if(!CheckIfOccupant2(usr)) - set name = "Unload Cargo" - set desc = "Unloads the cargo" - set category = "Spacepod" - set src = usr.loc - if(!equipment_system.cargo_system) - to_chat(usr, "\The [src] has no cargo system!") - return - equipment_system.cargo_system.unload() + set name = "Unload Cargo" + set desc = "Unloads the cargo" + set category = "Spacepod" + set src = usr.loc + if(!equipment_system.cargo_system) + to_chat(usr, "\The [src] has no cargo system!") + return + equipment_system.cargo_system.unload() /obj/spacepod/verb/toggleLights() set name = "Toggle Lights" set category = "Spacepod" set src = usr.loc - if(!CheckIfOccupant2(usr)) - lightsToggle() + lightsToggle() /obj/spacepod/proc/lightsToggle() lights = !lights @@ -861,8 +781,7 @@ return /obj/spacepod/relaymove(mob/user, direction) - if(!CheckIfOccupant2(user)) - handlerelaymove(user, direction) + handlerelaymove(user, direction) /obj/spacepod/proc/handlerelaymove(mob/user, direction) if(world.time < next_move) @@ -909,15 +828,6 @@ battery.charge = max(0, battery.charge - 1) next_move = world.time + move_delay -/obj/spacepod/proc/CheckIfOccupant2(mob/user) - if(!src.occupant2) - return 0 - if(src.occupant2) - if(user == src.occupant2) - return 1 - else - return 0 - /obj/effect/landmark/spacepod/random name = "spacepod spawner" invisibility = 101 From f63328262fab6de9e784e66cb51d325810224506 Mon Sep 17 00:00:00 2001 From: IK3I Date: Sun, 8 May 2016 04:24:48 -0500 Subject: [PATCH 016/343] Completes Stage One of Occupant Refactor Occupants are now members of a list with a maximum size and a special associative tag for pilots. Gating the verbs and testing is still needed. --- .../computer/pod_tracking_console.dm | 24 ++-- code/game/machinery/portable_turret.dm | 2 +- code/game/machinery/turrets.dm | 22 ++-- .../living/simple_animal/hostile/hostile.dm | 7 +- .../hostile/retaliate/retaliate.dm | 6 +- .../mob/living/simple_animal/simple_animal.dm | 2 +- code/modules/spacepods/spacepod.dm | 115 +++++++++++------- 7 files changed, 101 insertions(+), 77 deletions(-) diff --git a/code/game/machinery/computer/pod_tracking_console.dm b/code/game/machinery/computer/pod_tracking_console.dm index 5ac31a0f567..e759cc0357f 100644 --- a/code/game/machinery/computer/pod_tracking_console.dm +++ b/code/game/machinery/computer/pod_tracking_console.dm @@ -17,17 +17,21 @@ var/data[0] var/list/pods[0] for(var/obj/item/device/spacepod_equipment/misc/tracker/TR in world) - var/obj/spacepod/myPod = TR.my_atom + var/obj/spacepod/my_pod = TR.my_atom var/enabled = TR.enabled - if(myPod && enabled) - var/podname = capitalize(sanitize(myPod.name)) - var/occupant = "None" - var/occupant2 = "None" - if(myPod.occupant) - occupant = myPod.occupant.name - if(myPod.occupant2) - occupant2 = myPod.occupant2.name - pods.Add(list(list("pod" = "\ref[myPod]", "name" = podname, "occupant" = occupant, "occupant2" = occupant2, "x" = myPod.x, "y" = myPod.y, "z" = myPod.z))) + if(my_pod && enabled) + var/podname = capitalize(sanitize(my_pod.name)) + var/list/chairs = list() + if(my_pod.occupants) + var/mob/pilot = my_pod.occupants[PILOT] + if(my_pod.occupants[PILOT]) + chairs += list("pilot" = pilot.name) + for(var/mob/M in my_pod.occupants) + if(M == pilot) + continue + chairs += list("passenger" = M.name) + + pods.Add(list(list("pod" = "\ref[my_pod]", "name" = podname) + chairs + list("x" = my_pod.x, "y" = my_pod.y, "z" = my_pod.z))) data["pods"] = pods diff --git a/code/game/machinery/portable_turret.dm b/code/game/machinery/portable_turret.dm index f916998e26b..c5cd700abaf 100644 --- a/code/game/machinery/portable_turret.dm +++ b/code/game/machinery/portable_turret.dm @@ -519,7 +519,7 @@ var/list/turret_icons assess_and_assign(ME.occupant, targets, secondarytargets) for(var/obj/spacepod/SP in view(7,src)) - assess_and_assign(SP.occupant, targets, secondarytargets) + assess_and_assign(SP.occupants[PILOT], targets, secondarytargets) for(var/obj/vehicle/T in view(7,src)) assess_and_assign(T.buckled_mob, targets, secondarytargets) diff --git a/code/game/machinery/turrets.dm b/code/game/machinery/turrets.dm index b1d92718104..022e0d2765e 100644 --- a/code/game/machinery/turrets.dm +++ b/code/game/machinery/turrets.dm @@ -21,7 +21,7 @@ turretTargets |= Mech else if( istype(O, /obj/spacepod) ) var/obj/spacepod/Pod = O - if( Pod.occupant || Pod.occupant2 ) + if( Pod.occupants ) turretTargets |= Pod else if(istype(O,/mob/living/simple_animal)) turretTargets |= O @@ -139,7 +139,7 @@ return 1 else if( istype(T, /obj/spacepod) ) var/obj/spacepod/SP = T - if( SP.occupant || SP.occupant2 ) + if( SP.occupants ) return 1 else if(istype(T,/mob/living/simple_animal)) var/mob/living/simple_animal/A = T @@ -159,8 +159,8 @@ if(M.occupant) new_targets += M for(var/obj/spacepod/M in protected_area.turretTargets) - if(M.occupant) - new_targets += M + if(M.occupants[PILOT]) + new_targets += M.occupants[PILOT] for(var/mob/living/simple_animal/M in protected_area.turretTargets) if(!M.stat) new_targets += M @@ -488,7 +488,7 @@ return 1 else if(istype(target, /obj/spacepod)) var/obj/spacepod/S = target - if(S.occupant || S.occupant2) + if(S.occupants) return 1 return 0 @@ -522,14 +522,12 @@ continue //Don't shoot at empty mechs. pos_targets += M for(var/obj/spacepod/M in oview(scan_range, src)) - if(M.occupant) - if(faction in M.occupant.faction) + if(M.occupants[PILOT]) + var/mob/P = M.occupants[PILOT] + if(faction in P.faction) continue - if(M.occupant2) - if(faction in M.occupant2.faction) - continue - if(!M.occupant && !M.occupant2) - continue //Don't shoot at empty mechs. + if(!M.occupants) + continue //Don't shoot at empty pods. pos_targets += M if(pos_targets.len) target = pick(pos_targets) diff --git a/code/modules/mob/living/simple_animal/hostile/hostile.dm b/code/modules/mob/living/simple_animal/hostile/hostile.dm index 757b72f3809..81a0828df14 100644 --- a/code/modules/mob/living/simple_animal/hostile/hostile.dm +++ b/code/modules/mob/living/simple_animal/hostile/hostile.dm @@ -118,9 +118,10 @@ return 1 if(istype(the_target, /obj/spacepod)) var/obj/spacepod/S = the_target - if(S.occupant || S.occupant2)//Just so we don't attack empty mechs - if(CanAttack(S.occupant) || CanAttack(S.occupant2)) - return 1 + if(S.occupants) //Just so we don't attack empty pods + for(var/mob/M in S.occupants) + if(CanAttack(M)) + return 1 if(isliving(the_target)) var/mob/living/L = the_target var/faction_check = 0 diff --git a/code/modules/mob/living/simple_animal/hostile/retaliate/retaliate.dm b/code/modules/mob/living/simple_animal/hostile/retaliate/retaliate.dm index b9f04ec68ee..e6d373d7504 100644 --- a/code/modules/mob/living/simple_animal/hostile/retaliate/retaliate.dm +++ b/code/modules/mob/living/simple_animal/hostile/retaliate/retaliate.dm @@ -14,7 +14,7 @@ return A else if(istype(A, /obj/spacepod)) var/obj/spacepod/M = A - if(M.occupant || M.occupant2) + if(M.occupants) return A /mob/living/simple_animal/hostile/retaliate/ListTargets() @@ -47,9 +47,9 @@ enemies |= M.occupant else if(istype(A, /obj/spacepod)) var/obj/spacepod/M = A - if(M.occupant || M.occupant2) + if(M.occupants[PILOT]) enemies |= M - enemies |= M.occupant + enemies |= M.occupants[PILOT] for(var/mob/living/simple_animal/hostile/retaliate/H in around) var/retaliate_faction_check = 0 diff --git a/code/modules/mob/living/simple_animal/simple_animal.dm b/code/modules/mob/living/simple_animal/simple_animal.dm index 23477c2fc18..09c82dbf1b2 100644 --- a/code/modules/mob/living/simple_animal/simple_animal.dm +++ b/code/modules/mob/living/simple_animal/simple_animal.dm @@ -529,7 +529,7 @@ return 0 if (istype(the_target,/obj/spacepod)) var/obj/spacepod/S = the_target - if (S.occupant || S.occupant2) + if (S.occupants) return 0 return 1 diff --git a/code/modules/spacepods/spacepod.dm b/code/modules/spacepods/spacepod.dm index 01f9a82ae39..512a8ff0d38 100644 --- a/code/modules/spacepods/spacepod.dm +++ b/code/modules/spacepods/spacepod.dm @@ -1,5 +1,6 @@ #define DAMAGE 1 #define FIRE 2 +#define PILOT "pilot" /obj/spacepod name = "\improper space pod" @@ -14,7 +15,8 @@ layer = 3.9 infra_luminosity = 15 - var/mob/living/carbon/occupant + var/list/mob/occupants = list() //uses [PILOT] index for pilot and numerics for passangers + var/max_occupants = 1 var/datum/spacepod/equipment/equipment_system @@ -90,9 +92,10 @@ qdel(ion_trail) ion_trail = null occupant_sanity_check() - if(occupant) - occupant.forceMove(get_turf(src)) - occupant = null + if(occupants) + for(var/mob/M in occupants) + M.forceMove(get_turf(src)) + occupants -= M spacepods_list -= src return ..() @@ -151,25 +154,29 @@ health = max(0, health - damage) var/percentage = (health / initial(health)) * 100 occupant_sanity_check() - if(occupant && oldhealth > health && percentage <= 25 && percentage > 0) + if(occupants && oldhealth > health && percentage <= 25 && percentage > 0) var/sound/S = sound('sound/effects/engine_alert2.ogg') S.wait = 0 //No queue S.channel = 0 //Any channel S.volume = 50 - to_chat(occupant, S) - if(occupant && oldhealth > health && !health) + for(var/mob/M in occupants) + to_chat(M, S) + if(occupants && oldhealth > health && !health) var/sound/S = sound('sound/effects/engine_alert1.ogg') S.wait = 0 S.channel = 0 S.volume = 50 - to_chat(occupant, S) + for(var/mob/M in occupants) + to_chat(M, S) if(!health) spawn(0) - if(occupant) - to_chat(occupant, "Critical damage to the vessel detected, core explosion imminent!") + if(occupants) + for(var/mob/M in occupants) + to_chat(M, "Critical damage to the vessel detected, core explosion imminent!") for(var/i = 10, i >= 0; --i) - if(occupant) - to_chat(occupant, "[i]") + if(occupants) + for(var/mob/M in occupants) + to_chat(M, "[i]") if(i == 0) explosion(loc, 2, 4, 8) qdel(src) @@ -187,11 +194,12 @@ occupant_sanity_check() switch(severity) if(1) - var/mob/living/carbon/human/H = occupant - if(H) - H.forceMove(get_turf(src)) - H.ex_act(severity + 1) - to_chat(H, "You are forcefully thrown from \the [src]!") + for(var/mob/M in occupants) + var/mob/living/carbon/human/H = M + if(H) + H.forceMove(get_turf(src)) + H.ex_act(severity + 1) + to_chat(H, "You are forcefully thrown from \the [src]!") qdel(ion_trail) qdel(src) if(2) @@ -204,8 +212,9 @@ occupant_sanity_check() switch(severity) if(1) - if(occupant) - to_chat(occupant, "The pod console flashes 'Heavy EMP WAVE DETECTED'.")//warn the occupants + if(occupants) + for(var/mob/M in occupants) + to_chat(M, "The pod console flashes 'Heavy EMP WAVE DETECTED'.")//warn the occupants if(battery) @@ -216,8 +225,9 @@ processing_objects.Add(src) if(2) - if(occupant) - to_chat(occupant, "The pod console flashes 'EMP WAVE DETECTED'.")//warn the occupants + if(occupants) + for(var/mob/M in occupants) + to_chat(M, "The pod console flashes 'EMP WAVE DETECTED'.")//warn the occupants deal_damage(40) if(battery) @@ -301,7 +311,7 @@ if(istype(W, /obj/item/device/spacepod_key) && istype(equipment_system.lock_system, /obj/item/device/spacepod_equipment/lock/keyed)) var/obj/item/device/spacepod_key/key = W if (key.id == equipment_system.lock_system.id) - locksecondseat() + lock_pod() else to_chat(user, "This is the wrong key!") return @@ -464,10 +474,11 @@ set category = "Spacepod" set src = usr.loc set popup_menu = 0 - if(usr!=src.occupant) + if(usr != src.occupants[PILOT]) return use_internal_tank = !use_internal_tank - to_chat(occupant, "Now taking air from [use_internal_tank?"internal airtank":"environment"].") + for(var/mob/M in occupants) + to_chat(M, "Now taking air from [use_internal_tank?"internal airtank":"environment"].") return /obj/spacepod/proc/add_cabin() @@ -614,31 +625,44 @@ occupant_sanity_check() - if(!occupant) + if(occupants.len < max_occupants) visible_message("[user] starts to climb into \the [src].") if(do_after(user, 40, target = src)) - if(!occupant) + if(occupants.len < max_occupants) user.stop_pulling() - occupant = user + if(!occupants[PILOT]) + occupants[PILOT] = user + else + occupants += user user.forceMove(src) add_fingerprint(user) playsound(src, 'sound/machines/windowdoor.ogg', 50, 1) else - to_chat(user, "[occupant] was faster. Try better next time, loser.") + to_chat(user, "You were too slow. Try better next time, loser.") else to_chat(user, "You stop entering \the [src].") else to_chat(user, "You can't fit in \the [src], it's full!") /obj/spacepod/proc/occupant_sanity_check() // going to have to adjust this later for cargo refactor - if(occupant) - if(!ismob(occupant)) - occupant.forceMove(get_turf(src)) - log_debug("##SPACEPOD WARNING: NON-MOB OCCUPANT [occupant], TURF [get_turf(src)] | AREA [get_area(src)] | COORDS [x], [y], [z]") - occupant = null - else if(occupant.loc != src) - log_debug("##SPACEPOD WARNING: OCCUPANT [occupant] ESCAPED, TURF [get_turf(src)] | AREA [get_area(src)] | COORDS [x], [y], [z]") - occupant = null + if(occupants) + if(occupants.len == max_occupants && !occupants[PILOT]) + occupants[PILOT] = occupants[1] + log_debug("##SPACEPOD WARNING: IMPOSSIBLE SEATING ARRANGEMENT: OCCUPANTS [english_list(occupants)], TURF [get_turf(src)] | AREA [get_area(src)] | COORDS [x], [y], [z]") + if(occupants.len > max_occupants) + for(var/i = occupants.len; i <= max_occupants; i--) + var/mob/occupant = occupants[i - 1] + occupant.forceMove(get_turf(src)) + log_debug("##SPACEPOD WARNING: OCCUPANTS EXCEED CAP: MAX OCCUPANTS [max_occupants], OCCUPANTS [english_list(occupants)], TURF [get_turf(src)] | AREA [get_area(src)] | COORDS [x], [y], [z]") + occupants[i - 1] = null + for(var/mob/M in occupants) + if(!ismob(M)) + M.forceMove(get_turf(src)) + log_debug("##SPACEPOD WARNING: NON-MOB OCCUPANT [M], TURF [get_turf(src)] | AREA [get_area(src)] | COORDS [x], [y], [z]") + occupants -= M + else if(M.loc != src) + log_debug("##SPACEPOD WARNING: OCCUPANT [M] ESCAPED, TURF [get_turf(src)] | AREA [get_area(src)] | COORDS [x], [y], [z]") + occupants -= M /obj/spacepod/verb/exit_pod() set name = "Exit pod" @@ -646,22 +670,18 @@ set src = usr.loc var/mob/user = usr - var/spos = 0 if(!istype(user)) return occupant_sanity_check() - if(occupant == user) spos = 1 - - switch(spos) - if(0) return - if(1) - occupant.forceMove(src.loc) - occupant = null + for(var/mob/M in occupants) + if(M == user) + M.forceMove(src.loc) + occupants -= M to_chat(user, "You climb out of \the [src].") -/obj/spacepod/verb/locksecondseat() +/obj/spacepod/verb/lock_pod() set name = "Lock Doors" set category = "Spacepod" set src = usr.loc @@ -723,7 +743,8 @@ set_light(lights_power) else set_light(0) - to_chat(occupant, "Toggled lights [lights ? "on" : "off"].") + for(var/mob/M in occupants) + to_chat(M, "Lights toggled [lights ? "on" : "off"].") return /obj/spacepod/proc/enter_after(delay as num, var/mob/user as mob, var/numticks = 5) @@ -839,4 +860,4 @@ ..() #undef DAMAGE -#undef FIRE +#undef FIRE \ No newline at end of file From f0520a2ed4dd7d9a826412b74869713561fa0599 Mon Sep 17 00:00:00 2001 From: IK3I Date: Sun, 8 May 2016 18:37:27 -0500 Subject: [PATCH 017/343] The first playable version of the Refactor Pods are single seat because nothing is in to expand max_occupants yet. Everything else works as intended however and there don't appear to be any runtimes in my testing. --- code/modules/spacepods/spacepod.dm | 52 +++++++++++++++++++++++------- 1 file changed, 40 insertions(+), 12 deletions(-) diff --git a/code/modules/spacepods/spacepod.dm b/code/modules/spacepods/spacepod.dm index 512a8ff0d38..36e9305258a 100644 --- a/code/modules/spacepods/spacepod.dm +++ b/code/modules/spacepods/spacepod.dm @@ -48,7 +48,7 @@ "pod_black" = "#3B8FE5", \ "pod_industrial" = "#CCCC00") - var/allow2enter = 1 + var/unlocked = 1 var/move_delay = 2 var/next_move = 0 @@ -238,7 +238,7 @@ /obj/spacepod/attackby(obj/item/W as obj, mob/user as mob, params) if(iscrowbar(W)) - if(!equipment_system.lock_system || allow2enter || hatch_open) + if(!equipment_system.lock_system || unlocked || hatch_open) hatch_open = !hatch_open playsound(loc, 'sound/items/Crowbar.ogg', 50, 1) to_chat(user, "You [hatch_open ? "open" : "close"] the maintenance hatch.") @@ -475,6 +475,7 @@ set src = usr.loc set popup_menu = 0 if(usr != src.occupants[PILOT]) + to_chat(usr, "You can't put a corpse into the driver's seat!") return 0 @@ -565,7 +566,7 @@ */ if(M == user) - if(!equipment_system.lock_system || allow2enter) + if(!equipment_system.lock_system || unlocked) enter_pod(user) else to_chat(user, "\The [src]'s doors are locked!") @@ -647,7 +648,9 @@ /obj/spacepod/proc/occupant_sanity_check() // going to have to adjust this later for cargo refactor if(occupants) if(occupants.len == max_occupants && !occupants[PILOT]) - occupants[PILOT] = occupants[1] + var/occ = occupants[1] + occupants -= occ + occupants[PILOT] = occ log_debug("##SPACEPOD WARNING: IMPOSSIBLE SEATING ARRANGEMENT: OCCUPANTS [english_list(occupants)], TURF [get_turf(src)] | AREA [get_area(src)] | COORDS [x], [y], [z]") if(occupants.len > max_occupants) for(var/i = occupants.len; i <= max_occupants; i--) @@ -673,21 +676,31 @@ if(!istype(user)) return + if (usr.stat != CONSCIOUS) // unconscious people can't let themselves out + return + occupant_sanity_check() - for(var/mob/M in occupants) - if(M == user) - M.forceMove(src.loc) - occupants -= M - to_chat(user, "You climb out of \the [src].") + if(user in occupants) + user.forceMove(get_turf(src)) + occupants -= user + to_chat(user, "You climb out of \the [src].") + if(user == occupants[PILOT]) + user.forceMove(get_turf(src)) + occupants[PILOT] = null + to_chat(user, "You climb out of \the [src].") /obj/spacepod/verb/lock_pod() set name = "Lock Doors" set category = "Spacepod" set src = usr.loc - allow2enter = !allow2enter - to_chat(usr, "You [allow2enter ? "unlock" : "lock"] the doors.") + if(usr in occupants && usr != src.occupants[PILOT]) + to_chat(usr, "You [unlocked ? "unlock" : "lock"] the doors.") /obj/spacepod/verb/toggleDoors() @@ -695,6 +708,10 @@ set category = "Spacepod" set src = usr.loc + if(usr != src.occupants[PILOT]) + to_chat(usr, "\The [src] has no weapons!") return @@ -726,6 +746,9 @@ set desc = "Unloads the cargo" set category = "Spacepod" set src = usr.loc + if(usr != src.occupants[PILOT]) + to_chat(usr, "\The [src] has no cargo system!") return @@ -735,6 +758,9 @@ set name = "Toggle Lights" set category = "Spacepod" set src = usr.loc + if(usr != src.occupants[PILOT]) + to_chat(usr, " Date: Mon, 9 May 2016 02:11:53 -0400 Subject: [PATCH 018/343] Removes Players Ready From Lobby --- code/modules/mob/new_player/new_player.dm | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/code/modules/mob/new_player/new_player.dm b/code/modules/mob/new_player/new_player.dm index ffb6f6c13b8..c427f6e7a50 100644 --- a/code/modules/mob/new_player/new_player.dm +++ b/code/modules/mob/new_player/new_player.dm @@ -88,13 +88,17 @@ stat("Time To Start:", "DELAYED") if(ticker.current_state == GAME_STATE_PREGAME) - stat("Players: [totalPlayers]", "Players Ready: [totalPlayersReady]") + stat("Players:", "[totalPlayers]") + if(client.holder) + stat("Players Ready:", "[totalPlayersReady]") totalPlayers = 0 totalPlayersReady = 0 for(var/mob/new_player/player in player_list) - stat("[player.key]", (player.ready)?("(Playing)"):(null)) + if(client.holder) + stat("[player.key]", (player.ready)?("(Playing)"):(null)) totalPlayers++ - if(player.ready)totalPlayersReady++ + if(player.ready) + totalPlayersReady++ /mob/new_player/Topic(href, href_list[]) if(!client) return 0 From 10780aa20086d3f866449145be0f026e2bd46eb8 Mon Sep 17 00:00:00 2001 From: Matt Date: Tue, 10 May 2016 00:02:55 +0200 Subject: [PATCH 019/343] Adds pAIzing --- code/modules/admin/admin.dm | 5 +++++ code/modules/admin/topic.dm | 22 ++++++++++++++++++++++ code/modules/mob/transform_procs.dm | 29 +++++++++++++++++++++++++++++ 3 files changed, 56 insertions(+) diff --git a/code/modules/admin/admin.dm b/code/modules/admin/admin.dm index 6e4f58c5ab2..d7e79934389 100644 --- a/code/modules/admin/admin.dm +++ b/code/modules/admin/admin.dm @@ -142,6 +142,11 @@ var/global/nologevent = 0 if(istype(M, /mob/dead/observer)) body += "
Re-incarnate | " + if(ispAI(M)) + body += "Is a pAI " + else + body += "Make pAI | " + // DNA2 - Admin Hax if(M.dna && iscarbon(M)) body += "

" diff --git a/code/modules/admin/topic.dm b/code/modules/admin/topic.dm index 7fb6806b5c0..090955de57a 100644 --- a/code/modules/admin/topic.dm +++ b/code/modules/admin/topic.dm @@ -1142,6 +1142,28 @@ message_admins("\blue [key_name_admin(usr)] attempting to corgize [key_name_admin(H)]", 1) H.corgize() + else if(href_list["makePAI"]) + if(!check_rights(R_SPAWN)) return + + var/mob/living/carbon/human/H = locate(href_list["makePAI"]) + if(!istype(H)) + to_chat(usr, "This can only be used on instances of type /mob/living/carbon/human") + return + + var/painame = "Default" + var/name = "" + if(alert(usr, "Do you want to set their name or let them choose their own name?", "Name Choice", "Set Name", "Let them choose") == "Set Name") + name = sanitize(copytext(input(usr, "Enter a name for the new pAI. Default name is [painame].", "pAI Name", painame),1,MAX_NAME_LEN)) + else + name = sanitize(copytext(input(H, "An admin wants to make you into a pAI. Choose a name. Default is [painame].", "pAI Name", painame),1,MAX_NAME_LEN)) + + if(!name) + name = painame + + log_admin("[key_name(usr)] attempting to pAIze [key_name(H)]") + message_admins("\blue [key_name_admin(usr)] attempting to pAIze [key_name_admin(H)]", 1) + H.paize(name) + else if(href_list["forcespeech"]) if(!check_rights(R_SERVER|R_EVENT)) return diff --git a/code/modules/mob/transform_procs.dm b/code/modules/mob/transform_procs.dm index ac3dd8af716..ea70bbe88ac 100644 --- a/code/modules/mob/transform_procs.dm +++ b/code/modules/mob/transform_procs.dm @@ -319,6 +319,35 @@ qdel(src) + +/mob/living/carbon/human/proc/paize(var/name) + if(notransform) + return + for(var/obj/item/W in src) + unEquip(W) + regenerate_icons() + notransform = 1 + canmove = 0 + icon = null + invisibility = 101 + for(var/t in organs) //this really should not be necessary + qdel(t) + + var/obj/item/device/paicard/card = new(loc) + var/mob/living/silicon/pai/pai = new(card) + pai.key = key + card.setPersonality(pai) + + pai.name = name + pai.real_name = name + card.name = name + + to_chat(pai, "You have become a pAI! Your name is [pai.name].") + pai.update_pipe_vision() + spawn(0)//To prevent the proc from returning null. + qdel(src) + return + /mob/proc/safe_respawn(var/MP) if(!MP) return 0 From 1d0965b1f935b18dd8887c4922b37acb2fff9ac1 Mon Sep 17 00:00:00 2001 From: KasparoVy Date: Tue, 10 May 2016 00:25:42 -0400 Subject: [PATCH 020/343] Back up to date. --- code/modules/reagents/newchem/drugs.dm | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/code/modules/reagents/newchem/drugs.dm b/code/modules/reagents/newchem/drugs.dm index 127a37593d1..62daeee99a3 100644 --- a/code/modules/reagents/newchem/drugs.dm +++ b/code/modules/reagents/newchem/drugs.dm @@ -337,9 +337,10 @@ var/check = rand(0,100) if(ishuman(M)) var/mob/living/carbon/human/H = M - if(check < 8 && H.h_style != "Very Long Beard") - H.h_style = "Very Long Hair" - H.f_style = "Very Long Beard" + var/obj/item/organ/external/head/head_organ = H.get_organ("head") + if(check < 8 && head_organ.h_style != "Very Long Beard") + head_organ.h_style = "Very Long Hair" + head_organ.f_style = "Very Long Beard" H.update_hair() H.update_fhair() H.visible_message("[H] has a wild look in their eyes!") From e5fae9c078905186cc74eacf33e7420e9d5aac0a Mon Sep 17 00:00:00 2001 From: KasparoVy Date: Tue, 10 May 2016 02:23:41 -0400 Subject: [PATCH 021/343] Small Fix Fixes rare occasions where markings (IPC optics) and head accessories wouldn't reset if you switched species via C.M.A. --- .../mob/living/carbon/human/appearance.dm | 24 +++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/code/modules/mob/living/carbon/human/appearance.dm b/code/modules/mob/living/carbon/human/appearance.dm index ce20923369d..52488051f50 100644 --- a/code/modules/mob/living/carbon/human/appearance.dm +++ b/code/modules/mob/living/carbon/human/appearance.dm @@ -124,6 +124,11 @@ /mob/living/carbon/human/proc/reset_hair() reset_head_hair() reset_facial_hair() + reset_head_accessory() + if(m_style && m_style != "None") //Resets the markings if they were head markings. + var/datum/sprite_accessory/marking_style = marking_styles_list[m_style] + if(marking_style && marking_style.marking_location == "head") + reset_markings() /mob/living/carbon/human/proc/reset_head_hair() var/obj/item/organ/external/head/H = get_organ("head") @@ -146,6 +151,25 @@ H.f_style = "Shaved" update_fhair() +/mob/living/carbon/human/proc/reset_markings() + var/list/valid_markings = generate_valid_markings() + if(valid_markings.len) + m_style = pick(valid_markings) + else + //this shouldn't happen + m_style = "None" + update_markings() + +/mob/living/carbon/human/proc/reset_head_accessory() + var/obj/item/organ/external/head/H = get_organ("head") + var/list/valid_head_accessories = generate_valid_head_accessories() + if(valid_head_accessories.len) + H.ha_style = pick(valid_head_accessories) + else + //this shouldn't happen + H.ha_style = "None" + update_head_accessory() + /mob/living/carbon/human/proc/change_eye_color(var/red, var/green, var/blue) if(red == r_eyes && green == g_eyes && blue == b_eyes) return From 241d779da4cf492c79e026978cc2814de58c48ba Mon Sep 17 00:00:00 2001 From: Matt Date: Tue, 10 May 2016 15:41:25 +0200 Subject: [PATCH 022/343] Snibbidy snab --- code/game/objects/items/weapons/legcuffs.dm | 33 ++++++++++++++++++++- 1 file changed, 32 insertions(+), 1 deletion(-) diff --git a/code/game/objects/items/weapons/legcuffs.dm b/code/game/objects/items/weapons/legcuffs.dm index fa485cbf93b..b50389c3931 100644 --- a/code/game/objects/items/weapons/legcuffs.dm +++ b/code/game/objects/items/weapons/legcuffs.dm @@ -19,11 +19,15 @@ desc = "A trap used to catch bears and other legged creatures." var/armed = 0 var/obj/item/weapon/grenade/iedcasing/IED = null + var/obj/item/device/assembly/signaler/sig = null /obj/item/weapon/restraints/legcuffs/beartrap/Destroy() if(IED) qdel(IED) IED = null + if(sig) + qdel(sig) + sig = null return ..() /obj/item/weapon/restraints/legcuffs/beartrap/suicide_act(mob/user) @@ -43,6 +47,9 @@ if(IED) to_chat(user, "This beartrap already has an IED hooked up to it!") return + if(sig) + to_chat(user, "This beartrap already has a signaller hooked up to it!") + return IED = I switch(IED.assembled) if(0,1) //if it's not fueled/hooked up @@ -60,12 +67,33 @@ to_chat(user, "You shouldn't be reading this message! Contact a coder or someone, something broke!") IED = null return + if(istype(I, /obj/item/device/assembly/signaler)) + if(IED) + to_chat(user, "This beartrap already has an IED hooked up to it!") + return + if(sig) + to_chat(user, "This beartrap already has a signaller hooked up to it!") + return + sig = I + if(sig.secured) + to_chat(user, "The signaller is secured.") + sig = null + return + user.drop_item(src) + I.forceMove(src) + to_chat(user, "You sneak the [sig] underneath the pressure plate and connect the trigger wire.") + desc = "A trap used to catch bears and other legged creatures. There is a remote signaller hooked up to it." if(istype(I, /obj/item/weapon/screwdriver)) if(IED) IED.forceMove(get_turf(src)) IED = null to_chat(user, "You remove the IED from the [src].") return + if(sig) + sig.forceMove(get_turf(src)) + sig = null + to_chat(user, "You remove the signaller from the [src].") + return ..() /obj/item/weapon/restraints/legcuffs/beartrap/Crossed(AM as mob|obj) @@ -88,6 +116,9 @@ spawn(IED.det_time) IED.prime() + if(sig && isturf(src.loc)) + sig.signal() + if(ishuman(AM)) var/mob/living/carbon/H = AM if(H.lying) @@ -192,4 +223,4 @@ /obj/item/weapon/legcuffs/bolas/Bump() ..() - throw_failed() //allows a mech bolas to be destroyed \ No newline at end of file + throw_failed() //allows a mech bolas to be destroyed From ed58122df2bcfb2f1a30de6f08da857909d39b5f Mon Sep 17 00:00:00 2001 From: Matt Date: Tue, 10 May 2016 15:43:46 +0200 Subject: [PATCH 023/343] Grammar --- code/game/objects/items/weapons/legcuffs.dm | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/code/game/objects/items/weapons/legcuffs.dm b/code/game/objects/items/weapons/legcuffs.dm index b50389c3931..6b88d280592 100644 --- a/code/game/objects/items/weapons/legcuffs.dm +++ b/code/game/objects/items/weapons/legcuffs.dm @@ -48,7 +48,7 @@ to_chat(user, "This beartrap already has an IED hooked up to it!") return if(sig) - to_chat(user, "This beartrap already has a signaller hooked up to it!") + to_chat(user, "This beartrap already has a signaler hooked up to it!") return IED = I switch(IED.assembled) @@ -72,17 +72,17 @@ to_chat(user, "This beartrap already has an IED hooked up to it!") return if(sig) - to_chat(user, "This beartrap already has a signaller hooked up to it!") + to_chat(user, "This beartrap already has a signaler hooked up to it!") return sig = I if(sig.secured) - to_chat(user, "The signaller is secured.") + to_chat(user, "The signaler is secured.") sig = null return user.drop_item(src) I.forceMove(src) to_chat(user, "You sneak the [sig] underneath the pressure plate and connect the trigger wire.") - desc = "A trap used to catch bears and other legged creatures. There is a remote signaller hooked up to it." + desc = "A trap used to catch bears and other legged creatures. There is a remote signaler hooked up to it." if(istype(I, /obj/item/weapon/screwdriver)) if(IED) IED.forceMove(get_turf(src)) @@ -92,7 +92,7 @@ if(sig) sig.forceMove(get_turf(src)) sig = null - to_chat(user, "You remove the signaller from the [src].") + to_chat(user, "You remove the signaler from the [src].") return ..() From b6edc4a0ac88d63cb9d6c537142359b4744df1bc Mon Sep 17 00:00:00 2001 From: Fox-McCloud Date: Tue, 10 May 2016 23:46:25 -0400 Subject: [PATCH 024/343] Can Flip Over Someone --- code/modules/mob/living/carbon/human/emote.dm | 22 ++++++++++++++----- 1 file changed, 16 insertions(+), 6 deletions(-) diff --git a/code/modules/mob/living/carbon/human/emote.dm b/code/modules/mob/living/carbon/human/emote.dm index 1bb9ec062a9..eca554dcb0c 100644 --- a/code/modules/mob/living/carbon/human/emote.dm +++ b/code/modules/mob/living/carbon/human/emote.dm @@ -307,18 +307,28 @@ if (M == src) M = null - if (M) - if(src.lying || src.weakened) + if(M) + if(lying || weakened) message = "[src] flops and flails around on the floor." else message = "[src] flips in [M]'s general direction." - src.SpinAnimation(5,1) + SpinAnimation(5,1) else - if(src.lying || src.weakened) + if(lying || weakened) message = "[src] flops and flails around on the floor." else - message = "[src] does a flip!" - src.SpinAnimation(5,1) + var/obj/item/weapon/grab/G = get_active_hand() + if(G && G.affecting) + var/turf/oldloc = loc + var/turf/newloc = G.affecting.loc + if(isturf(oldloc) && isturf(newloc)) + SpinAnimation(5,1) + forceMove(newloc) + G.affecting.forceMove(oldloc) + message = "[src] flips over [G.affecting]!" + else + message = "[src] does a flip!" + SpinAnimation(5,1) if ("aflap", "aflaps") if (!src.restrained()) From 007c7ba8d3436ff7dce9a76bbf4057496f1d86fa Mon Sep 17 00:00:00 2001 From: Fox-McCloud Date: Wed, 11 May 2016 19:12:26 -0400 Subject: [PATCH 025/343] Dumber --- code/game/dna/genes/powers.dm | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/code/game/dna/genes/powers.dm b/code/game/dna/genes/powers.dm index 2aca5878f83..eb33cef7ccf 100644 --- a/code/game/dna/genes/powers.dm +++ b/code/game/dna/genes/powers.dm @@ -144,8 +144,8 @@ /datum/dna/gene/basic/tk name="Telekenesis" - activation_messages=list("You feel smarter.") - deactivation_messages=("You feel dumber.") + activation_messages = list("You feel smarter.") + deactivation_messages = list("You feel dumber.") mutation=TK activation_prob=10 From b3169f18eaf37f4c779aa7d87b7d1d80c072bff9 Mon Sep 17 00:00:00 2001 From: IK3I Date: Wed, 11 May 2016 18:20:04 -0500 Subject: [PATCH 026/343] Cargo and Occupant Refactor with some cleaning Various code optimizations and bug fixes New cargo systems to make storage useful and test with Secondary cargo system is now the slot that your chair or loot box can go in --- .../research/designs/spacepod_designs.dm | 48 +++- code/modules/spacepods/equipment.dm | 78 +++++- code/modules/spacepods/spacepod.dm | 242 ++++++++++-------- 3 files changed, 254 insertions(+), 114 deletions(-) diff --git a/code/modules/research/designs/spacepod_designs.dm b/code/modules/research/designs/spacepod_designs.dm index c1927e47654..2a57f8399f6 100644 --- a/code/modules/research/designs/spacepod_designs.dm +++ b/code/modules/research/designs/spacepod_designs.dm @@ -12,6 +12,7 @@ ////////////////////////////////////////////////// /////////SPACEPOD PARTS/////////////////////////// ////////////////////////////////////////////////// + /datum/design/podframe_fp construction_time = 200 name = "Fore port pod frame" @@ -89,6 +90,7 @@ ////////////////////////////////////////// //////SPACEPOD GUNS/////////////////////// ////////////////////////////////////////// + /datum/design/pod_gun_taser construction_time = 200 name = "Spacepod Equipment (Taser)" @@ -157,6 +159,7 @@ materials = list(MAT_METAL = 10000, MAT_GLASS = 5000, MAT_SILVER = 4000, MAT_GOLD = 4000, MAT_DIAMOND = 4000) build_path = /obj/item/device/spacepod_equipment/weaponry/mining_laser_hyper category = list("Pod_Weaponry") + ////////////////////////////////////////// //////SPACEPOD MISC. ITEMS//////////////// ////////////////////////////////////////// @@ -172,16 +175,57 @@ build_path = /obj/item/device/spacepod_equipment/misc/tracker category = list("Pod_Parts") +////////////////////////////////////////// +//////SPACEPOD CARGO ITEMS//////////////// +////////////////////////////////////////// + /datum/design/pod_cargo_ore construction_time = 100 name = "Spacepod Ore Storage Module" desc = "Allows for the construction of a Space Pod Ore Storage Module." id = "podcargo_ore" - req_tech = list("materials" = 3) + req_tech = list("materials" = 3, "engineering" = 2) build_type = PODFAB materials = list(MAT_METAL=20000, MAT_GLASS=2000) build_path = /obj/item/device/spacepod_equipment/cargo/ore - category = list("Pod_Parts") + category = list("Cargo Systems") + +/datum/design/pod_cargo_crate + construction_time = 100 + name = "Spacepod Crate Storage Module" + desc = "Allows the construction of a Space Pod Crate Storage Module." + id = "podcargo_crate" + req_tech = list("materials" = 4, "engineering" = 2) //hollowing out this much of the pod without compromising structural integrity is hard + build_type = PODFAB + materials = list(MAT_METAL=25000) + build_path = /obj/item/device/spacepod_equipment/cargo/crate + category = list("Cargo Systems") + +////////////////////////////////////////// +//////SPACEPOD SEC CARGO ITEMS//////////// +////////////////////////////////////////// + +/datum/design/passenger_seat + construction_time = 100 + name = "Spacepod Passenger Seat" + desc = "Allows the construction of a Space Pod Passenger Seat Module." + id = "podcargo_sec_seat" + req_tech = list("materials" = 1) // Because rule number one of refactoring + build_type = PODFAB + materials = list(MAT_METAL=7500, MAT_GLASS=2500) + build_path = /obj/item/device/spacepod_equipment/sec_cargo/chair + category = list("Secondary Cargo Systems") + +/datum/design/loot_box + construction_time = 100 + name = "Spacepod Loot Storage Module" + desc = "Allows the construction of a Space Pod Crate Storage Module." + id = "podcargo_sec_lootbox" + req_tech = list("materials" = 1) //it's just a set of shelves, It's not that hard to make + build_type = PODFAB + materials = list(MAT_METAL=7500, MAT_GLASS=2500) + build_path = /obj/item/device/spacepod_equipment/sec_cargo/loot_box + category = list("Secondary Cargo Systems") ////////////////////////////////////////// //////SPACEPOD LOCK ITEMS//////////////// diff --git a/code/modules/spacepods/equipment.dm b/code/modules/spacepods/equipment.dm index 91588fa0a8b..7ff052d1e6e 100644 --- a/code/modules/spacepods/equipment.dm +++ b/code/modules/spacepods/equipment.dm @@ -49,6 +49,7 @@ var/obj/item/device/spacepod_equipment/weaponry/weapon_system // weapons system var/obj/item/device/spacepod_equipment/misc/misc_system // misc system var/obj/item/device/spacepod_equipment/cargo/cargo_system // cargo system + var/obj/item/device/spacepod_equipment/cargo/sec_cargo_system // secondary cargo system var/obj/item/device/spacepod_equipment/lock/lock_system // lock system //var/obj/item/device/spacepod_equipment/engine/engine_system // engine system //var/obj/item/device/spacepod_equipment/shield/shield_system // shielding system @@ -61,11 +62,17 @@ /obj/item/device/spacepod_equipment name = "equipment" var/obj/spacepod/my_atom + var/occupant_mod = 0 // so any module can modify occupancy + var/list/storage_mod = list("slots" = 0, "w_class" = 0) // so any module can modify storage slots /obj/item/device/spacepod_equipment/proc/removed(var/mob/user) // So that you can unload cargo when you remove the module return -// base item for spacepod weapons +/* +/////////////////////////////////////// +/////////Weapon System/////////////////// +/////////////////////////////////////// +*/ /obj/item/device/spacepod_equipment/weaponry name = "pod weapon" @@ -135,7 +142,12 @@ fire_delay = 8 fire_sound = 'sound/weapons/Kenetic_accel.ogg' -//base item for spacepod misc equipment (tracker) +/* +/////////////////////////////////////// +/////////Misc. System/////////////////// +/////////////////////////////////////// +*/ + /obj/item/device/spacepod_equipment/misc name = "pod misc" desc = "You shouldn't be seeing this" @@ -160,6 +172,12 @@ else ..() +/* +/////////////////////////////////////// +/////////Cargo System////////////////// +/////////////////////////////////////// +*/ + /obj/item/device/spacepod_equipment/cargo name = "pod cargo" desc = "You shouldn't be seeing this" @@ -169,11 +187,13 @@ /obj/item/device/spacepod_equipment/cargo/proc/passover(var/obj/item/I) return -/obj/item/device/spacepod_equipment/cargo/proc/unload() +/obj/item/device/spacepod_equipment/cargo/proc/unload() // called by unload verb return + +// Ore System /obj/item/device/spacepod_equipment/cargo/ore - name = "\improper spacepod ore storage system" + name = "spacepod ore storage system" desc = "An ore storage system for spacepods. Scoops up any ore you drive over." icon_state = "cargo_ore" var/obj/structure/ore_box/box @@ -191,6 +211,56 @@ . = ..() unload() +// Crate System +/obj/item/device/spacepod_equipment/cargo/crate + name = "spacepod crate storage system" + desc = "A heavy duty storage system for spacepods. Holds one crate." + icon_state = "cargo_ore" + var/obj/structure/closet/crate/crate + +/obj/item/device/spacepod_equipment/cargo/crate/unload() + if(crate) + crate.forceMove(get_turf(my_atom)) + crate = null + +/obj/item/device/spacepod_equipment/cargo/crate/removed(var/mob/user) + . = ..() + unload() + +/* +/////////////////////////////////////// +/////////Secondary Cargo System//////// +/////////////////////////////////////// +*/ + +//Storage system and inventory is handled in cargo_hold.dm + +/obj/item/device/spacepod_equipment/sec_cargo + name = "secondary cargo" + desc = "you shouldn't be seeing this" + icon = 'icons/vehicles/spacepod.dmi' + icon_state = "blank" + +// Passenger Seat +/obj/item/device/spacepod_equipment/sec_cargo/chair + name = "passanger seat" + desc = "A passenger seat for a spacepod" + icon_state = "cargo_ore" + occupant_mod = 1 + +// Loot Box +/obj/item/device/spacepod_equipment/sec_cargo/loot_box + name = "loot box" + desc = "A small compartment to store valuables" + icon_state = "cargo_ore" + storage_mod = list("slots" = 7, "w_class" = 14) + +/* +/////////////////////////////////////// +/////////Lock System/////////////////// +/////////////////////////////////////// +*/ + /obj/item/device/spacepod_equipment/lock name = "pod lock" desc = "You shouldn't be seeing this" diff --git a/code/modules/spacepods/spacepod.dm b/code/modules/spacepods/spacepod.dm index 36e9305258a..4fe925ac085 100644 --- a/code/modules/spacepods/spacepod.dm +++ b/code/modules/spacepods/spacepod.dm @@ -17,6 +17,7 @@ var/list/mob/occupants = list() //uses [PILOT] index for pilot and numerics for passangers var/max_occupants = 1 + var/obj/item/weapon/storage/internal/cargo_hold var/datum/spacepod/equipment/equipment_system @@ -73,12 +74,19 @@ pr_give_air = new /datum/global_iterator/pod_tank_give_air(list(src)) equipment_system = new(src) spacepods_list += src + cargo_hold = new/obj/item/weapon/storage/internal(src) + cargo_hold.w_class = 5 //so you can put bags in + cargo_hold.storage_slots = 0 //You need to install cargo modules to use it. + cargo_hold.max_w_class = 5 //fit almost anything + cargo_hold.max_combined_w_class = 0 //you can optimize your stash with larger items /obj/spacepod/Destroy() if (equipment_system.cargo_system) equipment_system.cargo_system.removed(null) qdel(equipment_system) equipment_system = null + qdel(cargo_hold) + cargo_hold = null qdel(battery) battery = null qdel(cabin_air) @@ -210,6 +218,7 @@ /obj/spacepod/emp_act(severity) occupant_sanity_check() + cargo_hold.emp_act(severity) switch(severity) if(1) if(occupants) @@ -244,6 +253,7 @@ to_chat(user, "You [hatch_open ? "open" : "close"] the maintenance hatch.") else to_chat(user, "The hatch is locked shut!") + return if(istype(W, /obj/item/weapon/stock_parts/cell)) if(!hatch_open) to_chat(user, "\red The maintenance hatch is closed!") @@ -260,61 +270,32 @@ to_chat(user, "\red The maintenance hatch is closed!") return if(!equipment_system) - to_chat(user, "The pod has no equipment datum, yell at pomf") + to_chat(user, "The pod has no equipment datum, yell at IK3I") return if(istype(W, /obj/item/device/spacepod_equipment/weaponry)) - if(equipment_system.weapon_system) - to_chat(user, "The pod already has a weapon system, remove it first.") - return - else - to_chat(user, "You insert \the [W] into the equipment system.") - user.drop_item(W) - W.forceMove(src) - equipment_system.weapon_system = W - equipment_system.weapon_system.my_atom = src - return - + add_equipment(user, W, "weapon_system") + return if(istype(W, /obj/item/device/spacepod_equipment/misc)) - if(equipment_system.misc_system) - to_chat(user, "The pod already has a miscellaneous system, remove it first.") - return - else - to_chat(user, "You insert \the [W] into the equipment system.") - user.drop_item(W) - W.forceMove(src) - equipment_system.misc_system = W - equipment_system.misc_system.my_atom = src - return + add_equipment(user, W, "misc_system") + return if(istype(W, /obj/item/device/spacepod_equipment/cargo)) - if(equipment_system.cargo_system) - to_chat(user, "The pod already has a cargo system, remove it first.") - return - else - to_chat(user, "You insert \the [W] into the cargo system.") - user.drop_item(W) - W.forceMove(src) - equipment_system.cargo_system = W - equipment_system.cargo_system.my_atom = src - return + add_equipment(user, W, "cargo_system") + return + if(istype(W, /obj/item/device/spacepod_equipment/sec_cargo)) + add_equipment(user, W, "sec_cargo_system") + return if(istype(W, /obj/item/device/spacepod_equipment/lock)) - if(equipment_system.lock_system) - to_chat(user, "The pod already has a lock system, remove it first.") - return - else - to_chat(user, "You insert \the [W] into the lock system.") - user.drop_item(W) - W.forceMove(src) - equipment_system.lock_system = W - equipment_system.lock_system.my_atom = src - return + add_equipment(user, W, "lock_system") + return if(istype(W, /obj/item/device/spacepod_key) && istype(equipment_system.lock_system, /obj/item/device/spacepod_equipment/lock/keyed)) var/obj/item/device/spacepod_key/key = W if (key.id == equipment_system.lock_system.id) lock_pod() + return else to_chat(user, "This is the wrong key!") - return + return if(istype(W, /obj/item/weapon/weldingtool)) if(!hatch_open) @@ -331,12 +312,38 @@ if(!src || !WT.remove_fuel(3, user)) return repair_damage(10) to_chat(user, "\blue You mend some [pick("dents","bumps","damage")] with \the [WT]") + return else to_chat(user, "\blue \The [src] is fully repaired!") + return + if(cargo_hold.storage_slots > 0 && !hatch_open && unlocked) // must be the last option as all items not listed prior will be stored + cargo_hold.attackby(W, user, params) + return + +obj/spacepod/proc/add_equipment(mob/user, var/obj/item/device/spacepod_equipment/SPE, var/slot) + if(equipment_system.vars[slot]) + to_chat(user, "The pod already has a [slot], remove it first.") + return + else + to_chat(user, "You insert \the [SPE] into the pod.") + user.drop_item(SPE) + SPE.forceMove(src) + equipment_system.vars[slot] = SPE + var/obj/item/device/spacepod_equipment/system = equipment_system.vars[slot] + system.my_atom = src + max_occupants += SPE.occupant_mod + cargo_hold.storage_slots += SPE.storage_mod["slots"] + cargo_hold.max_combined_w_class += SPE.storage_mod["w_class"] + return /obj/spacepod/attack_hand(mob/user as mob) if(!hatch_open) + if(cargo_hold.storage_slots > 0) + if(unlocked) + cargo_hold.open(user) + else + to_chat(user, "The storage compartment is locked") return ..() if(!equipment_system || !istype(equipment_system)) to_chat(user, "The pod has no equpment datum, or is the wrong type, yell at pomf.") @@ -350,75 +357,83 @@ possible.Add("Misc. System") if(equipment_system.cargo_system) possible.Add("Cargo System") + if(equipment_system.sec_cargo_system) + possible.Add("Secondary Cargo System") if(equipment_system.lock_system) possible.Add("Lock System") - /* Not yet implemented - if(equipment_system.engine_system) - possible.Add("Engine System") - if(equipment_system.shield_system) - possible.Add("Shield System") - */ - var/obj/item/device/spacepod_equipment/SPE switch(input(user, "Remove which equipment?", null, null) as null|anything in possible) if("Energy Cell") if(user.put_in_any_hand_if_possible(battery)) to_chat(user, "You remove \the [battery] from the space pod") battery = null + else + to_chat(user, "You need an open hand to do that.") + return if("Weapon System") - SPE = equipment_system.weapon_system - if(user.put_in_any_hand_if_possible(SPE)) - to_chat(user, "You remove \the [SPE] from the equipment system.") - SPE.removed(user) - SPE.my_atom = null - equipment_system.weapon_system = null - else - to_chat(user, "You need an open hand to do that.") + remove_equipment(user, equipment_system.weapon_system, "weapon_system") + return if("Misc. System") - SPE = equipment_system.misc_system - if(user.put_in_any_hand_if_possible(SPE)) - to_chat(user, "You remove \the [SPE] from the equipment system.") - SPE.removed(user) - SPE.my_atom = null - equipment_system.misc_system = null - else - to_chat(user, "You need an open hand to do that.") + remove_equipment(user, equipment_system.misc_system, "misc_system") + return if("Cargo System") - SPE = equipment_system.cargo_system - if(user.put_in_any_hand_if_possible(SPE)) - to_chat(user, "You remove \the [SPE] from the equipment system.") - SPE.removed(user) - SPE.my_atom = null - equipment_system.cargo_system = null - else - to_chat(user, "You need an open hand to do that.") + remove_equipment(user, equipment_system.cargo_system, "cargo_system") + return + if("Secondary Cargo System") + remove_equipment(user, equipment_system.sec_cargo_system, "sec_cargo_system") + return if("Lock System") - SPE = equipment_system.lock_system - if(user.put_in_any_hand_if_possible(SPE)) - to_chat(user, "You remove \the [SPE] from the equipment system.") - SPE.removed(user) - SPE.my_atom = null - equipment_system.lock_system = null - else - to_chat(user, "You need an open hand to do that.") - /* - if("engine system") - SPE = equipment_system.engine_system - if(user.put_in_any_hand_if_possible(SPE)) - to_chat(user, "You remove \the [SPE] from the equipment system.") - equipment_system.engine_system = null - else - to_chat(user, "You need an open hand to do that.") - if("shield system") - SPE = equipment_system.shield_system - if(user.put_in_any_hand_if_possible(SPE)) - to_chat(user, "You remove \the [SPE] from the equipment system.") - equipment_system.shield_system = null - else - to_chat(user, "You need an open hand to do that.") - */ - + remove_equipment(user, equipment_system.lock_system, "lock_system") + return return +/obj/spacepod/proc/remove_equipment(mob/user, var/obj/item/device/spacepod_equipment/SPE, var/slot) + + if(occupants.len > max_occupants - SPE.occupant_mod) + to_chat(user, "Someone is sitting in \the [SPE]!") + return + + var/sum_w_class = 0 + for(var/obj/item/I in cargo_hold.contents) + sum_w_class += I.w_class + if(cargo_hold.contents.len > cargo_hold.storage_slots - SPE.storage_mod["slots"] || sum_w_class > cargo_hold.max_combined_w_class - SPE.storage_mod["w_class"]) + to_chat(user, "Empty \the [SPE] first!") + return + + if(user.put_in_any_hand_if_possible(SPE)) + to_chat(user, "You remove \the [SPE] from the equipment system.") + max_occupants -= SPE.occupant_mod + cargo_hold.storage_slots -= SPE.storage_mod["slots"] + cargo_hold.max_combined_w_class -= SPE.storage_mod["w_class"] + SPE.removed(user) + SPE.my_atom = null + equipment_system.vars[slot] = null + else + to_chat(user, "You need an open hand to do that.") + return + + +/obj/spacepod/hear_talk/hear_talk(mob/M, var/msg) + cargo_hold.hear_talk(M, msg) + ..() + +/obj/spacepod/hear_message(mob/M, var/msg) + cargo_hold.hear_message(M, msg) + ..() + +/obj/spacepod/proc/return_inv() + + var/list/L = list( ) + + L += src.contents + + for(var/obj/item/weapon/storage/S in src) + L += S.return_inv() + for(var/obj/item/weapon/gift/G in src) + L += G.gift + if (istype(G.gift, /obj/item/weapon/storage)) + L += G.gift:return_inv() + return L + /obj/spacepod/civilian icon_state = "pod_civ" desc = "A sleek civilian space pod." @@ -566,11 +581,7 @@ */ if(M == user) - if(!equipment_system.lock_system || unlocked) - enter_pod(user) - else - to_chat(user, "\The [src]'s doors are locked!") - + enter_pod(user) if(istype(A, /obj/structure/ore_box)) // For loading ore boxes var/obj/structure/ore_box/O = A @@ -587,14 +598,29 @@ else to_chat(user, "\The [src] already has \an [C.box]") -/obj/spacepod/verb/enter_pod(mob/user = usr) - set category = "Object" - set name = "Enter Pod" - set src in oview(1) + if(istype(A, /obj/structure/closet/crate)) // For loading crates + var/obj/structure/closet/crate/O = A + if(equipment_system.cargo_system && istype(equipment_system.cargo_system, /obj/item/device/spacepod_equipment/cargo/crate)) + var/obj/item/device/spacepod_equipment/cargo/crate/C = equipment_system.cargo_system + if(!C.crate) + to_chat(user, "You begin loading \the [O] into \the [src]'s [equipment_system.cargo_system]") + if(do_after(user, 40, target = src)) + C.crate = O + O.forceMove(C) + to_chat(user, "You load \the [O] into \the [src]'s [equipment_system.cargo_system]!") + else + to_chat(user, "You fail to load \the [O] into \the [src]'s [equipment_system.cargo_system]") + else + to_chat(user, "\The [src] already has \an [C.crate]") +/obj/spacepod/proc/enter_pod(mob/user) if (usr.stat != CONSCIOUS) return + if(equipment_system.lock_system && !unlocked) + to_chat(user, "\The [src]'s doors are locked!") + return + if(get_dist(src, user) > 2 || get_dist(usr, user) > 1) to_chat(usr, "They are too far away to put inside") return From a5da710c8b245344e82a47d63a366bed204fa4ed Mon Sep 17 00:00:00 2001 From: monster860 Date: Thu, 12 May 2016 18:20:49 -0400 Subject: [PATCH 027/343] Fixes camerachunk --- code/modules/mob/living/silicon/ai/freelook/chunk.dm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/modules/mob/living/silicon/ai/freelook/chunk.dm b/code/modules/mob/living/silicon/ai/freelook/chunk.dm index e4b7f983b9d..71d80df9e02 100644 --- a/code/modules/mob/living/silicon/ai/freelook/chunk.dm +++ b/code/modules/mob/living/silicon/ai/freelook/chunk.dm @@ -142,7 +142,7 @@ if(c.can_use()) cameras += c - for(var/turf/t in block(locate(x, y, z), locate(min(x + CHUNK_SIZE - 1, world.maxx), min(y + CHUNK_SIZE - 1, world.maxy), z))) + for(var/turf/t in block(locate(max(x, 1), max(y, 1), max(z, 1)), locate(min(x + CHUNK_SIZE - 1, world.maxx), min(y + CHUNK_SIZE - 1, world.maxy), z))) turfs[t] = t for(var/camera in cameras) From 53e52f24d4ff54100d3ebf675c33817f54843feb Mon Sep 17 00:00:00 2001 From: monster860 Date: Thu, 12 May 2016 18:39:01 -0400 Subject: [PATCH 028/343] lein nutes --- code/game/objects/items/weapons/RCD.dm | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/code/game/objects/items/weapons/RCD.dm b/code/game/objects/items/weapons/RCD.dm index d00e456d3e8..5d85ea20e2b 100644 --- a/code/game/objects/items/weapons/RCD.dm +++ b/code/game/objects/items/weapons/RCD.dm @@ -103,7 +103,8 @@ RCD if(useResource(1, user)) to_chat(user, "Building Floor...") activate() - A:ChangeTurf(/turf/simulated/floor/plating) + var/turf/AT = A + AT.ChangeTurf(/turf/simulated/floor/plating) return 1 return 0 @@ -114,7 +115,8 @@ RCD if(do_after(user, 20, target = A)) if(!useResource(3, user)) return 0 activate() - A:ChangeTurf(/turf/simulated/wall) + var/turf/AT = A + AT.ChangeTurf(/turf/simulated/wall) return 1 return 0 @@ -142,7 +144,8 @@ RCD if(do_after(user, 40, target = A)) if(!useResource(5, user)) return 0 activate() - A:ChangeTurf(/turf/simulated/floor/plating) + var/turf/AT = A + AT.ChangeTurf(/turf/simulated/floor/plating) return 1 return 0 @@ -153,7 +156,8 @@ RCD if(do_after(user, 50, target = A)) if(!useResource(5, user)) return 0 activate() - A:ChangeTurf(/turf/space) + var/turf/AT = A + AT.ChangeTurf(/turf/space) return 1 return 0 @@ -236,7 +240,8 @@ RCD else // Build a window! var/obj/structure/window/reinforced/W = new(A) W.dir = cdir - A:ChangeTurf(/turf/simulated/floor/plating) // Platings go under windows. + var/turf/AT = A + AT.ChangeTurf(/turf/simulated/floor/plating) // Platings go under windows. return 1 else to_chat(user, "ERROR: RCD in MODE: [mode] attempted use by [user]. Send this text #coderbus or an admin.") From b77541bc9b9bfe11287deb63d3e943b9f6161ee3 Mon Sep 17 00:00:00 2001 From: Tastyfish Date: Thu, 12 May 2016 19:22:07 -0400 Subject: [PATCH 029/343] Fixes a couple runtimes and weird add_reagents/add_reagents_list that was silly --- code/_onclick/hud/action.dm | 3 ++- code/datums/diseases/advance/symptoms/sensory.dm | 2 +- code/game/objects/items/devices/radio/radio.dm | 2 +- 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/code/_onclick/hud/action.dm b/code/_onclick/hud/action.dm index 0a891be21f5..233add211f6 100644 --- a/code/_onclick/hud/action.dm +++ b/code/_onclick/hud/action.dm @@ -50,7 +50,8 @@ T.client.screen -= button qdel(button) button = null - T.actions.Remove(src) + if(T.actions) + T.actions.Remove(src) T.update_action_buttons() owner = null return diff --git a/code/datums/diseases/advance/symptoms/sensory.dm b/code/datums/diseases/advance/symptoms/sensory.dm index b25c4bacf47..99f670c258e 100644 --- a/code/datums/diseases/advance/symptoms/sensory.dm +++ b/code/datums/diseases/advance/symptoms/sensory.dm @@ -31,7 +31,7 @@ Bonus switch(A.stage) if(2) if(M.reagents.get_reagent_amount("oculine")<10) - M.reagents.add_reagent("oculine"=10) + M.reagents.add_reagent("oculine", 10) to_chat(M, "Your hearing feels clearer and crisp.") if(3) if(M.reagents.get_reagent_amount("antihol") < 10 && M.reagents.get_reagent_amount("oculine") < 10 ) diff --git a/code/game/objects/items/devices/radio/radio.dm b/code/game/objects/items/devices/radio/radio.dm index 741ecfa7fa2..75b2a458d54 100644 --- a/code/game/objects/items/devices/radio/radio.dm +++ b/code/game/objects/items/devices/radio/radio.dm @@ -520,7 +520,7 @@ var/global/list/default_medbay_channels = list( // what the range is in which mobs will hear the radio // returns: -1 if can't receive, range otherwise - if (wires.IsIndexCut(WIRE_RECEIVE)) + if (!wires || wires.IsIndexCut(WIRE_RECEIVE)) return -1 if(!listening) return -1 From 2988b66c7b0329cec2a894857c9ac677b118a6ba Mon Sep 17 00:00:00 2001 From: ParadiseSS13-Bot Date: Thu, 12 May 2016 19:35:53 -0400 Subject: [PATCH 030/343] Automatic changelog generation for PR #4375 --- html/changelogs/AutoChangeLog-pr-4375.yml | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 html/changelogs/AutoChangeLog-pr-4375.yml diff --git a/html/changelogs/AutoChangeLog-pr-4375.yml b/html/changelogs/AutoChangeLog-pr-4375.yml new file mode 100644 index 00000000000..5556d1b71b2 --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-4375.yml @@ -0,0 +1,4 @@ +author: monster860 +delete-after: True +changes: + - rscadd: "Windows can now be constructed and deconstructed using RCD's." From e22bc8a42b07fbe61723d8d5add4037511de58ba Mon Sep 17 00:00:00 2001 From: Fox-McCloud Date: Thu, 12 May 2016 23:47:30 -0400 Subject: [PATCH 031/343] Foam Fixes+Changes --- code/game/objects/effects/effect_system.dm | 51 +++++++++++----- .../items/weapons/grenades/chem_grenade.dm | 6 +- .../mob/living/simple_animal/bot/medbot.dm | 2 +- code/modules/reagents/Chemistry-Holder.dm | 59 ++++++++++--------- code/modules/reagents/newchem/pyro.dm | 4 +- code/modules/surgery/organs/blood.dm | 4 +- 6 files changed, 76 insertions(+), 50 deletions(-) diff --git a/code/game/objects/effects/effect_system.dm b/code/game/objects/effects/effect_system.dm index 744edcd7711..d73edde1525 100644 --- a/code/game/objects/effects/effect_system.dm +++ b/code/game/objects/effects/effect_system.dm @@ -916,6 +916,8 @@ steam.start() -- spawns the effect /obj/effect/effect/foam/New(loc, var/ismetal=0) ..(loc) icon_state = "[ismetal ? "m":""]foam" + if(!ismetal && reagents) + color = mix_color_from_reagents(reagents.reagent_list) metal = ismetal playsound(src, 'sound/effects/bubbles2.ogg', 80, 1, -3) spawn(3 + metal*3) @@ -944,10 +946,13 @@ steam.start() -- spawns the effect // on delete, transfer any reagents to the floor /obj/effect/effect/foam/Destroy() if(!metal && reagents) - for(var/atom/A in oview(0,src)) + reagents.handle_reactions() + for(var/atom/A in oview(1, src)) if(A == src) continue - reagents.reaction(A, 1, 1) + if(reagents.total_volume) + var/fraction = 5 / reagents.total_volume + reagents.reaction(A, TOUCH, fraction) return ..() /obj/effect/effect/foam/process() @@ -969,13 +974,14 @@ steam.start() -- spawns the effect if(F) continue - F = new(T, metal) + F = new /obj/effect/effect/foam(T, metal) F.amount = amount if(!metal) - F.create_reagents(10) - if (reagents) + F.create_reagents(15) + if(reagents) for(var/datum/reagent/R in reagents.reagent_list) - F.reagents.add_reagent(R.id,1) + F.reagents.add_reagent(R.id, min(R.volume, 3), R.data, reagents.chem_temp) + F.color = mix_color_from_reagents(reagents.reagent_list) // foam disolves when heated // except metal foams @@ -993,16 +999,26 @@ steam.start() -- spawns the effect if (istype(AM, /mob/living/carbon)) var/mob/living/carbon/M = AM - M.slip("foam", 5, 2) + if(M.slip("foam", 5, 2)) + if(reagents) + for(var/reagent_id in reagents.reagent_list) + var/amount = M.reagents.get_reagent_amount(reagent_id) + if(amount < 25) + M.reagents.add_reagent(reagent_id, min(round(amount / 2), 15)) + if(reagents.total_volume) + var/fraction = 5 / reagents.total_volume + reagents.reaction(M, TOUCH, fraction) /datum/effect/system/foam_spread var/amount = 5 // the size of the foam spread. var/list/carried_reagents // the IDs of reagents present when the foam was mixed var/metal = 0 // 0=foam, 1=metalfoam, 2=ironfoam + var/temperature = T0C + var/list/banned_reagents = list("smoke_powder", "fluorosurfactant", "stimulants") /datum/effect/system/foam_spread/set_up(amt=5, loca, var/datum/reagents/carry = null, var/metalfoam = 0) - amount = round(sqrt(amt / 3), 1) + amount = min(round(amt/5, 1), 7) if(istype(loca, /turf/)) location = loca else @@ -1010,35 +1026,40 @@ steam.start() -- spawns the effect carried_reagents = list() metal = metalfoam - + temperature = carry.chem_temp // bit of a hack here. Foam carries along any reagent also present in the glass it is mixed // with (defaults to water if none is present). Rather than actually transfer the reagents, // this makes a list of the reagent ids and spawns 1 unit of that reagent when the foam disolves. - if(carry && !metal) for(var/datum/reagent/R in carry.reagent_list) - carried_reagents += R.id + carried_reagents[R.id] = R.volume /datum/effect/system/foam_spread/start() spawn(0) var/obj/effect/effect/foam/F = locate() in location if(F) F.amount += amount + F.amount = min(F.amount, 27) return - F = new(src.location, metal) + F = new /obj/effect/effect/foam(location, metal) F.amount = amount if(!metal) // don't carry other chemicals if a metal foam - F.create_reagents(10) + F.create_reagents(15) if(carried_reagents) for(var/id in carried_reagents) - F.reagents.add_reagent(id,1) + if(banned_reagents.Find("[id]")) + continue + var/datum/reagent/reagent_volume = carried_reagents[id] + F.reagents.add_reagent(id, min(reagent_volume, 3), null, temperature) + F.color = mix_color_from_reagents(F.reagents.reagent_list) else - F.reagents.add_reagent("water", 1) + F.reagents.add_reagent("cleaner", 1) + F.color = mix_color_from_reagents(F.reagents.reagent_list) // wall formed by metal foams // dense and opaque, but easy to break diff --git a/code/game/objects/items/weapons/grenades/chem_grenade.dm b/code/game/objects/items/weapons/grenades/chem_grenade.dm index 149cc03a866..a951f1ade8f 100644 --- a/code/game/objects/items/weapons/grenades/chem_grenade.dm +++ b/code/game/objects/items/weapons/grenades/chem_grenade.dm @@ -458,11 +458,11 @@ New() ..() var/obj/item/weapon/reagent_containers/glass/beaker/B1 = new(src) - var/obj/item/weapon/reagent_containers/glass/beaker/large/B2 = new(src) + var/obj/item/weapon/reagent_containers/glass/beaker/B2 = new(src) B1.reagents.add_reagent("fluorosurfactant", 40) - B2.reagents.add_reagent("water", 40) - B2.reagents.add_reagent("cleaner", 60) + B2.reagents.add_reagent("cleaner", 10) + B2.reagents.add_reagent("water", 40) //when you make pre-designed foam reactions that carry the reagents, always add water last beakers += B1 beakers += B2 diff --git a/code/modules/mob/living/simple_animal/bot/medbot.dm b/code/modules/mob/living/simple_animal/bot/medbot.dm index 3534bbf55b2..80bcbc679f0 100644 --- a/code/modules/mob/living/simple_animal/bot/medbot.dm +++ b/code/modules/mob/living/simple_animal/bot/medbot.dm @@ -492,7 +492,7 @@ if(reagent_id == "internal_beaker") if(use_beaker && reagent_glass && reagent_glass.reagents.total_volume) var/fraction = min(injection_amount/reagent_glass.reagents.total_volume, 1) - reagent_glass.reagents.reaction(patient, 2, fraction) + reagent_glass.reagents.reaction(patient, INGEST, fraction) reagent_glass.reagents.trans_to(patient, injection_amount) //Inject from beaker instead. else patient.reagents.add_reagent(reagent_id,injection_amount) diff --git a/code/modules/reagents/Chemistry-Holder.dm b/code/modules/reagents/Chemistry-Holder.dm index 1b2e9a0b3d4..9be9ea9c124 100644 --- a/code/modules/reagents/Chemistry-Holder.dm +++ b/code/modules/reagents/Chemistry-Holder.dm @@ -387,45 +387,48 @@ var/const/INGEST = 2 can_process = 1 return can_process -/datum/reagents/proc/reaction(var/atom/A, var/method=TOUCH, var/volume_modifier=0) - +/datum/reagents/proc/reaction(atom/A, method=TOUCH, volume_modifier = 1) switch(method) if(TOUCH) for(var/datum/reagent/R in reagent_list) if(ismob(A)) - spawn(0) - if(!R) return - var/check = reaction_check(A, R) - if(!check) - continue - else - R.reaction_mob(A, TOUCH, R.volume+volume_modifier) + if(!R) + return + var/check = reaction_check(A, R) + if(!check) + continue + else + R.reaction_mob(A, TOUCH, R.volume*volume_modifier) if(isturf(A)) - spawn(0) - if(!R) return - else R.reaction_turf(A, R.volume+volume_modifier) + if(!R) + return + else + R.reaction_turf(A, R.volume*volume_modifier) if(isobj(A)) - spawn(0) - if(!R) return - else R.reaction_obj(A, R.volume+volume_modifier) + if(!R) + return + else + R.reaction_obj(A, R.volume*volume_modifier) if(INGEST) for(var/datum/reagent/R in reagent_list) if(ismob(A) && R) - spawn(0) - if(!R) return - var/check = reaction_check(A, R) - if(!check) - continue - else - R.reaction_mob(A, INGEST, R.volume+volume_modifier) + if(!R) + return + var/check = reaction_check(A, R) + if(!check) + continue + else + R.reaction_mob(A, INGEST, R.volume*volume_modifier) if(isturf(A) && R) - spawn(0) - if(!R) return - else R.reaction_turf(A, R.volume+volume_modifier) + if(!R) + return + else + R.reaction_turf(A, R.volume*volume_modifier) if(isobj(A) && R) - spawn(0) - if(!R) return - else R.reaction_obj(A, R.volume+volume_modifier) + if(!R) + return + else + R.reaction_obj(A, R.volume*volume_modifier) return /datum/reagents/proc/add_reagent_list(list/list_reagents, list/data=null) // Like add_reagent but you can enter a list. Format it like this: list("toxin" = 10, "beer" = 15) diff --git a/code/modules/reagents/newchem/pyro.dm b/code/modules/reagents/newchem/pyro.dm index b4070440ab3..655b8e996eb 100644 --- a/code/modules/reagents/newchem/pyro.dm +++ b/code/modules/reagents/newchem/pyro.dm @@ -293,7 +293,7 @@ datum/reagent/blackpowder/reaction_turf(var/turf/T, var/volume) //oh shit required_reagents = list("potassium" = 1, "sugar" = 1, "phosphorus" = 1) result_amount = 1 mix_message = "The mixture quickly turns into a pall of smoke!" - var/forbidden_reagents = list("sugar", "phosphorus", "potassium") //Do not transfer this stuff through smoke. + var/forbidden_reagents = list("sugar", "phosphorus", "potassium", "stimulants") //Do not transfer this stuff through smoke. /datum/chemical_reaction/smoke/on_reaction(var/datum/reagents/holder, var/created_volume) for(var/f_reagent in forbidden_reagents) @@ -325,7 +325,7 @@ datum/reagent/blackpowder/reaction_turf(var/turf/T, var/volume) //oh shit min_temp = 374 secondary = 1 result_amount = 1 - forbidden_reagents = list() + forbidden_reagents = list("stimulants") mix_sound = null /datum/reagent/sonic_powder diff --git a/code/modules/surgery/organs/blood.dm b/code/modules/surgery/organs/blood.dm index f2dd4c3c778..c1a1c7562a9 100644 --- a/code/modules/surgery/organs/blood.dm +++ b/code/modules/surgery/organs/blood.dm @@ -190,7 +190,9 @@ var/const/BLOOD_VOLUME_SURVIVE = 122 if(src.species.exotic_blood) vessel.remove_reagent(species.exotic_blood,amm) - vessel.reaction(T, TOUCH, amm) + if(vessel.total_volume) + var/fraction = amm / vessel.total_volume + vessel.reaction(T, TOUCH, fraction) return else From a4adb28b3e07018783bfac43c0e9e5719f407556 Mon Sep 17 00:00:00 2001 From: Isaac Erwin Date: Fri, 13 May 2016 14:31:59 -0400 Subject: [PATCH 032/343] Removes a random pipe and cable from engineering There's a disposal pipe and cable in engineering under and next to the door to the hardsuit storage. Neither connect to anything or seem to serve any purpose. --- _maps/map_files/cyberiad/cyberiad.dmm | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/_maps/map_files/cyberiad/cyberiad.dmm b/_maps/map_files/cyberiad/cyberiad.dmm index 47df198e5b8..3ee7365eaf2 100644 --- a/_maps/map_files/cyberiad/cyberiad.dmm +++ b/_maps/map_files/cyberiad/cyberiad.dmm @@ -7232,7 +7232,7 @@ "cJd" = (/obj/machinery/computer/station_alert,/turf/simulated/floor/plasteel,/area/engine/engineering) "cJe" = (/obj/structure/cable{d1 = 1; d2 = 2; icon_state = "1-2"; tag = ""},/turf/simulated/floor/plasteel,/area/engine/engineering) "cJf" = (/obj/effect/spawner/window/reinforced,/obj/machinery/atmospherics/pipe/simple/hidden/supply,/turf/simulated/floor/plating,/area/engine/hardsuitstorage) -"cJg" = (/obj/effect/spawner/window/reinforced,/obj/structure/disposalpipe/segment{dir = 4},/turf/simulated/floor/plating,/area/engine/hardsuitstorage) +"cJg" = (/obj/machinery/door/firedoor,/obj/machinery/door/airlock/glass_engineering{name = "Storage"; req_access_txt = "11"; req_one_access_txt = null},/turf/simulated/floor/plasteel,/area/engine/hardsuitstorage) "cJh" = (/obj/structure/sink{icon_state = "sink"; dir = 8; pixel_x = -12; pixel_y = 2},/obj/machinery/alarm{dir = 4; icon_state = "alarm0"; pixel_x = -22; pixel_y = 0},/turf/simulated/floor/plasteel{tag = "icon-whitegreen (WEST)"; icon_state = "whitegreen"; dir = 8},/area/medical/virology) "cJi" = (/obj/machinery/camera{c_tag = "Engineering Chief Engineer's Office"; dir = 4; network = list("SS13")},/obj/item/device/radio/intercom{name = "station intercom (General)"; pixel_x = -28; pixel_y = 0},/obj/machinery/disposal,/obj/structure/disposalpipe/trunk,/obj/machinery/firealarm{dir = 1; pixel_y = -24},/turf/simulated/floor/plasteel{dir = 8; icon_state = "neutralfull"},/area/engine/chiefs_office) "cJj" = (/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers,/turf/simulated/floor/plasteel{dir = 8; icon_state = "neutralfull"},/area/engine/chiefs_office) @@ -7337,7 +7337,6 @@ "cLe" = (/obj/machinery/door/airlock/maintenance{req_access_txt = "12"},/turf/simulated/floor/plating,/area/maintenance/asmaint2) "cLf" = (/obj/structure/closet/crate,/obj/item/clothing/under/color/lightpurple,/obj/item/weapon/spacecash/c200,/turf/simulated/floor/plating,/area/maintenance/asmaint2) "cLg" = (/obj/effect/spawner/window,/turf/simulated/floor/plating,/area/maintenance/asmaint) -"cLh" = (/obj/machinery/door/firedoor,/obj/structure/cable{d1 = 4; d2 = 8; icon_state = "4-8"; pixel_x = 0; tag = ""},/obj/machinery/door/airlock/glass_engineering{name = "Storage"; req_access_txt = "11"; req_one_access_txt = null},/turf/simulated/floor/plasteel,/area/engine/hardsuitstorage) "cLi" = (/obj/effect/spawner/window/reinforced,/obj/structure/disposalpipe/segment{dir = 4},/obj/structure/disposalpipe/segment,/obj/structure/cable,/obj/machinery/door/poddoor{density = 0; icon_state = "pdoor0"; id_tag = "xenobio4"; name = "Containment Blast Doors"; opacity = 0},/turf/simulated/floor/plating,/area/toxins/xenobiology) "cLj" = (/obj/machinery/door/window/southright{name = "Containment Pen"; req_access_txt = "55"},/obj/machinery/door/poddoor{density = 0; icon_state = "pdoor0"; id_tag = "xenobio4"; name = "Containment Blast Doors"; opacity = 0},/turf/simulated/floor/engine,/area/toxins/xenobiology) "cLk" = (/obj/effect/spawner/window/reinforced,/obj/structure/disposalpipe/segment{dir = 4},/obj/machinery/door/poddoor{density = 0; icon_state = "pdoor0"; id_tag = "xenobio4"; name = "Containment Blast Doors"; opacity = 0},/obj/structure/cable,/turf/simulated/floor/plating,/area/toxins/xenobiology) @@ -8921,7 +8920,7 @@ bikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbi bikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikafxaabcFscFtcFtcFucFvcFwcFwcFwcFvcFwcFwcFwcFvcFwcFwcFxcFtcFtcFtcFtcFtcFycFzcFAcFBcFCcFDcFEcFFcFGcfRcwWcFHcDfcvKcvKcvKcFIcEBcECcFJcFKcFLcyrcFNcDucFPcFOcFQcFScFTcSpcFVcFWcFXcFScFYcFZcDwcGacDzcDzcDzcGbcBCcGccGccDFcGdcGecGfcGgcGhcGicGjcGkcGlcGmcGncDOcGocDQcGpcDTcDTcCKcHBcoDcEhclUcyMcyLcyNcFfclUcnkclTcFfclUcyQcyScyRcyTcyTclUcusbGycJOcoAbikckPcxOcxPcxOcGAcxRcqUcGBcJPcJJcqUdlWcGDcwAcwAcwAckPbikbikaabaabbikbikbikbikbikbwocyKcvzbwobikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbik bikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikacGbikaabbikaabaabcGFaabbikaabcGFaabbikaabcGFaabbikbikbikbikbikbikbikbikcDccDccDccGGcGHcFMcDdcGJcfRcGKcExcExcExcExcGLcExcFGcECcGMcGNcGOcGPcGQcGRcGScGTcGUcGVcGWcGXcGYcGZcHacHbcFYcELcDwcHccHdcDzcDzcHecBCcHfcHgcDFcHhcCAcHicHjcHkcHlcHmcHncHocHpcHocHqaabcCKcCKcCKcCKcCKcHBcoAcEhclUcIJcyVcyYcyXcEecEccEgcEfcHwcGucHZczVcIRcIQclUcusbGycJRcoAbikckPcxOcxOcxOcFjcHEcHFcHGcJScHIcCZcCZcCZcHJcHKcHLcHMbikbikbikaabaabbikbikbikbikbwobwocvzbwobikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbik bikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikacGacGafxaabaabczocHOczqbikczocHOczqbikczocHOczqaabbikbikbikbikbikbikbikaabaabcDccDdcDdcDdcDdcHPcHQcHRcfRcHScfRcfRcEBcHTcfRcECcHUcHVcGOcHWcFNcHXcHYcIacIacIbcIccIdcIedmabRFcIbcIhcIicIjcIkcIlcImcIncIocIpcIqcGfcIrcIscItcIucIvcIwcIxcIycIzcIAcIBcICcIDcDPcDQcIEcIFcIFcCKcHBcoAcEhclUclUclUclUclUcJhcANcBRcJQcMccBScMecMdcMCcBVclUcuscGqcGrcGrcGrcJTcJTcJTcJTcJTcJUcKTcKbcKUcIUczbcIVczbcIWczbcIXcHMbikbikbikbikaabaabbikbikbikbikbwocvzbwoaabaabaabaabaabaabbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbik -bikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikczocHOczqaabczocHOczqbikczocHOczqbikbikbikaabbikbikbikbikaabaabaabbikbikaabaabcJbcJbcJbcJbcJbcJbcJbcJccJbcJbcECcJdcJecGOcHWcFNcJfcFNcJgcLhcDtcJicJjcFWcJkcFRcDtcJmcDzcDwcJncJocJpcIncJqcJrcJscJtcJucJvcJwcJtcJxcJycJzcJAcDFcJBcJCcJDcJEaabcEVcJFcJGcJHcCKcHBcoDcKWcKVcKVcKVcKXclUcFacyLcCLcFecyScCMcyTcyTcyScCNclUcuscGvbVibGycKYcKZcoAbikbikckPcJVcJWcJXcJYcJVcJWcJZcKacJVcJWcLackPaabaabaabaabaabaabaabaabaabaabbwocvzbwobwobwobikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikdjcbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbik +bikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikczocHOczqaabczocHOczqbikczocHOczqbikbikbikaabbikbikbikbikaabaabaabbikbikaabaabcJbcJbcJbcJbcJbcJbcJbcJccJbcJbcECcJdcJecGOcHWcFNcJfcFNcFNcJgcDtcJicJjcFWcJkcFRcDtcJmcDzcDwcJncJocJpcIncJqcJrcJscJtcJucJvcJwcJtcJxcJycJzcJAcDFcJBcJCcJDcJEaabcEVcJFcJGcJHcCKcHBcoDcKWcKVcKVcKVcKXclUcFacyLcCLcFecyScCMcyTcyTcyScCNclUcuscGvbVibGycKYcKZcoAbikbikckPcJVcJWcJXcJYcJVcJWcJZcKacJVcJWcLackPaabaabaabaabaabaabaabaabaabaabbwocvzbwobwobwobikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikdjcbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbik bikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikafxaabczocHOczqbikczocHOczqbikczocHOczqaabbikbikbikbikbikbikbikaabaabbikbikaabaabaabcJbcKjcKjcKkcGIcKmcKmcKncKocKocKpcKqcKrcGOcHWcGOcKscGOcGOcGOcDtcKtcKucKvcKwcKxcKycKzcKAcKBcKCcKCcKCcKDcKEcKFcKGcKHcKIcHhcCAcKJcKKcKLcKMcKNcDFcJBcKOcKPcKQcKRcDQcKScIFcIFcCKcHBcoDcEhbVibVibVibYDclUcFgcCOcDXcNDcyScPocPMcyTcPVcPQclUcuscGvbVibGycyHbGycoAbikbikckPcLicLjcLkcwAcLlcLmcLncwAcLocLpcLqckPaabaabbikbikbikbikbikbikbikbikbwocvzbxXbxXbwoaabaabbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbik bikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikafxaabczocHOczqbikczocHOczqaabczocHOczqaabaabaabbikaabbikbikaabaabbikbikbikaabbikbikcJbcKjcKjcKkcLscLscLscLtcLucLvcECcLwcLxcLycLzcLAcLBcLCcLDcLDcLEcLFcLGcGOcGOcGOcLHcLIcLJcLKcLLcLMcLNcLOcLPcECcLQcLQcLRcHhcCAcLScLTcLUcLVcLWcDFcLXcLYcLZcMacMbcCKcCKcCKcCKcCKcHBcoDcEhcLbbGybGybYDclUcNEczVczVcOtcDZcQMcRwcyTdbkcYuclUcuscGvczhbGychCcITcoAbikbikckPcMpcxOcxOcwAcMpcxOcxOcwAcMpcxOcxOckPbikaabaabbikbikbikbikbikbikbikbwocLccyJbxXbwobwobwocJNcJNaabaabaabaabbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbik bikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikagiaabczocMqczqbikczocMqczqbikczocMqczqaabafxaabaabaabaabaabaabbikbikbikbikbikbikaabcJbcMrcMscLscLscLscMtcMucMucMucMucMucMucMucMvcMwcMxcMycMzcMzcMzcMAcMBdcpdcodcvcMzcMBcMDcMEcMFcLMcMGcLOcLPcMHcMIcMJcMKcMLcMMcMNcMOcKNcMPcMQcMRcMScMTcMUcIDcMVcDQcMWcMXcMXcCKcHBcoAcEhbVicozcLdbYDclUcOBczVcQgcPYcySdcydczcyTdcBdcAclUcuscGvbVibGybVibVicoAaabaabckPcNncBZcxOcwAcNncBZcxOcwAcNncBZcxOckPbikbikaabaabbikbikbikbikbikbikbwocvzcyJcLecyJcLfbwoaabaabaabbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbikbik From d555e9d6a34003f272c73fe9d48393e00ebdc931 Mon Sep 17 00:00:00 2001 From: ParadiseSS13-Bot Date: Fri, 13 May 2016 15:10:05 -0400 Subject: [PATCH 033/343] Automatic changelog generation for PR #4415 --- html/changelogs/AutoChangeLog-pr-4415.yml | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 html/changelogs/AutoChangeLog-pr-4415.yml diff --git a/html/changelogs/AutoChangeLog-pr-4415.yml b/html/changelogs/AutoChangeLog-pr-4415.yml new file mode 100644 index 00000000000..25ae9a07845 --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-4415.yml @@ -0,0 +1,4 @@ +author: Fox McCloud +delete-after: True +changes: + - rscadd: "Adds in the ability to flip over someone with *flip" From e8e531eb3a49a66e52e6b5e562e9ee9a7602f02c Mon Sep 17 00:00:00 2001 From: ParadiseSS13-Bot Date: Fri, 13 May 2016 15:29:00 -0400 Subject: [PATCH 034/343] Automatic changelog generation for PR #4401 --- html/changelogs/AutoChangeLog-pr-4401.yml | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 html/changelogs/AutoChangeLog-pr-4401.yml diff --git a/html/changelogs/AutoChangeLog-pr-4401.yml b/html/changelogs/AutoChangeLog-pr-4401.yml new file mode 100644 index 00000000000..8f9a142b383 --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-4401.yml @@ -0,0 +1,4 @@ +author: Fox McCloud +delete-after: True +changes: + - tweak: "Players can no longer see how many players have readied up or who has readied up" From 47e00dee34a2ee2563c4e83a84f0b9a05ee8f2fa Mon Sep 17 00:00:00 2001 From: ParadiseSS13-Bot Date: Fri, 13 May 2016 15:34:17 -0400 Subject: [PATCH 035/343] Automatic changelog generation for PR #4231 --- html/changelogs/AutoChangeLog-pr-4231.yml | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 html/changelogs/AutoChangeLog-pr-4231.yml diff --git a/html/changelogs/AutoChangeLog-pr-4231.yml b/html/changelogs/AutoChangeLog-pr-4231.yml new file mode 100644 index 00000000000..047c22c3b30 --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-4231.yml @@ -0,0 +1,4 @@ +author: monster860 +delete-after: True +changes: + - bugfix: "Fixes sleep() in telecomms" From d445506b1d5b104064774d63465929c7ae57cbb0 Mon Sep 17 00:00:00 2001 From: ParadiseSS13-Bot Date: Fri, 13 May 2016 15:36:36 -0400 Subject: [PATCH 036/343] Automatic changelog generation for PR #4331 --- html/changelogs/AutoChangeLog-pr-4331.yml | 14 ++++++++++++++ 1 file changed, 14 insertions(+) create mode 100644 html/changelogs/AutoChangeLog-pr-4331.yml diff --git a/html/changelogs/AutoChangeLog-pr-4331.yml b/html/changelogs/AutoChangeLog-pr-4331.yml new file mode 100644 index 00000000000..f6ca1298944 --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-4331.yml @@ -0,0 +1,14 @@ +author: KasparoVy +delete-after: True +changes: + - tweak: "Refactors hair so it's on the head (organ)." + - tweak: "Adjusts some Vox hair style names so they're consistent with all others." + - tweak: "Refactors Morph and the order by which options are presented." + - tweak: "Players with heads of a different species than the body will now only be able to access the head accessories, hair/facial hair styles of the head's species." + - bugfix: "Fixes some typos." + - bugfix: "Fixes a bug where hairgrownium made you bald and super hairgrownium only changed the hair/facial hair styles of Humans." + - bugfix: "Fixes a bug where Morph wouldn't correctly set eye colour or skin tone." + - bugfix: "Fixes a typo that didn't really have any negative effect on the beard organ to begin with." + - bugfix: "Fixes bugs where Alopecia and Facial Hypertrichosis disease symptoms wouldn't update player sprite correctly." + - rscadd: "Adds a new Vox hairstyle." + - rscadd: "You can now change your head accessory (and its colour), body markings (and their colour), and body accessory if you're a species that has such things via the Morph genetic power and C.M.A. (the bathroom SalonPro Nano-Mirrors and admin verbs)." From 69c51878a58ef00f2285705fcfe47907517cee27 Mon Sep 17 00:00:00 2001 From: AugRob Date: Fri, 13 May 2016 17:11:17 -0500 Subject: [PATCH 037/343] Add screwdriver sound when opening airlock panels --- code/game/machinery/doors/airlock.dm | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/code/game/machinery/doors/airlock.dm b/code/game/machinery/doors/airlock.dm index 26d159e959a..c131c55ee49 100644 --- a/code/game/machinery/doors/airlock.dm +++ b/code/game/machinery/doors/airlock.dm @@ -799,6 +799,7 @@ About the new airlock wires panel: else return else if(istype(C, /obj/item/weapon/screwdriver)) + playsound(src.loc, 'sound/items/Screwdriver.ogg', 25, 1) src.p_open = !( src.p_open ) src.update_icon() else if(istype(C, /obj/item/weapon/wirecutters)) @@ -1066,4 +1067,4 @@ About the new airlock wires panel: src.unlock() src.open() src.lock() - return \ No newline at end of file + return From bbe031044f217f426b936acec5250e78f08cda0e Mon Sep 17 00:00:00 2001 From: monster860 Date: Sat, 14 May 2016 14:50:53 -0400 Subject: [PATCH 038/343] Adds the floor painter --- .../objects/items/devices/floor_painter.dm | 77 +++++++++++++++++++ .../research/designs/autolathe_designs.dm | 8 ++ paradise.dme | 1 + 3 files changed, 86 insertions(+) create mode 100644 code/game/objects/items/devices/floor_painter.dm diff --git a/code/game/objects/items/devices/floor_painter.dm b/code/game/objects/items/devices/floor_painter.dm new file mode 100644 index 00000000000..a43218bca39 --- /dev/null +++ b/code/game/objects/items/devices/floor_painter.dm @@ -0,0 +1,77 @@ +// Floor painter + +/obj/item/device/floor_painter + name = "floor painter" + icon = 'icons/obj/bureaucracy.dmi' + icon_state = "labeler1" + item_state = "flight" + + var/floor_icon + var/floor_state = "floor" + var/floor_dir = SOUTH + + var/list/allowed_states = list("arrival", "arrivalcorner", "bar", "barber", "blackcorner", "blue", "bluecorner", + "bluefull", "bluered", "blueyellow", "blueyellowfull", "bot", "brown", "browncorner", "browncornerold", "brownold", + "cafeteria", "caution", "cautioncorner", "chapel", "cmo", "dark", "delivery", "escape", "escapecorner", "floor", + "freezerfloor", "gcircuit", "green", "greenblue", "greenbluefull", "greencorner", "greenfull", "greenyellow", + "greenyellowfull", "grimy", "loadingarea", "neutral", "neutralcorner", "neutralfull", "orange", "orangecorner", + "orangefull", "plaque", "purple", "purplecorner", "purplefull", "rampbottom", "ramptop", "red", "redblue", "redbluefull", + "redcorner", "redfull", "redgreen", "redgreenfull", "redyellow", "redyellowfull", "warning", "warningcorner", "warnwhite", + "warnwhitecorner", "white", "whiteblue", "whitebluecorner", "whitebluefull", "whitebot", "whitecorner", "whitedelivery", + "whitegreen", "whitegreencorner", "whitegreenfull", "whitehall", "whitepurple", "whitepurplecorner", "whitepurplefull", + "whitered", "whiteredcorner", "whiteredfull", "whiteyellow", "whiteyellowcorner", "whiteyellowfull", "yellow", + "yellowcorner", "yellowcornersiding", "yellowsiding") + +/obj/item/device/floor_painter/afterattack(var/atom/A, var/mob/user, proximity, params) + if(!proximity) + return + + var/turf/simulated/floor/plasteel/F = A + if(!istype(F)) + user << "\The [src] can only be used on station flooring." + return + + F.icon_state = floor_state + F.icon_regular_floor = floor_state + F.dir = floor_dir + +/obj/item/device/floor_painter/attack_self(var/mob/user) + if(!user) + return 0 + user.set_machine(src) + interact(user) + return 1 + +/obj/item/device/floor_painter/interact(mob/user as mob) + if(!floor_icon) + floor_icon = icon('icons/turf/floors.dmi', floor_state, floor_dir) + user << browse_rsc(floor_icon, "floor.png") + var/dat = {" +
+ Choose Style +
Style: [floor_state]
+ Choose Direction +
Direction: [dir2text(floor_dir)]
+ "} + + var/datum/browser/popup = new(user, "floor_painter", name, 200, 300) + popup.set_content(dat) + popup.open() + +/obj/item/device/floor_painter/Topic(href, href_list) + if(..()) + return + + if(href_list["choose_state"]) + var/state = input("Please select a style", "[src]") as null|anything in allowed_states + if(state) + floor_state = state + floor_dir = SOUTH // Reset dir, because some icon_states might not have that dir. + if(href_list["choose_dir"]) + var/seldir = input("Please select a direction", "[src]") as null|anything in list("north", "south", "east", "west", "northeast", "northwest", "southeast", "southwest") + if(seldir) + floor_dir = text2dir(seldir) + + floor_icon = icon('icons/turf/floors.dmi', floor_state, floor_dir) + if(usr) + attack_self(usr) diff --git a/code/modules/research/designs/autolathe_designs.dm b/code/modules/research/designs/autolathe_designs.dm index b5d44579d07..8337e0ffaf7 100644 --- a/code/modules/research/designs/autolathe_designs.dm +++ b/code/modules/research/designs/autolathe_designs.dm @@ -688,6 +688,14 @@ build_path = /obj/item/weapon/hand_labeler category = list("initial", "Electronics") +/datum/design/floorpainter + name = "Floor painter" + id = "floor_painter" + build_type = AUTOLATHE + materials = list(MAT_METAL = 150, MAT_GLASS = 125) + build_path = /obj/item/device/floor_painter + category = list("initial", "Electronics") + /datum/design/logic_board name = "Logic Circuit" id = "logic_board" diff --git a/paradise.dme b/paradise.dme index 0adb0c5b5b4..cef243d4259 100644 --- a/paradise.dme +++ b/paradise.dme @@ -723,6 +723,7 @@ #include "code\game\objects\items\devices\debugger.dm" #include "code\game\objects\items\devices\flash.dm" #include "code\game\objects\items\devices\flashlight.dm" +#include "code\game\objects\items\devices\floor_painter.dm" #include "code\game\objects\items\devices\guitar.dm" #include "code\game\objects\items\devices\laserpointer.dm" #include "code\game\objects\items\devices\lightreplacer.dm" From 650eebdd14656fdf8f2050898b1b05bcd51d37af Mon Sep 17 00:00:00 2001 From: monster860 Date: Sat, 14 May 2016 14:58:19 -0400 Subject: [PATCH 039/343] Dang it --- code/game/objects/items/devices/floor_painter.dm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/game/objects/items/devices/floor_painter.dm b/code/game/objects/items/devices/floor_painter.dm index a43218bca39..64a6ff79e16 100644 --- a/code/game/objects/items/devices/floor_painter.dm +++ b/code/game/objects/items/devices/floor_painter.dm @@ -28,7 +28,7 @@ var/turf/simulated/floor/plasteel/F = A if(!istype(F)) - user << "\The [src] can only be used on station flooring." + to_chat(user, "\The [src] can only be used on station flooring.") return F.icon_state = floor_state From 3f79345b8b58fe5a8ff462d737ec6b9d874737d0 Mon Sep 17 00:00:00 2001 From: monster860 Date: Sat, 14 May 2016 15:45:31 -0400 Subject: [PATCH 040/343] Adds left and right arrows --- .../objects/items/devices/floor_painter.dm | 24 ++++++++++++++++--- 1 file changed, 21 insertions(+), 3 deletions(-) diff --git a/code/game/objects/items/devices/floor_painter.dm b/code/game/objects/items/devices/floor_painter.dm index 64a6ff79e16..10961837f63 100644 --- a/code/game/objects/items/devices/floor_painter.dm +++ b/code/game/objects/items/devices/floor_painter.dm @@ -10,7 +10,7 @@ var/floor_state = "floor" var/floor_dir = SOUTH - var/list/allowed_states = list("arrival", "arrivalcorner", "bar", "barber", "blackcorner", "blue", "bluecorner", + var/static/list/allowed_states = list("arrival", "arrivalcorner", "bar", "barber", "blackcorner", "blue", "bluecorner", "bluefull", "bluered", "blueyellow", "blueyellowfull", "bot", "brown", "browncorner", "browncornerold", "brownold", "cafeteria", "caution", "cautioncorner", "chapel", "cmo", "dark", "delivery", "escape", "escapecorner", "floor", "freezerfloor", "gcircuit", "green", "greenblue", "greenbluefull", "greencorner", "greenfull", "greenyellow", @@ -47,14 +47,18 @@ floor_icon = icon('icons/turf/floors.dmi', floor_state, floor_dir) user << browse_rsc(floor_icon, "floor.png") var/dat = {" -
+
+ <- + + -> +
Choose Style
Style: [floor_state]
Choose Direction
Direction: [dir2text(floor_dir)]
"} - var/datum/browser/popup = new(user, "floor_painter", name, 200, 300) + var/datum/browser/popup = new(user, "floor_painter", name, 225, 300) popup.set_content(dat) popup.open() @@ -71,6 +75,20 @@ var/seldir = input("Please select a direction", "[src]") as null|anything in list("north", "south", "east", "west", "northeast", "northwest", "southeast", "southwest") if(seldir) floor_dir = text2dir(seldir) + if(href_list["cycleleft"]) + var/index = allowed_states.Find(floor_state) + index-- + if(index < 1) + index = allowed_states.len + floor_state = allowed_states[index] + floor_dir = SOUTH + if(href_list["cycleright"]) + var/index = allowed_states.Find(floor_state) + index++ + if(index > allowed_states.len) + index = 1 + floor_state = allowed_states[index] + floor_dir = SOUTH floor_icon = icon('icons/turf/floors.dmi', floor_state, floor_dir) if(usr) From 9abc2b282258b85154becbb6ac4b28fd2d20a90b Mon Sep 17 00:00:00 2001 From: monster860 Date: Sat, 14 May 2016 16:52:04 -0400 Subject: [PATCH 041/343] custom icon --- icons/obj/device.dmi | Bin 34130 -> 34361 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/icons/obj/device.dmi b/icons/obj/device.dmi index 46a4a9743164a928d73eaf9cdb3a1ddf089e0773..338b56148ee502dec066f2a27358e3eac883024d 100644 GIT binary patch delta 12606 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 delta 12336 zcmY+qc|26#A3uJ_E_;NCQIdTtBFa!nQm7OmYax5~EORGo$yP+NCW*+JeHr`6nq*&Q z>^ozhVV2+Z{(OJG$M5@xhkMVx_sr{@^E$8dd_G^V>L{AOku-7VVZJ3|4zzs8dagiO zB;}Q)1rps$W#oLLsw=emTe~cuR^vXnD9oo_Po)n3V3HDYbu{NWE7qp&m;(zoUE$dI z9QN7cPFrV}R_QxQ@d4YQd+Gu@O*~gVCf>66d-c`dZoJR0P&|#F_HY}$k(>puHs|62 zW{tJ1%VIP+Z7>J{=MXMCO78Ns^BFxj+DYyUTo@b{$E{al+Z%Hwcut*~zNsGr{$`V- zU=VS>hf1ZTrH1Z%S^A7W^pfNhfxDFAcL(za~s&z=;qJq&r(@&fsD_g!7`Z#xp> zdA!?b=_#QMb}dgJs3_s{t|k9P0mpIy<3e*SbcbUd!k0%%Isow(N)$uKs zj~>wjRlhG+SX1qh{JZ*!6BAzQ-Ye*&X6h=`K+-SK$}mC#Z=$20-x>P_0|+@eHbYUT z1KCD|Rf7>k@BK;@t()j3UKBJan3dDj^>MGp$Wzkp%YVft@(Pr|6yWOKzlQ)y{o}_f z#N) zmlU!G9DN4a=oeR^Vval5yS~LG!Zw59J(2+CD@W^fV{R zn%#eIDl* z|F4S-Ea_x2*}KW|p#0}QCm83{23_L+9S3AFTbBrv`+z|5y)z%xulQKT_@~ z4u~j=(Ojp*oh+m zXnb@3tJl!{$>7LskL&^qw$Sj>hbXXT4~COa^KHtBLG^~`38(@_kCyeNWgYTP_EA%Z zj#8f?Gv%0Qi=FV^=fMIx812N zEW@{QgVSb!9P4S&#V74t(^DV=xjiTvMDhSB6;Tu7?YW?N=EBL>p`oGvU2EfLY?jM& z@$;EWsV=@SRncYv0?s#5k*V=su`)hsVPh!yL{eo0cwj&sNWL?@=a0YH{RMvtZWukb=^Fak!Jv@kqL7(a z>LBrWTRjmZZgT~)0PWEs`Qt(l^S}OBVJ6V#)>uZXOp*5ABai_{vRa7Zcivqh#;e0< zdQOys*0?4`^V65o(vt`ZLG)IP5=BHf1`d+$f8YhKkgxNHYiVi%{~VQlD(hoDH4iNq zpF`hg1=;CSg@k%|PL=jtxu1(w?0k@QPISxbXrHOXLuX2LBRA>{VV_&^a;eT zV(Xr$=r`JT>EO)M`=BY?-(R&|It@E)AqoV<#Z@n|aK`dVN=mBPZm!0*Z7we}155w% zxKD`j=iYKf01`ajmd^tiv6z0h-ItBEC&1N>8_4l+ovh2dFAL^;WvFl7uOTYY=y$r7 z_wTd$kUREy`4#_iOH)2dN20%6bzH>qA6_F=(>0o}XPiXoq}0`2&2bs808q`%*C%Ry z`<4a>pOu}$D_q929)8y+%qLmi3^-GqiVPx@;ORRq@=|SQijn{TI8aEy+h@2efj-_i z;qX$s9)Wj038a{H@P)ak^Y|gBe6(%E`;m&hvzEwN26uep4PElkb}sQ=)85izCXVXY zLT?3!!&6mX(qQtVRay`Ozxb~O?B9I!=u~g|HEBm0k)(_`-mkI%%0)Rb+%=XIn~0Ed z94Mt_ywD(?ggq1c87nXo&Tb8WlivXkS$Y(4irV^B%fdpK7Qp0_|K#5DRdO6HoVv)N zSA?4$eCU@WseZTUQU#WuIPeAgc0$ua1qe2 z_04DX;Wd}!g-kjW^omF-XIU)mh2x8)r6mWu4weuZ)1jWhQ&UqG1jm*O{q1$`KIjBP z7C?)W&iW*Xuv{ZQM|5^d-KCHT8PpHhn43M(70VX^F@R2sUuuzN_w{!9QPxX78U#=S)%LgraG|qkJkHMD{vbtEQSm(t zg%DhBu&nm@HYj%onllC6$B%jKWW5F?YhSUN#D56hd+~yQA||bp8CA5e`*LR%bI~Q( z^zBKeveHt{y6Q65=`3O$ddqOVE{=CDsnP9Cd$eH6(_5WRxZV|myLX@Y?=CepTuGw^ za8u$JE?hhY0h7*fQ_0q=8_oPh_Nk64Tb$ ztH}`4v(nNmK;z)eMNI5-4c+l6oM$`H>0oX(K}T7BhKxQ)X;nkKJBwzb{P-cY!=n49 z?C5ok=`~E}N9j{<-@d(TXvnFbe)TtFP)xkIK^8~_DS;=g9D;5LN8AI#zscJIxW&9p zNmLEoDu!BBg=_mPP)mIEeF}N|6lcfg1X5=v{?~fs6;BJB$3IQmlEQwu^%)GDI59;7 z1Xc-`+4r?CW`KpjNRE>nN_RP8h$=(W-g1(X?vWe#mFLP$n5;c0*pIX1BMSslDdd;C zOZ}jKQ;Hsq#paekL+c9-0?YIV6oeA#u^_enzD`I6gP--1q22XZ;SSS^ySwm4>*X%~ zjR;?p!;3k4ug&W?MEy*_sAk-R?~VwFYwT5k-^`NEzBxaMzCD&cRwWl-lkARB{!y?J)JMF-*X~WdlB|eL;;}zcJ z1`6p>H}Z^VQ2O{`%XB>;^e0U-UE>Nb&~Sk=7f;a9W#;6=ydj2&leXvqa07Gj5Xdk! zoaNx)&`D)Gde+^yPTRf4_&@8PWF&@Xb07*3wp%tDO!SP5w7}u+a*K-YyJcfGIQz$a zvRWbEFChryAQm&y(|$gbt3ar!eO~@Uk*vE!xM*RyN9PFN$E4cTmQ<+Vak+dvk+*US z_i1?!rYZaMRT#o-tTmzHSS|eUx~iE z@B>y7;oZEkl4I1Z?=bDzGLw(o!2&>ZZxt;1vla|4v60bS|H9?!{M7O zJF?ZET`zjnq)Gm@>k ztD)3Kk{B&`gTMA+;}1FBNmYovIf($Attni-e z;L@m_uL>kyY;I{G!mX)aqTP3#w&SV&yXsQom2Q~w85^U7B*9d-T=Q;$;kl()93P$N{~?8)}(J$Iat@b?N(rmpY%Nq-CWHvC_>AYkP=10E#FYQ z1LT-F83M=}fO(_568CpmeZa=nHu;i$F92M>aYNCmowb2p(;1n5n0{^poX)60VIzKv@4S4rOD#*GvI1a}Ms_u@)f9WE(+vP3fbLB#qxH3! z0}YUVryRq&jvN`t@F7O_zFOR$20I334u#&gL~zhr1*FM8sjHe&Udq)9asQI3`Q0<& zQxA5oXa`PM7N5%S*v(x+7A~hmSZ6lUrV`3d*7Mv0v}H4MX?UXh>E;cuRxw_N`7!M} z(n+jPyuB(0G!aQ|(dI@`AG9@jfSadQ3od!wXGTd>n6Hb!MW0n_b<0h319KmVNJuaR z9qkV;&tYWqGdP!g8Rm*5V7Oqge1HE9Gu*)#5}KiRk0c$O~+HPbp+{N)`r zOK`9_caPgSUT%^AG~P?`TDDW6hSUuZe(Bh!(amX1y{J8e{TpWtAnwH`k8=bN+0qUS z0=#b3rI9>Na&cMXl^KUYEm;FIU0}qlzjcY;0Qrh!Jg8km-+e>klK|=!ARz#=`c;zt z?jCE(835oR9lFqv1lJI$=DvDU5Z?Jy?P<^L1Q3Zt6Qu{f)V6JvXF+D9>!Cg5a9n5D zYczzAX37C0mW}9wik6@cf|s2QTkB1XSy(tYFz?+OE{@T4f%ktcp8c#h4<}P`TxX&T z06&00hf29dW|?XcUmeD~0`8S%2vt=Rd-&Qb%52E^Syfej^Ul5BhsqL_i(80E_6!F! zIHA!h?`Lol{k3KA_Ujt6zq?%0g!h&j=zw>;Kq&fv^$2tI-_v51U&D>7iJor#%~@tE zQPvU!$`KUj8GyUV7wKm)Wl69qV8;7Zi|=4PKINIzow$wcVnZv*5Na!kiai7l-7t!3{N zH`&{RW?0c_>a-!8JpMMK{lm#C*0(nArku@ zwBtaFr2%1GO09j9%vJ^TnjJKQ982Vo6WEAB`XJYpnFqc>`-gk0ssZ~2P5pqZD-8Dm z0DRE<@&~a}#NYDYvF~x8(?!pnyUPIA{45|rT%TS10FaS@ol|4*Fyu`W#Wgvi<)?O6 zhdF?NpBVu??=yPF$Q1OibQ%cHZ&x_cxs@S-GrfY;5ec zJ~mj`lp(@|nLhHJ_ZqKN`BQsf z^Mvg5lb`v|V>A+9R9JYq%G_tu8E4H;ZTQ=%!T30qu0w&9hK45daehhdx;NO$Q&Hi= zO{X=Y>1D(d{|bj{Hc$R^MkA1)i;K(e`6~gSrO7^SAEuRWT*M%<5rm(sL}xhBn-upj zvQ(5j_f-<`BhAY*B%!^JE~mTuE@F)zeSEupv(9>FRk&}J6{#mjySs^nZ;iPEMRnVe z{qvCA<$kd7bW4~a+wh-D1Q?9a>IexiN@ydWY;84S;{o=blf6fW0^TMc0e7J+4^Pk4k7i{;!6ME#THinJ@gQzLr+|CG>qoMt5l+a8 zJuTI_B&>X!=en%c!23P5e9H`8S<@xDSJr*tjV1)KgX?@~1g-C;z+}##EWoqIeBC13 zc}1mdx+OxnKTgY)gt_wN6B>7ZZ_ij zHlJ&2Q_R~ZCxrx}87vEruJ2Nrx1rE5bM#Y~5w{)3d>22}6X}Z}1wVnlq(7MY5j}z` zJ7R90YSm9|y~!>d>9le^zAFup5}Ucd?oKvM&P4>zi6e;Lw#)`;6s*80e+K_1IloQ2 zHq@)tGFh|R7}IYswr z*_~fh<{QYE_8xO6Fh*=uZYxlhEOd6vQUP<}i(f48v#M2IpXZdV?GLy^&6Rw8b!OY; zMryqC^@$OBNoT1ydBMV@1iY^1fx1BU!DjeVJ}K?Vh#c3RRbtrDOS#SS#NV5olzA(6 zGoxBBJs!Lft!(@B#4$QMs$l}ygPaO z0ytVMqVg)8Uu}pr?&+5NyG3p$zeyuO!4R@Uw9p_cCD&(}#484v8wMP-$bVw=?S%mz z?4<*(tv7Ria|@LOZl#=%49+M!vi~k@z0e!PsJ(LCYm@tTQWCFp|6h5gZ*6xP3cgu# zB4VHVUMd3}Z&lqp`sKfU*3NE?CRgvHUydiDp>D~anPhg91^u&Jz>XzlUewahxpkgW!YRfQn0&7FiAKSk#cjeapqJKw8tC z9Y7>#_SprGQWs27->~2?uJ<0BT@R8E7~figu&j;L-R)I3wAEquZ`H&d#)}s(63Fhn z)aX^I)K2w?<@gJtFQ?3(kN|h7%`?4o>BY6^Ae4N}JP8Ku65rv8W`WEo79_Mk_7=dO z=G70rUzVYdndu{JTml-ugdjvb8uDjKHHNZ4IWeajblS{0Cmy)(>It;#4<7 zC&{Y~qfF2^Hu56p1aV)gZ>iqF6te6$Zkhu->Exb{?ujEhp zmaV4)o|m_MI{4AJSWOIka#n`6QJlrY(ClG|R*OYz)F?Asjk7hg9b=;`tKWfr=Q%`rt(MZ>PgVR z#_YBEFO0m*EVN{i8+_^1ji+h?*Qn2*&l~EwQ}q4~_m|tB*D%?=3}n7w89IK?;uMu2 z+tkv<64qJv!G&tq=0d6i;WT9Ovn~5)&#dl^IsTif6?=z(+!4A6OOJ;CqNrc)o%q4o9$4tcJo6 zi>wYm^+y$V3kUw%rs5aBT%D+S5Tg6_`=#cK0r*%k>G!^KoQ`yuzK^3JVk~?xl=C8$ z%3G+p@%Bb;VO{WYQ3kM1jmv-yL<=@#JoHuzY%_*7&@Sg}UX^DRt! zd)CWK9CfDil=;ug27VC@6Edi)A#%;kyBN zXXe0don_7-Bp^@TCg?g>SNX4b+RB~RCK(^`ZtL&N%g_50h~>?{Scv$63C+qOjmF#S z?B*Sea&xxNo!}LsnWmqG9G3Y)Pd~hn2}L#kuyRb4B)8WB$hFTEKrztuqy*8L+B%{G z2@DD6cJIM~U=Dz2Ld@Y9=fY>-go7w%M<+)Bh<)J9R^fmT`pJM9hOUbJs>{4 zzAjsX?Hc3=@El2uabetMlN%_xVL$g{^m$u*-{7h7vJrSHshgG|Y55HJ7iO40y|^M( zgT-J3j}D3#ssAptETRL3dmHoO@mpL}(h;$0CSvjmfFiMqVz7C%?hn`y@U2*^Y3rF# z?F?v{ttV9kg@!C2Jh1Uf|GCSu>QwPf_YS&R19)&$3k3|wiL)$CEJK*z{6lI^ZDxpN zpp~Js4CORj2(tnM#*56W|E_u1%t9HFt<9x`B7Gq{J~XIl#*@bajU+lGg56g08J)#O zyF^9mV}<$oc|Xxky^?)R`uLQjz6-E1?^Y=8asK;u$FKTu+GMI|Y52LqVR!!HXR>ufQc;C!B{>sOc z|6@(=Jw1t{#O6NCDYWqK793tK7wMRuwfybd-It?5gsWwS_k9An;=%oMDRd6t@cUr2 zK2mS7{?=Es@eeiJkMoCKOBg0u;T!oB{BSIL3oPnd-wN;Wl66d65sM5~cwU7(a z3-*V%2(W*(V;)S^0HNt5?kq}IHM!9QTzlx&u+lfHnzkdj(3iAuS=D~O=rdR0r?i@6 z7*JmEB4Ee&w5p#33N3R{odaZ5G5GmdR73=2IsBMf5dA)KFn&}|#N4j_>zvt{uAO=E z;)Rgug^vjdjmGLysXuK2Kyz+b@YFJxRxnGg$fj$ke&wAMMo}Bh#11J!dPG5=XQbQZ zl0`ILDj-HBFy(cH3r%R!H-1-(=|{?A70kHd@fd3kcx7QW~8qto2 zvu^b<$G~yO`G=NjzGalAD~k=ChZ(16+&B$iN6XEjdQQ|*FiDxDnf&^X0 z=(0-Qu>_i4%e&;VHWNJCb5-mhz`rz2dha{XVSs!>*13t?N7a)aivd3ntB5F^o16|? zqTcIc+vFTKur0*0wMqElL!e6dfv?%nHRfA3=MhAqQFL#cXNvy;?!!~b$;nw8=OGROFX0w{ zqQr0P>FXO@KX|mRr5%AiaO8WpvXF_Sv$0vn^T>6uw zFI{^0fnE9-_ooeS-pw6!OlvH9oZsU^7f2y4ZjpBSXn}`jW_lT~Ps>2E-v3QIZk0xy z?O0}%p)Mw!I38#3s_$jUZm&Xe3Jb*zO}>2Y+&RKQ1P7c~nfa5Nw^V$3x}4dAvtd{; zi%!I6=KKW@yrKC+zR%_xq|rdSa<_=#@95uePKVC#)2<IJvma`k%yCS-)gyghyPO-WZy|)j{L~ zR@^7uVB}8!^J-n|s5;{|E$Y@+t>@r#v5m=E@!$K$9mZqtCo4Pgmig~F*3u8;=1R0; zFru=u(Iw}ZaevTWoN##Gh+23f^ucLY0d8*FgV5_z=r(4}hm{M*gr(^fT<&SO=PPj- zFuCbae1_HaT^YzeyLilrqkGFRUqAk5b&;jMD>iY(xLkupmJih-v8}0$b;E7X^CkAn@p{3ZHixYVsDw7pDD9$VbBf1K?~9D-h_~qWn*MN z)0lHFw3zdNB~EWJ8y@HWs$GI;@^%S?wtf-OvN2LWqb|N;a1$ zr;=lW46+&xqUtbx(=u4F`pvs{ws-4?K};f@7J}e5_UreYEb98>0+TO0$j$^wV8xV9 z-~*lWR9$kif^{$r5UT8MU7c`yy;2Rf#5csJ`;OP*WmvVVfQt!^4Qpwv)A!I0{&@D&Z9WYR-`Y58Ik$&uc zz-0o*8CAoQ7Xud<6ol*cHi_6uH@JS9TARy_CYPk~@N(V8hM=QjH>}2#qW6jsWiOPO zyWrZ*{P$yS-XKl!MoP5b%Q^Q3-a-SHdu$AB0bG~t#1$YUuiY1SOeX&S*x)Q?xM#08TR`!81sr$(>#g5D$AjvaIdyJvQT|}7i%g{b3sRG0o-~hai^6$$LdEnF z6)G;krl+SbELJ-7(*VW3n-**12Otj(ZJ*gXE}Sy?>jgJ}zeXMS`M93lnj}JH6Mqcos)iRnpz@AsiaTuhijz_}3D;jnKi(#m~?5@lIG{qb8)}Fnsy)g%kiK!hM>S z>tAPp6)!TP_Xw5cmogNRi|0mZ&Mh0035chmy_Vq`#1v5FcVet@>tL zqtbS?iH_ag_E;M&!z^?G03j33%Nw4Wn(9CB<_%M>Q44Aru>M1TACZA14Y z0FvFfI5|-h6XujsVECjJiwnc<&CCaH3!m0zfe^w|n;$7-JZ^iYDPf7c9mF7X;)L_y zcJ}^lttbywAA};$63raV8|I0Sf5MUu=_e3s!Q!65oubxBGmXFU| zHGr!@*37K-#XE&zM$J2*i;FCPoBJKVx3KqjpQgcU`NNXMf8lviUS6INsM{L?&Dczb zKbsa_F_QYI{|5n5u2MCW64+3$Un6dm7pl?fn=h29N*2V7aM1Lg)b6h}zC*Y& zx4U`}%r`E7aL|_kk2`=GRFMIJR4C(TV`C#w=j!TOC{YfgT%d%>HQy_!fT9O^D{`=c zE(V&P*oHhOa$C%Nb6HKCV%pQeP6mZr0Wx2M6icTe+SvL?;PU|+-rG!5!+<2 zxVL!SDFAsB}c_p`sa}3ZkV`#I}w#vTAeG65gJ*_sD(uV%ot2 zFPemLHzu;h$b{zE{p+q!LeU}MkZq5q@;la0-p~G!G_QfIMu3`!o9Iulx-ZTn#ah-I z4Ip{m#rs4G@zSMnMHW7W>4|F7{EGe(TU$`ZlBRFz%h=g$HS6Y2HE)j{q`Xm_b3tT6xfcs^g<1Qub7)KNw1 z;1L@k0BnZNTkntC0v`kT?Zdr7yS@!u55fG$&tF)UH#Uc9nfzkvuEesJ_$izPgP>ht z=hKjsl+^ogLM>*l63VggO$e*FB?_idy>%5Y5P#7Dgu}z@YYVx22RHm0W zp#@MW9-Nnd!vL2bBEQdgYCRDL%!`MK`7g zM}kjkta``+s^DcfuyPM(m1aDdvoVR5AEI1|!U|lxbm=+yF9?;$%=ubSzp@(d7)wd7 z(t}VI9$5`_i|njt0H7NUW}wl{9vYXL5Ir+*{vkjh5Hc%ra;6f#78G=EM`gh}){|y< zFCAMrCyt7W8tTryKNW~$9KpG*9R_)MDM7#FeG)+3qq%zZDj^ZNpgY{#xpk}k+J(#e zpqiM2DNmwCiyDN&-uVY#_VvXitu}Cy>AKdT!X1(9kbA&NFnMh>$cq67Te(HL1l1M( zd@N|*P-rVs?D<_F0r&?YEzR~Ew`bR0cpNc9u=T}#sm*f|xmT#^0gbVoP^5`EeJRJ{ ziVER zpP+>Q58OgkLHTfoo18XTAPdKF;SW5!&L#an&73hTo){(tLgfHC`e{-tIM$)-$i;mq zqr*9)CHtRlKOJh43am}lr*P@7vk}wA4IoYa%{vIW-Mt%iUA0_g&es(I^?6o~myKSg zVDDwo`e~-)ViRaE*8{sNfMXZ}Ns;%NoKT92ijj~Dj(?NgK zQXTJY3TE7ZgZ3O#a2#Vib0eg?B!9UPA&`c)?-LH0x1qnVji4ZpD|`krLew2Tb zXwh4z-%JMWyl&8x+vW=Cy`8qLKDKGS2(K~rrHH2VH2t9gw|c3brz8y-*fEwqeLBWK z2R)6gMibOD62k6Rc#eME?#x0G`h&phVD^@qJIBlO*XlBiU;P5-4;DVJPG|<&W0+z3 zldU6)uc1n5Qr#(AnwMMuo{X2@1^}4daSmUy-^YC|TG231uDHo^$ybOL$J0K=|8*6^ zZ(avVq=O50e_EoT6Q?`5AS11iv-{LAVqsR(-0&%IxN?XIJQMt|>a8N2(I%`B!SGsD zEDJOnG|4rRx=dgpjbCry-tlIKOS^B)X!nzj^EpZ;O6;iG+S=d8XU1T%&yt7*TLQGl zprvcYKudR=Z3#FCx%KsRZLPWz6v=x@5b9gL+g1p3R1%O0tD}@V&F>u?jT%2jmtxgR ziN~8`t3(3E#LTRCg$hB4;{rv*sal5H|F6H=UWQfqtbZOQLfK!nhn}k@5S0JVTW^Ql zqlKNm(QVe)LG?R&apssFzEVg5I71Wu<9KH|Sa=a^amV}N4Tdp3-0>`wIpTtI{^w{+ c&CEn Date: Sat, 14 May 2016 16:52:11 -0400 Subject: [PATCH 042/343] icon --- code/game/objects/items/devices/floor_painter.dm | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/code/game/objects/items/devices/floor_painter.dm b/code/game/objects/items/devices/floor_painter.dm index 10961837f63..91d2ce6011d 100644 --- a/code/game/objects/items/devices/floor_painter.dm +++ b/code/game/objects/items/devices/floor_painter.dm @@ -2,14 +2,17 @@ /obj/item/device/floor_painter name = "floor painter" - icon = 'icons/obj/bureaucracy.dmi' - icon_state = "labeler1" - item_state = "flight" + icon_state = "floor_painter" var/floor_icon var/floor_state = "floor" var/floor_dir = SOUTH + w_class = 1 + item_state = "electronic" + flags = CONDUCT + slot_flags = SLOT_BELT + var/static/list/allowed_states = list("arrival", "arrivalcorner", "bar", "barber", "blackcorner", "blue", "bluecorner", "bluefull", "bluered", "blueyellow", "blueyellowfull", "bot", "brown", "browncorner", "browncornerold", "brownold", "cafeteria", "caution", "cautioncorner", "chapel", "cmo", "dark", "delivery", "escape", "escapecorner", "floor", From a7330745a26742d1d9c85c10cd0a8bd916003e63 Mon Sep 17 00:00:00 2001 From: monster860 Date: Sat, 14 May 2016 18:09:47 -0400 Subject: [PATCH 043/343] Adds permanent teleporter --- code/game/machinery/constructable_frame.dm | 11 ++++ code/game/machinery/teleporter.dm | 69 ++++++++++++++++++++++ 2 files changed, 80 insertions(+) diff --git a/code/game/machinery/constructable_frame.dm b/code/game/machinery/constructable_frame.dm index 6b13dbe95e3..4c820d26857 100644 --- a/code/game/machinery/constructable_frame.dm +++ b/code/game/machinery/constructable_frame.dm @@ -698,6 +698,17 @@ obj/item/weapon/circuitboard/rdserver /obj/item/weapon/stock_parts/capacitor = 2, /obj/item/weapon/stock_parts/console_screen = 1) +/obj/item/weapon/circuitboard/teleporter_perma + name = "circuit board (Permanent Teleporter)" + build_path = /obj/machinery/teleport/perma + board_type = "machine" + origin_tech = "programming=3;engineering=5;bluespace=5;materials=4" + frame_desc = "Requires 3 Bluespace Crystals and 1 Matter Bin." + req_components = list( + /obj/item/weapon/ore/bluespace_crystal = 3, + /obj/item/weapon/stock_parts/matter_bin = 1) + var/target + /obj/item/weapon/circuitboard/telesci_pad name = "Circuit board (Telepad)" build_path = /obj/machinery/telepad diff --git a/code/game/machinery/teleporter.dm b/code/game/machinery/teleporter.dm index 6dd9954046b..4ab4ca1d27e 100644 --- a/code/game/machinery/teleporter.dm +++ b/code/game/machinery/teleporter.dm @@ -370,6 +370,70 @@ else icon_state = "tele0" +/obj/machinery/teleport/perma + name = "permanent teleporter" + desc = "A teleporter with the target pre-set on the circuit board." + icon_state = "tele0" + var/recalibrating = 0 + use_power = 1 + idle_power_usage = 10 + active_power_usage = 2000 + + var/target + var/tele_delay = 50 + +/obj/machinery/teleport/perma/RefreshParts() + for(var/obj/item/weapon/circuitboard/teleporter_perma/C in component_parts) + target = C.target + var/A = 40 + for(var/obj/item/weapon/stock_parts/matter_bin/M in component_parts) + A -= M.rating * 10 + tele_delay = max(A, 0) + update_icon() + +/obj/machinery/teleport/perma/Bumped(M as mob|obj) + if(stat & (BROKEN|NOPOWER)) + return + if(z == ZLEVEL_CENTCOMM) + to_chat(M, "You can't use this here.") + if(target && !recalibrating && !panel_open) + //--FalseIncarnate + //Prevents AI cores from using the teleporter, prints out failure messages for clarity + if(istype(M, /mob/living/silicon/ai) || istype(M, /obj/structure/AIcore)) + visible_message("\red The teleporter rejects the AI unit.") + if(istype(M, /mob/living/silicon/ai)) + var/mob/living/silicon/ai/T = M + var/list/TPError = list("\red Firmware instructions dictate you must remain on your assigned station!", + "\red You cannot interface with this technology and get rejected!", + "\red External firewalls prevent you from utilizing this machine!", + "\red Your AI core's anti-bluespace failsafes trigger and prevent teleportation!") + to_chat(T, "[pick(TPError)]") + return + else + do_teleport(M, target) + use_power(5000) + + if(tele_delay) + recalibrating = 1 + update_icon() + spawn(tele_delay) + recalibrating = 0 + update_icon() + //--FalseIncarnate + return + +/obj/machinery/teleport/perma/power_change() + ..() + update_icon() + +/obj/machinery/teleport/perma/update_icon() + if(panel_open) + icon_state = "tele-o" + else if(target && !recalibrating && !(stat & (BROKEN|NOPOWER))) + icon_state = "tele1" + else + icon_state = "tele0" + /obj/machinery/teleport/station name = "station" desc = "The power control station for a bluespace teleporter." @@ -457,6 +521,11 @@ link_console_and_hub() to_chat(user, "You reconnect the station to nearby machinery.") return + if(istype(W, /obj/item/weapon/circuitboard/teleporter_perma)) + var/obj/item/weapon/circuitboard/teleporter_perma/C = W + C.target = teleporter_console.target + to_chat(user, "You copy the targeting information from \the [src] to \the [W]") + return /obj/machinery/teleport/station/attack_ai() src.attack_hand() From be6c65efc375177369279e92f9639ea353d6b563 Mon Sep 17 00:00:00 2001 From: monster860 Date: Sat, 14 May 2016 18:10:08 -0400 Subject: [PATCH 044/343] adds it to rnd --- code/modules/research/designs/machine_designs.dm | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/code/modules/research/designs/machine_designs.dm b/code/modules/research/designs/machine_designs.dm index d2da596b692..385969c3f3f 100644 --- a/code/modules/research/designs/machine_designs.dm +++ b/code/modules/research/designs/machine_designs.dm @@ -92,6 +92,16 @@ build_path = /obj/item/weapon/circuitboard/teleporter_station category = list ("Teleportation Machinery") +/datum/design/teleport_perma + name = "Machine Board (Permanent Teleporter)" + desc = "Allows for the construction of circuit boards used to build a Permanent Teleporter." + id = "tele_perma" + req_tech = list("programming" = 3, "bluespace" = 5, "materials" = 4, "engineering" = 5) + build_type = IMPRINTER + materials = list(MAT_GLASS = 1000, "sacid" = 20) + build_path = /obj/item/weapon/circuitboard/teleporter_perma + category = list ("Teleportation Machinery") + /datum/design/bodyscanner name = "Machine Board (Body Scanner)" desc = "Allows for the construction of circuit boards used to build a Body Scanner." From 63574226c6113a7602972ffa2f2cd95ec3129bbc Mon Sep 17 00:00:00 2001 From: monster860 Date: Sat, 14 May 2016 18:26:58 -0400 Subject: [PATCH 045/343] spans --- code/game/machinery/teleporter.dm | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/code/game/machinery/teleporter.dm b/code/game/machinery/teleporter.dm index 4ab4ca1d27e..60924f4c4e3 100644 --- a/code/game/machinery/teleporter.dm +++ b/code/game/machinery/teleporter.dm @@ -323,13 +323,13 @@ //--FalseIncarnate //Prevents AI cores from using the teleporter, prints out failure messages for clarity if(istype(M, /mob/living/silicon/ai) || istype(M, /obj/structure/AIcore)) - visible_message("\red The teleporter rejects the AI unit.") + visible_message("The teleporter rejects the AI unit.") if(istype(M, /mob/living/silicon/ai)) var/mob/living/silicon/ai/T = M - var/list/TPError = list("\red Firmware instructions dictate you must remain on your assigned station!", - "\red You cannot interface with this technology and get rejected!", - "\red External firewalls prevent you from utilizing this machine!", - "\red Your AI core's anti-bluespace failsafes trigger and prevent teleportation!") + var/list/TPError = list("Firmware instructions dictate you must remain on your assigned station!", + "You cannot interface with this technology and get rejected!", + "External firewalls prevent you from utilizing this machine!", + "Your AI core's anti-bluespace failsafes trigger and prevent teleportation!") to_chat(T, "[pick(TPError)]") return else @@ -400,13 +400,13 @@ //--FalseIncarnate //Prevents AI cores from using the teleporter, prints out failure messages for clarity if(istype(M, /mob/living/silicon/ai) || istype(M, /obj/structure/AIcore)) - visible_message("\red The teleporter rejects the AI unit.") + visible_message("The teleporter rejects the AI unit.") if(istype(M, /mob/living/silicon/ai)) var/mob/living/silicon/ai/T = M - var/list/TPError = list("\red Firmware instructions dictate you must remain on your assigned station!", - "\red You cannot interface with this technology and get rejected!", - "\red External firewalls prevent you from utilizing this machine!", - "\red Your AI core's anti-bluespace failsafes trigger and prevent teleportation!") + var/list/TPError = list("Firmware instructions dictate you must remain on your assigned station!", + "You cannot interface with this technology and get rejected!", + "External firewalls prevent you from utilizing this machine!", + "Your AI core's anti-bluespace failsafes trigger and prevent teleportation!") to_chat(T, "[pick(TPError)]") return else From 3dcbe81b6b06d0c31898113516ecbee439ec3845 Mon Sep 17 00:00:00 2001 From: monster860 Date: Sat, 14 May 2016 18:45:44 -0400 Subject: [PATCH 046/343] adds return --- code/game/machinery/teleporter.dm | 2 ++ 1 file changed, 2 insertions(+) diff --git a/code/game/machinery/teleporter.dm b/code/game/machinery/teleporter.dm index 60924f4c4e3..3052d5a28ce 100644 --- a/code/game/machinery/teleporter.dm +++ b/code/game/machinery/teleporter.dm @@ -319,6 +319,7 @@ /obj/machinery/teleport/hub/Bumped(M as mob|obj) if(z == ZLEVEL_CENTCOMM) to_chat(M, "You can't use this here.") + return if(power_station && power_station.engaged && !panel_open) //--FalseIncarnate //Prevents AI cores from using the teleporter, prints out failure messages for clarity @@ -396,6 +397,7 @@ return if(z == ZLEVEL_CENTCOMM) to_chat(M, "You can't use this here.") + return if(target && !recalibrating && !panel_open) //--FalseIncarnate //Prevents AI cores from using the teleporter, prints out failure messages for clarity From b169615080f383d8e748ebc6124bc2bb6ce4961b Mon Sep 17 00:00:00 2001 From: IK3I Date: Sat, 14 May 2016 19:50:07 -0500 Subject: [PATCH 047/343] Final changes of the refactor A couple bug fixes might be needed, but it /should/ be ready for live. --- .../computer/pod_tracking_console.dm | 11 +- code/game/machinery/portable_turret.dm | 2 +- code/game/machinery/turrets.dm | 16 +- .../living/simple_animal/hostile/hostile.dm | 4 +- .../hostile/retaliate/retaliate.dm | 6 +- .../mob/living/simple_animal/simple_animal.dm | 2 +- code/modules/spacepods/equipment.dm | 51 ++-- code/modules/spacepods/spacepod.dm | 265 ++++++++++-------- icons/vehicles/spacepod.dmi | Bin 3194 -> 4134 bytes 9 files changed, 194 insertions(+), 163 deletions(-) diff --git a/code/game/machinery/computer/pod_tracking_console.dm b/code/game/machinery/computer/pod_tracking_console.dm index e759cc0357f..371c3af366d 100644 --- a/code/game/machinery/computer/pod_tracking_console.dm +++ b/code/game/machinery/computer/pod_tracking_console.dm @@ -22,13 +22,10 @@ if(my_pod && enabled) var/podname = capitalize(sanitize(my_pod.name)) var/list/chairs = list() - if(my_pod.occupants) - var/mob/pilot = my_pod.occupants[PILOT] - if(my_pod.occupants[PILOT]) - chairs += list("pilot" = pilot.name) - for(var/mob/M in my_pod.occupants) - if(M == pilot) - continue + if(my_pod.pilot || my_pod.passengers) + if(my_pod.pilot) + chairs += list("pilot" = my_pod.pilot.name) + for(var/mob/M in my_pod.passengers) chairs += list("passenger" = M.name) pods.Add(list(list("pod" = "\ref[my_pod]", "name" = podname) + chairs + list("x" = my_pod.x, "y" = my_pod.y, "z" = my_pod.z))) diff --git a/code/game/machinery/portable_turret.dm b/code/game/machinery/portable_turret.dm index c5cd700abaf..eab12bb22d5 100644 --- a/code/game/machinery/portable_turret.dm +++ b/code/game/machinery/portable_turret.dm @@ -519,7 +519,7 @@ var/list/turret_icons assess_and_assign(ME.occupant, targets, secondarytargets) for(var/obj/spacepod/SP in view(7,src)) - assess_and_assign(SP.occupants[PILOT], targets, secondarytargets) + assess_and_assign(SP.pilot, targets, secondarytargets) for(var/obj/vehicle/T in view(7,src)) assess_and_assign(T.buckled_mob, targets, secondarytargets) diff --git a/code/game/machinery/turrets.dm b/code/game/machinery/turrets.dm index 022e0d2765e..82060d47bc2 100644 --- a/code/game/machinery/turrets.dm +++ b/code/game/machinery/turrets.dm @@ -21,7 +21,7 @@ turretTargets |= Mech else if( istype(O, /obj/spacepod) ) var/obj/spacepod/Pod = O - if( Pod.occupants ) + if( Pod.pilot ) turretTargets |= Pod else if(istype(O,/mob/living/simple_animal)) turretTargets |= O @@ -139,7 +139,7 @@ return 1 else if( istype(T, /obj/spacepod) ) var/obj/spacepod/SP = T - if( SP.occupants ) + if( SP.pilot ) return 1 else if(istype(T,/mob/living/simple_animal)) var/mob/living/simple_animal/A = T @@ -159,8 +159,8 @@ if(M.occupant) new_targets += M for(var/obj/spacepod/M in protected_area.turretTargets) - if(M.occupants[PILOT]) - new_targets += M.occupants[PILOT] + if(M.pilot) + new_targets += M.pilot for(var/mob/living/simple_animal/M in protected_area.turretTargets) if(!M.stat) new_targets += M @@ -488,7 +488,7 @@ return 1 else if(istype(target, /obj/spacepod)) var/obj/spacepod/S = target - if(S.occupants) + if(S.pilot) return 1 return 0 @@ -522,11 +522,11 @@ continue //Don't shoot at empty mechs. pos_targets += M for(var/obj/spacepod/M in oview(scan_range, src)) - if(M.occupants[PILOT]) - var/mob/P = M.occupants[PILOT] + if(M.pilot) + var/mob/P = M.pilot if(faction in P.faction) continue - if(!M.occupants) + if(!M.pilot) continue //Don't shoot at empty pods. pos_targets += M if(pos_targets.len) diff --git a/code/modules/mob/living/simple_animal/hostile/hostile.dm b/code/modules/mob/living/simple_animal/hostile/hostile.dm index 81a0828df14..6e34ff4b8b0 100644 --- a/code/modules/mob/living/simple_animal/hostile/hostile.dm +++ b/code/modules/mob/living/simple_animal/hostile/hostile.dm @@ -118,8 +118,8 @@ return 1 if(istype(the_target, /obj/spacepod)) var/obj/spacepod/S = the_target - if(S.occupants) //Just so we don't attack empty pods - for(var/mob/M in S.occupants) + if(S.pilot) //Just so we don't attack empty pods + for(var/mob/M in S.pilot) if(CanAttack(M)) return 1 if(isliving(the_target)) diff --git a/code/modules/mob/living/simple_animal/hostile/retaliate/retaliate.dm b/code/modules/mob/living/simple_animal/hostile/retaliate/retaliate.dm index e6d373d7504..a58223acb04 100644 --- a/code/modules/mob/living/simple_animal/hostile/retaliate/retaliate.dm +++ b/code/modules/mob/living/simple_animal/hostile/retaliate/retaliate.dm @@ -14,7 +14,7 @@ return A else if(istype(A, /obj/spacepod)) var/obj/spacepod/M = A - if(M.occupants) + if(M.pilot) return A /mob/living/simple_animal/hostile/retaliate/ListTargets() @@ -47,9 +47,9 @@ enemies |= M.occupant else if(istype(A, /obj/spacepod)) var/obj/spacepod/M = A - if(M.occupants[PILOT]) + if(M.pilot) enemies |= M - enemies |= M.occupants[PILOT] + enemies |= M.pilot for(var/mob/living/simple_animal/hostile/retaliate/H in around) var/retaliate_faction_check = 0 diff --git a/code/modules/mob/living/simple_animal/simple_animal.dm b/code/modules/mob/living/simple_animal/simple_animal.dm index 09c82dbf1b2..45f2c6789c9 100644 --- a/code/modules/mob/living/simple_animal/simple_animal.dm +++ b/code/modules/mob/living/simple_animal/simple_animal.dm @@ -529,7 +529,7 @@ return 0 if (istype(the_target,/obj/spacepod)) var/obj/spacepod/S = the_target - if (S.occupants) + if (S.pilot) return 0 return 1 diff --git a/code/modules/spacepods/equipment.dm b/code/modules/spacepods/equipment.dm index 7ff052d1e6e..9b0655958c3 100644 --- a/code/modules/spacepods/equipment.dm +++ b/code/modules/spacepods/equipment.dm @@ -51,14 +51,19 @@ var/obj/item/device/spacepod_equipment/cargo/cargo_system // cargo system var/obj/item/device/spacepod_equipment/cargo/sec_cargo_system // secondary cargo system var/obj/item/device/spacepod_equipment/lock/lock_system // lock system - //var/obj/item/device/spacepod_equipment/engine/engine_system // engine system - //var/obj/item/device/spacepod_equipment/shield/shield_system // shielding system /datum/spacepod/equipment/New(var/obj/spacepod/SP) ..() if(istype(SP)) my_atom = SP +/datum/spacepod/equipment/proc/get_list() + var/list/stuff + for(var/obj/I in vars) + if(istype(I, /obj/item/device/spacepod_equipment)) + stuff += I + return stuff + /obj/item/device/spacepod_equipment name = "equipment" var/obj/spacepod/my_atom @@ -182,50 +187,36 @@ name = "pod cargo" desc = "You shouldn't be seeing this" icon = 'icons/vehicles/spacepod.dmi' - icon_state = "blank" + icon_state = "cargo_blank" + var/obj/storage = null /obj/item/device/spacepod_equipment/cargo/proc/passover(var/obj/item/I) return /obj/item/device/spacepod_equipment/cargo/proc/unload() // called by unload verb - return + if(storage) + storage.forceMove(get_turf(my_atom)) + storage = null +/obj/item/device/spacepod_equipment/cargo/removed(var/mob/user) // called when system removed + . = ..() + unload() // Ore System /obj/item/device/spacepod_equipment/cargo/ore name = "spacepod ore storage system" desc = "An ore storage system for spacepods. Scoops up any ore you drive over." icon_state = "cargo_ore" - var/obj/structure/ore_box/box /obj/item/device/spacepod_equipment/cargo/ore/passover(var/obj/item/I) - if(box && istype(I,/obj/item/weapon/ore)) - I.forceMove(box) - -/obj/item/device/spacepod_equipment/cargo/ore/unload() - if(box) - box.forceMove(get_turf(my_atom)) - box = null - -/obj/item/device/spacepod_equipment/cargo/ore/removed(var/mob/user) - . = ..() - unload() + if(storage && istype(I,/obj/item/weapon/ore)) + I.forceMove(storage) // Crate System /obj/item/device/spacepod_equipment/cargo/crate name = "spacepod crate storage system" desc = "A heavy duty storage system for spacepods. Holds one crate." - icon_state = "cargo_ore" - var/obj/structure/closet/crate/crate - -/obj/item/device/spacepod_equipment/cargo/crate/unload() - if(crate) - crate.forceMove(get_turf(my_atom)) - crate = null - -/obj/item/device/spacepod_equipment/cargo/crate/removed(var/mob/user) - . = ..() - unload() + icon_state = "cargo_crate" /* /////////////////////////////////////// @@ -233,8 +224,6 @@ /////////////////////////////////////// */ -//Storage system and inventory is handled in cargo_hold.dm - /obj/item/device/spacepod_equipment/sec_cargo name = "secondary cargo" desc = "you shouldn't be seeing this" @@ -245,14 +234,14 @@ /obj/item/device/spacepod_equipment/sec_cargo/chair name = "passanger seat" desc = "A passenger seat for a spacepod" - icon_state = "cargo_ore" + icon_state = "sec_cargo_chair" occupant_mod = 1 // Loot Box /obj/item/device/spacepod_equipment/sec_cargo/loot_box name = "loot box" desc = "A small compartment to store valuables" - icon_state = "cargo_ore" + icon_state = "sec_cargo_loot" storage_mod = list("slots" = 7, "w_class" = 14) /* diff --git a/code/modules/spacepods/spacepod.dm b/code/modules/spacepods/spacepod.dm index 4fe925ac085..c1c4fc3def9 100644 --- a/code/modules/spacepods/spacepod.dm +++ b/code/modules/spacepods/spacepod.dm @@ -1,6 +1,5 @@ #define DAMAGE 1 #define FIRE 2 -#define PILOT "pilot" /obj/spacepod name = "\improper space pod" @@ -15,8 +14,9 @@ layer = 3.9 infra_luminosity = 15 - var/list/mob/occupants = list() //uses [PILOT] index for pilot and numerics for passangers - var/max_occupants = 1 + var/list/mob/pilot //There is only ever one pilot and he gets all the privledge + var/list/mob/passengers = list() //passengers can't do anything and are variable in number + var/max_passengers = 0 var/obj/item/weapon/storage/internal/cargo_hold var/datum/spacepod/equipment/equipment_system @@ -100,10 +100,10 @@ qdel(ion_trail) ion_trail = null occupant_sanity_check() - if(occupants) - for(var/mob/M in occupants) + if(passengers) + for(var/mob/M in passengers) M.forceMove(get_turf(src)) - occupants -= M + passengers -= M spacepods_list -= src return ..() @@ -113,7 +113,6 @@ else processing_objects.Remove(src) - /obj/spacepod/proc/update_icons() if(!pod_overlays) pod_overlays = new/list(2) @@ -162,28 +161,28 @@ health = max(0, health - damage) var/percentage = (health / initial(health)) * 100 occupant_sanity_check() - if(occupants && oldhealth > health && percentage <= 25 && percentage > 0) + if(passengers && oldhealth > health && percentage <= 25 && percentage > 0) var/sound/S = sound('sound/effects/engine_alert2.ogg') S.wait = 0 //No queue S.channel = 0 //Any channel S.volume = 50 - for(var/mob/M in occupants) + for(var/mob/M in passengers) to_chat(M, S) - if(occupants && oldhealth > health && !health) + if(passengers && oldhealth > health && !health) var/sound/S = sound('sound/effects/engine_alert1.ogg') S.wait = 0 S.channel = 0 S.volume = 50 - for(var/mob/M in occupants) + for(var/mob/M in passengers) to_chat(M, S) if(!health) spawn(0) - if(occupants) - for(var/mob/M in occupants) + if(passengers) + for(var/mob/M in passengers) to_chat(M, "Critical damage to the vessel detected, core explosion imminent!") for(var/i = 10, i >= 0; --i) - if(occupants) - for(var/mob/M in occupants) + if(passengers) + for(var/mob/M in passengers) to_chat(M, "[i]") if(i == 0) explosion(loc, 2, 4, 8) @@ -202,7 +201,7 @@ occupant_sanity_check() switch(severity) if(1) - for(var/mob/M in occupants) + for(var/mob/M in passengers) var/mob/living/carbon/human/H = M if(H) H.forceMove(get_turf(src)) @@ -221,9 +220,11 @@ cargo_hold.emp_act(severity) switch(severity) if(1) - if(occupants) - for(var/mob/M in occupants) - to_chat(M, "The pod console flashes 'Heavy EMP WAVE DETECTED'.")//warn the occupants + if(pilot) + to_chat(pilot, "The pod console flashes 'Heavy EMP WAVE DETECTED'.") + if(passengers) + for(var/mob/M in passengers) + to_chat(M, "The pod console flashes 'Heavy EMP WAVE DETECTED'.")//warn the passengers if(battery) @@ -234,9 +235,11 @@ processing_objects.Add(src) if(2) - if(occupants) - for(var/mob/M in occupants) - to_chat(M, "The pod console flashes 'EMP WAVE DETECTED'.")//warn the occupants + if(pilot) + to_chat(pilot, "The pod console flashes 'EMP WAVE DETECTED'.") + if(passengers) + for(var/mob/M in passengers) + to_chat(M, "The pod console flashes 'EMP WAVE DETECTED'.")//warn the passengers deal_damage(40) if(battery) @@ -332,12 +335,33 @@ obj/spacepod/proc/add_equipment(mob/user, var/obj/item/device/spacepod_equipment equipment_system.vars[slot] = SPE var/obj/item/device/spacepod_equipment/system = equipment_system.vars[slot] system.my_atom = src - max_occupants += SPE.occupant_mod + max_passengers += SPE.occupant_mod cargo_hold.storage_slots += SPE.storage_mod["slots"] cargo_hold.max_combined_w_class += SPE.storage_mod["w_class"] return /obj/spacepod/attack_hand(mob/user as mob) + if(user.a_intent == I_GRAB && unlocked) + var/mob/target + if(pilot) + target = pilot + else if(passengers.len > 0) + target = passengers[1] + + if(target && istype(target)) + src.visible_message("[user] is trying to rip the door open and pull [target] out of the [src]!", + "You see [user] outside the door trying to rip it open!") + if(do_after(user, 50, target = src)) + target.forceMove(get_turf(src)) + target.Stun(1) + passengers -= target + target.visible_message("[user] flings the door open and tears [target] out of the [src]", + "The door flies open and you are thrown out of the [src] and to the ground!") + else + target.visible_message("[user] was unable to get the door open!", + "You manage to keep [user] out of the [src]!") + return + if(!hatch_open) if(cargo_hold.storage_slots > 0) if(unlocked) @@ -346,7 +370,7 @@ obj/spacepod/proc/add_equipment(mob/user, var/obj/item/device/spacepod_equipment to_chat(user, "The storage compartment is locked") return ..() if(!equipment_system || !istype(equipment_system)) - to_chat(user, "The pod has no equpment datum, or is the wrong type, yell at pomf.") + to_chat(user, "The pod has no equpment datum, or is the wrong type, yell at IK3I.") return var/list/possible = list() if(battery) @@ -388,7 +412,7 @@ obj/spacepod/proc/add_equipment(mob/user, var/obj/item/device/spacepod_equipment /obj/spacepod/proc/remove_equipment(mob/user, var/obj/item/device/spacepod_equipment/SPE, var/slot) - if(occupants.len > max_occupants - SPE.occupant_mod) + if(passengers.len > max_passengers - SPE.occupant_mod) to_chat(user, "Someone is sitting in \the [SPE]!") return @@ -401,7 +425,7 @@ obj/spacepod/proc/add_equipment(mob/user, var/obj/item/device/spacepod_equipment if(user.put_in_any_hand_if_possible(SPE)) to_chat(user, "You remove \the [SPE] from the equipment system.") - max_occupants -= SPE.occupant_mod + max_passengers -= SPE.occupant_mod cargo_hold.storage_slots -= SPE.storage_mod["slots"] cargo_hold.max_combined_w_class -= SPE.storage_mod["w_class"] SPE.removed(user) @@ -459,6 +483,11 @@ obj/spacepod/proc/add_equipment(mob/user, var/obj/item/device/spacepod_equipment equipment_system.misc_system = L equipment_system.misc_system.my_atom = src equipment_system.misc_system.enabled = 1 + var/obj/item/device/spacepod_equipment/sec_cargo/chair/C = new /obj/item/device/spacepod_equipment/sec_cargo/chair + C.loc = equipment_system + equipment_system.sec_cargo_system = C + equipment_system.sec_cargo_system.my_atom = src + max_passengers = 1 var/obj/item/device/spacepod_equipment/lock/keyed/K = new /obj/item/device/spacepod_equipment/lock/keyed K.loc = equipment_system equipment_system.lock_system = K @@ -489,12 +518,11 @@ obj/spacepod/proc/add_equipment(mob/user, var/obj/item/device/spacepod_equipment set category = "Spacepod" set src = usr.loc set popup_menu = 0 - if(usr != src.occupants[PILOT]) - to_chat(usr, "You can't reach the controls from your chair") return use_internal_tank = !use_internal_tank - for(var/mob/M in occupants) - to_chat(M, "Now taking air from [use_internal_tank?"internal airtank":"environment"].") + to_chat(usr, "Now taking air from [use_internal_tank?"internal airtank":"environment"].") return /obj/spacepod/proc/add_cabin() @@ -549,19 +577,20 @@ obj/spacepod/proc/add_equipment(mob/user, var/obj/item/device/spacepod_equipment . = t_air.return_temperature() return -/* Save for cargo refactor /obj/spacepod/proc/moved_other_inside(var/mob/living/carbon/human/H as mob) occupant_sanity_check() - if(!occupant2) + if(passengers.len < max_passengers) H.stop_pulling() H.forceMove(src) - occupant2 = H + passengers += H H.forceMove(src) playsound(src, 'sound/machines/windowdoor.ogg', 50, 1) return 1 -*/ /obj/spacepod/MouseDrop_T(atom/A, mob/user) + if(user == pilot || user in passengers) + return + if(istype(A,/mob)) var/mob/M = A if(!isliving(M)) @@ -569,61 +598,48 @@ obj/spacepod/proc/add_equipment(mob/user, var/obj/item/device/spacepod_equipment occupant_sanity_check() -/* save for cargo refactor - if(M != user && M.stat == DEAD && unlocked) - if(occupant2 && !occupant) - to_chat(usr, "You can't put a corpse into the driver's seat!") + if(M != user && unlocked && (M.stat == DEAD || M.incapacitated())) + if(passengers.len >= max_passengers && !pilot) + to_chat(usr, "That person can't fly the pod!") return 0 - if(!occupant2) + if(passengers.len < max_passengers) visible_message("[user.name] starts loading [M.name] into the pod!") - sleep(10) - moved_other_inside(M) -*/ + if(do_after(user, 50, M)) + moved_other_inside(M) if(M == user) enter_pod(user) - if(istype(A, /obj/structure/ore_box)) // For loading ore boxes - var/obj/structure/ore_box/O = A - if(equipment_system.cargo_system && istype(equipment_system.cargo_system,/obj/item/device/spacepod_equipment/cargo/ore)) - var/obj/item/device/spacepod_equipment/cargo/ore/C = equipment_system.cargo_system - if(!C.box) - to_chat(user, "You begin loading \the [O] into \the [src]'s [equipment_system.cargo_system]") - if(do_after(user, 40, target = src)) - C.box = O - O.forceMove(C) - to_chat(user, "You load \the [O] into \the [src]'s [equipment_system.cargo_system]!") - else - to_chat(user, "You fail to load \the [O] into \the [src]'s [equipment_system.cargo_system]") - else - to_chat(user, "\The [src] already has \an [C.box]") + if(istype(A, /obj/structure/ore_box) && equipment_system.cargo_system && istype(equipment_system.cargo_system,/obj/item/device/spacepod_equipment/cargo/ore)) // For loading ore boxes + load_cargo(user, A) - if(istype(A, /obj/structure/closet/crate)) // For loading crates - var/obj/structure/closet/crate/O = A - if(equipment_system.cargo_system && istype(equipment_system.cargo_system, /obj/item/device/spacepod_equipment/cargo/crate)) - var/obj/item/device/spacepod_equipment/cargo/crate/C = equipment_system.cargo_system - if(!C.crate) - to_chat(user, "You begin loading \the [O] into \the [src]'s [equipment_system.cargo_system]") - if(do_after(user, 40, target = src)) - C.crate = O - O.forceMove(C) - to_chat(user, "You load \the [O] into \the [src]'s [equipment_system.cargo_system]!") - else - to_chat(user, "You fail to load \the [O] into \the [src]'s [equipment_system.cargo_system]") - else - to_chat(user, "\The [src] already has \an [C.crate]") + if(istype(A, /obj/structure/closet/crate) && equipment_system.cargo_system && istype(equipment_system.cargo_system, /obj/item/device/spacepod_equipment/cargo/crate)) // For loading crates + load_cargo(user, A) + +/obj/spacepod/proc/load_cargo(mob/user, var/obj/O) + var/obj/item/device/spacepod_equipment/cargo/ore/C = equipment_system.cargo_system + if(!C.storage) + to_chat(user, "You begin loading \the [O] into \the [src]'s [equipment_system.cargo_system]") + if(do_after(user, 40, target = src)) + C.storage = O + O.forceMove(C) + to_chat(user, "You load \the [O] into \the [src]'s [equipment_system.cargo_system]!") + else + to_chat(user, "You fail to load \the [O] into \the [src]'s [equipment_system.cargo_system]") + else + to_chat(user, "\The [src] already has \an [C.storage]") /obj/spacepod/proc/enter_pod(mob/user) if (usr.stat != CONSCIOUS) - return + return 0 if(equipment_system.lock_system && !unlocked) to_chat(user, "\The [src]'s doors are locked!") - return + return 0 if(get_dist(src, user) > 2 || get_dist(usr, user) > 1) to_chat(usr, "They are too far away to put inside") - return + return 0 if(!istype(user)) return 0 @@ -652,15 +668,19 @@ obj/spacepod/proc/add_equipment(mob/user, var/obj/item/device/spacepod_equipment occupant_sanity_check() - if(occupants.len < max_occupants) + if(passengers.len <= max_passengers) visible_message("[user] starts to climb into \the [src].") if(do_after(user, 40, target = src)) - if(occupants.len < max_occupants) + if(!pilot || pilot == null) user.stop_pulling() - if(!occupants[PILOT]) - occupants[PILOT] = user - else - occupants += user + pilot = user + user.forceMove(src) + add_fingerprint(user) + playsound(src, 'sound/machines/windowdoor.ogg', 50, 1) + return + if(passengers.len < max_passengers) + user.stop_pulling() + passengers += user user.forceMove(src) add_fingerprint(user) playsound(src, 'sound/machines/windowdoor.ogg', 50, 1) @@ -672,26 +692,21 @@ obj/spacepod/proc/add_equipment(mob/user, var/obj/item/device/spacepod_equipment to_chat(user, "You can't fit in \the [src], it's full!") /obj/spacepod/proc/occupant_sanity_check() // going to have to adjust this later for cargo refactor - if(occupants) - if(occupants.len == max_occupants && !occupants[PILOT]) - var/occ = occupants[1] - occupants -= occ - occupants[PILOT] = occ - log_debug("##SPACEPOD WARNING: IMPOSSIBLE SEATING ARRANGEMENT: OCCUPANTS [english_list(occupants)], TURF [get_turf(src)] | AREA [get_area(src)] | COORDS [x], [y], [z]") - if(occupants.len > max_occupants) - for(var/i = occupants.len; i <= max_occupants; i--) - var/mob/occupant = occupants[i - 1] + if(passengers) + if(passengers.len > max_passengers) + for(var/i = passengers.len; i <= max_passengers; i--) + var/mob/occupant = passengers[i - 1] occupant.forceMove(get_turf(src)) - log_debug("##SPACEPOD WARNING: OCCUPANTS EXCEED CAP: MAX OCCUPANTS [max_occupants], OCCUPANTS [english_list(occupants)], TURF [get_turf(src)] | AREA [get_area(src)] | COORDS [x], [y], [z]") - occupants[i - 1] = null - for(var/mob/M in occupants) + log_debug("##SPACEPOD WARNING: passengers EXCEED CAP: MAX passengers [max_passengers], passengers [english_list(passengers)], TURF [get_turf(src)] | AREA [get_area(src)] | COORDS [x], [y], [z]") + passengers[i - 1] = null + for(var/mob/M in passengers) if(!ismob(M)) M.forceMove(get_turf(src)) log_debug("##SPACEPOD WARNING: NON-MOB OCCUPANT [M], TURF [get_turf(src)] | AREA [get_area(src)] | COORDS [x], [y], [z]") - occupants -= M + passengers -= M else if(M.loc != src) log_debug("##SPACEPOD WARNING: OCCUPANT [M] ESCAPED, TURF [get_turf(src)] | AREA [get_area(src)] | COORDS [x], [y], [z]") - occupants -= M + passengers -= M /obj/spacepod/verb/exit_pod() set name = "Exit pod" @@ -702,18 +717,18 @@ obj/spacepod/proc/add_equipment(mob/user, var/obj/item/device/spacepod_equipment if(!istype(user)) return - if (usr.stat != CONSCIOUS) // unconscious people can't let themselves out + if (user.stat != CONSCIOUS || user.incapacitated()) // unconscious and restrained people can't let themselves out return occupant_sanity_check() - if(user in occupants) + if(user == pilot) user.forceMove(get_turf(src)) - occupants -= user + pilot = null to_chat(user, "You climb out of \the [src].") - if(user == occupants[PILOT]) + if(user in passengers) user.forceMove(get_turf(src)) - occupants[PILOT] = null + passengers -= user to_chat(user, "You climb out of \the [src].") /obj/spacepod/verb/lock_pod() @@ -721,8 +736,8 @@ obj/spacepod/proc/add_equipment(mob/user, var/obj/item/device/spacepod_equipment set category = "Spacepod" set src = usr.loc - if(usr in occupants && usr != src.occupants[PILOT]) - to_chat(usr, "You can't reach the controls from your chair") return unlocked = !unlocked @@ -734,8 +749,8 @@ obj/spacepod/proc/add_equipment(mob/user, var/obj/item/device/spacepod_equipment set category = "Spacepod" set src = usr.loc - if(usr != src.occupants[PILOT]) - to_chat(usr, "You can't reach the controls from your chair") return for(var/obj/machinery/door/poddoor/multi_tile/P in orange(3,src)) @@ -747,6 +762,14 @@ obj/spacepod/proc/add_equipment(mob/user, var/obj/item/device/spacepod_equipment else P.close() return 1 + for(var/mob/living/carbon/human/O in passengers) + if(P.check_access(O.get_active_hand()) || P.check_access(O.wear_id)) + if(P.density) + P.open() + return 1 + else + P.close() + return 1 to_chat(usr, "Access denied.") return @@ -759,8 +782,8 @@ obj/spacepod/proc/add_equipment(mob/user, var/obj/item/device/spacepod_equipment set desc = "Fire the weapons." set category = "Spacepod" set src = usr.loc - if(usr != src.occupants[PILOT]) - to_chat(usr, "You can't reach the controls from your chair") return if(!equipment_system.weapon_system) to_chat(usr, "\The [src] has no weapons!") @@ -772,8 +795,8 @@ obj/spacepod/proc/add_equipment(mob/user, var/obj/item/device/spacepod_equipment set desc = "Unloads the cargo" set category = "Spacepod" set src = usr.loc - if(usr != src.occupants[PILOT]) - to_chat(usr, "You can't reach the controls from your chair") return if(!equipment_system.cargo_system) to_chat(usr, "\The [src] has no cargo system!") @@ -784,8 +807,8 @@ obj/spacepod/proc/add_equipment(mob/user, var/obj/item/device/spacepod_equipment set name = "Toggle Lights" set category = "Spacepod" set src = usr.loc - if(usr != src.occupants[PILOT]) - to_chat(usr, "You can't reach the controls from your chair") return lightsToggle() @@ -795,10 +818,32 @@ obj/spacepod/proc/add_equipment(mob/user, var/obj/item/device/spacepod_equipment set_light(lights_power) else set_light(0) - for(var/mob/M in occupants) + to_chat(usr, "Lights toggled [lights ? "on" : "off"].") + for(var/mob/M in passengers) to_chat(M, "Lights toggled [lights ? "on" : "off"].") return +/obj/spacepod/verb/checkSeat() + set name = "Check under Seat" + set category = "Spacepod" + set src = usr.loc + var/mob/user = usr + to_chat(user, "You start rooting around under the seat for lost items") + if(do_after(user, 40, src)) + var/obj/badlist = list(internal_tank, cargo_hold, pilot, battery) + equipment_system.get_list() + var/list/true_contents = contents - badlist + if(true_contents.len > 0) + var/obj/I = pick(true_contents) + if(user.put_in_any_hand_if_possible(I)) + src.contents -= I + to_chat(user, "You find a [I] [pick("under the seat", "under the console", "in the mainenance access")]!") + else + to_chat(user, "You think you saw something shiny, but you can't reach it!") + else + to_chat(user, "You fail to find anything of value.") + else + to_chat(user, "You decide against searching the [src]") + /obj/spacepod/proc/enter_after(delay as num, var/mob/user as mob, var/numticks = 5) var/delayfraction = delay/numticks @@ -854,7 +899,7 @@ obj/spacepod/proc/add_equipment(mob/user, var/obj/item/device/spacepod_equipment return /obj/spacepod/relaymove(mob/user, direction) - if(usr != src.occupants[PILOT]) + if(usr != src.pilot) return handlerelaymove(user, direction) diff --git a/icons/vehicles/spacepod.dmi b/icons/vehicles/spacepod.dmi index e55085622c9ad236c0b3fe4ba1eea300de26c9c5..54edb864aba2f28c995cfde7da069596d3991ed9 100644 GIT binary patch literal 4134 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 qcLSBw3xMw`GtaSp&VLA6#L(p;fiCUEgs literal 3194 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 From 007278a81567852b8c724118a4a4685b67770ec8 Mon Sep 17 00:00:00 2001 From: IK3I Date: Sat, 14 May 2016 22:07:23 -0500 Subject: [PATCH 048/343] Adds pod lock busters The CE and the Armory now have specialized drills for stubborn pod flying criminals. --- _maps/map_files/cyberiad/cyberiad.dmm | 4 ++-- code/modules/spacepods/lock_buster.dm | 13 +++++++++++++ code/modules/spacepods/spacepod.dm | 22 ++++++++++++++++++++-- icons/obj/device.dmi | Bin 34130 -> 34501 bytes paradise.dme | 1 + 5 files changed, 36 insertions(+), 4 deletions(-) create mode 100644 code/modules/spacepods/lock_buster.dm diff --git a/_maps/map_files/cyberiad/cyberiad.dmm b/_maps/map_files/cyberiad/cyberiad.dmm index 47df198e5b8..aab249117a5 100644 --- a/_maps/map_files/cyberiad/cyberiad.dmm +++ b/_maps/map_files/cyberiad/cyberiad.dmm @@ -464,7 +464,7 @@ "aiV" = (/obj/structure/cable{d1 = 1; d2 = 2; icon_state = "1-2"; tag = ""},/turf/simulated/floor/plasteel,/area/security/armoury) "aiW" = (/obj/structure/rack,/obj/item/weapon/storage/box/seccarts{pixel_x = 3; pixel_y = 2},/obj/item/weapon/storage/box/handcuffs,/obj/item/weapon/storage/box/flashbangs{pixel_x = -2; pixel_y = -2},/obj/machinery/atmospherics/pipe/simple/hidden/supply,/obj/item/weapon/storage/box/handcuffs,/obj/effect/decal/warning_stripes/red/hollow,/turf/simulated/floor/plasteel{icon_state = "floorgrime"},/area/security/armoury) "aiX" = (/obj/structure/rack,/obj/item/clothing/mask/gas{pixel_x = 3; pixel_y = 3},/obj/item/clothing/mask/gas{pixel_x = 3; pixel_y = 3},/obj/item/clothing/mask/gas,/obj/item/clothing/mask/gas,/obj/item/clothing/mask/gas{pixel_x = -3; pixel_y = -3},/obj/item/clothing/mask/gas{pixel_x = -3; pixel_y = -3},/obj/effect/decal/warning_stripes/red/hollow,/turf/simulated/floor/plasteel{icon_state = "floorgrime"},/area/security/armoury) -"aiY" = (/obj/structure/table,/obj/effect/decal/warning_stripes/red/hollow,/obj/item/weapon/storage/toolbox/mechanical,/turf/simulated/floor/plasteel{icon_state = "floorgrime"},/area/security/armoury) +"aiY" = (/obj/structure/table,/obj/effect/decal/warning_stripes/red/hollow,/obj/item/weapon/storage/toolbox/mechanical,/obj/item/device/lock_buster,/turf/simulated/floor/plasteel{icon_state = "floorgrime"},/area/security/armoury) "aiZ" = (/obj/machinery/recharger/wallcharger{pixel_x = -25; pixel_y = 0},/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers{dir = 6},/obj/structure/cable{d1 = 2; d2 = 4; icon_state = "2-4"; tag = ""},/obj/machinery/light{dir = 8},/turf/simulated/floor/plasteel{icon_state = "red"; dir = 8},/area/security/main) "aja" = (/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers{dir = 9},/obj/structure/cable{d1 = 1; d2 = 8; icon_state = "1-8"; tag = ""},/turf/simulated/floor/plasteel,/area/security/main) "ajb" = (/obj/machinery/atmospherics/pipe/simple/hidden/supply{dir = 5},/turf/simulated/floor/plasteel,/area/security/main) @@ -7063,7 +7063,7 @@ "cFQ" = (/obj/structure/rack{dir = 8; layer = 2.9},/obj/item/clothing/shoes/magboots,/obj/item/clothing/suit/space/rig/engineering,/obj/item/clothing/mask/breath,/obj/item/clothing/head/helmet/space/rig/engineering,/obj/machinery/firealarm{dir = 2; pixel_y = 24},/turf/simulated/floor/plasteel,/area/engine/hardsuitstorage) "cFR" = (/obj/machinery/power/apc{dir = 4; name = "CE Office APC"; pixel_x = 24; pixel_y = 0; shock_proof = 1},/obj/structure/cable{d2 = 8; icon_state = "0-8"},/turf/simulated/floor/plasteel{dir = 8; icon_state = "neutralfull"},/area/engine/chiefs_office) "cFS" = (/obj/effect/spawner/window/reinforced,/obj/structure/cable{icon_state = "0-2"; pixel_y = 1; d2 = 2},/turf/simulated/floor/plating,/area/engine/chiefs_office) -"cFT" = (/obj/machinery/keycard_auth{pixel_x = 0; pixel_y = 24},/obj/structure/table/reinforced,/obj/item/weapon/rcd,/obj/item/weapon/rcd_ammo,/obj/item/weapon/rcd_ammo,/obj/item/weapon/rcd_ammo,/obj/item/weapon/rcd_ammo,/obj/item/weapon/rcd_ammo,/obj/item/weapon/rcd_ammo,/obj/item/weapon/stock_parts/cell/high{charge = 100; maxcharge = 15000},/obj/item/weapon/stock_parts/cell/high{charge = 100; maxcharge = 15000},/obj/item/clothing/glasses/meson{pixel_y = 4},/obj/item/device/megaphone,/mob/living/simple_animal/parrot/Poly,/turf/simulated/floor/plasteel{dir = 8; icon_state = "neutralfull"},/area/engine/chiefs_office) +"cFT" = (/obj/machinery/keycard_auth{pixel_x = 0; pixel_y = 24},/obj/structure/table/reinforced,/obj/item/weapon/rcd,/obj/item/weapon/rcd_ammo,/obj/item/weapon/rcd_ammo,/obj/item/weapon/rcd_ammo,/obj/item/weapon/rcd_ammo,/obj/item/weapon/rcd_ammo,/obj/item/weapon/rcd_ammo,/obj/item/weapon/stock_parts/cell/high{charge = 100; maxcharge = 15000},/obj/item/weapon/stock_parts/cell/high{charge = 100; maxcharge = 15000},/obj/item/clothing/glasses/meson{pixel_y = 4},/obj/item/device/megaphone,/obj/item/device/lock_buster,/mob/living/simple_animal/parrot/Poly,/turf/simulated/floor/plasteel{dir = 8; icon_state = "neutralfull"},/area/engine/chiefs_office) "cFU" = (/obj/machinery/atmospherics/unary/vent_scrubber{dir = 8; on = 1; scrub_N2O = 1; scrub_Toxins = 1},/obj/structure/closet/firecloset,/obj/machinery/requests_console{department = "Atmospherics"; departmentType = 3; name = "Atmospherics Requests Console"; pixel_x = -30},/turf/simulated/floor/plasteel,/area/atmos) "cFV" = (/obj/machinery/door_control{id = "atmos"; name = "Atmospherics Lockdown"; pixel_x = 10; pixel_y = 24; req_access_txt = "24"},/obj/machinery/door_control{desc = "A remote control-switch for the engineering security doors."; id = "Engineering"; name = "Engineering Lockdown"; pixel_x = -10; pixel_y = 24; req_access_txt = "10"},/obj/machinery/door_control{desc = "A remote control-switch for secure storage."; id = "Secure Storage"; name = "Engineering Secure Storage"; pixel_x = 0; pixel_y = 24; req_access_txt = "11"},/obj/machinery/light_switch{pixel_y = 38},/obj/machinery/atmospherics/unary/vent_pump{dir = 1; external_pressure_bound = 101; on = 1; pressure_checks = 1},/turf/simulated/floor/plasteel{dir = 8; icon_state = "neutralfull"},/area/engine/chiefs_office) "cFW" = (/turf/simulated/floor/plasteel{dir = 8; icon_state = "neutralfull"},/area/engine/chiefs_office) diff --git a/code/modules/spacepods/lock_buster.dm b/code/modules/spacepods/lock_buster.dm new file mode 100644 index 00000000000..276386d89a6 --- /dev/null +++ b/code/modules/spacepods/lock_buster.dm @@ -0,0 +1,13 @@ +/obj/item/device/lock_buster + name = "pod lock buster" + desc = "Destroys a podlock in mere seconds once applied. Waranty void if used." + icon_state = "lock_buster_off" + var/on = 0 + +/obj/item/device/lock_buster/attack_self(mob/user as mob) + on = !on + if(on) + icon_state = "lock_buster_on" + else + icon_state = "lock_buster_off" + to_chat(usr, "You turn the [src] [on ? "on" : "off"].") \ No newline at end of file diff --git a/code/modules/spacepods/spacepod.dm b/code/modules/spacepods/spacepod.dm index c1c4fc3def9..2f1a9e592d1 100644 --- a/code/modules/spacepods/spacepod.dm +++ b/code/modules/spacepods/spacepod.dm @@ -320,6 +320,24 @@ to_chat(user, "\blue \The [src] is fully repaired!") return + if(istype(W, /obj/item/device/lock_buster)) + var/obj/item/device/lock_buster/L = W + if(L.on & equipment_system.lock_system) + user.visible_message(user, "[user] is drilling through the [src]'s lock!", + "You start drilling through the [src]'s lock!") + if(do_after(user, 100, target = src)) + qdel(equipment_system.lock_system) + equipment_system.lock_system = null + user.visible_message(user, "[user] has destroyed the [src]'s lock!", + "You destroy the [src]'s lock!") + else + user.visible_message(user, "[user] fails to break through the [src]'s lock!", + "You were unable to break through the [src]'s lock!") + return + else + to_chat(user, "Turn the [L] on first.") + return + if(cargo_hold.storage_slots > 0 && !hatch_open && unlocked) // must be the last option as all items not listed prior will be stored cargo_hold.attackby(W, user, params) return @@ -604,7 +622,7 @@ obj/spacepod/proc/add_equipment(mob/user, var/obj/item/device/spacepod_equipment return 0 if(passengers.len < max_passengers) visible_message("[user.name] starts loading [M.name] into the pod!") - if(do_after(user, 50, M)) + if(do_after(user, 50, target = M)) moved_other_inside(M) if(M == user) @@ -829,7 +847,7 @@ obj/spacepod/proc/add_equipment(mob/user, var/obj/item/device/spacepod_equipment set src = usr.loc var/mob/user = usr to_chat(user, "You start rooting around under the seat for lost items") - if(do_after(user, 40, src)) + if(do_after(user, 40, target = src)) var/obj/badlist = list(internal_tank, cargo_hold, pilot, battery) + equipment_system.get_list() var/list/true_contents = contents - badlist if(true_contents.len > 0) diff --git a/icons/obj/device.dmi b/icons/obj/device.dmi index 46a4a9743164a928d73eaf9cdb3a1ddf089e0773..3874da51a6470c19339c894fbdaf46489a65e729 100644 GIT binary patch delta 13654 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 diff --git a/paradise.dme b/paradise.dme index b609a2fc55f..8b24cc343ce 100644 --- a/paradise.dme +++ b/paradise.dme @@ -1967,6 +1967,7 @@ #include "code\modules\space_transition\space_transition.dm" #include "code\modules\spacepods\construction.dm" #include "code\modules\spacepods\equipment.dm" +#include "code\modules\spacepods\lock_buster.dm" #include "code\modules\spacepods\parts.dm" #include "code\modules\spacepods\pod_fabricator.dm" #include "code\modules\spacepods\spacepod.dm" From b1bef10909f598779cd61e1de299149cd99201d6 Mon Sep 17 00:00:00 2001 From: monster860 Date: Sun, 15 May 2016 10:17:26 -0400 Subject: [PATCH 049/343] Fix shuttle HREF exploit --- code/modules/shuttle/shuttle.dm | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/code/modules/shuttle/shuttle.dm b/code/modules/shuttle/shuttle.dm index 2a794de2ff8..bf07626ffc2 100644 --- a/code/modules/shuttle/shuttle.dm +++ b/code/modules/shuttle/shuttle.dm @@ -683,7 +683,13 @@ to_chat(usr, "Access denied.") return + var/list/options = params2list(possible_destinations) if(href_list["move"]) + if(!options.Find(href_list["move"])) //I see you're trying Href exploits, I see you're failing, I SEE ADMIN WARNING. + // Seriously, though, NEVER trust a Topic with something like this. Ever. + message_admins("move HREF ([src] attempted to move to: [href_list["move"]]) exploit attempted by [key_name_admin(usr)] on [src] (JMP)") + to_chat(usr, "Expect a ban. Soon.") + return switch(shuttle_master.moveShuttle(shuttleId, href_list["move"], 1)) if(0) to_chat(usr, "Shuttle received message and will be sent shortly.") From f58887fa1f61ce818270b377efa583002005db3c Mon Sep 17 00:00:00 2001 From: monster860 Date: Sun, 15 May 2016 10:30:19 -0400 Subject: [PATCH 050/343] removes the fun part --- code/modules/shuttle/shuttle.dm | 1 - 1 file changed, 1 deletion(-) diff --git a/code/modules/shuttle/shuttle.dm b/code/modules/shuttle/shuttle.dm index bf07626ffc2..119378d53f4 100644 --- a/code/modules/shuttle/shuttle.dm +++ b/code/modules/shuttle/shuttle.dm @@ -688,7 +688,6 @@ if(!options.Find(href_list["move"])) //I see you're trying Href exploits, I see you're failing, I SEE ADMIN WARNING. // Seriously, though, NEVER trust a Topic with something like this. Ever. message_admins("move HREF ([src] attempted to move to: [href_list["move"]]) exploit attempted by [key_name_admin(usr)] on [src] (JMP)") - to_chat(usr, "Expect a ban. Soon.") return switch(shuttle_master.moveShuttle(shuttleId, href_list["move"], 1)) if(0) From de63af38de4c6e5891cf116de0eb3e3a24624903 Mon Sep 17 00:00:00 2001 From: ParadiseSS13-Bot Date: Sun, 15 May 2016 18:30:58 -0400 Subject: [PATCH 051/343] Automatic changelog generation for PR #4427 --- html/changelogs/AutoChangeLog-pr-4427.yml | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 html/changelogs/AutoChangeLog-pr-4427.yml diff --git a/html/changelogs/AutoChangeLog-pr-4427.yml b/html/changelogs/AutoChangeLog-pr-4427.yml new file mode 100644 index 00000000000..fdec7855212 --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-4427.yml @@ -0,0 +1,4 @@ +author: AugRob +delete-after: True +changes: + - rscadd: "Add screwdriver sound when opening/closing panels on airlocks" From 230b220d5cb2f5b5c7c95354dfc0ba92798f059a Mon Sep 17 00:00:00 2001 From: HugoLuman Date: Sun, 15 May 2016 17:51:44 -0700 Subject: [PATCH 052/343] Addresses https://github.com/ParadiseSS13/Paradise/issues/4434 Makes the description for the dehydrated space carp in the syndicate uplink menu more accurate and informative. It now reads: "Just add water to make your very own hostile to everything space carp. It looks just like a plushie. The first person to squeeze it will be registered as its owner, who it will not attack. If no owner is registered, it'll just attack everyone." The previous description did not provide players enough information to use the item correctly. :cl:HugoLuman fix: Makes dehydrated space carp description more accurate and informative /:cl: --- code/datums/uplink_item.dm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/datums/uplink_item.dm b/code/datums/uplink_item.dm index 7b30a0bb9a6..9345c51379f 100644 --- a/code/datums/uplink_item.dm +++ b/code/datums/uplink_item.dm @@ -699,7 +699,7 @@ var/list/uplink_items = list() /datum/uplink_item/stealthy_weapons/dehy_carp name = "Dehydrated Space Carp" - desc = "Just add water to make your very own hostile to everything space carp. It looks just like a plushie." + desc = "Just add water to make your very own hostile to everything space carp. It looks just like a plushie. \The first person to squeeze it will be registered as its owner, who it will not attack. If no owner is registered, it'll just attack everyone." reference = "DSC" item = /obj/item/toy/carpplushie/dehy_carp cost = 3 From 718caa3f69294397dde573333c160b749bb70fa5 Mon Sep 17 00:00:00 2001 From: HugoLuman Date: Sun, 15 May 2016 19:48:43 -0700 Subject: [PATCH 053/343] Removes "\The" No more erroneous ``\The``s I didn't touch all the ``\`` that aren't ``\n`` though, I don't know how or why it's like that or what it would do if I went through and changed it. --- code/datums/uplink_item.dm | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/code/datums/uplink_item.dm b/code/datums/uplink_item.dm index 9345c51379f..327ac67c801 100644 --- a/code/datums/uplink_item.dm +++ b/code/datums/uplink_item.dm @@ -644,7 +644,7 @@ var/list/uplink_items = list() /datum/uplink_item/stealthy_weapons/sleepy_pen name = "Sleepy Pen" - desc = "A syringe disguised as a functional pen. It's filled with a potent anaesthetic. \The pen holds two doses of the mixture. The pen can be refilled." + desc = "A syringe disguised as a functional pen. It's filled with a potent anaesthetic. \ The pen holds two doses of the mixture. The pen can be refilled." reference = "SP" item = /obj/item/weapon/pen/sleepy cost = 8 @@ -699,7 +699,7 @@ var/list/uplink_items = list() /datum/uplink_item/stealthy_weapons/dehy_carp name = "Dehydrated Space Carp" - desc = "Just add water to make your very own hostile to everything space carp. It looks just like a plushie. \The first person to squeeze it will be registered as its owner, who it will not attack. If no owner is registered, it'll just attack everyone." + desc = "Just add water to make your very own hostile to everything space carp. It looks just like a plushie. The first person to squeeze it will be registered as its owner, who it will not attack. If no owner is registered, it'll just attack everyone." reference = "DSC" item = /obj/item/toy/carpplushie/dehy_carp cost = 3 From cc8cfe8ab681ebeb6bafd9a1d0c1a4d53ba27adb Mon Sep 17 00:00:00 2001 From: Tigercat2000 Date: Mon, 16 May 2016 04:05:03 -0700 Subject: [PATCH 054/343] Abductor probing console human icon fixes the lack of occupant icon on the probing console --- .../abduction/machinery/experiment.dm | 20 +++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/code/game/gamemodes/miniantags/abduction/machinery/experiment.dm b/code/game/gamemodes/miniantags/abduction/machinery/experiment.dm index 44b37ed22e5..8adf07a60ba 100644 --- a/code/game/gamemodes/miniantags/abduction/machinery/experiment.dm +++ b/code/game/gamemodes/miniantags/abduction/machinery/experiment.dm @@ -43,12 +43,28 @@ experimentUI(user) +/obj/machinery/abductor/experiment/proc/dissection_icon(mob/living/carbon/human/H) + var/icon/I = icon(H.stand_icon) + + var/icon/splat = icon(H.species.damage_overlays, "30") + splat.Blend(icon(H.species.damage_mask, "torso"), ICON_MULTIPLY) + splat.Blend(H.species.blood_color, ICON_MULTIPLY) + I.Blend(splat, ICON_OVERLAY) + + return I + /obj/machinery/abductor/experiment/proc/experimentUI(mob/user) var/dat dat += "

Experiment

" if(occupant) - dat += "
" - dat += "" + var/icon/H = icon(dissection_icon(occupant), dir = SOUTH) + if(H) + user << browse_rsc(H, "dissection_img.png") + dat += "
" + dat += "" + dat += "" + else + dat += "ERR: Unable to retrieve image data for occupant." dat += "Probe
" dat += "Dissect
" dat += "Analyze
" From 2190c9ed340e108078ac92aebf6e68454e9ac6db Mon Sep 17 00:00:00 2001 From: Vivalas Date: Mon, 16 May 2016 14:18:01 -0500 Subject: [PATCH 055/343] Fixes #3993 --- code/modules/research/xenoarchaeology/finds/finds_misc.dm | 1 - 1 file changed, 1 deletion(-) diff --git a/code/modules/research/xenoarchaeology/finds/finds_misc.dm b/code/modules/research/xenoarchaeology/finds/finds_misc.dm index 68293501b77..e94049a74f1 100644 --- a/code/modules/research/xenoarchaeology/finds/finds_misc.dm +++ b/code/modules/research/xenoarchaeology/finds/finds_misc.dm @@ -25,7 +25,6 @@ return /obj/item/weapon/shard/plasma/attackby(obj/item/weapon/W as obj, mob/user as mob, params) - ..() if ( istype(W, /obj/item/weapon/weldingtool)) var/obj/item/weapon/weldingtool/WT = W if(WT.remove_fuel(0, user)) From 7e9334a5481d6a5f75e2734e1c90cd19b2515905 Mon Sep 17 00:00:00 2001 From: monster860 Date: Mon, 16 May 2016 15:24:22 -0400 Subject: [PATCH 056/343] remove gcircuit and plaque --- code/game/objects/items/devices/floor_painter.dm | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/code/game/objects/items/devices/floor_painter.dm b/code/game/objects/items/devices/floor_painter.dm index 91d2ce6011d..7fa9759e330 100644 --- a/code/game/objects/items/devices/floor_painter.dm +++ b/code/game/objects/items/devices/floor_painter.dm @@ -16,9 +16,9 @@ var/static/list/allowed_states = list("arrival", "arrivalcorner", "bar", "barber", "blackcorner", "blue", "bluecorner", "bluefull", "bluered", "blueyellow", "blueyellowfull", "bot", "brown", "browncorner", "browncornerold", "brownold", "cafeteria", "caution", "cautioncorner", "chapel", "cmo", "dark", "delivery", "escape", "escapecorner", "floor", - "freezerfloor", "gcircuit", "green", "greenblue", "greenbluefull", "greencorner", "greenfull", "greenyellow", + "freezerfloor", "green", "greenblue", "greenbluefull", "greencorner", "greenfull", "greenyellow", "greenyellowfull", "grimy", "loadingarea", "neutral", "neutralcorner", "neutralfull", "orange", "orangecorner", - "orangefull", "plaque", "purple", "purplecorner", "purplefull", "rampbottom", "ramptop", "red", "redblue", "redbluefull", + "orangefull", "purple", "purplecorner", "purplefull", "rampbottom", "ramptop", "red", "redblue", "redbluefull", "redcorner", "redfull", "redgreen", "redgreenfull", "redyellow", "redyellowfull", "warning", "warningcorner", "warnwhite", "warnwhitecorner", "white", "whiteblue", "whitebluecorner", "whitebluefull", "whitebot", "whitecorner", "whitedelivery", "whitegreen", "whitegreencorner", "whitegreenfull", "whitehall", "whitepurple", "whitepurplecorner", "whitepurplefull", From 683fca467b5337621dbfba4a46865e18c6f1689c Mon Sep 17 00:00:00 2001 From: ParadiseSS13-Bot Date: Mon, 16 May 2016 20:15:41 -0400 Subject: [PATCH 057/343] Automatic changelog generation for PR #4423 --- html/changelogs/AutoChangeLog-pr-4423.yml | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 html/changelogs/AutoChangeLog-pr-4423.yml diff --git a/html/changelogs/AutoChangeLog-pr-4423.yml b/html/changelogs/AutoChangeLog-pr-4423.yml new file mode 100644 index 00000000000..c59bf34afcb --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-4423.yml @@ -0,0 +1,4 @@ +author: Fox McCloud +delete-after: True +changes: + - tweak: "Fixes and improves foam to better interact with reagents" From 1ff24812c178a2add6267f9977d427c14a023f17 Mon Sep 17 00:00:00 2001 From: HugoLuman Date: Mon, 16 May 2016 18:59:17 -0700 Subject: [PATCH 058/343] Refactors examine code to make disguising a humanoid's species possible with s string specified in clothing item definitions. Cardborg disguises now say their wearer is "a high-tech robot!" when they are examined. Also, makes ABSTRACT flagged gear invisible on examination. Signed-off-by: HugoLuman --- code/modules/clothing/clothing.dm | 1 + code/modules/clothing/head/misc_special.dm | 1 + code/modules/clothing/suits/miscellaneous.dm | 1 + .../mob/living/carbon/human/examine.dm | 31 +++++++++++-------- 4 files changed, 21 insertions(+), 13 deletions(-) diff --git a/code/modules/clothing/clothing.dm b/code/modules/clothing/clothing.dm index 04f0f3ed42d..8d6595b73ff 100644 --- a/code/modules/clothing/clothing.dm +++ b/code/modules/clothing/clothing.dm @@ -25,6 +25,7 @@ var/active_sound = null var/toggle_cooldown = null var/cooldown = 0 + var/species_disguise = null //BS12: Species-restricted clothing check. /obj/item/clothing/mob_can_equip(M as mob, slot) diff --git a/code/modules/clothing/head/misc_special.dm b/code/modules/clothing/head/misc_special.dm index 071c6032722..8bda5f4c30f 100644 --- a/code/modules/clothing/head/misc_special.dm +++ b/code/modules/clothing/head/misc_special.dm @@ -216,6 +216,7 @@ item_state = "cardborg_h" flags = HEADCOVERSEYES | HEADCOVERSMOUTH flags_inv = HIDEMASK|HIDEEARS|HIDEEYES|HIDEFACE + species_disguise = "High-tech robot" /obj/item/clothing/head/cardborg/equipped(mob/living/user, slot) ..() diff --git a/code/modules/clothing/suits/miscellaneous.dm b/code/modules/clothing/suits/miscellaneous.dm index 5abc5e86cbf..7985eb06b57 100644 --- a/code/modules/clothing/suits/miscellaneous.dm +++ b/code/modules/clothing/suits/miscellaneous.dm @@ -206,6 +206,7 @@ item_state = "cardborg" body_parts_covered = UPPER_TORSO|LOWER_TORSO flags_inv = HIDEJUMPSUIT + species_disguise = "High-tech robot" /obj/item/clothing/suit/cardborg/equipped(mob/living/user, slot) ..() diff --git a/code/modules/mob/living/carbon/human/examine.dm b/code/modules/mob/living/carbon/human/examine.dm index 714e9c45146..69eb172d4fe 100644 --- a/code/modules/mob/living/carbon/human/examine.dm +++ b/code/modules/mob/living/carbon/human/examine.dm @@ -56,17 +56,22 @@ var/list/nospecies = list("Abductor", "Shadowling", "Neara", "Monkey", "Stok", "Farwa", "Wolpin") //species that won't show their race no matter what - if (skipjumpsuit && skipface || (species.name in nospecies)) //either obscured or on the nospecies list - msg += "!\n" //omit the species when examining - else if (species.name == "Slime People") //snowflakey because Slime People are defined as a plural + var/displayed_species = get_species() + for(var/obj/item/clothing/C in src) + if(C.species_disguise) + displayed_species = C.species_disguise + else continue + if (skipjumpsuit && skipface || (displayed_species in nospecies)) //either obscured or on the nospecies list + msg += "!\n" //omit the species when examining + else if (displayed_species == "Slime People") //snowflakey because Slime People are defined as a plural msg += ", a slime person!\n" - else if (species.name == "Unathi") //DAMN YOU, VOWELS + else if (displayed_species == "Unathi") //DAMN YOU, VOWELS msg += ", a unathi!\n" else - msg += ", \a [lowertext(species.name)]!\n" + msg += ", \a [lowertext(displayed_species)]!\n" //uniform - if(w_uniform && !skipjumpsuit) + if(w_uniform && !skipjumpsuit && !(w_uniform.flags & ABSTRACT)) //Ties var/tie_msg if(istype(w_uniform,/obj/item/clothing/under)) @@ -80,14 +85,14 @@ msg += "[t_He] [t_is] wearing \icon[w_uniform] \a [w_uniform][tie_msg].\n" //head - if(head) + if(head && !(head.flags & ABSTRACT)) if(head.blood_DNA) msg += "[t_He] [t_is] wearing \icon[head] [head.gender==PLURAL?"some":"a"] [head.blood_color != "#030303" ? "blood-stained":"oil-stained"] [head.name] on [t_his] head!\n" else msg += "[t_He] [t_is] wearing \icon[head] \a [head] on [t_his] head.\n" //suit/armour - if(wear_suit) + if(wear_suit && !(wear_suit.flags & ABSTRACT)) if(wear_suit.blood_DNA) msg += "[t_He] [t_is] wearing \icon[wear_suit] [wear_suit.gender==PLURAL?"some":"a"] [wear_suit.blood_color != "#030303" ? "blood-stained":"oil-stained"] [wear_suit.name]!\n" else @@ -101,7 +106,7 @@ msg += "[t_He] [t_is] carrying \icon[s_store] \a [s_store] on [t_his] [wear_suit.name].\n" //back - if(back) + if(back && !(back.flags & ABSTRACT)) if(back.blood_DNA) msg += "[t_He] [t_has] \icon[back] [back.gender==PLURAL?"some":"a"] [back.blood_color != "#030303" ? "blood-stained":"oil-stained"] [back] on [t_his] back.\n" else @@ -122,7 +127,7 @@ msg += "[t_He] [t_is] holding \icon[r_hand] \a [r_hand] in [t_his] right hand.\n" //gloves - if(gloves && !skipgloves) + if(gloves && !skipgloves && !(gloves.flags & ABSTRACT)) if(gloves.blood_DNA) msg += "[t_He] [t_has] \icon[gloves] [gloves.gender==PLURAL?"some":"a"] [gloves.blood_color != "#030303" ? "blood-stained":"oil-stained"] [gloves.name] on [t_his] hands!\n" else @@ -147,7 +152,7 @@ msg += "[t_He] [t_has] \icon[belt] \a [belt] about [t_his] waist.\n" //shoes - if(shoes && !skipshoes) + if(shoes && !skipshoes && !(shoes.flags & ABSTRACT)) if(shoes.blood_DNA) msg += "[t_He] [t_is] wearing \icon[shoes] [shoes.gender==PLURAL?"some":"a"] [shoes.blood_color != "#030303" ? "blood-stained":"oil-stained"] [shoes.name] on [t_his] feet!\n" else @@ -157,14 +162,14 @@ //mask - if(wear_mask && !skipmask) + if(wear_mask && !skipmask && !(wear_mask.flags & ABSTRACT)) if(wear_mask.blood_DNA) msg += "[t_He] [t_has] \icon[wear_mask] [wear_mask.gender==PLURAL?"some":"a"] [wear_mask.blood_color != "#030303" ? "blood-stained":"oil-stained"] [wear_mask.name] on [t_his] face!\n" else msg += "[t_He] [t_has] \icon[wear_mask] \a [wear_mask] on [t_his] face.\n" //eyes - if(glasses && !skipeyes) + if(glasses && !skipeyes && !(glasses.flags & ABSTRACT)) if(glasses.blood_DNA) msg += "[t_He] [t_has] \icon[glasses] [glasses.gender==PLURAL?"some":"a"] [glasses.blood_color != "#030303" ? "blood-stained":"oil-stained"] [glasses] covering [t_his] eyes!\n" else From 0d49138c94dd1155cb34196e0b364cab7446ccd6 Mon Sep 17 00:00:00 2001 From: Aurorablade Date: Tue, 17 May 2016 00:31:53 -0400 Subject: [PATCH 059/343] changelog --- html/changelog.html | 38 +++++++++++++++++++++++ html/changelogs/.all_changelog.yml | 35 +++++++++++++++++++++ html/changelogs/AutoChangeLog-pr-4231.yml | 4 --- html/changelogs/AutoChangeLog-pr-4331.yml | 14 --------- html/changelogs/AutoChangeLog-pr-4375.yml | 4 --- html/changelogs/AutoChangeLog-pr-4391.yml | 6 ---- html/changelogs/AutoChangeLog-pr-4401.yml | 4 --- html/changelogs/AutoChangeLog-pr-4407.yml | 4 --- html/changelogs/AutoChangeLog-pr-4415.yml | 4 --- html/changelogs/AutoChangeLog-pr-4423.yml | 4 --- html/changelogs/AutoChangeLog-pr-4427.yml | 4 --- 11 files changed, 73 insertions(+), 48 deletions(-) delete mode 100644 html/changelogs/AutoChangeLog-pr-4231.yml delete mode 100644 html/changelogs/AutoChangeLog-pr-4331.yml delete mode 100644 html/changelogs/AutoChangeLog-pr-4375.yml delete mode 100644 html/changelogs/AutoChangeLog-pr-4391.yml delete mode 100644 html/changelogs/AutoChangeLog-pr-4401.yml delete mode 100644 html/changelogs/AutoChangeLog-pr-4407.yml delete mode 100644 html/changelogs/AutoChangeLog-pr-4415.yml delete mode 100644 html/changelogs/AutoChangeLog-pr-4423.yml delete mode 100644 html/changelogs/AutoChangeLog-pr-4427.yml diff --git a/html/changelog.html b/html/changelog.html index 102d0b0136d..00c5ed89885 100644 --- a/html/changelog.html +++ b/html/changelog.html @@ -55,6 +55,44 @@ -->
+

17 May 2016

+

AugRob updated:

+
    +
  • Add screwdriver sound when opening/closing panels on airlocks
  • +
+

Fox MCCloud updated:

+
    +
  • Removes "harm" traitor objective
  • +
  • Increases non-escape/hijack/die objectives from 1 to 2
  • +
  • Tweaks available objectives to traitors a bit
  • +
+

Fox McCloud updated:

+
    +
  • Players can no longer see how many players have readied up or who has readied up
  • +
  • Hulks, Shadowlings, and Golems can no longer use laserpointers
  • +
  • Adds in the ability to flip over someone with *flip
  • +
  • Fixes and improves foam to better interact with reagents
  • +
+

KasparoVy updated:

+
    +
  • Refactors hair so it's on the head (organ).
  • +
  • Adjusts some Vox hair style names so they're consistent with all others.
  • +
  • Refactors Morph and the order by which options are presented.
  • +
  • Players with heads of a different species than the body will now only be able to access the head accessories, hair/facial hair styles of the head's species.
  • +
  • Fixes some typos.
  • +
  • Fixes a bug where hairgrownium made you bald and super hairgrownium only changed the hair/facial hair styles of Humans.
  • +
  • Fixes a bug where Morph wouldn't correctly set eye colour or skin tone.
  • +
  • Fixes a typo that didn't really have any negative effect on the beard organ to begin with.
  • +
  • Fixes bugs where Alopecia and Facial Hypertrichosis disease symptoms wouldn't update player sprite correctly.
  • +
  • Adds a new Vox hairstyle.
  • +
  • You can now change your head accessory (and its colour), body markings (and their colour), and body accessory if you're a species that has such things via the Morph genetic power and C.M.A. (the bathroom SalonPro Nano-Mirrors and admin verbs).
  • +
+

monster860 updated:

+
    +
  • Fixes sleep() in telecomms
  • +
  • Windows can now be constructed and deconstructed using RCD's.
  • +
+

10 May 2016

Crazylemon64 updated: