diff --git a/baystation12.dme b/baystation12.dme index 52a2cd5319..4851c962cb 100644 --- a/baystation12.dme +++ b/baystation12.dme @@ -396,7 +396,6 @@ #include "code\game\machinery\embedded_controller\docking_program_multi.dm" #include "code\game\machinery\embedded_controller\embedded_controller_base.dm" #include "code\game\machinery\embedded_controller\embedded_program_base.dm" -#include "code\game\machinery\embedded_controller\escape_pod_docking_controller.dm" #include "code\game\machinery\embedded_controller\simple_docking_controller.dm" #include "code\game\machinery\kitchen\gibber.dm" #include "code\game\machinery\kitchen\juicer.dm" @@ -487,6 +486,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\lightreplacer.dm" #include "code\game\objects\items\devices\megaphone.dm" #include "code\game\objects\items\devices\modkit.dm" @@ -746,6 +746,7 @@ #include "code\modules\client\client defines.dm" #include "code\modules\client\client procs.dm" #include "code\modules\client\preferences.dm" +#include "code\modules\client\preferences_factions.dm" #include "code\modules\client\preferences_gear.dm" #include "code\modules\client\preferences_savefile.dm" #include "code\modules\client\preferences_spawnpoints.dm" @@ -1324,6 +1325,7 @@ #include "code\modules\shieldgen\shield_gen_external.dm" #include "code\modules\shuttles\antagonist.dm" #include "code\modules\shuttles\departmental.dm" +#include "code\modules\shuttles\escape_pods.dm" #include "code\modules\shuttles\shuttle.dm" #include "code\modules\shuttles\shuttle_console.dm" #include "code\modules\shuttles\shuttle_emergency.dm" diff --git a/code/WorkInProgress/computer3/NTOS.dm b/code/WorkInProgress/computer3/NTOS.dm index 86157dcc1c..5119084f0e 100644 --- a/code/WorkInProgress/computer3/NTOS.dm +++ b/code/WorkInProgress/computer3/NTOS.dm @@ -210,6 +210,9 @@ if("viewperipheral" in href_list) // open drive, show status of peripheral var/obj/item/part/computer/C = locate(href_list["viewperipheral"]) + if(!istype(C) || (C.loc != src.computer)) + return + if(istype(C,/obj/item/part/computer/storage)) current = C interact() diff --git a/code/WorkInProgress/computer3/computers/camera.dm b/code/WorkInProgress/computer3/computers/camera.dm index 0883680f5c..193070ce3e 100644 --- a/code/WorkInProgress/computer3/computers/camera.dm +++ b/code/WorkInProgress/computer3/computers/camera.dm @@ -258,10 +258,11 @@ if("show" in href_list) var/obj/machinery/camera/C = locate(href_list["show"]) - current = C - usr.reset_view(C) - interact() - return + if(istype(C) && C.status) + current = C + usr.reset_view(C) + interact() + return if("keyselect" in href_list) current = null @@ -278,4 +279,4 @@ // Atlantis: Required for camnetkeys to work. /datum/file/program/security/hidden - hidden_file = 1 \ No newline at end of file + hidden_file = 1 diff --git a/code/WorkInProgress/computer3/computers/medical.dm b/code/WorkInProgress/computer3/computers/medical.dm index 7fc5da1232..f1d5018bc0 100644 --- a/code/WorkInProgress/computer3/computers/medical.dm +++ b/code/WorkInProgress/computer3/computers/medical.dm @@ -263,7 +263,7 @@ switch(href_list["field"]) if("fingerprint") if (istype(src.active1, /datum/data/record)) - var/t1 = copytext(sanitize(input("Please input fingerprint hash:", "Med. records", src.active1.fields["fingerprint"], null) as text),1,MAX_MESSAGE_LEN) + var/t1 = copytext(trim(sanitize(input("Please input fingerprint hash:", "Med. records", src.active1.fields["fingerprint"], null) as text)),1,MAX_MESSAGE_LEN) if ((!( t1 ) || !( src.authenticated ) || usr.stat || usr.restrained() || (!interactable() && (!istype(usr, /mob/living/silicon))) || src.active1 != a1)) return src.active1.fields["fingerprint"] = t1 @@ -281,55 +281,55 @@ src.active1.fields["age"] = t1 if("mi_dis") if (istype(src.active2, /datum/data/record)) - var/t1 = copytext(sanitize(input("Please input minor disabilities list:", "Med. records", src.active2.fields["mi_dis"], null) as text),1,MAX_MESSAGE_LEN) + var/t1 = copytext(trim(sanitize(input("Please input minor disabilities list:", "Med. records", src.active2.fields["mi_dis"], null) as text)),1,MAX_MESSAGE_LEN) if ((!( t1 ) || !( src.authenticated ) || usr.stat || usr.restrained() || (!interactable() && (!istype(usr, /mob/living/silicon))) || src.active2 != a2)) return src.active2.fields["mi_dis"] = t1 if("mi_dis_d") if (istype(src.active2, /datum/data/record)) - var/t1 = copytext(sanitize(input("Please summarize minor dis.:", "Med. records", src.active2.fields["mi_dis_d"], null) as message),1,MAX_MESSAGE_LEN) + var/t1 = copytext(trim(sanitize(input("Please summarize minor dis.:", "Med. records", src.active2.fields["mi_dis_d"], null) as message)),1,MAX_MESSAGE_LEN) if ((!( t1 ) || !( src.authenticated ) || usr.stat || usr.restrained() || (!interactable() && (!istype(usr, /mob/living/silicon))) || src.active2 != a2)) return src.active2.fields["mi_dis_d"] = t1 if("ma_dis") if (istype(src.active2, /datum/data/record)) - var/t1 = copytext(sanitize(input("Please input major diabilities list:", "Med. records", src.active2.fields["ma_dis"], null) as text),1,MAX_MESSAGE_LEN) + var/t1 = copytext(trim(sanitize(input("Please input major diabilities list:", "Med. records", src.active2.fields["ma_dis"], null) as text)),1,MAX_MESSAGE_LEN) if ((!( t1 ) || !( src.authenticated ) || usr.stat || usr.restrained() || (!interactable() && (!istype(usr, /mob/living/silicon))) || src.active2 != a2)) return src.active2.fields["ma_dis"] = t1 if("ma_dis_d") if (istype(src.active2, /datum/data/record)) - var/t1 = copytext(sanitize(input("Please summarize major dis.:", "Med. records", src.active2.fields["ma_dis_d"], null) as message),1,MAX_MESSAGE_LEN) + var/t1 = copytext(trim(sanitize(input("Please summarize major dis.:", "Med. records", src.active2.fields["ma_dis_d"], null) as message)),1,MAX_MESSAGE_LEN) if ((!( t1 ) || !( src.authenticated ) || usr.stat || usr.restrained() || (!interactable() && (!istype(usr, /mob/living/silicon))) || src.active2 != a2)) return src.active2.fields["ma_dis_d"] = t1 if("alg") if (istype(src.active2, /datum/data/record)) - var/t1 = copytext(sanitize(input("Please state allergies:", "Med. records", src.active2.fields["alg"], null) as text),1,MAX_MESSAGE_LEN) + var/t1 = copytext(trim(sanitize(input("Please state allergies:", "Med. records", src.active2.fields["alg"], null) as text)),1,MAX_MESSAGE_LEN) if ((!( t1 ) || !( src.authenticated ) || usr.stat || usr.restrained() || (!interactable() && (!istype(usr, /mob/living/silicon))) || src.active2 != a2)) return src.active2.fields["alg"] = t1 if("alg_d") if (istype(src.active2, /datum/data/record)) - var/t1 = copytext(sanitize(input("Please summarize allergies:", "Med. records", src.active2.fields["alg_d"], null) as message),1,MAX_MESSAGE_LEN) + var/t1 = copytext(trim(sanitize(input("Please summarize allergies:", "Med. records", src.active2.fields["alg_d"], null) as message)),1,MAX_MESSAGE_LEN) if ((!( t1 ) || !( src.authenticated ) || usr.stat || usr.restrained() || (!interactable() && (!istype(usr, /mob/living/silicon))) || src.active2 != a2)) return src.active2.fields["alg_d"] = t1 if("cdi") if (istype(src.active2, /datum/data/record)) - var/t1 = copytext(sanitize(input("Please state diseases:", "Med. records", src.active2.fields["cdi"], null) as text),1,MAX_MESSAGE_LEN) + var/t1 = copytext(trim(sanitize(input("Please state diseases:", "Med. records", src.active2.fields["cdi"], null) as text)),1,MAX_MESSAGE_LEN) if ((!( t1 ) || !( src.authenticated ) || usr.stat || usr.restrained() || (!interactable() && (!istype(usr, /mob/living/silicon))) || src.active2 != a2)) return src.active2.fields["cdi"] = t1 if("cdi_d") if (istype(src.active2, /datum/data/record)) - var/t1 = copytext(sanitize(input("Please summarize diseases:", "Med. records", src.active2.fields["cdi_d"], null) as message),1,MAX_MESSAGE_LEN) + var/t1 = copytext(trim(sanitize(input("Please summarize diseases:", "Med. records", src.active2.fields["cdi_d"], null) as message)),1,MAX_MESSAGE_LEN) if ((!( t1 ) || !( src.authenticated ) || usr.stat || usr.restrained() || (!interactable() && (!istype(usr, /mob/living/silicon))) || src.active2 != a2)) return src.active2.fields["cdi_d"] = t1 if("notes") if (istype(src.active2, /datum/data/record)) - var/t1 = copytext(html_encode(input("Please summarize notes:", "Med. records", html_decode(src.active2.fields["notes"]), null) as message),1,MAX_MESSAGE_LEN) + var/t1 = copytext(html_encode(trim(input("Please summarize notes:", "Med. records", html_decode(src.active2.fields["notes"]), null) as message)),1,MAX_MESSAGE_LEN) if ((!( t1 ) || !( src.authenticated ) || usr.stat || usr.restrained() || (!interactable() && (!istype(usr, /mob/living/silicon))) || src.active2 != a2)) return src.active2.fields["notes"] = t1 @@ -343,22 +343,22 @@ if (istype(src.active2, /datum/data/record)) src.temp = text("Blood Type:
\n\tA- A+
\n\tB- B+
\n\tAB- AB+
\n\tO- O+
", src, src, src, src, src, src, src, src) if("b_dna") - if (istype(src.active1, /datum/data/record)) - var/t1 = copytext(sanitize(input("Please input DNA hash:", "Med. records", src.active1.fields["dna"], null) as text),1,MAX_MESSAGE_LEN) - if ((!( t1 ) || !( src.authenticated ) || usr.stat || usr.restrained() || (!interactable() && (!istype(usr, /mob/living/silicon))) || src.active1 != a1)) + if (istype(src.active2, /datum/data/record)) + var/t1 = copytext(sanitize(trim(input("Please input DNA hash:", "Med. records", src.active2.fields["b_dna"], null) as text)),1,MAX_MESSAGE_LEN) + if ((!( t1 ) || !( src.authenticated ) || usr.stat || usr.restrained() || (!interactable() && (!istype(usr, /mob/living/silicon))) || src.active2 != a2)) return - src.active1.fields["dna"] = t1 + src.active2.fields["b_dna"] = t1 if("vir_name") var/datum/data/record/v = locate(href_list["edit_vir"]) if (v) - var/t1 = copytext(sanitize(input("Please input pathogen name:", "VirusDB", v.fields["name"], null) as text),1,MAX_MESSAGE_LEN) + var/t1 = copytext(trim(sanitize(input("Please input pathogen name:", "VirusDB", v.fields["name"], null) as text)),1,MAX_MESSAGE_LEN) if ((!( t1 ) || !( src.authenticated ) || usr.stat || usr.restrained() || (!interactable() && (!istype(usr, /mob/living/silicon))) || src.active1 != a1)) return v.fields["name"] = t1 if("vir_desc") var/datum/data/record/v = locate(href_list["edit_vir"]) if (v) - var/t1 = copytext(sanitize(input("Please input information about pathogen:", "VirusDB", v.fields["description"], null) as message),1,MAX_MESSAGE_LEN) + var/t1 = copytext(trim(sanitize(input("Please input information about pathogen:", "VirusDB", v.fields["description"], null) as message)),1,MAX_MESSAGE_LEN) if ((!( t1 ) || !( src.authenticated ) || usr.stat || usr.restrained() || (!interactable() && (!istype(usr, /mob/living/silicon))) || src.active1 != a1)) return v.fields["description"] = t1 diff --git a/code/WorkInProgress/computer3/computers/prisoner.dm b/code/WorkInProgress/computer3/computers/prisoner.dm index 3ec29a5480..11aa5ebd6e 100644 --- a/code/WorkInProgress/computer3/computers/prisoner.dm +++ b/code/WorkInProgress/computer3/computers/prisoner.dm @@ -73,25 +73,29 @@ if(href_list["inject1"]) var/obj/item/weapon/implant/I = locate(href_list["inject1"]) - if(I) I.activate(1) + if(istype(I)) + I.activate(1) else if(href_list["inject5"]) var/obj/item/weapon/implant/I = locate(href_list["inject5"]) - if(I) I.activate(5) + if(istype(I)) + I.activate(5) else if(href_list["inject10"]) var/obj/item/weapon/implant/I = locate(href_list["inject10"]) - if(I) I.activate(10) + if(istype(I)) + I.activate(10) else if(href_list["lock"]) screen = !screen else if(href_list["warn"]) - var/warning = copytext(sanitize(input(usr,"Message:","Enter your message here!","")),1,MAX_MESSAGE_LEN) + var/warning = trim(copytext(sanitize(input(usr,"Message:","Enter your message here!","")),1,MAX_MESSAGE_LEN)) if(!warning) return var/obj/item/weapon/implant/I = locate(href_list["warn"]) - if((I)&&(I.imp_in)) + if( istype(I) && I.imp_in) var/mob/living/carbon/R = I.imp_in + log_say("PrisonComputer3 message: [key_name(usr)]->[key_name(R)] : [warning]") R << "\green You hear a voice in your head saying: '[warning]'" interact() diff --git a/code/WorkInProgress/computer3/computers/security.dm b/code/WorkInProgress/computer3/computers/security.dm index f193b07139..f4682a8d50 100644 --- a/code/WorkInProgress/computer3/computers/security.dm +++ b/code/WorkInProgress/computer3/computers/security.dm @@ -467,19 +467,19 @@ What a mess.*/ switch(href_list["field"]) if("name") if (istype(active1, /datum/data/record)) - var/t1 = input("Please input name:", "Secure. records", active1.fields["name"], null) as text + var/t1 = reject_bad_name(input("Please input name:", "Secure. records", active1.fields["name"], null) as text) if ((!( t1 ) || !length(trim(t1)) || !( authenticated ) || usr.stat || usr.restrained() || (!interactable() && (!istype(usr, /mob/living/silicon)))) || active1 != a1) return active1.fields["name"] = t1 if("id") if (istype(active2, /datum/data/record)) - var/t1 = copytext(sanitize(input("Please input id:", "Secure. records", active1.fields["id"], null) as text),1,MAX_MESSAGE_LEN) + var/t1 = copytext(trim(sanitize(input("Please input id:", "Secure. records", active1.fields["id"], null) as text)),1,MAX_MESSAGE_LEN) if ((!( t1 ) || !( authenticated ) || usr.stat || usr.restrained() || (!interactable() && (!istype(usr, /mob/living/silicon))) || active1 != a1)) return active1.fields["id"] = t1 if("fingerprint") if (istype(active1, /datum/data/record)) - var/t1 = copytext(sanitize(input("Please input fingerprint hash:", "Secure. records", active1.fields["fingerprint"], null) as text),1,MAX_MESSAGE_LEN) + var/t1 = copytext(trim(sanitize(input("Please input fingerprint hash:", "Secure. records", active1.fields["fingerprint"], null) as text)),1,MAX_MESSAGE_LEN) if ((!( t1 ) || !( authenticated ) || usr.stat || usr.restrained() || (!interactable() && (!istype(usr, /mob/living/silicon))) || active1 != a1)) return active1.fields["fingerprint"] = t1 @@ -497,31 +497,31 @@ What a mess.*/ active1.fields["age"] = t1 if("mi_crim") if (istype(active2, /datum/data/record)) - var/t1 = copytext(sanitize(input("Please input minor disabilities list:", "Secure. records", active2.fields["mi_crim"], null) as text),1,MAX_MESSAGE_LEN) + var/t1 = copytext(trim(sanitize(input("Please input minor disabilities list:", "Secure. records", active2.fields["mi_crim"], null) as text)),1,MAX_MESSAGE_LEN) if ((!( t1 ) || !( authenticated ) || usr.stat || usr.restrained() || (!interactable() && (!istype(usr, /mob/living/silicon))) || active2 != a2)) return active2.fields["mi_crim"] = t1 if("mi_crim_d") if (istype(active2, /datum/data/record)) - var/t1 = copytext(sanitize(input("Please summarize minor dis.:", "Secure. records", active2.fields["mi_crim_d"], null) as message),1,MAX_MESSAGE_LEN) + var/t1 = copytext(trim(sanitize(input("Please summarize minor dis.:", "Secure. records", active2.fields["mi_crim_d"], null) as message)),1,MAX_MESSAGE_LEN) if ((!( t1 ) || !( authenticated ) || usr.stat || usr.restrained() || (!interactable() && (!istype(usr, /mob/living/silicon))) || active2 != a2)) return active2.fields["mi_crim_d"] = t1 if("ma_crim") if (istype(active2, /datum/data/record)) - var/t1 = copytext(sanitize(input("Please input major diabilities list:", "Secure. records", active2.fields["ma_crim"], null) as text),1,MAX_MESSAGE_LEN) + var/t1 = copytext(trim(sanitize(input("Please input major diabilities list:", "Secure. records", active2.fields["ma_crim"], null) as text)),1,MAX_MESSAGE_LEN) if ((!( t1 ) || !( authenticated ) || usr.stat || usr.restrained() || (!interactable() && (!istype(usr, /mob/living/silicon))) || active2 != a2)) return active2.fields["ma_crim"] = t1 if("ma_crim_d") if (istype(active2, /datum/data/record)) - var/t1 = copytext(sanitize(input("Please summarize major dis.:", "Secure. records", active2.fields["ma_crim_d"], null) as message),1,MAX_MESSAGE_LEN) + var/t1 = copytext(trim(sanitize(input("Please summarize major dis.:", "Secure. records", active2.fields["ma_crim_d"], null) as message)),1,MAX_MESSAGE_LEN) if ((!( t1 ) || !( authenticated ) || usr.stat || usr.restrained() || (!interactable() && (!istype(usr, /mob/living/silicon))) || active2 != a2)) return active2.fields["ma_crim_d"] = t1 if("notes") if (istype(active2, /datum/data/record)) - var/t1 = copytext(html_encode(input("Please summarize notes:", "Secure. records", html_decode(active2.fields["notes"]), null) as message),1,MAX_MESSAGE_LEN) + var/t1 = copytext(html_encode(trim(input("Please summarize notes:", "Secure. records", html_decode(active2.fields["notes"]), null) as message)),1,MAX_MESSAGE_LEN) if ((!( t1 ) || !( authenticated ) || usr.stat || usr.restrained() || (!interactable() && (!istype(usr, /mob/living/silicon))) || active2 != a2)) return active2.fields["notes"] = t1 diff --git a/code/WorkInProgress/computer3/program.dm b/code/WorkInProgress/computer3/program.dm index 4c977489f5..74083b8ffd 100644 --- a/code/WorkInProgress/computer3/program.dm +++ b/code/WorkInProgress/computer3/program.dm @@ -239,7 +239,7 @@ Programs are a file that can be executed // if("runfile" in href_list) var/datum/file/F = locate(href_list["runfile"]) - if(F && F.computer == computer) + if(istype(F) && F.computer == computer) F.execute(src) return 1 diff --git a/code/__HELPERS/icons.dm b/code/__HELPERS/icons.dm index e7a6bbba96..34fdfdc3ae 100644 --- a/code/__HELPERS/icons.dm +++ b/code/__HELPERS/icons.dm @@ -635,7 +635,7 @@ The _flatIcons list is a cache for generated icon files. */ proc // Creates a single icon from a given /atom or /image. Only the first argument is required. - getFlatIcon(image/A, defdir=A.dir, deficon=A.icon, defstate=A.icon_state, defblend=A.blend_mode) + getFlatIcon(image/A, defdir=2, deficon=null, defstate="", defblend=BLEND_DEFAULT) // We start with a blank canvas, otherwise some icon procs crash silently var/icon/flat = icon('icons/effects/effects.dmi', "icon_state"="nothing") // Final flattened icon if(!A) diff --git a/code/controllers/master_controller.dm b/code/controllers/master_controller.dm index 9a097030d5..0777c6aa41 100644 --- a/code/controllers/master_controller.dm +++ b/code/controllers/master_controller.dm @@ -113,6 +113,11 @@ datum/controller/game_controller/proc/setup_objects() asteroid_ore_map = new /datum/ore_distribution() asteroid_ore_map.populate_distribution_map() + //Shitty hack to fix mining turf overlays, for some reason New() is not being called. + for(var/turf/simulated/floor/plating/airless/asteroid/T in world) + T.updateMineralOverlays() + T.name = "asteroid" + //Set up spawn points. populate_spawn_points() @@ -301,7 +306,7 @@ datum/controller/game_controller/proc/process_machines_power() //check if the area has power for M's channel //this will keep stat updated in case the machine is moved from one area to another. M.power_change(A) //we've already made sure A is a master area, above. - + if(!(M.stat & NOPOWER) && M.use_power) M.auto_use_power() diff --git a/code/datums/mind.dm b/code/datums/mind.dm index 621b1b6bb9..34dc2e1344 100644 --- a/code/datums/mind.dm +++ b/code/datums/mind.dm @@ -665,7 +665,7 @@ datum/mind if("tome") var/mob/living/carbon/human/H = current if (istype(H)) - var/obj/item/weapon/tome/T = new(H) + var/obj/item/weapon/book/tome/T = new(H) var/list/slots = list ( "backpack" = slot_in_backpack, @@ -1129,7 +1129,7 @@ datum/mind var/mob/living/carbon/human/H = current if (istype(H)) - var/obj/item/weapon/tome/T = new(H) + var/obj/item/weapon/book/tome/T = new(H) var/list/slots = list ( "backpack" = slot_in_backpack, diff --git a/code/datums/supplypacks.dm b/code/datums/supplypacks.dm index 1e267e524f..f0e0e31644 100755 --- a/code/datums/supplypacks.dm +++ b/code/datums/supplypacks.dm @@ -235,7 +235,7 @@ var/list/all_supply_groups = list("Operations","Security","Hospitality","Enginee /datum/supply_packs/cargotrain name = "Cargo Train Tug" contains = list(/obj/vehicle/train/cargo/engine) - cost = 30 + cost = 45 containertype = /obj/structure/largecrate containername = "Cargo Train Tug Crate" group = "Operations" @@ -243,7 +243,7 @@ var/list/all_supply_groups = list("Operations","Security","Hospitality","Enginee /datum/supply_packs/cargotrailer name = "Cargo Train Trolley" contains = list(/obj/vehicle/train/cargo/trolley) - cost = 20 + cost = 15 containertype = /obj/structure/largecrate containername = "Cargo Train Trolley Crate" group = "Operations" diff --git a/code/game/gamemodes/cult/cult_items.dm b/code/game/gamemodes/cult/cult_items.dm index 1d2ae0061b..f6aa21e14d 100644 --- a/code/game/gamemodes/cult/cult_items.dm +++ b/code/game/gamemodes/cult/cult_items.dm @@ -57,7 +57,7 @@ item_state = "cultrobes" flags = FPRINT | TABLEPASS body_parts_covered = UPPER_TORSO|LOWER_TORSO|LEGS|ARMS - allowed = list(/obj/item/weapon/tome,/obj/item/weapon/melee/cultblade) + allowed = list(/obj/item/weapon/book/tome,/obj/item/weapon/melee/cultblade) armor = list(melee = 50, bullet = 30, laser = 50,energy = 20, bomb = 25, bio = 10, rad = 0) flags_inv = HIDEJUMPSUIT siemens_coefficient = 0 @@ -80,12 +80,11 @@ item_state = "magusred" flags = FPRINT | TABLEPASS body_parts_covered = UPPER_TORSO|LOWER_TORSO|LEGS|FEET|ARMS|HANDS - allowed = list(/obj/item/weapon/tome,/obj/item/weapon/melee/cultblade) + allowed = list(/obj/item/weapon/book/tome,/obj/item/weapon/melee/cultblade) armor = list(melee = 50, bullet = 30, laser = 50,energy = 20, bomb = 25, bio = 10, rad = 0) flags_inv = HIDEGLOVES|HIDESHOES|HIDEJUMPSUIT siemens_coefficient = 0 - /obj/item/clothing/head/helmet/space/cult name = "cult helmet" desc = "A space worthy helmet used by the followers of Nar-Sie" @@ -101,7 +100,7 @@ item_state = "cult_armour" desc = "A bulky suit of armour, bristling with spikes. It looks space proof." w_class = 3 - allowed = list(/obj/item/weapon/tome,/obj/item/weapon/melee/cultblade,/obj/item/weapon/tank/emergency_oxygen,/obj/item/device/suit_cooling_unit) + allowed = list(/obj/item/weapon/book/tome,/obj/item/weapon/melee/cultblade,/obj/item/weapon/tank/emergency_oxygen,/obj/item/device/suit_cooling_unit) slowdown = 1 armor = list(melee = 60, bullet = 50, laser = 30,energy = 15, bomb = 30, bio = 30, rad = 30) siemens_coefficient = 0 diff --git a/code/game/gamemodes/cult/ritual.dm b/code/game/gamemodes/cult/ritual.dm index 24f3ba27c7..e60795f5fd 100644 --- a/code/game/gamemodes/cult/ritual.dm +++ b/code/game/gamemodes/cult/ritual.dm @@ -91,7 +91,7 @@ var/engwords = list("travel", "blood", "join", "hell", "destroy", "technology", attackby(I as obj, user as mob) - if(istype(I, /obj/item/weapon/tome) && iscultist(user)) + if(istype(I, /obj/item/weapon/book/tome) && iscultist(user)) user << "You retrace your steps, carefully undoing the lines of the rune." del(src) return @@ -178,13 +178,15 @@ var/engwords = list("travel", "blood", "join", "hell", "destroy", "technology", check_icon() icon = get_uristrune_cult(word1, word2, word3) -/obj/item/weapon/tome +/obj/item/weapon/book/tome name = "arcane tome" + icon = 'icons/obj/weapons.dmi' icon_state ="tome" throw_speed = 1 throw_range = 5 w_class = 2.0 flags = FPRINT | TABLEPASS + unique = 1 var/notedat = "" var/tomedat = "" var/list/words = list("ire" = "ire", "ego" = "ego", "nahlizet" = "nahlizet", "certum" = "certum", "veri" = "veri", "jatkaa" = "jatkaa", "balaq" = "balaq", "mgar" = "mgar", "karazet" = "karazet", "geeri" = "geeri") @@ -313,7 +315,7 @@ var/engwords = list("travel", "blood", "join", "hell", "destroy", "technology", [words[10]] is [words[words[10]]] Clear
"} usr << browse("[notedat]", "window=notes") -// call(/obj/item/weapon/tome/proc/edit_notes)() +// call(/obj/item/weapon/book/tome/proc/edit_notes)() else usr << browse(null, "window=notes") return @@ -408,7 +410,7 @@ var/engwords = list("travel", "blood", "join", "hell", "destroy", "technology", [words[9]] is [words[words[9]]] Clear
[words[10]] is [words[words[10]]] Clear
"} -// call(/obj/item/weapon/tome/proc/edit_notes)() +// call(/obj/item/weapon/book/tome/proc/edit_notes)() user << browse("[notedat]", "window=notes") return if(usr.get_active_hand() != src) @@ -493,8 +495,8 @@ var/engwords = list("travel", "blood", "join", "hell", "destroy", "technology", user << "The book seems full of illegible scribbles. Is this a joke?" return - attackby(obj/item/weapon/tome/T as obj, mob/living/user as mob) - if(istype(T, /obj/item/weapon/tome)) // sanity check to prevent a runtime error + attackby(obj/item/weapon/book/tome/T as obj, mob/living/user as mob) + if(istype(T, /obj/item/weapon/book/tome)) // sanity check to prevent a runtime error switch(alert("Copy the runes from your tome?",,"Copy", "Cancel")) if("cancel") return @@ -515,7 +517,7 @@ var/engwords = list("travel", "blood", "join", "hell", "destroy", "technology", else usr << "The scriptures of Nar-Sie, The One Who Sees, The Geometer of Blood. Contains the details of every ritual his followers could think of. Most of these are useless, though." -/obj/item/weapon/tome/imbued //admin tome, spawns working runes without waiting +/obj/item/weapon/book/tome/imbued //admin tome, spawns working runes without waiting w_class = 2.0 var/cultistsonly = 1 attack_self(mob/user as mob) diff --git a/code/game/gamemodes/cult/runes.dm b/code/game/gamemodes/cult/runes.dm index 3da1dd8d25..14b253f415 100644 --- a/code/game/gamemodes/cult/runes.dm +++ b/code/game/gamemodes/cult/runes.dm @@ -87,9 +87,9 @@ var/list/sacrificed = list() "\red You are blinded by the flash of red light! After you're able to see again, you see that now instead of the rune there's a book.", \ "\red You hear a pop and smell ozone.") if(istype(src,/obj/effect/rune)) - new /obj/item/weapon/tome(src.loc) + new /obj/item/weapon/book/tome(src.loc) else - new /obj/item/weapon/tome(usr.loc) + new /obj/item/weapon/book/tome(usr.loc) del(src) return @@ -775,6 +775,7 @@ var/list/sacrificed = list() for(var/mob/living/carbon/C in orange(1,src)) if(iscultist(C) && !C.stat) users+=C + var/dam = round(15 / users.len) if(users.len>=3) var/mob/living/carbon/cultist = input("Choose the one who you want to free", "Followers of Geometer") as null|anything in (cultists - users) if(!cultist) @@ -804,7 +805,7 @@ var/list/sacrificed = list() if(istype(cultist.loc, /obj/machinery/dna_scannernew)&&cultist.loc:locked) cultist.loc:locked = 0 for(var/mob/living/carbon/C in users) - user.take_overall_damage(15, 0) + user.take_overall_damage(dam, 0) C.say("Khari[pick("'","`")]d! Gual'te nikka!") del(src) return fizzle() @@ -820,7 +821,7 @@ var/list/sacrificed = list() var/list/mob/living/carbon/users = new for(var/mob/living/carbon/C in orange(1,src)) if(iscultist(C) && !C.stat) - users+=C + users += C if(users.len>=3) var/mob/living/carbon/cultist = input("Choose the one who you want to summon", "Followers of Geometer") as null|anything in (cultists - user) if(!cultist) @@ -833,10 +834,16 @@ var/list/sacrificed = list() cultist.loc = src.loc cultist.lying = 1 cultist.regenerate_icons() - for(var/mob/living/carbon/human/C in orange(1,src)) + + var/dam = round(25 / (users.len/2)) //More people around the rune less damage everyone takes. Minimum is 3 cultists + + for(var/mob/living/carbon/human/C in users) if(iscultist(C) && !C.stat) C.say("N'ath reth sh'yro eth d[pick("'","`")]rekkathnor!") - C.take_overall_damage(25, 0) + C.take_overall_damage(dam, 0) + if(users.len <= 4) // You did the minimum, this is going to hurt more and we're going to stun you. + C.apply_effect(rand(3,6), STUN) + C.apply_effect(1, WEAKEN) user.visible_message("\red Rune disappears with a flash of red light, and in its place now a body lies.", \ "\red You are blinded by the flash of red light! After you're able to see again, you see that now instead of the rune there's a body.", \ "\red You hear a pop and smell ozone.") diff --git a/code/game/gamemodes/events/ninja_equipment.dm b/code/game/gamemodes/events/ninja_equipment.dm index f2f62581f8..787f2cf93e 100644 --- a/code/game/gamemodes/events/ninja_equipment.dm +++ b/code/game/gamemodes/events/ninja_equipment.dm @@ -510,7 +510,7 @@ ________________________________________________________________________________ var/damage = min(cell.charge, rand(50,150))//Uses either the current energy left over or between 50 and 150. if(damage>1)//So they don't spam it when energy is a factor. spark_system.start()//SPARKS THERE SHALL BE SPARKS - U.electrocute_act(damage, src,0.1,1)//The last argument is a safety for the human proc that checks for gloves. + U.electrocute_act(damage, src, 0.1) if(cell.charge < damage) cell.use(cell.charge) else diff --git a/code/game/gamemodes/gameticker.dm b/code/game/gamemodes/gameticker.dm index 0c8a7aa8bd..797afab1d4 100644 --- a/code/game/gamemodes/gameticker.dm +++ b/code/game/gamemodes/gameticker.dm @@ -297,6 +297,7 @@ var/global/datum/controller/gameticker/ticker captainless=0 if(player.mind.assigned_role != "MODE") job_master.EquipRank(player, player.mind.assigned_role, 0) + UpdateFactionList(player) EquipCustomItems(player) if(captainless) for(var/mob/M in player_list) diff --git a/code/game/jobs/job/civilian.dm b/code/game/jobs/job/civilian.dm index ee0a20a33a..3d83666a46 100644 --- a/code/game/jobs/job/civilian.dm +++ b/code/game/jobs/job/civilian.dm @@ -171,7 +171,7 @@ selection_color = "#dddddd" access = list(access_maint_tunnels, access_mailsorting, access_cargo, access_cargo_bot, access_qm, access_mint, access_mining, access_mining_station) minimal_access = list(access_mining, access_mint, access_mining_station, access_mailsorting) - + alt_titles = list("Drill Technician","Prospector") equip(var/mob/living/carbon/human/H) if(!H) return 0 diff --git a/code/game/jobs/job_controller.dm b/code/game/jobs/job_controller.dm index d0600b4cca..580d4f0fac 100644 --- a/code/game/jobs/job_controller.dm +++ b/code/game/jobs/job_controller.dm @@ -355,7 +355,7 @@ var/global/datum/controller/occupations/job_master if(job) //Equip custom gear loadout. - if(H.client.prefs.gear && H.client.prefs.gear.len) + if(H.client.prefs.gear && H.client.prefs.gear.len && job.title != "Cyborg" && job.title != "AI") for(var/thing in H.client.prefs.gear) var/datum/gear/G = gear_datums[thing] diff --git a/code/game/machinery/atmoalter/meter.dm b/code/game/machinery/atmoalter/meter.dm index 1e3c9961e6..9c26fa4a4e 100644 --- a/code/game/machinery/atmoalter/meter.dm +++ b/code/game/machinery/atmoalter/meter.dm @@ -65,9 +65,16 @@ ) radio_connection.post_signal(src, signal) -/obj/machinery/meter/proc/status() - var/t = "" - if (src.target) +/obj/machinery/meter/examine() + var/t = "A gas flow meter. " + + if(get_dist(usr, src) > 3 && !(istype(usr, /mob/living/silicon/ai) || istype(usr, /mob/dead))) + t += "\blue You are too far away to read it." + + else if(stat & (NOPOWER|BROKEN)) + t += "\red The display is off." + + else if(src.target) var/datum/gas_mixture/environment = target.return_air() if(environment) t += "The pressure gauge reads [round(environment.return_pressure(), 0.01)] kPa; [round(environment.temperature,0.01)]°K ([round(environment.temperature-T0C,0.01)]°C)" @@ -75,31 +82,16 @@ t += "The sensor error light is blinking." else t += "The connect error light is blinking." - return t - -/obj/machinery/meter/examine() - set src in view(3) - - var/t = "A gas flow meter. " - t += status() + usr << t - - /obj/machinery/meter/Click() - if(stat & (NOPOWER|BROKEN)) + if(istype(usr, /mob/living/silicon/ai)) // ghosts can call ..() for examine + examine() return 1 - - var/t = null - if (get_dist(usr, src) <= 3 || istype(usr, /mob/living/silicon/ai) || istype(usr, /mob/dead)) - t += status() - else - usr << "\blue You are too far away." - return 1 - - usr << t - return 1 + + return ..() /obj/machinery/meter/attackby(var/obj/item/weapon/W as obj, var/mob/user as mob) if (!istype(W, /obj/item/weapon/wrench)) diff --git a/code/game/machinery/computer/medical.dm b/code/game/machinery/computer/medical.dm index 3898593172..18f1ca059f 100644 --- a/code/game/machinery/computer/medical.dm +++ b/code/game/machinery/computer/medical.dm @@ -333,11 +333,11 @@ if (istype(src.active2, /datum/data/record)) src.temp = text("Blood Type:
\n\tA- A+
\n\tB- B+
\n\tAB- AB+
\n\tO- O+
", src, src, src, src, src, src, src, src) if("b_dna") - if (istype(src.active1, /datum/data/record)) - var/t1 = copytext(trim(sanitize(input("Please input DNA hash:", "Med. records", src.active1.fields["dna"], null) as text)),1,MAX_MESSAGE_LEN) - if ((!( t1 ) || !( src.authenticated ) || usr.stat || usr.restrained() || (!in_range(src, usr) && (!istype(usr, /mob/living/silicon))) || src.active1 != a1)) + if (istype(src.active2, /datum/data/record)) + var/t1 = copytext(trim(sanitize(input("Please input DNA hash:", "Med. records", src.active2.fields["b_dna"], null) as text)),1,MAX_MESSAGE_LEN) + if ((!( t1 ) || !( src.authenticated ) || usr.stat || usr.restrained() || (!in_range(src, usr) && (!istype(usr, /mob/living/silicon))) || src.active2 != a2)) return - src.active1.fields["dna"] = t1 + src.active2.fields["b_dna"] = t1 if("vir_name") var/datum/data/record/v = locate(href_list["edit_vir"]) if (v) diff --git a/code/game/machinery/computer/message.dm b/code/game/machinery/computer/message.dm index 60e7ac0484..120e274e63 100644 --- a/code/game/machinery/computer/message.dm +++ b/code/game/machinery/computer/message.dm @@ -19,7 +19,7 @@ var/noserver = "ALERT: No server detected." var/incorrectkey = "ALERT: Incorrect decryption key!" var/defaultmsg = "Welcome. Please select an option." - var/rebootmsg = "%$&(£: Critical %$$@ Error // !RestArting! - ?pLeaSe wAit!" + var/rebootmsg = "%$&(£: Critical %$$@ Error // !RestArting! - ?pLeaSe wAit!" //Computer properties var/screen = 0 // 0 = Main menu, 1 = Message Logs, 2 = Hacked screen, 3 = Custom Message var/hacking = 0 // Is it being hacked into by the AI/Cyborg @@ -36,6 +36,7 @@ /obj/machinery/computer/message_monitor/attackby(obj/item/weapon/O as obj, mob/living/user as mob) if(stat & (NOPOWER|BROKEN)) + ..() return if(!istype(user)) return @@ -52,7 +53,7 @@ var/obj/item/weapon/paper/monitorkey/MK = new/obj/item/weapon/paper/monitorkey MK.loc = src.loc // Will help make emagging the console not so easy to get away with. - MK.info += "

£%@%(*$%&(£&?*(%&£/{}" + MK.info += "

£%@%(*$%&(£&?*(%&£/{}" spawn(100*length(src.linkedServer.decryptkey)) UnmagConsole() message = rebootmsg else diff --git a/code/game/machinery/computer/robot.dm b/code/game/machinery/computer/robot.dm index 30c5a3cd9b..f8029b0e96 100644 --- a/code/game/machinery/computer/robot.dm +++ b/code/game/machinery/computer/robot.dm @@ -197,7 +197,10 @@ else if (href_list["magbot"]) if(src.allowed(usr)) var/mob/living/silicon/robot/R = locate(href_list["magbot"]) - if(R) + + // whatever weirdness this is supposed to be, but that is how the href gets added, so here it is again + if(istype(R) && istype(usr, /mob/living/silicon) && usr.mind.special_role && (usr.mind.original == usr) && !R.emagged) + var/choice = input("Are you certain you wish to hack [R.name]?") in list("Confirm", "Abort") if(choice == "Confirm") if(R && istype(R)) @@ -225,4 +228,4 @@ if(!R.scrambledcodes && !istype(R, /mob/living/silicon/robot/drone)) R.self_destruct() - return \ No newline at end of file + return diff --git a/code/game/machinery/cryopod.dm b/code/game/machinery/cryopod.dm index ce9749402d..50b17ddc33 100644 --- a/code/game/machinery/cryopod.dm +++ b/code/game/machinery/cryopod.dm @@ -152,7 +152,8 @@ var/global/list/frozen_items = list() /obj/item/clothing/suit, /obj/item/clothing/shoes/magboots, /obj/item/blueprints, - /obj/item/clothing/head/helmet/space/ + /obj/item/clothing/head/helmet/space, + /obj/item/weapon/storage/internal ) /obj/machinery/cryopod/right @@ -186,6 +187,8 @@ var/global/list/frozen_items = list() if(W.contents.len) //Make sure we catch anything not handled by del() on the items. for(var/obj/item/O in W.contents) + if(istype(O,/obj/item/weapon/storage/internal)) //Stop eating pockets you fuck! + continue O.loc = src //Delete all items not on the preservation list. @@ -194,6 +197,7 @@ var/global/list/frozen_items = list() items -= announce // or the autosay radio. for(var/obj/item/W in items) + var/preserve = null for(var/T in preserve_items) if(istype(W,T)) @@ -204,11 +208,14 @@ var/global/list/frozen_items = list() del(W) else frozen_items += W + W.loc = null //Update any existing objectives involving this mob. for(var/datum/objective/O in all_objectives) - if(istype(O,/datum/objective/mutiny) && O.target == occupant.mind) //We don't want revs to get objectives that aren't for heads of staff. Letting them win or lose based on cryo is silly so we remove the objective. - del(O) //TODO: Update rev objectives on login by head (may happen already?) ~ Z + // We don't want revs to get objectives that aren't for heads of staff. Letting + // them win or lose based on cryo is silly so we remove the objective. + if(istype(O,/datum/objective/mutiny) && O.target == occupant.mind) + del(O) else if(O.target && istype(O.target,/datum/mind)) if(O.target == occupant.mind) if(O.owner && O.owner.current) diff --git a/code/game/machinery/teleporter.dm b/code/game/machinery/teleporter.dm index f9bc8d879b..b247f17919 100644 --- a/code/game/machinery/teleporter.dm +++ b/code/game/machinery/teleporter.dm @@ -17,6 +17,7 @@ return /obj/machinery/computer/teleporter/initialize() + ..() var/obj/machinery/teleport/station/station = locate(/obj/machinery/teleport/station, get_step(src, dir)) var/obj/machinery/teleport/hub/hub if(station) diff --git a/code/game/machinery/vending.dm b/code/game/machinery/vending.dm index 1c18c33263..ac3b09ff6a 100644 --- a/code/game/machinery/vending.dm +++ b/code/game/machinery/vending.dm @@ -789,7 +789,7 @@ icon_state = "cigs" products = list(/obj/item/weapon/storage/fancy/cigarettes = 10,/obj/item/weapon/storage/box/matches = 10,/obj/item/weapon/lighter/random = 4) contraband = list(/obj/item/weapon/lighter/zippo = 4) - premium = list(/obj/item/clothing/mask/cigarette/cigar/havana = 2) + premium = list(/obj/item/weapon/storage/fancy/cigar = 5) prices = list(/obj/item/weapon/storage/fancy/cigarettes = 15,/obj/item/weapon/storage/box/matches = 1,/obj/item/weapon/lighter/random = 2) diff --git a/code/game/objects/effects/chemsmoke.dm b/code/game/objects/effects/chemsmoke.dm index 4c245b78cc..fb9b049a3e 100644 --- a/code/game/objects/effects/chemsmoke.dm +++ b/code/game/objects/effects/chemsmoke.dm @@ -224,24 +224,25 @@ pending += location while(pending.len) - for(var/turf/simulated/current in pending) + for(var/turf/current in pending) for(var/D in cardinal) - var/turf/simulated/target = get_step(current, D) - + var/turf/target = get_step(current, D) if(wallList) if(istype(target, /turf/simulated/wall)) if(!(target in wallList)) wallList += target continue - if(!target.zone) - continue + if(target in pending) continue if(target in complete) continue if(!(target in targetTurfs)) continue - + if(current.c_airblock(target)) //this is needed to stop chemsmoke from passing through thin window walls + continue + if(target.c_airblock(current)) + continue pending += target pending -= current @@ -249,4 +250,4 @@ targetTurfs = complete - return \ No newline at end of file + return 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 0000000000..ebb1111429 --- /dev/null +++ b/code/game/objects/items/devices/floor_painter.dm @@ -0,0 +1,209 @@ +/obj/item/device/floor_painter + name = "floor painter" + icon = 'icons/obj/bureaucracy.dmi' + icon_state = "labeler1" + item_state = "flight" + + var/mode_nice = "standard" + var/mode = "floor" + var/tile_dir_mode = 0 + + // mode 0 ignore direction; sets dir=0 + // mode 1 all-direction + // mode 2 corner selecting the side CW from the selected corner + // mode 3 cardinal + // mode 4 warningcorner and warnwhitecorner direction fix + // mode 5 Opposite corner tiles where the second icon_state is "[mode]_inv" +/obj/item/device/floor_painter/afterattack(atom/A, mob/user as mob, proximity) + if(!proximity) + return + + if(istype(A, /turf/simulated/floor)) + var/turf/simulated/floor/F = A + + if(F.is_plasteel_floor()) // only tiled floors + if(tile_dir_mode) + var/D = get_dir(usr, F) + if(usr.loc == F) + D = usr.dir + + switch(tile_dir_mode) + if(1) // All directions accepted + F.dir = D + F.icon_state = mode + if(2) // Corner mode - diagonal directions converted CW around. + switch(D) + if(NORTHEAST) + D = EAST + if(SOUTHEAST) + D = SOUTH + if(SOUTHWEST) + D = WEST + if(NORTHWEST) + D = NORTH + F.dir = D + F.icon_state = mode + if(3) // cardinal directions only. I've adjusted diagonals the same way the facing code does. + switch(D) + if(NORTHEAST) + D = EAST + if(SOUTHEAST) + D = EAST + if(SOUTHWEST) + D = WEST + if(NORTHWEST) + D = WEST + F.dir = D + F.icon_state = mode + if(4) // floors.dmi icon_states "warningcorner" and "warnwhitecorner" are incorrect, this fixes it + var/D2 + switch(D) + if(NORTHEAST) + D2 = WEST + if(SOUTHEAST) + D2 = SOUTH + if(SOUTHWEST) + D2 = NORTH + if(NORTHWEST) + D2 = EAST + F.dir = D2 + F.icon_state = mode + if(5) + F.dir = 0 + if(D == NORTH || D == SOUTH || D == NORTHEAST || D == SOUTHWEST) + F.icon_state = mode + else + F.icon_state = "[mode]_inv" + else + F.dir = 0 + F.icon_state = mode + else + usr << "You can't paint that!" + +/obj/item/device/floor_painter/attack_self(mob/user as mob) + var/type = input("What type of floor?", "Floor painter", "solid") in list("solid", "corner", "opposite corners", "side/three corners", "special", "letters") + + tile_dir_mode = 0 + + switch(type) + if("solid") + tile_dir_mode = 0 + var/design = input("Which color?", "Floor painter") in list("standard", "dark", "red", "blue", "green", "yellow", "purple", "neutral", "white", "white-red", "white-blue", "white-green", "white-yellow", "white-purple", "freezer", "hydro", "showroom") + if(design == "standard") + mode = "floor" + mode_nice = "standard" + return + if(design == "white") + mode = "white" + mode_nice = "white" + return + if(design == "showroom" || design == "hydro" || design == "freezer") + mode = "[design]floor" + mode_nice = design + return + mode_nice = design + mode = "[replacetext(design, "-", "")]full" + if("corner") + var/design = input("Which design?", "Floor painter") in list("black", "red", "blue", "green", "yellow", "purple", "neutral", "white", "white-grey", "white-red", "white-blue", "white-green", "white-yellow", "white-purple") + mode_nice = "[design] corner" + mode = "[replacetext(design, "-", "")]corner" + tile_dir_mode = 2 + if("opposite corners") + var/design = input("Which design?", "Floor painter") in list("bar", "cmo", "yellowpatch", "cafeteria", "red-yellow", "red-blue", "red-green", "green-yellow", "green-blue", "blue-yellow") + mode_nice = design + if(design == "bar" || design == "cmo" || design == "yellowpatch" || design == "cafeteria") + mode = design + else + mode = "[replacetext(design, "-", "")]full" + if(design == "yellowpatch") + tile_dir_mode = 5 + else + tile_dir_mode = 0 + if("side/three corners") + var/design = input("Which design?", "Floor painter") in list("black", "red", "blue", "green", "yellow", "purple", "neutral", "white", "white-red", "white-blue", "white-green", "white-yellow", "white-purple", "red-yellow", "red-blue", "blue-red", "red-green", "green-yellow", "green-blue", "blue-yellow") + if(design == "white") + mode = "whitehall" + mode_nice = "white side" + tile_dir_mode = 1 + else + mode_nice = design + mode = replacetext(design, "-", "") + tile_dir_mode = 1 + if("special") + var/design = input("Which design?", "Floor painter") in list("arrival", "escape", "caution", "warning", "white-warning", "white-blue-green", "loadingarea", "delivery", "bot", "white-delivery", "white-bot") + if(design == "white-blue-green") + mode_nice = design + mode = "whitebluegreencorners" + tile_dir_mode = 2 + else if(design == "delivery" || design == "bot") + mode_nice = design + mode = design + tile_dir_mode = 0 + else if(design == "loadingarea") + mode_nice = design + mode = design + tile_dir_mode = 3 + else + if(design == "white-warning") + mode_nice = design + design = "warnwhite" + var/s_corner = alert("Do you want to paint a single corner of the tile?", "Floor painter","Yes","No") == "Yes" + if(s_corner) + mode_nice = "[design] corner" + mode = "[design]corner" + if(design == "warning" || design == "white-warning") // sprites for these are weird, need to fix dirs (icons/turf/floors.dmi, "warningcorner" and "warnwhitecorner") + tile_dir_mode = 4 + else + tile_dir_mode = 2 + else + mode_nice = design + mode = design + tile_dir_mode = 1 + if("letters") + var/which = input("Which letters/design?", "Floor painter") in list("A1", "A2", "DI", "SA", "SA (red)", "SB", "SB (red)", "SC", "SC (red)", "W (red)", "V (green)", "Psy", "Ex", "Ex (blue)", "CMO", "O (OP)", "P (OP)") + mode_nice = which + switch(which) + if("A1") + mode = "white_1" + if("A2") + mode = "white_2" + if("DI") + mode = "white_d" + if("SA") + mode = "white_a" + if("SA (red)") + mode = "whitered_a" + tile_dir_mode = 3 + if("SB") + mode = "white_b" + if("SB (red)") + mode = "whitered_b" + tile_dir_mode = 3 + if("SC") + mode = "white_c" + if("SC (red)") + mode = "whitered_c" + tile_dir_mode = 3 + if("W (red)") + mode = "whitered_w" + tile_dir_mode = 3 + if("V (green)") + mode = "whitegreen_v" + tile_dir_mode = 3 + if("Psy") + mode = "white_p" + if("Ex") + mode = "white_ex" + if("Ex (blue)") + mode = "whiteblue_ex" + tile_dir_mode = 3 + if("CMO") // yes this is also in "opposite corners" choices, but it's a different icon_state (!!) + mode = "white_cmo" + if("O (OP)") + mode = "white_halfo" + if("P (OP)") + mode = "white_halfp" + +/obj/item/device/floor_painter/examine() + ..() + usr << "It is in [mode_nice] mode." \ No newline at end of file diff --git a/code/game/objects/items/weapons/cosmetics.dm b/code/game/objects/items/weapons/cosmetics.dm index d473343e61..2e5f61f80e 100644 --- a/code/game/objects/items/weapons/cosmetics.dm +++ b/code/game/objects/items/weapons/cosmetics.dm @@ -65,24 +65,4 @@ else user << "Where are the lips on that?" -//you can wipe off lipstick with paper! -/obj/item/weapon/paper/attack(mob/living/carbon/M as mob, mob/living/carbon/user as mob) - if(user.zone_sel.selecting == "mouth") - if(!istype(M, /mob)) return - - if(ishuman(M)) - var/mob/living/carbon/human/H = M - if(H == user) - user << "You wipe off the lipstick with [src]." - H.lip_style = null - H.update_body() - else - user.visible_message("[user] begins to wipe [H]'s lipstick off with \the [src].", \ - "You begin to wipe off [H]'s lipstick.") - if(do_after(user, 10) && do_after(H, 10, 5, 0)) //user needs to keep their active hand, H does not. - user.visible_message("[user] wipes [H]'s lipstick off with \the [src].", \ - "You wipe off [H]'s lipstick.") - H.lip_style = null - H.update_body() - else - ..() \ No newline at end of file +//you can wipe off lipstick with paper! see code/modules/paperwork/paper.dm, paper/attack() diff --git a/code/game/objects/items/weapons/storage/boxes.dm b/code/game/objects/items/weapons/storage/boxes.dm index 86bbd13651..dea00bcf08 100644 --- a/code/game/objects/items/weapons/storage/boxes.dm +++ b/code/game/objects/items/weapons/storage/boxes.dm @@ -397,7 +397,7 @@ /obj/item/weapon/storage/box/mousetraps name = "box of Pest-B-Gon mousetraps" - desc = "WARNING: Keep out of reach of children." + desc = "WARNING: Keep out of reach of children." icon_state = "mousetraps" New() @@ -506,4 +506,4 @@ for(var/i = 0; i < 14; i++) new /obj/item/weapon/light/tube(src) for(var/i = 0; i < 7; i++) - new /obj/item/weapon/light/bulb(src) \ No newline at end of file + new /obj/item/weapon/light/bulb(src) diff --git a/code/game/objects/items/weapons/storage/fancy.dm b/code/game/objects/items/weapons/storage/fancy.dm index 5766fd27e4..5353b6871d 100644 --- a/code/game/objects/items/weapons/storage/fancy.dm +++ b/code/game/objects/items/weapons/storage/fancy.dm @@ -202,6 +202,55 @@ icon_state = "Dpacket" item_state = "Dpacket" +/obj/item/weapon/storage/fancy/cigar + name = "cigar case" + desc = "A case for holding your cigars when you are not smoking them." + icon_state = "cigarcase" + item_state = "cigarcase" + icon = 'icons/obj/cigarettes.dmi' + w_class = 1 + throwforce = 2 + flags = TABLEPASS + slot_flags = SLOT_BELT + storage_slots = 7 + can_hold = list("/obj/item/clothing/mask/cigarette/cigar") + icon_type = "cigar" + +/obj/item/weapon/storage/fancy/cigar/New() + ..() + flags |= NOREACT + for(var/i = 1 to storage_slots) + new /obj/item/clothing/mask/cigarette/cigar(src) + create_reagents(15 * storage_slots) + +/obj/item/weapon/storage/fancy/cigar/Del() + del(reagents) + ..() + +/obj/item/weapon/storage/fancy/cigar/update_icon() + icon_state = "[initial(icon_state)][contents.len]" + return + +/obj/item/weapon/storage/fancy/cigar/remove_from_storage(obj/item/W as obj, atom/new_location) + var/obj/item/clothing/mask/cigarette/cigar/C = W + if(!istype(C)) return + reagents.trans_to(C, (reagents.total_volume/contents.len)) + ..() + +/obj/item/weapon/storage/fancy/cigar/attack(mob/living/carbon/M as mob, mob/living/carbon/user as mob) + if(!istype(M, /mob)) + return + + if(M == user && user.zone_sel.selecting == "mouth" && contents.len > 0 && !user.wear_mask) + var/obj/item/clothing/mask/cigarette/cigar/W = new /obj/item/clothing/mask/cigarette/cigar(user) + reagents.trans_to(W, (reagents.total_volume/contents.len)) + user.equip_to_slot_if_possible(W, slot_wear_mask) + reagents.maximum_volume = 15 * contents.len + contents.len-- + user << "You take a cigar out of the case." + update_icon() + else + ..() /* * Vial Box diff --git a/code/game/objects/items/weapons/tanks/jetpack.dm b/code/game/objects/items/weapons/tanks/jetpack.dm index 953e9a010d..6c0e13b7c3 100644 --- a/code/game/objects/items/weapons/tanks/jetpack.dm +++ b/code/game/objects/items/weapons/tanks/jetpack.dm @@ -13,62 +13,58 @@ var/volume_rate = 500 //Needed for borg jetpack transfer icon_action_button = "action_jetpack" - New() - ..() - src.ion_trail = new /datum/effect/effect/system/ion_trail_follow() - src.ion_trail.set_up(src) - return +/obj/item/weapon/tank/jetpack/New() + ..() + src.ion_trail = new /datum/effect/effect/system/ion_trail_follow() + src.ion_trail.set_up(src) +/obj/item/weapon/tank/jetpack/examine() + set src in usr + ..() + if(air_contents.gas["oxygen"] < 10) + usr << text("\red The meter on the [src.name] indicates you are almost out of air!") + playsound(usr, 'sound/effects/alert.ogg', 50, 1) - examine() - set src in usr - ..() - if(air_contents.gas["oxygen"] < 10) - usr << text("\red The meter on the [src.name] indicates you are almost out of air!") - playsound(usr, 'sound/effects/alert.ogg', 50, 1) - return +/obj/item/weapon/tank/jetpack/verb/toggle_rockets() + set name = "Toggle Jetpack Stabilization" + set category = "Object" + src.stabilization_on = !( src.stabilization_on ) + usr << "You toggle the stabilization [stabilization_on? "on":"off"]." +/obj/item/weapon/tank/jetpack/verb/toggle() + set name = "Toggle Jetpack" + set category = "Object" - verb/toggle_rockets() - set name = "Toggle Jetpack Stabilization" - set category = "Object" - src.stabilization_on = !( src.stabilization_on ) - usr << "You toggle the stabilization [stabilization_on? "on":"off"]." - return + on = !on + if(on) + icon_state = "[icon_state]-on" + ion_trail.start() + else + icon_state = initial(icon_state) + ion_trail.stop() + if (ismob(usr)) + var/mob/M = usr + M.update_inv_back() - verb/toggle() - set name = "Toggle Jetpack" - set category = "Object" - on = !on - if(on) - icon_state = "[icon_state]-on" -// item_state = "[item_state]-on" - ion_trail.start() - else - icon_state = initial(icon_state) -// item_state = initial(item_state) - ion_trail.stop() - return +/obj/item/weapon/tank/jetpack/proc/allow_thrust(num, mob/living/user as mob) + if(!(src.on)) + return 0 + if((num < 0.005 || src.air_contents.total_moles < num)) + src.ion_trail.stop() + return 0 + var/datum/gas_mixture/G = src.air_contents.remove(num) - proc/allow_thrust(num, mob/living/user as mob) - if(!(src.on)) - return 0 - if((num < 0.005 || src.air_contents.total_moles < num)) - src.ion_trail.stop() - return 0 + var/allgases = G.gas["carbon_dioxide"] + G.gas["nitrogen"] + G.gas["oxygen"] + G.gas["phoron"] + if(allgases >= 0.005) + return 1 - var/datum/gas_mixture/G = src.air_contents.remove(num) + del(G) + return - if(G.total_moles >= 0.005) - return 1 - - del(G) - return - - ui_action_click() - toggle() +/obj/item/weapon/tank/jetpack/ui_action_click() + toggle() /obj/item/weapon/tank/jetpack/void @@ -77,10 +73,10 @@ icon_state = "jetpack-void" item_state = "jetpack-void" - New() - ..() - air_contents.adjust_gas("oxygen", (6*ONE_ATMOSPHERE)*volume/(R_IDEAL_GAS_EQUATION*T20C)) - return +/obj/item/weapon/tank/jetpack/void/New() + ..() + air_contents.adjust_gas("oxygen", (6*ONE_ATMOSPHERE)*volume/(R_IDEAL_GAS_EQUATION*T20C)) + return /obj/item/weapon/tank/jetpack/oxygen name = "Jetpack (Oxygen)" @@ -88,10 +84,10 @@ icon_state = "jetpack" item_state = "jetpack" - New() - ..() - air_contents.adjust_gas("oxygen", (6*ONE_ATMOSPHERE)*volume/(R_IDEAL_GAS_EQUATION*T20C)) - return +/obj/item/weapon/tank/jetpack/oxygen/New() + ..() + air_contents.adjust_gas("oxygen", (6*ONE_ATMOSPHERE)*volume/(R_IDEAL_GAS_EQUATION*T20C)) + return /obj/item/weapon/tank/jetpack/carbondioxide name = "Jetpack (Carbon Dioxide)" @@ -100,18 +96,18 @@ icon_state = "jetpack-black" item_state = "jetpack-black" - New() - ..() - src.ion_trail = new /datum/effect/effect/system/ion_trail_follow() - src.ion_trail.set_up(src) - //src.air_contents.carbon_dioxide = (6*ONE_ATMOSPHERE)*volume/(R_IDEAL_GAS_EQUATION*T20C) - air_contents.adjust_gas("carbon_dioxide", (6*ONE_ATMOSPHERE)*volume/(R_IDEAL_GAS_EQUATION*T20C)) - return +/obj/item/weapon/tank/jetpack/carbondioxide/New() + ..() + src.ion_trail = new /datum/effect/effect/system/ion_trail_follow() + src.ion_trail.set_up(src) + //src.air_contents.carbon_dioxide = (6*ONE_ATMOSPHERE)*volume/(R_IDEAL_GAS_EQUATION*T20C) + air_contents.adjust_gas("carbon_dioxide", (6*ONE_ATMOSPHERE)*volume/(R_IDEAL_GAS_EQUATION*T20C)) + return - examine() - set src in usr - ..() - if(air_contents.gas["carbon_dioxide"] < 10) - usr << text("\red The meter on the [src.name] indicates you are almost out of air!") - playsound(usr, 'sound/effects/alert.ogg', 50, 1) - return +/obj/item/weapon/tank/jetpack/carbondioxide/examine() + set src in usr + ..() + if(air_contents.gas["carbon_dioxide"] < 10) + usr << text("\red The meter on the [src.name] indicates you are almost out of air!") + playsound(usr, 'sound/effects/alert.ogg', 50, 1) + return diff --git a/code/game/objects/items/weapons/tools.dm b/code/game/objects/items/weapons/tools.dm index d148b3b758..af50cd1088 100644 --- a/code/game/objects/items/weapons/tools.dm +++ b/code/game/objects/items/weapons/tools.dm @@ -251,9 +251,9 @@ playsound(src.loc, 'sound/effects/refill.ogg', 50, 1, -6) return else if (istype(O, /obj/structure/reagent_dispensers/fueltank) && get_dist(src,O) <= 1 && src.welding) - message_admins("[key_name_admin(user)] triggered a fueltank explosion.") - log_game("[key_name(user)] triggered a fueltank explosion.") - user << "\red That was stupid of you." + message_admins("[key_name_admin(user)] triggered a fueltank explosion with a welding tool.") + log_game("[key_name(user)] triggered a fueltank explosion with a welding tool.") + user << "\red You begin welding on the fueltank and with a moment of lucidity you realize, this might not have been the smartest thing you've ever done." var/obj/structure/reagent_dispensers/fueltank/tank = O tank.explode() return @@ -470,4 +470,4 @@ user << "Nothing to fix!" else - return ..() \ No newline at end of file + return ..() diff --git a/code/game/objects/structures/crates_lockers/closets/fireaxe.dm b/code/game/objects/structures/crates_lockers/closets/fireaxe.dm index 2090d76af5..87eb2cb811 100644 --- a/code/game/objects/structures/crates_lockers/closets/fireaxe.dm +++ b/code/game/objects/structures/crates_lockers/closets/fireaxe.dm @@ -25,10 +25,10 @@ if(istype(O, /obj/item/device/multitool)) user << "\red Resetting circuitry..." playsound(user, 'sound/machines/lockreset.ogg', 50, 1) - sleep(50) // Sleeping time~ - src.locked = 0 - user << "\blue You disable the locking modules." - update_icon() + if(do_after(user, 20)) + src.locked = 0 + user << " You disable the locking modules." + update_icon() return else if(istype(O, /obj/item/weapon)) var/obj/item/weapon/W = O @@ -87,6 +87,9 @@ src.locked = 1 user << "\blue You re-enable the locking modules." playsound(user, 'sound/machines/lockenable.ogg', 50, 1) + if(do_after(user,20)) + src.locked = 1 + user << " You re-enable the locking modules." return else localopened = !localopened diff --git a/code/game/objects/structures/window.dm b/code/game/objects/structures/window.dm index 4977da7f4d..7052bf5a98 100644 --- a/code/game/objects/structures/window.dm +++ b/code/game/objects/structures/window.dm @@ -163,6 +163,7 @@ /obj/structure/window/attackby(obj/item/W as obj, mob/user as mob) if(!istype(W)) return//I really wish I did not need this + if(W.flags & NOBLUDGEON) return if (istype(W, /obj/item/weapon/grab) && get_dist(src,user)<2) var/obj/item/weapon/grab/G = W diff --git a/code/modules/admin/admin.dm b/code/modules/admin/admin.dm index 11c3980db4..12b5bf7789 100644 --- a/code/modules/admin/admin.dm +++ b/code/modules/admin/admin.dm @@ -120,7 +120,7 @@ var/global/floorIsLava = 0 body += "Animalize | " // DNA2 - Admin Hax - if(iscarbon(M)) + if(M.dna && iscarbon(M)) body += "

" body += "DNA Blocks:
" var/bname @@ -369,21 +369,21 @@ var/global/floorIsLava = 0 if(6) dat+="ERROR: Could not submit Feed story to Network.

" if(src.admincaster_feed_channel.channel_name=="") - dat+="•Invalid receiving channel name.
" + dat+="•Invalid receiving channel name.
" if(src.admincaster_feed_message.body == "" || src.admincaster_feed_message.body == "\[REDACTED\]") - dat+="•Invalid message body.
" + dat+="•Invalid message body.
" dat+="
Return
" if(7) dat+="ERROR: Could not submit Feed Channel to Network.

" if(src.admincaster_feed_channel.channel_name =="" || src.admincaster_feed_channel.channel_name == "\[REDACTED\]") - dat+="•Invalid channel name.
" + dat+="•Invalid channel name.
" var/check = 0 for(var/datum/feed_channel/FC in news_network.network_channels) if(FC.channel_name == src.admincaster_feed_channel.channel_name) check = 1 break if(check) - dat+="•Channel name already in use.
" + dat+="•Channel name already in use.
" dat+="
Return
" if(9) dat+="[src.admincaster_feed_channel.channel_name]: \[created by: [src.admincaster_feed_channel.author]\]
" @@ -497,9 +497,9 @@ var/global/floorIsLava = 0 if(16) dat+="ERROR: Wanted Issue rejected by Network.

" if(src.admincaster_feed_message.author =="" || src.admincaster_feed_message.author == "\[REDACTED\]") - dat+="•Invalid name for person wanted.
" + dat+="•Invalid name for person wanted.
" if(src.admincaster_feed_message.body == "" || src.admincaster_feed_message.body == "\[REDACTED\]") - dat+="•Invalid description.
" + dat+="•Invalid description.
" dat+="
Return
" if(17) dat+={" @@ -1142,4 +1142,4 @@ var/global/floorIsLava = 0 // //ALL DONE //********************************************************************************************************* -// +// diff --git a/code/modules/admin/verbs/debug.dm b/code/modules/admin/verbs/debug.dm index 0076cded1b..73e615f577 100644 --- a/code/modules/admin/verbs/debug.dm +++ b/code/modules/admin/verbs/debug.dm @@ -310,7 +310,7 @@ But you can call procs that are of type /mob/living/carbon/human/proc/ for that else if(alert("Spawn that person a tome?",,"Yes","No")=="Yes") M << "\red You catch a glimpse of the Realm of Nar-Sie, The Geometer of Blood. You now see how flimsy the world is, you see that it should be open to the knowledge of Nar-Sie. A tome, a message from your new master, appears on the ground." - new /obj/item/weapon/tome(M.loc) + new /obj/item/weapon/book/tome(M.loc) else M << "\red You catch a glimpse of the Realm of Nar-Sie, The Geometer of Blood. You now see how flimsy the world is, you see that it should be open to the knowledge of Nar-Sie." var/glimpse=pick("1","2","3","4","5","6","7","8") diff --git a/code/modules/client/preferences.dm b/code/modules/client/preferences.dm index a471aeba39..38ef31dbf1 100644 --- a/code/modules/client/preferences.dm +++ b/code/modules/client/preferences.dm @@ -77,6 +77,12 @@ datum/preferences var/language = "None" //Secondary language var/list/gear //Custom/fluff item loadout. + //Some faction information. + var/home_system = "Unset" //System of birth. + var/citizenship = "None" //Current home system. + var/faction = "None" //Antag faction/general associated faction. + var/religion = "None" //Religious association. + //Mob preview var/icon/preview_icon = null var/icon/preview_icon_front = null @@ -406,7 +412,14 @@ datum/preferences dat += "
Body Color
" dat += "Change Color
 12345
__
" + dat += "

Background Information
" + dat += "Home system: [home_system]
" + dat += "Citizenship: [citizenship]
" + dat += "Faction: [faction]
" + dat += "Religion: [religion]
" + dat += "

" + if(jobban_isbanned(user, "Syndicate")) dat += "You are banned from antagonist roles." src.be_special = 0 @@ -1343,6 +1356,46 @@ datum/preferences return spawnpoint = choice + if("home_system") + var/choice = input(user, "Please choose a home system.") as null|anything in home_system_choices + list("Unset","Other") + if(!choice) + return + if(choice == "Other") + var/raw_choice = input(user, "Please enter a home system.") as text|null + if(raw_choice) + home_system = sanitize(copytext(raw_choice,1,MAX_MESSAGE_LEN)) + return + home_system = choice + if("citizenship") + var/choice = input(user, "Please choose your current citizenship.") as null|anything in citizenship_choices + list("None","Other") + if(!choice) + return + if(choice == "Other") + var/raw_choice = input(user, "Please enter your current citizenship.", "Character Preference") as text|null + if(raw_choice) + citizenship = sanitize(copytext(raw_choice,1,MAX_MESSAGE_LEN)) + return + citizenship = choice + if("faction") + var/choice = input(user, "Please choose a faction to work for.") as null|anything in faction_choices + list("None","Other") + if(!choice) + return + if(choice == "Other") + var/raw_choice = input(user, "Please enter a faction.") as text|null + if(raw_choice) + faction = sanitize(copytext(raw_choice,1,MAX_MESSAGE_LEN)) + return + faction = choice + if("religion") + var/choice = input(user, "Please choose a religion.") as null|anything in religion_choices + list("None","Other") + if(!choice) + return + if(choice == "Other") + var/raw_choice = input(user, "Please enter a religon.") as text|null + if(raw_choice) + religion = sanitize(copytext(raw_choice,1,MAX_MESSAGE_LEN)) + return + religion = choice else switch(href_list["preference"]) if("gender") diff --git a/code/modules/client/preferences_factions.dm b/code/modules/client/preferences_factions.dm new file mode 100644 index 0000000000..2293be7dd6 --- /dev/null +++ b/code/modules/client/preferences_factions.dm @@ -0,0 +1,53 @@ +var/global/list/seen_citizenships = list() +var/global/list/seen_systems = list() +var/global/list/seen_factions = list() +var/global/list/seen_religions = list() + +//Commenting this out for now until I work the lists it into the event generator/journalist/chaplain. +/proc/UpdateFactionList(mob/living/carbon/human/M) + /*if(M && M.client && M.client.prefs) + seen_citizenships |= M.client.prefs.citizenship + seen_systems |= M.client.prefs.home_system + seen_factions |= M.client.prefs.faction + seen_religions |= M.client.prefs.religion*/ + return + +var/global/list/citizenship_choices = list( + "Earth", + "Mars", + "Moghes", + "Ahdomai", + "Qerrbalak" + ) + +var/global/list/home_system_choices = list( + "Sol", + "Nyx", + "Tau Ceti", + "Epsilon Ursae Majoris", + "S'randarr" + ) + +var/global/list/faction_choices = list( + "Sol Central", + "Vey Med", + "Einstein Engines", + "Free Trade Union", + "NanoTrasen", + "Ward-Takahashi GMB", + "Gilthari Exports", + "Grayson Manufactories Ltd.", + "Aether Atmospherics", + "Zeng-Hu Pharmaceuticals", + "Hesphaistos Industries" + ) + +var/global/list/religion_choices = list( + "Unitarianism", + "Hinduism", + "Buddhist", + "Islamic", + "Christian", + "Agnostic", + "Deist" + ) \ No newline at end of file diff --git a/code/modules/client/preferences_savefile.dm b/code/modules/client/preferences_savefile.dm index 896be32bac..dd205c3862 100644 --- a/code/modules/client/preferences_savefile.dm +++ b/code/modules/client/preferences_savefile.dm @@ -166,6 +166,10 @@ S["skill_specialization"] >> skill_specialization S["organ_data"] >> organ_data S["gear"] >> gear + S["home_system"] >> home_system + S["citizenship"] >> citizenship + S["faction"] >> faction + S["religion"] >> religion S["nanotrasen_relation"] >> nanotrasen_relation //S["skin_style"] >> skin_style @@ -225,6 +229,11 @@ if(!gear) src.gear = list() //if(!skin_style) skin_style = "Default" + if(!home_system) home_system = "Unset" + if(!citizenship) citizenship = "None" + if(!faction) faction = "None" + if(!religion) religion = "None" + return 1 /datum/preferences/proc/save_character() @@ -297,6 +306,10 @@ S["skill_specialization"] << skill_specialization S["organ_data"] << organ_data S["gear"] << gear + S["home_system"] << home_system + S["citizenship"] << citizenship + S["faction"] << faction + S["religion"] << religion S["nanotrasen_relation"] << nanotrasen_relation //S["skin_style"] << skin_style diff --git a/code/modules/clothing/clothing.dm b/code/modules/clothing/clothing.dm index 38f39edff5..fa519d6f0b 100644 --- a/code/modules/clothing/clothing.dm +++ b/code/modules/clothing/clothing.dm @@ -33,16 +33,21 @@ return 1 /obj/item/clothing/proc/refit_for_species(var/target_species) + //Set species_restricted list switch(target_species) if("Human", "Skrell") //humanoid bodytypes species_restricted = list("exclude","Unathi","Tajaran","Diona","Vox") else species_restricted = list(target_species) + //Set icon if (sprite_sheets_obj && (target_species in sprite_sheets_obj)) icon = sprite_sheets_obj[target_species] + else + icon = initial(icon) /obj/item/clothing/head/helmet/refit_for_species(var/target_species) + //Set species_restricted list switch(target_species) if("Skrell") species_restricted = list("exclude","Unathi","Tajaran","Diona","Vox") @@ -51,8 +56,11 @@ else species_restricted = list(target_species) + //Set icon if (sprite_sheets_obj && (target_species in sprite_sheets_obj)) icon = sprite_sheets_obj[target_species] + else + icon = initial(icon) //Ears: headsets, earmuffs and tiny objects diff --git a/code/modules/clothing/spacesuits/rig.dm b/code/modules/clothing/spacesuits/rig.dm index 4009d1a8f8..6a0ecc4933 100644 --- a/code/modules/clothing/spacesuits/rig.dm +++ b/code/modules/clothing/spacesuits/rig.dm @@ -20,6 +20,9 @@ "Tajaran" = 'icons/mob/species/tajaran/helmet.dmi', "Skrell" = 'icons/mob/species/skrell/helmet.dmi' ) + sprite_sheets_obj = list( + "Tajaran" = 'icons/obj/clothing/species/tajaran/hats.dmi', + ) attack_self(mob/user) if(!isturf(user.loc)) @@ -65,6 +68,9 @@ "Tajaran" = 'icons/mob/species/tajaran/suit.dmi', "Skrell" = 'icons/mob/species/skrell/suit.dmi' ) + sprite_sheets_obj = list( + "Tajaran" = 'icons/obj/clothing/species/tajaran/suits.dmi', + ) //Breach thresholds, should ideally be inherited by most (if not all) hardsuits. breach_threshold = 18 @@ -299,9 +305,6 @@ icon_state = "rig0-engineering" item_state = "eng_helm" armor = list(melee = 40, bullet = 5, laser = 20,energy = 5, bomb = 35, bio = 100, rad = 80) - sprite_sheets_obj = list( - "Tajaran" = 'icons/obj/clothing/species/tajaran/hats.dmi', - ) /obj/item/clothing/suit/space/rig/engineering name = "engineering hardsuit" @@ -311,9 +314,6 @@ slowdown = 1 armor = list(melee = 40, bullet = 5, laser = 20,energy = 5, bomb = 35, bio = 100, rad = 80) allowed = list(/obj/item/device/flashlight,/obj/item/weapon/tank,/obj/item/device/suit_cooling_unit,/obj/item/weapon/storage/bag/ore,/obj/item/device/t_scanner,/obj/item/weapon/pickaxe, /obj/item/weapon/rcd) - sprite_sheets_obj = list( - "Tajaran" = 'icons/obj/clothing/species/tajaran/suits.dmi', - ) //Chief Engineer's rig /obj/item/clothing/head/helmet/space/rig/engineering/chief @@ -323,7 +323,6 @@ item_state = "ce_helm" item_color = "white" sprite_sheets = null - sprite_sheets_obj = null /obj/item/clothing/suit/space/rig/engineering/chief icon_state = "rig-white" @@ -331,7 +330,6 @@ desc = "An advanced suit that protects against hazardous, low pressure environments. Shines with a high polish." item_state = "ce_hardsuit" sprite_sheets = null - sprite_sheets_obj = null //Mining rig /obj/item/clothing/head/helmet/space/rig/mining @@ -412,6 +410,7 @@ armor = list(melee = 40, bullet = 20, laser = 20,energy = 20, bomb = 35, bio = 100, rad = 60) siemens_coefficient = 0.7 sprite_sheets = null + sprite_sheets_obj = null /obj/item/clothing/suit/space/rig/wizard icon_state = "rig-wiz" @@ -424,6 +423,7 @@ armor = list(melee = 40, bullet = 20, laser = 20,energy = 20, bomb = 35, bio = 100, rad = 60) siemens_coefficient = 0.7 sprite_sheets = null + sprite_sheets_obj = null //Medical Rig /obj/item/clothing/head/helmet/space/rig/medical diff --git a/code/modules/customitems/item_defines.dm b/code/modules/customitems/item_defines.dm index cc2d439b80..b37489cc31 100644 --- a/code/modules/customitems/item_defines.dm +++ b/code/modules/customitems/item_defines.dm @@ -295,7 +295,7 @@ attack_self(mob/user) if(user.r_hand == src || user.l_hand == src) for(var/mob/O in viewers(user, null)) - O.show_message(text("\red [] uses [] to comb their hair with incredible style and sophistication. What a guy.", user, src), 1) + O.show_message(text("\red [] uses [] to comb their hair with incredible style and sophistication. What a [].", user, src, user.gender == FEMALE ? "lady" : "guy"), 1) return /obj/item/weapon/fluff/hugo_cinderbacth_1 //thatoneguy: Hugo Cinderbatch diff --git a/code/modules/detectivework/footprints_and_rag.dm b/code/modules/detectivework/footprints_and_rag.dm index e8a207ca8e..c94786e17a 100644 --- a/code/modules/detectivework/footprints_and_rag.dm +++ b/code/modules/detectivework/footprints_and_rag.dm @@ -23,6 +23,7 @@ possible_transfer_amounts = list(5) volume = 5 can_be_placed_into = null + flags = FPRINT | TABLEPASS | OPENCONTAINER | NOBLUDGEON /obj/item/weapon/reagent_containers/glass/rag/attack_self(mob/user as mob) return diff --git a/code/modules/library/lib_machines.dm b/code/modules/library/lib_machines.dm index d93348d6bd..d1561da59d 100644 --- a/code/modules/library/lib_machines.dm +++ b/code/modules/library/lib_machines.dm @@ -147,7 +147,7 @@ datum/borrowbook // Datum used to keep track of who has borrowed what when and f if(src.emagged) dat += "7. Access the Forbidden Lore Vault
" if(src.arcanecheckout) - new /obj/item/weapon/tome(src.loc) + new /obj/item/weapon/book/tome(src.loc) user << "Your sanity barely endures the seconds spent in the vault's browsing window. The only thing to remind you of this when you stop browsing is a dusty old tome sitting on the desk. You don't really remember printing it." user.visible_message("[user] stares at the blank screen for a few moments, his expression frozen in fear. When he finally awakens from it, he looks a lot older.", 2) src.arcanecheckout = 0 @@ -329,26 +329,29 @@ datum/borrowbook // Datum used to keep track of who has borrowed what when and f if(scanner.cache) var/choice = input("Are you certain you wish to upload this title to the Archive?") in list("Confirm", "Abort") if(choice == "Confirm") - establish_old_db_connection() - if(!dbcon_old.IsConnected()) - alert("Connection to Archive has been severed. Aborting.") + if(scanner.cache.unique) + alert("This book has been rejected from the database. Aborting!") else - /* - var/sqltitle = dbcon.Quote(scanner.cache.name) - var/sqlauthor = dbcon.Quote(scanner.cache.author) - var/sqlcontent = dbcon.Quote(scanner.cache.dat) - var/sqlcategory = dbcon.Quote(upload_category) - */ - var/sqltitle = sanitizeSQL(scanner.cache.name) - var/sqlauthor = sanitizeSQL(scanner.cache.author) - var/sqlcontent = sanitizeSQL(scanner.cache.dat) - var/sqlcategory = sanitizeSQL(upload_category) - var/DBQuery/query = dbcon_old.NewQuery("INSERT INTO library (author, title, content, category) VALUES ('[sqlauthor]', '[sqltitle]', '[sqlcontent]', '[sqlcategory]')") - if(!query.Execute()) - usr << query.ErrorMsg() + establish_old_db_connection() + if(!dbcon_old.IsConnected()) + alert("Connection to Archive has been severed. Aborting.") else - log_game("[usr.name]/[usr.key] has uploaded the book titled [scanner.cache.name], [length(scanner.cache.dat)] signs") - alert("Upload Complete.") + /* + var/sqltitle = dbcon.Quote(scanner.cache.name) + var/sqlauthor = dbcon.Quote(scanner.cache.author) + var/sqlcontent = dbcon.Quote(scanner.cache.dat) + var/sqlcategory = dbcon.Quote(upload_category) + */ + var/sqltitle = sanitizeSQL(scanner.cache.name) + var/sqlauthor = sanitizeSQL(scanner.cache.author) + var/sqlcontent = sanitizeSQL(scanner.cache.dat) + var/sqlcategory = sanitizeSQL(upload_category) + var/DBQuery/query = dbcon_old.NewQuery("INSERT INTO library (author, title, content, category) VALUES ('[sqlauthor]', '[sqltitle]', '[sqlcontent]', '[sqlcategory]')") + if(!query.Execute()) + usr << query.ErrorMsg() + else + log_game("[usr.name]/[usr.key] has uploaded the book titled [scanner.cache.name], [length(scanner.cache.dat)] signs") + alert("Upload Complete.") if(href_list["targetid"]) var/sqlid = sanitizeSQL(href_list["targetid"]) diff --git a/code/modules/mining/drilling/distribution.dm b/code/modules/mining/drilling/distribution.dm index bf32d417cd..e152a60b34 100644 --- a/code/modules/mining/drilling/distribution.dm +++ b/code/modules/mining/drilling/distribution.dm @@ -163,7 +163,6 @@ Deep minerals: target_turf = locate(tx+j, ty+i, asteroid_z) if(target_turf && target_turf.has_resources) - target_turf.resources = list() target_turf.resources["silicates"] = rand(3,5) target_turf.resources["carbonaceous rock"] = rand(3,5) diff --git a/code/modules/mining/mine_items.dm b/code/modules/mining/mine_items.dm index c54853355e..f695621d97 100644 --- a/code/modules/mining/mine_items.dm +++ b/code/modules/mining/mine_items.dm @@ -181,3 +181,70 @@ icon_opened = "miningcaropen" icon_closed = "miningcar" +// Flags. + +/obj/item/stack/flag + name = "flags" + desc = "Some colourful flags." + singular_name = "flag" + amount = 10 + max_amount = 10 + icon = 'icons/obj/mining.dmi' + var/upright = 0 + var/base_state + +/obj/item/stack/flag/New() + ..() + base_state = icon_state + +/obj/item/stack/flag/red + name = "red flags" + singular_name = "red flag" + icon_state = "redflag" + +/obj/item/stack/flag/yellow + name = "yellow flags" + singular_name = "yellow flag" + icon_state = "yellowflag" + +/obj/item/stack/flag/green + name = "green flags" + singular_name = "green flag" + icon_state = "greenflag" + +/obj/item/stack/flag/attackby(obj/item/W as obj, mob/user as mob) + if(upright && istype(W,src.type)) + src.attack_hand(user) + else + ..() + +/obj/item/stack/flag/attack_hand(user as mob) + if(upright) + upright = 0 + icon_state = base_state + anchored = 0 + src.visible_message("[user] knocks down [src].") + else + ..() + +/obj/item/stack/flag/attack_self(mob/user as mob) + + var/obj/item/stack/flag/F = locate() in get_turf(src) + + var/turf/T = get_turf(src) + if(!T || !istype(T,/turf/simulated/floor/plating/airless/asteroid)) + user << "The flag won't stand up in this terrain." + return + + if(F && F.upright) + user << "There is already a flag here." + return + + var/obj/item/stack/flag/newflag = new src.type(T) + newflag.amount = 1 + newflag.upright = 1 + anchored = 1 + newflag.name = newflag.singular_name + newflag.icon_state = "[newflag.base_state]_open" + newflag.visible_message("[user] plants [newflag] firmly in the ground.") + src.use(1) diff --git a/code/modules/mining/mine_turfs.dm b/code/modules/mining/mine_turfs.dm index 207b331535..bf70bb5c76 100644 --- a/code/modules/mining/mine_turfs.dm +++ b/code/modules/mining/mine_turfs.dm @@ -26,353 +26,333 @@ has_resources = 1 - New() - . = ..() +/turf/simulated/mineral/New() - MineralSpread() + . = ..() - spawn(1) - var/turf/T - if((istype(get_step(src, NORTH), /turf/simulated/floor)) || (istype(get_step(src, NORTH), /turf/space)) || (istype(get_step(src, NORTH), /turf/simulated/shuttle/floor))) - T = get_step(src, NORTH) - if (T) - T.overlays += image('icons/turf/walls.dmi', "rock_side_s", layer=2) - if((istype(get_step(src, SOUTH), /turf/simulated/floor)) || (istype(get_step(src, SOUTH), /turf/space)) || (istype(get_step(src, SOUTH), /turf/simulated/shuttle/floor))) - T = get_step(src, SOUTH) - if (T) - T.overlays += image('icons/turf/walls.dmi', "rock_side_n", layer=2) - if((istype(get_step(src, EAST), /turf/simulated/floor)) || (istype(get_step(src, EAST), /turf/space)) || (istype(get_step(src, EAST), /turf/simulated/shuttle/floor))) - T = get_step(src, EAST) - if (T) - T.overlays += image('icons/turf/walls.dmi', "rock_side_w", layer=2) - if((istype(get_step(src, WEST), /turf/simulated/floor)) || (istype(get_step(src, WEST), /turf/space)) || (istype(get_step(src, WEST), /turf/simulated/shuttle/floor))) - T = get_step(src, WEST) - if (T) - T.overlays += image('icons/turf/walls.dmi', "rock_side_e", layer=2) + MineralSpread() + spawn(2) + var/list/step_overlays = list("s" = NORTH, "n" = SOUTH, "w" = EAST, "e" = WEST) + for(var/direction in step_overlays) + var/turf/turf_to_check = get_step(src,step_overlays[direction]) - ex_act(severity) - switch(severity) - if(2.0) - if (prob(70)) - mined_ore = 1 //some of the stuff gets blown up - GetDrilled() - if(1.0) - mined_ore = 2 //some of the stuff gets blown up + if(istype(turf_to_check,/turf/simulated/floor/plating/airless/asteroid)) + var/turf/simulated/floor/plating/airless/asteroid/T = turf_to_check + T.updateMineralOverlays() + + else if(istype(turf_to_check,/turf/space) || istype(turf_to_check,/turf/simulated/floor)) + turf_to_check.overlays += image('icons/turf/walls.dmi', "rock_side_[direction]") + +/turf/simulated/mineral/ex_act(severity) + switch(severity) + if(2.0) + if (prob(70)) + mined_ore = 1 //some of the stuff gets blown up GetDrilled() + if(1.0) + mined_ore = 2 //some of the stuff gets blown up + GetDrilled() + +/turf/simulated/mineral/Bumped(AM) + . = ..() + if(istype(AM,/mob/living/carbon/human)) + var/mob/living/carbon/human/H = AM + if((istype(H.l_hand,/obj/item/weapon/pickaxe)) && (!H.hand)) + attackby(H.l_hand,H) + else if((istype(H.r_hand,/obj/item/weapon/pickaxe)) && H.hand) + attackby(H.r_hand,H) + + else if(istype(AM,/mob/living/silicon/robot)) + var/mob/living/silicon/robot/R = AM + if(istype(R.module_active,/obj/item/weapon/pickaxe)) + attackby(R.module_active,R) + + else if(istype(AM,/obj/mecha)) + var/obj/mecha/M = AM + if(istype(M.selected,/obj/item/mecha_parts/mecha_equipment/tool/drill)) + M.selected.action(src) + +/turf/simulated/mineral/proc/MineralSpread() + if(mineral && mineral.spread) + for(var/trydir in cardinal) + if(prob(mineral.spread_chance)) + var/turf/simulated/mineral/random/target_turf = get_step(src, trydir) + if(istype(target_turf) && !target_turf.mineral) + target_turf.mineral = mineral + target_turf.UpdateMineral() + target_turf.MineralSpread() - Bumped(AM) - . = ..() - if(istype(AM,/mob/living/carbon/human)) - var/mob/living/carbon/human/H = AM - if((istype(H.l_hand,/obj/item/weapon/pickaxe)) && (!H.hand)) - attackby(H.l_hand,H) - else if((istype(H.r_hand,/obj/item/weapon/pickaxe)) && H.hand) - attackby(H.r_hand,H) +/turf/simulated/mineral/proc/UpdateMineral() + if(!mineral) + name = "\improper Rock" + icon_state = "rock" + return + name = "\improper [mineral.display_name] deposit" + overlays.Cut() + overlays += "rock_[mineral.name]" - else if(istype(AM,/mob/living/silicon/robot)) - var/mob/living/silicon/robot/R = AM - if(istype(R.module_active,/obj/item/weapon/pickaxe)) - attackby(R.module_active,R) +//Not even going to touch this pile of spaghetti +/turf/simulated/mineral/attackby(obj/item/weapon/W as obj, mob/user as mob) - else if(istype(AM,/obj/mecha)) - var/obj/mecha/M = AM - if(istype(M.selected,/obj/item/mecha_parts/mecha_equipment/tool/drill)) - M.selected.action(src) + if (!(istype(usr, /mob/living/carbon/human) || ticker) && ticker.mode.name != "monkey") + usr << "\red You don't have the dexterity to do this!" + return + if (istype(W, /obj/item/device/core_sampler)) + geologic_data.UpdateNearbyArtifactInfo(src) + var/obj/item/device/core_sampler/C = W + C.sample_item(src, user) + return - proc/MineralSpread() - if(mineral && mineral.spread) - for(var/trydir in cardinal) - if(prob(mineral.spread_chance)) - var/turf/simulated/mineral/random/target_turf = get_step(src, trydir) - if(istype(target_turf) && !target_turf.mineral) - target_turf.mineral = mineral - target_turf.UpdateMineral() - target_turf.MineralSpread() + if (istype(W, /obj/item/device/depth_scanner)) + var/obj/item/device/depth_scanner/C = W + C.scan_atom(user, src) + return + if (istype(W, /obj/item/device/measuring_tape)) + var/obj/item/device/measuring_tape/P = W + user.visible_message("\blue[user] extends [P] towards [src].","\blue You extend [P] towards [src].") + if(do_after(user,25)) + user << "\blue \icon[P] [src] has been excavated to a depth of [2*excavation_level]cm." + return - proc/UpdateMineral() - if(!mineral) - name = "\improper Rock" - icon_state = "rock" - return - name = "\improper [mineral.display_name] deposit" - overlays.Cut() - overlays += "rock_[mineral.name]" - - - //Not even going to touch this pile of spaghetti - attackby(obj/item/weapon/W as obj, mob/user as mob) - - if (!(istype(usr, /mob/living/carbon/human) || ticker) && ticker.mode.name != "monkey") - usr << "\red You don't have the dexterity to do this!" + if (istype(W, /obj/item/weapon/pickaxe)) + var/turf/T = user.loc + if (!( istype(T, /turf) )) return - if (istype(W, /obj/item/device/core_sampler)) - geologic_data.UpdateNearbyArtifactInfo(src) - var/obj/item/device/core_sampler/C = W - C.sample_item(src, user) + var/obj/item/weapon/pickaxe/P = W + if(last_act + P.digspeed > world.time)//prevents message spam return + last_act = world.time - if (istype(W, /obj/item/device/depth_scanner)) - var/obj/item/device/depth_scanner/C = W - C.scan_atom(user, src) - return + playsound(user, P.drill_sound, 20, 1) - if (istype(W, /obj/item/device/measuring_tape)) - var/obj/item/device/measuring_tape/P = W - user.visible_message("\blue[user] extends [P] towards [src].","\blue You extend [P] towards [src].") - if(do_after(user,25)) - user << "\blue \icon[P] [src] has been excavated to a depth of [2*excavation_level]cm." - return + //handle any archaeological finds we might uncover + var/fail_message + if(finds && finds.len) + var/datum/find/F = finds[1] + if(excavation_level + P.excavation_amount > F.excavation_required) + //Chance to destroy / extract any finds here + fail_message = ". [pick("There is a crunching noise","[W] collides with some different rock","Part of the rock face crumbles away","Something breaks under [W]")]" - if (istype(W, /obj/item/weapon/pickaxe)) - var/turf/T = user.loc - if (!( istype(T, /turf) )) - return + user << "\red You start [P.drill_verb][fail_message ? fail_message : ""]." - var/obj/item/weapon/pickaxe/P = W - if(last_act + P.digspeed > world.time)//prevents message spam - return - last_act = world.time + if(fail_message && prob(90)) + if(prob(25)) + excavate_find(5, finds[1]) + else if(prob(50)) + finds.Remove(finds[1]) + if(prob(50)) + artifact_debris() - playsound(user, P.drill_sound, 20, 1) + if(do_after(user,P.digspeed)) + user << "\blue You finish [P.drill_verb] the rock." - //handle any archaeological finds we might uncover - var/fail_message if(finds && finds.len) var/datum/find/F = finds[1] - if(excavation_level + P.excavation_amount > F.excavation_required) - //Chance to destroy / extract any finds here - fail_message = ", [pick("there is a crunching noise","[W] collides with some different rock","part of the rock face crumbles away","something breaks under [W]")]" - - user << "\red You start [P.drill_verb][fail_message ? fail_message : ""]." - - if(fail_message && prob(90)) - if(prob(25)) - excavate_find(5, finds[1]) - else if(prob(50)) - finds.Remove(finds[1]) - if(prob(50)) - artifact_debris() - - if(do_after(user,P.digspeed)) - user << "\blue You finish [P.drill_verb] the rock." - - if(finds && finds.len) - var/datum/find/F = finds[1] - if(round(excavation_level + P.excavation_amount) == F.excavation_required) - //Chance to extract any items here perfectly, otherwise just pull them out along with the rock surrounding them - if(excavation_level + P.excavation_amount > F.excavation_required) - //if you can get slightly over, perfect extraction - excavate_find(100, F) - else - excavate_find(80, F) - - else if(excavation_level + P.excavation_amount > F.excavation_required - F.clearance_range) - //just pull the surrounding rock out - excavate_find(0, F) - - if( excavation_level + P.excavation_amount >= 100 ) - //if players have been excavating this turf, leave some rocky debris behind - var/obj/structure/boulder/B - if(artifact_find) - if( excavation_level > 0 || prob(15) ) - //boulder with an artifact inside - B = new(src) - if(artifact_find) - B.artifact_find = artifact_find - else - artifact_debris(1) - else if(prob(15)) - //empty boulder - B = new(src) - - if(B) - GetDrilled(0) + if(round(excavation_level + P.excavation_amount) == F.excavation_required) + //Chance to extract any items here perfectly, otherwise just pull them out along with the rock surrounding them + if(excavation_level + P.excavation_amount > F.excavation_required) + //if you can get slightly over, perfect extraction + excavate_find(100, F) else - GetDrilled(1) - return + excavate_find(80, F) - excavation_level += P.excavation_amount + else if(excavation_level + P.excavation_amount > F.excavation_required - F.clearance_range) + //just pull the surrounding rock out + excavate_find(0, F) - //archaeo overlays - if(!archaeo_overlay && finds && finds.len) - var/datum/find/F = finds[1] - if(F.excavation_required <= excavation_level + F.view_range) - archaeo_overlay = "overlay_archaeo[rand(1,3)]" - overlays += archaeo_overlay + if( excavation_level + P.excavation_amount >= 100 ) + //if players have been excavating this turf, leave some rocky debris behind + var/obj/structure/boulder/B + if(artifact_find) + if( excavation_level > 0 || prob(15) ) + //boulder with an artifact inside + B = new(src) + if(artifact_find) + B.artifact_find = artifact_find + else + artifact_debris(1) + else if(prob(15)) + //empty boulder + B = new(src) - //there's got to be a better way to do this - var/update_excav_overlay = 0 - if(excavation_level >= 75) - if(excavation_level - P.excavation_amount < 75) - update_excav_overlay = 1 - else if(excavation_level >= 50) - if(excavation_level - P.excavation_amount < 50) - update_excav_overlay = 1 - else if(excavation_level >= 25) - if(excavation_level - P.excavation_amount < 25) - update_excav_overlay = 1 - - //update overlays displaying excavation level - if( !(excav_overlay && excavation_level > 0) || update_excav_overlay ) - var/excav_quadrant = round(excavation_level / 25) + 1 - excav_overlay = "overlay_excv[excav_quadrant]_[rand(1,3)]" - overlays += excav_overlay - - /* Nope. - //extract pesky minerals while we're excavating - while(excavation_minerals.len && excavation_level > excavation_minerals[excavation_minerals.len]) - DropMineral() - pop(excavation_minerals) - mineralAmt-- */ - - //drop some rocks - next_rock += P.excavation_amount * 10 - while(next_rock > 100) - next_rock -= 100 - var/obj/item/weapon/ore/O = new(src) - geologic_data.UpdateNearbyArtifactInfo(src) - O.geologic_data = geologic_data - - else - return attack_hand(user) - - - proc/DropMineral() - if(!mineral) - return - - var/obj/item/weapon/ore/O = new mineral.ore (src) - if(istype(O)) - geologic_data.UpdateNearbyArtifactInfo(src) - O.geologic_data = geologic_data - return O - - - proc/GetDrilled(var/artifact_fail = 0) - //var/destroyed = 0 //used for breaking strange rocks - if (mineral && mineral.result_amount) - - //if the turf has already been excavated, some of it's ore has been removed - for (var/i = 1 to mineral.result_amount - mined_ore) - DropMineral() - - //destroyed artifacts have weird, unpleasant effects - //make sure to destroy them before changing the turf though - if(artifact_find && artifact_fail) - var/pain = 0 - if(prob(50)) - pain = 1 - for(var/mob/living/M in range(src, 200)) - M << "[pick("A high pitched [pick("keening","wailing","whistle")]","A rumbling noise like [pick("thunder","heavy machinery")]")] somehow penetrates your mind before fading away!" - if(pain) - flick("pain",M.pain) - if(prob(50)) - M.adjustBruteLoss(5) + if(B) + GetDrilled(0) else - flick("flash",M.flash) - if(prob(50)) - M.Stun(5) - M.apply_effect(25, IRRADIATE) + GetDrilled(1) + return - var/turf/simulated/floor/plating/airless/asteroid/N = ChangeTurf(/turf/simulated/floor/plating/airless/asteroid) - N.fullUpdateMineralOverlays() + excavation_level += P.excavation_amount - if(rand(1,500) == 1) - visible_message("An old dusty crate was buried within!") - new /obj/structure/closet/crate/secure/loot(src) + //archaeo overlays + if(!archaeo_overlay && finds && finds.len) + var/datum/find/F = finds[1] + if(F.excavation_required <= excavation_level + F.view_range) + archaeo_overlay = "overlay_archaeo[rand(1,3)]" + overlays += archaeo_overlay + + //there's got to be a better way to do this + var/update_excav_overlay = 0 + if(excavation_level >= 75) + if(excavation_level - P.excavation_amount < 75) + update_excav_overlay = 1 + else if(excavation_level >= 50) + if(excavation_level - P.excavation_amount < 50) + update_excav_overlay = 1 + else if(excavation_level >= 25) + if(excavation_level - P.excavation_amount < 25) + update_excav_overlay = 1 + + //update overlays displaying excavation level + if( !(excav_overlay && excavation_level > 0) || update_excav_overlay ) + var/excav_quadrant = round(excavation_level / 25) + 1 + excav_overlay = "overlay_excv[excav_quadrant]_[rand(1,3)]" + overlays += excav_overlay + + //drop some rocks + next_rock += P.excavation_amount * 10 + while(next_rock > 100) + next_rock -= 100 + var/obj/item/weapon/ore/O = new(src) + geologic_data.UpdateNearbyArtifactInfo(src) + O.geologic_data = geologic_data + + else + return attack_hand(user) + +/turf/simulated/mineral/proc/DropMineral() + if(!mineral) + return + + var/obj/item/weapon/ore/O = new mineral.ore (src) + if(istype(O)) + geologic_data.UpdateNearbyArtifactInfo(src) + O.geologic_data = geologic_data + return O + +/turf/simulated/mineral/proc/GetDrilled(var/artifact_fail = 0) + //var/destroyed = 0 //used for breaking strange rocks + if (mineral && mineral.result_amount) + + //if the turf has already been excavated, some of it's ore has been removed + for (var/i = 1 to mineral.result_amount - mined_ore) + DropMineral() + + //destroyed artifacts have weird, unpleasant effects + //make sure to destroy them before changing the turf though + if(artifact_find && artifact_fail) + var/pain = 0 + if(prob(50)) + pain = 1 + for(var/mob/living/M in range(src, 200)) + M << "[pick("A high pitched [pick("keening","wailing","whistle")]","A rumbling noise like [pick("thunder","heavy machinery")]")] somehow penetrates your mind before fading away!" + if(pain) + flick("pain",M.pain) + if(prob(50)) + M.adjustBruteLoss(5) + else + flick("flash",M.flash) + if(prob(50)) + M.Stun(5) + M.apply_effect(25, IRRADIATE) + + var/turf/simulated/floor/plating/airless/asteroid/N = ChangeTurf(/turf/simulated/floor/plating/airless/asteroid) + for(var/i=0;iAn old dusty crate was buried within!") + new /obj/structure/closet/crate/secure/loot(src) - proc/excavate_find(var/prob_clean = 0, var/datum/find/F) - //with skill and luck, players can cleanly extract finds - //otherwise, they come out inside a chunk of rock - var/obj/item/weapon/X - if(prob_clean) - X = new /obj/item/weapon/archaeological_find(src, new_item_type = F.find_type) - else - X = new /obj/item/weapon/ore/strangerock(src, inside_item_type = F.find_type) - geologic_data.UpdateNearbyArtifactInfo(src) - X:geologic_data = geologic_data +/turf/simulated/mineral/proc/excavate_find(var/prob_clean = 0, var/datum/find/F) + //with skill and luck, players can cleanly extract finds + //otherwise, they come out inside a chunk of rock + var/obj/item/weapon/X + if(prob_clean) + X = new /obj/item/weapon/archaeological_find(src, new_item_type = F.find_type) + else + X = new /obj/item/weapon/ore/strangerock(src, inside_item_type = F.find_type) + geologic_data.UpdateNearbyArtifactInfo(src) + X:geologic_data = geologic_data - //some find types delete the /obj/item/weapon/archaeological_find and replace it with something else, this handles when that happens - //yuck - var/display_name = "something" - if(!X) - X = last_find - if(X) - display_name = X.name + //some find types delete the /obj/item/weapon/archaeological_find and replace it with something else, this handles when that happens + //yuck + var/display_name = "something" + if(!X) + X = last_find + if(X) + display_name = X.name - //many finds are ancient and thus very delicate - luckily there is a specialised energy suspension field which protects them when they're being extracted - if(prob(F.prob_delicate)) - var/obj/effect/suspension_field/S = locate() in src - if(!S || S.field_type != get_responsive_reagent(F.find_type)) - if(X) - visible_message("\red[pick("[display_name] crumbles away into dust","[display_name] breaks apart")].") - del(X) + //many finds are ancient and thus very delicate - luckily there is a specialised energy suspension field which protects them when they're being extracted + if(prob(F.prob_delicate)) + var/obj/effect/suspension_field/S = locate() in src + if(!S || S.field_type != get_responsive_reagent(F.find_type)) + if(X) + visible_message("\red[pick("[display_name] crumbles away into dust","[display_name] breaks apart")].") + del(X) - finds.Remove(F) + finds.Remove(F) - proc/artifact_debris(var/severity = 0) - //cael's patented random limited drop componentized loot system! - //sky's patented not-fucking-retarded overhaul! +/turf/simulated/mineral/proc/artifact_debris(var/severity = 0) + //cael's patented random limited drop componentized loot system! + //sky's patented not-fucking-retarded overhaul! - //Give a random amount of loot from 1 to 3 or 5, varying on severity. - for(var/j in 1 to rand(1, 3 + max(min(severity, 1), 0) * 2)) - switch(rand(1,7)) - if(1) - var/obj/item/stack/rods/R = new(src) - R.amount = rand(5,25) + //Give a random amount of loot from 1 to 3 or 5, varying on severity. + for(var/j in 1 to rand(1, 3 + max(min(severity, 1), 0) * 2)) + switch(rand(1,7)) + if(1) + var/obj/item/stack/rods/R = new(src) + R.amount = rand(5,25) - if(2) - var/obj/item/stack/tile/R = new(src) - R.amount = rand(1,5) + if(2) + var/obj/item/stack/tile/R = new(src) + R.amount = rand(1,5) - if(3) - var/obj/item/stack/sheet/metal/R = new(src) - R.amount = rand(5,25) + if(3) + var/obj/item/stack/sheet/metal/R = new(src) + R.amount = rand(5,25) - if(4) - var/obj/item/stack/sheet/plasteel/R = new(src) - R.amount = rand(5,25) + if(4) + var/obj/item/stack/sheet/plasteel/R = new(src) + R.amount = rand(5,25) - if(5) - var/quantity = rand(1,3) - for(var/i=0, iYou feel a powerful shock course through your body!", \ - "\red You hear a heavy electrical crack." \ - ) -// if(src.stunned < shock_damage) src.stunned = shock_damage - Stun(10)//This should work for now, more is really silly and makes you lay there forever -// if(src.weakened < 20*siemens_coeff) src.weakened = 20*siemens_coeff - Weaken(10) + src.apply_damage(shock_damage, BURN, def_zone, used_weapon="Electrocution") + + playsound(loc, "sparks", 50, 1, -1) + if (shock_damage > 10) + src.visible_message( + "\red [src] was shocked by the [source]!", \ + "\red You feel a powerful shock course through your body!", \ + "\red You hear a heavy electrical crack." \ + ) + Stun(10)//This should work for now, more is really silly and makes you lay there forever + Weaken(10) + else + src.visible_message( + "\red [src] was mildly shocked by the [source].", \ + "\red You feel a mild shock course through your body.", \ + "\red You hear a light zapping." \ + ) var/datum/effect/effect/system/spark_spread/s = new /datum/effect/effect/system/spark_spread s.set_up(5, 1, loc) diff --git a/code/modules/mob/living/carbon/human/human.dm b/code/modules/mob/living/carbon/human/human.dm index d561271aa3..b250884e9f 100644 --- a/code/modules/mob/living/carbon/human/human.dm +++ b/code/modules/mob/living/carbon/human/human.dm @@ -531,13 +531,18 @@ if(wear_id) return wear_id.GetID() -//Added a safety check in case you want to shock a human mob directly through electrocute_act. -/mob/living/carbon/human/electrocute_act(var/shock_damage, var/obj/source, var/siemens_coeff = 1.0, var/safety = 0) - if(!safety) - if(gloves) - var/obj/item/clothing/gloves/G = gloves - siemens_coeff = G.siemens_coefficient - return ..(shock_damage,source,siemens_coeff) +//Removed the horrible safety parameter. It was only being used by ninja code anyways. +//Now checks siemens_coefficient of the affected area by default +/mob/living/carbon/human/electrocute_act(var/shock_damage, var/obj/source, var/base_siemens_coeff = 1.0, var/def_zone = null) + if(status_flags & GODMODE) return 0 //godmode + + if (!def_zone) + def_zone = pick("l_hand", "r_hand") + + var/datum/organ/external/affected_organ = get_organ(check_zone(def_zone)) + var/siemens_coeff = base_siemens_coeff * get_siemens_coefficient_organ(affected_organ) + + return ..(shock_damage, source, siemens_coeff, def_zone) /mob/living/carbon/human/Topic(href, href_list) diff --git a/code/modules/mob/living/carbon/human/human_defense.dm b/code/modules/mob/living/carbon/human/human_defense.dm index 9ef3ed5cd0..407b83c9c3 100644 --- a/code/modules/mob/living/carbon/human/human_defense.dm +++ b/code/modules/mob/living/carbon/human/human_defense.dm @@ -16,7 +16,7 @@ emp_act if(check_shields(P.damage, "the [P.name]")) P.on_hit(src, 2, def_zone) return 2 - + //Laserproof armour if(wear_suit && istype(wear_suit, /obj/item/clothing/suit/armor/laserproof)) if(istype(P, /obj/item/projectile/energy) || istype(P, /obj/item/projectile/beam)) @@ -59,7 +59,7 @@ emp_act var/siemens_coeff = get_siemens_coefficient_organ(affected) stun_amount *= siemens_coeff agony_amount *= siemens_coeff - + switch (def_zone) if("head") agony_amount *= 1.50 @@ -69,17 +69,17 @@ emp_act c_hand = l_hand else c_hand = r_hand - + if(c_hand && (stun_amount || agony_amount > 10)) msg_admin_attack("[src.name] ([src.ckey]) was disarmed by a stun effect") - + u_equip(c_hand) if (affected.status & ORGAN_ROBOT) emote("me", 1, "drops what they were holding, their [affected.display_name] malfunctioning!") else var/emote_scream = pick("screams in pain and", "lets out a sharp cry and", "cries out and") emote("me", 1, "[(species && species.flags & NO_PAIN) ? "" : emote_scream ] drops what they were holding in their [affected.display_name]!") - + ..(stun_amount, agony_amount, def_zone) /mob/living/carbon/human/getarmor(var/def_zone, var/type) @@ -99,6 +99,19 @@ emp_act organnum++ return (armorval/max(organnum, 1)) +//this proc returns the Siemens coefficient of electrical resistivity for a particular external organ. +/mob/living/carbon/human/proc/get_siemens_coefficient_organ(var/datum/organ/external/def_zone) + if (!def_zone) + return 1.0 + + var/siemens_coefficient = 1.0 + + var/list/clothing_items = list(head, wear_mask, wear_suit, w_uniform, gloves, shoes) // What all are we checking? + for(var/obj/item/clothing/C in clothing_items) + if(istype(C) && (C.body_parts_covered & def_zone.body_part)) // Is that body part being targeted covered? + siemens_coefficient *= C.siemens_coefficient + + return siemens_coefficient //this proc returns the armour value for a particular external organ. /mob/living/carbon/human/proc/getarmor_organ(var/datum/organ/external/def_zone, var/type) @@ -113,20 +126,6 @@ emp_act protection += C.armor[type] return protection -//this proc returns the Siemens coefficient of electrical resistivity for a particular external organ. -/mob/living/carbon/human/proc/get_siemens_coefficient_organ(var/datum/organ/external/def_zone) - if (!def_zone) - return 1.0 - - var/siemens_coefficient = 1.0 - - var/list/clothing_items = list(head, wear_mask, wear_suit, w_uniform, gloves, shoes) // What all are we checking? - for(var/obj/item/clothing/C in clothing_items) - if(istype(C) && (C.body_parts_covered & def_zone.body_part)) // Is that body part being targeted covered? - siemens_coefficient *= C.siemens_coefficient - - return siemens_coefficient - /mob/living/carbon/human/proc/check_head_coverage() var/list/body_parts = list(head, wear_mask, wear_suit, w_uniform) @@ -185,7 +184,7 @@ emp_act if(!I || !user) return 0 var/target_zone = def_zone? check_zone(def_zone) : get_zone_with_miss_chance(user.zone_sel.selecting, src) - + if(user == src) // Attacking yourself can't miss target_zone = user.zone_sel.selecting if(!target_zone) @@ -275,17 +274,17 @@ emp_act if(bloody) bloody_body(src) - + //Melee weapon embedded object code. if (I.damtype == BRUTE && !I.is_robot_module()) var/damage = I.force if (armor) damage /= armor+1 - + //blunt objects should really not be embedding in things unless a huge amount of force is involved var/embed_chance = weapon_sharp? damage/I.w_class : damage/(I.w_class*3) var/embed_threshold = weapon_sharp? 5*I.w_class : 15*I.w_class - + //Sharp objects will always embed if they do enough damage. if((weapon_sharp && damage > (10*I.w_class)) || (damage > embed_threshold && prob(embed_chance))) affecting.embed(I) @@ -300,14 +299,14 @@ emp_act var/obj/item/weapon/W = O dtype = W.damtype var/throw_damage = O.throwforce*(speed/5) - + var/zone if (istype(O.thrower, /mob/living)) var/mob/living/L = O.thrower zone = check_zone(L.zone_sel.selecting) else zone = ran_zone("chest",75) //Hits a random part of the body, geared towards the chest - + //check if we hit if (O.throw_source) var/distance = get_dist(O.throw_source, loc) @@ -318,15 +317,15 @@ emp_act if(!zone) visible_message("\blue \The [O] misses [src] narrowly!") return - + O.throwing = 0 //it hit, so stop moving - + if ((O.thrower != src) && check_shields(throw_damage, "[O]")) return - + var/datum/organ/external/affecting = get_organ(zone) var/hit_area = affecting.display_name - + src.visible_message("\red [src] has been hit in the [hit_area] by [O].") var/armor = run_armor_check(affecting, "melee", "Your armor has protected your [hit_area].", "Your armor has softened hit to your [hit_area].") //I guess "melee" is the best fit here @@ -350,16 +349,16 @@ emp_act var/damage = throw_damage if (armor) damage /= armor+1 - + //blunt objects should really not be embedding in things unless a huge amount of force is involved var/embed_chance = sharp? damage/I.w_class : damage/(I.w_class*3) var/embed_threshold = sharp? 5*I.w_class : 15*I.w_class - + //Sharp objects will always embed if they do enough damage. //Thrown sharp objects have some momentum already and have a small chance to embed even if the damage is below the threshold if((sharp && prob(damage/(10*I.w_class)*100)) || (damage > embed_threshold && prob(embed_chance))) affecting.embed(I) - + // Begin BS12 momentum-transfer code. if(O.throw_source && speed >= 15) var/obj/item/weapon/W = O diff --git a/code/modules/mob/living/carbon/species.dm b/code/modules/mob/living/carbon/species.dm index 59c02ab2f7..286bffb3a0 100644 --- a/code/modules/mob/living/carbon/species.dm +++ b/code/modules/mob/living/carbon/species.dm @@ -291,7 +291,6 @@ if(H.mind) H.mind.transfer_to(S) - S.key = H for(var/mob/living/carbon/monkey/diona/D in H.contents) if(D.client) diff --git a/code/modules/mob/living/say.dm b/code/modules/mob/living/say.dm index 12309900b3..95dd82aafe 100644 --- a/code/modules/mob/living/say.dm +++ b/code/modules/mob/living/say.dm @@ -14,6 +14,7 @@ var/list/department_radio_keys = list( ":t" = "Syndicate", "#t" = "Syndicate", ".t" = "Syndicate", ":u" = "Supply", "#u" = "Supply", ".u" = "Supply", ":g" = "changeling", "#g" = "changeling", ".g" = "changeling", + ":d" = "dronechat", "#d" = "dronechat", ".d" = "dronechat", ":R" = "right ear", "#R" = "right ear", ".R" = "right ear", ":L" = "left ear", "#L" = "left ear", ".L" = "left ear", @@ -30,6 +31,7 @@ var/list/department_radio_keys = list( ":T" = "Syndicate", "#T" = "Syndicate", ".T" = "Syndicate", ":U" = "Supply", "#U" = "Supply", ".U" = "Supply", ":G" = "changeling", "#G" = "changeling", ".G" = "changeling", + ":D" = "dronechat", "#D" = "dronechat", ".D" = "dronechat", //kinda localization -- rastaf0 //same keys as above, but on russian keyboard layout. This file uses cp1251 as encoding. diff --git a/code/modules/mob/living/silicon/robot/drone/drone.dm b/code/modules/mob/living/silicon/robot/drone/drone.dm index 272c3a1184..b4d2990782 100644 --- a/code/modules/mob/living/silicon/robot/drone/drone.dm +++ b/code/modules/mob/living/silicon/robot/drone/drone.dm @@ -110,7 +110,7 @@ return emote(copytext(message,2)) else if(length(message) >= 2) - if(copytext(message, 1 ,3) == ":d" || copytext(message, 1 ,3) == ":D") + if(parse_message_mode(message, "NONE") == "dronechat") if(!is_component_functioning("radio")) src << "\red Your radio transmitter isn't functional." diff --git a/code/modules/mob/living/silicon/robot/robot.dm b/code/modules/mob/living/silicon/robot/robot.dm index 7170636006..a6e71ca7b3 100644 --- a/code/modules/mob/living/silicon/robot/robot.dm +++ b/code/modules/mob/living/silicon/robot/robot.dm @@ -281,10 +281,13 @@ /mob/living/silicon/robot/proc/updatename(var/prefix as text) if(prefix) modtype = prefix - if(istype(mmi, /obj/item/device/mmi/posibrain)) - braintype = "Android" + if(mmi) + if(istype(mmi, /obj/item/device/mmi/posibrain)) + braintype = "Android" + else + braintype = "Cyborg" else - braintype = "Cyborg" + braintype = "Robot" var/changed_name = "" if(custom_name) @@ -592,6 +595,10 @@ return if (istype(W, /obj/item/weapon/weldingtool)) + if (src == user) + user << "You lack the reach to be able to repair yourself." + return + if (!getBruteLoss()) user << "Nothing to fix here!" return @@ -1091,18 +1098,24 @@ /mob/living/silicon/robot/Topic(href, href_list) ..() - + + if(usr != src) + return + if (href_list["showalerts"]) robot_alerts() return if (href_list["mod"]) var/obj/item/O = locate(href_list["mod"]) - if (O) + if (istype(O) && (O.loc == src)) O.attack_self(src) if (href_list["act"]) var/obj/item/O = locate(href_list["act"]) + if (!istype(O) || !(O in src.module.modules)) + return + if(activated(O)) src << "Already activated" return diff --git a/code/modules/mob/living/silicon/robot/robot_modules.dm b/code/modules/mob/living/silicon/robot/robot_modules.dm index dbfe037455..45acf2c713 100644 --- a/code/modules/mob/living/silicon/robot/robot_modules.dm +++ b/code/modules/mob/living/silicon/robot/robot_modules.dm @@ -398,14 +398,14 @@ /obj/item/weapon/robot_module/drone name = "drone module" stacktypes = list( - /obj/item/stack/sheet/wood/cyborg = 1, - /obj/item/stack/sheet/mineral/plastic/cyborg = 1, - /obj/item/stack/sheet/rglass/cyborg = 5, + /obj/item/stack/sheet/wood = 1, + /obj/item/stack/sheet/mineral/plastic = 1, + /obj/item/stack/sheet/rglass = 5, /obj/item/stack/tile/wood = 5, /obj/item/stack/rods = 15, /obj/item/stack/tile/plasteel = 15, - /obj/item/stack/sheet/metal/cyborg = 20, - /obj/item/stack/sheet/glass/cyborg = 20, + /obj/item/stack/sheet/metal = 20, + /obj/item/stack/sheet/glass = 20, /obj/item/weapon/cable_coil = 30 ) diff --git a/code/modules/mob/living/simple_animal/simple_animal.dm b/code/modules/mob/living/simple_animal/simple_animal.dm index 5abbe38e28..0fb08d0868 100644 --- a/code/modules/mob/living/simple_animal/simple_animal.dm +++ b/code/modules/mob/living/simple_animal/simple_animal.dm @@ -226,7 +226,9 @@ adjustBruteLoss(damage) /mob/living/simple_animal/bullet_act(var/obj/item/projectile/Proj) - if(!Proj) return + if(!Proj || Proj.nodamage) + return + adjustBruteLoss(Proj.damage) return 0 diff --git a/code/modules/mob/mob.dm b/code/modules/mob/mob.dm index 8887fefd15..e30fbc6e16 100644 --- a/code/modules/mob/mob.dm +++ b/code/modules/mob/mob.dm @@ -736,28 +736,23 @@ note dizziness decrements automatically in the mob's Life() proc. //Updates canmove, lying and icons. Could perhaps do with a rename but I can't think of anything to describe it. /mob/proc/update_canmove() - - var/is_movable - if(buckled && istype(buckled)) - is_movable = buckled.movable - - if(buckled && !is_movable) + if(istype(buckled, /obj/vehicle)) + var/obj/vehicle/V = buckled + if(stat || weakened || paralysis || resting || sleeping || (status_flags & FAKEDEATH)) + lying = 1 + canmove = 0 + pixel_y = V.mob_offset_y - 5 + else + lying = 0 + canmove = 1 + pixel_y = V.mob_offset_y + else if(buckled && (!buckled.movable)) anchored = 1 canmove = 0 if(istype(buckled,/obj/structure/stool/bed/chair) ) lying = 0 - else if(istype(buckled, /obj/vehicle)) - var/obj/vehicle/V = buckled - if(V.standing_mob) - lying = 0 - else - lying = 1 else lying = 1 - else if(buckled && is_movable) - anchored = 0 - canmove = 1 - lying = 0 else if( stat || weakened || paralysis || resting || sleeping || (status_flags & FAKEDEATH)) lying = 1 canmove = 0 @@ -963,8 +958,7 @@ mob/proc/yank_out_object() if(valid_objects.len == 1) //Yanking out last object - removing verb. src.verbs -= /mob/proc/yank_out_object - if(istype(src,/mob/living/carbon/human)) - + if(ishuman(src)) var/mob/living/carbon/human/H = src var/datum/organ/external/affected @@ -975,7 +969,6 @@ mob/proc/yank_out_object() affected.implants -= selection H.shock_stage+=20 - H.bloody_hands(S) affected.take_damage((selection.w_class * 3), 0, 0, 1, "Embedded object extraction") if(prob(selection.w_class * 5)) //I'M SO ANEMIC I COULD JUST -DIE-. @@ -983,6 +976,10 @@ mob/proc/yank_out_object() affected.wounds += I H.custom_pain("Something tears wetly in your [affected] as [selection] is pulled free!", 1) + if (ishuman(U)) + var/mob/living/carbon/human/human_user = U + human_user.bloody_hands(H) + selection.loc = get_turf(src) for(var/obj/item/weapon/O in pinned) diff --git a/code/modules/mob/new_player/new_player.dm b/code/modules/mob/new_player/new_player.dm index 3338989ebe..f044d849ec 100644 --- a/code/modules/mob/new_player/new_player.dm +++ b/code/modules/mob/new_player/new_player.dm @@ -301,6 +301,7 @@ var/mob/living/carbon/human/character = create_character() //creates the human and transfers vars and mind job_master.EquipRank(character, rank, 1) //equips the human + UpdateFactionList(character) EquipCustomItems(character) //Find our spawning point. @@ -330,6 +331,9 @@ if(character.mind.assigned_role != "Cyborg") data_core.manifest_inject(character) ticker.minds += character.mind//Cyborgs and AIs handle this in the transform proc. //TODO!!!!! ~Carn + + //Grab some data from the character prefs for use in random news procs. + AnnounceArrival(character, rank, join_message) else diff --git a/code/modules/mob/new_player/sprite_accessories.dm b/code/modules/mob/new_player/sprite_accessories.dm index b508614397..1e5906eaef 100644 --- a/code/modules/mob/new_player/sprite_accessories.dm +++ b/code/modules/mob/new_player/sprite_accessories.dm @@ -118,6 +118,11 @@ name = "Ponytail 3" icon_state = "hair_ponytail3" + ponytail4 + name = "Ponytail 4" + icon_state = "hair_ponytail4" + gender = FEMALE + sideponytail name = "Side Ponytail" icon_state = "hair_stail" @@ -156,6 +161,11 @@ gender = FEMALE species_allowed = list("Human","Unathi") + beehive2 + name = "Beehive 2" + icon_state = "hair_beehive2" + gender = FEMALE + bobcurl name = "Bobcurl" icon_state = "hair_bobcurl" @@ -189,6 +199,16 @@ icon_state = "hair_combover" gender = MALE + father + name = "Father" + icon_state = "hair_father" + gender = MALE + + reversemohawk + name = "Reverse Mohawk" + icon_state = "hair_reversemohawk" + gender = MALE + devillock name = "Devil Lock" icon_state = "hair_devilock" @@ -223,6 +243,11 @@ name = "Emo" icon_state = "hair_emo" + longemo + name = "Long Emo" + icon_state = "hair_emolong" + gender = FEMALE + shortovereye name = "Overeye Short" icon_state = "hair_shortovereye" @@ -286,6 +311,11 @@ icon_state = "hair_braid" gender = FEMALE + mbraid + name = "Medium Braid" + icon_state = "hair_shortbraid" + gender = FEMALE + braid2 name = "Long Braid" icon_state = "hair_hbraid" diff --git a/code/modules/mob/say.dm b/code/modules/mob/say.dm index 8bb02af6d4..a9648bc95d 100644 --- a/code/modules/mob/say.dm +++ b/code/modules/mob/say.dm @@ -87,6 +87,8 @@ return 1 if (istype(other, src.type) || istype(src, other.type)) return 1 + if(src.alien_talk_understand && other.alien_talk_understand) + return 1 return 0 //Language check. @@ -159,4 +161,3 @@ return L return null - diff --git a/code/modules/organs/blood.dm b/code/modules/organs/blood.dm index 1459098db7..8933427f73 100644 --- a/code/modules/organs/blood.dm +++ b/code/modules/organs/blood.dm @@ -128,8 +128,6 @@ var/const/BLOOD_VOLUME_SURVIVE = 122 continue for(var/datum/wound/W in temp.wounds) if(W.bleeding()) blood_max += W.damage / 4 - if(temp.status & ORGAN_DESTROYED && !(temp.status & ORGAN_GAUZED) && !temp.amputated) - blood_max += 20 //Yer missing a fucking limb. if (temp.open) blood_max += 2 //Yer stomach is cut open drip(blood_max) diff --git a/code/modules/organs/organ_external.dm b/code/modules/organs/organ_external.dm index d1bf4f170d..e1cf22f60e 100644 --- a/code/modules/organs/organ_external.dm +++ b/code/modules/organs/organ_external.dm @@ -155,14 +155,14 @@ // sync the organ's damage with its wounds src.update_damages() - + //If limb took enough damage, try to cut or tear it off if(body_part != UPPER_TORSO && body_part != LOWER_TORSO) //as hilarious as it is, getting hit on the chest too much shouldn't effectively gib you. if(config.limbs_can_break && brute_dam >= max_damage * config.organ_health_multiplier) if( (edge && prob(5 * brute)) || (brute > 20 && prob(2 * brute)) ) droplimb(1) return - + owner.updatehealth() var/result = update_icon() @@ -291,6 +291,8 @@ This function completely restores a damaged organ to perfect condition. //Determines if we even need to process this organ. /datum/organ/external/proc/need_process() + if(destspawn) //Missing limb is missing + return 0 if(status && status != ORGAN_ROBOT) // If it's robotic, that's fine it will have a status. return 1 if(brute_dam || burn_dam) @@ -305,17 +307,6 @@ This function completely restores a damaged organ to perfect condition. return 0 /datum/organ/external/process() - // Process wounds, doing healing etc. Only do this every few ticks to save processing power - if(owner.life_tick % wound_update_accuracy == 0) - update_wounds() - - //Chem traces slowly vanish - if(owner.life_tick % 10 == 0) - for(var/chemID in trace_chemicals) - trace_chemicals[chemID] = trace_chemicals[chemID] - 1 - if(trace_chemicals[chemID] <= 0) - trace_chemicals.Remove(chemID) - //Dismemberment if(status & ORGAN_DESTROYED) if(!destspawn && config.limbs_can_break) @@ -327,6 +318,17 @@ This function completely restores a damaged organ to perfect condition. owner.update_body(1) return + // Process wounds, doing healing etc. Only do this every few ticks to save processing power + if(owner.life_tick % wound_update_accuracy == 0) + update_wounds() + + //Chem traces slowly vanish + if(owner.life_tick % 10 == 0) + for(var/chemID in trace_chemicals) + trace_chemicals[chemID] = trace_chemicals[chemID] - 1 + if(trace_chemicals[chemID] <= 0) + trace_chemicals.Remove(chemID) + //Bone fracurtes if(config.bones_can_break && brute_dam > min_broken_damage * config.organ_health_multiplier && !(status & ORGAN_ROBOT)) src.fracture() @@ -585,13 +587,27 @@ Note that amputating the affected organ does in fact remove the infection from t src.status &= ~ORGAN_BROKEN src.status &= ~ORGAN_BLEEDING src.status &= ~ORGAN_SPLINTED + src.status &= ~ORGAN_DEAD for(var/implant in implants) del(implant) + germ_level = 0 + + //Replace all wounds on that arm with one wound on parent organ. + wounds.Cut() + if (parent) + var/datum/wound/W + if(max_damage < 50) + W = new/datum/wound/lost_limb/small(max_damage) + else + W = new/datum/wound/lost_limb(max_damage) + parent.wounds += W + parent.update_damages() + update_damages() + // If any organs are attached to this, destroy them - for(var/datum/organ/external/O in owner.organs) - if(O.parent == src) - O.droplimb(1) + for(var/datum/organ/external/O in children) + O.droplimb(1) var/obj/organ //Dropped limb object switch(body_part) diff --git a/code/modules/organs/wound.dm b/code/modules/organs/wound.dm index d20fc0dbfb..383e6be014 100644 --- a/code/modules/organs/wound.dm +++ b/code/modules/organs/wound.dm @@ -31,7 +31,7 @@ var/germ_level = 0 /* These are defined by the wound type and should not be changed */ - + // stages such as "cut", "deep cut", etc. var/list/stages // internal wounds can only be fixed through surgery @@ -51,7 +51,7 @@ // helper lists var/tmp/list/desc_list = list() var/tmp/list/damage_list = list() - + New(var/damage) created = world.time @@ -65,7 +65,7 @@ src.damage = damage max_bleeding_stage = src.desc_list.len - max_bleeding_stage - + // initialize with the appropriate stage src.init_stage(damage) @@ -74,7 +74,7 @@ // returns 1 if there's a next stage, 0 otherwise proc/init_stage(var/initial_damage) current_stage = stages.len - + while(src.current_stage > 1 && src.damage_list[current_stage-1] <= initial_damage / src.amount) src.current_stage-- @@ -84,20 +84,20 @@ // the amount of damage per wound proc/wound_damage() return src.damage / src.amount - + proc/can_autoheal() if(src.wound_damage() <= autoheal_cutoff) return 1 - + return is_treated() - + // checks whether the wound has been appropriately treated proc/is_treated() if(damage_type == BRUISE || damage_type == CUT) return bandaged else if(damage_type == BURN) return salved - + // Checks whether other other can be merged into src. proc/can_merge(var/datum/wound/other) if (other.type != src.type) return 0 @@ -128,10 +128,10 @@ if (disinfected) germ_level = 0 //reset this, just in case return 0 - + if (damage_type == BRUISE && !bleeding()) //bruises only infectable if bleeding return 0 - + var/dam_coef = round(damage/10) switch (damage_type) if (BRUISE) @@ -179,32 +179,32 @@ proc/can_worsen(damage_type, damage) if (src.damage_type != damage_type) return 0 //incompatible damage types - + if (src.amount > 1) return 0 - + //with 1.5*, a shallow cut will be able to carry at most 30 damage, //37.5 for a deep cut //52.5 for a flesh wound, etc. var/max_wound_damage = 1.5*src.damage_list[1] if (src.damage + damage > max_wound_damage) return 0 - + return 1 proc/bleeding() if (src.internal) return 0 // internal wounds don't bleed in the sense of this function - + if (current_stage > max_bleeding_stage) return 0 - + if (bandaged||clamped) return 0 - + if (wound_damage() <= 30 && bleed_timer <= 0) return 0 //Bleed timer has run out. Wounds with more than 30 damage don't stop bleeding on their own. - + return (damage_type == BRUISE && wound_damage() >= 20 || damage_type == CUT && wound_damage() >= 5) /** CUTS **/ @@ -273,3 +273,15 @@ datum/wound/cut/massive stages = list("severed vein" = 30, "cut vein" = 20, "damaged vein" = 10, "bruised vein" = 5) autoheal_cutoff = 5 max_bleeding_stage = 0 //all stages bleed. It's called internal bleeding after all. + +/** EXTERNAL ORGAN LOSS **/ +/datum/wound/lost_limb + damage_type = CUT + stages = list("ripped stump" = 65, "bloody stump" = 50, "clotted stump" = 25, "scarred stump" = 0) + max_bleeding_stage = 3 + + can_merge(var/datum/wound/other) + return 0 //cannot be merged + +/datum/wound/lost_limb/small + stages = list("ripped stump" = 40, "bloody stump" = 30, "clotted stump" = 15, "scarred stump" = 0) \ No newline at end of file diff --git a/code/modules/paperwork/clipboard.dm b/code/modules/paperwork/clipboard.dm index ea49067e13..ca128c2c10 100644 --- a/code/modules/paperwork/clipboard.dm +++ b/code/modules/paperwork/clipboard.dm @@ -44,6 +44,7 @@ return /obj/item/weapon/clipboard/attackby(obj/item/weapon/W as obj, mob/user as mob) + if(istype(W, /obj/item/weapon/paper) || istype(W, /obj/item/weapon/photo)) user.drop_item() W.loc = src @@ -51,9 +52,11 @@ toppaper = W user << "You clip the [W] onto \the [src]." update_icon() - else if(toppaper) - toppaper.attackby(usr.get_active_hand(), usr) + + else if(istype(toppaper) && istype(W, /obj/item/weapon/pen)) + toppaper.attackby(W, usr) update_icon() + return /obj/item/weapon/clipboard/attack_self(mob/user as mob) @@ -85,32 +88,39 @@ if((usr.stat || usr.restrained())) return - if(usr.contents.Find(src)) + if(src.loc == usr) if(href_list["pen"]) - if(haspen) + if(istype(haspen) && (haspen.loc == src)) haspen.loc = usr.loc usr.put_in_hands(haspen) haspen = null - if(href_list["addpen"]) + else if(href_list["addpen"]) if(!haspen) - if(istype(usr.get_active_hand(), /obj/item/weapon/pen)) - var/obj/item/weapon/pen/W = usr.get_active_hand() + var/obj/item/weapon/pen/W = usr.get_active_hand() + if(istype(W, /obj/item/weapon/pen)) usr.drop_item() W.loc = src haspen = W usr << "You slot the pen into \the [src]." - if(href_list["write"]) - var/obj/item/P = locate(href_list["write"]) - if(P) - if(usr.get_active_hand()) - P.attackby(usr.get_active_hand(), usr) + else if(href_list["write"]) + var/obj/item/weapon/P = locate(href_list["write"]) + + if(P && (P.loc == src) && istype(P, /obj/item/weapon/paper) && (P == toppaper) ) + + var/obj/item/I = usr.get_active_hand() + + if(istype(I, /obj/item/weapon/pen)) + + P.attackby(I, usr) - if(href_list["remove"]) + else if(href_list["remove"]) var/obj/item/P = locate(href_list["remove"]) - if(P) + + if(P && (P.loc == src) && (istype(P, /obj/item/weapon/paper) || istype(P, /obj/item/weapon/photo)) ) + P.loc = usr.loc usr.put_in_hands(P) if(P == toppaper) @@ -121,9 +131,11 @@ else toppaper = null - if(href_list["read"]) + else if(href_list["read"]) var/obj/item/weapon/paper/P = locate(href_list["read"]) - if(P) + + if(P && (P.loc == src) && istype(P, /obj/item/weapon/paper) ) + if(!(istype(usr, /mob/living/carbon/human) || istype(usr, /mob/dead/observer) || istype(usr, /mob/living/silicon))) usr << browse("[P.name][stars(P.info)][P.stamps]", "window=[P.name]") onclose(usr, "[P.name]") @@ -131,18 +143,18 @@ usr << browse("[P.name][P.info][P.stamps]", "window=[P.name]") onclose(usr, "[P.name]") - if(href_list["look"]) + else if(href_list["look"]) var/obj/item/weapon/photo/P = locate(href_list["look"]) - if(P) + if(P && (P.loc == src) && istype(P, /obj/item/weapon/photo) ) P.show(usr) - if(href_list["top"]) + else if(href_list["top"]) // currently unused var/obj/item/P = locate(href_list["top"]) - if(P) + if(P && (P.loc == src) && istype(P, /obj/item/weapon/paper) ) toppaper = P usr << "You move [P.name] to the top." //Update everything attack_self(usr) update_icon() - return \ No newline at end of file + return diff --git a/code/modules/paperwork/filingcabinet.dm b/code/modules/paperwork/filingcabinet.dm index 1dd51443fb..5bb1dde195 100644 --- a/code/modules/paperwork/filingcabinet.dm +++ b/code/modules/paperwork/filingcabinet.dm @@ -57,9 +57,7 @@ user.set_machine(src) var/dat = "
" - var/i - for(i=contents.len, i>=1, i--) - var/obj/item/P = contents[i] + for(var/obj/item/P in src) dat += "" dat += "
[P.name]
" user << browse("[name][dat]", "window=filingcabinet;size=350x300") @@ -89,12 +87,13 @@ //var/retrieveindex = text2num(href_list["retrieve"]) var/obj/item/P = locate(href_list["retrieve"])//contents[retrieveindex] - if(P && in_range(src, usr)) + if(istype(P) && (P.loc == src) && src.Adjacent(usr)) usr.put_in_hands(P) updateUsrDialog() icon_state = "[initial(icon_state)]-open" - sleep(5) - icon_state = initial(icon_state) + spawn(0) + sleep(5) + icon_state = initial(icon_state) /* diff --git a/code/modules/paperwork/folders.dm b/code/modules/paperwork/folders.dm index 0f1b612e93..868fac3053 100644 --- a/code/modules/paperwork/folders.dm +++ b/code/modules/paperwork/folders.dm @@ -59,34 +59,34 @@ if((usr.stat || usr.restrained())) return - if(usr.contents.Find(src)) + if(src.loc == usr) if(href_list["remove"]) var/obj/item/P = locate(href_list["remove"]) - if(P && P.loc == src) + if(P && (P.loc == src) && istype(P)) P.loc = usr.loc usr.put_in_hands(P) - if(href_list["read"]) + else if(href_list["read"]) var/obj/item/weapon/paper/P = locate(href_list["read"]) - if(P) + if(P && (P.loc == src) && istype(P)) if(!(istype(usr, /mob/living/carbon/human) || istype(usr, /mob/dead/observer) || istype(usr, /mob/living/silicon))) usr << browse("[P.name][stars(P.info)][P.stamps]", "window=[P.name]") onclose(usr, "[P.name]") else usr << browse("[P.name][P.info][P.stamps]", "window=[P.name]") onclose(usr, "[P.name]") - if(href_list["look"]) + else if(href_list["look"]) var/obj/item/weapon/photo/P = locate(href_list["look"]) - if(P) + if(P && (P.loc == src) && istype(P)) P.show(usr) - if(href_list["browse"]) + else if(href_list["browse"]) var/obj/item/weapon/paper_bundle/P = locate(href_list["browse"]) - if(P) + if(P && (P.loc == src) && istype(P)) P.attack_self(usr) onclose(usr, "[P.name]") //Update everything attack_self(usr) update_icon() - return \ No newline at end of file + return diff --git a/code/modules/paperwork/paper.dm b/code/modules/paperwork/paper.dm index bd7a82a125..515d6b0bc8 100644 --- a/code/modules/paperwork/paper.dm +++ b/code/modules/paperwork/paper.dm @@ -113,6 +113,22 @@ user.visible_message("You show the paper to [M]. ", \ " [user] holds up a paper and shows it to [M]. ") M << examine() + + else if(user.zone_sel.selecting == "mouth") // lipstick wiping + if(ishuman(M)) + var/mob/living/carbon/human/H = M + if(H == user) + user << "You wipe off the lipstick with [src]." + H.lip_style = null + H.update_body() + else + user.visible_message("[user] begins to wipe [H]'s lipstick off with \the [src].", \ + "You begin to wipe off [H]'s lipstick.") + if(do_after(user, 10) && do_after(H, 10, 5, 0)) //user needs to keep their active hand, H does not. + user.visible_message("[user] wipes [H]'s lipstick off with \the [src].", \ + "You wipe off [H]'s lipstick.") + H.lip_style = null + H.update_body() /obj/item/weapon/paper/proc/addtofield(var/id, var/text, var/links = 0) var/locid = 0 @@ -294,7 +310,8 @@ iscrayon = 1 - if((!in_range(src, usr) && loc != usr && !( istype(loc, /obj/item/weapon/clipboard) ) && loc.loc != usr && usr.get_active_hand() != i)) // Some check to see if he's allowed to write + // if paper is not in usr, then it must be near them, or in a clipboard or folder, which must be in or near usr + if(src.loc != usr && !src.Adjacent(usr) && !((istype(src.loc, /obj/item/weapon/clipboard) || istype(src.loc, /obj/item/weapon/folder)) && (src.loc.loc == usr || src.loc.Adjacent(usr)) ) ) return /* t = checkhtml(t) diff --git a/code/modules/power/power.dm b/code/modules/power/power.dm index 2fb3171104..c2421ea3de 100644 --- a/code/modules/power/power.dm +++ b/code/modules/power/power.dm @@ -513,6 +513,9 @@ //No animations will be performed by this proc. /proc/electrocute_mob(mob/living/carbon/M as mob, var/power_source, var/obj/source, var/siemens_coeff = 1.0) if(istype(M.loc,/obj/mecha)) return 0 //feckin mechs are dumb + + //This is for performance optimization only. + //DO NOT modify siemens_coeff here. That is checked in human/electrocute_act() if(istype(M,/mob/living/carbon/human)) var/mob/living/carbon/human/H = M if(H.gloves) diff --git a/code/modules/projectiles/guns/projectile/crossbow.dm b/code/modules/projectiles/guns/projectile/crossbow.dm index e9bfb12b84..84bd0d096a 100644 --- a/code/modules/projectiles/guns/projectile/crossbow.dm +++ b/code/modules/projectiles/guns/projectile/crossbow.dm @@ -84,6 +84,7 @@ if(!..()) return //Only do this on a successful shot. icon_state = "crossbow" + tension = 0 /obj/item/weapon/gun/launcher/crossbow/attack_self(mob/living/user as mob) if(tension) diff --git a/code/modules/reagents/Chemistry-Reagents.dm b/code/modules/reagents/Chemistry-Reagents.dm index 3740aca7c2..cc4a5b1354 100644 --- a/code/modules/reagents/Chemistry-Reagents.dm +++ b/code/modules/reagents/Chemistry-Reagents.dm @@ -2081,25 +2081,29 @@ datum description = "This is what makes chilis hot." reagent_state = LIQUID color = "#B31008" // rgb: 179, 16, 8 - + on_mob_life(var/mob/living/M as mob) - if(!M) M = holder.my_atom - if(!data) data = 1 - switch(data) - if(1 to 15) - M.bodytemperature += 5 * TEMPERATURE_DAMAGE_COEFFICIENT - if(holder.has_reagent("frostoil")) - holder.remove_reagent("frostoil", 5) - if(istype(M, /mob/living/carbon/slime)) - M.bodytemperature += rand(5,20) - if(15 to 25) - M.bodytemperature += 10 * TEMPERATURE_DAMAGE_COEFFICIENT - if(istype(M, /mob/living/carbon/slime)) - M.bodytemperature += rand(10,20) - if(25 to INFINITY) - M.bodytemperature += 15 * TEMPERATURE_DAMAGE_COEFFICIENT - if(istype(M, /mob/living/carbon/slime)) - M.bodytemperature += rand(15,20) + if(!M) + M = holder.my_atom + if(!data) + data = 1 + if(ishuman(M)) + var/mob/living/carbon/human/H = M + if(H.species && !(H.species.flags & (NO_PAIN | IS_SYNTHETIC)) ) + switch(data) + if(1 to 2) + H << "\red Your insides feel uncomfortably hot !" + if(2 to 20) + if(prob(5)) + H << "\red Your insides feel uncomfortably hot !" + if(20 to INFINITY) + H.apply_effect(2,AGONY,0) + if(prob(5)) + H.visible_message("[H] [pick("dry heaves!","coughs!","splutters!")]") + H << "\red You feel like your insides are burning !" + else if(istype(M, /mob/living/carbon/slime)) + M.bodytemperature += rand(10,25) + holder.remove_reagent("frostoil", 5) holder.remove_reagent(src.id, FOOD_METABOLISM) data++ ..() @@ -2165,10 +2169,29 @@ datum victim.Weaken(5) //victim.Paralyse(10) //victim.drop_item() + on_mob_life(var/mob/living/M as mob) - if(!M) M = holder.my_atom - if(prob(5)) - M.visible_message("[M] [pick("dry heaves!","coughs!","splutters!")]") + if(!M) + M = holder.my_atom + if(!data) + data = 1 + if(ishuman(M)) + var/mob/living/carbon/human/H = M + if(H.species && !(H.species.flags & (NO_PAIN | IS_SYNTHETIC)) ) + switch(data) + if(1) + H << "\red You feel like your insides are burning !" + if(2 to INFINITY) + H.apply_effect(4,AGONY,0) + if(prob(5)) + H.visible_message("[H] [pick("dry heaves!","coughs!","splutters!")]") + H << "\red You feel like your insides are burning !" + else if(istype(M, /mob/living/carbon/slime)) + M.bodytemperature += rand(15,30) + holder.remove_reagent("frostoil", 5) + holder.remove_reagent(src.id, FOOD_METABOLISM) + data++ + ..() return frostoil @@ -3063,6 +3086,9 @@ datum paperaffected.clearpaper() usr << "The solution dissolves the ink on the paper." if(istype(O,/obj/item/weapon/book)) + if(istype(O,/obj/item/weapon/book/tome)) + usr << "The solution does nothing. Whatever this is, it isn't normal ink." + return if(volume >= 5) var/obj/item/weapon/book/affectedbook = O affectedbook.dat = null diff --git a/code/modules/reagents/reagent_containers/food/drinks/drinkingglass.dm b/code/modules/reagents/reagent_containers/food/drinks/drinkingglass.dm index 454badcf19..fa788fc5b4 100644 --- a/code/modules/reagents/reagent_containers/food/drinks/drinkingglass.dm +++ b/code/modules/reagents/reagent_containers/food/drinks/drinkingglass.dm @@ -605,8 +605,8 @@ center_of_mass = list("x"=16, "y"=10) else icon_state = "glass_empty" - name = "Drinking glass" - desc = "Your standard drinking glass" + name = "glass" + desc = "Your standard drinking glass." center_of_mass = list("x"=16, "y"=10) return diff --git a/code/modules/reagents/reagent_dispenser.dm b/code/modules/reagents/reagent_dispenser.dm index fd5821784e..5444845032 100644 --- a/code/modules/reagents/reagent_dispenser.dm +++ b/code/modules/reagents/reagent_dispenser.dm @@ -147,6 +147,10 @@ /obj/structure/reagent_dispensers/fueltank/bullet_act(var/obj/item/projectile/Proj) if(istype(Proj ,/obj/item/projectile/beam)||istype(Proj,/obj/item/projectile/bullet)) + if(istype(Proj.firer)) + message_admins("[key_name_admin(Proj.firer)] shot fueltank at ([loc.x],[loc.y],[loc.z]).") + log_game("[key_name(Proj.firer)] shot fueltank at ([loc.x],[loc.y],[loc.z]).") + if(!istype(Proj ,/obj/item/projectile/beam/lastertag) && !istype(Proj ,/obj/item/projectile/beam/practice) ) explode() diff --git a/code/game/machinery/embedded_controller/escape_pod_docking_controller.dm b/code/modules/shuttles/escape_pods.dm similarity index 81% rename from code/game/machinery/embedded_controller/escape_pod_docking_controller.dm rename to code/modules/shuttles/escape_pods.dm index 943b1a59fa..0261997a9d 100644 --- a/code/game/machinery/embedded_controller/escape_pod_docking_controller.dm +++ b/code/modules/shuttles/escape_pods.dm @@ -1,3 +1,22 @@ +/datum/shuttle/ferry/escape_pod + var/datum/computer/file/embedded_program/docking/simple/escape_pod/arming_controller + +/datum/shuttle/ferry/escape_pod/can_launch() + if(arming_controller && !arming_controller.armed) //must be armed + return 0 + if(location) + return 0 //it's a one-way trip. + return ..() + +/datum/shuttle/ferry/escape_pod/can_force() + if (arming_controller.eject_time && world.time < arming_controller.eject_time + 50) + return 0 //dont allow force launching until 5 seconds after the arming controller has reached it's countdown + return ..() + +/datum/shuttle/ferry/escape_pod/can_cancel() + return 0 + + //This controller goes on the escape pod itself /obj/machinery/embedded_controller/radio/simple_docking_controller/escape_pod name = "escape pod controller" @@ -11,7 +30,7 @@ "override_enabled" = docking_program.override_enabled, "door_state" = docking_program.memory["door_status"]["state"], "door_lock" = docking_program.memory["door_status"]["lock"], - "can_force" = pod.can_force(), + "can_force" = pod.can_force() || (emergency_shuttle.departed && pod.can_launch()), //allow players to manually launch ahead of time if the shuttle leaves "is_armed" = pod.arming_controller.armed, ) @@ -30,7 +49,10 @@ if("manual_arm") pod.arming_controller.arm() if("force_launch") - pod.force_launch(src) + if (pod.can_force()) + pod.force_launch(src) + else if (emergency_shuttle.departed && pod.can_launch()) //allow players to manually launch ahead of time if the shuttle leaves + pod.launch(src) return 0 diff --git a/code/modules/shuttles/shuttle_emergency.dm b/code/modules/shuttles/shuttle_emergency.dm index 98f0223247..c7fff897e6 100644 --- a/code/modules/shuttles/shuttle_emergency.dm +++ b/code/modules/shuttles/shuttle_emergency.dm @@ -223,38 +223,13 @@ if(..()) return - if(href_list["auth"]) - /* - //This doesn't work at all. - if (!emagged && href_list["auth"] == -1) - //They selected an empty entry. Try to scan their id. - if (ishuman(usr)) - var/mob/living/carbon/human/H = usr - if (!read_authorization(H.get_active_hand())) //try to read what's in their hand first - read_authorization(H.wear_id) - else - */ - //remove the authorization - var/dna_hash = href_list["auth"] + if(href_list["removeid"]) + var/dna_hash = href_list["removeid"] authorized -= dna_hash - - - - -/datum/shuttle/ferry/escape_pod - var/datum/computer/file/embedded_program/docking/simple/escape_pod/arming_controller - -/datum/shuttle/ferry/escape_pod/can_launch() - if(arming_controller && !arming_controller.armed) - return 0 - if(location) - return 0 //it's a one-way trip. - return ..() - -/datum/shuttle/ferry/escape_pod/can_force() - if (arming_controller.eject_time && world.time < arming_controller.eject_time + 50) - return 0 //dont allow force launching until 5 seconds after the arming controller has reached it's countdown - return ..() - -/datum/shuttle/ferry/escape_pod/can_cancel() - return 0 + + if(!emagged && href_list["scanid"]) + //They selected an empty entry. Try to scan their id. + if (ishuman(usr)) + var/mob/living/carbon/human/H = usr + if (!read_authorization(H.get_active_hand())) //try to read what's in their hand first + read_authorization(H.wear_id) diff --git a/code/modules/supermatter/supermatter.dm b/code/modules/supermatter/supermatter.dm index 89b29c47a6..c87886b9db 100644 --- a/code/modules/supermatter/supermatter.dm +++ b/code/modules/supermatter/supermatter.dm @@ -141,11 +141,13 @@ if(damage > explosion_point) for(var/mob/living/mob in living_mob_list) - if(istype(mob, /mob/living/carbon/human)) - //Hilariously enough, running into a closet should make you get hit the hardest. - mob:hallucination += max(50, min(300, DETONATION_HALLUCINATION * sqrt(1 / (get_dist(mob, src) + 1)) ) ) - var/rads = DETONATION_RADS * sqrt( 1 / (get_dist(mob, src) + 1) ) - mob.apply_effect(rads, IRRADIATE) + if(loc.z == mob.loc.z) + if(istype(mob, /mob/living/carbon/human)) + //Hilariously enough, running into a closet should make you get hit the hardest. + var/mob/living/carbon/human/H = mob + H.hallucination += max(50, min(300, DETONATION_HALLUCINATION * sqrt(1 / (get_dist(mob, src) + 1)) ) ) + var/rads = DETONATION_RADS * sqrt( 1 / (get_dist(mob, src) + 1) ) + mob.apply_effect(rads, IRRADIATE) explode() else @@ -328,10 +330,15 @@ if(is_type_in_list(X, uneatable)) continue if(((X) && (!istype(X,/mob/living/carbon/human)))) step_towards(X,src) - if(!X:anchored) //unanchored objects pulled twice as fast + if(istype(X, /obj)) //unanchored objects pulled twice as fast + var/obj/O = X + if(!O.anchored) + step_towards(X,src) + else step_towards(X,src) if(istype(X, /obj/structure/window)) //shatter windows - X.ex_act(2.0) + var/obj/structure/window/W = X + W.ex_act(2.0) else if(istype(X,/mob/living/carbon/human)) var/mob/living/carbon/human/H = X if(istype(H.shoes,/obj/item/clothing/shoes/magboots)) diff --git a/code/modules/vehicles/cargo_train.dm b/code/modules/vehicles/cargo_train.dm index 11d0c53fb8..ea3f7b72e6 100644 --- a/code/modules/vehicles/cargo_train.dm +++ b/code/modules/vehicles/cargo_train.dm @@ -7,10 +7,9 @@ powered = 1 locked = 0 - standing_mob = 1 load_item_visible = 1 load_offset_x = 0 - load_offset_y = 7 + mob_offset_y = 7 var/car_limit = 3 //how many cars an engine can pull before performance degrades active_engines = 1 @@ -31,10 +30,10 @@ passenger_allowed = 0 locked = 0 - standing_mob = 1 load_item_visible = 1 load_offset_x = 0 load_offset_y = 4 + mob_offset_y = 8 //------------------------------------------- // Standard procs @@ -43,13 +42,13 @@ ..() cell = new /obj/item/weapon/cell/high verbs -= /atom/movable/verb/pull - verbs -= /obj/vehicle/train/cargo/engine/verb/stop_engine key = new() var/image/I = new(icon = 'icons/obj/vehicles.dmi', icon_state = "cargo_engine_overlay", layer = src.layer + 0.2) //over mobs overlays += I + turn_off() //so engine verbs are correctly set /obj/vehicle/train/cargo/engine/Move() - if(on && cell.charge < power_use) + if(on && cell.charge < charge_use) turn_off() update_stats() if(load && is_train_head()) @@ -117,6 +116,25 @@ ..() update_stats() + verbs -= /obj/vehicle/train/cargo/engine/verb/stop_engine + verbs -= /obj/vehicle/train/cargo/engine/verb/start_engine + + if(on) + verbs += /obj/vehicle/train/cargo/engine/verb/stop_engine + else + verbs += /obj/vehicle/train/cargo/engine/verb/start_engine + +/obj/vehicle/train/cargo/engine/turn_off() + ..() + + verbs -= /obj/vehicle/train/cargo/engine/verb/stop_engine + verbs -= /obj/vehicle/train/cargo/engine/verb/start_engine + + if(!on) + verbs += /obj/vehicle/train/cargo/engine/verb/start_engine + else + verbs += /obj/vehicle/train/cargo/engine/verb/stop_engine + /obj/vehicle/train/cargo/RunOver(var/mob/living/carbon/human/H) var/list/parts = list("head", "chest", "l_leg", "r_leg", "l_arm", "r_arm") @@ -149,7 +167,7 @@ return 0 if(is_train_head()) - if(direction == reverse_direction(dir)) + if(direction == reverse_direction(dir) && tow) return 0 if(Move(get_step(src, direction))) return 1 @@ -165,20 +183,7 @@ if(get_dist(usr,src) <= 1) usr << "The power light is [on ? "on" : "off"].\nThere are[key ? "" : " no"] keys in the ignition." - -/obj/vehicle/train/cargo/engine/verb/check_power() - set name = "Check power level" - set category = "Object" - set src in view(1) - - if(!istype(usr, /mob/living/carbon/human)) - return - - if(!cell) - usr << "There is no power cell installed in [src]." - return - - usr << "The power meter reads [round(cell.percent(), 0.01)]%" + usr << "The charge meter reads [cell? round(cell.percent(), 0.01) : 0]%" /obj/vehicle/train/cargo/engine/verb/start_engine() set name = "Start engine" @@ -195,10 +200,8 @@ turn_on() if (on) usr << "You start [src]'s engine." - verbs += /obj/vehicle/train/cargo/engine/verb/stop_engine - verbs -= /obj/vehicle/train/cargo/engine/verb/start_engine else - if(cell.charge < power_use) + if(cell.charge < charge_use) usr << "[src] is out of power." else usr << "[src]'s engine won't start." @@ -218,8 +221,6 @@ turn_off() if (!on) usr << "You stop [src]'s engine." - verbs -= /obj/vehicle/train/cargo/engine/verb/stop_engine - verbs += /obj/vehicle/train/cargo/engine/verb/start_engine /obj/vehicle/train/cargo/engine/verb/remove_key() set name = "Remove key" @@ -252,10 +253,7 @@ return 0 ..() - - if(istype(load, /mob/living/carbon/human)) - load.pixel_y += 4 - + if(load) return 1 @@ -277,13 +275,22 @@ // more engines increases this limit by car_limit per // engine. //------------------------------------------------------- -/obj/vehicle/train/cargo/engine/update_train_stats() - ..() +/obj/vehicle/train/cargo/engine/update_car(var/train_length, var/active_engines) + src.train_length = train_length + src.active_engines = active_engines - update_move_delay() + //Update move delay + if(!is_train_head() || !on) + move_delay = initial(move_delay) //so that engines that have been turned off don't lag behind + else + move_delay = max(0, (-car_limit * active_engines) + train_length - active_engines) //limits base overweight so you cant overspeed trains + move_delay *= (1 / max(1, active_engines)) * 2 //overweight penalty (scaled by the number of engines) + move_delay += config.run_speed //base reference speed + move_delay *= 1.1 //makes cargo trains 10% slower than running when not overweight -/obj/vehicle/train/cargo/trolley/update_train_stats() - ..() +/obj/vehicle/train/cargo/trolley/update_car(var/train_length, var/active_engines) + src.train_length = train_length + src.active_engines = active_engines if(!lead && !tow) anchored = 0 @@ -294,12 +301,3 @@ else anchored = 1 verbs -= /atom/movable/verb/pull - -/obj/vehicle/train/cargo/engine/proc/update_move_delay() - if(!is_train_head() || !on) - move_delay = initial(move_delay) //so that engines that have been turned off don't lag behind - else - move_delay = max(0, (-car_limit * active_engines) + train_length - active_engines) //limits base overweight so you cant overspeed trains - move_delay *= (1 / max(1, active_engines)) * 2 //overweight penalty (scaled by the number of engines) - move_delay += config.run_speed //base reference speed - move_delay *= 1.05 //makes cargo trains 5% slower than running when not overweight \ No newline at end of file diff --git a/code/modules/vehicles/train.dm b/code/modules/vehicles/train.dm index d29933b5ed..d8e372d818 100644 --- a/code/modules/vehicles/train.dm +++ b/code/modules/vehicles/train.dm @@ -32,6 +32,8 @@ tow.Move(old_loc) return 1 else + if(lead) + unattach() return 0 /obj/vehicle/train/Bump(atom/Obstacle) @@ -48,14 +50,23 @@ if(istype(A, /mob/living)) var/mob/living/M = A visible_message("\red [src] knocks over [M]!") - M.apply_effects(5, 5) //knock people down if you hit them - M.apply_damages(5 * train_length / move_delay) // and do damage according to how fast the train is going and how heavy it is + M.apply_effects(5, 5) //knock people down if you hit them + M.apply_damages(22 / move_delay) // and do damage according to how fast the train is going if(istype(load, /mob/living/carbon/human)) var/mob/living/D = load D << "\red You hit [M]!" msg_admin_attack("[D.name] ([D.ckey]) hit [M.name] ([M.ckey]) with [src]. (JMP)") +//------------------------------------------- +// Vehicle procs +//------------------------------------------- +/obj/vehicle/train/explode() + if (tow) + tow.unattach() + unattach() + ..() + //------------------------------------------- // Interaction procs @@ -79,7 +90,7 @@ return 1 /obj/vehicle/train/MouseDrop_T(var/atom/movable/C, mob/user as mob) - if(user.buckled || user.stat || user.restrained() || !Adjacent(user) || !user.Adjacent(C) || !istype(C)) + if(user.buckled || user.stat || user.restrained() || !Adjacent(user) || !user.Adjacent(C) || !istype(C) || (user == C && !user.canmove)) return if(istype(C,/obj/vehicle/train)) latch(C, user) @@ -132,6 +143,15 @@ if (T.tow) user << "\red [T] is already towing something." return + + //check for cycles. + var/obj/vehicle/train/next_car = T + while (next_car) + if (next_car == src) + user << "\red That seems very silly." + return + next_car = next_car.lead + //latch with src as the follower lead = T T.tow = src @@ -182,23 +202,28 @@ // size of the train, to limit super long trains. //------------------------------------------------------- /obj/vehicle/train/update_stats() - if(tow) - return tow.update_stats() //take us to the very end - else - update_train_stats() //we're at the end + //first, seek to the end of the train + var/obj/vehicle/train/T = src + while(T.tow) + //check for cyclic train. + if (T.tow == src) + lead.tow = null + lead.update_stats() + + lead = null + update_stats() + return + T = T.tow -/obj/vehicle/train/proc/update_train_stats() - if(powered && on) - active_engines = 1 //increment active engine count if this is a running engine - else - active_engines = 0 + //now walk back to the front. + var/active_engines = 0 + var/train_length = 0 + while(T) + train_length++ + if (powered && on) + active_engines++ + T.update_car(train_length, active_engines) + T = T.lead - train_length = 1 - - if(istype(tow)) - active_engines += tow.active_engines - train_length += tow.train_length - - //update the next section of train ahead of us - if(istype(lead)) - lead.update_train_stats() \ No newline at end of file +/obj/vehicle/train/proc/update_car(var/train_length, var/active_engines) + return diff --git a/code/modules/vehicles/vehicle.dm b/code/modules/vehicles/vehicle.dm index caec0c896a..c018064349 100644 --- a/code/modules/vehicles/vehicle.dm +++ b/code/modules/vehicles/vehicle.dm @@ -22,13 +22,13 @@ var/movable = 1 var/obj/item/weapon/cell/cell - var/power_use = 5 //set this to adjust the amount of power the vehicle uses per move + var/charge_use = 5 //set this to adjust the amount of power the vehicle uses per move - var/standing_mob = 0 //if a mob loaded on the vehicle should be standing var/atom/movable/load //all vehicles can take a load, since they should all be a least drivable var/load_item_visible = 1 //set if the loaded item should be overlayed on the vehicle sprite var/load_offset_x = 0 //pixel_x offset for item overlay var/load_offset_y = 0 //pixel_y offset for item overlay + var/mob_offset_y = 0 //pixel_y offset for mob overlay //------------------------------------------- // Standard procs @@ -39,16 +39,20 @@ /obj/vehicle/Move() if(world.time > l_move_time + move_delay) - if(on && powered && cell.charge < power_use) + if(on && powered && cell.charge < charge_use) turn_off() var/init_anc = anchored anchored = 0 - if(..()) - if(on && powered) - cell.use(power_use) + if(!..()) + anchored = init_anc + return 0 + anchored = init_anc + if(on && powered) + cell.use(charge_use) + if(load) load.forceMove(loc)// = loc load.dir = dir @@ -168,7 +172,7 @@ /obj/vehicle/proc/turn_on() if(stat) return 0 - if(powered && cell.charge < power_use) + if(powered && cell.charge < charge_use) return 0 on = 1 luminosity = initial(luminosity) @@ -200,6 +204,11 @@ cell.update_icon() cell = null + //stuns people who are thrown off a train that has been blown up + if(istype(load, /mob/living)) + var/mob/living/M = load + M.apply_effects(5, 5) + unload() new /obj/effect/gibspawner/robot(Tsec) @@ -219,7 +228,7 @@ turn_off() return - if(cell.charge < power_use) + if(cell.charge < charge_use) turn_off() return @@ -280,7 +289,10 @@ if(load_item_visible) C.pixel_x += load_offset_x - C.pixel_y += load_offset_y + if(ismob(C)) + C.pixel_y += mob_offset_y + else + C.pixel_y += load_offset_y C.layer = layer + 0.1 //so it sits above the vehicle if(ismob(C)) diff --git a/html/changelog.html b/html/changelog.html index 4145379370..e5fe332b92 100644 --- a/html/changelog.html +++ b/html/changelog.html @@ -142,6 +142,11 @@ should be listed in the changelog upon commit though. Thanks. -->