From 1caba774316571d4ffae48ccfbd90267fe464836 Mon Sep 17 00:00:00 2001 From: CitadelStationBot Date: Tue, 29 Aug 2017 17:16:17 -0500 Subject: [PATCH 01/74] Server tools versioning and fix to displayed testmerges --- code/__DEFINES/server_tools.dm | 4 +++- code/datums/helper_datums/getrev.dm | 10 ++++++++-- code/modules/server_tools/server_tools.dm | 4 ++++ 3 files changed, 15 insertions(+), 3 deletions(-) diff --git a/code/__DEFINES/server_tools.dm b/code/__DEFINES/server_tools.dm index a4afa58a87..d2be3e578e 100644 --- a/code/__DEFINES/server_tools.dm +++ b/code/__DEFINES/server_tools.dm @@ -9,7 +9,9 @@ //keep these in sync with TGS3 #define SERVICE_WORLD_PARAM "server_service" -#define SERVICE_PR_TEST_JSON "..\\..\\prtestjob.json" +#define SERVICE_VERSION_PARAM "server_service_version" +#define SERVICE_PR_TEST_JSON "prtestjob.json" +#define SERVICE_PR_TEST_JSON_OLD "..\\..\\[SERVICE_PR_TEST_JSON]" #define SERVICE_CMD_HARD_REBOOT "hard_reboot" #define SERVICE_CMD_GRACEFUL_SHUTDOWN "graceful_shutdown" diff --git a/code/datums/helper_datums/getrev.dm b/code/datums/helper_datums/getrev.dm index 806f48a24f..c6958fa997 100644 --- a/code/datums/helper_datums/getrev.dm +++ b/code/datums/helper_datums/getrev.dm @@ -6,8 +6,14 @@ var/date /datum/getrev/New() - if(world.RunningService() && fexists(SERVICE_PR_TEST_JSON)) - testmerge = json_decode(file2text(SERVICE_PR_TEST_JSON)) + if(world.RunningService()) + var/file_name + if(ServiceVersion()) //will return null for versions < 3.0.91.0 + file_name = SERVICE_PR_TEST_JSON_OLD + else + file_name = SERVICE_PR_TEST_JSON + if(fexists(file_name)) + testmerge = json_decode(file2text(file_name)) #ifdef SERVERTOOLS else if(!world.RunningService() && fexists("../prtestjob.lk")) //tgs2 support var/list/tmp = world.file2list("..\\prtestjob.lk") diff --git a/code/modules/server_tools/server_tools.dm b/code/modules/server_tools/server_tools.dm index be8c80ac24..f16a56b2f9 100644 --- a/code/modules/server_tools/server_tools.dm +++ b/code/modules/server_tools/server_tools.dm @@ -4,6 +4,10 @@ GLOBAL_PROTECT(reboot_mode) /world/proc/RunningService() return params[SERVICE_WORLD_PARAM] +/proc/ServiceVersion() + if(world.RunningService()) + return world.params[SERVICE_VERSION_PARAM] + /world/proc/ExportService(command) return RunningService() && shell("python code/modules/server_tools/nudge.py \"[command]\"") == 0 From acd129ac37292a70ac03b43a1f91a90f7160e129 Mon Sep 17 00:00:00 2001 From: CitadelStationBot Date: Wed, 30 Aug 2017 08:01:27 -0500 Subject: [PATCH 02/74] Adds db connectivity check to jobban cache building --- code/modules/admin/banjob.dm | 2 ++ 1 file changed, 2 insertions(+) diff --git a/code/modules/admin/banjob.dm b/code/modules/admin/banjob.dm index 0128b719d7..a260746e66 100644 --- a/code/modules/admin/banjob.dm +++ b/code/modules/admin/banjob.dm @@ -22,6 +22,8 @@ return 0 /proc/jobban_buildcache(client/C) + if(!SSdbcore.Connect()) + return if(C && istype(C)) C.jobbancache = list() var/datum/DBQuery/query_jobban_build_cache = SSdbcore.NewQuery("SELECT job, reason FROM [format_table_name("ban")] WHERE ckey = '[sanitizeSQL(C.ckey)]' AND (bantype = 'JOB_PERMABAN' OR (bantype = 'JOB_TEMPBAN' AND expiration_time > Now())) AND isnull(unbanned)") From 50b88388da6413d1764dd4958b4aa6c757b69c22 Mon Sep 17 00:00:00 2001 From: CitadelStationBot Date: Wed, 30 Aug 2017 17:03:20 -0500 Subject: [PATCH 03/74] Crew monitoring rework part 1: crew pinpointers --- _maps/map_files/BoxStation/BoxStation.dmm | 2 +- .../map_files/Deltastation/DeltaStation2.dmm | 2 +- _maps/map_files/MetaStation/MetaStation.dmm | 2 +- _maps/map_files/OmegaStation/OmegaStation.dmm | 2 +- _maps/map_files/PubbyStation/PubbyStation.dmm | 2 +- code/__DEFINES/pinpointers.dm | 3 - .../gamemodes/malfunction/Malf_Modules.dm.rej | 11 ++ code/game/gamemodes/nuclear/nuclear.dm.rej | 10 ++ .../game/gamemodes/nuclear/nuclearbomb.dm.rej | 33 ++++ code/game/gamemodes/nuclear/pinpointer.dm | 6 - code/game/gamemodes/nuclear/pinpointer.dm.rej | 21 +++ code/game/gamemodes/objective_items.dm.rej | 10 ++ code/game/machinery/vending.dm | 2 +- code/game/objects/items/devices/pinpointer.dm | 152 ++++++++++++++++++ code/game/objects/items/pinpointer.dm | 150 +++++++++++++++++ .../crates_lockers/closets/secure/security.dm | 4 +- code/modules/admin/verbs/onlyone.dm | 4 +- code/modules/jobs/job_types/medical.dm | 1 + .../mob/living/silicon/ai/death.dm.rej | 13 ++ .../living/silicon/robot/robot_modules.dm.rej | 19 +++ code/modules/power/apc.dm.rej | 13 ++ icons/obj/device.dmi | Bin 38526 -> 37754 bytes tgstation.dme | 1 + tgstation.dme.rej | 20 +-- 24 files changed, 453 insertions(+), 30 deletions(-) create mode 100644 code/game/gamemodes/malfunction/Malf_Modules.dm.rej create mode 100644 code/game/gamemodes/nuclear/nuclear.dm.rej create mode 100644 code/game/gamemodes/nuclear/nuclearbomb.dm.rej create mode 100644 code/game/gamemodes/nuclear/pinpointer.dm.rej create mode 100644 code/game/gamemodes/objective_items.dm.rej create mode 100644 code/game/objects/items/devices/pinpointer.dm create mode 100644 code/game/objects/items/pinpointer.dm create mode 100644 code/modules/mob/living/silicon/ai/death.dm.rej create mode 100644 code/modules/mob/living/silicon/robot/robot_modules.dm.rej create mode 100644 code/modules/power/apc.dm.rej diff --git a/_maps/map_files/BoxStation/BoxStation.dmm b/_maps/map_files/BoxStation/BoxStation.dmm index 95f1cb283c..27f366f7f8 100644 --- a/_maps/map_files/BoxStation/BoxStation.dmm +++ b/_maps/map_files/BoxStation/BoxStation.dmm @@ -24458,7 +24458,7 @@ /area/crew_quarters/heads/captain) "bfE" = ( /obj/structure/table/wood, -/obj/item/pinpointer, +/obj/item/pinpointer/nuke, /obj/item/disk/nuclear, /obj/item/storage/secure/safe{ pixel_x = 35; diff --git a/_maps/map_files/Deltastation/DeltaStation2.dmm b/_maps/map_files/Deltastation/DeltaStation2.dmm index 5e0ded4416..0484d95b79 100644 --- a/_maps/map_files/Deltastation/DeltaStation2.dmm +++ b/_maps/map_files/Deltastation/DeltaStation2.dmm @@ -53210,7 +53210,7 @@ /area/tcommsat/server) "bYo" = ( /obj/structure/table/wood, -/obj/item/pinpointer, +/obj/item/pinpointer/nuke, /obj/item/disk/nuclear, /obj/item/device/radio/intercom{ name = "Station Intercom"; diff --git a/_maps/map_files/MetaStation/MetaStation.dmm b/_maps/map_files/MetaStation/MetaStation.dmm index ec76a564d5..a60e43dd83 100644 --- a/_maps/map_files/MetaStation/MetaStation.dmm +++ b/_maps/map_files/MetaStation/MetaStation.dmm @@ -29108,7 +29108,7 @@ }, /obj/machinery/atmospherics/pipe/simple/scrubbers/hidden, /obj/structure/table/wood, -/obj/item/pinpointer, +/obj/item/pinpointer/nuke, /obj/item/disk/nuclear, /turf/open/floor/carpet, /area/crew_quarters/heads/captain/private) diff --git a/_maps/map_files/OmegaStation/OmegaStation.dmm b/_maps/map_files/OmegaStation/OmegaStation.dmm index 9a3b2b9454..6b4f65c67e 100644 --- a/_maps/map_files/OmegaStation/OmegaStation.dmm +++ b/_maps/map_files/OmegaStation/OmegaStation.dmm @@ -1187,7 +1187,7 @@ pixel_x = 32; pixel_y = 24 }, -/obj/item/pinpointer, +/obj/item/pinpointer/nuke, /obj/item/disk/nuclear, /obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{ dir = 10 diff --git a/_maps/map_files/PubbyStation/PubbyStation.dmm b/_maps/map_files/PubbyStation/PubbyStation.dmm index 7f55c286c7..497bf0a4ce 100644 --- a/_maps/map_files/PubbyStation/PubbyStation.dmm +++ b/_maps/map_files/PubbyStation/PubbyStation.dmm @@ -13937,7 +13937,7 @@ /area/storage/primary) "aEx" = ( /obj/structure/table/wood, -/obj/item/pinpointer, +/obj/item/pinpointer/nuke, /obj/item/disk/nuclear, /obj/machinery/light{ dir = 8 diff --git a/code/__DEFINES/pinpointers.dm b/code/__DEFINES/pinpointers.dm index 80403e54de..75f0452ea9 100644 --- a/code/__DEFINES/pinpointers.dm +++ b/code/__DEFINES/pinpointers.dm @@ -2,6 +2,3 @@ #define TRACK_NUKE_DISK 1 //We track the nuclear authentication disk, either to protect it or steal it #define TRACK_MALF_AI 2 //We track the malfunctioning AI, so we can prevent it from blowing us all up #define TRACK_INFILTRATOR 3 //We track the Syndicate infiltrator, so we can get back to ship when the nuke's armed -#define TRACK_OPERATIVES 4 //We track the closest operative, so we can regroup when we need to -#define TRACK_ATOM 5 //We track a specified atom, so admins can make us function for events -#define TRACK_COORDINATES 6 //We point towards the specified coordinates on our z-level, so we can navigate diff --git a/code/game/gamemodes/malfunction/Malf_Modules.dm.rej b/code/game/gamemodes/malfunction/Malf_Modules.dm.rej new file mode 100644 index 0000000000..97dbe2bbdb --- /dev/null +++ b/code/game/gamemodes/malfunction/Malf_Modules.dm.rej @@ -0,0 +1,11 @@ +diff a/code/game/gamemodes/malfunction/Malf_Modules.dm b/code/game/gamemodes/malfunction/Malf_Modules.dm (rejected hunks) +@@ -309,8 +309,7 @@ GLOBAL_LIST_INIT(blacklisted_malf_machines, typecacheof(list( + owner_AI.nuking = TRUE + owner_AI.doomsday_device = DOOM + owner_AI.doomsday_device.start() +- for(var/pinpointer in GLOB.pinpointer_list) +- var/obj/item/weapon/pinpointer/P = pinpointer ++ for(var/obj/item/weapon/pinpointer/nuke/P in GLOB.pinpointer_list) + P.switch_mode_to(TRACK_MALF_AI) //Pinpointers start tracking the AI wherever it goes + qdel(src) + diff --git a/code/game/gamemodes/nuclear/nuclear.dm.rej b/code/game/gamemodes/nuclear/nuclear.dm.rej new file mode 100644 index 0000000000..19648547c7 --- /dev/null +++ b/code/game/gamemodes/nuclear/nuclear.dm.rej @@ -0,0 +1,10 @@ +diff a/code/game/gamemodes/nuclear/nuclear.dm b/code/game/gamemodes/nuclear/nuclear.dm (rejected hunks) +@@ -325,7 +325,7 @@ + gloves = /obj/item/clothing/gloves/combat + back = /obj/item/weapon/storage/backpack + ears = /obj/item/device/radio/headset/syndicate/alt +- l_pocket = /obj/item/weapon/pinpointer/syndicate ++ l_pocket = /obj/item/weapon/pinpointer/nuke/syndicate + id = /obj/item/weapon/card/id/syndicate + belt = /obj/item/weapon/gun/ballistic/automatic/pistol + backpack_contents = list(/obj/item/weapon/storage/box/syndie=1) diff --git a/code/game/gamemodes/nuclear/nuclearbomb.dm.rej b/code/game/gamemodes/nuclear/nuclearbomb.dm.rej new file mode 100644 index 0000000000..6a35e91cde --- /dev/null +++ b/code/game/gamemodes/nuclear/nuclearbomb.dm.rej @@ -0,0 +1,33 @@ +diff a/code/game/gamemodes/nuclear/nuclearbomb.dm b/code/game/gamemodes/nuclear/nuclearbomb.dm (rejected hunks) +@@ -362,9 +362,9 @@ + if(safety) + if(timing) + set_security_level(previous_level) +- for(var/obj/item/weapon/pinpointer/syndicate/S in GLOB.pinpointer_list) ++ for(var/obj/item/weapon/pinpointer/nuke/syndicate/S in GLOB.pinpointer_list) + S.switch_mode_to(initial(S.mode)) +- S.nuke_warning = FALSE ++ S.alert = FALSE + timing = FALSE + bomb_set = TRUE + detonation_timer = null +@@ -381,16 +381,16 @@ + bomb_set = TRUE + set_security_level("delta") + detonation_timer = world.time + (timer_set * 10) +- for(var/obj/item/weapon/pinpointer/syndicate/S in GLOB.pinpointer_list) ++ for(var/obj/item/weapon/pinpointer/nuke/syndicate/S in GLOB.pinpointer_list) + S.switch_mode_to(TRACK_INFILTRATOR) + countdown.start() + else + bomb_set = FALSE + detonation_timer = null + set_security_level(previous_level) +- for(var/obj/item/weapon/pinpointer/syndicate/S in GLOB.pinpointer_list) ++ for(var/obj/item/weapon/pinpointer/nuke/syndicate/S in GLOB.pinpointer_list) + S.switch_mode_to(initial(S.mode)) +- S.nuke_warning = FALSE ++ S.alert = FALSE + countdown.stop() + update_icon() + diff --git a/code/game/gamemodes/nuclear/pinpointer.dm b/code/game/gamemodes/nuclear/pinpointer.dm index 9f63309643..342bcac090 100644 --- a/code/game/gamemodes/nuclear/pinpointer.dm +++ b/code/game/gamemodes/nuclear/pinpointer.dm @@ -60,12 +60,6 @@ msg += "\"01000001 01001001\"." if(TRACK_INFILTRATOR) msg += "\"vasvygengbefuvc\"." - if(TRACK_OPERATIVES) - msg += "\"[target ? "Operative [target]" : "friends"]\"." - if(TRACK_ATOM) - msg += "\"[initial(constant_target.name)]\"." - if(TRACK_COORDINATES) - msg += "\"([target_x], [target_y])\"." else msg = "Its tracking indicator is blank." to_chat(user, msg) diff --git a/code/game/gamemodes/nuclear/pinpointer.dm.rej b/code/game/gamemodes/nuclear/pinpointer.dm.rej new file mode 100644 index 0000000000..79d652af9b --- /dev/null +++ b/code/game/gamemodes/nuclear/pinpointer.dm.rej @@ -0,0 +1,21 @@ +diff a/code/game/gamemodes/nuclear/pinpointer.dm b/code/game/gamemodes/nuclear/pinpointer.dm (rejected hunks) +@@ -30,7 +30,6 @@ + var/mob/living/L = loc + to_chat(L, "Your [name] vibrates and lets out a tinny alarm. Uh oh.") + +- + /obj/item/pinpointer/nuke/scan_for_target() + target = null + switch(mode) +@@ -58,10 +57,10 @@ + mode = new_mode + scan_for_target() + +- + /obj/item/pinpointer/nuke/syndicate // Syndicate pinpointers automatically point towards the infiltrator once the nuke is active. + name = "syndicate pinpointer" + desc = "A handheld tracking device that locks onto certain signals. It's configured to switch tracking modes once it detects the activation signal of a nuclear device." ++ icon_state = "pinpointer_syndicate" + + /obj/item/pinpointer/syndicate_cyborg // Cyborg pinpointers just look for a random operative. + name = "cyborg syndicate pinpointer" diff --git a/code/game/gamemodes/objective_items.dm.rej b/code/game/gamemodes/objective_items.dm.rej new file mode 100644 index 0000000000..3770d7eea9 --- /dev/null +++ b/code/game/gamemodes/objective_items.dm.rej @@ -0,0 +1,10 @@ +diff a/code/game/gamemodes/objective_items.dm b/code/game/gamemodes/objective_items.dm (rejected hunks) +@@ -158,7 +158,7 @@ + difficulty = 10 + + //Old ninja objectives. +-/datum/objective_item/special/pinpointer ++/datum/objective_item/special/pinpointer/nuke + name = "the captain's pinpointer." + targetitem = /obj/item/pinpointer + difficulty = 10 diff --git a/code/game/machinery/vending.dm b/code/game/machinery/vending.dm index 427bc95253..bf879f84da 100644 --- a/code/game/machinery/vending.dm +++ b/code/game/machinery/vending.dm @@ -869,7 +869,7 @@ IF YOU MODIFY THE PRODUCTS LIST OF A MACHINE, MAKE SURE TO UPDATE ITS RESUPPLY C products = list(/obj/item/reagent_containers/syringe = 12, /obj/item/reagent_containers/dropper = 3, /obj/item/stack/medical/gauze = 8, /obj/item/reagent_containers/pill/patch/styptic = 5, /obj/item/reagent_containers/pill/insulin = 10, /obj/item/reagent_containers/pill/patch/silver_sulf = 5, /obj/item/reagent_containers/glass/bottle/charcoal = 4, /obj/item/reagent_containers/spray/medical/sterilizer = 1, /obj/item/reagent_containers/glass/bottle/epinephrine = 4, /obj/item/reagent_containers/glass/bottle/morphine = 4, /obj/item/reagent_containers/glass/bottle/salglu_solution = 3, - /obj/item/reagent_containers/glass/bottle/toxin = 3, /obj/item/reagent_containers/syringe/antiviral = 6, /obj/item/reagent_containers/pill/salbutamol = 2, /obj/item/device/healthanalyzer = 4, /obj/item/device/sensor_device = 2) + /obj/item/reagent_containers/glass/bottle/toxin = 3, /obj/item/reagent_containers/syringe/antiviral = 6, /obj/item/reagent_containers/pill/salbutamol = 2, /obj/item/device/healthanalyzer = 4, /obj/item/device/sensor_device = 2, /obj/item/pinpointer/crew = 2) contraband = list(/obj/item/reagent_containers/pill/tox = 3, /obj/item/reagent_containers/pill/morphine = 4, /obj/item/reagent_containers/pill/charcoal = 6) premium = list(/obj/item/storage/box/hug/medical = 1, /obj/item/reagent_containers/hypospray/medipen = 3, /obj/item/storage/belt/medical = 3, /obj/item/wrench/medical = 1) armor = list(melee = 100, bullet = 100, laser = 100, energy = 100, bomb = 0, bio = 0, rad = 0, fire = 100, acid = 50) diff --git a/code/game/objects/items/devices/pinpointer.dm b/code/game/objects/items/devices/pinpointer.dm new file mode 100644 index 0000000000..1d11f312a4 --- /dev/null +++ b/code/game/objects/items/devices/pinpointer.dm @@ -0,0 +1,152 @@ +//Pinpointers are used to track atoms from a distance as long as they're on the same z-level. The captain and nuke ops have ones that track the nuclear authentication disk. +/obj/item/weapon/pinpointer + name = "pinpointer" + desc = "A handheld tracking device that locks onto certain signals." + icon = 'icons/obj/device.dmi' + icon_state = "pinpointer" + flags = CONDUCT + slot_flags = SLOT_BELT + w_class = WEIGHT_CLASS_SMALL + item_state = "electronic" + lefthand_file = 'icons/mob/inhands/misc/devices_lefthand.dmi' + righthand_file = 'icons/mob/inhands/misc/devices_righthand.dmi' + throw_speed = 3 + throw_range = 7 + materials = list(MAT_METAL = 500, MAT_GLASS = 250) + resistance_flags = INDESTRUCTIBLE | LAVA_PROOF | FIRE_PROOF | ACID_PROOF + var/active = FALSE + var/atom/movable/target = null //The thing we're searching for + var/minimum_range = 0 //at what range the pinpointer declares you to be at your destination + var/alert = FALSE // TRUE to display things more seriously + +/obj/item/weapon/pinpointer/New() + ..() + GLOB.pinpointer_list += src + +/obj/item/weapon/pinpointer/Destroy() + STOP_PROCESSING(SSfastprocess, src) + GLOB.pinpointer_list -= src + return ..() + +/obj/item/weapon/pinpointer/attack_self(mob/living/user) + active = !active + user.visible_message("[user] [active ? "" : "de"]activates their pinpointer.", "You [active ? "" : "de"]activate your pinpointer.") + playsound(user, 'sound/items/screwdriver2.ogg', 50, 1) + if(active) + START_PROCESSING(SSfastprocess, src) + else + target = null + STOP_PROCESSING(SSfastprocess, src) + update_pointer_overlay() + +/obj/item/weapon/pinpointer/process() + if(!active) + STOP_PROCESSING(SSfastprocess, src) + return + scan_for_target() + update_pointer_overlay() + +/obj/item/weapon/pinpointer/proc/scan_for_target() + return + +/obj/item/weapon/pinpointer/proc/update_pointer_overlay() + cut_overlays() + if(!active) + return + if(!target) + add_overlay("pinon[alert ? "alert" : ""]null") + var/turf/here = get_turf(src) + var/turf/there = get_turf(target) + if(here.z != there.z) + add_overlay("pinon[alert ? "alert" : ""]null") + return + if(get_dist_euclidian(here,there) <= minimum_range) + add_overlay("pinon[alert ? "alert" : ""]direct") + else + setDir(get_dir(here, there)) + switch(get_dist(here, there)) + if(1 to 8) + add_overlay("pinon[alert ? "alert" : "close"]") + if(9 to 16) + add_overlay("pinon[alert ? "alert" : "medium"]") + if(16 to INFINITY) + add_overlay("pinon[alert ? "alert" : "far"]") + +/obj/item/weapon/pinpointer/crew // A replacement for the old crew monitoring consoles + name = "crew pinpointer" + desc = "A handheld tracking device that points to crew suit sensors." + icon_state = "pinpointer_crew" + +/obj/item/weapon/pinpointer/crew/proc/trackable(mob/living/carbon/human/H) + var/turf/here = get_turf(src) + if((H.z == 0 || H.z == here.z) && istype(H.w_uniform, /obj/item/clothing/under)) + var/obj/item/clothing/under/U = H.w_uniform + + // Suit sensors must be on maximum. + if(!U.has_sensor || U.sensor_mode < SENSOR_COORDS) + return FALSE + + var/turf/there = get_turf(H) + return (H.z != 0 || (there && there.z == H.z)) + + return FALSE + +/obj/item/weapon/pinpointer/crew/attack_self(mob/living/user) + if(active) + active = FALSE + user.visible_message("[user] deactivates their pinpointer.", "You deactivate your pinpointer.") + playsound(user, 'sound/items/screwdriver2.ogg', 50, 1) + target = null //Restarting the pinpointer forces a target reset + STOP_PROCESSING(SSfastprocess, src) + update_pointer_overlay() + return + + var/list/name_counts = list() + var/list/names = list() + + for(var/mob/living/carbon/human/H in GLOB.mob_list) + if(!trackable(H)) + continue + + var/name = "Unknown" + if(H.wear_id) + var/obj/item/weapon/card/id/I = H.wear_id.GetID() + name = I.registered_name + + while(name in name_counts) + name_counts[name]++ + name = text("[] ([])", name, name_counts[name]) + names[name] = H + name_counts[name] = 1 + + if(!names.len) + user.visible_message("[user]'s pinpointer fails to detect a signal.", "Your pinpointer fails to detect a signal.") + return + + var/A = input(user, "Person to track", "Pinpoint") in names + if(!src || QDELETED(src) || !user || !user.is_holding(src) || user.incapacitated() || !A) + return + + target = names[A] + active = TRUE + user.visible_message("[user] activates their pinpointer.", "You activate your pinpointer.") + playsound(user, 'sound/items/screwdriver2.ogg', 50, 1) + START_PROCESSING(SSfastprocess, src) + update_pointer_overlay() + +/obj/item/weapon/pinpointer/crew/scan_for_target() + if(target) + if(ishuman(target)) + var/mob/living/carbon/human/H = target + if(!trackable(H)) + target = null + if(!target) + active = FALSE + +/obj/item/weapon/pinpointer/process() + if(!active) + STOP_PROCESSING(SSfastprocess, src) + return + scan_for_target() + update_pointer_overlay() + diff --git a/code/game/objects/items/pinpointer.dm b/code/game/objects/items/pinpointer.dm new file mode 100644 index 0000000000..28488a231f --- /dev/null +++ b/code/game/objects/items/pinpointer.dm @@ -0,0 +1,150 @@ +//Pinpointers are used to track atoms from a distance as long as they're on the same z-level. The captain and nuke ops have ones that track the nuclear authentication disk. +/obj/item/pinpointer + name = "pinpointer" + desc = "A handheld tracking device that locks onto certain signals." + icon = 'icons/obj/device.dmi' + icon_state = "pinpointer" + flags_1 = CONDUCT_1 + slot_flags = SLOT_BELT + w_class = WEIGHT_CLASS_SMALL + item_state = "electronic" + lefthand_file = 'icons/mob/inhands/misc/devices_lefthand.dmi' + righthand_file = 'icons/mob/inhands/misc/devices_righthand.dmi' + throw_speed = 3 + throw_range = 7 + materials = list(MAT_METAL = 500, MAT_GLASS = 250) + resistance_flags = INDESTRUCTIBLE | LAVA_PROOF | FIRE_PROOF | ACID_PROOF + var/active = FALSE + var/atom/movable/target //The thing we're searching for + var/minimum_range = 0 //at what range the pinpointer declares you to be at your destination + var/alert = FALSE // TRUE to display things more seriously + +/obj/item/pinpointer/Initialize() + . = ..() + GLOB.pinpointer_list += src + +/obj/item/pinpointer/Destroy() + STOP_PROCESSING(SSfastprocess, src) + GLOB.pinpointer_list -= src + return ..() + +/obj/item/pinpointer/attack_self(mob/living/user) + active = !active + user.visible_message("[user] [active ? "" : "de"]activates their pinpointer.", "You [active ? "" : "de"]activate your pinpointer.") + playsound(src, 'sound/items/screwdriver2.ogg', 50, 1) + if(active) + START_PROCESSING(SSfastprocess, src) + else + target = null + STOP_PROCESSING(SSfastprocess, src) + update_icon() + +/obj/item/pinpointer/process() + if(!active) + return PROCESS_KILL + scan_for_target() + update_icon() + +/obj/item/pinpointer/proc/scan_for_target() + return + +/obj/item/pinpointer/update_icon() + cut_overlays() + if(!active) + return + if(!target) + add_overlay("pinon[alert ? "alert" : ""]null") + var/turf/here = get_turf(src) + var/turf/there = get_turf(target) + if(here.z != there.z) + add_overlay("pinon[alert ? "alert" : ""]null") + return + if(get_dist_euclidian(here,there) <= minimum_range) + add_overlay("pinon[alert ? "alert" : ""]direct") + else + setDir(get_dir(here, there)) + switch(get_dist(here, there)) + if(1 to 8) + add_overlay("pinon[alert ? "alert" : "close"]") + if(9 to 16) + add_overlay("pinon[alert ? "alert" : "medium"]") + if(16 to INFINITY) + add_overlay("pinon[alert ? "alert" : "far"]") + +/obj/item/pinpointer/crew // A replacement for the old crew monitoring consoles + name = "crew pinpointer" + desc = "A handheld tracking device that points to crew suit sensors." + icon_state = "pinpointer_crew" + +/obj/item/pinpointer/crew/proc/trackable(mob/living/carbon/human/H) + var/turf/here = get_turf(src) + if((H.z == 0 || H.z == here.z) && istype(H.w_uniform, /obj/item/clothing/under)) + var/obj/item/clothing/under/U = H.w_uniform + + // Suit sensors must be on maximum. + if(!U.has_sensor || U.sensor_mode < SENSOR_COORDS) + return FALSE + + var/turf/there = get_turf(H) + return (H.z != 0 || (there && there.z == H.z)) + + return FALSE + +/obj/item/pinpointer/crew/attack_self(mob/living/user) + if(active) + active = FALSE + user.visible_message("[user] deactivates their pinpointer.", "You deactivate your pinpointer.") + playsound(src, 'sound/items/screwdriver2.ogg', 50, 1) + target = null //Restarting the pinpointer forces a target reset + STOP_PROCESSING(SSfastprocess, src) + update_icon() + return + + var/list/name_counts = list() + var/list/names = list() + + for(var/mob/living/carbon/human/H in GLOB.mob_list) + if(!trackable(H)) + continue + + var/crewmember_name = "Unknown" + if(H.wear_id) + var/obj/item/card/id/I = H.wear_id.GetID() + crewmember_name = I.registered_name + + while(crewmember_name in name_counts) + name_counts[crewmember_name]++ + crewmember_name = text("[] ([])", crewmember_name, name_counts[crewmember_name]) + names[crewmember_name] = H + name_counts[crewmember_name] = 1 + + if(!names.len) + user.visible_message("[user]'s pinpointer fails to detect a signal.", "Your pinpointer fails to detect a signal.") + return + + var/A = input(user, "Person to track", "Pinpoint") in names + if(!A || QDELETED(src) || !user || !user.is_holding(src) || user.incapacitated()) + return + + target = names[A] + active = TRUE + user.visible_message("[user] activates their pinpointer.", "You activate your pinpointer.") + playsound(src, 'sound/items/screwdriver2.ogg', 50, 1) + START_PROCESSING(SSfastprocess, src) + update_icon() + +/obj/item/pinpointer/crew/scan_for_target() + if(target) + if(ishuman(target)) + var/mob/living/carbon/human/H = target + if(!trackable(H)) + target = null + if(!target) //target can be set to null from above code, or elsewhere + active = FALSE + +/obj/item/pinpointer/process() + if(!active) + return PROCESS_KILL + scan_for_target() + update_icon() + diff --git a/code/game/objects/structures/crates_lockers/closets/secure/security.dm b/code/game/objects/structures/crates_lockers/closets/secure/security.dm index 6327d2d3ff..f13eaf73c4 100644 --- a/code/game/objects/structures/crates_lockers/closets/secure/security.dm +++ b/code/game/objects/structures/crates_lockers/closets/secure/security.dm @@ -83,7 +83,7 @@ new /obj/item/storage/belt/security/full(src) new /obj/item/gun/energy/e_gun/hos(src) new /obj/item/device/flashlight/seclite(src) - new /obj/item/pinpointer(src) + new /obj/item/pinpointer/nuke(src) /obj/structure/closet/secure_closet/warden name = "\proper warden's locker" @@ -108,6 +108,7 @@ new /obj/item/clothing/gloves/krav_maga/sec(src) new /obj/item/door_remote/head_of_security(src) new /obj/item/gun/ballistic/shotgun/automatic/combat/compact(src) + new /obj/item/pinpointer/crew(src) /obj/structure/closet/secure_closet/security name = "security officer's locker" @@ -183,6 +184,7 @@ new /obj/item/reagent_containers/spray/pepper(src) new /obj/item/clothing/suit/armor/vest/det_suit(src) new /obj/item/storage/belt/holster/full(src) + new /obj/item/pinpointer/crew(src) /obj/structure/closet/secure_closet/injection name = "lethal injections" diff --git a/code/modules/admin/verbs/onlyone.dm b/code/modules/admin/verbs/onlyone.dm index 7301724eb6..abb87a4235 100644 --- a/code/modules/admin/verbs/onlyone.dm +++ b/code/modules/admin/verbs/onlyone.dm @@ -50,8 +50,8 @@ GLOBAL_VAR_INIT(highlander, FALSE) equip_to_slot_or_del(new /obj/item/device/radio/headset/heads/captain(src), slot_ears) equip_to_slot_or_del(new /obj/item/clothing/head/beret/highlander(src), slot_head) equip_to_slot_or_del(new /obj/item/clothing/shoes/combat(src), slot_shoes) - equip_to_slot_or_del(new /obj/item/pinpointer(src), slot_l_store) - for(var/obj/item/pinpointer/P in src) + equip_to_slot_or_del(new /obj/item/pinpointer/nuke(src), slot_l_store) + for(var/obj/item/pinpointer/nuke/P in src) P.attack_self(src) var/obj/item/card/id/W = new(src) W.icon_state = "centcom" diff --git a/code/modules/jobs/job_types/medical.dm b/code/modules/jobs/job_types/medical.dm index 5f22e1886a..3d9f857dbf 100644 --- a/code/modules/jobs/job_types/medical.dm +++ b/code/modules/jobs/job_types/medical.dm @@ -30,6 +30,7 @@ Chief Medical Officer id = /obj/item/card/id/silver belt = /obj/item/device/pda/heads/cmo + l_pocket = /obj/item/pinpointer/crew ears = /obj/item/device/radio/headset/heads/cmo uniform = /obj/item/clothing/under/rank/chief_medical_officer shoes = /obj/item/clothing/shoes/sneakers/brown diff --git a/code/modules/mob/living/silicon/ai/death.dm.rej b/code/modules/mob/living/silicon/ai/death.dm.rej new file mode 100644 index 0000000000..40b5625e8c --- /dev/null +++ b/code/modules/mob/living/silicon/ai/death.dm.rej @@ -0,0 +1,13 @@ +diff a/code/modules/mob/living/silicon/ai/death.dm b/code/modules/mob/living/silicon/ai/death.dm (rejected hunks) +@@ -35,9 +35,9 @@ + if(nuking) + set_security_level("red") + nuking = FALSE +- for(var/obj/item/weapon/pinpointer/P in GLOB.pinpointer_list) ++ for(var/obj/item/weapon/pinpointer/nuke/P in GLOB.pinpointer_list) + P.switch_mode_to(TRACK_NUKE_DISK) //Party's over, back to work, everyone +- P.nuke_warning = FALSE ++ P.alert = FALSE + + if(doomsday_device) + doomsday_device.timing = FALSE diff --git a/code/modules/mob/living/silicon/robot/robot_modules.dm.rej b/code/modules/mob/living/silicon/robot/robot_modules.dm.rej new file mode 100644 index 0000000000..b0f0812dc4 --- /dev/null +++ b/code/modules/mob/living/silicon/robot/robot_modules.dm.rej @@ -0,0 +1,19 @@ +diff a/code/modules/mob/living/silicon/robot/robot_modules.dm b/code/modules/mob/living/silicon/robot/robot_modules.dm (rejected hunks) +@@ -519,7 +519,7 @@ + /obj/item/weapon/gun/ballistic/revolver/grenadelauncher/cyborg, + /obj/item/weapon/card/emag, + /obj/item/weapon/crowbar/cyborg, +- /obj/item/weapon/pinpointer/syndicate/cyborg) ++ /obj/item/weapon/pinpointer/syndicate_cyborg) + + ratvar_modules = list( + /obj/item/clockwork/slab/cyborg/security, +@@ -545,7 +545,7 @@ + /obj/item/roller/robo, + /obj/item/weapon/card/emag, + /obj/item/weapon/crowbar/cyborg, +- /obj/item/weapon/pinpointer/syndicate/cyborg, ++ /obj/item/weapon/pinpointer/syndicate_cyborg, + /obj/item/stack/medical/gauze/cyborg, + /obj/item/weapon/gun/medbeam) + ratvar_modules = list( diff --git a/code/modules/power/apc.dm.rej b/code/modules/power/apc.dm.rej new file mode 100644 index 0000000000..9e432f503c --- /dev/null +++ b/code/modules/power/apc.dm.rej @@ -0,0 +1,13 @@ +diff a/code/modules/power/apc.dm b/code/modules/power/apc.dm (rejected hunks) +@@ -867,9 +867,9 @@ + occupier.loc = src.loc + occupier.death() + occupier.gib() +- for(var/obj/item/weapon/pinpointer/P in GLOB.pinpointer_list) ++ for(var/obj/item/weapon/pinpointer/nuke/P in GLOB.pinpointer_list) + P.switch_mode_to(TRACK_NUKE_DISK) //Pinpointers go back to tracking the nuke disk +- P.nuke_warning = FALSE ++ P.alert = FALSE + + /obj/machinery/power/apc/transfer_ai(interaction, mob/user, mob/living/silicon/ai/AI, obj/item/device/aicard/card) + if(card.AI) diff --git a/icons/obj/device.dmi b/icons/obj/device.dmi index 808de6944665734cb96d96dbd42c08aeefa1452e..79f0a207d41d802e2e87d718157c7a5ca1983ffd 100644 GIT binary patch literal 37754 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 aH-6%}!&bucoQ)y~JeO=8ZK`qJNq+-{0&jQ# literal 38526 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 diff --git a/tgstation.dme b/tgstation.dme index 1e1c153493..4c2da1f48b 100755 --- a/tgstation.dme +++ b/tgstation.dme @@ -793,6 +793,7 @@ #include "code\game\objects\items\mop.dm" #include "code\game\objects\items\paint.dm" #include "code\game\objects\items\paiwire.dm" +#include "code\game\objects\items\pinpointer.dm" #include "code\game\objects\items\pneumaticCannon.dm" #include "code\game\objects\items\powerfist.dm" #include "code\game\objects\items\RCD.dm" diff --git a/tgstation.dme.rej b/tgstation.dme.rej index a5ff4dc3cb..82c613607a 100644 --- a/tgstation.dme.rej +++ b/tgstation.dme.rej @@ -1,13 +1,9 @@ diff a/tgstation.dme b/tgstation.dme (rejected hunks) -@@ -1746,6 +1745,11 @@ - #include "code\modules\mob\living\simple_animal\hostile\gorilla\emotes.dm" - #include "code\modules\mob\living\simple_animal\hostile\gorilla\gorilla.dm" - #include "code\modules\mob\living\simple_animal\hostile\gorilla\visuals_icons.dm" -+#include "code\modules\mob\living\simple_animal\hostile\jungle\_jungle_mobs.dm" -+#include "code\modules\mob\living\simple_animal\hostile\jungle\leaper.dm" -+#include "code\modules\mob\living\simple_animal\hostile\jungle\mega_arachnid.dm" -+#include "code\modules\mob\living\simple_animal\hostile\jungle\mook.dm" -+#include "code\modules\mob\living\simple_animal\hostile\jungle\seedling.dm" - #include "code\modules\mob\living\simple_animal\hostile\megafauna\blood_drunk_miner.dm" - #include "code\modules\mob\living\simple_animal\hostile\megafauna\bubblegum.dm" - #include "code\modules\mob\living\simple_animal\hostile\megafauna\colossus.dm" +@@ -793,7 +794,6 @@ + #include "code\game\objects\items\devices\megaphone.dm" + #include "code\game\objects\items\devices\multitool.dm" + #include "code\game\objects\items\devices\paicard.dm" +-#include "code\game\objects\items\devices\pinpointer.dm" + #include "code\game\objects\items\devices\pipe_painter.dm" + #include "code\game\objects\items\devices\powersink.dm" + #include "code\game\objects\items\devices\pressureplates.dm" From 64b94e93934f2a972dc331b58c4c911f54fa678a Mon Sep 17 00:00:00 2001 From: LetterJay Date: Mon, 4 Sep 2017 11:07:47 -0500 Subject: [PATCH 04/74] disables the lisp that lizard tongues have --- code/modules/surgery/organs/tongue.dm | 2 ++ 1 file changed, 2 insertions(+) diff --git a/code/modules/surgery/organs/tongue.dm b/code/modules/surgery/organs/tongue.dm index b69c1f4c5c..0113166d86 100644 --- a/code/modules/surgery/organs/tongue.dm +++ b/code/modules/surgery/organs/tongue.dm @@ -47,6 +47,7 @@ say_mod = "hisses" taste_sensitivity = 10 // combined nose + tongue, extra sensitive +/* /obj/item/organ/tongue/lizard/TongueSpeech(var/message) var/regex/lizard_hiss = new("s+", "g") var/regex/lizard_hiSS = new("S+", "g") @@ -54,6 +55,7 @@ message = lizard_hiss.Replace(message, "sss") message = lizard_hiSS.Replace(message, "SSS") return message + */ /obj/item/organ/tongue/fly name = "proboscis" From d73b82cf1140157d5280108c542b2a13fdfb7b83 Mon Sep 17 00:00:00 2001 From: tortellinitony <22010639+tortellinitony@users.noreply.github.com> Date: Thu, 7 Sep 2017 00:38:24 -0400 Subject: [PATCH 05/74] Gets rid of manual overlay manipulation --- .../clock_structures/prolonging_prism.dm | 2 +- code/game/objects/items/devices/flashlight.dm | 2 +- .../objects/items/devices/pressureplates.dm | 2 +- code/game/objects/items/tools.dm | 793 ++++++++++++++++++ code/game/turfs/turf.dm | 4 +- code/modules/hydroponics/hydroponics.dm | 2 +- 6 files changed, 799 insertions(+), 6 deletions(-) diff --git a/code/game/gamemodes/clock_cult/clock_structures/prolonging_prism.dm b/code/game/gamemodes/clock_cult/clock_structures/prolonging_prism.dm index cf730189e3..a6bc9a7f38 100644 --- a/code/game/gamemodes/clock_cult/clock_structures/prolonging_prism.dm +++ b/code/game/gamemodes/clock_cult/clock_structures/prolonging_prism.dm @@ -126,7 +126,7 @@ if(!hex_combo) hex_combo = mutable_appearance('icons/effects/64x64.dmi', n, RIPPLE_LAYER) else - hex_combo.overlays += mutable_appearance('icons/effects/64x64.dmi', n, RIPPLE_LAYER) + hex_combo.add_overlay(mutable_appearance('icons/effects/64x64.dmi', n, RIPPLE_LAYER)) if(hex_combo) //YOU BUILT A HEXAGON hex_combo.pixel_x = -16 hex_combo.pixel_y = -16 diff --git a/code/game/objects/items/devices/flashlight.dm b/code/game/objects/items/devices/flashlight.dm index b41438451c..9c19f37f3f 100644 --- a/code/game/objects/items/devices/flashlight.dm +++ b/code/game/objects/items/devices/flashlight.dm @@ -428,7 +428,7 @@ /obj/item/device/flashlight/glowstick/update_icon() item_state = "glowstick" - overlays.Cut() + cut_overlays() if(!fuel) icon_state = "glowstick-empty" cut_overlays() diff --git a/code/game/objects/items/devices/pressureplates.dm b/code/game/objects/items/devices/pressureplates.dm index bab40edb29..b8b4884db7 100644 --- a/code/game/objects/items/devices/pressureplates.dm +++ b/code/game/objects/items/devices/pressureplates.dm @@ -86,7 +86,7 @@ icon_state = null active = TRUE if(tile_overlay) - loc.overlays += tile_overlay + loc.add_overlay(tile_overlay) else if(crossed) trigger() //no cheesing. diff --git a/code/game/objects/items/tools.dm b/code/game/objects/items/tools.dm index 23f68ca93c..0e557497c0 100644 --- a/code/game/objects/items/tools.dm +++ b/code/game/objects/items/tools.dm @@ -1,3 +1,4 @@ +<<<<<<< HEAD #define WELDER_FUEL_BURN_INTERVAL 13 /* Tools! @@ -788,3 +789,795 @@ user.put_in_active_hand(cutjaws) #undef WELDER_FUEL_BURN_INTERVAL +======= +#define WELDER_FUEL_BURN_INTERVAL 13 + +/* Tools! + * Note: Multitools are /obj/item/device + * + * Contains: + * Wrench + * Screwdriver + * Wirecutters + * Welding Tool + * Crowbar + */ + +/* + * Wrench + */ +/obj/item/wrench + name = "wrench" + desc = "A wrench with common uses. Can be found in your hand." + icon = 'icons/obj/tools.dmi' + icon_state = "wrench" + lefthand_file = 'icons/mob/inhands/equipment/tools_lefthand.dmi' + righthand_file = 'icons/mob/inhands/equipment/tools_righthand.dmi' + flags_1 = CONDUCT_1 + slot_flags = SLOT_BELT + force = 5 + throwforce = 7 + w_class = WEIGHT_CLASS_SMALL + usesound = 'sound/items/ratchet.ogg' + materials = list(MAT_METAL=150) + origin_tech = "materials=1;engineering=1" + attack_verb = list("bashed", "battered", "bludgeoned", "whacked") + toolspeed = 1 + armor = list(melee = 0, bullet = 0, laser = 0, energy = 0, bomb = 0, bio = 0, rad = 0, fire = 50, acid = 30) + +/obj/item/wrench/suicide_act(mob/user) + user.visible_message("[user] is beating [user.p_them()]self to death with [src]! It looks like [user.p_theyre()] trying to commit suicide!") + playsound(loc, 'sound/weapons/genhit.ogg', 50, 1, -1) + return (BRUTELOSS) + +/obj/item/wrench/cyborg + name = "automatic wrench" + desc = "An advanced robotic wrench. Can be found in construction cyborgs." + toolspeed = 0.5 + +/obj/item/wrench/brass + name = "brass wrench" + desc = "A brass wrench. It's faintly warm to the touch." + resistance_flags = FIRE_PROOF | ACID_PROOF + icon_state = "wrench_brass" + toolspeed = 0.5 + +/obj/item/wrench/abductor + name = "alien wrench" + desc = "A polarized wrench. It causes anything placed between the jaws to turn." + icon = 'icons/obj/abductor.dmi' + icon_state = "wrench" + usesound = 'sound/effects/empulse.ogg' + toolspeed = 0.1 + origin_tech = "materials=5;engineering=5;abductor=3" + +/obj/item/wrench/power + name = "hand drill" + desc = "A simple powered hand drill. It's fitted with a bolt bit." + icon_state = "drill_bolt" + item_state = "drill" + lefthand_file = 'icons/mob/inhands/equipment/tools_lefthand.dmi' + righthand_file = 'icons/mob/inhands/equipment/tools_righthand.dmi' + usesound = 'sound/items/drill_use.ogg' + materials = list(MAT_METAL=150,MAT_SILVER=50,MAT_TITANIUM=25) + origin_tech = "materials=2;engineering=2" //done for balance reasons, making them high value for research, but harder to get + force = 8 //might or might not be too high, subject to change + w_class = WEIGHT_CLASS_SMALL + throwforce = 8 + attack_verb = list("drilled", "screwed", "jabbed") + toolspeed = 0.25 + +/obj/item/wrench/power/attack_self(mob/user) + playsound(get_turf(user),'sound/items/change_drill.ogg',50,1) + var/obj/item/wirecutters/power/s_drill = new /obj/item/screwdriver/power + to_chat(user, "You attach the screw driver bit to [src].") + qdel(src) + user.put_in_active_hand(s_drill) + +/obj/item/wrench/power/suicide_act(mob/user) + user.visible_message("[user] is pressing [src] against [user.p_their()] head! It looks like [user.p_theyre()] trying to commit suicide!") + return (BRUTELOSS) + +/obj/item/wrench/medical + name = "medical wrench" + desc = "A medical wrench with common(medical?) uses. Can be found in your hand." + icon_state = "wrench_medical" + force = 2 //MEDICAL + throwforce = 4 + origin_tech = "materials=1;engineering=1;biotech=3" + attack_verb = list("wrenched", "medicaled", "tapped", "jabbed", "whacked") + +/obj/item/wrench/medical/suicide_act(mob/living/user) + user.visible_message("[user] is praying to the medical wrench to take [user.p_their()] soul. It looks like [user.p_theyre()] trying to commit suicide!") + // TODO Make them glow with the power of the M E D I C A L W R E N C H + // during their ascension + + // Stun stops them from wandering off + user.Stun(100, ignore_canstun = TRUE) + playsound(loc, 'sound/effects/pray.ogg', 50, 1, -1) + + // Let the sound effect finish playing + sleep(20) + + if(!user) + return + + for(var/obj/item/W in user) + user.dropItemToGround(W) + + var/obj/item/wrench/medical/W = new /obj/item/wrench/medical(loc) + W.add_fingerprint(user) + W.desc += " For some reason, it reminds you of [user.name]." + + if(!user) + return + + user.dust() + + return OXYLOSS + +/* + * Screwdriver + */ +/obj/item/screwdriver + name = "screwdriver" + desc = "You can be totally screwy with this." + icon = 'icons/obj/tools.dmi' + icon_state = "screwdriver" + item_state = "screwdriver" + lefthand_file = 'icons/mob/inhands/equipment/tools_lefthand.dmi' + righthand_file = 'icons/mob/inhands/equipment/tools_righthand.dmi' + flags_1 = CONDUCT_1 + slot_flags = SLOT_BELT + force = 5 + w_class = WEIGHT_CLASS_TINY + throwforce = 5 + throw_speed = 3 + throw_range = 5 + materials = list(MAT_METAL=75) + attack_verb = list("stabbed") + hitsound = 'sound/weapons/bladeslice.ogg' + usesound = 'sound/items/screwdriver.ogg' + toolspeed = 1 + armor = list(melee = 0, bullet = 0, laser = 0, energy = 0, bomb = 0, bio = 0, rad = 0, fire = 50, acid = 30) + var/random_color = TRUE //if the screwdriver uses random coloring + var/static/list/screwdriver_colors = list(\ + "blue" = rgb(24, 97, 213), \ + "red" = rgb(149, 23, 16), \ + "pink" = rgb(213, 24, 141), \ + "brown" = rgb(160, 82, 18), \ + "green" = rgb(14, 127, 27), \ + "cyan" = rgb(24, 162, 213), \ + "yellow" = rgb(213, 140, 24), \ + ) + +/obj/item/screwdriver/suicide_act(mob/user) + user.visible_message("[user] is stabbing [src] into [user.p_their()] [pick("temple", "heart")]! It looks like [user.p_theyre()] trying to commit suicide!") + return(BRUTELOSS) + +/obj/item/screwdriver/Initialize() + . = ..() + if(random_color) //random colors! + var/our_color = pick(screwdriver_colors) + add_atom_colour(screwdriver_colors[our_color], FIXED_COLOUR_PRIORITY) + update_icon() + if(prob(75)) + pixel_y = rand(0, 16) + +/obj/item/screwdriver/update_icon() + if(!random_color) //icon override + return + cut_overlays() + var/mutable_appearance/base_overlay = mutable_appearance(icon, "screwdriver_screwybits") + base_overlay.appearance_flags = RESET_COLOR + add_overlay(base_overlay) + +/obj/item/screwdriver/worn_overlays(isinhands = FALSE, icon_file) + . = list() + if(isinhands && random_color) + var/mutable_appearance/M = mutable_appearance(icon_file, "screwdriver_head") + M.appearance_flags = RESET_COLOR + . += M + +/obj/item/screwdriver/get_belt_overlay() + if(random_color) + var/mutable_appearance/body = mutable_appearance('icons/obj/clothing/belt_overlays.dmi', "screwdriver") + var/mutable_appearance/head = mutable_appearance('icons/obj/clothing/belt_overlays.dmi', "screwdriver_head") + body.color = color + head.add_overlay(body) + return head + else + return mutable_appearance('icons/obj/clothing/belt_overlays.dmi', icon_state) + +/obj/item/screwdriver/attack(mob/living/carbon/M, mob/living/carbon/user) + if(!istype(M)) + return ..() + if(user.zone_selected != "eyes" && user.zone_selected != "head") + return ..() + if(user.disabilities & CLUMSY && prob(50)) + M = user + return eyestab(M,user) + +/obj/item/screwdriver/brass + name = "brass screwdriver" + desc = "A screwdriver made of brass. The handle feels freezing cold." + resistance_flags = FIRE_PROOF | ACID_PROOF + icon_state = "screwdriver_brass" + item_state = "screwdriver_brass" + toolspeed = 0.5 + random_color = FALSE + +/obj/item/screwdriver/abductor + name = "alien screwdriver" + desc = "An ultrasonic screwdriver." + icon = 'icons/obj/abductor.dmi' + icon_state = "screwdriver_a" + item_state = "screwdriver_nuke" + usesound = 'sound/items/pshoom.ogg' + toolspeed = 0.1 + random_color = FALSE + +/obj/item/screwdriver/power + name = "hand drill" + desc = "A simple powered hand drill. It's fitted with a screw bit." + icon_state = "drill_screw" + item_state = "drill" + lefthand_file = 'icons/mob/inhands/equipment/tools_lefthand.dmi' + righthand_file = 'icons/mob/inhands/equipment/tools_righthand.dmi' + materials = list(MAT_METAL=150,MAT_SILVER=50,MAT_TITANIUM=25) + origin_tech = "materials=2;engineering=2" //done for balance reasons, making them high value for research, but harder to get + force = 8 //might or might not be too high, subject to change + w_class = WEIGHT_CLASS_SMALL + throwforce = 8 + throw_speed = 2 + throw_range = 3//it's heavier than a screw driver/wrench, so it does more damage, but can't be thrown as far + attack_verb = list("drilled", "screwed", "jabbed","whacked") + hitsound = 'sound/items/drill_hit.ogg' + usesound = 'sound/items/drill_use.ogg' + toolspeed = 0.25 + random_color = FALSE + +/obj/item/screwdriver/power/suicide_act(mob/user) + user.visible_message("[user] is putting [src] to [user.p_their()] temple. It looks like [user.p_theyre()] trying to commit suicide!") + return(BRUTELOSS) + +/obj/item/screwdriver/power/attack_self(mob/user) + playsound(get_turf(user),'sound/items/change_drill.ogg',50,1) + var/obj/item/wrench/power/b_drill = new /obj/item/wrench/power + to_chat(user, "You attach the bolt driver bit to [src].") + qdel(src) + user.put_in_active_hand(b_drill) + +/obj/item/screwdriver/cyborg + name = "powered screwdriver" + desc = "An electrical screwdriver, designed to be both precise and quick." + usesound = 'sound/items/drill_use.ogg' + toolspeed = 0.5 + +/* + * Wirecutters + */ +/obj/item/wirecutters + name = "wirecutters" + desc = "This cuts wires." + icon = 'icons/obj/tools.dmi' + icon_state = null + lefthand_file = 'icons/mob/inhands/equipment/tools_lefthand.dmi' + righthand_file = 'icons/mob/inhands/equipment/tools_righthand.dmi' + flags_1 = CONDUCT_1 + slot_flags = SLOT_BELT + force = 6 + throw_speed = 3 + throw_range = 7 + w_class = WEIGHT_CLASS_SMALL + materials = list(MAT_METAL=80) + attack_verb = list("pinched", "nipped") + hitsound = 'sound/items/wirecutter.ogg' + usesound = 'sound/items/wirecutter.ogg' + origin_tech = "materials=1;engineering=1" + toolspeed = 1 + armor = list(melee = 0, bullet = 0, laser = 0, energy = 0, bomb = 0, bio = 0, rad = 0, fire = 50, acid = 30) + + +/obj/item/wirecutters/New(loc, var/param_color = null) + ..() + if(!icon_state) + if(!param_color) + param_color = pick("yellow","red") + icon_state = "cutters_[param_color]" + +/obj/item/wirecutters/attack(mob/living/carbon/C, mob/user) + if(istype(C) && C.handcuffed && istype(C.handcuffed, /obj/item/restraints/handcuffs/cable)) + user.visible_message("[user] cuts [C]'s restraints with [src]!") + qdel(C.handcuffed) + C.handcuffed = null + if(C.buckled && C.buckled.buckle_requires_restraints) + C.buckled.unbuckle_mob(C) + C.update_handcuffed() + return + else + ..() + +/obj/item/wirecutters/suicide_act(mob/user) + user.visible_message("[user] is cutting at [user.p_their()] arteries with [src]! It looks like [user.p_theyre()] trying to commit suicide!") + playsound(loc, usesound, 50, 1, -1) + return (BRUTELOSS) + +/obj/item/wirecutters/brass + name = "brass wirecutters" + desc = "A pair of wirecutters made of brass. The handle feels freezing cold to the touch." + resistance_flags = FIRE_PROOF | ACID_PROOF + icon_state = "cutters_brass" + toolspeed = 0.5 + +/obj/item/wirecutters/abductor + name = "alien wirecutters" + desc = "Extremely sharp wirecutters, made out of a silvery-green metal." + icon = 'icons/obj/abductor.dmi' + icon_state = "cutters" + toolspeed = 0.1 + origin_tech = "materials=5;engineering=4;abductor=3" + +/obj/item/wirecutters/cyborg + name = "wirecutters" + desc = "This cuts wires." + toolspeed = 0.5 + +/obj/item/wirecutters/power + name = "jaws of life" + desc = "A set of jaws of life, compressed through the magic of science. It's fitted with a cutting head." + icon_state = "jaws_cutter" + item_state = "jawsoflife" + origin_tech = "materials=2;engineering=2" + materials = list(MAT_METAL=150,MAT_SILVER=50,MAT_TITANIUM=25) + usesound = 'sound/items/jaws_cut.ogg' + toolspeed = 0.25 + +/obj/item/wirecutters/power/suicide_act(mob/user) + user.visible_message("[user] is wrapping \the [src] around [user.p_their()] neck. It looks like [user.p_theyre()] trying to rip [user.p_their()] head off!") + playsound(loc, 'sound/items/jaws_cut.ogg', 50, 1, -1) + if(iscarbon(user)) + var/mob/living/carbon/C = user + var/obj/item/bodypart/BP = C.get_bodypart("head") + if(BP) + BP.drop_limb() + playsound(loc,pick('sound/misc/desceration-01.ogg','sound/misc/desceration-02.ogg','sound/misc/desceration-01.ogg') ,50, 1, -1) + return (BRUTELOSS) + +/obj/item/wirecutters/power/attack_self(mob/user) + playsound(get_turf(user), 'sound/items/change_jaws.ogg', 50, 1) + var/obj/item/crowbar/power/pryjaws = new /obj/item/crowbar/power + to_chat(user, "You attach the pry jaws to [src].") + qdel(src) + user.put_in_active_hand(pryjaws) +/* + * Welding Tool + */ +/obj/item/weldingtool + name = "welding tool" + desc = "A standard edition welder provided by Nanotrasen." + icon = 'icons/obj/tools.dmi' + icon_state = "welder" + item_state = "welder" + lefthand_file = 'icons/mob/inhands/equipment/tools_lefthand.dmi' + righthand_file = 'icons/mob/inhands/equipment/tools_righthand.dmi' + flags_1 = CONDUCT_1 + slot_flags = SLOT_BELT + force = 3 + throwforce = 5 + hitsound = "swing_hit" + usesound = 'sound/items/welder.ogg' + var/acti_sound = 'sound/items/welderactivate.ogg' + var/deac_sound = 'sound/items/welderdeactivate.ogg' + throw_speed = 3 + throw_range = 5 + w_class = WEIGHT_CLASS_SMALL + armor = list(melee = 0, bullet = 0, laser = 0, energy = 0, bomb = 0, bio = 0, rad = 0, fire = 100, acid = 30) + resistance_flags = FIRE_PROOF + + materials = list(MAT_METAL=70, MAT_GLASS=30) + origin_tech = "engineering=1;plasmatech=1" + var/welding = 0 //Whether or not the welding tool is off(0), on(1) or currently welding(2) + var/status = TRUE //Whether the welder is secured or unsecured (able to attach rods to it to make a flamethrower) + var/max_fuel = 20 //The max amount of fuel the welder can hold + var/change_icons = 1 + var/can_off_process = 0 + var/light_intensity = 2 //how powerful the emitted light is when used. + var/burned_fuel_for = 0 //when fuel was last removed + heat = 3800 + toolspeed = 1 + +/obj/item/weldingtool/Initialize() + . = ..() + create_reagents(max_fuel) + reagents.add_reagent("welding_fuel", max_fuel) + update_icon() + + +/obj/item/weldingtool/proc/update_torch() + if(welding) + add_overlay("[initial(icon_state)]-on") + item_state = "[initial(item_state)]1" + else + item_state = "[initial(item_state)]" + + +/obj/item/weldingtool/update_icon() + cut_overlays() + if(change_icons) + var/ratio = get_fuel() / max_fuel + ratio = Ceiling(ratio*4) * 25 + add_overlay("[initial(icon_state)][ratio]") + update_torch() + return + + +/obj/item/weldingtool/process() + switch(welding) + if(0) + force = 3 + damtype = "brute" + update_icon() + if(!can_off_process) + STOP_PROCESSING(SSobj, src) + return + //Welders left on now use up fuel, but lets not have them run out quite that fast + if(1) + force = 15 + damtype = "fire" + ++burned_fuel_for + if(burned_fuel_for >= WELDER_FUEL_BURN_INTERVAL) + remove_fuel(1) + update_icon() + + //This is to start fires. process() is only called if the welder is on. + open_flame() + + +/obj/item/weldingtool/suicide_act(mob/user) + user.visible_message("[user] welds [user.p_their()] every orifice closed! It looks like [user.p_theyre()] trying to commit suicide!") + return (FIRELOSS) + + +/obj/item/weldingtool/attackby(obj/item/I, mob/user, params) + if(istype(I, /obj/item/screwdriver)) + flamethrower_screwdriver(I, user) + else if(istype(I, /obj/item/stack/rods)) + flamethrower_rods(I, user) + else + return ..() + + +/obj/item/weldingtool/attack(mob/living/carbon/human/H, mob/user) + if(!istype(H)) + return ..() + + var/obj/item/bodypart/affecting = H.get_bodypart(check_zone(user.zone_selected)) + + if(affecting && affecting.status == BODYPART_ROBOTIC && user.a_intent != INTENT_HARM) + if(src.remove_fuel(1)) + playsound(loc, usesound, 50, 1) + if(user == H) + user.visible_message("[user] starts to fix some of the dents on [H]'s [affecting.name].", "You start fixing some of the dents on [H]'s [affecting.name].") + if(!do_mob(user, H, 50)) + return + item_heal_robotic(H, user, 15, 0) + else + return ..() + + +/obj/item/weldingtool/afterattack(atom/O, mob/user, proximity) + if(!proximity) return + + if(welding) + remove_fuel(1) + var/turf/location = get_turf(user) + location.hotspot_expose(700, 50, 1) + if(get_fuel() <= 0) + set_light(0) + + if(isliving(O)) + var/mob/living/L = O + if(L.IgniteMob()) + message_admins("[key_name_admin(user)] set [key_name_admin(L)] on fire") + log_game("[key_name(user)] set [key_name(L)] on fire") + + +/obj/item/weldingtool/attack_self(mob/user) + switched_on(user) + if(welding) + set_light(light_intensity) + + update_icon() + + +//Returns the amount of fuel in the welder +/obj/item/weldingtool/proc/get_fuel() + return reagents.get_reagent_amount("welding_fuel") + + +//Removes fuel from the welding tool. If a mob is passed, it will try to flash the mob's eyes. This should probably be renamed to use() +/obj/item/weldingtool/proc/remove_fuel(amount = 1, mob/living/M = null) + if(!welding || !check_fuel()) + return 0 + if(amount) + burned_fuel_for = 0 + if(get_fuel() >= amount) + reagents.remove_reagent("welding_fuel", amount) + check_fuel() + if(M) + M.flash_act(light_intensity) + return TRUE + else + if(M) + to_chat(M, "You need more welding fuel to complete this task!") + return FALSE + + +//Turns off the welder if there is no more fuel (does this really need to be its own proc?) +/obj/item/weldingtool/proc/check_fuel(mob/user) + if(get_fuel() <= 0 && welding) + switched_on(user) + update_icon() + //mob icon update + if(ismob(loc)) + var/mob/M = loc + M.update_inv_hands(0) + + return 0 + return 1 + +//Switches the welder on +/obj/item/weldingtool/proc/switched_on(mob/user) + if(!status) + to_chat(user, "[src] can't be turned on while unsecured!") + return + welding = !welding + if(welding) + if(get_fuel() >= 1) + to_chat(user, "You switch [src] on.") + playsound(loc, acti_sound, 50, 1) + force = 15 + damtype = "fire" + hitsound = 'sound/items/welder.ogg' + update_icon() + START_PROCESSING(SSobj, src) + else + to_chat(user, "You need more fuel!") + switched_off(user) + else + to_chat(user, "You switch [src] off.") + playsound(loc, deac_sound, 50, 1) + switched_off(user) + +//Switches the welder off +/obj/item/weldingtool/proc/switched_off(mob/user) + welding = 0 + set_light(0) + + force = 3 + damtype = "brute" + hitsound = "swing_hit" + update_icon() + + +/obj/item/weldingtool/examine(mob/user) + ..() + to_chat(user, "It contains [get_fuel()] unit\s of fuel out of [max_fuel].") + +/obj/item/weldingtool/is_hot() + return welding * heat + +//Returns whether or not the welding tool is currently on. +/obj/item/weldingtool/proc/isOn() + return welding + + +/obj/item/weldingtool/proc/flamethrower_screwdriver(obj/item/I, mob/user) + if(welding) + to_chat(user, "Turn it off first!") + return + status = !status + if(status) + to_chat(user, "You resecure [src].") + else + to_chat(user, "[src] can now be attached and modified.") + add_fingerprint(user) + +/obj/item/weldingtool/proc/flamethrower_rods(obj/item/I, mob/user) + if(!status) + var/obj/item/stack/rods/R = I + if (R.use(1)) + var/obj/item/flamethrower/F = new /obj/item/flamethrower(user.loc) + if(!remove_item_from_storage(F)) + user.transferItemToLoc(src, F, TRUE) + F.weldtool = src + add_fingerprint(user) + to_chat(user, "You add a rod to a welder, starting to build a flamethrower.") + user.put_in_hands(F) + else + to_chat(user, "You need one rod to start building a flamethrower!") + +/obj/item/weldingtool/ignition_effect(atom/A, mob/user) + if(welding && remove_fuel(1, user)) + . = "[user] casually lights [A] with [src], what a badass." + else + . = "" + +/obj/item/weldingtool/largetank + name = "industrial welding tool" + desc = "A slightly larger welder with a larger tank." + icon_state = "indwelder" + max_fuel = 40 + materials = list(MAT_GLASS=60) + origin_tech = "engineering=2;plasmatech=2" + +/obj/item/weldingtool/largetank/cyborg + name = "integrated welding tool" + desc = "An advanced welder designed to be used in robotic systems." + toolspeed = 0.5 + +/obj/item/weldingtool/largetank/flamethrower_screwdriver() + return + + +/obj/item/weldingtool/mini + name = "emergency welding tool" + desc = "A miniature welder used during emergencies." + icon_state = "miniwelder" + max_fuel = 10 + w_class = WEIGHT_CLASS_TINY + materials = list(MAT_METAL=30, MAT_GLASS=10) + change_icons = 0 + +/obj/item/weldingtool/mini/flamethrower_screwdriver() + return + +/obj/item/weldingtool/abductor + name = "alien welding tool" + desc = "An alien welding tool. Whatever fuel it uses, it never runs out." + icon = 'icons/obj/abductor.dmi' + icon_state = "welder" + toolspeed = 0.1 + light_intensity = 0 + change_icons = 0 + origin_tech = "plasmatech=5;engineering=5;abductor=3" + +/obj/item/weldingtool/abductor/process() + if(get_fuel() <= max_fuel) + reagents.add_reagent("welding_fuel", 1) + ..() + +/obj/item/weldingtool/hugetank + name = "upgraded industrial welding tool" + desc = "An upgraded welder based of the industrial welder." + icon_state = "upindwelder" + item_state = "upindwelder" + max_fuel = 80 + materials = list(MAT_METAL=70, MAT_GLASS=120) + origin_tech = "engineering=3;plasmatech=2" + +/obj/item/weldingtool/experimental + name = "experimental welding tool" + desc = "An experimental welder capable of self-fuel generation and less harmful to the eyes." + icon_state = "exwelder" + item_state = "exwelder" + max_fuel = 40 + materials = list(MAT_METAL=70, MAT_GLASS=120) + origin_tech = "materials=4;engineering=4;bluespace=3;plasmatech=4" + var/last_gen = 0 + change_icons = 0 + can_off_process = 1 + light_intensity = 1 + toolspeed = 0.5 + var/nextrefueltick = 0 + +/obj/item/weldingtool/experimental/brass + name = "brass welding tool" + desc = "A brass welder that seems to constantly refuel itself. It is faintly warm to the touch." + resistance_flags = FIRE_PROOF | ACID_PROOF + icon_state = "brasswelder" + item_state = "brasswelder" + + +/obj/item/weldingtool/experimental/process() + ..() + if(get_fuel() < max_fuel && nextrefueltick < world.time) + nextrefueltick = world.time + 10 + reagents.add_reagent("welding_fuel", 1) + + +/* + * Crowbar + */ + +/obj/item/crowbar + name = "pocket crowbar" + desc = "A small crowbar. This handy tool is useful for lots of things, such as prying floor tiles or opening unpowered doors." + icon = 'icons/obj/tools.dmi' + icon_state = "crowbar" + lefthand_file = 'icons/mob/inhands/equipment/tools_lefthand.dmi' + righthand_file = 'icons/mob/inhands/equipment/tools_righthand.dmi' + usesound = 'sound/items/crowbar.ogg' + flags_1 = CONDUCT_1 + slot_flags = SLOT_BELT + force = 5 + throwforce = 7 + w_class = WEIGHT_CLASS_SMALL + materials = list(MAT_METAL=50) + origin_tech = "engineering=1;combat=1" + attack_verb = list("attacked", "bashed", "battered", "bludgeoned", "whacked") + toolspeed = 1 + armor = list(melee = 0, bullet = 0, laser = 0, energy = 0, bomb = 0, bio = 0, rad = 0, fire = 50, acid = 30) + +/obj/item/crowbar/suicide_act(mob/user) + user.visible_message("[user] is beating [user.p_them()]self to death with [src]! It looks like [user.p_theyre()] trying to commit suicide!") + playsound(loc, 'sound/weapons/genhit.ogg', 50, 1, -1) + return (BRUTELOSS) + +/obj/item/crowbar/red + icon_state = "crowbar_red" + force = 8 + +/obj/item/crowbar/brass + name = "brass crowbar" + desc = "A brass crowbar. It feels faintly warm to the touch." + resistance_flags = FIRE_PROOF | ACID_PROOF + icon_state = "crowbar_brass" + toolspeed = 0.5 + +/obj/item/crowbar/abductor + name = "alien crowbar" + desc = "A hard-light crowbar. It appears to pry by itself, without any effort required." + icon = 'icons/obj/abductor.dmi' + usesound = 'sound/weapons/sonic_jackhammer.ogg' + icon_state = "crowbar" + toolspeed = 0.1 + origin_tech = "combat=4;engineering=4;abductor=3" + +/obj/item/crowbar/large + name = "crowbar" + desc = "It's a big crowbar. It doesn't fit in your pockets, because it's big." + force = 12 + w_class = WEIGHT_CLASS_NORMAL + throw_speed = 3 + throw_range = 3 + materials = list(MAT_METAL=70) + icon_state = "crowbar_large" + item_state = "crowbar" + toolspeed = 0.5 + +/obj/item/crowbar/cyborg + name = "hydraulic crowbar" + desc = "A hydraulic prying tool, compact but powerful. Designed to replace crowbar in construction cyborgs." + usesound = 'sound/items/jaws_pry.ogg' + force = 10 + toolspeed = 0.5 + +/obj/item/crowbar/power + name = "jaws of life" + desc = "A set of jaws of life, compressed through the magic of science. It's fitted with a prying head." + icon_state = "jaws_pry" + item_state = "jawsoflife" + lefthand_file = 'icons/mob/inhands/equipment/tools_lefthand.dmi' + righthand_file = 'icons/mob/inhands/equipment/tools_righthand.dmi' + materials = list(MAT_METAL=150,MAT_SILVER=50,MAT_TITANIUM=25) + origin_tech = "materials=2;engineering=2" + usesound = 'sound/items/jaws_pry.ogg' + force = 15 + toolspeed = 0.25 + +/obj/item/crowbar/power/suicide_act(mob/user) + user.visible_message("[user] is putting [user.p_their()] head in [src], it looks like [user.p_theyre()] trying to commit suicide!") + playsound(loc, 'sound/items/jaws_pry.ogg', 50, 1, -1) + return (BRUTELOSS) + +/obj/item/crowbar/power/attack_self(mob/user) + playsound(get_turf(user), 'sound/items/change_jaws.ogg', 50, 1) + var/obj/item/wirecutters/power/cutjaws = new /obj/item/wirecutters/power + to_chat(user, "You attach the cutting jaws to [src].") + qdel(src) + user.put_in_active_hand(cutjaws) + +#undef WELDER_FUEL_BURN_INTERVAL +>>>>>>> 2240756... Gets rid of manual overlay manipulation (#30454) diff --git a/code/game/turfs/turf.dm b/code/game/turfs/turf.dm index e6314861b6..c8be2aa28a 100755 --- a/code/game/turfs/turf.dm +++ b/code/game/turfs/turf.dm @@ -524,12 +524,12 @@ /turf/proc/photograph(limit=20) var/image/I = new() - I.overlays += src + I.add_overlay(src) for(var/V in contents) var/atom/A = V if(A.invisibility) continue - I.overlays += A + I.add_overlay(A) if(limit) limit-- else diff --git a/code/modules/hydroponics/hydroponics.dm b/code/modules/hydroponics/hydroponics.dm index 66a15ac705..52f5e4e138 100644 --- a/code/modules/hydroponics/hydroponics.dm +++ b/code/modules/hydroponics/hydroponics.dm @@ -248,7 +248,7 @@ if(istype(src, /obj/machinery/hydroponics/soil)) add_atom_colour(rgb(255, 175, 0), FIXED_COLOUR_PRIORITY) else - overlays += mutable_appearance('icons/obj/hydroponics/equipment.dmi', "gaia_blessing") + add_overlay(mutable_appearance('icons/obj/hydroponics/equipment.dmi', "gaia_blessing")) set_light(3) update_icon_hoses() From d8a3b87719be4d429bccd12d6f13a4d531318d76 Mon Sep 17 00:00:00 2001 From: ShizCalev Date: Thu, 7 Sep 2017 06:14:17 -0400 Subject: [PATCH 06/74] Fixes brains counting towards highlander killstreaks --- code/game/objects/items/weaponry.dm | 569 ++++++++++++++++++++++++++++ 1 file changed, 569 insertions(+) diff --git a/code/game/objects/items/weaponry.dm b/code/game/objects/items/weaponry.dm index 13acf7e990..fe9c9485cd 100644 --- a/code/game/objects/items/weaponry.dm +++ b/code/game/objects/items/weaponry.dm @@ -23,6 +23,7 @@ else M.visible_message("[M] has been banned FOR NO REISIN by [user]", "You have been banned FOR NO REISIN by [user]", "you hear a banhammer banning someone") +<<<<<<< HEAD playsound(loc, 'sound/effects/adminhelp.ogg', 15) //keep it at 15% volume so people don't jump out of their skin too much /obj/item/sord @@ -589,4 +590,572 @@ /obj/item/proc/can_trigger_gun(mob/living/user) if(!user.can_use_guns(src)) return FALSE +======= + playsound(loc, 'sound/effects/adminhelp.ogg', 15) //keep it at 15% volume so people don't jump out of their skin too much + +/obj/item/sord + name = "\improper SORD" + desc = "This thing is so unspeakably shitty you are having a hard time even holding it." + icon_state = "sord" + item_state = "sord" + lefthand_file = 'icons/mob/inhands/weapons/swords_lefthand.dmi' + righthand_file = 'icons/mob/inhands/weapons/swords_righthand.dmi' + slot_flags = SLOT_BELT + force = 2 + throwforce = 1 + w_class = WEIGHT_CLASS_NORMAL + hitsound = 'sound/weapons/bladeslice.ogg' + attack_verb = list("attacked", "slashed", "stabbed", "sliced", "torn", "ripped", "diced", "cut") + +/obj/item/sord/suicide_act(mob/user) + user.visible_message("[user] is trying to impale [user.p_them()]self with [src]! It might be a suicide attempt if it weren't so shitty.", \ + "You try to impale yourself with [src], but it's USELESS...") + return SHAME + +/obj/item/claymore + name = "claymore" + desc = "What are you standing around staring at this for? Get to killing!" + icon_state = "claymore" + item_state = "claymore" + lefthand_file = 'icons/mob/inhands/weapons/swords_lefthand.dmi' + righthand_file = 'icons/mob/inhands/weapons/swords_righthand.dmi' + hitsound = 'sound/weapons/bladeslice.ogg' + flags_1 = CONDUCT_1 + slot_flags = SLOT_BELT | SLOT_BACK + force = 40 + throwforce = 10 + w_class = WEIGHT_CLASS_NORMAL + attack_verb = list("attacked", "slashed", "stabbed", "sliced", "torn", "ripped", "diced", "cut") + block_chance = 50 + sharpness = IS_SHARP + max_integrity = 200 + armor = list(melee = 0, bullet = 0, laser = 0, energy = 0, bomb = 0, bio = 0, rad = 0, fire = 100, acid = 50) + resistance_flags = FIRE_PROOF + +/obj/item/claymore/suicide_act(mob/user) + user.visible_message("[user] is falling on [src]! It looks like [user.p_theyre()] trying to commit suicide!") + return(BRUTELOSS) + +/obj/item/claymore/highlander //ALL COMMENTS MADE REGARDING THIS SWORD MUST BE MADE IN ALL CAPS + desc = "THERE CAN BE ONLY ONE, AND IT WILL BE YOU!!!\nActivate it in your hand to point to the nearest victim." + flags_1 = CONDUCT_1 | NODROP_1 | DROPDEL_1 + slot_flags = null + block_chance = 0 //RNG WON'T HELP YOU NOW, PANSY + luminosity = 3 + attack_verb = list("brutalized", "eviscerated", "disemboweled", "hacked", "carved", "cleaved") //ONLY THE MOST VISCERAL ATTACK VERBS + var/notches = 0 //HOW MANY PEOPLE HAVE BEEN SLAIN WITH THIS BLADE + var/obj/item/disk/nuclear/nuke_disk //OUR STORED NUKE DISK + +/obj/item/claymore/highlander/Initialize() + . = ..() + START_PROCESSING(SSobj, src) + +/obj/item/claymore/highlander/Destroy() + if(nuke_disk) + nuke_disk.forceMove(get_turf(src)) + nuke_disk.visible_message("The nuke disk is vulnerable!") + nuke_disk = null + STOP_PROCESSING(SSobj, src) + return ..() + +/obj/item/claymore/highlander/process() + if(ishuman(loc)) + var/mob/living/carbon/human/H = loc + loc.layer = LARGE_MOB_LAYER //NO HIDING BEHIND PLANTS FOR YOU, DICKWEED (HA GET IT, BECAUSE WEEDS ARE PLANTS) + H.bleedsuppress = TRUE //AND WE WON'T BLEED OUT LIKE COWARDS + else + if(!admin_spawned) + qdel(src) + + +/obj/item/claymore/highlander/pickup(mob/living/user) + to_chat(user, "The power of Scotland protects you! You are shielded from all stuns and knockdowns.") + user.add_stun_absorption("highlander", INFINITY, 1, " is protected by the power of Scotland!", "The power of Scotland absorbs the stun!", " is protected by the power of Scotland!") + user.status_flags += IGNORESLOWDOWN + +/obj/item/claymore/highlander/dropped(mob/living/user) + user.status_flags -= IGNORESLOWDOWN + qdel(src) //If this ever happens, it's because you lost an arm + +/obj/item/claymore/highlander/examine(mob/user) + ..() + to_chat(user, "It has [!notches ? "nothing" : "[notches] notches"] scratched into the blade.") + if(nuke_disk) + to_chat(user, "It's holding the nuke disk!") + +/obj/item/claymore/highlander/attack(mob/living/target, mob/living/user) + . = ..() + if(!QDELETED(target) && iscarbon(target) && target.stat == DEAD && target.mind && target.mind.special_role == "highlander") + user.fully_heal() //STEAL THE LIFE OF OUR FALLEN FOES + add_notch(user) + target.visible_message("[target] crumbles to dust beneath [user]'s blows!", "As you fall, your body crumbles to dust!") + target.dust() + +/obj/item/claymore/highlander/attack_self(mob/living/user) + var/closest_victim + var/closest_distance = 255 + for(var/mob/living/carbon/human/H in GLOB.player_list - user) + if(H.client && H.mind.special_role == "highlander" && (!closest_victim || get_dist(user, closest_victim) < closest_distance)) + closest_victim = H + if(!closest_victim) + to_chat(user, "[src] thrums for a moment and falls dark. Perhaps there's nobody nearby.") + return + to_chat(user, "[src] thrums and points to the [dir2text(get_dir(user, closest_victim))].") + +/obj/item/claymore/highlander/IsReflect() + return 1 //YOU THINK YOUR PUNY LASERS CAN STOP ME? + +/obj/item/claymore/highlander/proc/add_notch(mob/living/user) //DYNAMIC CLAYMORE PROGRESSION SYSTEM - THIS IS THE FUTURE + notches++ + force++ + var/new_name = name + switch(notches) + if(1) + to_chat(user, "Your first kill - hopefully one of many. You scratch a notch into [src]'s blade.") + to_chat(user, "You feel your fallen foe's soul entering your blade, restoring your wounds!") + new_name = "notched claymore" + if(2) + to_chat(user, "Another falls before you. Another soul fuses with your own. Another notch in the blade.") + new_name = "double-notched claymore" + add_atom_colour(rgb(255, 235, 235), ADMIN_COLOUR_PRIORITY) + if(3) + to_chat(user, "You're beginning to relish the thrill of battle.") + new_name = "triple-notched claymore" + add_atom_colour(rgb(255, 215, 215), ADMIN_COLOUR_PRIORITY) + if(4) + to_chat(user, "You've lost count of how many you've killed.") + new_name = "many-notched claymore" + add_atom_colour(rgb(255, 195, 195), ADMIN_COLOUR_PRIORITY) + if(5) + to_chat(user, "Five voices now echo in your mind, cheering the slaughter.") + new_name = "battle-tested claymore" + add_atom_colour(rgb(255, 175, 175), ADMIN_COLOUR_PRIORITY) + if(6) + to_chat(user, "Is this what the vikings felt like? Visions of glory fill your head as you slay your sixth foe.") + new_name = "battle-scarred claymore" + add_atom_colour(rgb(255, 155, 155), ADMIN_COLOUR_PRIORITY) + if(7) + to_chat(user, "Kill. Butcher. Conquer.") + new_name = "vicious claymore" + add_atom_colour(rgb(255, 135, 135), ADMIN_COLOUR_PRIORITY) + if(8) + to_chat(user, "IT NEVER GETS OLD. THE SCREAMING. THE BLOOD AS IT SPRAYS ACROSS YOUR FACE.") + new_name = "bloodthirsty claymore" + add_atom_colour(rgb(255, 115, 115), ADMIN_COLOUR_PRIORITY) + if(9) + to_chat(user, "ANOTHER ONE FALLS TO YOUR BLOWS. ANOTHER WEAKLING UNFIT TO LIVE.") + new_name = "gore-stained claymore" + add_atom_colour(rgb(255, 95, 95), ADMIN_COLOUR_PRIORITY) + if(10) + user.visible_message("[user]'s eyes light up with a vengeful fire!", \ + "YOU FEEL THE POWER OF VALHALLA FLOWING THROUGH YOU! THERE CAN BE ONLY ONE!!!") + user.update_icons() + new_name = "GORE-DRENCHED CLAYMORE OF [pick("THE WHIMSICAL SLAUGHTER", "A THOUSAND SLAUGHTERED CATTLE", "GLORY AND VALHALLA", "ANNIHILATION", "OBLITERATION")]" + icon_state = "claymore_valhalla" + item_state = "cultblade" + remove_atom_colour(ADMIN_COLOUR_PRIORITY) + + name = new_name + playsound(user, 'sound/items/screwdriver2.ogg', 50, 1) + +/obj/item/katana + name = "katana" + desc = "Woefully underpowered in D20" + icon_state = "katana" + item_state = "katana" + lefthand_file = 'icons/mob/inhands/weapons/swords_lefthand.dmi' + righthand_file = 'icons/mob/inhands/weapons/swords_righthand.dmi' + flags_1 = CONDUCT_1 + slot_flags = SLOT_BELT | SLOT_BACK + force = 40 + throwforce = 10 + w_class = WEIGHT_CLASS_NORMAL + hitsound = 'sound/weapons/bladeslice.ogg' + attack_verb = list("attacked", "slashed", "stabbed", "sliced", "torn", "ripped", "diced", "cut") + block_chance = 50 + sharpness = IS_SHARP + max_integrity = 200 + armor = list(melee = 0, bullet = 0, laser = 0, energy = 0, bomb = 0, bio = 0, rad = 0, fire = 100, acid = 50) + resistance_flags = FIRE_PROOF + +/obj/item/katana/cursed + slot_flags = null + +/obj/item/katana/suicide_act(mob/user) + user.visible_message("[user] is slitting [user.p_their()] stomach open with [src]! It looks like [user.p_theyre()] trying to commit seppuku!") + return(BRUTELOSS) + +/obj/item/wirerod + name = "wired rod" + desc = "A rod with some wire wrapped around the top. It'd be easy to attach something to the top bit." + icon_state = "wiredrod" + item_state = "rods" + flags_1 = CONDUCT_1 + force = 9 + throwforce = 10 + w_class = WEIGHT_CLASS_NORMAL + materials = list(MAT_METAL=1150, MAT_GLASS=75) + attack_verb = list("hit", "bludgeoned", "whacked", "bonked") + +/obj/item/wirerod/attackby(obj/item/I, mob/user, params) + if(istype(I, /obj/item/shard)) + var/obj/item/twohanded/spear/S = new /obj/item/twohanded/spear + + remove_item_from_storage(user) + qdel(I) + qdel(src) + + user.put_in_hands(S) + to_chat(user, "You fasten the glass shard to the top of the rod with the cable.") + + else if(istype(I, /obj/item/device/assembly/igniter) && !(I.flags_1 & NODROP_1)) + var/obj/item/melee/baton/cattleprod/P = new /obj/item/melee/baton/cattleprod + + remove_item_from_storage(user) + + to_chat(user, "You fasten [I] to the top of the rod with the cable.") + + qdel(I) + qdel(src) + + user.put_in_hands(P) + else + return ..() + + +/obj/item/throwing_star + name = "throwing star" + desc = "An ancient weapon still used to this day due to it's ease of lodging itself into victim's body parts" + icon_state = "throwingstar" + item_state = "eshield0" + lefthand_file = 'icons/mob/inhands/equipment/shields_lefthand.dmi' + righthand_file = 'icons/mob/inhands/equipment/shields_righthand.dmi' + force = 2 + throwforce = 20 //This is never used on mobs since this has a 100% embed chance. + throw_speed = 4 + embedded_pain_multiplier = 4 + w_class = WEIGHT_CLASS_SMALL + embed_chance = 100 + embedded_fall_chance = 0 //Hahaha! + sharpness = IS_SHARP + materials = list(MAT_METAL=500, MAT_GLASS=500) + resistance_flags = FIRE_PROOF + + +/obj/item/switchblade + name = "switchblade" + icon_state = "switchblade" + lefthand_file = 'icons/mob/inhands/weapons/swords_lefthand.dmi' + righthand_file = 'icons/mob/inhands/weapons/swords_righthand.dmi' + desc = "A sharp, concealable, spring-loaded knife." + flags_1 = CONDUCT_1 + force = 3 + w_class = WEIGHT_CLASS_SMALL + throwforce = 5 + throw_speed = 3 + throw_range = 6 + materials = list(MAT_METAL=12000) + origin_tech = "engineering=3;combat=2" + hitsound = 'sound/weapons/genhit.ogg' + attack_verb = list("stubbed", "poked") + resistance_flags = FIRE_PROOF + var/extended = 0 + +/obj/item/switchblade/attack_self(mob/user) + extended = !extended + playsound(src.loc, 'sound/weapons/batonextend.ogg', 50, 1) + if(extended) + force = 20 + w_class = WEIGHT_CLASS_NORMAL + throwforce = 23 + icon_state = "switchblade_ext" + attack_verb = list("slashed", "stabbed", "sliced", "torn", "ripped", "diced", "cut") + hitsound = 'sound/weapons/bladeslice.ogg' + sharpness = IS_SHARP + else + force = 3 + w_class = WEIGHT_CLASS_SMALL + throwforce = 5 + icon_state = "switchblade" + attack_verb = list("stubbed", "poked") + hitsound = 'sound/weapons/genhit.ogg' + sharpness = IS_BLUNT + +/obj/item/switchblade/suicide_act(mob/user) + user.visible_message("[user] is slitting [user.p_their()] own throat with [src]! It looks like [user.p_theyre()] trying to commit suicide!") + return (BRUTELOSS) + +/obj/item/phone + name = "red phone" + desc = "Should anything ever go wrong..." + icon = 'icons/obj/items_and_weapons.dmi' + icon_state = "red_phone" + force = 3 + throwforce = 2 + throw_speed = 3 + throw_range = 4 + w_class = WEIGHT_CLASS_SMALL + attack_verb = list("called", "rang") + hitsound = 'sound/weapons/ring.ogg' + +/obj/item/phone/suicide_act(mob/user) + if(locate(/obj/structure/chair/stool) in user.loc) + user.visible_message("[user] begins to tie a noose with [src]'s cord! It looks like [user.p_theyre()] trying to commit suicide!") + else + user.visible_message("[user] is strangling [user.p_them()]self with [src]'s cord! It looks like [user.p_theyre()] trying to commit suicide!") + return(OXYLOSS) + +/obj/item/cane + name = "cane" + desc = "A cane used by a true gentleman. Or a clown." + icon = 'icons/obj/items_and_weapons.dmi' + icon_state = "cane" + item_state = "stick" + lefthand_file = 'icons/mob/inhands/weapons/melee_lefthand.dmi' + righthand_file = 'icons/mob/inhands/weapons/melee_righthand.dmi' + force = 5 + throwforce = 5 + w_class = WEIGHT_CLASS_SMALL + materials = list(MAT_METAL=50) + attack_verb = list("bludgeoned", "whacked", "disciplined", "thrashed") + +/obj/item/staff + name = "wizard staff" + desc = "Apparently a staff used by the wizard." + icon = 'icons/obj/wizard.dmi' + icon_state = "staff" + lefthand_file = 'icons/mob/inhands/weapons/staves_lefthand.dmi' + righthand_file = 'icons/mob/inhands/weapons/staves_righthand.dmi' + force = 3 + throwforce = 5 + throw_speed = 2 + throw_range = 5 + w_class = WEIGHT_CLASS_SMALL + armour_penetration = 100 + attack_verb = list("bludgeoned", "whacked", "disciplined") + resistance_flags = FLAMMABLE + +/obj/item/staff/broom + name = "broom" + desc = "Used for sweeping, and flying into the night while cackling. Black cat not included." + icon = 'icons/obj/wizard.dmi' + icon_state = "broom" + resistance_flags = FLAMMABLE + +/obj/item/staff/stick + name = "stick" + desc = "A great tool to drag someone else's drinks across the bar." + icon = 'icons/obj/items_and_weapons.dmi' + icon_state = "stick" + item_state = "stick" + lefthand_file = 'icons/mob/inhands/weapons/melee_lefthand.dmi' + righthand_file = 'icons/mob/inhands/weapons/melee_righthand.dmi' + force = 3 + throwforce = 5 + throw_speed = 2 + throw_range = 5 + w_class = WEIGHT_CLASS_SMALL + +/obj/item/ectoplasm + name = "ectoplasm" + desc = "spooky" + gender = PLURAL + icon = 'icons/obj/wizard.dmi' + icon_state = "ectoplasm" + +/obj/item/ectoplasm/suicide_act(mob/user) + user.visible_message("[user] is inhaling [src]! It looks like [user.p_theyre()] trying to visit the astral plane.") + return (OXYLOSS) + +/obj/item/mounted_chainsaw + name = "mounted chainsaw" + desc = "A chainsaw that has replaced your arm." + icon_state = "chainsaw_on" + item_state = "mounted_chainsaw" + lefthand_file = 'icons/mob/inhands/weapons/chainsaw_lefthand.dmi' + righthand_file = 'icons/mob/inhands/weapons/chainsaw_righthand.dmi' + flags_1 = NODROP_1 | ABSTRACT_1 | DROPDEL_1 + w_class = WEIGHT_CLASS_HUGE + force = 21 + throwforce = 0 + throw_range = 0 + throw_speed = 0 + sharpness = IS_SHARP + attack_verb = list("sawed", "torn", "cut", "chopped", "diced") + hitsound = 'sound/weapons/chainsawhit.ogg' + +/obj/item/mounted_chainsaw/Destroy() + var/obj/item/bodypart/part + new /obj/item/twohanded/required/chainsaw(get_turf(src)) + if(iscarbon(loc)) + var/mob/living/carbon/holder = loc + var/index = holder.get_held_index_of_item(src) + if(index) + part = holder.hand_bodyparts[index] + . = ..() + if(part) + part.drop_limb() + +/obj/item/statuebust + name = "bust" + desc = "A priceless ancient marble bust, the kind that belongs in a museum." //or you can hit people with it + icon = 'icons/obj/statue.dmi' + icon_state = "bust" + force = 15 + throwforce = 10 + throw_speed = 5 + throw_range = 2 + attack_verb = list("busted") + +/obj/item/tailclub + name = "tail club" + desc = "For the beating to death of lizards with their own tails." + icon_state = "tailclub" + force = 14 + throwforce = 1 // why are you throwing a club do you even weapon + throw_speed = 1 + throw_range = 1 + attack_verb = list("clubbed", "bludgeoned") + +/obj/item/melee/chainofcommand/tailwhip + name = "liz o' nine tails" + desc = "A whip fashioned from the severed tails of lizards." + icon_state = "tailwhip" + origin_tech = "engineering=3;combat=3;biotech=3" + needs_permit = 0 + +/obj/item/melee/chainofcommand/tailwhip/kitty + name = "cat o' nine tails" + desc = "A whip fashioned from the severed tails of cats." + icon_state = "catwhip" + +/obj/item/melee/skateboard + name = "skateboard" + desc = "A skateboard. It can be placed on its wheels and ridden, or used as a strong weapon." + icon_state = "skateboard" + item_state = "skateboard" + force = 12 + throwforce = 4 + w_class = WEIGHT_CLASS_HUGE + attack_verb = list("smacked", "whacked", "slammed", "smashed") + +/obj/item/melee/skateboard/attack_self(mob/user) + new /obj/vehicle/scooter/skateboard(get_turf(user)) + qdel(src) + +/obj/item/melee/baseball_bat + name = "baseball bat" + desc = "There ain't a skull in the league that can withstand a swatter." + icon = 'icons/obj/items_and_weapons.dmi' + icon_state = "baseball_bat" + item_state = "baseball_bat" + lefthand_file = 'icons/mob/inhands/weapons/melee_lefthand.dmi' + righthand_file = 'icons/mob/inhands/weapons/melee_righthand.dmi' + force = 10 + throwforce = 12 + attack_verb = list("beat", "smacked") + w_class = WEIGHT_CLASS_HUGE + var/homerun_ready = 0 + var/homerun_able = 0 + +/obj/item/melee/baseball_bat/homerun + name = "home run bat" + desc = "This thing looks dangerous... Dangerously good at baseball, that is." + homerun_able = 1 + +/obj/item/melee/baseball_bat/attack_self(mob/user) + if(!homerun_able) + ..() + return + if(homerun_ready) + to_chat(user, "You're already ready to do a home run!") + ..() + return + to_chat(user, "You begin gathering strength...") + playsound(get_turf(src), 'sound/magic/lightning_chargeup.ogg', 65, 1) + if(do_after(user, 90, target = src)) + to_chat(user, "You gather power! Time for a home run!") + homerun_ready = 1 + ..() + +/obj/item/melee/baseball_bat/attack(mob/living/target, mob/living/user) + . = ..() + var/atom/throw_target = get_edge_target_turf(target, user.dir) + if(homerun_ready) + user.visible_message("It's a home run!") + target.throw_at(throw_target, rand(8,10), 14, user) + target.ex_act(EXPLODE_HEAVY) + playsound(get_turf(src), 'sound/weapons/homerun.ogg', 100, 1) + homerun_ready = 0 + return + else if(!target.anchored) + target.throw_at(throw_target, rand(1,2), 7, user) + +/obj/item/melee/baseball_bat/ablative + name = "metal baseball bat" + desc = "This bat is made of highly reflective, highly armored material." + icon_state = "baseball_bat_metal" + item_state = "baseball_bat_metal" + force = 12 + throwforce = 15 + +/obj/item/melee/baseball_bat/ablative/IsReflect()//some day this will reflect thrown items instead of lasers + var/picksound = rand(1,2) + var/turf = get_turf(src) + if(picksound == 1) + playsound(turf, 'sound/weapons/effects/batreflect1.ogg', 50, 1) + if(picksound == 2) + playsound(turf, 'sound/weapons/effects/batreflect2.ogg', 50, 1) + return 1 + +/obj/item/melee/flyswatter + name = "flyswatter" + desc = "Useful for killing insects of all sizes." + icon = 'icons/obj/items_and_weapons.dmi' + icon_state = "flyswatter" + item_state = "flyswatter" + lefthand_file = 'icons/mob/inhands/weapons/melee_lefthand.dmi' + righthand_file = 'icons/mob/inhands/weapons/melee_righthand.dmi' + force = 1 + throwforce = 1 + attack_verb = list("swatted", "smacked") + hitsound = 'sound/effects/snap.ogg' + w_class = WEIGHT_CLASS_SMALL + //Things in this list will be instantly splatted. Flyman weakness is handled in the flyman species weakness proc. + var/list/strong_against + +/obj/item/melee/flyswatter/Initialize() + . = ..() + strong_against = typecacheof(list( + /mob/living/simple_animal/hostile/poison/bees/, + /mob/living/simple_animal/butterfly, + /mob/living/simple_animal/cockroach, + /obj/item/queen_bee + )) + + +/obj/item/melee/flyswatter/afterattack(atom/target, mob/user, proximity_flag) + if(proximity_flag) + if(is_type_in_typecache(target, strong_against)) + new /obj/effect/decal/cleanable/deadcockroach(get_turf(target)) + to_chat(user, "You easily splat the [target].") + if(istype(target, /mob/living/)) + var/mob/living/bug = target + bug.death(1) + else + qdel(target) + +/obj/item/circlegame + name = "circled hand" + desc = "If somebody looks at this while it's below your waist, you get to bop them." + icon_state = "madeyoulook" + force = 0 + throwforce = 0 + flags_1 = DROPDEL_1 | ABSTRACT_1 + attack_verb = list("bopped") + +/obj/item/proc/can_trigger_gun(mob/living/user) + if(!user.can_use_guns(src)) + return FALSE +>>>>>>> 129a7b9... Fixes brains counting towards highlander killstreaks (#30396) return TRUE From 3f025582f285a0e5a39c48d9a0c8762aa3ecaa0b Mon Sep 17 00:00:00 2001 From: Kyle Spier-Swenson Date: Thu, 7 Sep 2017 08:01:26 -0700 Subject: [PATCH 07/74] Gives admins the ability to show a read only vv window to a player --- code/datums/datumvars.dm | 506 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 506 insertions(+) diff --git a/code/datums/datumvars.dm b/code/datums/datumvars.dm index 87c6ad7334..cb9be25f05 100644 --- a/code/datums/datumvars.dm +++ b/code/datums/datumvars.dm @@ -22,6 +22,7 @@ //please call . = ..() first and append to the result, that way parent items are always at the top and child items are further down //add separaters by doing . += "---" +<<<<<<< HEAD /datum/proc/vv_get_dropdown() . = list() . += "---" @@ -485,6 +486,472 @@ if(!check_rights(0)) return +======= +/datum/proc/vv_get_dropdown() + . = list() + . += "---" + .["Call Proc"] = "?_src_=vars;proc_call=\ref[src]" + .["Mark Object"] = "?_src_=vars;mark_object=\ref[src]" + .["Delete"] = "?_src_=vars;delete=\ref[src]" + .["Show VV To Player"] = "?_src_=vars;expose=\ref[src]" + + +/datum/proc/on_reagent_change() + return + + +/client/proc/debug_variables(datum/D in world) + set category = "Debug" + set name = "View Variables" + //set src in world + var/static/cookieoffset = rand(1, 9999) //to force cookies to reset after the round. + + if(!usr.client || !usr.client.holder) //The usr vs src abuse in this proc is intentional and must not be changed + to_chat(usr, "You need to be an administrator to access this.") + return + + if(!D) + return + + var/islist = islist(D) + if (!islist && !istype(D)) + return + + var/title = "" + var/refid = "\ref[D]" + var/icon/sprite + var/hash + + var/type = /list + if (!islist) + type = D.type + + + + if(istype(D, /atom)) + var/atom/AT = D + if(AT.icon && AT.icon_state) + sprite = new /icon(AT.icon, AT.icon_state) + hash = md5(AT.icon) + hash = md5(hash + AT.icon_state) + src << browse_rsc(sprite, "vv[hash].png") + + title = "[D] (\ref[D]) = [type]" + + var/sprite_text + if(sprite) + sprite_text = "" + var/list/atomsnowflake = list() + + if(istype(D, /atom)) + var/atom/A = D + if(isliving(A)) + atomsnowflake += "[D]" + if(A.dir) + atomsnowflake += "
<< [dir2text(A.dir)] >>" + var/mob/living/M = A + atomsnowflake += {" +
[M.ckey ? M.ckey : "No ckey"] / [M.real_name ? M.real_name : "No real name"] +
+ BRUTE:[M.getBruteLoss()] + FIRE:[M.getFireLoss()] + TOXIN:[M.getToxLoss()] + OXY:[M.getOxyLoss()] + CLONE:[M.getCloneLoss()] + BRAIN:[M.getBrainLoss()] + STAMINA:[M.getStaminaLoss()] + + "} + else + atomsnowflake += "[D]" + if(A.dir) + atomsnowflake += "
<< [dir2text(A.dir)] >>" + else + atomsnowflake += "[D]" + + var/formatted_type = "[type]" + if(length(formatted_type) > 25) + var/middle_point = length(formatted_type) / 2 + var/splitpoint = findtext(formatted_type,"/",middle_point) + if(splitpoint) + formatted_type = "[copytext(formatted_type,1,splitpoint)]
[copytext(formatted_type,splitpoint)]" + else + formatted_type = "Type too long" //No suitable splitpoint (/) found. + + var/marked + if(holder && holder.marked_datum && holder.marked_datum == D) + marked = "
Marked Object" + var/varedited_line = "" + if(!islist && D.var_edited) + varedited_line = "
Var Edited" + + var/list/dropdownoptions = list() + if (islist) + dropdownoptions = list( + "---", + "Add Item" = "?_src_=vars;listadd=[refid]", + "Remove Nulls" = "?_src_=vars;listnulls=[refid]", + "Remove Dupes" = "?_src_=vars;listdupes=[refid]", + "Set len" = "?_src_=vars;listlen=[refid]", + "Shuffle" = "?_src_=vars;listshuffle=[refid]", + "Show VV To Player" = "?_src_=vars;expose=[refid]" + ) + else + dropdownoptions = D.vv_get_dropdown() + var/list/dropdownoptions_html = list() + + for (var/name in dropdownoptions) + var/link = dropdownoptions[name] + if (link) + dropdownoptions_html += "" + else + dropdownoptions_html += "" + + var/list/names = list() + if (!islist) + for (var/V in D.vars) + names += V + sleep(1)//For some reason, without this sleep, VVing will cause client to disconnect on certain objects. + + var/list/variable_html = list() + if (islist) + var/list/L = D + for (var/i in 1 to L.len) + var/key = L[i] + var/value + if (IS_NORMAL_LIST(L) && !isnum(key)) + value = L[key] + variable_html += debug_variable(i, value, 0, D) + else + + names = sortList(names) + for (var/V in names) + if(D.can_vv_get(V)) + variable_html += D.vv_get_var(V) + + var/html = {" + + + [title] + + + + +
+ + + + + +
+ + + + +
+ [sprite_text] +
+ [atomsnowflake.Join()] +
+
+
+ [formatted_type] + [marked] + [varedited_line] +
+
+
+ Refresh +
+ +
+
+
+
+
+ + E - Edit, tries to determine the variable type by itself.
+ C - Change, asks you for the var type first.
+ M - Mass modify: changes this variable for all objects of this type.
+
+
+ + + + + +
+
+ Search: +
+
+ +
+
+
    + [variable_html.Join()] +
+ + + +"} + src << browse(html, "window=variables[refid];size=475x650") + + +#define VV_HTML_ENCODE(thing) ( sanitize ? html_encode(thing) : thing ) +/proc/debug_variable(name, value, level, datum/DA = null, sanitize = TRUE) + var/header + if(DA) + if (islist(DA)) + var/index = name + if (value) + name = DA[name] //name is really the index until this line + else + value = DA[name] + header = "
  • (E) (C) (-) " + else + header = "
  • (E) (C) (M) " + else + header = "
  • " + + var/item + if (isnull(value)) + item = "[VV_HTML_ENCODE(name)] = null" + + else if (istext(value)) + item = "[VV_HTML_ENCODE(name)] = \"[VV_HTML_ENCODE(value)]\"" + + else if (isicon(value)) + #ifdef VARSICON + var/icon/I = new/icon(value) + var/rnd = rand(1,10000) + var/rname = "tmp\ref[I][rnd].png" + usr << browse_rsc(I, rname) + item = "[VV_HTML_ENCODE(name)] = ([value]) " + #else + item = "[VV_HTML_ENCODE(name)] = /icon ([value])" + #endif + +/* else if (istype(value, /image)) + #ifdef VARSICON + var/rnd = rand(1, 10000) + var/image/I = value + + src << browse_rsc(I.icon, "tmp\ref[value][rnd].png") + html += "[name] = " + #else + html += "[name] = /image ([value])" + #endif +*/ + else if (isfile(value)) + item = "[VV_HTML_ENCODE(name)] = '[value]'" + + //else if (istype(value, /client)) + // var/client/C = value + // item = "[VV_HTML_ENCODE(name)] \ref[value] = [C] [C.type]" + + else if (istype(value, /datum)) + var/datum/D = value + if ("[D]" != "[D.type]") //if the thing as a name var, lets use it. + item = "[VV_HTML_ENCODE(name)] \ref[value] = [D] [D.type]" + else + item = "[VV_HTML_ENCODE(name)] \ref[value] = [D.type]" + + else if (islist(value)) + var/list/L = value + var/list/items = list() + + if (L.len > 0 && !(name == "underlays" || name == "overlays" || L.len > (IS_NORMAL_LIST(L) ? 50 : 150))) + for (var/i in 1 to L.len) + var/key = L[i] + var/val + if (IS_NORMAL_LIST(L) && !isnum(key)) + val = L[key] + if (!val) + val = key + key = i + + items += debug_variable(key, val, level + 1, sanitize = sanitize) + + item = "[VV_HTML_ENCODE(name)] = /list ([L.len])
      [items.Join()]
    " + else + item = "[VV_HTML_ENCODE(name)] = /list ([L.len])" + + else + item = "[VV_HTML_ENCODE(name)] = [VV_HTML_ENCODE(value)]" + + return "[header][item]
  • " + +#undef VV_HTML_ENCODE + +/client/proc/view_var_Topic(href, href_list, hsrc) + if( (usr.client != src) || !src.holder ) + return + if(href_list["Vars"]) + debug_variables(locate(href_list["Vars"])) + + else if(href_list["datumrefresh"]) + var/datum/DAT = locate(href_list["datumrefresh"]) + if(!DAT) //can't be an istype() because /client etc aren't datums + return + src.debug_variables(DAT) + + else if(href_list["mob_player_panel"]) + if(!check_rights(0)) + return + +>>>>>>> 6656ce6... Gives admins the ability to show a read only vv window to a player (#30463) var/mob/M = locate(href_list["mob_player_panel"]) in GLOB.mob_list if(!istype(M)) to_chat(usr, "This can only be used on instances of type /mob") @@ -541,6 +1008,7 @@ return var/mob/M = locate(href_list["regenerateicons"]) in GLOB.mob_list +<<<<<<< HEAD if(!ismob(M)) to_chat(usr, "This can only be done to instances of type /mob") return @@ -557,6 +1025,44 @@ if(!check_rights(0)) return +======= + if(!ismob(M)) + to_chat(usr, "This can only be done to instances of type /mob") + return + M.regenerate_icons() + else if(href_list["expose"]) + if(!check_rights(R_ADMIN, FALSE)) + return + var/thing = locate(href_list["expose"]) + if (!thing) + return + var/value = vv_get_value(VV_CLIENT) + if (value["class"] != VV_CLIENT) + return + var/client/C = value["value"] + if (!C) + return + var/prompt = alert("Do you want to grant [C] access to view this VV window? (they will not be able to edit or change anything nor open nested vv windows unless they themselves are an admin)", "Confirm", "Yes", "No") + if (prompt != "Yes" || !usr.client) + return + message_admins("[key_name_admin(usr)] Showed [key_name_admin(C)] a VV window") + log_admin("Admin [key_name(usr)] Showed [key_name(C)] a VV window of a [thing]") + to_chat(C, "[usr.client.holder.fakekey ? "an Administrator" : "[usr.client.key]"] has granted you access to view a View Variables window") + C.debug_variables(thing) + + +//Needs +VAREDIT past this point + + else if(check_rights(R_VAREDIT)) + + + //~CARN: for renaming mobs (updates their name, real_name, mind.name, their ID/PDA and datacore records). + + if(href_list["rename"]) + if(!check_rights(0)) + return + +>>>>>>> 6656ce6... Gives admins the ability to show a read only vv window to a player (#30463) var/mob/M = locate(href_list["rename"]) in GLOB.mob_list if(!istype(M)) to_chat(usr, "This can only be used on instances of type /mob") From c2c69d359f1255e1869d9a9b69bc8633cee9dd38 Mon Sep 17 00:00:00 2001 From: AnturK Date: Wed, 6 Sep 2017 10:44:38 +0200 Subject: [PATCH 08/74] Fixes shuttle name on ramming. --- code/modules/shuttle/on_move.dm | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/code/modules/shuttle/on_move.dm b/code/modules/shuttle/on_move.dm index 59a0a46ae8..e80b690737 100644 --- a/code/modules/shuttle/on_move.dm +++ b/code/modules/shuttle/on_move.dm @@ -14,7 +14,12 @@ All ShuttleMove procs go here // Called from the new turf before anything has been moved // Only gets called if fromShuttleMove returns true first // returns the new move_mode (based on the old) +<<<<<<< HEAD /turf/proc/toShuttleMove(turf/oldT, shuttle_dir, move_mode) +======= +/turf/proc/toShuttleMove(turf/oldT, move_mode, obj/docking_port/mobile/shuttle) + var/shuttle_dir = shuttle.dir +>>>>>>> 9ac60a8... Typo for(var/i in contents) var/atom/movable/thing = i if(ismob(thing)) From cf07ead653fbc0cfd3b3195e69b133e0c17185b6 Mon Sep 17 00:00:00 2001 From: kingofkosmos Date: Fri, 8 Sep 2017 17:57:51 +0300 Subject: [PATCH 10/74] Regularizes resisting out of containers --- .../abduction/machinery/experiment.dm | 22 +- code/game/machinery/cloning.dm | 3 + code/game/machinery/dna_scanner.dm | 24 +- code/game/machinery/gulag_teleporter.dm | 23 +- code/game/machinery/suit_storage_unit.dm | 278 ++++++++++++++++++ .../objects/items/implants/implantchair.dm | 191 ++++++++++++ .../structures/crates_lockers/closets.dm | 25 +- code/game/objects/structures/morgue.dm | 26 +- .../transit_tubes/transit_tube_pod.dm | 3 + code/modules/VR/vr_sleeper.dm | 4 + .../components/unary_devices/cryo.dm | 27 +- .../kitchen_machinery/gibber.dm | 5 +- 12 files changed, 567 insertions(+), 64 deletions(-) diff --git a/code/game/gamemodes/miniantags/abduction/machinery/experiment.dm b/code/game/gamemodes/miniantags/abduction/machinery/experiment.dm index 58ca8bbea9..182b7e2756 100644 --- a/code/game/gamemodes/miniantags/abduction/machinery/experiment.dm +++ b/code/game/gamemodes/miniantags/abduction/machinery/experiment.dm @@ -12,6 +12,8 @@ var/list/abductee_minds var/flash = " - || - " var/obj/machinery/abductor/console/console + var/message_cooldown = 0 + var/breakout_time = 0.75 /obj/machinery/abductor/experiment/MouseDrop_T(mob/target, mob/user) if(user.stat || user.lying || !Adjacent(user) || !target.Adjacent(user) || !ishuman(target)) @@ -40,25 +42,23 @@ /obj/machinery/abductor/experiment/relaymove(mob/user) if(user.stat != CONSCIOUS) return - container_resist(user) + if(message_cooldown <= world.time) + message_cooldown = world.time + 50 + to_chat(user, "[src]'s door won't budge!") /obj/machinery/abductor/experiment/container_resist(mob/living/user) - var/breakout_time = 600 user.changeNext_move(CLICK_CD_BREAKOUT) user.last_special = world.time + CLICK_CD_BREAKOUT - to_chat(user, "You lean on the back of [src] and start pushing the door open... (this will take about a minute.)") - user.visible_message("You hear a metallic creaking from [src]!") - - if(do_after(user,(breakout_time), target = src)) + user.visible_message("You see [user] kicking against the door of [src]!", \ + "You lean on the back of [src] and start pushing the door open... (this will take about [(breakout_time<1) ? "[breakout_time*60] seconds" : "[breakout_time] minute\s"].)", \ + "You hear a metallic creaking from [src].") + if(do_after(user,(breakout_time*60*10), target = src)) //minutes * 60seconds * 10deciseconds if(!user || user.stat != CONSCIOUS || user.loc != src || state_open) return - - visible_message("[user] successfully broke out of [src]!") - to_chat(user, "You successfully break out of [src]!") - + user.visible_message("[user] successfully broke out of [src]!", \ + "You successfully break out of [src]!") open_machine() - /obj/machinery/abductor/experiment/proc/dissection_icon(mob/living/carbon/human/H) var/icon/photo = null var/g = (H.gender == FEMALE) ? "f" : "m" diff --git a/code/game/machinery/cloning.dm b/code/game/machinery/cloning.dm index 7ea954a671..2276b5154b 100644 --- a/code/game/machinery/cloning.dm +++ b/code/game/machinery/cloning.dm @@ -392,6 +392,9 @@ QDEL_IN(mob_occupant, 40) /obj/machinery/clonepod/relaymove(mob/user) + container_resist() + +/obj/machinery/clonepod/container_resist(mob/living/user) if(user.stat == CONSCIOUS) go_out() diff --git a/code/game/machinery/dna_scanner.dm b/code/game/machinery/dna_scanner.dm index 65a6088721..4085b4edb4 100644 --- a/code/game/machinery/dna_scanner.dm +++ b/code/game/machinery/dna_scanner.dm @@ -14,6 +14,8 @@ var/damage_coeff var/scan_level var/precision_coeff + var/message_cooldown + var/breakout_time = 2 /obj/machinery/dna_scannernew/RefreshParts() scan_level = 0 @@ -65,23 +67,20 @@ open_machine() /obj/machinery/dna_scannernew/container_resist(mob/living/user) - var/breakout_time = 2 - if(state_open || !locked) //Open and unlocked, no need to escape - state_open = TRUE + if(!locked) + open_machine() return user.changeNext_move(CLICK_CD_BREAKOUT) user.last_special = world.time + CLICK_CD_BREAKOUT - to_chat(user, "You lean on the back of [src] and start pushing the door open... (this will take about [breakout_time] minutes.)") - user.visible_message("You hear a metallic creaking from [src]!") - + user.visible_message("You see [user] kicking against the door of [src]!", \ + "You lean on the back of [src] and start pushing the door open... (this will take about [(breakout_time<1) ? "[breakout_time*60] seconds" : "[breakout_time] minute\s"].)", \ + "You hear a metallic creaking from [src].") if(do_after(user,(breakout_time*60*10), target = src)) //minutes * 60seconds * 10deciseconds if(!user || user.stat != CONSCIOUS || user.loc != src || state_open || !locked) return - locked = FALSE - visible_message("[user] successfully broke out of [src]!") - to_chat(user, "You successfully break out of [src]!") - + user.visible_message("[user] successfully broke out of [src]!", \ + "You successfully break out of [src]!") open_machine() /obj/machinery/dna_scannernew/proc/locate_computer(type_) @@ -122,10 +121,11 @@ /obj/machinery/dna_scannernew/relaymove(mob/user as mob) if(user.stat || locked) + if(message_cooldown <= world.time) + message_cooldown = world.time + 50 + to_chat(user, "[src]'s door won't budge!") return - open_machine() - return /obj/machinery/dna_scannernew/attackby(obj/item/I, mob/user, params) diff --git a/code/game/machinery/gulag_teleporter.dm b/code/game/machinery/gulag_teleporter.dm index b37c5a10a7..d77e91af90 100644 --- a/code/game/machinery/gulag_teleporter.dm +++ b/code/game/machinery/gulag_teleporter.dm @@ -19,6 +19,8 @@ The console is located at computer/gulag_teleporter.dm active_power_usage = 5000 circuit = /obj/item/circuitboard/machine/gulag_teleporter var/locked = FALSE + var/message_cooldown + var/breakout_time = 1 var/jumpsuit_type = /obj/item/clothing/under/rank/prisoner var/shoes_type = /obj/item/clothing/shoes/sneakers/orange var/obj/machinery/gulag_item_reclaimer/linked_reclaimer @@ -46,7 +48,7 @@ The console is located at computer/gulag_teleporter.dm /obj/machinery/gulag_teleporter/interact(mob/user) if(locked) - to_chat(user, "[src] is locked.") + to_chat(user, "[src] is locked!") return toggle_open() @@ -89,28 +91,27 @@ The console is located at computer/gulag_teleporter.dm if(user.stat != CONSCIOUS) return if(locked) - to_chat(user, "[src] is locked!") + if(message_cooldown <= world.time) + message_cooldown = world.time + 50 + to_chat(user, "[src]'s door won't budge!") return open_machine() /obj/machinery/gulag_teleporter/container_resist(mob/living/user) - var/breakout_time = 600 if(!locked) open_machine() return user.changeNext_move(CLICK_CD_BREAKOUT) user.last_special = world.time + CLICK_CD_BREAKOUT - to_chat(user, "You lean on the back of [src] and start pushing the door open... (this will take about a minute.)") - user.visible_message("You hear a metallic creaking from [src]!") - - if(do_after(user,(breakout_time), target = src)) + user.visible_message("You see [user] kicking against the door of [src]!", \ + "You lean on the back of [src] and start pushing the door open... (this will take about [(breakout_time<1) ? "[breakout_time*60] seconds" : "[breakout_time] minute\s"].)", \ + "You hear a metallic creaking from [src].") + if(do_after(user,(breakout_time*60*10), target = src)) //minutes * 60seconds * 10deciseconds if(!user || user.stat != CONSCIOUS || user.loc != src || state_open || !locked) return - locked = FALSE - visible_message("[user] successfully broke out of [src]!") - to_chat(user, "You successfully break out of [src]!") - + user.visible_message("[user] successfully broke out of [src]!", \ + "You successfully break out of [src]!") open_machine() /obj/machinery/gulag_teleporter/proc/locate_reclaimer() diff --git a/code/game/machinery/suit_storage_unit.dm b/code/game/machinery/suit_storage_unit.dm index cd2a5bd3b5..6ab0cbf17b 100644 --- a/code/game/machinery/suit_storage_unit.dm +++ b/code/game/machinery/suit_storage_unit.dm @@ -6,6 +6,7 @@ icon_state = "close" anchored = TRUE density = TRUE +<<<<<<< HEAD max_integrity = 250 var/obj/item/clothing/suit/space/suit = null @@ -101,6 +102,105 @@ mask_type = /obj/item/clothing/mask/breath storage_type = /obj/item/tank/internals/emergency_oxygen/double +======= + max_integrity = 250 + + var/obj/item/clothing/suit/space/suit = null + var/obj/item/clothing/head/helmet/space/helmet = null + var/obj/item/clothing/mask/mask = null + var/obj/item/storage = null + + var/suit_type = null + var/helmet_type = null + var/mask_type = null + var/storage_type = null + + state_open = FALSE + var/locked = FALSE + panel_open = FALSE + var/safeties = TRUE + + var/uv = FALSE + var/uv_super = FALSE + var/uv_cycles = 6 + var/message_cooldown + var/breakout_time = 0.5 + +/obj/machinery/suit_storage_unit/standard_unit + suit_type = /obj/item/clothing/suit/space/eva + helmet_type = /obj/item/clothing/head/helmet/space/eva + mask_type = /obj/item/clothing/mask/breath + +/obj/machinery/suit_storage_unit/captain + suit_type = /obj/item/clothing/suit/space/hardsuit/captain + mask_type = /obj/item/clothing/mask/gas/sechailer + storage_type = /obj/item/tank/jetpack/oxygen/captain + +/obj/machinery/suit_storage_unit/engine + suit_type = /obj/item/clothing/suit/space/hardsuit/engine + mask_type = /obj/item/clothing/mask/breath + +/obj/machinery/suit_storage_unit/ce + suit_type = /obj/item/clothing/suit/space/hardsuit/engine/elite + mask_type = /obj/item/clothing/mask/breath + storage_type= /obj/item/clothing/shoes/magboots/advance + +/obj/machinery/suit_storage_unit/security + suit_type = /obj/item/clothing/suit/space/hardsuit/security + mask_type = /obj/item/clothing/mask/gas/sechailer + +/obj/machinery/suit_storage_unit/hos + suit_type = /obj/item/clothing/suit/space/hardsuit/security/hos + mask_type = /obj/item/clothing/mask/gas/sechailer + storage_type = /obj/item/tank/internals/oxygen + +/obj/machinery/suit_storage_unit/atmos + suit_type = /obj/item/clothing/suit/space/hardsuit/engine/atmos + mask_type = /obj/item/clothing/mask/gas + storage_type = /obj/item/watertank/atmos + +/obj/machinery/suit_storage_unit/mining + suit_type = /obj/item/clothing/suit/hooded/explorer + mask_type = /obj/item/clothing/mask/gas/explorer + +/obj/machinery/suit_storage_unit/mining/eva + suit_type = /obj/item/clothing/suit/space/hardsuit/mining + mask_type = /obj/item/clothing/mask/breath + +/obj/machinery/suit_storage_unit/cmo + suit_type = /obj/item/clothing/suit/space/hardsuit/medical + mask_type = /obj/item/clothing/mask/breath + +/obj/machinery/suit_storage_unit/rd + suit_type = /obj/item/clothing/suit/space/hardsuit/rd + mask_type = /obj/item/clothing/mask/breath + +/obj/machinery/suit_storage_unit/syndicate + suit_type = /obj/item/clothing/suit/space/hardsuit/syndi + mask_type = /obj/item/clothing/mask/gas/syndicate + storage_type = /obj/item/tank/jetpack/oxygen/harness + +/obj/machinery/suit_storage_unit/ert/command + suit_type = /obj/item/clothing/suit/space/hardsuit/ert + mask_type = /obj/item/clothing/mask/breath + storage_type = /obj/item/tank/internals/emergency_oxygen/double + +/obj/machinery/suit_storage_unit/ert/security + suit_type = /obj/item/clothing/suit/space/hardsuit/ert/sec + mask_type = /obj/item/clothing/mask/breath + storage_type = /obj/item/tank/internals/emergency_oxygen/double + +/obj/machinery/suit_storage_unit/ert/engineer + suit_type = /obj/item/clothing/suit/space/hardsuit/ert/engi + mask_type = /obj/item/clothing/mask/breath + storage_type = /obj/item/tank/internals/emergency_oxygen/double + +/obj/machinery/suit_storage_unit/ert/medical + suit_type = /obj/item/clothing/suit/space/hardsuit/ert/med + mask_type = /obj/item/clothing/mask/breath + storage_type = /obj/item/tank/internals/emergency_oxygen/double + +>>>>>>> d4d898f... Regularizes resisting out of containers (#30412) /obj/machinery/suit_storage_unit/Initialize() . = ..() wires = new /datum/wires/suit_storage_unit(src) @@ -162,6 +262,7 @@ /obj/machinery/suit_storage_unit/deconstruct(disassembled = TRUE) if(!(flags_1 & NODECONSTRUCT_1)) +<<<<<<< HEAD open_machine() dump_contents() new /obj/item/stack/sheet/metal (loc, 2) @@ -312,6 +413,183 @@ return ..() +======= + open_machine() + dump_contents() + new /obj/item/stack/sheet/metal (loc, 2) + qdel(src) + +/obj/machinery/suit_storage_unit/MouseDrop_T(atom/A, mob/user) + if(user.stat || user.lying || !Adjacent(user) || !Adjacent(A) || !isliving(A)) + return + var/mob/living/target = A + if(!state_open) + to_chat(user, "The unit's doors are shut!") + return + if(!is_operational()) + to_chat(user, "The unit is not operational!") + return + if(occupant || helmet || suit || storage) + to_chat(user, "It's too cluttered inside to fit in!") + return + + if(target == user) + user.visible_message("[user] starts squeezing into [src]!", "You start working your way into [src]...") + else + target.visible_message("[user] starts shoving [target] into [src]!", "[user] starts shoving you into [src]!") + + if(do_mob(user, target, 30)) + if(occupant || helmet || suit || storage) + return + if(target == user) + user.visible_message("[user] slips into [src] and closes the door behind them!", "You slip into [src]'s cramped space and shut its door.") + else + target.visible_message("[user] pushes [target] into [src] and shuts its door!", "[user] shoves you into [src] and shuts the door!") + close_machine(target) + add_fingerprint(user) + +/obj/machinery/suit_storage_unit/proc/cook() + if(uv_cycles) + uv_cycles-- + uv = TRUE + locked = TRUE + update_icon() + if(occupant) + var/mob/living/mob_occupant = occupant + if(uv_super) + mob_occupant.adjustFireLoss(rand(20, 36)) + else + mob_occupant.adjustFireLoss(rand(10, 16)) + mob_occupant.emote("scream") + addtimer(CALLBACK(src, .proc/cook), 50) + else + uv_cycles = initial(uv_cycles) + uv = FALSE + locked = FALSE + if(uv_super) + visible_message("[src]'s door creaks open with a loud whining noise. A cloud of foul black smoke escapes from its chamber.") + playsound(src, 'sound/machines/airlock_alien_prying.ogg', 50, 1) + helmet = null + qdel(helmet) + suit = null + qdel(suit) // Delete everything but the occupant. + mask = null + qdel(mask) + storage = null + qdel(storage) + // The wires get damaged too. + wires.cut_all() + else + if(!occupant) + visible_message("[src]'s door slides open. The glowing yellow lights dim to a gentle green.") + else + visible_message("[src]'s door slides open, barraging you with the nauseating smell of charred flesh.") + playsound(src, 'sound/machines/airlockclose.ogg', 25, 1) + for(var/obj/item/I in src) //Scorches away blood and forensic evidence, although the SSU itself is unaffected + I.clean_blood() + I.fingerprints = list() + open_machine(FALSE) + if(occupant) + dump_contents() + +/obj/machinery/suit_storage_unit/proc/shock(mob/user, prb) + if(!prob(prb)) + var/datum/effect_system/spark_spread/s = new /datum/effect_system/spark_spread + s.set_up(5, 1, src) + s.start() + if(electrocute_mob(user, src, src, 1, TRUE)) + return 1 + +/obj/machinery/suit_storage_unit/relaymove(mob/user) + if(locked) + if(message_cooldown <= world.time) + message_cooldown = world.time + 50 + to_chat(user, "[src]'s door won't budge!") + return + open_machine() + dump_contents() + +/obj/machinery/suit_storage_unit/container_resist(mob/living/user) + if(!locked) + open_machine() + dump_contents() + return + user.changeNext_move(CLICK_CD_BREAKOUT) + user.last_special = world.time + CLICK_CD_BREAKOUT + user.visible_message("You see [user] kicking against the doors of [src]!", \ + "You start kicking against the doors... (this will take about [(breakout_time<1) ? "[breakout_time*60] seconds" : "[breakout_time] minute\s"].)", \ + "You hear a thump from [src].") + if(do_after(user,(breakout_time*60*10), target = src)) //minutes * 60seconds * 10deciseconds + if(!user || user.stat != CONSCIOUS || user.loc != src ) + return + user.visible_message("[user] successfully broke out of [src]!", \ + "You successfully break out of [src]!") + open_machine() + dump_contents() + + add_fingerprint(user) + if(locked) + visible_message("You see [user] kicking against the doors of [src]!", \ + "You start kicking against the doors...") + addtimer(CALLBACK(src, .proc/resist_open, user), 300) + else + open_machine() + dump_contents() + +/obj/machinery/suit_storage_unit/proc/resist_open(mob/user) + if(!state_open && occupant && (user in src) && user.stat == 0) // Check they're still here. + visible_message("You see [user] bursts out of [src]!", \ + "You escape the cramped confines of [src]!") + open_machine() + +/obj/machinery/suit_storage_unit/attackby(obj/item/I, mob/user, params) + if(state_open && is_operational()) + if(istype(I, /obj/item/clothing/suit/space)) + if(suit) + to_chat(user, "The unit already contains a suit!.") + return + if(!user.drop_item()) + return + suit = I + else if(istype(I, /obj/item/clothing/head/helmet)) + if(helmet) + to_chat(user, "The unit already contains a helmet!") + return + if(!user.drop_item()) + return + helmet = I + else if(istype(I, /obj/item/clothing/mask)) + if(mask) + to_chat(user, "The unit already contains a mask!") + return + if(!user.drop_item()) + return + mask = I + else + if(storage) + to_chat(user, "The auxiliary storage compartment is full!") + return + if(!user.drop_item()) + return + storage = I + + I.loc = src + visible_message("[user] inserts [I] into [src]", "You load [I] into [src].") + update_icon() + return + + if(panel_open && is_wire_tool(I)) + wires.interact(user) + if(!state_open) + if(default_deconstruction_screwdriver(user, "panel", "close", I)) + return + if(default_pry_open(I)) + dump_contents() + return + + return ..() + +>>>>>>> d4d898f... Regularizes resisting out of containers (#30412) /obj/machinery/suit_storage_unit/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = FALSE, \ datum/tgui/master_ui = null, datum/ui_state/state = GLOB.notcontained_state) ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open) diff --git a/code/game/objects/items/implants/implantchair.dm b/code/game/objects/items/implants/implantchair.dm index 55a35960cf..c7035f748e 100644 --- a/code/game/objects/items/implants/implantchair.dm +++ b/code/game/objects/items/implants/implantchair.dm @@ -1,3 +1,4 @@ +<<<<<<< HEAD /obj/machinery/implantchair name = "mindshield implanter" desc = "Used to implant occupants with mindshield implants." @@ -185,3 +186,193 @@ log_game("[key_name_admin(user)] brainwashed [key_name_admin(C)] with objective '[objective]'.") return 1 +======= +/obj/machinery/implantchair + name = "mindshield implanter" + desc = "Used to implant occupants with mindshield implants." + icon = 'icons/obj/machines/implantchair.dmi' + icon_state = "implantchair" + density = TRUE + opacity = 0 + anchored = TRUE + + var/ready = TRUE + var/replenishing = FALSE + + var/ready_implants = 5 + var/max_implants = 5 + var/injection_cooldown = 600 + var/replenish_cooldown = 6000 + var/implant_type = /obj/item/implant/mindshield + var/auto_inject = FALSE + var/auto_replenish = TRUE + var/special = FALSE + var/special_name = "special function" + var/message_cooldown + var/breakout_time = 1 + +/obj/machinery/implantchair/Initialize() + . = ..() + open_machine() + update_icon() + + +/obj/machinery/implantchair/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = FALSE, datum/tgui/master_ui = null, datum/ui_state/state = GLOB.notcontained_state) + ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open) + if(!ui) + ui = new(user, src, ui_key, "implantchair", name, 375, 280, master_ui, state) + ui.open() + + +/obj/machinery/implantchair/ui_data() + var/list/data = list() + data["occupied"] = occupant ? 1 : 0 + data["open"] = state_open + + data["occupant"] = list() + if(occupant) + var/mob/living/mob_occupant = occupant + data["occupant"]["name"] = mob_occupant.name + data["occupant"]["stat"] = mob_occupant.stat + + data["special_name"] = special ? special_name : null + data["ready_implants"] = ready_implants + data["ready"] = ready + data["replenishing"] = replenishing + + return data + +/obj/machinery/implantchair/ui_act(action, params) + if(..()) + return + switch(action) + if("door") + if(state_open) + close_machine() + else + open_machine() + . = TRUE + if("implant") + implant(occupant,usr) + . = TRUE + +/obj/machinery/implantchair/proc/implant(mob/living/M,mob/user) + if (!istype(M)) + return + if(!ready_implants || !ready) + return + if(implant_action(M,user)) + ready_implants-- + if(!replenishing && auto_replenish) + replenishing = TRUE + addtimer(CALLBACK(src,"replenish"),replenish_cooldown) + if(injection_cooldown > 0) + ready = FALSE + addtimer(CALLBACK(src,"set_ready"),injection_cooldown) + else + playsound(get_turf(src), 'sound/machines/buzz-sigh.ogg', 25, 1) + update_icon() + +/obj/machinery/implantchair/proc/implant_action(mob/living/M) + var/obj/item/implant/I = new implant_type + if(I.implant(M)) + visible_message("[M] has been implanted by the [name].") + return 1 + +/obj/machinery/implantchair/update_icon() + icon_state = initial(icon_state) + if(state_open) + icon_state += "_open" + if(occupant) + icon_state += "_occupied" + if(ready) + add_overlay("ready") + else + cut_overlays() + +/obj/machinery/implantchair/proc/replenish() + if(ready_implants < max_implants) + ready_implants++ + if(ready_implants < max_implants) + addtimer(CALLBACK(src,"replenish"),replenish_cooldown) + else + replenishing = FALSE + +/obj/machinery/implantchair/proc/set_ready() + ready = TRUE + update_icon() + +/obj/machinery/implantchair/container_resist(mob/living/user) + user.changeNext_move(CLICK_CD_BREAKOUT) + user.last_special = world.time + CLICK_CD_BREAKOUT + user.visible_message("You see [user] kicking against the door of [src]!", \ + "You lean on the back of [src] and start pushing the door open... (this will take about [(breakout_time<1) ? "[breakout_time*60] seconds" : "[breakout_time] minute\s"].)", \ + "You hear a metallic creaking from [src].") + if(do_after(user,(breakout_time*60*10), target = src)) //minutes * 60seconds * 10deciseconds + if(!user || user.stat != CONSCIOUS || user.loc != src || state_open) + return + user.visible_message("[user] successfully broke out of [src]!", \ + "You successfully break out of [src]!") + open_machine() + +/obj/machinery/implantchair/relaymove(mob/user) + if(message_cooldown <= world.time) + message_cooldown = world.time + 50 + to_chat(user, "[src]'s door won't budge!") + +/obj/machinery/implantchair/MouseDrop_T(mob/target, mob/user) + if(user.stat || user.lying || !Adjacent(user) || !user.Adjacent(target) || !isliving(target) || !user.IsAdvancedToolUser()) + return + close_machine(target) + +/obj/machinery/implantchair/close_machine(mob/living/user) + if((isnull(user) || istype(user)) && state_open) + ..(user) + if(auto_inject && ready && ready_implants > 0) + implant(user,null) + +/obj/machinery/implantchair/genepurge + name = "Genetic purifier" + desc = "Used to purge human genome of foreign influences" + special = TRUE + special_name = "Purge genome" + injection_cooldown = 0 + replenish_cooldown = 300 + +/obj/machinery/implantchair/genepurge/implant_action(mob/living/carbon/human/H,mob/user) + if(!istype(H)) + return 0 + H.set_species(/datum/species/human, 1)//lizards go home + purrbation_remove(H)//remove cats + H.dna.remove_all_mutations()//hulks out + return 1 + + +/obj/machinery/implantchair/brainwash + name = "Neural Imprinter" + desc = "Used to indoctrinate rehabilitate hardened recidivists." + special_name = "Imprint" + injection_cooldown = 3000 + auto_inject = FALSE + auto_replenish = FALSE + special = TRUE + var/objective = "Obey the law. Praise Nanotrasen." + var/custom = FALSE + +/obj/machinery/implantchair/brainwash/implant_action(mob/living/C,mob/user) + if(!istype(C) || !C.mind) // I don't know how this makes any sense for silicons but laws trump objectives anyway. + return 0 + if(custom) + if(!user || !user.Adjacent(src)) + return 0 + objective = stripped_input(usr,"What order do you want to imprint on [C]?","Enter the order","",120) + message_admins("[key_name_admin(user)] set brainwash machine objective to '[objective]'.") + log_game("[key_name_admin(user)] set brainwash machine objective to '[objective]'.") + var/datum/objective/custom_objective = new/datum/objective(objective) + custom_objective.owner = C.mind + C.mind.objectives += custom_objective + C.mind.announce_objectives() + message_admins("[key_name_admin(user)] brainwashed [key_name_admin(C)] with objective '[objective]'.") + log_game("[key_name_admin(user)] brainwashed [key_name_admin(C)] with objective '[objective]'.") + return 1 +>>>>>>> d4d898f... Regularizes resisting out of containers (#30412) diff --git a/code/game/objects/structures/crates_lockers/closets.dm b/code/game/objects/structures/crates_lockers/closets.dm index 78e672e49d..4f8705aa71 100644 --- a/code/game/objects/structures/crates_lockers/closets.dm +++ b/code/game/objects/structures/crates_lockers/closets.dm @@ -16,7 +16,7 @@ integrity_failure = 50 armor = list(melee = 20, bullet = 10, laser = 10, energy = 0, bomb = 10, bio = 0, rad = 0, fire = 70, acid = 60) var/breakout_time = 2 - var/lastbang + var/message_cooldown var/can_weld_shut = TRUE var/horizontal = FALSE var/allow_objects = FALSE @@ -300,14 +300,12 @@ /obj/structure/closet/relaymove(mob/user) if(user.stat || !isturf(loc) || !isliving(user)) return - var/mob/living/L = user - if(!open()) - if(L.last_special <= world.time) - container_resist(L) - if(world.time > lastbang+5) - lastbang = world.time - for(var/mob/M in get_hearers_in_view(src, null)) - M.show_message("BANG, bang!", 2) + if(locked) + if(message_cooldown <= world.time) + message_cooldown = world.time + 50 + to_chat(user, "[src]'s door won't budge!") + return + container_resist() /obj/structure/closet/attack_hand(mob/user) ..() @@ -367,9 +365,10 @@ //okay, so the closet is either welded or locked... resist!!! user.changeNext_move(CLICK_CD_BREAKOUT) user.last_special = world.time + CLICK_CD_BREAKOUT - to_chat(user, "You lean on the back of [src] and start pushing the door open.") - visible_message("[src] begins to shake violently!") - if(do_after(user,(breakout_time * 60 * 10), target = src)) //minutes * 60seconds * 10deciseconds + user.visible_message("[src] begins to shake violently!", \ + "You lean on the back of [src] and start pushing the door open... (this will take about [(breakout_time<1) ? "[breakout_time*60] seconds" : "[breakout_time] minute\s"].)", \ + "You hear banging from [src].") + if(do_after(user,(breakout_time*60*10), target = src)) //minutes * 60seconds * 10deciseconds if(!user || user.stat != CONSCIOUS || user.loc != src || opened || (!locked && !welded) ) return //we check after a while whether there is a point of resisting anymore and whether the user is capable of resisting @@ -388,7 +387,7 @@ /obj/structure/closet/AltClick(mob/user) ..() - if(!user.canUseTopic(src, be_close=TRUE)) + if(!user.canUseTopic(src, be_close=TRUE) || isturf(loc)) to_chat(user, "You can't do that right now!") return if(opened || !secure) diff --git a/code/game/objects/structures/morgue.dm b/code/game/objects/structures/morgue.dm index 600e15201d..f4a98811c0 100644 --- a/code/game/objects/structures/morgue.dm +++ b/code/game/objects/structures/morgue.dm @@ -23,6 +23,8 @@ var/obj/structure/tray/connected = null var/locked = FALSE var/opendir = SOUTH + var/message_cooldown + var/breakout_time = 1 /obj/structure/bodycontainer/Destroy() open() @@ -41,6 +43,11 @@ /obj/structure/bodycontainer/relaymove(mob/user) if(user.stat || !isturf(loc)) return + if(locked) + if(message_cooldown <= world.time) + message_cooldown = world.time + 50 + to_chat(user, "[src]'s door won't budge!") + return open() /obj/structure/bodycontainer/attack_paw(mob/user) @@ -84,11 +91,20 @@ qdel(src) /obj/structure/bodycontainer/container_resist(mob/living/user) - open() - -/obj/structure/bodycontainer/relay_container_resist(mob/living/user, obj/O) - to_chat(user, "You slam yourself into the side of [O].") - container_resist(user) + if(!locked) + open() + return + user.changeNext_move(CLICK_CD_BREAKOUT) + user.last_special = world.time + CLICK_CD_BREAKOUT + user.visible_message(null, \ + "You lean on the back of [src] and start pushing the tray open... (this will take about [(breakout_time<1) ? "[breakout_time*60] seconds" : "[breakout_time] minute\s"].)", \ + "You hear a metallic creaking from [src].") + if(do_after(user,(breakout_time*60*10), target = src)) //minutes * 60seconds * 10deciseconds + if(!user || user.stat != CONSCIOUS || user.loc != src ) + return + user.visible_message("[user] successfully broke out of [src]!", \ + "You successfully break out of [src]!") + open() /obj/structure/bodycontainer/proc/open() playsound(src.loc, 'sound/items/deconstruct.ogg', 50, 1) diff --git a/code/game/objects/structures/transit_tubes/transit_tube_pod.dm b/code/game/objects/structures/transit_tubes/transit_tube_pod.dm index 89f02b13af..fcd9ead2a7 100644 --- a/code/game/objects/structures/transit_tubes/transit_tube_pod.dm +++ b/code/game/objects/structures/transit_tubes/transit_tube_pod.dm @@ -66,6 +66,9 @@ deconstruct(FALSE) /obj/structure/transit_tube_pod/container_resist(mob/living/user) + if(!user.incapacitated()) + empty_pod() + return if(!moving) user.changeNext_move(CLICK_CD_BREAKOUT) user.last_special = world.time + CLICK_CD_BREAKOUT diff --git a/code/modules/VR/vr_sleeper.dm b/code/modules/VR/vr_sleeper.dm index a83ced850e..f447b2f3e9 100644 --- a/code/modules/VR/vr_sleeper.dm +++ b/code/modules/VR/vr_sleeper.dm @@ -49,6 +49,10 @@ open_machine() +/obj/machinery/vr_sleeper/container_resist(mob/living/user) + open_machine() + + /obj/machinery/vr_sleeper/Destroy() open_machine() cleanup_vr_human() diff --git a/code/modules/atmospherics/machinery/components/unary_devices/cryo.dm b/code/modules/atmospherics/machinery/components/unary_devices/cryo.dm index f0f41e375a..89e6538b07 100644 --- a/code/modules/atmospherics/machinery/components/unary_devices/cryo.dm +++ b/code/modules/atmospherics/machinery/components/unary_devices/cryo.dm @@ -32,6 +32,8 @@ var/running_bob_anim = FALSE var/escape_in_progress = FALSE + var/message_cooldown + var/breakout_time = 0.5 /obj/machinery/atmospherics/components/unary/cryo_cell/Initialize() . = ..() @@ -219,7 +221,9 @@ update_icon() /obj/machinery/atmospherics/components/unary/cryo_cell/relaymove(mob/user) - container_resist(user) + if(message_cooldown <= world.time) + message_cooldown = world.time + 50 + to_chat(user, "[src]'s door won't budge!") /obj/machinery/atmospherics/components/unary/cryo_cell/open_machine(drop = 0) if(!state_open && !panel_open) @@ -239,16 +243,17 @@ return occupant /obj/machinery/atmospherics/components/unary/cryo_cell/container_resist(mob/living/user) - if(escape_in_progress) - to_chat(user, "You are already trying to exit (This will take around 30 seconds)") - return - escape_in_progress = TRUE - to_chat(user, "You struggle inside the cryotube, kicking the release with your foot... (This will take around 30 seconds.)") - audible_message("You hear a thump from [src].") - if(do_after(user, 300)) - if(occupant == user) // Check they're still here. - open_machine() - escape_in_progress = FALSE + user.changeNext_move(CLICK_CD_BREAKOUT) + user.last_special = world.time + CLICK_CD_BREAKOUT + user.visible_message("You see [user] kicking against the glass of [src]!", \ + "You struggle inside [src], kicking the release with your foot... (this will take about [(breakout_time<1) ? "[breakout_time*60] seconds" : "[breakout_time] minute\s"].)", \ + "You hear a thump from [src].") + if(do_after(user,(breakout_time*60*10), target = src)) //minutes * 60seconds * 10deciseconds + if(!user || user.stat != CONSCIOUS || user.loc != src ) + return + user.visible_message("[user] successfully broke out of [src]!", \ + "You successfully break out of [src]!") + open_machine() /obj/machinery/atmospherics/components/unary/cryo_cell/examine(mob/user) ..() diff --git a/code/modules/food_and_drinks/kitchen_machinery/gibber.dm b/code/modules/food_and_drinks/kitchen_machinery/gibber.dm index d9f70160a4..978e8af62d 100644 --- a/code/modules/food_and_drinks/kitchen_machinery/gibber.dm +++ b/code/modules/food_and_drinks/kitchen_machinery/gibber.dm @@ -51,6 +51,9 @@ /obj/machinery/gibber/container_resist(mob/living/user) go_out() +/obj/machinery/gibber/relaymove(mob/living/user) + go_out() + /obj/machinery/gibber/attack_hand(mob/user) if(stat & (NOPOWER|BROKEN)) return @@ -225,4 +228,4 @@ if(M.loc == input_plate) M.forceMove(src) - M.gib() \ No newline at end of file + M.gib() From 0dfe72d77ed5a9a5d37c23736c88ab3d255753f0 Mon Sep 17 00:00:00 2001 From: Armhulen Date: Fri, 8 Sep 2017 08:00:34 -0700 Subject: [PATCH 11/74] chainsaws rebalance, but working this time :) --- code/game/objects/items/twohanded.dm | 2 +- code/game/objects/items/weaponry.dm | 569 +++++++++++++++++++++++++++ code/modules/crafting/recipes.dm | 4 +- 3 files changed, 572 insertions(+), 3 deletions(-) diff --git a/code/game/objects/items/twohanded.dm b/code/game/objects/items/twohanded.dm index 323527fc88..6c19b49073 100644 --- a/code/game/objects/items/twohanded.dm +++ b/code/game/objects/items/twohanded.dm @@ -487,7 +487,7 @@ righthand_file = 'icons/mob/inhands/weapons/chainsaw_righthand.dmi' flags_1 = CONDUCT_1 force = 13 - var/force_on = 21 + var/force_on = 24 w_class = WEIGHT_CLASS_HUGE throwforce = 13 throw_speed = 2 diff --git a/code/game/objects/items/weaponry.dm b/code/game/objects/items/weaponry.dm index 13acf7e990..1c5a409dd3 100644 --- a/code/game/objects/items/weaponry.dm +++ b/code/game/objects/items/weaponry.dm @@ -23,6 +23,7 @@ else M.visible_message("[M] has been banned FOR NO REISIN by [user]", "You have been banned FOR NO REISIN by [user]", "you hear a banhammer banning someone") +<<<<<<< HEAD playsound(loc, 'sound/effects/adminhelp.ogg', 15) //keep it at 15% volume so people don't jump out of their skin too much /obj/item/sord @@ -589,4 +590,572 @@ /obj/item/proc/can_trigger_gun(mob/living/user) if(!user.can_use_guns(src)) return FALSE +======= + playsound(loc, 'sound/effects/adminhelp.ogg', 15) //keep it at 15% volume so people don't jump out of their skin too much + +/obj/item/sord + name = "\improper SORD" + desc = "This thing is so unspeakably shitty you are having a hard time even holding it." + icon_state = "sord" + item_state = "sord" + lefthand_file = 'icons/mob/inhands/weapons/swords_lefthand.dmi' + righthand_file = 'icons/mob/inhands/weapons/swords_righthand.dmi' + slot_flags = SLOT_BELT + force = 2 + throwforce = 1 + w_class = WEIGHT_CLASS_NORMAL + hitsound = 'sound/weapons/bladeslice.ogg' + attack_verb = list("attacked", "slashed", "stabbed", "sliced", "torn", "ripped", "diced", "cut") + +/obj/item/sord/suicide_act(mob/user) + user.visible_message("[user] is trying to impale [user.p_them()]self with [src]! It might be a suicide attempt if it weren't so shitty.", \ + "You try to impale yourself with [src], but it's USELESS...") + return SHAME + +/obj/item/claymore + name = "claymore" + desc = "What are you standing around staring at this for? Get to killing!" + icon_state = "claymore" + item_state = "claymore" + lefthand_file = 'icons/mob/inhands/weapons/swords_lefthand.dmi' + righthand_file = 'icons/mob/inhands/weapons/swords_righthand.dmi' + hitsound = 'sound/weapons/bladeslice.ogg' + flags_1 = CONDUCT_1 + slot_flags = SLOT_BELT | SLOT_BACK + force = 40 + throwforce = 10 + w_class = WEIGHT_CLASS_NORMAL + attack_verb = list("attacked", "slashed", "stabbed", "sliced", "torn", "ripped", "diced", "cut") + block_chance = 50 + sharpness = IS_SHARP + max_integrity = 200 + armor = list(melee = 0, bullet = 0, laser = 0, energy = 0, bomb = 0, bio = 0, rad = 0, fire = 100, acid = 50) + resistance_flags = FIRE_PROOF + +/obj/item/claymore/suicide_act(mob/user) + user.visible_message("[user] is falling on [src]! It looks like [user.p_theyre()] trying to commit suicide!") + return(BRUTELOSS) + +/obj/item/claymore/highlander //ALL COMMENTS MADE REGARDING THIS SWORD MUST BE MADE IN ALL CAPS + desc = "THERE CAN BE ONLY ONE, AND IT WILL BE YOU!!!\nActivate it in your hand to point to the nearest victim." + flags_1 = CONDUCT_1 | NODROP_1 | DROPDEL_1 + slot_flags = null + block_chance = 0 //RNG WON'T HELP YOU NOW, PANSY + luminosity = 3 + attack_verb = list("brutalized", "eviscerated", "disemboweled", "hacked", "carved", "cleaved") //ONLY THE MOST VISCERAL ATTACK VERBS + var/notches = 0 //HOW MANY PEOPLE HAVE BEEN SLAIN WITH THIS BLADE + var/obj/item/disk/nuclear/nuke_disk //OUR STORED NUKE DISK + +/obj/item/claymore/highlander/Initialize() + . = ..() + START_PROCESSING(SSobj, src) + +/obj/item/claymore/highlander/Destroy() + if(nuke_disk) + nuke_disk.forceMove(get_turf(src)) + nuke_disk.visible_message("The nuke disk is vulnerable!") + nuke_disk = null + STOP_PROCESSING(SSobj, src) + return ..() + +/obj/item/claymore/highlander/process() + if(ishuman(loc)) + var/mob/living/carbon/human/H = loc + loc.layer = LARGE_MOB_LAYER //NO HIDING BEHIND PLANTS FOR YOU, DICKWEED (HA GET IT, BECAUSE WEEDS ARE PLANTS) + H.bleedsuppress = TRUE //AND WE WON'T BLEED OUT LIKE COWARDS + else + if(!admin_spawned) + qdel(src) + + +/obj/item/claymore/highlander/pickup(mob/living/user) + to_chat(user, "The power of Scotland protects you! You are shielded from all stuns and knockdowns.") + user.add_stun_absorption("highlander", INFINITY, 1, " is protected by the power of Scotland!", "The power of Scotland absorbs the stun!", " is protected by the power of Scotland!") + user.status_flags += IGNORESLOWDOWN + +/obj/item/claymore/highlander/dropped(mob/living/user) + user.status_flags -= IGNORESLOWDOWN + qdel(src) //If this ever happens, it's because you lost an arm + +/obj/item/claymore/highlander/examine(mob/user) + ..() + to_chat(user, "It has [!notches ? "nothing" : "[notches] notches"] scratched into the blade.") + if(nuke_disk) + to_chat(user, "It's holding the nuke disk!") + +/obj/item/claymore/highlander/attack(mob/living/target, mob/living/user) + . = ..() + if(!QDELETED(target) && iscarbon(target) && target.stat == DEAD && target.mind && target.mind.special_role == "highlander") + user.fully_heal() //STEAL THE LIFE OF OUR FALLEN FOES + add_notch(user) + target.visible_message("[target] crumbles to dust beneath [user]'s blows!", "As you fall, your body crumbles to dust!") + target.dust() + +/obj/item/claymore/highlander/attack_self(mob/living/user) + var/closest_victim + var/closest_distance = 255 + for(var/mob/living/carbon/human/H in GLOB.player_list - user) + if(H.client && H.mind.special_role == "highlander" && (!closest_victim || get_dist(user, closest_victim) < closest_distance)) + closest_victim = H + if(!closest_victim) + to_chat(user, "[src] thrums for a moment and falls dark. Perhaps there's nobody nearby.") + return + to_chat(user, "[src] thrums and points to the [dir2text(get_dir(user, closest_victim))].") + +/obj/item/claymore/highlander/IsReflect() + return 1 //YOU THINK YOUR PUNY LASERS CAN STOP ME? + +/obj/item/claymore/highlander/proc/add_notch(mob/living/user) //DYNAMIC CLAYMORE PROGRESSION SYSTEM - THIS IS THE FUTURE + notches++ + force++ + var/new_name = name + switch(notches) + if(1) + to_chat(user, "Your first kill - hopefully one of many. You scratch a notch into [src]'s blade.") + to_chat(user, "You feel your fallen foe's soul entering your blade, restoring your wounds!") + new_name = "notched claymore" + if(2) + to_chat(user, "Another falls before you. Another soul fuses with your own. Another notch in the blade.") + new_name = "double-notched claymore" + add_atom_colour(rgb(255, 235, 235), ADMIN_COLOUR_PRIORITY) + if(3) + to_chat(user, "You're beginning to relish the thrill of battle.") + new_name = "triple-notched claymore" + add_atom_colour(rgb(255, 215, 215), ADMIN_COLOUR_PRIORITY) + if(4) + to_chat(user, "You've lost count of how many you've killed.") + new_name = "many-notched claymore" + add_atom_colour(rgb(255, 195, 195), ADMIN_COLOUR_PRIORITY) + if(5) + to_chat(user, "Five voices now echo in your mind, cheering the slaughter.") + new_name = "battle-tested claymore" + add_atom_colour(rgb(255, 175, 175), ADMIN_COLOUR_PRIORITY) + if(6) + to_chat(user, "Is this what the vikings felt like? Visions of glory fill your head as you slay your sixth foe.") + new_name = "battle-scarred claymore" + add_atom_colour(rgb(255, 155, 155), ADMIN_COLOUR_PRIORITY) + if(7) + to_chat(user, "Kill. Butcher. Conquer.") + new_name = "vicious claymore" + add_atom_colour(rgb(255, 135, 135), ADMIN_COLOUR_PRIORITY) + if(8) + to_chat(user, "IT NEVER GETS OLD. THE SCREAMING. THE BLOOD AS IT SPRAYS ACROSS YOUR FACE.") + new_name = "bloodthirsty claymore" + add_atom_colour(rgb(255, 115, 115), ADMIN_COLOUR_PRIORITY) + if(9) + to_chat(user, "ANOTHER ONE FALLS TO YOUR BLOWS. ANOTHER WEAKLING UNFIT TO LIVE.") + new_name = "gore-stained claymore" + add_atom_colour(rgb(255, 95, 95), ADMIN_COLOUR_PRIORITY) + if(10) + user.visible_message("[user]'s eyes light up with a vengeful fire!", \ + "YOU FEEL THE POWER OF VALHALLA FLOWING THROUGH YOU! THERE CAN BE ONLY ONE!!!") + user.update_icons() + new_name = "GORE-DRENCHED CLAYMORE OF [pick("THE WHIMSICAL SLAUGHTER", "A THOUSAND SLAUGHTERED CATTLE", "GLORY AND VALHALLA", "ANNIHILATION", "OBLITERATION")]" + icon_state = "claymore_valhalla" + item_state = "cultblade" + remove_atom_colour(ADMIN_COLOUR_PRIORITY) + + name = new_name + playsound(user, 'sound/items/screwdriver2.ogg', 50, 1) + +/obj/item/katana + name = "katana" + desc = "Woefully underpowered in D20" + icon_state = "katana" + item_state = "katana" + lefthand_file = 'icons/mob/inhands/weapons/swords_lefthand.dmi' + righthand_file = 'icons/mob/inhands/weapons/swords_righthand.dmi' + flags_1 = CONDUCT_1 + slot_flags = SLOT_BELT | SLOT_BACK + force = 40 + throwforce = 10 + w_class = WEIGHT_CLASS_NORMAL + hitsound = 'sound/weapons/bladeslice.ogg' + attack_verb = list("attacked", "slashed", "stabbed", "sliced", "torn", "ripped", "diced", "cut") + block_chance = 50 + sharpness = IS_SHARP + max_integrity = 200 + armor = list(melee = 0, bullet = 0, laser = 0, energy = 0, bomb = 0, bio = 0, rad = 0, fire = 100, acid = 50) + resistance_flags = FIRE_PROOF + +/obj/item/katana/cursed + slot_flags = null + +/obj/item/katana/suicide_act(mob/user) + user.visible_message("[user] is slitting [user.p_their()] stomach open with [src]! It looks like [user.p_theyre()] trying to commit seppuku!") + return(BRUTELOSS) + +/obj/item/wirerod + name = "wired rod" + desc = "A rod with some wire wrapped around the top. It'd be easy to attach something to the top bit." + icon_state = "wiredrod" + item_state = "rods" + flags_1 = CONDUCT_1 + force = 9 + throwforce = 10 + w_class = WEIGHT_CLASS_NORMAL + materials = list(MAT_METAL=1150, MAT_GLASS=75) + attack_verb = list("hit", "bludgeoned", "whacked", "bonked") + +/obj/item/wirerod/attackby(obj/item/I, mob/user, params) + if(istype(I, /obj/item/shard)) + var/obj/item/twohanded/spear/S = new /obj/item/twohanded/spear + + remove_item_from_storage(user) + qdel(I) + qdel(src) + + user.put_in_hands(S) + to_chat(user, "You fasten the glass shard to the top of the rod with the cable.") + + else if(istype(I, /obj/item/device/assembly/igniter) && !(I.flags_1 & NODROP_1)) + var/obj/item/melee/baton/cattleprod/P = new /obj/item/melee/baton/cattleprod + + remove_item_from_storage(user) + + to_chat(user, "You fasten [I] to the top of the rod with the cable.") + + qdel(I) + qdel(src) + + user.put_in_hands(P) + else + return ..() + + +/obj/item/throwing_star + name = "throwing star" + desc = "An ancient weapon still used to this day due to it's ease of lodging itself into victim's body parts" + icon_state = "throwingstar" + item_state = "eshield0" + lefthand_file = 'icons/mob/inhands/equipment/shields_lefthand.dmi' + righthand_file = 'icons/mob/inhands/equipment/shields_righthand.dmi' + force = 2 + throwforce = 20 //This is never used on mobs since this has a 100% embed chance. + throw_speed = 4 + embedded_pain_multiplier = 4 + w_class = WEIGHT_CLASS_SMALL + embed_chance = 100 + embedded_fall_chance = 0 //Hahaha! + sharpness = IS_SHARP + materials = list(MAT_METAL=500, MAT_GLASS=500) + resistance_flags = FIRE_PROOF + + +/obj/item/switchblade + name = "switchblade" + icon_state = "switchblade" + lefthand_file = 'icons/mob/inhands/weapons/swords_lefthand.dmi' + righthand_file = 'icons/mob/inhands/weapons/swords_righthand.dmi' + desc = "A sharp, concealable, spring-loaded knife." + flags_1 = CONDUCT_1 + force = 3 + w_class = WEIGHT_CLASS_SMALL + throwforce = 5 + throw_speed = 3 + throw_range = 6 + materials = list(MAT_METAL=12000) + origin_tech = "engineering=3;combat=2" + hitsound = 'sound/weapons/genhit.ogg' + attack_verb = list("stubbed", "poked") + resistance_flags = FIRE_PROOF + var/extended = 0 + +/obj/item/switchblade/attack_self(mob/user) + extended = !extended + playsound(src.loc, 'sound/weapons/batonextend.ogg', 50, 1) + if(extended) + force = 20 + w_class = WEIGHT_CLASS_NORMAL + throwforce = 23 + icon_state = "switchblade_ext" + attack_verb = list("slashed", "stabbed", "sliced", "torn", "ripped", "diced", "cut") + hitsound = 'sound/weapons/bladeslice.ogg' + sharpness = IS_SHARP + else + force = 3 + w_class = WEIGHT_CLASS_SMALL + throwforce = 5 + icon_state = "switchblade" + attack_verb = list("stubbed", "poked") + hitsound = 'sound/weapons/genhit.ogg' + sharpness = IS_BLUNT + +/obj/item/switchblade/suicide_act(mob/user) + user.visible_message("[user] is slitting [user.p_their()] own throat with [src]! It looks like [user.p_theyre()] trying to commit suicide!") + return (BRUTELOSS) + +/obj/item/phone + name = "red phone" + desc = "Should anything ever go wrong..." + icon = 'icons/obj/items_and_weapons.dmi' + icon_state = "red_phone" + force = 3 + throwforce = 2 + throw_speed = 3 + throw_range = 4 + w_class = WEIGHT_CLASS_SMALL + attack_verb = list("called", "rang") + hitsound = 'sound/weapons/ring.ogg' + +/obj/item/phone/suicide_act(mob/user) + if(locate(/obj/structure/chair/stool) in user.loc) + user.visible_message("[user] begins to tie a noose with [src]'s cord! It looks like [user.p_theyre()] trying to commit suicide!") + else + user.visible_message("[user] is strangling [user.p_them()]self with [src]'s cord! It looks like [user.p_theyre()] trying to commit suicide!") + return(OXYLOSS) + +/obj/item/cane + name = "cane" + desc = "A cane used by a true gentleman. Or a clown." + icon = 'icons/obj/items_and_weapons.dmi' + icon_state = "cane" + item_state = "stick" + lefthand_file = 'icons/mob/inhands/weapons/melee_lefthand.dmi' + righthand_file = 'icons/mob/inhands/weapons/melee_righthand.dmi' + force = 5 + throwforce = 5 + w_class = WEIGHT_CLASS_SMALL + materials = list(MAT_METAL=50) + attack_verb = list("bludgeoned", "whacked", "disciplined", "thrashed") + +/obj/item/staff + name = "wizard staff" + desc = "Apparently a staff used by the wizard." + icon = 'icons/obj/wizard.dmi' + icon_state = "staff" + lefthand_file = 'icons/mob/inhands/weapons/staves_lefthand.dmi' + righthand_file = 'icons/mob/inhands/weapons/staves_righthand.dmi' + force = 3 + throwforce = 5 + throw_speed = 2 + throw_range = 5 + w_class = WEIGHT_CLASS_SMALL + armour_penetration = 100 + attack_verb = list("bludgeoned", "whacked", "disciplined") + resistance_flags = FLAMMABLE + +/obj/item/staff/broom + name = "broom" + desc = "Used for sweeping, and flying into the night while cackling. Black cat not included." + icon = 'icons/obj/wizard.dmi' + icon_state = "broom" + resistance_flags = FLAMMABLE + +/obj/item/staff/stick + name = "stick" + desc = "A great tool to drag someone else's drinks across the bar." + icon = 'icons/obj/items_and_weapons.dmi' + icon_state = "stick" + item_state = "stick" + lefthand_file = 'icons/mob/inhands/weapons/melee_lefthand.dmi' + righthand_file = 'icons/mob/inhands/weapons/melee_righthand.dmi' + force = 3 + throwforce = 5 + throw_speed = 2 + throw_range = 5 + w_class = WEIGHT_CLASS_SMALL + +/obj/item/ectoplasm + name = "ectoplasm" + desc = "spooky" + gender = PLURAL + icon = 'icons/obj/wizard.dmi' + icon_state = "ectoplasm" + +/obj/item/ectoplasm/suicide_act(mob/user) + user.visible_message("[user] is inhaling [src]! It looks like [user.p_theyre()] trying to visit the astral plane.") + return (OXYLOSS) + +/obj/item/mounted_chainsaw + name = "mounted chainsaw" + desc = "A chainsaw that has replaced your arm." + icon_state = "chainsaw_on" + item_state = "mounted_chainsaw" + lefthand_file = 'icons/mob/inhands/weapons/chainsaw_lefthand.dmi' + righthand_file = 'icons/mob/inhands/weapons/chainsaw_righthand.dmi' + flags_1 = NODROP_1 | ABSTRACT_1 | DROPDEL_1 + w_class = WEIGHT_CLASS_HUGE + force = 24 + throwforce = 0 + throw_range = 0 + throw_speed = 0 + sharpness = IS_SHARP + attack_verb = list("sawed", "torn", "cut", "chopped", "diced") + hitsound = 'sound/weapons/chainsawhit.ogg' + +/obj/item/mounted_chainsaw/Destroy() + var/obj/item/bodypart/part + new /obj/item/twohanded/required/chainsaw(get_turf(src)) + if(iscarbon(loc)) + var/mob/living/carbon/holder = loc + var/index = holder.get_held_index_of_item(src) + if(index) + part = holder.hand_bodyparts[index] + . = ..() + if(part) + part.drop_limb() + +/obj/item/statuebust + name = "bust" + desc = "A priceless ancient marble bust, the kind that belongs in a museum." //or you can hit people with it + icon = 'icons/obj/statue.dmi' + icon_state = "bust" + force = 15 + throwforce = 10 + throw_speed = 5 + throw_range = 2 + attack_verb = list("busted") + +/obj/item/tailclub + name = "tail club" + desc = "For the beating to death of lizards with their own tails." + icon_state = "tailclub" + force = 14 + throwforce = 1 // why are you throwing a club do you even weapon + throw_speed = 1 + throw_range = 1 + attack_verb = list("clubbed", "bludgeoned") + +/obj/item/melee/chainofcommand/tailwhip + name = "liz o' nine tails" + desc = "A whip fashioned from the severed tails of lizards." + icon_state = "tailwhip" + origin_tech = "engineering=3;combat=3;biotech=3" + needs_permit = 0 + +/obj/item/melee/chainofcommand/tailwhip/kitty + name = "cat o' nine tails" + desc = "A whip fashioned from the severed tails of cats." + icon_state = "catwhip" + +/obj/item/melee/skateboard + name = "skateboard" + desc = "A skateboard. It can be placed on its wheels and ridden, or used as a strong weapon." + icon_state = "skateboard" + item_state = "skateboard" + force = 12 + throwforce = 4 + w_class = WEIGHT_CLASS_HUGE + attack_verb = list("smacked", "whacked", "slammed", "smashed") + +/obj/item/melee/skateboard/attack_self(mob/user) + new /obj/vehicle/scooter/skateboard(get_turf(user)) + qdel(src) + +/obj/item/melee/baseball_bat + name = "baseball bat" + desc = "There ain't a skull in the league that can withstand a swatter." + icon = 'icons/obj/items_and_weapons.dmi' + icon_state = "baseball_bat" + item_state = "baseball_bat" + lefthand_file = 'icons/mob/inhands/weapons/melee_lefthand.dmi' + righthand_file = 'icons/mob/inhands/weapons/melee_righthand.dmi' + force = 10 + throwforce = 12 + attack_verb = list("beat", "smacked") + w_class = WEIGHT_CLASS_HUGE + var/homerun_ready = 0 + var/homerun_able = 0 + +/obj/item/melee/baseball_bat/homerun + name = "home run bat" + desc = "This thing looks dangerous... Dangerously good at baseball, that is." + homerun_able = 1 + +/obj/item/melee/baseball_bat/attack_self(mob/user) + if(!homerun_able) + ..() + return + if(homerun_ready) + to_chat(user, "You're already ready to do a home run!") + ..() + return + to_chat(user, "You begin gathering strength...") + playsound(get_turf(src), 'sound/magic/lightning_chargeup.ogg', 65, 1) + if(do_after(user, 90, target = src)) + to_chat(user, "You gather power! Time for a home run!") + homerun_ready = 1 + ..() + +/obj/item/melee/baseball_bat/attack(mob/living/target, mob/living/user) + . = ..() + var/atom/throw_target = get_edge_target_turf(target, user.dir) + if(homerun_ready) + user.visible_message("It's a home run!") + target.throw_at(throw_target, rand(8,10), 14, user) + target.ex_act(EXPLODE_HEAVY) + playsound(get_turf(src), 'sound/weapons/homerun.ogg', 100, 1) + homerun_ready = 0 + return + else if(!target.anchored) + target.throw_at(throw_target, rand(1,2), 7, user) + +/obj/item/melee/baseball_bat/ablative + name = "metal baseball bat" + desc = "This bat is made of highly reflective, highly armored material." + icon_state = "baseball_bat_metal" + item_state = "baseball_bat_metal" + force = 12 + throwforce = 15 + +/obj/item/melee/baseball_bat/ablative/IsReflect()//some day this will reflect thrown items instead of lasers + var/picksound = rand(1,2) + var/turf = get_turf(src) + if(picksound == 1) + playsound(turf, 'sound/weapons/effects/batreflect1.ogg', 50, 1) + if(picksound == 2) + playsound(turf, 'sound/weapons/effects/batreflect2.ogg', 50, 1) + return 1 + +/obj/item/melee/flyswatter + name = "flyswatter" + desc = "Useful for killing insects of all sizes." + icon = 'icons/obj/items_and_weapons.dmi' + icon_state = "flyswatter" + item_state = "flyswatter" + lefthand_file = 'icons/mob/inhands/weapons/melee_lefthand.dmi' + righthand_file = 'icons/mob/inhands/weapons/melee_righthand.dmi' + force = 1 + throwforce = 1 + attack_verb = list("swatted", "smacked") + hitsound = 'sound/effects/snap.ogg' + w_class = WEIGHT_CLASS_SMALL + //Things in this list will be instantly splatted. Flyman weakness is handled in the flyman species weakness proc. + var/list/strong_against + +/obj/item/melee/flyswatter/Initialize() + . = ..() + strong_against = typecacheof(list( + /mob/living/simple_animal/hostile/poison/bees/, + /mob/living/simple_animal/butterfly, + /mob/living/simple_animal/cockroach, + /obj/item/queen_bee + )) + + +/obj/item/melee/flyswatter/afterattack(atom/target, mob/user, proximity_flag) + if(proximity_flag) + if(is_type_in_typecache(target, strong_against)) + new /obj/effect/decal/cleanable/deadcockroach(get_turf(target)) + to_chat(user, "You easily splat the [target].") + if(istype(target, /mob/living/)) + var/mob/living/bug = target + bug.death(1) + else + qdel(target) + +/obj/item/circlegame + name = "circled hand" + desc = "If somebody looks at this while it's below your waist, you get to bop them." + icon_state = "madeyoulook" + force = 0 + throwforce = 0 + flags_1 = DROPDEL_1 | ABSTRACT_1 + attack_verb = list("bopped") + +/obj/item/proc/can_trigger_gun(mob/living/user) + if(!user.can_use_guns(src)) + return FALSE +>>>>>>> bcbc166... chainsaws rebalance, but working this time :) (#30399) return TRUE diff --git a/code/modules/crafting/recipes.dm b/code/modules/crafting/recipes.dm index 1f12e671ec..d3b53d3a41 100644 --- a/code/modules/crafting/recipes.dm +++ b/code/modules/crafting/recipes.dm @@ -308,8 +308,8 @@ name = "Chainsaw" result = /obj/item/twohanded/required/chainsaw reqs = list(/obj/item/circular_saw = 1, - /obj/item/stack/cable_coil = 1, - /obj/item/stack/sheet/plasteel = 1) + /obj/item/stack/cable_coil = 3, + /obj/item/stack/sheet/plasteel = 5) tools = list(/obj/item/weldingtool) time = 50 category = CAT_WEAPONRY From 33f36fd0de5d8dfa880ca0380f3f329ed5da6c9a Mon Sep 17 00:00:00 2001 From: ExcessiveUseOfCobblestone <11748095+ExcessiveUseOfCobblestone@users.noreply.github.com> Date: Fri, 8 Sep 2017 11:01:30 -0400 Subject: [PATCH 12/74] Adds Archaeology Component --- code/__DEFINES/components.dm | 11 ++- code/__DEFINES/is_helpers.dm | 2 + code/datums/components/archaeology.dm | 92 +++++++++++++++++++ code/game/atoms.dm | 5 +- .../mecha/equipment/tools/mining_tools.dm | 4 +- code/game/objects/items.dm | 3 +- code/game/objects/objs.dm | 1 + code/game/objects/structures/lattice.dm | 1 + .../structures/transit_tubes/transit_tube.dm | 1 + .../transit_tubes/transit_tube_pod.dm | 1 + code/game/objects/structures/window.dm | 1 + code/game/turfs/open.dm | 3 + code/game/turfs/simulated/floor.dm | 1 + code/game/turfs/simulated/floor/misc_floor.dm | 1 + .../turfs/simulated/floor/plating/asteroid.dm | 83 +++-------------- .../game/turfs/simulated/floor/reinf_floor.dm | 1 + code/game/turfs/simulated/wall/reinf_walls.dm | 1 + code/game/turfs/simulated/walls.dm | 1 + .../atmospherics/machinery/atmosmachinery.dm | 1 + .../atmospherics/machinery/other/meter.dm | 1 + code/modules/mob/living/carbon/human/human.dm | 2 +- code/modules/mob/living/living.dm | 1 + code/modules/power/cable.dm | 1 + code/modules/recycling/disposal-structures.dm | 1 + code/modules/recycling/disposal-unit.dm | 1 + tgstation.dme | 1 + 26 files changed, 146 insertions(+), 76 deletions(-) create mode 100644 code/datums/components/archaeology.dm diff --git a/code/__DEFINES/components.dm b/code/__DEFINES/components.dm index 0225dad669..37af346a88 100644 --- a/code/__DEFINES/components.dm +++ b/code/__DEFINES/components.dm @@ -5,7 +5,7 @@ // How multiple components of the exact same type are handled in the same datum #define COMPONENT_DUPE_HIGHLANDER 0 //old component is deleted (default) -#define COMPONENT_DUPE_ALLOWED 1 //duplicates allowed +#define COMPONENT_DUPE_ALLOWED 1 //duplicates allowed #define COMPONENT_DUPE_UNIQUE 2 //new component is deleted // All signals. Format: @@ -14,5 +14,14 @@ #define COMSIG_COMPONENT_ADDED "component_added" //when a component is added to a datum: (datum/component) #define COMSIG_COMPONENT_REMOVING "component_removing" //before a component is removed from a datum because of RemoveComponent: (datum/component) #define COMSIG_PARENT_QDELETED "parent_qdeleted" //before a datum's Destroy() is called: () +<<<<<<< HEAD #define COMSIG_ATOM_ENTERED "atom_entered" //from base of atom/Entered(): (atom/movable, atom) #define COMSIG_MOVABLE_CROSSED "movable_crossed" //from base of atom/movable/Crossed(): (atom/movable) +======= +#define COMSIG_PARENT_ATTACKBY "atom_attackby" //from the base of atom/attackby: (obj/item, mob/living, params) +#define COMSIG_PARENT_EXAMINE "atom_examine" //from the base of atom/examine: (mob) +#define COMSIG_ATOM_ENTERED "atom_entered" //from base of atom/Entered(): (atom/movable, atom) +#define COMSIG_ATOM_EX_ACT "atom_ex_act" //from base of atom/ex_act(): (severity, target) +#define COMSIG_ATOM_SING_PULL "atom_sing_pull" //from base of atom/singularity_pull(): (S, current_size) +#define COMSIG_MOVABLE_CROSSED "movable_crossed" //from base of atom/movable/Crossed(): (atom/movable) +>>>>>>> 1e17bb7... Adds Archaeology Component (#30220) diff --git a/code/__DEFINES/is_helpers.dm b/code/__DEFINES/is_helpers.dm index 16b2a8f4fb..2c18e51f01 100644 --- a/code/__DEFINES/is_helpers.dm +++ b/code/__DEFINES/is_helpers.dm @@ -25,6 +25,8 @@ #define islava(A) (istype(A, /turf/open/lava)) +#define isplatingturf(A) (istype(A, /turf/open/floor/plating)) + //Mobs #define isliving(A) (istype(A, /mob/living)) diff --git a/code/datums/components/archaeology.dm b/code/datums/components/archaeology.dm new file mode 100644 index 0000000000..22a6b24bc4 --- /dev/null +++ b/code/datums/components/archaeology.dm @@ -0,0 +1,92 @@ +/datum/component/archaeology + dupe_type = COMPONENT_DUPE_UNIQUE + var/list/archdrops + var/prob2drop + var/dug + +/datum/component/archaeology/Initialize(_prob2drop, list/_archdrops = list()) + prob2drop = Clamp(_prob2drop, 0, 100) + archdrops = _archdrops + RegisterSignal(COMSIG_PARENT_ATTACKBY,.proc/Dig) + RegisterSignal(COMSIG_ATOM_EX_ACT, .proc/BombDig) + RegisterSignal(COMSIG_ATOM_SING_PULL, .proc/SingDig) + +/datum/component/archaeology/InheritComponent(datum/component/archaeology/A, i_am_original) + var/list/other_archdrops = A.archdrops + var/list/_archdrops = archdrops + for(var/I in other_archdrops) + _archdrops[I] += other_archdrops[I] + +/datum/component/archaeology/proc/Dig(mob/user, obj/item/W) + if(dug) + to_chat(user, "Looks like someone has dug here already.") + return FALSE + else + var/digging_speed + if (istype(W, /obj/item/shovel)) + var/obj/item/shovel/S = W + digging_speed = S.digspeed + else if (istype(W, /obj/item/pickaxe)) + var/obj/item/pickaxe/P = W + digging_speed = P.digspeed + + if (digging_speed && isturf(user.loc)) + to_chat(user, "You start digging...") + playsound(parent, 'sound/effects/shovel_dig.ogg', 50, 1) + + if(do_after(user, digging_speed, target = parent)) + to_chat(user, "You dig a hole.") + gets_dug() + dug = TRUE + SSblackbox.add_details("pick_used_mining",W.type) + return TRUE + return FALSE + +/datum/component/archaeology/proc/gets_dug() + if(dug) + return + else + var/turf/open/OT = get_turf(parent) + for(var/thing in archdrops) + var/maxtodrop = archdrops[thing] + for(var/i in 1 to maxtodrop) + if(prob(prob2drop)) // can't win them all! + new thing(OT) + + if(isopenturf(OT)) + if(OT.postdig_icon_change) + if(istype(OT, /turf/open/floor/plating/asteroid/) && !OT.postdig_icon) + var/turf/open/floor/plating/asteroid/AOT = parent + AOT.icon_plating = "[AOT.environment_type]_dug" + AOT.icon_state = "[AOT.environment_type]_dug" + else + if(isplatingturf(OT)) + var/turf/open/floor/plating/POT = parent + POT.icon_plating = "[POT.postdig_icon]" + OT.icon_state = "[OT.postdig_icon]" + + if(OT.slowdown) //Things like snow slow you down until you dig them. + OT.slowdown = 0 + dug = TRUE + +/datum/component/archaeology/proc/SingDig(S, current_size) + switch(current_size) + if(STAGE_THREE) + if(prob(30)) + gets_dug() + if(STAGE_FOUR) + if(prob(50)) + gets_dug() + else + if(current_size >= STAGE_FIVE && prob(70)) + gets_dug() + +/datum/component/archaeology/proc/BombDig(severity, target) + switch(severity) + if(3) + return + if(2) + if(prob(20)) + gets_dug() + if(1) + gets_dug() diff --git a/code/game/atoms.dm b/code/game/atoms.dm index 77bcefeddf..1e8ef4c5e2 100644 --- a/code/game/atoms.dm +++ b/code/game/atoms.dm @@ -304,6 +304,7 @@ /atom/proc/ex_act(severity, target) set waitfor = FALSE contents_explosion(severity, target) + SendSignal(COMSIG_ATOM_EX_ACT, severity, target) /atom/proc/blob_act(obj/structure/blob/B) return @@ -468,8 +469,8 @@ GLOBAL_LIST_EMPTY(blood_splatter_icons) /atom/proc/singularity_act() return -/atom/proc/singularity_pull() - return +/atom/proc/singularity_pull(obj/singularity/S, current_size) + SendSignal(COMSIG_ATOM_SING_PULL, S, current_size) /atom/proc/acid_act(acidpwr, acid_volume) return diff --git a/code/game/mecha/equipment/tools/mining_tools.dm b/code/game/mecha/equipment/tools/mining_tools.dm index 6d15716941..d0a1310e8e 100644 --- a/code/game/mecha/equipment/tools/mining_tools.dm +++ b/code/game/mecha/equipment/tools/mining_tools.dm @@ -58,7 +58,9 @@ /turf/open/floor/plating/asteroid/drill_act(obj/item/mecha_parts/mecha_equipment/drill/drill) for(var/turf/open/floor/plating/asteroid/M in range(1, drill.chassis)) if(get_dir(drill.chassis,M)&drill.chassis.dir) - M.gets_dug() + for(var/I in GetComponents(/datum/component/archaeology)) + var/datum/component/archaeology/archy = I + archy.gets_dug() drill.log_message("Drilled through [src]") drill.move_ores() diff --git a/code/game/objects/items.dm b/code/game/objects/items.dm index 96dcba36cf..f640e0f90b 100644 --- a/code/game/objects/items.dm +++ b/code/game/objects/items.dm @@ -549,9 +549,10 @@ GLOBAL_VAR_INIT(rpg_loot_items, FALSE) transfer_blood = 0 /obj/item/singularity_pull(S, current_size) + ..() if(current_size >= STAGE_FOUR) throw_at(S,14,3, spin=0) - else ..() + else return /obj/item/throw_impact(atom/A) if(A && !QDELETED(A)) diff --git a/code/game/objects/objs.dm b/code/game/objects/objs.dm index 1f3668f283..c8f105dfbe 100644 --- a/code/game/objects/objs.dm +++ b/code/game/objects/objs.dm @@ -169,6 +169,7 @@ return /obj/singularity_pull(S, current_size) + ..() if(!anchored || current_size >= STAGE_FIVE) step_towards(src,S) diff --git a/code/game/objects/structures/lattice.dm b/code/game/objects/structures/lattice.dm index 8a24b0271f..081cf186a3 100644 --- a/code/game/objects/structures/lattice.dm +++ b/code/game/objects/structures/lattice.dm @@ -45,6 +45,7 @@ qdel(src) /obj/structure/lattice/singularity_pull(S, current_size) + ..() if(current_size >= STAGE_FOUR) deconstruct() diff --git a/code/game/objects/structures/transit_tubes/transit_tube.dm b/code/game/objects/structures/transit_tubes/transit_tube.dm index 7b86cdffcc..10d883d392 100644 --- a/code/game/objects/structures/transit_tubes/transit_tube.dm +++ b/code/game/objects/structures/transit_tubes/transit_tube.dm @@ -30,6 +30,7 @@ return ..() /obj/structure/transit_tube/singularity_pull(S, current_size) + ..() if(current_size >= STAGE_FIVE) deconstruct(FALSE) diff --git a/code/game/objects/structures/transit_tubes/transit_tube_pod.dm b/code/game/objects/structures/transit_tubes/transit_tube_pod.dm index 89f02b13af..b885f980a2 100644 --- a/code/game/objects/structures/transit_tubes/transit_tube_pod.dm +++ b/code/game/objects/structures/transit_tubes/transit_tube_pod.dm @@ -62,6 +62,7 @@ AM.ex_act(severity, target) /obj/structure/transit_tube_pod/singularity_pull(S, current_size) + ..() if(current_size >= STAGE_FIVE) deconstruct(FALSE) diff --git a/code/game/objects/structures/window.dm b/code/game/objects/structures/window.dm index e70d5d3ddb..170a651315 100644 --- a/code/game/objects/structures/window.dm +++ b/code/game/objects/structures/window.dm @@ -105,6 +105,7 @@ qdel(src) /obj/structure/window/singularity_pull(S, current_size) + ..() if(current_size >= STAGE_FIVE) deconstruct(FALSE) diff --git a/code/game/turfs/open.dm b/code/game/turfs/open.dm index 2622a4e74c..f97f79068d 100644 --- a/code/game/turfs/open.dm +++ b/code/game/turfs/open.dm @@ -4,6 +4,9 @@ var/wet = 0 var/wet_time = 0 // Time in seconds that this floor will be wet for. var/mutable_appearance/wet_overlay + var/postdig_icon_change = FALSE + var/postdig_icon + var/list/archdrops /turf/open/indestructible name = "floor" diff --git a/code/game/turfs/simulated/floor.dm b/code/game/turfs/simulated/floor.dm index cfc834037d..df3d2aba86 100644 --- a/code/game/turfs/simulated/floor.dm +++ b/code/game/turfs/simulated/floor.dm @@ -170,6 +170,7 @@ return make_plating() /turf/open/floor/singularity_pull(S, current_size) + ..() if(current_size == STAGE_THREE) if(prob(30)) if(floor_tile) diff --git a/code/game/turfs/simulated/floor/misc_floor.dm b/code/game/turfs/simulated/floor/misc_floor.dm index f8d6c1da71..f2475cf997 100644 --- a/code/game/turfs/simulated/floor/misc_floor.dm +++ b/code/game/turfs/simulated/floor/misc_floor.dm @@ -269,6 +269,7 @@ narsie_act(force, ignore_mobs, probability) /turf/open/floor/vines/singularity_pull(S, current_size) + ..() if(current_size >= STAGE_FIVE) if(prob(50)) ChangeTurf(src.baseturf) diff --git a/code/game/turfs/simulated/floor/plating/asteroid.dm b/code/game/turfs/simulated/floor/plating/asteroid.dm index b24b758d73..c6dd8cb2eb 100644 --- a/code/game/turfs/simulated/floor/plating/asteroid.dm +++ b/code/game/turfs/simulated/floor/plating/asteroid.dm @@ -9,11 +9,11 @@ icon = 'icons/turf/floors.dmi' icon_state = "asteroid" icon_plating = "asteroid" + postdig_icon_change = TRUE var/environment_type = "asteroid" var/turf_type = /turf/open/floor/plating/asteroid //Because caves do whacky shit to revert to normal - var/dug = 0 //0 = has not yet been dug, 1 = has already been dug - var/sand_type = /obj/item/ore/glass var/floor_variance = 20 //probability floor has a different icon state + archdrops = list(/obj/item/ore/glass = 5) /turf/open/floor/plating/asteroid/Initialize() var/proper_name = name @@ -22,6 +22,9 @@ if(prob(floor_variance)) icon_state = "[environment_type][rand(0,12)]" + if(LAZYLEN(archdrops)) + AddComponent(/datum/component/archaeology, 100, archdrops) + /turf/open/floor/plating/asteroid/burn_tile() return @@ -31,46 +34,7 @@ /turf/open/floor/plating/asteroid/MakeDry(wet_setting = TURF_WET_WATER) return -/turf/open/floor/plating/asteroid/ex_act(severity, target) - contents_explosion(severity, target) - switch(severity) - if(3) - return - if(2) - if(prob(20)) - src.gets_dug() - if(1) - src.gets_dug() - /turf/open/floor/plating/asteroid/attackby(obj/item/W, mob/user, params) - //note that this proc does not call ..() - if(!W || !user) - return 0 - var/digging_speed = 0 - if (istype(W, /obj/item/shovel)) - var/obj/item/shovel/S = W - digging_speed = S.digspeed - else if (istype(W, /obj/item/pickaxe)) - var/obj/item/pickaxe/P = W - digging_speed = P.digspeed - if (digging_speed) - var/turf/T = user.loc - if(!isturf(T)) - return - - if (dug) - to_chat(user, "This area has already been dug!") - return - - to_chat(user, "You start digging...") - playsound(src, 'sound/effects/shovel_dig.ogg', 50, 1) - - if(do_after(user, digging_speed, target = src)) - if(istype(src, /turf/open/floor/plating/asteroid)) - to_chat(user, "You dig a hole.") - gets_dug() - SSblackbox.add_details("pick_used_mining","[W.type]") - if(istype(W, /obj/item/storage/bag/ore)) var/obj/item/storage/bag/ore/S = W if(S.collection_mode == 1) @@ -88,37 +52,16 @@ var/turf/open/floor/light/F = T F.state = L.state playsound(src, 'sound/weapons/genhit.ogg', 50, 1) - -/turf/open/floor/plating/asteroid/proc/gets_dug() - if(dug) return - for(var/i in 1 to 5) - new sand_type(src) - dug = 1 - icon_plating = "[environment_type]_dug" - icon_state = "[environment_type]_dug" - slowdown = 0 - return + + return ..() + /turf/open/floor/plating/asteroid/singularity_act() if(turf_z_is_planet(src)) return ..() ChangeTurf(/turf/open/space) -/turf/open/floor/plating/asteroid/singularity_pull(S, current_size) - if(dug) - return - switch(current_size) - if(STAGE_THREE) - if(!prob(30)) - gets_dug() - if(STAGE_FOUR) - if(prob(50)) - gets_dug() - else - if(current_size >= STAGE_FIVE && prob(70)) - gets_dug() - /turf/open/floor/plating/asteroid/basalt name = "volcanic floor" @@ -127,7 +70,7 @@ icon_state = "basalt" icon_plating = "basalt" environment_type = "basalt" - sand_type = /obj/item/ore/glass/basalt + archdrops = list(/obj/item/ore/glass/basalt = 5) floor_variance = 15 /turf/open/floor/plating/asteroid/basalt/lava //lava underneath @@ -147,10 +90,10 @@ if("basalt5", "basalt9") B.set_light(1.4, 0.6, LIGHT_COLOR_LAVA) //barely anything! -/turf/open/floor/plating/asteroid/basalt/gets_dug() - if(!dug) - set_light(0) +/turf/open/floor/plating/asteroid/basalt/ComponentActivated(datum/component/C) ..() + if(istype(C, /datum/component/archaeology)) + set_light(0) ///////Surface. The surface is warm, but survivable without a suit. Internals are required. The floors break to chasms, which drop you into the underground. @@ -340,8 +283,8 @@ initial_gas_mix = "TEMP=180" slowdown = 2 environment_type = "snow" - sand_type = /obj/item/stack/sheet/mineral/snow flags_1 = NONE + archdrops = list(/obj/item/stack/sheet/mineral/snow = 5) /turf/open/floor/plating/asteroid/snow/airless initial_gas_mix = "TEMP=2.7" diff --git a/code/game/turfs/simulated/floor/reinf_floor.dm b/code/game/turfs/simulated/floor/reinf_floor.dm index df353653d7..eaf0e512f7 100644 --- a/code/game/turfs/simulated/floor/reinf_floor.dm +++ b/code/game/turfs/simulated/floor/reinf_floor.dm @@ -58,6 +58,7 @@ make_plating(1) /turf/open/floor/engine/singularity_pull(S, current_size) + ..() if(current_size >= STAGE_FIVE) if(floor_tile) if(prob(30)) diff --git a/code/game/turfs/simulated/wall/reinf_walls.dm b/code/game/turfs/simulated/wall/reinf_walls.dm index 261e856629..5ebe1d632a 100644 --- a/code/game/turfs/simulated/wall/reinf_walls.dm +++ b/code/game/turfs/simulated/wall/reinf_walls.dm @@ -247,6 +247,7 @@ icon_state = "r_wall" /turf/closed/wall/r_wall/singularity_pull(S, current_size) + ..() if(current_size >= STAGE_FIVE) if(prob(30)) dismantle_wall() diff --git a/code/game/turfs/simulated/walls.dm b/code/game/turfs/simulated/walls.dm index 57774a5754..9171c7f54c 100644 --- a/code/game/turfs/simulated/walls.dm +++ b/code/game/turfs/simulated/walls.dm @@ -245,6 +245,7 @@ QDEL_IN(O, 50) /turf/closed/wall/singularity_pull(S, current_size) + ..() if(current_size >= STAGE_FIVE) if(prob(50)) dismantle_wall() diff --git a/code/modules/atmospherics/machinery/atmosmachinery.dm b/code/modules/atmospherics/machinery/atmosmachinery.dm index e22da2f1b1..977d48fbd7 100644 --- a/code/modules/atmospherics/machinery/atmosmachinery.dm +++ b/code/modules/atmospherics/machinery/atmosmachinery.dm @@ -222,6 +222,7 @@ Pipelines + Other Objects -> Pipe network build_network() /obj/machinery/atmospherics/singularity_pull(S, current_size) + ..() if(current_size >= STAGE_FIVE) deconstruct(FALSE) diff --git a/code/modules/atmospherics/machinery/other/meter.dm b/code/modules/atmospherics/machinery/other/meter.dm index 89f8b8d2cb..b73fd986f8 100644 --- a/code/modules/atmospherics/machinery/other/meter.dm +++ b/code/modules/atmospherics/machinery/other/meter.dm @@ -120,6 +120,7 @@ return 1 /obj/machinery/meter/singularity_pull(S, current_size) + ..() if(current_size >= STAGE_FIVE) new /obj/item/pipe_meter(loc) qdel(src) diff --git a/code/modules/mob/living/carbon/human/human.dm b/code/modules/mob/living/carbon/human/human.dm index 304a745220..f93b1cc2f1 100644 --- a/code/modules/mob/living/carbon/human/human.dm +++ b/code/modules/mob/living/carbon/human/human.dm @@ -643,6 +643,7 @@ INITIALIZE_IMMEDIATE(/mob/living/carbon/human/dummy) update_hair() /mob/living/carbon/human/singularity_pull(S, current_size) + ..() if(current_size >= STAGE_THREE) for(var/obj/item/hand in held_items) if(prob(current_size * 5) && hand.w_class >= ((11-current_size)/2) && dropItemToGround(hand)) @@ -651,7 +652,6 @@ INITIALIZE_IMMEDIATE(/mob/living/carbon/human/dummy) rad_act(current_size * 3) if(mob_negates_gravity()) return - ..() /mob/living/carbon/human/proc/do_cpr(mob/living/carbon/C) CHECK_DNA_AND_SPECIES(C) diff --git a/code/modules/mob/living/living.dm b/code/modules/mob/living/living.dm index 70a8474165..522bf5cf57 100644 --- a/code/modules/mob/living/living.dm +++ b/code/modules/mob/living/living.dm @@ -690,6 +690,7 @@ who.equip_to_slot(what, where, TRUE) /mob/living/singularity_pull(S, current_size) + ..() if(current_size >= STAGE_SIX) throw_at(S,14,3, spin=1) else diff --git a/code/modules/power/cable.dm b/code/modules/power/cable.dm index ebe478a7bf..a24c0d7c57 100644 --- a/code/modules/power/cable.dm +++ b/code/modules/power/cable.dm @@ -170,6 +170,7 @@ By design, d1 is the smallest direction and d2 is the highest return 0 /obj/structure/cable/singularity_pull(S, current_size) + ..() if(current_size >= STAGE_FIVE) deconstruct() diff --git a/code/modules/recycling/disposal-structures.dm b/code/modules/recycling/disposal-structures.dm index efe730d1c2..9015320c56 100644 --- a/code/modules/recycling/disposal-structures.dm +++ b/code/modules/recycling/disposal-structures.dm @@ -335,6 +335,7 @@ /obj/structure/disposalpipe/singularity_pull(S, current_size) + ..() if(current_size >= STAGE_FIVE) deconstruct() diff --git a/code/modules/recycling/disposal-unit.dm b/code/modules/recycling/disposal-unit.dm index 14ebec8128..4c82605673 100644 --- a/code/modules/recycling/disposal-unit.dm +++ b/code/modules/recycling/disposal-unit.dm @@ -58,6 +58,7 @@ return ..() /obj/machinery/disposal/singularity_pull(S, current_size) + ..() if(current_size >= STAGE_FIVE) deconstruct() diff --git a/tgstation.dme b/tgstation.dme index df879e0b4d..4ecd700891 100755 --- a/tgstation.dme +++ b/tgstation.dme @@ -281,6 +281,7 @@ #include "code\datums\antagonists\datum_traitor.dm" #include "code\datums\antagonists\devil.dm" #include "code\datums\antagonists\ninja.dm" +#include "code\datums\components\archaeology.dm" #include "code\datums\components\component.dm" #include "code\datums\components\slippery.dm" #include "code\datums\diseases\_disease.dm" From 71e87d851c9a943a4d864a219a0d0c715c84ae05 Mon Sep 17 00:00:00 2001 From: Jordan Brown Date: Fri, 8 Sep 2017 11:27:53 -0400 Subject: [PATCH 13/74] Adds Features per Fix tracking --- tools/github_webhook_processor.php | 128 ++++++++++++++++++++++++++++- 1 file changed, 127 insertions(+), 1 deletion(-) diff --git a/tools/github_webhook_processor.php b/tools/github_webhook_processor.php index 6113714566..75cb3562b6 100644 --- a/tools/github_webhook_processor.php +++ b/tools/github_webhook_processor.php @@ -23,6 +23,12 @@ //This is required as otherwise somebody could trick the script into leaking the api key. $hookSecret = '08ajh0qj93209qj90jfq932j32r'; +$trackPRBalance = true; //set this to false to disable PR balance tracking +$prBalanceJson = ''; //Set this to the path you'd like the writable pr balance file to be stored, not setting it writes it to the working directory +$startingPRBalance = 3; //Starting balance for never before seen users +//team 133041: tgstation/commit-access +$maintainer_team_id = 133041; //org team id that is exempt from PR balance system, setting this to null will use anyone with write access to the repo. Get from https://api.github.com/orgs/:org/teams + //Api key for pushing changelogs. $apiKey = '209ab8d879c0f987d06a09b9d879c0f987d06a09b9d8787d0a089c'; @@ -168,7 +174,7 @@ function tag_pr($payload, $opened) { if(strpos($lowertitle, '[wip]') !== FALSE) $tags[] = 'Work In Progress'; - $url = $payload['pull_request']['base']['repo']['url'] . '/issues/' . $payload['pull_request']['number'] . '/labels'; + $url = $payload['pull_request']['issue_url'] . '/labels'; $existing_labels = file_get_contents($url, false, stream_context_create($scontext)); $existing_labels = json_decode($existing_labels, true); @@ -195,6 +201,12 @@ function handle_pr($payload) { switch ($payload["action"]) { case 'opened': tag_pr($payload, true); + if(get_pr_code_friendliness($payload) < 0){ + $balances = pr_balances(); + $author = $payload['pull_request']['user']['login']; + if(isset($balances[$author]) && $balances[$author] < 0) + create_comment($payload, 'You currently have a negative Fix/Feature pull request delta of ' . $balances[$author] . '. Maintainers may close this PR at will. Fixing issues or improving the codebase will improve this score.'); + } break; case 'edited': case 'synchronize': @@ -210,6 +222,11 @@ function handle_pr($payload) { else { $action = 'merged'; checkchangelog($payload, true, true); +<<<<<<< HEAD +======= + update_pr_balance($payload); + $validated = TRUE; //pr merged events always get announced. +>>>>>>> af44a7a... Adds Features per Fix tracking (#29897) } break; default: @@ -223,7 +240,116 @@ function handle_pr($payload) { $msg = '['.$payload['pull_request']['base']['repo']['full_name'].'] Pull Request '.$action.' by '.htmlSpecialChars($payload['sender']['login']).': '.htmlSpecialChars('#'.$payload['pull_request']['number'].' '.$payload['pull_request']['user']['login'].' - '.$payload['pull_request']['title']).''; sendtoallservers('?announce='.urlencode($msg), $payload); +} +//creates a comment on the payload issue +function create_comment($payload, $comment){ + apisend($payload['pull_request']['comments_url'], 'POST', json_encode(array('body' => $comment))); +} + +//returns the payload issue's labels as a flat array +function get_pr_labels_array($payload){ + $url = $payload['pull_request']['issue_url'] . '/labels'; + $issue = json_decode(apisend($url), true); + $result = array(); + foreach($issue as $l) + $result[] = $l['name']; + return $result; +} + +//helper for getting the path the the balance json file +function pr_balance_json_path(){ + global $prBalanceJson; + return $prBalanceJson != '' ? $prBalanceJson : 'pr_balances.json'; +} + +//return the assoc array of login -> balance for prs +function pr_balances(){ + $path = pr_balance_json_path(); + if(file_exists($path)) + return json_decode(file_get_contents($path), true); + else + return array(); +} + +//returns the difference in PR balance a pull request would cause +function get_pr_code_friendliness($payload, $oldbalance = null){ + global $startingPRBalance; + if($oldbalance == null) + $oldbalance = $startingPRBalance; + $labels = get_pr_labels_array($payload); + //anything not in this list defaults to 0 + $label_values = array( + 'Fix' => 2, + 'Refactor' => 2, + 'Code Improvement' => 1, + 'Priority: High' => 4, + 'Priority: CRITICAL' => 5, + 'Atmospherics' => 4, + 'Logging' => 1, + 'Feedback' => 1, + 'Performance' => 3, + 'Feature' => -1, + 'Balance/Rebalance' => -1, + 'Tweak' => -1, + 'PRB: Reset' => $startingPRBalance - $oldbalance, + ); + + $affecting = 0; + $is_neutral = FALSE; + $found_something_positive = false; + foreach($labels as $l){ + if($l == 'PRB: No Update') { //no effect on balance + $affecting = 0; + break; + } + else if(isset($label_values[$l])) { + $friendliness = $label_values[$l]; + if($friendliness > 0) + $found_something_positive = true; + $affecting = $found_something_positive ? max($affecting, $friendliness) : $friendliness; + } + } + return $affecting; +} + +function is_maintainer($payload, $author){ + global $maintainer_team_id; + $repo_is_org = $payload['pull_request']['base']['repo']['owner']['type'] == 'Organization'; + if($maintainer_team_id == null || !$repo_is_org) { + $collaburl = $payload['pull_request']['base']['repo']['collaborators_url'] . '/' . $author . '/permissions'; + $perms = json_decode(apisend($collaburl), true); + $permlevel = $perms['permission']; + return $permlevel == 'admin' || $permlevel == 'write'; + } + else { + $check_url = 'https://api.github.com/teams/' . $maintainer_team_id . '/memberships/' . $author; + $result = json_decode(apisend($check_url), true); + return isset($result['state']); //this field won't be here if they aren't a member + } +} + +//payload is a merged pull request, updates the pr balances file with the correct positive or negative balance based on comments +function update_pr_balance($payload) { + global $startingPRBalance; + global $trackPRBalance; + if(!$trackPRBalance) + return; + $author = $payload['pull_request']['user']['login']; + if(is_maintainer($payload, $author)) //immune + return; + $balances = pr_balances(); + if(!isset($balances[$author])) + $balances[$author] = $startingPRBalance; + $friendliness = get_pr_code_friendliness($payload, $balances[$author]); + $balances[$author] += $friendliness; + if($balances[$author] < 0 && $friendliness < 0) + create_comment($payload, 'Your Fix/Feature pull request delta is currently below zero (' . $balances[$author] . '). Maintainers may close future Feature/Tweak/Balance PRs. Fixing issues or helping to improve the codebase will raise this score.'); + else if($balances[$author] >= 0 && ($balances[$author] - $friendliness) < 0) + create_comment($payload, 'Your Fix/Feature pull request delta is now above zero (' . $balances[$author] . '). Feel free to make Feature/Tweak/Balance PRs.'); + $balances_file = fopen(pr_balance_json_path(), 'w'); + fwrite($balances_file, json_encode($balances)); + fclose($balances_file); } function has_tree_been_edited($payload, $tree){ From 770c6a8e5449b9bc5bf8e6716de32b10efcb43f5 Mon Sep 17 00:00:00 2001 From: Lexorion Date: Sat, 9 Sep 2017 03:52:35 +0200 Subject: [PATCH 14/74] New blackbox sprites (#30242) * New blackbox sprites * Changes the blackbox sprite again --- icons/obj/stationobjs.dmi | Bin 56174 -> 58072 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/icons/obj/stationobjs.dmi b/icons/obj/stationobjs.dmi index 28dd158ff78d6a0992bce25ffdb91cf9c604d449..0f4cda5d8bf11c5a952d56492728c4c463c82224 100644 GIT binary patch delta 15857 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 Date: Sat, 9 Sep 2017 12:23:54 -0700 Subject: [PATCH 16/74] num2text the Instances number (#30509) --- code/modules/mob/mob.dm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/modules/mob/mob.dm b/code/modules/mob/mob.dm index 76553d17fd..a759bb89ec 100644 --- a/code/modules/mob/mob.dm +++ b/code/modules/mob/mob.dm @@ -587,7 +587,7 @@ var/turf/T = get_turf(client.eye) stat("Location:", COORD(T)) stat("CPU:", "[world.cpu]") - stat("Instances:", "[world.contents.len]") + stat("Instances:", "[num2text(world.contents.len, 10)]") GLOB.stat_entry() config.stat_entry() stat(null) From eaeaae7bef957e594e2727d02a7f3accd4392567 Mon Sep 17 00:00:00 2001 From: Jordan Brown Date: Sat, 9 Sep 2017 20:39:49 -0400 Subject: [PATCH 18/74] Added warnings for ultrasafe and safe security modes (#30515) --- code/__DEFINES/misc.dm | 5 +++++ code/game/world.dm | 19 +++++++++++++++++++ 2 files changed, 24 insertions(+) diff --git a/code/__DEFINES/misc.dm b/code/__DEFINES/misc.dm index 209a33e0c5..1c79dde65f 100644 --- a/code/__DEFINES/misc.dm +++ b/code/__DEFINES/misc.dm @@ -458,3 +458,8 @@ GLOBAL_LIST_INIT(ghost_others_options, list(GHOST_OTHERS_SIMPLE, GHOST_OTHERS_DE #define SHELLEO_ERRORLEVEL 1 #define SHELLEO_STDOUT 2 #define SHELLEO_STDERR 3 + +//server security mode +#define SECURITY_SAFE 1 +#define SECURITY_ULTRASAFE 2 +#define SECURITY_TRUSTED 3 diff --git a/code/game/world.dm b/code/game/world.dm index a1fcc364cd..991e6230e6 100644 --- a/code/game/world.dm +++ b/code/game/world.dm @@ -1,3 +1,6 @@ +GLOBAL_VAR(security_mode) +GLOBAL_PROTECT(security_mode) + /world/New() log_world("World loaded at [time_stamp()]") @@ -5,6 +8,8 @@ GLOB.config_error_log = GLOB.sql_error_log = GLOB.world_href_log = GLOB.world_runtime_log = GLOB.world_attack_log = GLOB.world_game_log = file("data/logs/config_error.log") //temporary file used to record errors with loading config, moved to log directory once logging is set bl + CheckSecurityMode() + make_datum_references_lists() //initialises global lists for referencing frequently used datums (so that we only ever do it once) config = new @@ -94,6 +99,20 @@ if(GLOB.round_id) log_game("Round ID: [GLOB.round_id]") +/world/proc/CheckSecurityMode() + //try to write to data + if(!text2file("The world is running at least safe mode", "data/server_security_check.lock")) + GLOB.security_mode = SECURITY_ULTRASAFE + warning("/tg/station 13 is not supported in ultrasafe security mode. Everything will break!") + return + + //try to shell + if(shell("echo \"The world is running in trusted mode\"") != null) + GLOB.security_mode = SECURITY_TRUSTED + else + GLOB.security_mode = SECURITY_SAFE + warning("/tg/station 13 uses many file operations, a few shell()s, and some external call()s. Trusted mode is recommended. You can download our source code for your own browsing and compilation at https://github.com/tgstation/tgstation") + /world/Topic(T, addr, master, key) var/list/input = params2list(T) From 8a297a3a9cc58c056886a889eeffa4554814f861 Mon Sep 17 00:00:00 2001 From: KorPhaeron Date: Sat, 9 Sep 2017 21:07:02 -0500 Subject: [PATCH 20/74] People in soft crit will leave blood trails when dragging themselves/Will take less damage in soft crit --- .../mob/living/carbon/human/human_movement.dm | 56 +++++++++++++++++++ code/modules/mob/living/carbon/life.dm | 10 +++- code/modules/mob/living/living.dm | 28 +++++----- 3 files changed, 78 insertions(+), 16 deletions(-) diff --git a/code/modules/mob/living/carbon/human/human_movement.dm b/code/modules/mob/living/carbon/human/human_movement.dm index 52650ec273..d01048c69a 100644 --- a/code/modules/mob/living/carbon/human/human_movement.dm +++ b/code/modules/mob/living/carbon/human/human_movement.dm @@ -12,6 +12,7 @@ /mob/living/carbon/human/experience_pressure_difference() playsound(src, 'sound/effects/space_wind.ogg', 50, 1) if(shoes && shoes.flags_1&NOSLIP_1) +<<<<<<< HEAD return 0 return ..() @@ -65,3 +66,58 @@ if(..()) return 1 return dna.species.space_move(src) +======= + return 0 + return ..() + +/mob/living/carbon/human/mob_has_gravity() + . = ..() + if(!.) + if(mob_negates_gravity()) + . = 1 + +/mob/living/carbon/human/mob_negates_gravity() + return ((shoes && shoes.negates_gravity()) || dna.species.negates_gravity(src)) + +/mob/living/carbon/human/Move(NewLoc, direct) + . = ..() + for(var/datum/mutation/human/HM in dna.mutations) + HM.on_move(src, NewLoc) + + if(shoes) + if(!lying && !buckled) + if(loc == NewLoc) + if(!has_gravity(loc)) + return + var/obj/item/clothing/shoes/S = shoes + + //Bloody footprints + var/turf/T = get_turf(src) + if(S.bloody_shoes && S.bloody_shoes[S.blood_state]) + var/obj/effect/decal/cleanable/blood/footprints/oldFP = locate(/obj/effect/decal/cleanable/blood/footprints) in T + if(oldFP && oldFP.blood_state == S.blood_state) + return + else + //No oldFP or it's a different kind of blood + S.bloody_shoes[S.blood_state] = max(0, S.bloody_shoes[S.blood_state]-BLOOD_LOSS_PER_STEP) + var/obj/effect/decal/cleanable/blood/footprints/FP = new /obj/effect/decal/cleanable/blood/footprints(T) + FP.blood_state = S.blood_state + FP.entered_dirs |= dir + FP.bloodiness = S.bloody_shoes[S.blood_state] + if(S.blood_DNA && S.blood_DNA.len) + FP.transfer_blood_dna(S.blood_DNA) + FP.update_icon() + update_inv_shoes() + //End bloody footprints + + S.step_action() +/mob/living/carbon/human/Moved() + . = ..() + if(buckled_mobs && buckled_mobs.len && riding_datum) + riding_datum.on_vehicle_move() + +/mob/living/carbon/human/Process_Spacemove(movement_dir = 0) //Temporary laziness thing. Will change to handles by species reee. + if(..()) + return 1 + return dna.species.space_move(src) +>>>>>>> 96a55aa... People in soft crit will leave blood trails when dragging themselves/Will take less damage in soft crit (#30482) diff --git a/code/modules/mob/living/carbon/life.dm b/code/modules/mob/living/carbon/life.dm index d6d6084380..38e13f41d0 100644 --- a/code/modules/mob/living/carbon/life.dm +++ b/code/modules/mob/living/carbon/life.dm @@ -58,12 +58,14 @@ var/datum/gas_mixture/breath - if(health <= HEALTH_THRESHOLD_CRIT || (pulledby && pulledby.grab_state >= GRAB_KILL && !getorganslot("breathing_tube"))) + if(health <= HEALTH_THRESHOLD_FULLCRIT || (pulledby && pulledby.grab_state >= GRAB_KILL && !getorganslot("breathing_tube"))) losebreath++ + else if(health <= HEALTH_THRESHOLD_CRIT) + losebreath += 0.25 + //Suffocate if(losebreath > 0) - losebreath-- if(prob(10)) emote("gasp") if(istype(loc, /obj/)) @@ -113,7 +115,9 @@ if(!breath || (breath.total_moles() == 0) || !lungs) if(reagents.has_reagent("epinephrine") && lungs) return - adjustOxyLoss(1) + var/oxy_loss = min(losebreath, 1) + adjustOxyLoss(oxy_loss) + losebreath -= oxy_loss failed_last_breath = 1 throw_alert("not_enough_oxy", /obj/screen/alert/not_enough_oxy) return 0 diff --git a/code/modules/mob/living/living.dm b/code/modules/mob/living/living.dm index 70a8474165..b2c771db08 100644 --- a/code/modules/mob/living/living.dm +++ b/code/modules/mob/living/living.dm @@ -429,6 +429,7 @@ else return 0 + var/old_direction = dir var/atom/movable/pullee = pulling if(pullee && get_dist(src, pullee) > 1) stop_pulling() @@ -444,10 +445,6 @@ var/pull_dir = get_dir(src, pulling) if(get_dist(src, pulling) > 1 || ((pull_dir - 1) & pull_dir)) //puller and pullee more than one tile away or in diagonal position - if(isliving(pulling)) - var/mob/living/M = pulling - if(M.lying && !M.buckled && (prob(M.getBruteLoss()*200/M.maxHealth))) - M.makeTrail(T) pulling.Move(T, get_dir(pulling, T)) //the pullee tries to reach our previous position if(pulling && get_dist(src, pulling) > 1) //the pullee couldn't keep up stop_pulling() @@ -458,6 +455,10 @@ if (s_active && !(CanReach(s_active,view_only = TRUE))) s_active.close(src) + if(lying && !buckled && prob(getBruteLoss()*200/maxHealth)) + + makeTrail(newloc, T, old_direction) + /mob/living/movement_delay(ignorewalk = 0) . = ..() if(isopenturf(loc) && !is_flying()) @@ -474,31 +475,32 @@ if(MOVE_INTENT_WALK) . += config.walk_speed -/mob/living/proc/makeTrail(turf/target_turf) +/mob/living/proc/makeTrail(turf/target_turf, turf/start, direction) if(!has_gravity()) return var/blood_exists = FALSE - for(var/obj/effect/decal/cleanable/trail_holder/C in loc) //checks for blood splatter already on the floor + for(var/obj/effect/decal/cleanable/trail_holder/C in start) //checks for blood splatter already on the floor blood_exists = TRUE - if(isturf(loc)) + if(isturf(start)) var/trail_type = getTrail() if(trail_type) var/brute_ratio = round(getBruteLoss() / maxHealth, 0.1) if(blood_volume && blood_volume > max(BLOOD_VOLUME_NORMAL*(1 - brute_ratio * 0.25), 0))//don't leave trail if blood volume below a threshold blood_volume = max(blood_volume - max(1, brute_ratio * 2), 0) //that depends on our brute damage. - var/newdir = get_dir(target_turf, loc) - if(newdir != dir) - newdir = newdir | dir + var/newdir = get_dir(target_turf, start) + if(newdir != direction) + newdir = newdir | direction if(newdir == 3) //N + S newdir = NORTH else if(newdir == 12) //E + W newdir = EAST if((newdir in GLOB.cardinals) && (prob(50))) - newdir = turn(get_dir(target_turf, loc), 180) + newdir = turn(get_dir(target_turf, start), 180) if(!blood_exists) - new /obj/effect/decal/cleanable/trail_holder(loc) - for(var/obj/effect/decal/cleanable/trail_holder/TH in loc) + new /obj/effect/decal/cleanable/trail_holder(start) + + for(var/obj/effect/decal/cleanable/trail_holder/TH in start) if((!(newdir in TH.existing_dirs) || trail_type == "trails_1" || trail_type == "trails_2") && TH.existing_dirs.len <= 16) //maximum amount of overlays is 16 (all light & heavy directions filled) TH.existing_dirs += newdir TH.add_overlay(image('icons/effects/blood.dmi', trail_type, dir = newdir)) From adc85f0edca5f9bd267692a0fad2c2488939538f Mon Sep 17 00:00:00 2001 From: oranges Date: Sun, 10 Sep 2017 21:00:32 +1000 Subject: [PATCH 21/74] In which smartfridge ui_data is called only when needed, and a minor display bug involving drying racks is fixed --- .../kitchen_machinery/smartfridge.dm | 55 +++++++++++++++++++ 1 file changed, 55 insertions(+) diff --git a/code/modules/food_and_drinks/kitchen_machinery/smartfridge.dm b/code/modules/food_and_drinks/kitchen_machinery/smartfridge.dm index e996429939..491da12a81 100644 --- a/code/modules/food_and_drinks/kitchen_machinery/smartfridge.dm +++ b/code/modules/food_and_drinks/kitchen_machinery/smartfridge.dm @@ -150,6 +150,7 @@ if(stat) return FALSE +<<<<<<< HEAD var/dat = "Select an item:
    " if (contents.len == 0) @@ -189,6 +190,39 @@ /obj/machinery/smartfridge/Topic(var/href, var/list/href_list) if(..()) +======= +/obj/machinery/smartfridge/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = FALSE, datum/tgui/master_ui = null, datum/ui_state/state = GLOB.default_state) + ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open) + if(!ui) + ui = new(user, src, ui_key, "smartvend", name, 440, 550, master_ui, state) + ui.set_autoupdate(FALSE) + ui.open() + +/obj/machinery/smartfridge/ui_data(mob/user) + . = list() + + var/listofitems = list() + for (var/I in src) + var/atom/movable/O = I + if (!QDELETED(O)) + if (listofitems[O.name]) + listofitems[O.name]["amount"]++ + else + listofitems[O.name] = list("name" = O.name, "type" = O.type, "amount" = 1) + sortList(listofitems) + + .["contents"] = listofitems + .["name"] = name + .["isdryer"] = FALSE + + +/obj/machinery/smartfridge/handle_atom_del(atom/A) // Update the UIs in case something inside gets deleted + SStgui.update_uis(src) + +/obj/machinery/smartfridge/ui_act(action, params) + . = ..() + if(.) +>>>>>>> 5f6b2a9... Merge pull request #30519 from vuonojenmustaturska/smartfridges2electricboogaloo return usr.set_machine(src) @@ -240,6 +274,7 @@ /obj/machinery/smartfridge/drying_rack/default_deconstruction_crowbar(obj/item/crowbar/C, ignore_panel = 1) ..() +<<<<<<< HEAD /obj/machinery/smartfridge/drying_rack/interact(mob/user) var/dat = ..() if(dat) @@ -254,6 +289,25 @@ toggle_drying(FALSE) updateUsrDialog() update_icon() +======= +/obj/machinery/smartfridge/drying_rack/ui_data(mob/user) + . = ..() + .["isdryer"] = TRUE + .["verb"] = "Take" + .["drying"] = drying + + +/obj/machinery/smartfridge/drying_rack/ui_act(action, params) + . = ..() + if(.) + update_icon() // This is to handle a case where the last item is taken out manually instead of through drying pop-out + return + switch(action) + if("Dry") + toggle_drying(FALSE) + return TRUE + return FALSE +>>>>>>> 5f6b2a9... Merge pull request #30519 from vuonojenmustaturska/smartfridges2electricboogaloo /obj/machinery/smartfridge/drying_rack/power_change() if(powered() && anchored) @@ -279,6 +333,7 @@ ..() if(drying) if(rack_dry())//no need to update unless something got dried + SStgui.update_uis(src) update_icon() /obj/machinery/smartfridge/drying_rack/accept_check(obj/item/O) From 33f35fe4d2c895ecefa4970c2d25cf303c63951d Mon Sep 17 00:00:00 2001 From: LetterJay Date: Sun, 10 Sep 2017 11:46:34 -0500 Subject: [PATCH 22/74] Update tools.dm --- code/game/objects/items/tools.dm | 1583 +++++++++++++++--------------- 1 file changed, 790 insertions(+), 793 deletions(-) diff --git a/code/game/objects/items/tools.dm b/code/game/objects/items/tools.dm index 0e557497c0..5c901ca4bd 100644 --- a/code/game/objects/items/tools.dm +++ b/code/game/objects/items/tools.dm @@ -1,795 +1,793 @@ -<<<<<<< HEAD -#define WELDER_FUEL_BURN_INTERVAL 13 - -/* Tools! - * Note: Multitools are /obj/item/device - * - * Contains: - * Wrench - * Screwdriver - * Wirecutters - * Welding Tool - * Crowbar - */ - -/* - * Wrench - */ -/obj/item/wrench - name = "wrench" - desc = "A wrench with common uses. Can be found in your hand." - icon = 'icons/obj/tools.dmi' - icon_state = "wrench" - lefthand_file = 'icons/mob/inhands/equipment/tools_lefthand.dmi' - righthand_file = 'icons/mob/inhands/equipment/tools_righthand.dmi' - flags_1 = CONDUCT_1 - slot_flags = SLOT_BELT - force = 5 - throwforce = 7 - w_class = WEIGHT_CLASS_SMALL - usesound = 'sound/items/ratchet.ogg' - materials = list(MAT_METAL=150) - origin_tech = "materials=1;engineering=1" - attack_verb = list("bashed", "battered", "bludgeoned", "whacked") - toolspeed = 1 - armor = list(melee = 0, bullet = 0, laser = 0, energy = 0, bomb = 0, bio = 0, rad = 0, fire = 50, acid = 30) - -/obj/item/wrench/suicide_act(mob/user) - user.visible_message("[user] is beating [user.p_them()]self to death with [src]! It looks like [user.p_theyre()] trying to commit suicide!") - playsound(loc, 'sound/weapons/genhit.ogg', 50, 1, -1) - return (BRUTELOSS) - -/obj/item/wrench/cyborg - name = "automatic wrench" - desc = "An advanced robotic wrench. Can be found in construction cyborgs." - toolspeed = 0.5 - -/obj/item/wrench/brass - name = "brass wrench" - desc = "A brass wrench. It's faintly warm to the touch." - resistance_flags = FIRE_PROOF | ACID_PROOF - icon_state = "wrench_brass" - toolspeed = 0.5 - -/obj/item/wrench/abductor - name = "alien wrench" - desc = "A polarized wrench. It causes anything placed between the jaws to turn." - icon = 'icons/obj/abductor.dmi' - icon_state = "wrench" - usesound = 'sound/effects/empulse.ogg' - toolspeed = 0.1 - origin_tech = "materials=5;engineering=5;abductor=3" - -/obj/item/wrench/power - name = "hand drill" - desc = "A simple powered hand drill. It's fitted with a bolt bit." - icon_state = "drill_bolt" - item_state = "drill" - lefthand_file = 'icons/mob/inhands/equipment/tools_lefthand.dmi' - righthand_file = 'icons/mob/inhands/equipment/tools_righthand.dmi' - usesound = 'sound/items/drill_use.ogg' - materials = list(MAT_METAL=150,MAT_SILVER=50,MAT_TITANIUM=25) - origin_tech = "materials=2;engineering=2" //done for balance reasons, making them high value for research, but harder to get - force = 8 //might or might not be too high, subject to change - w_class = WEIGHT_CLASS_SMALL - throwforce = 8 - attack_verb = list("drilled", "screwed", "jabbed") - toolspeed = 0.25 - -/obj/item/wrench/power/attack_self(mob/user) - playsound(get_turf(user),'sound/items/change_drill.ogg',50,1) - var/obj/item/wirecutters/power/s_drill = new /obj/item/screwdriver/power - to_chat(user, "You attach the screw driver bit to [src].") - qdel(src) - user.put_in_active_hand(s_drill) - -/obj/item/wrench/power/suicide_act(mob/user) - user.visible_message("[user] is pressing [src] against [user.p_their()] head! It looks like [user.p_theyre()] trying to commit suicide!") - return (BRUTELOSS) - -/obj/item/wrench/medical - name = "medical wrench" - desc = "A medical wrench with common(medical?) uses. Can be found in your hand." - icon_state = "wrench_medical" - force = 2 //MEDICAL - throwforce = 4 - origin_tech = "materials=1;engineering=1;biotech=3" - attack_verb = list("wrenched", "medicaled", "tapped", "jabbed", "whacked") - -/obj/item/wrench/medical/suicide_act(mob/living/user) - user.visible_message("[user] is praying to the medical wrench to take [user.p_their()] soul. It looks like [user.p_theyre()] trying to commit suicide!") - // TODO Make them glow with the power of the M E D I C A L W R E N C H - // during their ascension - - // Stun stops them from wandering off - user.Stun(100, ignore_canstun = TRUE) - playsound(loc, 'sound/effects/pray.ogg', 50, 1, -1) - - // Let the sound effect finish playing - sleep(20) - - if(!user) - return - - for(var/obj/item/W in user) - user.dropItemToGround(W) - - var/obj/item/wrench/medical/W = new /obj/item/wrench/medical(loc) - W.add_fingerprint(user) - W.desc += " For some reason, it reminds you of [user.name]." - - if(!user) - return - - user.dust() - - return OXYLOSS - -/* - * Screwdriver - */ -/obj/item/screwdriver - name = "screwdriver" - desc = "You can be totally screwy with this." - icon = 'icons/obj/tools.dmi' - icon_state = "screwdriver" - item_state = "screwdriver" - lefthand_file = 'icons/mob/inhands/equipment/tools_lefthand.dmi' - righthand_file = 'icons/mob/inhands/equipment/tools_righthand.dmi' - flags_1 = CONDUCT_1 - slot_flags = SLOT_BELT - force = 5 - w_class = WEIGHT_CLASS_TINY - throwforce = 5 - throw_speed = 3 - throw_range = 5 - materials = list(MAT_METAL=75) - attack_verb = list("stabbed") - hitsound = 'sound/weapons/bladeslice.ogg' - usesound = 'sound/items/screwdriver.ogg' - toolspeed = 1 - armor = list(melee = 0, bullet = 0, laser = 0, energy = 0, bomb = 0, bio = 0, rad = 0, fire = 50, acid = 30) - var/random_color = TRUE //if the screwdriver uses random coloring - var/static/list/screwdriver_colors = list(\ - "blue" = rgb(24, 97, 213), \ - "red" = rgb(149, 23, 16), \ - "pink" = rgb(213, 24, 141), \ - "brown" = rgb(160, 82, 18), \ - "green" = rgb(14, 127, 27), \ - "cyan" = rgb(24, 162, 213), \ - "yellow" = rgb(213, 140, 24), \ - ) - -/obj/item/screwdriver/suicide_act(mob/user) - user.visible_message("[user] is stabbing [src] into [user.p_their()] [pick("temple", "heart")]! It looks like [user.p_theyre()] trying to commit suicide!") - return(BRUTELOSS) - -/obj/item/screwdriver/Initialize() - . = ..() - if(random_color) //random colors! - var/our_color = pick(screwdriver_colors) - add_atom_colour(screwdriver_colors[our_color], FIXED_COLOUR_PRIORITY) - update_icon() - if(prob(75)) - pixel_y = rand(0, 16) - -/obj/item/screwdriver/update_icon() - if(!random_color) //icon override - return - cut_overlays() - var/mutable_appearance/base_overlay = mutable_appearance(icon, "screwdriver_screwybits") - base_overlay.appearance_flags = RESET_COLOR - add_overlay(base_overlay) - -/obj/item/screwdriver/worn_overlays(isinhands = FALSE, icon_file) - . = list() - if(isinhands && random_color) - var/mutable_appearance/M = mutable_appearance(icon_file, "screwdriver_head") - M.appearance_flags = RESET_COLOR - . += M - -/obj/item/screwdriver/get_belt_overlay() - if(random_color) - var/mutable_appearance/body = mutable_appearance('icons/obj/clothing/belt_overlays.dmi', "screwdriver") - var/mutable_appearance/head = mutable_appearance('icons/obj/clothing/belt_overlays.dmi', "screwdriver_head") - body.color = color - head.overlays += body - return head - else - return mutable_appearance('icons/obj/clothing/belt_overlays.dmi', icon_state) - -/obj/item/screwdriver/attack(mob/living/carbon/M, mob/living/carbon/user) - if(!istype(M)) - return ..() - if(user.zone_selected != "eyes" && user.zone_selected != "head") - return ..() - if(user.disabilities & CLUMSY && prob(50)) - M = user - return eyestab(M,user) - -/obj/item/screwdriver/brass - name = "brass screwdriver" - desc = "A screwdriver made of brass. The handle feels freezing cold." - resistance_flags = FIRE_PROOF | ACID_PROOF - icon_state = "screwdriver_brass" - item_state = "screwdriver_brass" - toolspeed = 0.5 - random_color = FALSE - -/obj/item/screwdriver/abductor - name = "alien screwdriver" - desc = "An ultrasonic screwdriver." - icon = 'icons/obj/abductor.dmi' - icon_state = "screwdriver_a" - item_state = "screwdriver_nuke" - usesound = 'sound/items/pshoom.ogg' - toolspeed = 0.1 - random_color = FALSE - -/obj/item/screwdriver/power - name = "hand drill" - desc = "A simple powered hand drill. It's fitted with a screw bit." - icon_state = "drill_screw" - item_state = "drill" - lefthand_file = 'icons/mob/inhands/equipment/tools_lefthand.dmi' - righthand_file = 'icons/mob/inhands/equipment/tools_righthand.dmi' - materials = list(MAT_METAL=150,MAT_SILVER=50,MAT_TITANIUM=25) - origin_tech = "materials=2;engineering=2" //done for balance reasons, making them high value for research, but harder to get - force = 8 //might or might not be too high, subject to change - w_class = WEIGHT_CLASS_SMALL - throwforce = 8 - throw_speed = 2 - throw_range = 3//it's heavier than a screw driver/wrench, so it does more damage, but can't be thrown as far - attack_verb = list("drilled", "screwed", "jabbed","whacked") - hitsound = 'sound/items/drill_hit.ogg' - usesound = 'sound/items/drill_use.ogg' - toolspeed = 0.25 - random_color = FALSE - -/obj/item/screwdriver/power/suicide_act(mob/user) - user.visible_message("[user] is putting [src] to [user.p_their()] temple. It looks like [user.p_theyre()] trying to commit suicide!") - return(BRUTELOSS) - -/obj/item/screwdriver/power/attack_self(mob/user) - playsound(get_turf(user),'sound/items/change_drill.ogg',50,1) - var/obj/item/wrench/power/b_drill = new /obj/item/wrench/power - to_chat(user, "You attach the bolt driver bit to [src].") - qdel(src) - user.put_in_active_hand(b_drill) - -/obj/item/screwdriver/cyborg - name = "powered screwdriver" - desc = "An electrical screwdriver, designed to be both precise and quick." - usesound = 'sound/items/drill_use.ogg' - toolspeed = 0.5 - -/* - * Wirecutters - */ -/obj/item/wirecutters - name = "wirecutters" - desc = "This cuts wires." - icon = 'icons/obj/tools.dmi' - icon_state = null - lefthand_file = 'icons/mob/inhands/equipment/tools_lefthand.dmi' - righthand_file = 'icons/mob/inhands/equipment/tools_righthand.dmi' - flags_1 = CONDUCT_1 - slot_flags = SLOT_BELT - force = 6 - throw_speed = 3 - throw_range = 7 - w_class = WEIGHT_CLASS_SMALL - materials = list(MAT_METAL=80) - attack_verb = list("pinched", "nipped") - hitsound = 'sound/items/wirecutter.ogg' - usesound = 'sound/items/wirecutter.ogg' - origin_tech = "materials=1;engineering=1" - toolspeed = 1 - armor = list(melee = 0, bullet = 0, laser = 0, energy = 0, bomb = 0, bio = 0, rad = 0, fire = 50, acid = 30) - - -/obj/item/wirecutters/New(loc, var/param_color = null) - ..() - if(!icon_state) - if(!param_color) - param_color = pick("yellow","red") - icon_state = "cutters_[param_color]" - -/obj/item/wirecutters/attack(mob/living/carbon/C, mob/user) - if(istype(C) && C.handcuffed && istype(C.handcuffed, /obj/item/restraints/handcuffs/cable)) - user.visible_message("[user] cuts [C]'s restraints with [src]!") - qdel(C.handcuffed) - C.handcuffed = null - if(C.buckled && C.buckled.buckle_requires_restraints) - C.buckled.unbuckle_mob(C) - C.update_handcuffed() - return - else - ..() - -/obj/item/wirecutters/suicide_act(mob/user) - user.visible_message("[user] is cutting at [user.p_their()] arteries with [src]! It looks like [user.p_theyre()] trying to commit suicide!") - playsound(loc, usesound, 50, 1, -1) - return (BRUTELOSS) - -/obj/item/wirecutters/brass - name = "brass wirecutters" - desc = "A pair of wirecutters made of brass. The handle feels freezing cold to the touch." - resistance_flags = FIRE_PROOF | ACID_PROOF - icon_state = "cutters_brass" - toolspeed = 0.5 - -/obj/item/wirecutters/abductor - name = "alien wirecutters" - desc = "Extremely sharp wirecutters, made out of a silvery-green metal." - icon = 'icons/obj/abductor.dmi' - icon_state = "cutters" - toolspeed = 0.1 - origin_tech = "materials=5;engineering=4;abductor=3" - -/obj/item/wirecutters/cyborg - name = "wirecutters" - desc = "This cuts wires." - toolspeed = 0.5 - -/obj/item/wirecutters/power - name = "jaws of life" - desc = "A set of jaws of life, compressed through the magic of science. It's fitted with a cutting head." - icon_state = "jaws_cutter" - item_state = "jawsoflife" - origin_tech = "materials=2;engineering=2" - materials = list(MAT_METAL=150,MAT_SILVER=50,MAT_TITANIUM=25) - usesound = 'sound/items/jaws_cut.ogg' - toolspeed = 0.25 - -/obj/item/wirecutters/power/suicide_act(mob/user) - user.visible_message("[user] is wrapping \the [src] around [user.p_their()] neck. It looks like [user.p_theyre()] trying to rip [user.p_their()] head off!") - playsound(loc, 'sound/items/jaws_cut.ogg', 50, 1, -1) - if(iscarbon(user)) - var/mob/living/carbon/C = user - var/obj/item/bodypart/BP = C.get_bodypart("head") - if(BP) - BP.drop_limb() - playsound(loc,pick('sound/misc/desceration-01.ogg','sound/misc/desceration-02.ogg','sound/misc/desceration-01.ogg') ,50, 1, -1) - return (BRUTELOSS) - -/obj/item/wirecutters/power/attack_self(mob/user) - playsound(get_turf(user), 'sound/items/change_jaws.ogg', 50, 1) - var/obj/item/crowbar/power/pryjaws = new /obj/item/crowbar/power - to_chat(user, "You attach the pry jaws to [src].") - qdel(src) - user.put_in_active_hand(pryjaws) -/* - * Welding Tool - */ -/obj/item/weldingtool - name = "welding tool" - desc = "A standard edition welder provided by NanoTrasen." - icon = 'icons/obj/tools.dmi' - icon_state = "welder" - item_state = "welder" - lefthand_file = 'icons/mob/inhands/equipment/tools_lefthand.dmi' - righthand_file = 'icons/mob/inhands/equipment/tools_righthand.dmi' - flags_1 = CONDUCT_1 - slot_flags = SLOT_BELT - force = 3 - throwforce = 5 - hitsound = "swing_hit" - usesound = 'sound/items/welder.ogg' - var/acti_sound = 'sound/items/welderactivate.ogg' - var/deac_sound = 'sound/items/welderdeactivate.ogg' - throw_speed = 3 - throw_range = 5 - w_class = WEIGHT_CLASS_SMALL - armor = list(melee = 0, bullet = 0, laser = 0, energy = 0, bomb = 0, bio = 0, rad = 0, fire = 100, acid = 30) - resistance_flags = FIRE_PROOF - - materials = list(MAT_METAL=70, MAT_GLASS=30) - origin_tech = "engineering=1;plasmatech=1" - var/welding = 0 //Whether or not the welding tool is off(0), on(1) or currently welding(2) - var/status = TRUE //Whether the welder is secured or unsecured (able to attach rods to it to make a flamethrower) - var/max_fuel = 20 //The max amount of fuel the welder can hold - var/change_icons = 1 - var/can_off_process = 0 - var/light_intensity = 2 //how powerful the emitted light is when used. - var/burned_fuel_for = 0 //when fuel was last removed - heat = 3800 - toolspeed = 1 - -/obj/item/weldingtool/Initialize() - . = ..() - create_reagents(max_fuel) - reagents.add_reagent("welding_fuel", max_fuel) - update_icon() - - -/obj/item/weldingtool/proc/update_torch() - if(welding) - add_overlay("[initial(icon_state)]-on") - item_state = "[initial(item_state)]1" - else - item_state = "[initial(item_state)]" - - -/obj/item/weldingtool/update_icon() - cut_overlays() - if(change_icons) - var/ratio = get_fuel() / max_fuel - ratio = Ceiling(ratio*4) * 25 - add_overlay("[initial(icon_state)][ratio]") - update_torch() - return - - -/obj/item/weldingtool/process() - switch(welding) - if(0) - force = 3 - damtype = "brute" - update_icon() - if(!can_off_process) - STOP_PROCESSING(SSobj, src) - return - //Welders left on now use up fuel, but lets not have them run out quite that fast - if(1) - force = 15 - damtype = "fire" - ++burned_fuel_for - if(burned_fuel_for >= WELDER_FUEL_BURN_INTERVAL) - remove_fuel(1) - update_icon() - - //This is to start fires. process() is only called if the welder is on. - open_flame() - - -/obj/item/weldingtool/suicide_act(mob/user) - user.visible_message("[user] welds [user.p_their()] every orifice closed! It looks like [user.p_theyre()] trying to commit suicide!") - return (FIRELOSS) - - -/obj/item/weldingtool/attackby(obj/item/I, mob/user, params) - if(istype(I, /obj/item/screwdriver)) - flamethrower_screwdriver(I, user) - else if(istype(I, /obj/item/stack/rods)) - flamethrower_rods(I, user) - else - return ..() - - -/obj/item/weldingtool/attack(mob/living/carbon/human/H, mob/user) - if(!istype(H)) - return ..() - - var/obj/item/bodypart/affecting = H.get_bodypart(check_zone(user.zone_selected)) - - if(affecting && affecting.status == BODYPART_ROBOTIC && user.a_intent != INTENT_HARM) - if(src.remove_fuel(1)) - playsound(loc, usesound, 50, 1) - if(user == H) - user.visible_message("[user] starts to fix some of the dents on [H]'s [affecting.name].", "You start fixing some of the dents on [H]'s [affecting.name].") - if(!do_mob(user, H, 50)) - return - item_heal_robotic(H, user, 15, 0) - else - return ..() - - -/obj/item/weldingtool/afterattack(atom/O, mob/user, proximity) - if(!proximity) return - - if(welding) - remove_fuel(1) - var/turf/location = get_turf(user) - location.hotspot_expose(700, 50, 1) - if(get_fuel() <= 0) - set_light(0) - - if(isliving(O)) - var/mob/living/L = O - if(L.IgniteMob()) - message_admins("[key_name_admin(user)] set [key_name_admin(L)] on fire") - log_game("[key_name(user)] set [key_name(L)] on fire") - - -/obj/item/weldingtool/attack_self(mob/user) - switched_on(user) - if(welding) - set_light(light_intensity) - - update_icon() - - -//Returns the amount of fuel in the welder -/obj/item/weldingtool/proc/get_fuel() - return reagents.get_reagent_amount("welding_fuel") - - -//Removes fuel from the welding tool. If a mob is passed, it will try to flash the mob's eyes. This should probably be renamed to use() -/obj/item/weldingtool/proc/remove_fuel(amount = 1, mob/living/M = null) - if(!welding || !check_fuel()) - return 0 - if(amount) - burned_fuel_for = 0 - if(get_fuel() >= amount) - reagents.remove_reagent("welding_fuel", amount) - check_fuel() - if(M) - M.flash_act(light_intensity) - return TRUE - else - if(M) - to_chat(M, "You need more welding fuel to complete this task!") - return FALSE - - -//Turns off the welder if there is no more fuel (does this really need to be its own proc?) -/obj/item/weldingtool/proc/check_fuel(mob/user) - if(get_fuel() <= 0 && welding) - switched_on(user) - update_icon() - //mob icon update - if(ismob(loc)) - var/mob/M = loc - M.update_inv_hands(0) - - return 0 - return 1 - -//Switches the welder on -/obj/item/weldingtool/proc/switched_on(mob/user) - if(!status) - to_chat(user, "[src] can't be turned on while unsecured!") - return - welding = !welding - if(welding) - if(get_fuel() >= 1) - to_chat(user, "You switch [src] on.") - playsound(loc, acti_sound, 50, 1) - force = 15 - damtype = "fire" - hitsound = 'sound/items/welder.ogg' - update_icon() - START_PROCESSING(SSobj, src) - else - to_chat(user, "You need more fuel!") - switched_off(user) - else - to_chat(user, "You switch [src] off.") - playsound(loc, deac_sound, 50, 1) - switched_off(user) - -//Switches the welder off -/obj/item/weldingtool/proc/switched_off(mob/user) - welding = 0 - set_light(0) - - force = 3 - damtype = "brute" - hitsound = "swing_hit" - update_icon() - - -/obj/item/weldingtool/examine(mob/user) - ..() - to_chat(user, "It contains [get_fuel()] unit\s of fuel out of [max_fuel].") - -/obj/item/weldingtool/is_hot() - return welding * heat - -//Returns whether or not the welding tool is currently on. -/obj/item/weldingtool/proc/isOn() - return welding - - -/obj/item/weldingtool/proc/flamethrower_screwdriver(obj/item/I, mob/user) - if(welding) - to_chat(user, "Turn it off first!") - return - status = !status - if(status) - to_chat(user, "You resecure [src].") - else - to_chat(user, "[src] can now be attached and modified.") - add_fingerprint(user) - -/obj/item/weldingtool/proc/flamethrower_rods(obj/item/I, mob/user) - if(!status) - var/obj/item/stack/rods/R = I - if (R.use(1)) - var/obj/item/flamethrower/F = new /obj/item/flamethrower(user.loc) - if(!remove_item_from_storage(F)) - user.transferItemToLoc(src, F, TRUE) - F.weldtool = src - add_fingerprint(user) - to_chat(user, "You add a rod to a welder, starting to build a flamethrower.") - user.put_in_hands(F) - else - to_chat(user, "You need one rod to start building a flamethrower!") - -/obj/item/weldingtool/ignition_effect(atom/A, mob/user) - if(welding && remove_fuel(1, user)) - . = "[user] casually lights [A] with [src], what a badass." - else - . = "" - -/obj/item/weldingtool/largetank - name = "industrial welding tool" - desc = "A slightly larger welder with a larger tank." - icon_state = "indwelder" - max_fuel = 40 - materials = list(MAT_GLASS=60) - origin_tech = "engineering=2;plasmatech=2" - -/obj/item/weldingtool/largetank/cyborg - name = "integrated welding tool" - desc = "An advanced welder designed to be used in robotic systems." - toolspeed = 0.5 - -/obj/item/weldingtool/largetank/flamethrower_screwdriver() - return - - -/obj/item/weldingtool/mini - name = "emergency welding tool" - desc = "A miniature welder used during emergencies." - icon_state = "miniwelder" - max_fuel = 10 - w_class = WEIGHT_CLASS_TINY - materials = list(MAT_METAL=30, MAT_GLASS=10) - change_icons = 0 - -/obj/item/weldingtool/mini/flamethrower_screwdriver() - return - -/obj/item/weldingtool/abductor - name = "alien welding tool" - desc = "An alien welding tool. Whatever fuel it uses, it never runs out." - icon = 'icons/obj/abductor.dmi' - icon_state = "welder" - toolspeed = 0.1 - light_intensity = 0 - change_icons = 0 - origin_tech = "plasmatech=5;engineering=5;abductor=3" - -/obj/item/weldingtool/abductor/process() - if(get_fuel() <= max_fuel) - reagents.add_reagent("welding_fuel", 1) - ..() - -/obj/item/weldingtool/hugetank - name = "upgraded industrial welding tool" - desc = "An upgraded welder based of the industrial welder." - icon_state = "upindwelder" - item_state = "upindwelder" - max_fuel = 80 - materials = list(MAT_METAL=70, MAT_GLASS=120) - origin_tech = "engineering=3;plasmatech=2" - -/obj/item/weldingtool/experimental - name = "experimental welding tool" - desc = "An experimental welder capable of self-fuel generation and less harmful to the eyes." - icon_state = "exwelder" - item_state = "exwelder" - max_fuel = 40 - materials = list(MAT_METAL=70, MAT_GLASS=120) - origin_tech = "materials=4;engineering=4;bluespace=3;plasmatech=4" - var/last_gen = 0 - change_icons = 0 - can_off_process = 1 - light_intensity = 1 - toolspeed = 0.5 - var/nextrefueltick = 0 - -/obj/item/weldingtool/experimental/brass - name = "brass welding tool" - desc = "A brass welder that seems to constantly refuel itself. It is faintly warm to the touch." - resistance_flags = FIRE_PROOF | ACID_PROOF - icon_state = "brasswelder" - item_state = "brasswelder" - - -/obj/item/weldingtool/experimental/process() - ..() - if(get_fuel() < max_fuel && nextrefueltick < world.time) - nextrefueltick = world.time + 10 - reagents.add_reagent("welding_fuel", 1) - - -/* - * Crowbar - */ - -/obj/item/crowbar - name = "pocket crowbar" - desc = "A small crowbar. This handy tool is useful for lots of things, such as prying floor tiles or opening unpowered doors." - icon = 'icons/obj/tools.dmi' - icon_state = "crowbar" - lefthand_file = 'icons/mob/inhands/equipment/tools_lefthand.dmi' - righthand_file = 'icons/mob/inhands/equipment/tools_righthand.dmi' - usesound = 'sound/items/crowbar.ogg' - flags_1 = CONDUCT_1 - slot_flags = SLOT_BELT - force = 5 - throwforce = 7 - w_class = WEIGHT_CLASS_SMALL - materials = list(MAT_METAL=50) - origin_tech = "engineering=1;combat=1" - attack_verb = list("attacked", "bashed", "battered", "bludgeoned", "whacked") - toolspeed = 1 - armor = list(melee = 0, bullet = 0, laser = 0, energy = 0, bomb = 0, bio = 0, rad = 0, fire = 50, acid = 30) - -/obj/item/crowbar/suicide_act(mob/user) - user.visible_message("[user] is beating [user.p_them()]self to death with [src]! It looks like [user.p_theyre()] trying to commit suicide!") - playsound(loc, 'sound/weapons/genhit.ogg', 50, 1, -1) - return (BRUTELOSS) - -/obj/item/crowbar/red - icon_state = "crowbar_red" - force = 8 - -/obj/item/crowbar/brass - name = "brass crowbar" - desc = "A brass crowbar. It feels faintly warm to the touch." - resistance_flags = FIRE_PROOF | ACID_PROOF - icon_state = "crowbar_brass" - toolspeed = 0.5 - -/obj/item/crowbar/abductor - name = "alien crowbar" - desc = "A hard-light crowbar. It appears to pry by itself, without any effort required." - icon = 'icons/obj/abductor.dmi' - usesound = 'sound/weapons/sonic_jackhammer.ogg' - icon_state = "crowbar" - toolspeed = 0.1 - origin_tech = "combat=4;engineering=4;abductor=3" - -/obj/item/crowbar/large - name = "crowbar" - desc = "It's a big crowbar. It doesn't fit in your pockets, because it's big." - force = 12 - w_class = WEIGHT_CLASS_NORMAL - throw_speed = 3 - throw_range = 3 - materials = list(MAT_METAL=70) - icon_state = "crowbar_large" - item_state = "crowbar" - toolspeed = 0.5 - -/obj/item/crowbar/cyborg - name = "hydraulic crowbar" - desc = "A hydraulic prying tool, compact but powerful. Designed to replace crowbar in construction cyborgs." - usesound = 'sound/items/jaws_pry.ogg' - force = 10 - toolspeed = 0.5 - -/obj/item/crowbar/power - name = "jaws of life" - desc = "A set of jaws of life, compressed through the magic of science. It's fitted with a prying head." - icon_state = "jaws_pry" - item_state = "jawsoflife" - lefthand_file = 'icons/mob/inhands/equipment/tools_lefthand.dmi' - righthand_file = 'icons/mob/inhands/equipment/tools_righthand.dmi' - materials = list(MAT_METAL=150,MAT_SILVER=50,MAT_TITANIUM=25) - origin_tech = "materials=2;engineering=2" - usesound = 'sound/items/jaws_pry.ogg' - force = 15 - toolspeed = 0.25 - -/obj/item/crowbar/power/suicide_act(mob/user) - user.visible_message("[user] is putting [user.p_their()] head in [src], it looks like [user.p_theyre()] trying to commit suicide!") - playsound(loc, 'sound/items/jaws_pry.ogg', 50, 1, -1) - return (BRUTELOSS) - -/obj/item/crowbar/power/attack_self(mob/user) - playsound(get_turf(user), 'sound/items/change_jaws.ogg', 50, 1) - var/obj/item/wirecutters/power/cutjaws = new /obj/item/wirecutters/power - to_chat(user, "You attach the cutting jaws to [src].") - qdel(src) - user.put_in_active_hand(cutjaws) - -#undef WELDER_FUEL_BURN_INTERVAL -======= +#define WELDER_FUEL_BURN_INTERVAL 13 + +/* Tools! + * Note: Multitools are /obj/item/device + * + * Contains: + * Wrench + * Screwdriver + * Wirecutters + * Welding Tool + * Crowbar + */ + +/* + * Wrench + */ +/obj/item/wrench + name = "wrench" + desc = "A wrench with common uses. Can be found in your hand." + icon = 'icons/obj/tools.dmi' + icon_state = "wrench" + lefthand_file = 'icons/mob/inhands/equipment/tools_lefthand.dmi' + righthand_file = 'icons/mob/inhands/equipment/tools_righthand.dmi' + flags_1 = CONDUCT_1 + slot_flags = SLOT_BELT + force = 5 + throwforce = 7 + w_class = WEIGHT_CLASS_SMALL + usesound = 'sound/items/ratchet.ogg' + materials = list(MAT_METAL=150) + origin_tech = "materials=1;engineering=1" + attack_verb = list("bashed", "battered", "bludgeoned", "whacked") + toolspeed = 1 + armor = list(melee = 0, bullet = 0, laser = 0, energy = 0, bomb = 0, bio = 0, rad = 0, fire = 50, acid = 30) + +/obj/item/wrench/suicide_act(mob/user) + user.visible_message("[user] is beating [user.p_them()]self to death with [src]! It looks like [user.p_theyre()] trying to commit suicide!") + playsound(loc, 'sound/weapons/genhit.ogg', 50, 1, -1) + return (BRUTELOSS) + +/obj/item/wrench/cyborg + name = "automatic wrench" + desc = "An advanced robotic wrench. Can be found in construction cyborgs." + toolspeed = 0.5 + +/obj/item/wrench/brass + name = "brass wrench" + desc = "A brass wrench. It's faintly warm to the touch." + resistance_flags = FIRE_PROOF | ACID_PROOF + icon_state = "wrench_brass" + toolspeed = 0.5 + +/obj/item/wrench/abductor + name = "alien wrench" + desc = "A polarized wrench. It causes anything placed between the jaws to turn." + icon = 'icons/obj/abductor.dmi' + icon_state = "wrench" + usesound = 'sound/effects/empulse.ogg' + toolspeed = 0.1 + origin_tech = "materials=5;engineering=5;abductor=3" + +/obj/item/wrench/power + name = "hand drill" + desc = "A simple powered hand drill. It's fitted with a bolt bit." + icon_state = "drill_bolt" + item_state = "drill" + lefthand_file = 'icons/mob/inhands/equipment/tools_lefthand.dmi' + righthand_file = 'icons/mob/inhands/equipment/tools_righthand.dmi' + usesound = 'sound/items/drill_use.ogg' + materials = list(MAT_METAL=150,MAT_SILVER=50,MAT_TITANIUM=25) + origin_tech = "materials=2;engineering=2" //done for balance reasons, making them high value for research, but harder to get + force = 8 //might or might not be too high, subject to change + w_class = WEIGHT_CLASS_SMALL + throwforce = 8 + attack_verb = list("drilled", "screwed", "jabbed") + toolspeed = 0.25 + +/obj/item/wrench/power/attack_self(mob/user) + playsound(get_turf(user),'sound/items/change_drill.ogg',50,1) + var/obj/item/wirecutters/power/s_drill = new /obj/item/screwdriver/power + to_chat(user, "You attach the screw driver bit to [src].") + qdel(src) + user.put_in_active_hand(s_drill) + +/obj/item/wrench/power/suicide_act(mob/user) + user.visible_message("[user] is pressing [src] against [user.p_their()] head! It looks like [user.p_theyre()] trying to commit suicide!") + return (BRUTELOSS) + +/obj/item/wrench/medical + name = "medical wrench" + desc = "A medical wrench with common(medical?) uses. Can be found in your hand." + icon_state = "wrench_medical" + force = 2 //MEDICAL + throwforce = 4 + origin_tech = "materials=1;engineering=1;biotech=3" + attack_verb = list("wrenched", "medicaled", "tapped", "jabbed", "whacked") + +/obj/item/wrench/medical/suicide_act(mob/living/user) + user.visible_message("[user] is praying to the medical wrench to take [user.p_their()] soul. It looks like [user.p_theyre()] trying to commit suicide!") + // TODO Make them glow with the power of the M E D I C A L W R E N C H + // during their ascension + + // Stun stops them from wandering off + user.Stun(100, ignore_canstun = TRUE) + playsound(loc, 'sound/effects/pray.ogg', 50, 1, -1) + + // Let the sound effect finish playing + sleep(20) + + if(!user) + return + + for(var/obj/item/W in user) + user.dropItemToGround(W) + + var/obj/item/wrench/medical/W = new /obj/item/wrench/medical(loc) + W.add_fingerprint(user) + W.desc += " For some reason, it reminds you of [user.name]." + + if(!user) + return + + user.dust() + + return OXYLOSS + +/* + * Screwdriver + */ +/obj/item/screwdriver + name = "screwdriver" + desc = "You can be totally screwy with this." + icon = 'icons/obj/tools.dmi' + icon_state = "screwdriver" + item_state = "screwdriver" + lefthand_file = 'icons/mob/inhands/equipment/tools_lefthand.dmi' + righthand_file = 'icons/mob/inhands/equipment/tools_righthand.dmi' + flags_1 = CONDUCT_1 + slot_flags = SLOT_BELT + force = 5 + w_class = WEIGHT_CLASS_TINY + throwforce = 5 + throw_speed = 3 + throw_range = 5 + materials = list(MAT_METAL=75) + attack_verb = list("stabbed") + hitsound = 'sound/weapons/bladeslice.ogg' + usesound = 'sound/items/screwdriver.ogg' + toolspeed = 1 + armor = list(melee = 0, bullet = 0, laser = 0, energy = 0, bomb = 0, bio = 0, rad = 0, fire = 50, acid = 30) + var/random_color = TRUE //if the screwdriver uses random coloring + var/static/list/screwdriver_colors = list(\ + "blue" = rgb(24, 97, 213), \ + "red" = rgb(149, 23, 16), \ + "pink" = rgb(213, 24, 141), \ + "brown" = rgb(160, 82, 18), \ + "green" = rgb(14, 127, 27), \ + "cyan" = rgb(24, 162, 213), \ + "yellow" = rgb(213, 140, 24), \ + ) + +/obj/item/screwdriver/suicide_act(mob/user) + user.visible_message("[user] is stabbing [src] into [user.p_their()] [pick("temple", "heart")]! It looks like [user.p_theyre()] trying to commit suicide!") + return(BRUTELOSS) + +/obj/item/screwdriver/Initialize() + . = ..() + if(random_color) //random colors! + var/our_color = pick(screwdriver_colors) + add_atom_colour(screwdriver_colors[our_color], FIXED_COLOUR_PRIORITY) + update_icon() + if(prob(75)) + pixel_y = rand(0, 16) + +/obj/item/screwdriver/update_icon() + if(!random_color) //icon override + return + cut_overlays() + var/mutable_appearance/base_overlay = mutable_appearance(icon, "screwdriver_screwybits") + base_overlay.appearance_flags = RESET_COLOR + add_overlay(base_overlay) + +/obj/item/screwdriver/worn_overlays(isinhands = FALSE, icon_file) + . = list() + if(isinhands && random_color) + var/mutable_appearance/M = mutable_appearance(icon_file, "screwdriver_head") + M.appearance_flags = RESET_COLOR + . += M + +/obj/item/screwdriver/get_belt_overlay() + if(random_color) + var/mutable_appearance/body = mutable_appearance('icons/obj/clothing/belt_overlays.dmi', "screwdriver") + var/mutable_appearance/head = mutable_appearance('icons/obj/clothing/belt_overlays.dmi', "screwdriver_head") + body.color = color + head.overlays += body + return head + else + return mutable_appearance('icons/obj/clothing/belt_overlays.dmi', icon_state) + +/obj/item/screwdriver/attack(mob/living/carbon/M, mob/living/carbon/user) + if(!istype(M)) + return ..() + if(user.zone_selected != "eyes" && user.zone_selected != "head") + return ..() + if(user.disabilities & CLUMSY && prob(50)) + M = user + return eyestab(M,user) + +/obj/item/screwdriver/brass + name = "brass screwdriver" + desc = "A screwdriver made of brass. The handle feels freezing cold." + resistance_flags = FIRE_PROOF | ACID_PROOF + icon_state = "screwdriver_brass" + item_state = "screwdriver_brass" + toolspeed = 0.5 + random_color = FALSE + +/obj/item/screwdriver/abductor + name = "alien screwdriver" + desc = "An ultrasonic screwdriver." + icon = 'icons/obj/abductor.dmi' + icon_state = "screwdriver_a" + item_state = "screwdriver_nuke" + usesound = 'sound/items/pshoom.ogg' + toolspeed = 0.1 + random_color = FALSE + +/obj/item/screwdriver/power + name = "hand drill" + desc = "A simple powered hand drill. It's fitted with a screw bit." + icon_state = "drill_screw" + item_state = "drill" + lefthand_file = 'icons/mob/inhands/equipment/tools_lefthand.dmi' + righthand_file = 'icons/mob/inhands/equipment/tools_righthand.dmi' + materials = list(MAT_METAL=150,MAT_SILVER=50,MAT_TITANIUM=25) + origin_tech = "materials=2;engineering=2" //done for balance reasons, making them high value for research, but harder to get + force = 8 //might or might not be too high, subject to change + w_class = WEIGHT_CLASS_SMALL + throwforce = 8 + throw_speed = 2 + throw_range = 3//it's heavier than a screw driver/wrench, so it does more damage, but can't be thrown as far + attack_verb = list("drilled", "screwed", "jabbed","whacked") + hitsound = 'sound/items/drill_hit.ogg' + usesound = 'sound/items/drill_use.ogg' + toolspeed = 0.25 + random_color = FALSE + +/obj/item/screwdriver/power/suicide_act(mob/user) + user.visible_message("[user] is putting [src] to [user.p_their()] temple. It looks like [user.p_theyre()] trying to commit suicide!") + return(BRUTELOSS) + +/obj/item/screwdriver/power/attack_self(mob/user) + playsound(get_turf(user),'sound/items/change_drill.ogg',50,1) + var/obj/item/wrench/power/b_drill = new /obj/item/wrench/power + to_chat(user, "You attach the bolt driver bit to [src].") + qdel(src) + user.put_in_active_hand(b_drill) + +/obj/item/screwdriver/cyborg + name = "powered screwdriver" + desc = "An electrical screwdriver, designed to be both precise and quick." + usesound = 'sound/items/drill_use.ogg' + toolspeed = 0.5 + +/* + * Wirecutters + */ +/obj/item/wirecutters + name = "wirecutters" + desc = "This cuts wires." + icon = 'icons/obj/tools.dmi' + icon_state = null + lefthand_file = 'icons/mob/inhands/equipment/tools_lefthand.dmi' + righthand_file = 'icons/mob/inhands/equipment/tools_righthand.dmi' + flags_1 = CONDUCT_1 + slot_flags = SLOT_BELT + force = 6 + throw_speed = 3 + throw_range = 7 + w_class = WEIGHT_CLASS_SMALL + materials = list(MAT_METAL=80) + attack_verb = list("pinched", "nipped") + hitsound = 'sound/items/wirecutter.ogg' + usesound = 'sound/items/wirecutter.ogg' + origin_tech = "materials=1;engineering=1" + toolspeed = 1 + armor = list(melee = 0, bullet = 0, laser = 0, energy = 0, bomb = 0, bio = 0, rad = 0, fire = 50, acid = 30) + + +/obj/item/wirecutters/New(loc, var/param_color = null) + ..() + if(!icon_state) + if(!param_color) + param_color = pick("yellow","red") + icon_state = "cutters_[param_color]" + +/obj/item/wirecutters/attack(mob/living/carbon/C, mob/user) + if(istype(C) && C.handcuffed && istype(C.handcuffed, /obj/item/restraints/handcuffs/cable)) + user.visible_message("[user] cuts [C]'s restraints with [src]!") + qdel(C.handcuffed) + C.handcuffed = null + if(C.buckled && C.buckled.buckle_requires_restraints) + C.buckled.unbuckle_mob(C) + C.update_handcuffed() + return + else + ..() + +/obj/item/wirecutters/suicide_act(mob/user) + user.visible_message("[user] is cutting at [user.p_their()] arteries with [src]! It looks like [user.p_theyre()] trying to commit suicide!") + playsound(loc, usesound, 50, 1, -1) + return (BRUTELOSS) + +/obj/item/wirecutters/brass + name = "brass wirecutters" + desc = "A pair of wirecutters made of brass. The handle feels freezing cold to the touch." + resistance_flags = FIRE_PROOF | ACID_PROOF + icon_state = "cutters_brass" + toolspeed = 0.5 + +/obj/item/wirecutters/abductor + name = "alien wirecutters" + desc = "Extremely sharp wirecutters, made out of a silvery-green metal." + icon = 'icons/obj/abductor.dmi' + icon_state = "cutters" + toolspeed = 0.1 + origin_tech = "materials=5;engineering=4;abductor=3" + +/obj/item/wirecutters/cyborg + name = "wirecutters" + desc = "This cuts wires." + toolspeed = 0.5 + +/obj/item/wirecutters/power + name = "jaws of life" + desc = "A set of jaws of life, compressed through the magic of science. It's fitted with a cutting head." + icon_state = "jaws_cutter" + item_state = "jawsoflife" + origin_tech = "materials=2;engineering=2" + materials = list(MAT_METAL=150,MAT_SILVER=50,MAT_TITANIUM=25) + usesound = 'sound/items/jaws_cut.ogg' + toolspeed = 0.25 + +/obj/item/wirecutters/power/suicide_act(mob/user) + user.visible_message("[user] is wrapping \the [src] around [user.p_their()] neck. It looks like [user.p_theyre()] trying to rip [user.p_their()] head off!") + playsound(loc, 'sound/items/jaws_cut.ogg', 50, 1, -1) + if(iscarbon(user)) + var/mob/living/carbon/C = user + var/obj/item/bodypart/BP = C.get_bodypart("head") + if(BP) + BP.drop_limb() + playsound(loc,pick('sound/misc/desceration-01.ogg','sound/misc/desceration-02.ogg','sound/misc/desceration-01.ogg') ,50, 1, -1) + return (BRUTELOSS) + +/obj/item/wirecutters/power/attack_self(mob/user) + playsound(get_turf(user), 'sound/items/change_jaws.ogg', 50, 1) + var/obj/item/crowbar/power/pryjaws = new /obj/item/crowbar/power + to_chat(user, "You attach the pry jaws to [src].") + qdel(src) + user.put_in_active_hand(pryjaws) +/* + * Welding Tool + */ +/obj/item/weldingtool + name = "welding tool" + desc = "A standard edition welder provided by NanoTrasen." + icon = 'icons/obj/tools.dmi' + icon_state = "welder" + item_state = "welder" + lefthand_file = 'icons/mob/inhands/equipment/tools_lefthand.dmi' + righthand_file = 'icons/mob/inhands/equipment/tools_righthand.dmi' + flags_1 = CONDUCT_1 + slot_flags = SLOT_BELT + force = 3 + throwforce = 5 + hitsound = "swing_hit" + usesound = 'sound/items/welder.ogg' + var/acti_sound = 'sound/items/welderactivate.ogg' + var/deac_sound = 'sound/items/welderdeactivate.ogg' + throw_speed = 3 + throw_range = 5 + w_class = WEIGHT_CLASS_SMALL + armor = list(melee = 0, bullet = 0, laser = 0, energy = 0, bomb = 0, bio = 0, rad = 0, fire = 100, acid = 30) + resistance_flags = FIRE_PROOF + + materials = list(MAT_METAL=70, MAT_GLASS=30) + origin_tech = "engineering=1;plasmatech=1" + var/welding = 0 //Whether or not the welding tool is off(0), on(1) or currently welding(2) + var/status = TRUE //Whether the welder is secured or unsecured (able to attach rods to it to make a flamethrower) + var/max_fuel = 20 //The max amount of fuel the welder can hold + var/change_icons = 1 + var/can_off_process = 0 + var/light_intensity = 2 //how powerful the emitted light is when used. + var/burned_fuel_for = 0 //when fuel was last removed + heat = 3800 + toolspeed = 1 + +/obj/item/weldingtool/Initialize() + . = ..() + create_reagents(max_fuel) + reagents.add_reagent("welding_fuel", max_fuel) + update_icon() + + +/obj/item/weldingtool/proc/update_torch() + if(welding) + add_overlay("[initial(icon_state)]-on") + item_state = "[initial(item_state)]1" + else + item_state = "[initial(item_state)]" + + +/obj/item/weldingtool/update_icon() + cut_overlays() + if(change_icons) + var/ratio = get_fuel() / max_fuel + ratio = Ceiling(ratio*4) * 25 + add_overlay("[initial(icon_state)][ratio]") + update_torch() + return + + +/obj/item/weldingtool/process() + switch(welding) + if(0) + force = 3 + damtype = "brute" + update_icon() + if(!can_off_process) + STOP_PROCESSING(SSobj, src) + return + //Welders left on now use up fuel, but lets not have them run out quite that fast + if(1) + force = 15 + damtype = "fire" + ++burned_fuel_for + if(burned_fuel_for >= WELDER_FUEL_BURN_INTERVAL) + remove_fuel(1) + update_icon() + + //This is to start fires. process() is only called if the welder is on. + open_flame() + + +/obj/item/weldingtool/suicide_act(mob/user) + user.visible_message("[user] welds [user.p_their()] every orifice closed! It looks like [user.p_theyre()] trying to commit suicide!") + return (FIRELOSS) + + +/obj/item/weldingtool/attackby(obj/item/I, mob/user, params) + if(istype(I, /obj/item/screwdriver)) + flamethrower_screwdriver(I, user) + else if(istype(I, /obj/item/stack/rods)) + flamethrower_rods(I, user) + else + return ..() + + +/obj/item/weldingtool/attack(mob/living/carbon/human/H, mob/user) + if(!istype(H)) + return ..() + + var/obj/item/bodypart/affecting = H.get_bodypart(check_zone(user.zone_selected)) + + if(affecting && affecting.status == BODYPART_ROBOTIC && user.a_intent != INTENT_HARM) + if(src.remove_fuel(1)) + playsound(loc, usesound, 50, 1) + if(user == H) + user.visible_message("[user] starts to fix some of the dents on [H]'s [affecting.name].", "You start fixing some of the dents on [H]'s [affecting.name].") + if(!do_mob(user, H, 50)) + return + item_heal_robotic(H, user, 15, 0) + else + return ..() + + +/obj/item/weldingtool/afterattack(atom/O, mob/user, proximity) + if(!proximity) return + + if(welding) + remove_fuel(1) + var/turf/location = get_turf(user) + location.hotspot_expose(700, 50, 1) + if(get_fuel() <= 0) + set_light(0) + + if(isliving(O)) + var/mob/living/L = O + if(L.IgniteMob()) + message_admins("[key_name_admin(user)] set [key_name_admin(L)] on fire") + log_game("[key_name(user)] set [key_name(L)] on fire") + + +/obj/item/weldingtool/attack_self(mob/user) + switched_on(user) + if(welding) + set_light(light_intensity) + + update_icon() + + +//Returns the amount of fuel in the welder +/obj/item/weldingtool/proc/get_fuel() + return reagents.get_reagent_amount("welding_fuel") + + +//Removes fuel from the welding tool. If a mob is passed, it will try to flash the mob's eyes. This should probably be renamed to use() +/obj/item/weldingtool/proc/remove_fuel(amount = 1, mob/living/M = null) + if(!welding || !check_fuel()) + return 0 + if(amount) + burned_fuel_for = 0 + if(get_fuel() >= amount) + reagents.remove_reagent("welding_fuel", amount) + check_fuel() + if(M) + M.flash_act(light_intensity) + return TRUE + else + if(M) + to_chat(M, "You need more welding fuel to complete this task!") + return FALSE + + +//Turns off the welder if there is no more fuel (does this really need to be its own proc?) +/obj/item/weldingtool/proc/check_fuel(mob/user) + if(get_fuel() <= 0 && welding) + switched_on(user) + update_icon() + //mob icon update + if(ismob(loc)) + var/mob/M = loc + M.update_inv_hands(0) + + return 0 + return 1 + +//Switches the welder on +/obj/item/weldingtool/proc/switched_on(mob/user) + if(!status) + to_chat(user, "[src] can't be turned on while unsecured!") + return + welding = !welding + if(welding) + if(get_fuel() >= 1) + to_chat(user, "You switch [src] on.") + playsound(loc, acti_sound, 50, 1) + force = 15 + damtype = "fire" + hitsound = 'sound/items/welder.ogg' + update_icon() + START_PROCESSING(SSobj, src) + else + to_chat(user, "You need more fuel!") + switched_off(user) + else + to_chat(user, "You switch [src] off.") + playsound(loc, deac_sound, 50, 1) + switched_off(user) + +//Switches the welder off +/obj/item/weldingtool/proc/switched_off(mob/user) + welding = 0 + set_light(0) + + force = 3 + damtype = "brute" + hitsound = "swing_hit" + update_icon() + + +/obj/item/weldingtool/examine(mob/user) + ..() + to_chat(user, "It contains [get_fuel()] unit\s of fuel out of [max_fuel].") + +/obj/item/weldingtool/is_hot() + return welding * heat + +//Returns whether or not the welding tool is currently on. +/obj/item/weldingtool/proc/isOn() + return welding + + +/obj/item/weldingtool/proc/flamethrower_screwdriver(obj/item/I, mob/user) + if(welding) + to_chat(user, "Turn it off first!") + return + status = !status + if(status) + to_chat(user, "You resecure [src].") + else + to_chat(user, "[src] can now be attached and modified.") + add_fingerprint(user) + +/obj/item/weldingtool/proc/flamethrower_rods(obj/item/I, mob/user) + if(!status) + var/obj/item/stack/rods/R = I + if (R.use(1)) + var/obj/item/flamethrower/F = new /obj/item/flamethrower(user.loc) + if(!remove_item_from_storage(F)) + user.transferItemToLoc(src, F, TRUE) + F.weldtool = src + add_fingerprint(user) + to_chat(user, "You add a rod to a welder, starting to build a flamethrower.") + user.put_in_hands(F) + else + to_chat(user, "You need one rod to start building a flamethrower!") + +/obj/item/weldingtool/ignition_effect(atom/A, mob/user) + if(welding && remove_fuel(1, user)) + . = "[user] casually lights [A] with [src], what a badass." + else + . = "" + +/obj/item/weldingtool/largetank + name = "industrial welding tool" + desc = "A slightly larger welder with a larger tank." + icon_state = "indwelder" + max_fuel = 40 + materials = list(MAT_GLASS=60) + origin_tech = "engineering=2;plasmatech=2" + +/obj/item/weldingtool/largetank/cyborg + name = "integrated welding tool" + desc = "An advanced welder designed to be used in robotic systems." + toolspeed = 0.5 + +/obj/item/weldingtool/largetank/flamethrower_screwdriver() + return + + +/obj/item/weldingtool/mini + name = "emergency welding tool" + desc = "A miniature welder used during emergencies." + icon_state = "miniwelder" + max_fuel = 10 + w_class = WEIGHT_CLASS_TINY + materials = list(MAT_METAL=30, MAT_GLASS=10) + change_icons = 0 + +/obj/item/weldingtool/mini/flamethrower_screwdriver() + return + +/obj/item/weldingtool/abductor + name = "alien welding tool" + desc = "An alien welding tool. Whatever fuel it uses, it never runs out." + icon = 'icons/obj/abductor.dmi' + icon_state = "welder" + toolspeed = 0.1 + light_intensity = 0 + change_icons = 0 + origin_tech = "plasmatech=5;engineering=5;abductor=3" + +/obj/item/weldingtool/abductor/process() + if(get_fuel() <= max_fuel) + reagents.add_reagent("welding_fuel", 1) + ..() + +/obj/item/weldingtool/hugetank + name = "upgraded industrial welding tool" + desc = "An upgraded welder based of the industrial welder." + icon_state = "upindwelder" + item_state = "upindwelder" + max_fuel = 80 + materials = list(MAT_METAL=70, MAT_GLASS=120) + origin_tech = "engineering=3;plasmatech=2" + +/obj/item/weldingtool/experimental + name = "experimental welding tool" + desc = "An experimental welder capable of self-fuel generation and less harmful to the eyes." + icon_state = "exwelder" + item_state = "exwelder" + max_fuel = 40 + materials = list(MAT_METAL=70, MAT_GLASS=120) + origin_tech = "materials=4;engineering=4;bluespace=3;plasmatech=4" + var/last_gen = 0 + change_icons = 0 + can_off_process = 1 + light_intensity = 1 + toolspeed = 0.5 + var/nextrefueltick = 0 + +/obj/item/weldingtool/experimental/brass + name = "brass welding tool" + desc = "A brass welder that seems to constantly refuel itself. It is faintly warm to the touch." + resistance_flags = FIRE_PROOF | ACID_PROOF + icon_state = "brasswelder" + item_state = "brasswelder" + + +/obj/item/weldingtool/experimental/process() + ..() + if(get_fuel() < max_fuel && nextrefueltick < world.time) + nextrefueltick = world.time + 10 + reagents.add_reagent("welding_fuel", 1) + + +/* + * Crowbar + */ + +/obj/item/crowbar + name = "pocket crowbar" + desc = "A small crowbar. This handy tool is useful for lots of things, such as prying floor tiles or opening unpowered doors." + icon = 'icons/obj/tools.dmi' + icon_state = "crowbar" + lefthand_file = 'icons/mob/inhands/equipment/tools_lefthand.dmi' + righthand_file = 'icons/mob/inhands/equipment/tools_righthand.dmi' + usesound = 'sound/items/crowbar.ogg' + flags_1 = CONDUCT_1 + slot_flags = SLOT_BELT + force = 5 + throwforce = 7 + w_class = WEIGHT_CLASS_SMALL + materials = list(MAT_METAL=50) + origin_tech = "engineering=1;combat=1" + attack_verb = list("attacked", "bashed", "battered", "bludgeoned", "whacked") + toolspeed = 1 + armor = list(melee = 0, bullet = 0, laser = 0, energy = 0, bomb = 0, bio = 0, rad = 0, fire = 50, acid = 30) + +/obj/item/crowbar/suicide_act(mob/user) + user.visible_message("[user] is beating [user.p_them()]self to death with [src]! It looks like [user.p_theyre()] trying to commit suicide!") + playsound(loc, 'sound/weapons/genhit.ogg', 50, 1, -1) + return (BRUTELOSS) + +/obj/item/crowbar/red + icon_state = "crowbar_red" + force = 8 + +/obj/item/crowbar/brass + name = "brass crowbar" + desc = "A brass crowbar. It feels faintly warm to the touch." + resistance_flags = FIRE_PROOF | ACID_PROOF + icon_state = "crowbar_brass" + toolspeed = 0.5 + +/obj/item/crowbar/abductor + name = "alien crowbar" + desc = "A hard-light crowbar. It appears to pry by itself, without any effort required." + icon = 'icons/obj/abductor.dmi' + usesound = 'sound/weapons/sonic_jackhammer.ogg' + icon_state = "crowbar" + toolspeed = 0.1 + origin_tech = "combat=4;engineering=4;abductor=3" + +/obj/item/crowbar/large + name = "crowbar" + desc = "It's a big crowbar. It doesn't fit in your pockets, because it's big." + force = 12 + w_class = WEIGHT_CLASS_NORMAL + throw_speed = 3 + throw_range = 3 + materials = list(MAT_METAL=70) + icon_state = "crowbar_large" + item_state = "crowbar" + toolspeed = 0.5 + +/obj/item/crowbar/cyborg + name = "hydraulic crowbar" + desc = "A hydraulic prying tool, compact but powerful. Designed to replace crowbar in construction cyborgs." + usesound = 'sound/items/jaws_pry.ogg' + force = 10 + toolspeed = 0.5 + +/obj/item/crowbar/power + name = "jaws of life" + desc = "A set of jaws of life, compressed through the magic of science. It's fitted with a prying head." + icon_state = "jaws_pry" + item_state = "jawsoflife" + lefthand_file = 'icons/mob/inhands/equipment/tools_lefthand.dmi' + righthand_file = 'icons/mob/inhands/equipment/tools_righthand.dmi' + materials = list(MAT_METAL=150,MAT_SILVER=50,MAT_TITANIUM=25) + origin_tech = "materials=2;engineering=2" + usesound = 'sound/items/jaws_pry.ogg' + force = 15 + toolspeed = 0.25 + +/obj/item/crowbar/power/suicide_act(mob/user) + user.visible_message("[user] is putting [user.p_their()] head in [src], it looks like [user.p_theyre()] trying to commit suicide!") + playsound(loc, 'sound/items/jaws_pry.ogg', 50, 1, -1) + return (BRUTELOSS) + +/obj/item/crowbar/power/attack_self(mob/user) + playsound(get_turf(user), 'sound/items/change_jaws.ogg', 50, 1) + var/obj/item/wirecutters/power/cutjaws = new /obj/item/wirecutters/power + to_chat(user, "You attach the cutting jaws to [src].") + qdel(src) + user.put_in_active_hand(cutjaws) + +#undef WELDER_FUEL_BURN_INTERVAL #define WELDER_FUEL_BURN_INTERVAL 13 /* Tools! @@ -1580,4 +1578,3 @@ user.put_in_active_hand(cutjaws) #undef WELDER_FUEL_BURN_INTERVAL ->>>>>>> 2240756... Gets rid of manual overlay manipulation (#30454) From 3dbfac920ae6b0360a49d93e7ecc180c8faa277a Mon Sep 17 00:00:00 2001 From: LetterJay Date: Sun, 10 Sep 2017 11:48:28 -0500 Subject: [PATCH 23/74] Update weaponry.dm --- code/game/objects/items/weaponry.dm | 1175 +++++++++++++-------------- 1 file changed, 586 insertions(+), 589 deletions(-) diff --git a/code/game/objects/items/weaponry.dm b/code/game/objects/items/weaponry.dm index fe9c9485cd..443518ec0a 100644 --- a/code/game/objects/items/weaponry.dm +++ b/code/game/objects/items/weaponry.dm @@ -1,596 +1,594 @@ -/obj/item/banhammer - desc = "A banhammer" - name = "banhammer" - icon = 'icons/obj/items_and_weapons.dmi' - icon_state = "toyhammer" - slot_flags = SLOT_BELT - throwforce = 0 - w_class = WEIGHT_CLASS_TINY - throw_speed = 3 - throw_range = 7 - attack_verb = list("banned") - max_integrity = 200 - armor = list(melee = 0, bullet = 0, laser = 0, energy = 0, bomb = 0, bio = 0, rad = 0, fire = 100, acid = 70) - resistance_flags = FIRE_PROOF - -/obj/item/banhammer/suicide_act(mob/user) - user.visible_message("[user] is hitting [user.p_them()]self with [src]! It looks like [user.p_theyre()] trying to ban [user.p_them()]self from life.") - return (BRUTELOSS|FIRELOSS|TOXLOSS|OXYLOSS) - -/obj/item/banhammer/attack(mob/M, mob/user) +/obj/item/banhammer + desc = "A banhammer" + name = "banhammer" + icon = 'icons/obj/items_and_weapons.dmi' + icon_state = "toyhammer" + slot_flags = SLOT_BELT + throwforce = 0 + w_class = WEIGHT_CLASS_TINY + throw_speed = 3 + throw_range = 7 + attack_verb = list("banned") + max_integrity = 200 + armor = list(melee = 0, bullet = 0, laser = 0, energy = 0, bomb = 0, bio = 0, rad = 0, fire = 100, acid = 70) + resistance_flags = FIRE_PROOF + +/obj/item/banhammer/suicide_act(mob/user) + user.visible_message("[user] is hitting [user.p_them()]self with [src]! It looks like [user.p_theyre()] trying to ban [user.p_them()]self from life.") + return (BRUTELOSS|FIRELOSS|TOXLOSS|OXYLOSS) + +/obj/item/banhammer/attack(mob/M, mob/user) if(user.zone_selected == "head") M.visible_message("[user] are stroking the head of [M] with a bangammer", "[user] are stroking the head with a bangammer", "you hear a bangammer stroking a head"); else M.visible_message("[M] has been banned FOR NO REISIN by [user]", "You have been banned FOR NO REISIN by [user]", "you hear a banhammer banning someone") -<<<<<<< HEAD - playsound(loc, 'sound/effects/adminhelp.ogg', 15) //keep it at 15% volume so people don't jump out of their skin too much - -/obj/item/sord - name = "\improper SORD" - desc = "This thing is so unspeakably shitty you are having a hard time even holding it." - icon_state = "sord" - item_state = "sord" - lefthand_file = 'icons/mob/inhands/weapons/swords_lefthand.dmi' - righthand_file = 'icons/mob/inhands/weapons/swords_righthand.dmi' - slot_flags = SLOT_BELT - force = 2 - throwforce = 1 - w_class = WEIGHT_CLASS_NORMAL - hitsound = 'sound/weapons/bladeslice.ogg' - attack_verb = list("attacked", "slashed", "stabbed", "sliced", "torn", "ripped", "diced", "cut") - -/obj/item/sord/suicide_act(mob/user) - user.visible_message("[user] is trying to impale [user.p_them()]self with [src]! It might be a suicide attempt if it weren't so shitty.", \ - "You try to impale yourself with [src], but it's USELESS...") - return SHAME - -/obj/item/claymore - name = "claymore" - desc = "What are you standing around staring at this for? Get to killing!" - icon_state = "claymore" - item_state = "claymore" - lefthand_file = 'icons/mob/inhands/weapons/swords_lefthand.dmi' - righthand_file = 'icons/mob/inhands/weapons/swords_righthand.dmi' - hitsound = 'sound/weapons/bladeslice.ogg' - flags_1 = CONDUCT_1 - slot_flags = SLOT_BELT | SLOT_BACK - force = 40 - throwforce = 10 - w_class = WEIGHT_CLASS_NORMAL - attack_verb = list("attacked", "slashed", "stabbed", "sliced", "torn", "ripped", "diced", "cut") - block_chance = 50 - sharpness = IS_SHARP - max_integrity = 200 - armor = list(melee = 0, bullet = 0, laser = 0, energy = 0, bomb = 0, bio = 0, rad = 0, fire = 100, acid = 50) - resistance_flags = FIRE_PROOF - -/obj/item/claymore/suicide_act(mob/user) - user.visible_message("[user] is falling on [src]! It looks like [user.p_theyre()] trying to commit suicide!") - return(BRUTELOSS) - -/obj/item/claymore/highlander //ALL COMMENTS MADE REGARDING THIS SWORD MUST BE MADE IN ALL CAPS - desc = "THERE CAN BE ONLY ONE, AND IT WILL BE YOU!!!\nActivate it in your hand to point to the nearest victim." - flags_1 = CONDUCT_1 | NODROP_1 | DROPDEL_1 - slot_flags = null - block_chance = 0 //RNG WON'T HELP YOU NOW, PANSY - luminosity = 3 - attack_verb = list("brutalized", "eviscerated", "disemboweled", "hacked", "carved", "cleaved") //ONLY THE MOST VISCERAL ATTACK VERBS - var/notches = 0 //HOW MANY PEOPLE HAVE BEEN SLAIN WITH THIS BLADE - var/obj/item/disk/nuclear/nuke_disk //OUR STORED NUKE DISK - -/obj/item/claymore/highlander/Initialize() - . = ..() - START_PROCESSING(SSobj, src) - -/obj/item/claymore/highlander/Destroy() - if(nuke_disk) - nuke_disk.forceMove(get_turf(src)) - nuke_disk.visible_message("The nuke disk is vulnerable!") - nuke_disk = null - STOP_PROCESSING(SSobj, src) - return ..() - -/obj/item/claymore/highlander/process() - if(ishuman(loc)) - var/mob/living/carbon/human/H = loc - loc.layer = LARGE_MOB_LAYER //NO HIDING BEHIND PLANTS FOR YOU, DICKWEED (HA GET IT, BECAUSE WEEDS ARE PLANTS) - H.bleedsuppress = TRUE //AND WE WON'T BLEED OUT LIKE COWARDS - else - if(!admin_spawned) - qdel(src) - - -/obj/item/claymore/highlander/pickup(mob/living/user) - to_chat(user, "The power of Scotland protects you! You are shielded from all stuns and knockdowns.") - user.add_stun_absorption("highlander", INFINITY, 1, " is protected by the power of Scotland!", "The power of Scotland absorbs the stun!", " is protected by the power of Scotland!") - user.status_flags += IGNORESLOWDOWN - -/obj/item/claymore/highlander/dropped(mob/living/user) - user.status_flags -= IGNORESLOWDOWN - qdel(src) //If this ever happens, it's because you lost an arm - -/obj/item/claymore/highlander/examine(mob/user) - ..() - to_chat(user, "It has [!notches ? "nothing" : "[notches] notches"] scratched into the blade.") - if(nuke_disk) - to_chat(user, "It's holding the nuke disk!") - -/obj/item/claymore/highlander/attack(mob/living/target, mob/living/user) - . = ..() - if(target && target.stat == DEAD && target.mind && target.mind.special_role == "highlander") - user.fully_heal() //STEAL THE LIFE OF OUR FALLEN FOES - add_notch(user) - target.visible_message("[target] crumbles to dust beneath [user]'s blows!", "As you fall, your body crumbles to dust!") - target.dust() - -/obj/item/claymore/highlander/attack_self(mob/living/user) - var/closest_victim - var/closest_distance = 255 - for(var/mob/living/carbon/human/H in GLOB.player_list - user) - if(H.client && H.mind.special_role == "highlander" && (!closest_victim || get_dist(user, closest_victim) < closest_distance)) - closest_victim = H - if(!closest_victim) - to_chat(user, "[src] thrums for a moment and falls dark. Perhaps there's nobody nearby.") - return - to_chat(user, "[src] thrums and points to the [dir2text(get_dir(user, closest_victim))].") - -/obj/item/claymore/highlander/IsReflect() - return 1 //YOU THINK YOUR PUNY LASERS CAN STOP ME? - -/obj/item/claymore/highlander/proc/add_notch(mob/living/user) //DYNAMIC CLAYMORE PROGRESSION SYSTEM - THIS IS THE FUTURE - notches++ - force++ - var/new_name = name - switch(notches) - if(1) - to_chat(user, "Your first kill - hopefully one of many. You scratch a notch into [src]'s blade.") - to_chat(user, "You feel your fallen foe's soul entering your blade, restoring your wounds!") - new_name = "notched claymore" - if(2) - to_chat(user, "Another falls before you. Another soul fuses with your own. Another notch in the blade.") - new_name = "double-notched claymore" - add_atom_colour(rgb(255, 235, 235), ADMIN_COLOUR_PRIORITY) - if(3) - to_chat(user, "You're beginning to relish the thrill of battle.") - new_name = "triple-notched claymore" - add_atom_colour(rgb(255, 215, 215), ADMIN_COLOUR_PRIORITY) - if(4) - to_chat(user, "You've lost count of how many you've killed.") - new_name = "many-notched claymore" - add_atom_colour(rgb(255, 195, 195), ADMIN_COLOUR_PRIORITY) - if(5) - to_chat(user, "Five voices now echo in your mind, cheering the slaughter.") - new_name = "battle-tested claymore" - add_atom_colour(rgb(255, 175, 175), ADMIN_COLOUR_PRIORITY) - if(6) - to_chat(user, "Is this what the vikings felt like? Visions of glory fill your head as you slay your sixth foe.") - new_name = "battle-scarred claymore" - add_atom_colour(rgb(255, 155, 155), ADMIN_COLOUR_PRIORITY) - if(7) - to_chat(user, "Kill. Butcher. Conquer.") - new_name = "vicious claymore" - add_atom_colour(rgb(255, 135, 135), ADMIN_COLOUR_PRIORITY) - if(8) - to_chat(user, "IT NEVER GETS OLD. THE SCREAMING. THE BLOOD AS IT SPRAYS ACROSS YOUR FACE.") - new_name = "bloodthirsty claymore" - add_atom_colour(rgb(255, 115, 115), ADMIN_COLOUR_PRIORITY) - if(9) - to_chat(user, "ANOTHER ONE FALLS TO YOUR BLOWS. ANOTHER WEAKLING UNFIT TO LIVE.") - new_name = "gore-stained claymore" - add_atom_colour(rgb(255, 95, 95), ADMIN_COLOUR_PRIORITY) - if(10) - user.visible_message("[user]'s eyes light up with a vengeful fire!", \ - "YOU FEEL THE POWER OF VALHALLA FLOWING THROUGH YOU! THERE CAN BE ONLY ONE!!!") - user.update_icons() - new_name = "GORE-DRENCHED CLAYMORE OF [pick("THE WHIMSICAL SLAUGHTER", "A THOUSAND SLAUGHTERED CATTLE", "GLORY AND VALHALLA", "ANNIHILATION", "OBLITERATION")]" - icon_state = "claymore_valhalla" - item_state = "cultblade" - remove_atom_colour(ADMIN_COLOUR_PRIORITY) - - name = new_name - playsound(user, 'sound/items/screwdriver2.ogg', 50, 1) - -/obj/item/katana - name = "katana" - desc = "Woefully underpowered in D20" - icon_state = "katana" - item_state = "katana" - lefthand_file = 'icons/mob/inhands/weapons/swords_lefthand.dmi' - righthand_file = 'icons/mob/inhands/weapons/swords_righthand.dmi' - flags_1 = CONDUCT_1 - slot_flags = SLOT_BELT | SLOT_BACK - force = 40 - throwforce = 10 - w_class = WEIGHT_CLASS_NORMAL - hitsound = 'sound/weapons/bladeslice.ogg' - attack_verb = list("attacked", "slashed", "stabbed", "sliced", "torn", "ripped", "diced", "cut") - block_chance = 50 - sharpness = IS_SHARP - max_integrity = 200 - armor = list(melee = 0, bullet = 0, laser = 0, energy = 0, bomb = 0, bio = 0, rad = 0, fire = 100, acid = 50) - resistance_flags = FIRE_PROOF - -/obj/item/katana/cursed - slot_flags = null - -/obj/item/katana/suicide_act(mob/user) - user.visible_message("[user] is slitting [user.p_their()] stomach open with [src]! It looks like [user.p_theyre()] trying to commit seppuku!") - return(BRUTELOSS) - -/obj/item/wirerod - name = "wired rod" - desc = "A rod with some wire wrapped around the top. It'd be easy to attach something to the top bit." - icon_state = "wiredrod" - item_state = "rods" - flags_1 = CONDUCT_1 - force = 9 - throwforce = 10 - w_class = WEIGHT_CLASS_NORMAL - materials = list(MAT_METAL=1150, MAT_GLASS=75) - attack_verb = list("hit", "bludgeoned", "whacked", "bonked") - -/obj/item/wirerod/attackby(obj/item/I, mob/user, params) - if(istype(I, /obj/item/shard)) - var/obj/item/twohanded/spear/S = new /obj/item/twohanded/spear - - remove_item_from_storage(user) - qdel(I) - qdel(src) - - user.put_in_hands(S) - to_chat(user, "You fasten the glass shard to the top of the rod with the cable.") - - else if(istype(I, /obj/item/device/assembly/igniter) && !(I.flags_1 & NODROP_1)) - var/obj/item/melee/baton/cattleprod/P = new /obj/item/melee/baton/cattleprod - - remove_item_from_storage(user) - - to_chat(user, "You fasten [I] to the top of the rod with the cable.") - - qdel(I) - qdel(src) - - user.put_in_hands(P) - else - return ..() - - -/obj/item/throwing_star - name = "throwing star" - desc = "An ancient weapon still used to this day due to it's ease of lodging itself into victim's body parts" - icon_state = "throwingstar" - item_state = "eshield0" - lefthand_file = 'icons/mob/inhands/equipment/shields_lefthand.dmi' - righthand_file = 'icons/mob/inhands/equipment/shields_righthand.dmi' - force = 2 - throwforce = 20 //This is never used on mobs since this has a 100% embed chance. - throw_speed = 4 - embedded_pain_multiplier = 4 - w_class = WEIGHT_CLASS_SMALL - embed_chance = 100 - embedded_fall_chance = 0 //Hahaha! - sharpness = IS_SHARP - materials = list(MAT_METAL=500, MAT_GLASS=500) - resistance_flags = FIRE_PROOF - - -/obj/item/switchblade - name = "switchblade" - icon_state = "switchblade" - lefthand_file = 'icons/mob/inhands/weapons/swords_lefthand.dmi' - righthand_file = 'icons/mob/inhands/weapons/swords_righthand.dmi' - desc = "A sharp, concealable, spring-loaded knife." - flags_1 = CONDUCT_1 - force = 3 - w_class = WEIGHT_CLASS_SMALL - throwforce = 5 - throw_speed = 3 - throw_range = 6 - materials = list(MAT_METAL=12000) - origin_tech = "engineering=3;combat=2" - hitsound = 'sound/weapons/genhit.ogg' - attack_verb = list("stubbed", "poked") - resistance_flags = FIRE_PROOF - var/extended = 0 - -/obj/item/switchblade/attack_self(mob/user) - extended = !extended - playsound(src.loc, 'sound/weapons/batonextend.ogg', 50, 1) - if(extended) - force = 20 - w_class = WEIGHT_CLASS_NORMAL - throwforce = 23 - icon_state = "switchblade_ext" - attack_verb = list("slashed", "stabbed", "sliced", "torn", "ripped", "diced", "cut") - hitsound = 'sound/weapons/bladeslice.ogg' - sharpness = IS_SHARP - else - force = 3 - w_class = WEIGHT_CLASS_SMALL - throwforce = 5 - icon_state = "switchblade" - attack_verb = list("stubbed", "poked") - hitsound = 'sound/weapons/genhit.ogg' - sharpness = IS_BLUNT - -/obj/item/switchblade/suicide_act(mob/user) - user.visible_message("[user] is slitting [user.p_their()] own throat with [src]! It looks like [user.p_theyre()] trying to commit suicide!") - return (BRUTELOSS) - -/obj/item/phone - name = "red phone" - desc = "Should anything ever go wrong..." - icon = 'icons/obj/items_and_weapons.dmi' - icon_state = "red_phone" - force = 3 - throwforce = 2 - throw_speed = 3 - throw_range = 4 - w_class = WEIGHT_CLASS_SMALL - attack_verb = list("called", "rang") - hitsound = 'sound/weapons/ring.ogg' - -/obj/item/phone/suicide_act(mob/user) - if(locate(/obj/structure/chair/stool) in user.loc) - user.visible_message("[user] begins to tie a noose with [src]'s cord! It looks like [user.p_theyre()] trying to commit suicide!") - else - user.visible_message("[user] is strangling [user.p_them()]self with [src]'s cord! It looks like [user.p_theyre()] trying to commit suicide!") - return(OXYLOSS) - -/obj/item/cane - name = "cane" - desc = "A cane used by a true gentleman. Or a clown." - icon = 'icons/obj/items_and_weapons.dmi' - icon_state = "cane" - item_state = "stick" - lefthand_file = 'icons/mob/inhands/weapons/melee_lefthand.dmi' - righthand_file = 'icons/mob/inhands/weapons/melee_righthand.dmi' - force = 5 - throwforce = 5 - w_class = WEIGHT_CLASS_SMALL - materials = list(MAT_METAL=50) - attack_verb = list("bludgeoned", "whacked", "disciplined", "thrashed") - -/obj/item/staff - name = "wizard staff" - desc = "Apparently a staff used by the wizard." - icon = 'icons/obj/wizard.dmi' - icon_state = "staff" - lefthand_file = 'icons/mob/inhands/weapons/staves_lefthand.dmi' - righthand_file = 'icons/mob/inhands/weapons/staves_righthand.dmi' - force = 3 - throwforce = 5 - throw_speed = 2 - throw_range = 5 - w_class = WEIGHT_CLASS_SMALL - armour_penetration = 100 - attack_verb = list("bludgeoned", "whacked", "disciplined") - resistance_flags = FLAMMABLE - -/obj/item/staff/broom - name = "broom" - desc = "Used for sweeping, and flying into the night while cackling. Black cat not included." - icon = 'icons/obj/wizard.dmi' - icon_state = "broom" - resistance_flags = FLAMMABLE - -/obj/item/staff/stick - name = "stick" - desc = "A great tool to drag someone else's drinks across the bar." - icon = 'icons/obj/items_and_weapons.dmi' - icon_state = "stick" - item_state = "stick" - lefthand_file = 'icons/mob/inhands/weapons/melee_lefthand.dmi' - righthand_file = 'icons/mob/inhands/weapons/melee_righthand.dmi' - force = 3 - throwforce = 5 - throw_speed = 2 - throw_range = 5 - w_class = WEIGHT_CLASS_SMALL - -/obj/item/ectoplasm - name = "ectoplasm" - desc = "spooky" - gender = PLURAL - icon = 'icons/obj/wizard.dmi' - icon_state = "ectoplasm" - -/obj/item/ectoplasm/suicide_act(mob/user) - user.visible_message("[user] is inhaling [src]! It looks like [user.p_theyre()] trying to visit the astral plane.") - return (OXYLOSS) - -/obj/item/mounted_chainsaw - name = "mounted chainsaw" - desc = "A chainsaw that has replaced your arm." - icon_state = "chainsaw_on" - item_state = "mounted_chainsaw" - lefthand_file = 'icons/mob/inhands/weapons/chainsaw_lefthand.dmi' - righthand_file = 'icons/mob/inhands/weapons/chainsaw_righthand.dmi' - flags_1 = NODROP_1 | ABSTRACT_1 | DROPDEL_1 - w_class = WEIGHT_CLASS_HUGE - force = 21 - throwforce = 0 - throw_range = 0 - throw_speed = 0 - sharpness = IS_SHARP - attack_verb = list("sawed", "torn", "cut", "chopped", "diced") - hitsound = 'sound/weapons/chainsawhit.ogg' - -/obj/item/mounted_chainsaw/Destroy() - var/obj/item/bodypart/part - new /obj/item/twohanded/required/chainsaw(get_turf(src)) - if(iscarbon(loc)) - var/mob/living/carbon/holder = loc - var/index = holder.get_held_index_of_item(src) - if(index) - part = holder.hand_bodyparts[index] - . = ..() - if(part) - part.drop_limb() - -/obj/item/statuebust - name = "bust" - desc = "A priceless ancient marble bust, the kind that belongs in a museum." //or you can hit people with it - icon = 'icons/obj/statue.dmi' - icon_state = "bust" - force = 15 - throwforce = 10 - throw_speed = 5 - throw_range = 2 - attack_verb = list("busted") - -/obj/item/tailclub - name = "tail club" - desc = "For the beating to death of lizards with their own tails." - icon_state = "tailclub" - force = 14 - throwforce = 1 // why are you throwing a club do you even weapon - throw_speed = 1 - throw_range = 1 - attack_verb = list("clubbed", "bludgeoned") - -/obj/item/melee/chainofcommand/tailwhip - name = "liz o' nine tails" - desc = "A whip fashioned from the severed tails of lizards." - icon_state = "tailwhip" - origin_tech = "engineering=3;combat=3;biotech=3" - needs_permit = 0 - -/obj/item/melee/chainofcommand/tailwhip/kitty - name = "cat o' nine tails" - desc = "A whip fashioned from the severed tails of cats." - icon_state = "catwhip" - -/obj/item/melee/skateboard - name = "skateboard" - desc = "A skateboard. It can be placed on its wheels and ridden, or used as a strong weapon." - icon_state = "skateboard" - item_state = "skateboard" - force = 12 - throwforce = 4 - w_class = WEIGHT_CLASS_HUGE - attack_verb = list("smacked", "whacked", "slammed", "smashed") - -/obj/item/melee/skateboard/attack_self(mob/user) - new /obj/vehicle/scooter/skateboard(get_turf(user)) - qdel(src) - -/obj/item/melee/baseball_bat - name = "baseball bat" - desc = "There ain't a skull in the league that can withstand a swatter." - icon = 'icons/obj/items_and_weapons.dmi' - icon_state = "baseball_bat" - item_state = "baseball_bat" - lefthand_file = 'icons/mob/inhands/weapons/melee_lefthand.dmi' - righthand_file = 'icons/mob/inhands/weapons/melee_righthand.dmi' - force = 10 - throwforce = 12 - attack_verb = list("beat", "smacked") - w_class = WEIGHT_CLASS_HUGE - var/homerun_ready = 0 - var/homerun_able = 0 - -/obj/item/melee/baseball_bat/homerun - name = "home run bat" - desc = "This thing looks dangerous... Dangerously good at baseball, that is." - homerun_able = 1 - -/obj/item/melee/baseball_bat/attack_self(mob/user) - if(!homerun_able) - ..() - return - if(homerun_ready) - to_chat(user, "You're already ready to do a home run!") - ..() - return - to_chat(user, "You begin gathering strength...") - playsound(get_turf(src), 'sound/magic/lightning_chargeup.ogg', 65, 1) - if(do_after(user, 90, target = src)) - to_chat(user, "You gather power! Time for a home run!") - homerun_ready = 1 - ..() - -/obj/item/melee/baseball_bat/attack(mob/living/target, mob/living/user) - . = ..() - var/atom/throw_target = get_edge_target_turf(target, user.dir) - if(homerun_ready) - user.visible_message("It's a home run!") - target.throw_at(throw_target, rand(8,10), 14, user) - target.ex_act(EXPLODE_HEAVY) - playsound(get_turf(src), 'sound/weapons/homerun.ogg', 100, 1) - homerun_ready = 0 - return - else if(!target.anchored) - target.throw_at(throw_target, rand(1,2), 7, user) - -/obj/item/melee/baseball_bat/ablative - name = "metal baseball bat" - desc = "This bat is made of highly reflective, highly armored material." - icon_state = "baseball_bat_metal" - item_state = "baseball_bat_metal" - force = 12 - throwforce = 15 - -/obj/item/melee/baseball_bat/ablative/IsReflect()//some day this will reflect thrown items instead of lasers - var/picksound = rand(1,2) - var/turf = get_turf(src) - if(picksound == 1) - playsound(turf, 'sound/weapons/effects/batreflect1.ogg', 50, 1) - if(picksound == 2) - playsound(turf, 'sound/weapons/effects/batreflect2.ogg', 50, 1) - return 1 - -/obj/item/melee/flyswatter - name = "flyswatter" - desc = "Useful for killing insects of all sizes." - icon = 'icons/obj/items_and_weapons.dmi' - icon_state = "flyswatter" - item_state = "flyswatter" - lefthand_file = 'icons/mob/inhands/weapons/melee_lefthand.dmi' - righthand_file = 'icons/mob/inhands/weapons/melee_righthand.dmi' - force = 1 - throwforce = 1 - attack_verb = list("swatted", "smacked") - hitsound = 'sound/effects/snap.ogg' - w_class = WEIGHT_CLASS_SMALL - //Things in this list will be instantly splatted. Flyman weakness is handled in the flyman species weakness proc. - var/list/strong_against - -/obj/item/melee/flyswatter/Initialize() - . = ..() - strong_against = typecacheof(list( - /mob/living/simple_animal/hostile/poison/bees/, - /mob/living/simple_animal/butterfly, - /mob/living/simple_animal/cockroach, - /obj/item/queen_bee - )) - - -/obj/item/melee/flyswatter/afterattack(atom/target, mob/user, proximity_flag) - if(proximity_flag) - if(is_type_in_typecache(target, strong_against)) - new /obj/effect/decal/cleanable/deadcockroach(get_turf(target)) - to_chat(user, "You easily splat the [target].") - if(istype(target, /mob/living/)) - var/mob/living/bug = target - bug.death(1) - else - qdel(target) - -/obj/item/circlegame - name = "circled hand" - desc = "If somebody looks at this while it's below your waist, you get to bop them." - icon_state = "madeyoulook" - force = 0 - throwforce = 0 - flags_1 = DROPDEL_1 | ABSTRACT_1 - attack_verb = list("bopped") - -/obj/item/proc/can_trigger_gun(mob/living/user) - if(!user.can_use_guns(src)) - return FALSE -======= + playsound(loc, 'sound/effects/adminhelp.ogg', 15) //keep it at 15% volume so people don't jump out of their skin too much + +/obj/item/sord + name = "\improper SORD" + desc = "This thing is so unspeakably shitty you are having a hard time even holding it." + icon_state = "sord" + item_state = "sord" + lefthand_file = 'icons/mob/inhands/weapons/swords_lefthand.dmi' + righthand_file = 'icons/mob/inhands/weapons/swords_righthand.dmi' + slot_flags = SLOT_BELT + force = 2 + throwforce = 1 + w_class = WEIGHT_CLASS_NORMAL + hitsound = 'sound/weapons/bladeslice.ogg' + attack_verb = list("attacked", "slashed", "stabbed", "sliced", "torn", "ripped", "diced", "cut") + +/obj/item/sord/suicide_act(mob/user) + user.visible_message("[user] is trying to impale [user.p_them()]self with [src]! It might be a suicide attempt if it weren't so shitty.", \ + "You try to impale yourself with [src], but it's USELESS...") + return SHAME + +/obj/item/claymore + name = "claymore" + desc = "What are you standing around staring at this for? Get to killing!" + icon_state = "claymore" + item_state = "claymore" + lefthand_file = 'icons/mob/inhands/weapons/swords_lefthand.dmi' + righthand_file = 'icons/mob/inhands/weapons/swords_righthand.dmi' + hitsound = 'sound/weapons/bladeslice.ogg' + flags_1 = CONDUCT_1 + slot_flags = SLOT_BELT | SLOT_BACK + force = 40 + throwforce = 10 + w_class = WEIGHT_CLASS_NORMAL + attack_verb = list("attacked", "slashed", "stabbed", "sliced", "torn", "ripped", "diced", "cut") + block_chance = 50 + sharpness = IS_SHARP + max_integrity = 200 + armor = list(melee = 0, bullet = 0, laser = 0, energy = 0, bomb = 0, bio = 0, rad = 0, fire = 100, acid = 50) + resistance_flags = FIRE_PROOF + +/obj/item/claymore/suicide_act(mob/user) + user.visible_message("[user] is falling on [src]! It looks like [user.p_theyre()] trying to commit suicide!") + return(BRUTELOSS) + +/obj/item/claymore/highlander //ALL COMMENTS MADE REGARDING THIS SWORD MUST BE MADE IN ALL CAPS + desc = "THERE CAN BE ONLY ONE, AND IT WILL BE YOU!!!\nActivate it in your hand to point to the nearest victim." + flags_1 = CONDUCT_1 | NODROP_1 | DROPDEL_1 + slot_flags = null + block_chance = 0 //RNG WON'T HELP YOU NOW, PANSY + luminosity = 3 + attack_verb = list("brutalized", "eviscerated", "disemboweled", "hacked", "carved", "cleaved") //ONLY THE MOST VISCERAL ATTACK VERBS + var/notches = 0 //HOW MANY PEOPLE HAVE BEEN SLAIN WITH THIS BLADE + var/obj/item/disk/nuclear/nuke_disk //OUR STORED NUKE DISK + +/obj/item/claymore/highlander/Initialize() + . = ..() + START_PROCESSING(SSobj, src) + +/obj/item/claymore/highlander/Destroy() + if(nuke_disk) + nuke_disk.forceMove(get_turf(src)) + nuke_disk.visible_message("The nuke disk is vulnerable!") + nuke_disk = null + STOP_PROCESSING(SSobj, src) + return ..() + +/obj/item/claymore/highlander/process() + if(ishuman(loc)) + var/mob/living/carbon/human/H = loc + loc.layer = LARGE_MOB_LAYER //NO HIDING BEHIND PLANTS FOR YOU, DICKWEED (HA GET IT, BECAUSE WEEDS ARE PLANTS) + H.bleedsuppress = TRUE //AND WE WON'T BLEED OUT LIKE COWARDS + else + if(!admin_spawned) + qdel(src) + + +/obj/item/claymore/highlander/pickup(mob/living/user) + to_chat(user, "The power of Scotland protects you! You are shielded from all stuns and knockdowns.") + user.add_stun_absorption("highlander", INFINITY, 1, " is protected by the power of Scotland!", "The power of Scotland absorbs the stun!", " is protected by the power of Scotland!") + user.status_flags += IGNORESLOWDOWN + +/obj/item/claymore/highlander/dropped(mob/living/user) + user.status_flags -= IGNORESLOWDOWN + qdel(src) //If this ever happens, it's because you lost an arm + +/obj/item/claymore/highlander/examine(mob/user) + ..() + to_chat(user, "It has [!notches ? "nothing" : "[notches] notches"] scratched into the blade.") + if(nuke_disk) + to_chat(user, "It's holding the nuke disk!") + +/obj/item/claymore/highlander/attack(mob/living/target, mob/living/user) + . = ..() + if(target && target.stat == DEAD && target.mind && target.mind.special_role == "highlander") + user.fully_heal() //STEAL THE LIFE OF OUR FALLEN FOES + add_notch(user) + target.visible_message("[target] crumbles to dust beneath [user]'s blows!", "As you fall, your body crumbles to dust!") + target.dust() + +/obj/item/claymore/highlander/attack_self(mob/living/user) + var/closest_victim + var/closest_distance = 255 + for(var/mob/living/carbon/human/H in GLOB.player_list - user) + if(H.client && H.mind.special_role == "highlander" && (!closest_victim || get_dist(user, closest_victim) < closest_distance)) + closest_victim = H + if(!closest_victim) + to_chat(user, "[src] thrums for a moment and falls dark. Perhaps there's nobody nearby.") + return + to_chat(user, "[src] thrums and points to the [dir2text(get_dir(user, closest_victim))].") + +/obj/item/claymore/highlander/IsReflect() + return 1 //YOU THINK YOUR PUNY LASERS CAN STOP ME? + +/obj/item/claymore/highlander/proc/add_notch(mob/living/user) //DYNAMIC CLAYMORE PROGRESSION SYSTEM - THIS IS THE FUTURE + notches++ + force++ + var/new_name = name + switch(notches) + if(1) + to_chat(user, "Your first kill - hopefully one of many. You scratch a notch into [src]'s blade.") + to_chat(user, "You feel your fallen foe's soul entering your blade, restoring your wounds!") + new_name = "notched claymore" + if(2) + to_chat(user, "Another falls before you. Another soul fuses with your own. Another notch in the blade.") + new_name = "double-notched claymore" + add_atom_colour(rgb(255, 235, 235), ADMIN_COLOUR_PRIORITY) + if(3) + to_chat(user, "You're beginning to relish the thrill of battle.") + new_name = "triple-notched claymore" + add_atom_colour(rgb(255, 215, 215), ADMIN_COLOUR_PRIORITY) + if(4) + to_chat(user, "You've lost count of how many you've killed.") + new_name = "many-notched claymore" + add_atom_colour(rgb(255, 195, 195), ADMIN_COLOUR_PRIORITY) + if(5) + to_chat(user, "Five voices now echo in your mind, cheering the slaughter.") + new_name = "battle-tested claymore" + add_atom_colour(rgb(255, 175, 175), ADMIN_COLOUR_PRIORITY) + if(6) + to_chat(user, "Is this what the vikings felt like? Visions of glory fill your head as you slay your sixth foe.") + new_name = "battle-scarred claymore" + add_atom_colour(rgb(255, 155, 155), ADMIN_COLOUR_PRIORITY) + if(7) + to_chat(user, "Kill. Butcher. Conquer.") + new_name = "vicious claymore" + add_atom_colour(rgb(255, 135, 135), ADMIN_COLOUR_PRIORITY) + if(8) + to_chat(user, "IT NEVER GETS OLD. THE SCREAMING. THE BLOOD AS IT SPRAYS ACROSS YOUR FACE.") + new_name = "bloodthirsty claymore" + add_atom_colour(rgb(255, 115, 115), ADMIN_COLOUR_PRIORITY) + if(9) + to_chat(user, "ANOTHER ONE FALLS TO YOUR BLOWS. ANOTHER WEAKLING UNFIT TO LIVE.") + new_name = "gore-stained claymore" + add_atom_colour(rgb(255, 95, 95), ADMIN_COLOUR_PRIORITY) + if(10) + user.visible_message("[user]'s eyes light up with a vengeful fire!", \ + "YOU FEEL THE POWER OF VALHALLA FLOWING THROUGH YOU! THERE CAN BE ONLY ONE!!!") + user.update_icons() + new_name = "GORE-DRENCHED CLAYMORE OF [pick("THE WHIMSICAL SLAUGHTER", "A THOUSAND SLAUGHTERED CATTLE", "GLORY AND VALHALLA", "ANNIHILATION", "OBLITERATION")]" + icon_state = "claymore_valhalla" + item_state = "cultblade" + remove_atom_colour(ADMIN_COLOUR_PRIORITY) + + name = new_name + playsound(user, 'sound/items/screwdriver2.ogg', 50, 1) + +/obj/item/katana + name = "katana" + desc = "Woefully underpowered in D20" + icon_state = "katana" + item_state = "katana" + lefthand_file = 'icons/mob/inhands/weapons/swords_lefthand.dmi' + righthand_file = 'icons/mob/inhands/weapons/swords_righthand.dmi' + flags_1 = CONDUCT_1 + slot_flags = SLOT_BELT | SLOT_BACK + force = 40 + throwforce = 10 + w_class = WEIGHT_CLASS_NORMAL + hitsound = 'sound/weapons/bladeslice.ogg' + attack_verb = list("attacked", "slashed", "stabbed", "sliced", "torn", "ripped", "diced", "cut") + block_chance = 50 + sharpness = IS_SHARP + max_integrity = 200 + armor = list(melee = 0, bullet = 0, laser = 0, energy = 0, bomb = 0, bio = 0, rad = 0, fire = 100, acid = 50) + resistance_flags = FIRE_PROOF + +/obj/item/katana/cursed + slot_flags = null + +/obj/item/katana/suicide_act(mob/user) + user.visible_message("[user] is slitting [user.p_their()] stomach open with [src]! It looks like [user.p_theyre()] trying to commit seppuku!") + return(BRUTELOSS) + +/obj/item/wirerod + name = "wired rod" + desc = "A rod with some wire wrapped around the top. It'd be easy to attach something to the top bit." + icon_state = "wiredrod" + item_state = "rods" + flags_1 = CONDUCT_1 + force = 9 + throwforce = 10 + w_class = WEIGHT_CLASS_NORMAL + materials = list(MAT_METAL=1150, MAT_GLASS=75) + attack_verb = list("hit", "bludgeoned", "whacked", "bonked") + +/obj/item/wirerod/attackby(obj/item/I, mob/user, params) + if(istype(I, /obj/item/shard)) + var/obj/item/twohanded/spear/S = new /obj/item/twohanded/spear + + remove_item_from_storage(user) + qdel(I) + qdel(src) + + user.put_in_hands(S) + to_chat(user, "You fasten the glass shard to the top of the rod with the cable.") + + else if(istype(I, /obj/item/device/assembly/igniter) && !(I.flags_1 & NODROP_1)) + var/obj/item/melee/baton/cattleprod/P = new /obj/item/melee/baton/cattleprod + + remove_item_from_storage(user) + + to_chat(user, "You fasten [I] to the top of the rod with the cable.") + + qdel(I) + qdel(src) + + user.put_in_hands(P) + else + return ..() + + +/obj/item/throwing_star + name = "throwing star" + desc = "An ancient weapon still used to this day due to it's ease of lodging itself into victim's body parts" + icon_state = "throwingstar" + item_state = "eshield0" + lefthand_file = 'icons/mob/inhands/equipment/shields_lefthand.dmi' + righthand_file = 'icons/mob/inhands/equipment/shields_righthand.dmi' + force = 2 + throwforce = 20 //This is never used on mobs since this has a 100% embed chance. + throw_speed = 4 + embedded_pain_multiplier = 4 + w_class = WEIGHT_CLASS_SMALL + embed_chance = 100 + embedded_fall_chance = 0 //Hahaha! + sharpness = IS_SHARP + materials = list(MAT_METAL=500, MAT_GLASS=500) + resistance_flags = FIRE_PROOF + + +/obj/item/switchblade + name = "switchblade" + icon_state = "switchblade" + lefthand_file = 'icons/mob/inhands/weapons/swords_lefthand.dmi' + righthand_file = 'icons/mob/inhands/weapons/swords_righthand.dmi' + desc = "A sharp, concealable, spring-loaded knife." + flags_1 = CONDUCT_1 + force = 3 + w_class = WEIGHT_CLASS_SMALL + throwforce = 5 + throw_speed = 3 + throw_range = 6 + materials = list(MAT_METAL=12000) + origin_tech = "engineering=3;combat=2" + hitsound = 'sound/weapons/genhit.ogg' + attack_verb = list("stubbed", "poked") + resistance_flags = FIRE_PROOF + var/extended = 0 + +/obj/item/switchblade/attack_self(mob/user) + extended = !extended + playsound(src.loc, 'sound/weapons/batonextend.ogg', 50, 1) + if(extended) + force = 20 + w_class = WEIGHT_CLASS_NORMAL + throwforce = 23 + icon_state = "switchblade_ext" + attack_verb = list("slashed", "stabbed", "sliced", "torn", "ripped", "diced", "cut") + hitsound = 'sound/weapons/bladeslice.ogg' + sharpness = IS_SHARP + else + force = 3 + w_class = WEIGHT_CLASS_SMALL + throwforce = 5 + icon_state = "switchblade" + attack_verb = list("stubbed", "poked") + hitsound = 'sound/weapons/genhit.ogg' + sharpness = IS_BLUNT + +/obj/item/switchblade/suicide_act(mob/user) + user.visible_message("[user] is slitting [user.p_their()] own throat with [src]! It looks like [user.p_theyre()] trying to commit suicide!") + return (BRUTELOSS) + +/obj/item/phone + name = "red phone" + desc = "Should anything ever go wrong..." + icon = 'icons/obj/items_and_weapons.dmi' + icon_state = "red_phone" + force = 3 + throwforce = 2 + throw_speed = 3 + throw_range = 4 + w_class = WEIGHT_CLASS_SMALL + attack_verb = list("called", "rang") + hitsound = 'sound/weapons/ring.ogg' + +/obj/item/phone/suicide_act(mob/user) + if(locate(/obj/structure/chair/stool) in user.loc) + user.visible_message("[user] begins to tie a noose with [src]'s cord! It looks like [user.p_theyre()] trying to commit suicide!") + else + user.visible_message("[user] is strangling [user.p_them()]self with [src]'s cord! It looks like [user.p_theyre()] trying to commit suicide!") + return(OXYLOSS) + +/obj/item/cane + name = "cane" + desc = "A cane used by a true gentleman. Or a clown." + icon = 'icons/obj/items_and_weapons.dmi' + icon_state = "cane" + item_state = "stick" + lefthand_file = 'icons/mob/inhands/weapons/melee_lefthand.dmi' + righthand_file = 'icons/mob/inhands/weapons/melee_righthand.dmi' + force = 5 + throwforce = 5 + w_class = WEIGHT_CLASS_SMALL + materials = list(MAT_METAL=50) + attack_verb = list("bludgeoned", "whacked", "disciplined", "thrashed") + +/obj/item/staff + name = "wizard staff" + desc = "Apparently a staff used by the wizard." + icon = 'icons/obj/wizard.dmi' + icon_state = "staff" + lefthand_file = 'icons/mob/inhands/weapons/staves_lefthand.dmi' + righthand_file = 'icons/mob/inhands/weapons/staves_righthand.dmi' + force = 3 + throwforce = 5 + throw_speed = 2 + throw_range = 5 + w_class = WEIGHT_CLASS_SMALL + armour_penetration = 100 + attack_verb = list("bludgeoned", "whacked", "disciplined") + resistance_flags = FLAMMABLE + +/obj/item/staff/broom + name = "broom" + desc = "Used for sweeping, and flying into the night while cackling. Black cat not included." + icon = 'icons/obj/wizard.dmi' + icon_state = "broom" + resistance_flags = FLAMMABLE + +/obj/item/staff/stick + name = "stick" + desc = "A great tool to drag someone else's drinks across the bar." + icon = 'icons/obj/items_and_weapons.dmi' + icon_state = "stick" + item_state = "stick" + lefthand_file = 'icons/mob/inhands/weapons/melee_lefthand.dmi' + righthand_file = 'icons/mob/inhands/weapons/melee_righthand.dmi' + force = 3 + throwforce = 5 + throw_speed = 2 + throw_range = 5 + w_class = WEIGHT_CLASS_SMALL + +/obj/item/ectoplasm + name = "ectoplasm" + desc = "spooky" + gender = PLURAL + icon = 'icons/obj/wizard.dmi' + icon_state = "ectoplasm" + +/obj/item/ectoplasm/suicide_act(mob/user) + user.visible_message("[user] is inhaling [src]! It looks like [user.p_theyre()] trying to visit the astral plane.") + return (OXYLOSS) + +/obj/item/mounted_chainsaw + name = "mounted chainsaw" + desc = "A chainsaw that has replaced your arm." + icon_state = "chainsaw_on" + item_state = "mounted_chainsaw" + lefthand_file = 'icons/mob/inhands/weapons/chainsaw_lefthand.dmi' + righthand_file = 'icons/mob/inhands/weapons/chainsaw_righthand.dmi' + flags_1 = NODROP_1 | ABSTRACT_1 | DROPDEL_1 + w_class = WEIGHT_CLASS_HUGE + force = 21 + throwforce = 0 + throw_range = 0 + throw_speed = 0 + sharpness = IS_SHARP + attack_verb = list("sawed", "torn", "cut", "chopped", "diced") + hitsound = 'sound/weapons/chainsawhit.ogg' + +/obj/item/mounted_chainsaw/Destroy() + var/obj/item/bodypart/part + new /obj/item/twohanded/required/chainsaw(get_turf(src)) + if(iscarbon(loc)) + var/mob/living/carbon/holder = loc + var/index = holder.get_held_index_of_item(src) + if(index) + part = holder.hand_bodyparts[index] + . = ..() + if(part) + part.drop_limb() + +/obj/item/statuebust + name = "bust" + desc = "A priceless ancient marble bust, the kind that belongs in a museum." //or you can hit people with it + icon = 'icons/obj/statue.dmi' + icon_state = "bust" + force = 15 + throwforce = 10 + throw_speed = 5 + throw_range = 2 + attack_verb = list("busted") + +/obj/item/tailclub + name = "tail club" + desc = "For the beating to death of lizards with their own tails." + icon_state = "tailclub" + force = 14 + throwforce = 1 // why are you throwing a club do you even weapon + throw_speed = 1 + throw_range = 1 + attack_verb = list("clubbed", "bludgeoned") + +/obj/item/melee/chainofcommand/tailwhip + name = "liz o' nine tails" + desc = "A whip fashioned from the severed tails of lizards." + icon_state = "tailwhip" + origin_tech = "engineering=3;combat=3;biotech=3" + needs_permit = 0 + +/obj/item/melee/chainofcommand/tailwhip/kitty + name = "cat o' nine tails" + desc = "A whip fashioned from the severed tails of cats." + icon_state = "catwhip" + +/obj/item/melee/skateboard + name = "skateboard" + desc = "A skateboard. It can be placed on its wheels and ridden, or used as a strong weapon." + icon_state = "skateboard" + item_state = "skateboard" + force = 12 + throwforce = 4 + w_class = WEIGHT_CLASS_HUGE + attack_verb = list("smacked", "whacked", "slammed", "smashed") + +/obj/item/melee/skateboard/attack_self(mob/user) + new /obj/vehicle/scooter/skateboard(get_turf(user)) + qdel(src) + +/obj/item/melee/baseball_bat + name = "baseball bat" + desc = "There ain't a skull in the league that can withstand a swatter." + icon = 'icons/obj/items_and_weapons.dmi' + icon_state = "baseball_bat" + item_state = "baseball_bat" + lefthand_file = 'icons/mob/inhands/weapons/melee_lefthand.dmi' + righthand_file = 'icons/mob/inhands/weapons/melee_righthand.dmi' + force = 10 + throwforce = 12 + attack_verb = list("beat", "smacked") + w_class = WEIGHT_CLASS_HUGE + var/homerun_ready = 0 + var/homerun_able = 0 + +/obj/item/melee/baseball_bat/homerun + name = "home run bat" + desc = "This thing looks dangerous... Dangerously good at baseball, that is." + homerun_able = 1 + +/obj/item/melee/baseball_bat/attack_self(mob/user) + if(!homerun_able) + ..() + return + if(homerun_ready) + to_chat(user, "You're already ready to do a home run!") + ..() + return + to_chat(user, "You begin gathering strength...") + playsound(get_turf(src), 'sound/magic/lightning_chargeup.ogg', 65, 1) + if(do_after(user, 90, target = src)) + to_chat(user, "You gather power! Time for a home run!") + homerun_ready = 1 + ..() + +/obj/item/melee/baseball_bat/attack(mob/living/target, mob/living/user) + . = ..() + var/atom/throw_target = get_edge_target_turf(target, user.dir) + if(homerun_ready) + user.visible_message("It's a home run!") + target.throw_at(throw_target, rand(8,10), 14, user) + target.ex_act(EXPLODE_HEAVY) + playsound(get_turf(src), 'sound/weapons/homerun.ogg', 100, 1) + homerun_ready = 0 + return + else if(!target.anchored) + target.throw_at(throw_target, rand(1,2), 7, user) + +/obj/item/melee/baseball_bat/ablative + name = "metal baseball bat" + desc = "This bat is made of highly reflective, highly armored material." + icon_state = "baseball_bat_metal" + item_state = "baseball_bat_metal" + force = 12 + throwforce = 15 + +/obj/item/melee/baseball_bat/ablative/IsReflect()//some day this will reflect thrown items instead of lasers + var/picksound = rand(1,2) + var/turf = get_turf(src) + if(picksound == 1) + playsound(turf, 'sound/weapons/effects/batreflect1.ogg', 50, 1) + if(picksound == 2) + playsound(turf, 'sound/weapons/effects/batreflect2.ogg', 50, 1) + return 1 + +/obj/item/melee/flyswatter + name = "flyswatter" + desc = "Useful for killing insects of all sizes." + icon = 'icons/obj/items_and_weapons.dmi' + icon_state = "flyswatter" + item_state = "flyswatter" + lefthand_file = 'icons/mob/inhands/weapons/melee_lefthand.dmi' + righthand_file = 'icons/mob/inhands/weapons/melee_righthand.dmi' + force = 1 + throwforce = 1 + attack_verb = list("swatted", "smacked") + hitsound = 'sound/effects/snap.ogg' + w_class = WEIGHT_CLASS_SMALL + //Things in this list will be instantly splatted. Flyman weakness is handled in the flyman species weakness proc. + var/list/strong_against + +/obj/item/melee/flyswatter/Initialize() + . = ..() + strong_against = typecacheof(list( + /mob/living/simple_animal/hostile/poison/bees/, + /mob/living/simple_animal/butterfly, + /mob/living/simple_animal/cockroach, + /obj/item/queen_bee + )) + + +/obj/item/melee/flyswatter/afterattack(atom/target, mob/user, proximity_flag) + if(proximity_flag) + if(is_type_in_typecache(target, strong_against)) + new /obj/effect/decal/cleanable/deadcockroach(get_turf(target)) + to_chat(user, "You easily splat the [target].") + if(istype(target, /mob/living/)) + var/mob/living/bug = target + bug.death(1) + else + qdel(target) + +/obj/item/circlegame + name = "circled hand" + desc = "If somebody looks at this while it's below your waist, you get to bop them." + icon_state = "madeyoulook" + force = 0 + throwforce = 0 + flags_1 = DROPDEL_1 | ABSTRACT_1 + attack_verb = list("bopped") + +/obj/item/proc/can_trigger_gun(mob/living/user) + if(!user.can_use_guns(src)) + return FALSE playsound(loc, 'sound/effects/adminhelp.ogg', 15) //keep it at 15% volume so people don't jump out of their skin too much /obj/item/sord @@ -1157,5 +1155,4 @@ /obj/item/proc/can_trigger_gun(mob/living/user) if(!user.can_use_guns(src)) return FALSE ->>>>>>> 129a7b9... Fixes brains counting towards highlander killstreaks (#30396) return TRUE From 44e62d80162cd15f04592a6f28a35cc7f86a6235 Mon Sep 17 00:00:00 2001 From: Leo Date: Sun, 10 Sep 2017 16:17:04 -0300 Subject: [PATCH 24/74] Uplink lock codes now pick from the phonetic alphabet global list (#30538) * Uplink lock codes now pick from the phonetic alphabet global list * Update virus_cart.dm --- code/datums/mind.dm | 2 +- code/game/objects/items/devices/PDA/virus_cart.dm | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/code/datums/mind.dm b/code/datums/mind.dm index 78a402a2dc..7df65438f2 100644 --- a/code/datums/mind.dm +++ b/code/datums/mind.dm @@ -311,7 +311,7 @@ traitor_mob.mind.store_memory("Radio Frequency: [format_frequency(R.traitor_frequency)] ([R.name]).") else if(uplink_loc == PDA) - PDA.lock_code = "[rand(100,999)] [pick("Alpha","Bravo","Charlie","Delta","Echo","Foxtrot","Golf","Hotel","India","Juliet","Kilo","Lima","Mike","November","Oscar","Papa","Quebec","Romeo","Sierra","Tango","Uniform","Victor","Whiskey","X-ray","Yankee","Zulu")]" + PDA.lock_code = "[rand(100,999)] [pick(GLOB.phonetic_alphabet)]" if(!silent) to_chat(traitor_mob, "[employer] has cunningly disguised a Syndicate Uplink as your [PDA.name]. Simply enter the code \"[PDA.lock_code]\" into the ringtone select to unlock its hidden features.") traitor_mob.mind.store_memory("Uplink Passcode: [PDA.lock_code] ([PDA.name]).") diff --git a/code/game/objects/items/devices/PDA/virus_cart.dm b/code/game/objects/items/devices/PDA/virus_cart.dm index 2b0a9d3b3c..8c4a42a5aa 100644 --- a/code/game/objects/items/devices/PDA/virus_cart.dm +++ b/code/game/objects/items/devices/PDA/virus_cart.dm @@ -90,7 +90,7 @@ return if(!isnull(target) && !target.toff) charges-- - var/lock_code = "[rand(100,999)] [pick("Alpha","Bravo","Charlie","Delta","Echo","Foxtrot","Golf","Hotel","India","Juliet","Kilo","Lima","Mike","November","Oscar","Papa","Quebec","Romeo","Sierra","Tango","Uniform","Victor","Whiskey","X-ray","Yankee","Zulu")]" + var/lock_code = "[rand(100,999)] [pick(GLOB.phonetic_alphabet)]" to_chat(U, "Virus Sent! The unlock code to the target is: [lock_code]") if(!target.hidden_uplink) var/obj/item/device/uplink/uplink = new(target) From cb734046f728f54b1af4edf0af830bcbe813d3f1 Mon Sep 17 00:00:00 2001 From: Leo Date: Sun, 10 Sep 2017 16:18:12 -0300 Subject: [PATCH 26/74] Changes golem shell attackby istype chain to use an assoc list instead of an istype chain (#30542) * Changes golem shell attackby istype chain to use an assoc list instead * Makes the check use merge_type as opposed of item type --- code/modules/ruins/lavaland_ruin_code.dm | 86 +++++++----------------- 1 file changed, 25 insertions(+), 61 deletions(-) diff --git a/code/modules/ruins/lavaland_ruin_code.dm b/code/modules/ruins/lavaland_ruin_code.dm index e4927349d8..da965aae9d 100644 --- a/code/modules/ruins/lavaland_ruin_code.dm +++ b/code/modules/ruins/lavaland_ruin_code.dm @@ -46,71 +46,35 @@ desc = "The incomplete body of a golem. Add ten sheets of any mineral to finish." var/shell_type = /obj/effect/mob_spawn/human/golem var/has_owner = FALSE //if the resulting golem obeys someone - w_class = WEIGHT_CLASS_BULKY + w_class = WEIGHT_CLASS_BULKY /obj/item/golem_shell/attackby(obj/item/I, mob/user, params) ..() - var/species - if(istype(I, /obj/item/stack/)) + var/static/list/golem_shell_species_types = list( + /obj/item/stack/sheet/metal = /datum/species/golem, + /obj/item/stack/sheet/glass = /datum/species/golem/glass, + /obj/item/stack/sheet/plasteel = /datum/species/golem/plasteel, + /obj/item/stack/sheet/mineral/sandstone = /datum/species/golem/sand, + /obj/item/stack/sheet/mineral/plasma = /datum/species/golem/plasma, + /obj/item/stack/sheet/mineral/diamond = /datum/species/golem/diamond, + /obj/item/stack/sheet/mineral/gold = /datum/species/golem/gold, + /obj/item/stack/sheet/mineral/silver = /datum/species/golem/silver, + /obj/item/stack/sheet/mineral/uranium = /datum/species/golem/uranium, + /obj/item/stack/sheet/mineral/bananium = /datum/species/golem/bananium, + /obj/item/stack/sheet/mineral/titanium = /datum/species/golem/titanium, + /obj/item/stack/sheet/mineral/plastitanium = /datum/species/golem/plastitanium, + /obj/item/stack/sheet/mineral/abductor = /datum/species/golem/alloy, + /obj/item/stack/sheet/mineral/wood = /datum/species/golem/wood, + /obj/item/stack/sheet/bluespace_crystal = /datum/species/golem/bluespace, + /obj/item/stack/sheet/runed_metal = /datum/species/golem/runic, + /obj/item/stack/medical/gauze = /datum/species/golem/cloth, + /obj/item/stack/sheet/cloth = /datum/species/golem/cloth, + /obj/item/stack/sheet/mineral/adamantine = /datum/species/golem/adamantine, + /obj/item/stack/sheet/plastic = /datum/species/golem/plastic) + + if(istype(I, /obj/item/stack)) var/obj/item/stack/O = I - - if(istype(O, /obj/item/stack/sheet/metal)) - species = /datum/species/golem - - if(istype(O, /obj/item/stack/sheet/glass)) - species = /datum/species/golem/glass - - if(istype(O, /obj/item/stack/sheet/plasteel)) - species = /datum/species/golem/plasteel - - if(istype(O, /obj/item/stack/sheet/mineral/sandstone)) - species = /datum/species/golem/sand - - if(istype(O, /obj/item/stack/sheet/mineral/plasma)) - species = /datum/species/golem/plasma - - if(istype(O, /obj/item/stack/sheet/mineral/diamond)) - species = /datum/species/golem/diamond - - if(istype(O, /obj/item/stack/sheet/mineral/gold)) - species = /datum/species/golem/gold - - if(istype(O, /obj/item/stack/sheet/mineral/silver)) - species = /datum/species/golem/silver - - if(istype(O, /obj/item/stack/sheet/mineral/uranium)) - species = /datum/species/golem/uranium - - if(istype(O, /obj/item/stack/sheet/mineral/bananium)) - species = /datum/species/golem/bananium - - if(istype(O, /obj/item/stack/sheet/mineral/titanium)) - species = /datum/species/golem/titanium - - if(istype(O, /obj/item/stack/sheet/mineral/plastitanium)) - species = /datum/species/golem/plastitanium - - if(istype(O, /obj/item/stack/sheet/mineral/abductor)) - species = /datum/species/golem/alloy - - if(istype(O, /obj/item/stack/sheet/mineral/wood)) - species = /datum/species/golem/wood - - if(istype(O, /obj/item/stack/sheet/bluespace_crystal)) - species = /datum/species/golem/bluespace - - if(istype(O, /obj/item/stack/sheet/runed_metal)) - species = /datum/species/golem/runic - - if(istype(O, /obj/item/stack/medical/gauze) || istype(O, /obj/item/stack/sheet/cloth)) - species = /datum/species/golem/cloth - - if(istype(O, /obj/item/stack/sheet/mineral/adamantine)) - species = /datum/species/golem/adamantine - - if(istype(O, /obj/item/stack/sheet/plastic)) - species = /datum/species/golem/plastic - + var/species = golem_shell_species_types[O.merge_type] if(species) if(O.use(10)) to_chat(user, "You finish up the golem shell with ten sheets of [O].") From c3fed32afbcb55111662e13473554c504cf7085f Mon Sep 17 00:00:00 2001 From: LetterJay Date: Sun, 10 Sep 2017 15:17:25 -0500 Subject: [PATCH 28/74] Update prolonging_prism.dm --- .../clock_structures/prolonging_prism.dm | 903 +++++++++++++++--- 1 file changed, 779 insertions(+), 124 deletions(-) diff --git a/code/game/gamemodes/clock_cult/clock_structures/prolonging_prism.dm b/code/game/gamemodes/clock_cult/clock_structures/prolonging_prism.dm index a6bc9a7f38..c6692073b0 100644 --- a/code/game/gamemodes/clock_cult/clock_structures/prolonging_prism.dm +++ b/code/game/gamemodes/clock_cult/clock_structures/prolonging_prism.dm @@ -1,135 +1,790 @@ -//Prolonging Prism: A prism that consumes power to delay the shuttle -/obj/structure/destructible/clockwork/powered/prolonging_prism - name = "prolonging prism" - desc = "A dark onyx prism, held in midair by spiraling tendrils of stone." - clockwork_desc = "A powerful prism that will delay the arrival of an emergency shuttle." - icon_state = "prolonging_prism_inactive" - active_icon = "prolonging_prism" - inactive_icon = "prolonging_prism_inactive" - unanchored_icon = "prolonging_prism_unwrenched" - construction_value = 20 - max_integrity = 125 - break_message = "The prism falls to the ground with a heavy thud!" - debris = list(/obj/item/clockwork/alloy_shards/small = 3, \ - /obj/item/clockwork/alloy_shards/medium = 1, \ - /obj/item/clockwork/alloy_shards/large = 1, \ - /obj/item/clockwork/component/vanguard_cogwheel/onyx_prism = 1) - var/static/list/component_refund = list(VANGUARD_COGWHEEL = 2, GEIS_CAPACITOR = 1, REPLICANT_ALLOY = 1) - var/static/delay_cost = 3000 - var/static/delay_cost_increase = 1250 - var/static/delay_remaining = 0 +#define WELDER_FUEL_BURN_INTERVAL 13 -/obj/structure/destructible/clockwork/powered/prolonging_prism/examine(mob/user) - ..() - if(is_servant_of_ratvar(user) || isobserver(user)) - if(SSshuttle.emergency.mode == SHUTTLE_DOCKED || SSshuttle.emergency.mode == SHUTTLE_IGNITING || SSshuttle.emergency.mode == SHUTTLE_STRANDED || SSshuttle.emergency.mode == SHUTTLE_ESCAPE) - to_chat(user, "An emergency shuttle has arrived and this prism is no longer useful; attempt to activate it to gain a partial refund of components used.") - else - var/efficiency = get_efficiency_mod(TRUE) - to_chat(user, "It requires at least [get_delay_cost()]W of power to attempt to delay the arrival of an emergency shuttle by [2 * efficiency] minutes.") - to_chat(user, "This cost increases by [delay_cost_increase]W for every previous activation.") +/* Tools! + * Note: Multitools are /obj/item/device + * + * Contains: + * Wrench + * Screwdriver + * Wirecutters + * Welding Tool + * Crowbar + */ -/obj/structure/destructible/clockwork/powered/prolonging_prism/forced_disable(bad_effects) - if(active) - if(bad_effects) - try_use_power(MIN_CLOCKCULT_POWER*4) - visible_message("[src] emits an airy chuckling sound and falls dark!") - toggle() - return TRUE +/* + * Wrench + */ +/obj/item/wrench + name = "wrench" + desc = "A wrench with common uses. Can be found in your hand." + icon = 'icons/obj/tools.dmi' + icon_state = "wrench" + lefthand_file = 'icons/mob/inhands/equipment/tools_lefthand.dmi' + righthand_file = 'icons/mob/inhands/equipment/tools_righthand.dmi' + flags_1 = CONDUCT_1 + slot_flags = SLOT_BELT + force = 5 + throwforce = 7 + w_class = WEIGHT_CLASS_SMALL + usesound = 'sound/items/ratchet.ogg' + materials = list(MAT_METAL=150) + origin_tech = "materials=1;engineering=1" + attack_verb = list("bashed", "battered", "bludgeoned", "whacked") + toolspeed = 1 + armor = list(melee = 0, bullet = 0, laser = 0, energy = 0, bomb = 0, bio = 0, rad = 0, fire = 50, acid = 30) -/obj/structure/destructible/clockwork/powered/prolonging_prism/attack_hand(mob/living/user) - if(user.canUseTopic(src, !issilicon(user), NO_DEXTERY) && is_servant_of_ratvar(user)) - if(SSshuttle.emergency.mode == SHUTTLE_DOCKED || SSshuttle.emergency.mode == SHUTTLE_IGNITING || SSshuttle.emergency.mode == SHUTTLE_STRANDED || SSshuttle.emergency.mode == SHUTTLE_ESCAPE) - to_chat(user, "You break [src] apart, refunding some of the components used.") - for(var/i in component_refund) - generate_cache_component(i, src) - take_damage(max_integrity) - return 0 - if(active) - return 0 - var/turf/T = get_turf(src) - if(!T || T.z != ZLEVEL_STATION) - to_chat(user, "[src] must be on the station to function!") - return 0 - if(SSshuttle.emergency.mode != SHUTTLE_CALL) - to_chat(user, "No emergency shuttles are attempting to arrive at the station!") - return 0 - if(!try_use_power(get_delay_cost())) - to_chat(user, "[src] needs more power to function!") - return 0 - delay_cost += delay_cost_increase - delay_remaining += PRISM_DELAY_DURATION - toggle(0, user) +/obj/item/wrench/suicide_act(mob/user) + user.visible_message("[user] is beating [user.p_them()]self to death with [src]! It looks like [user.p_theyre()] trying to commit suicide!") + playsound(loc, 'sound/weapons/genhit.ogg', 50, 1, -1) + return (BRUTELOSS) -/obj/structure/destructible/clockwork/powered/prolonging_prism/process() - var/turf/own_turf = get_turf(src) - if(SSshuttle.emergency.mode != SHUTTLE_CALL || delay_remaining <= 0 || !own_turf || own_turf.z != ZLEVEL_STATION) - forced_disable(FALSE) +/obj/item/wrench/cyborg + name = "automatic wrench" + desc = "An advanced robotic wrench. Can be found in construction cyborgs." + toolspeed = 0.5 + +/obj/item/wrench/brass + name = "brass wrench" + desc = "A brass wrench. It's faintly warm to the touch." + resistance_flags = FIRE_PROOF | ACID_PROOF + icon_state = "wrench_brass" + toolspeed = 0.5 + +/obj/item/wrench/abductor + name = "alien wrench" + desc = "A polarized wrench. It causes anything placed between the jaws to turn." + icon = 'icons/obj/abductor.dmi' + icon_state = "wrench" + usesound = 'sound/effects/empulse.ogg' + toolspeed = 0.1 + origin_tech = "materials=5;engineering=5;abductor=3" + +/obj/item/wrench/power + name = "hand drill" + desc = "A simple powered hand drill. It's fitted with a bolt bit." + icon_state = "drill_bolt" + item_state = "drill" + lefthand_file = 'icons/mob/inhands/equipment/tools_lefthand.dmi' + righthand_file = 'icons/mob/inhands/equipment/tools_righthand.dmi' + usesound = 'sound/items/drill_use.ogg' + materials = list(MAT_METAL=150,MAT_SILVER=50,MAT_TITANIUM=25) + origin_tech = "materials=2;engineering=2" //done for balance reasons, making them high value for research, but harder to get + force = 8 //might or might not be too high, subject to change + w_class = WEIGHT_CLASS_SMALL + throwforce = 8 + attack_verb = list("drilled", "screwed", "jabbed") + toolspeed = 0.25 + +/obj/item/wrench/power/attack_self(mob/user) + playsound(get_turf(user),'sound/items/change_drill.ogg',50,1) + var/obj/item/wirecutters/power/s_drill = new /obj/item/screwdriver/power + to_chat(user, "You attach the screw driver bit to [src].") + qdel(src) + user.put_in_active_hand(s_drill) + +/obj/item/wrench/power/suicide_act(mob/user) + user.visible_message("[user] is pressing [src] against [user.p_their()] head! It looks like [user.p_theyre()] trying to commit suicide!") + return (BRUTELOSS) + +/obj/item/wrench/medical + name = "medical wrench" + desc = "A medical wrench with common(medical?) uses. Can be found in your hand." + icon_state = "wrench_medical" + force = 2 //MEDICAL + throwforce = 4 + origin_tech = "materials=1;engineering=1;biotech=3" + attack_verb = list("wrenched", "medicaled", "tapped", "jabbed", "whacked") + +/obj/item/wrench/medical/suicide_act(mob/living/user) + user.visible_message("[user] is praying to the medical wrench to take [user.p_their()] soul. It looks like [user.p_theyre()] trying to commit suicide!") + // TODO Make them glow with the power of the M E D I C A L W R E N C H + // during their ascension + + // Stun stops them from wandering off + user.Stun(100, ignore_canstun = TRUE) + playsound(loc, 'sound/effects/pray.ogg', 50, 1, -1) + + // Let the sound effect finish playing + sleep(20) + + if(!user) return + + for(var/obj/item/W in user) + user.dropItemToGround(W) + + var/obj/item/wrench/medical/W = new /obj/item/wrench/medical(loc) + W.add_fingerprint(user) + W.desc += " For some reason, it reminds you of [user.name]." + + if(!user) + return + + user.dust() + + return OXYLOSS + +/* + * Screwdriver + */ +/obj/item/screwdriver + name = "screwdriver" + desc = "You can be totally screwy with this." + icon = 'icons/obj/tools.dmi' + icon_state = "screwdriver" + item_state = "screwdriver" + lefthand_file = 'icons/mob/inhands/equipment/tools_lefthand.dmi' + righthand_file = 'icons/mob/inhands/equipment/tools_righthand.dmi' + flags_1 = CONDUCT_1 + slot_flags = SLOT_BELT + force = 5 + w_class = WEIGHT_CLASS_TINY + throwforce = 5 + throw_speed = 3 + throw_range = 5 + materials = list(MAT_METAL=75) + attack_verb = list("stabbed") + hitsound = 'sound/weapons/bladeslice.ogg' + usesound = 'sound/items/screwdriver.ogg' + toolspeed = 1 + armor = list(melee = 0, bullet = 0, laser = 0, energy = 0, bomb = 0, bio = 0, rad = 0, fire = 50, acid = 30) + var/random_color = TRUE //if the screwdriver uses random coloring + var/static/list/screwdriver_colors = list(\ + "blue" = rgb(24, 97, 213), \ + "red" = rgb(149, 23, 16), \ + "pink" = rgb(213, 24, 141), \ + "brown" = rgb(160, 82, 18), \ + "green" = rgb(14, 127, 27), \ + "cyan" = rgb(24, 162, 213), \ + "yellow" = rgb(213, 140, 24), \ + ) + +/obj/item/screwdriver/suicide_act(mob/user) + user.visible_message("[user] is stabbing [src] into [user.p_their()] [pick("temple", "heart")]! It looks like [user.p_theyre()] trying to commit suicide!") + return(BRUTELOSS) + +/obj/item/screwdriver/Initialize() . = ..() - var/delay_amount = 40 - delay_remaining -= delay_amount - var/efficiency = get_efficiency_mod() - SSshuttle.emergency.setTimer(SSshuttle.emergency.timeLeft(1) + (delay_amount * efficiency)) - var/highest_y - var/highest_x - var/lowest_y - var/lowest_x - var/list/prism_turfs = list() - for(var/t in SSshuttle.emergency.ripple_area(SSshuttle.getDock("emergency_home"))) - prism_turfs[t] = TRUE - var/turf/T = t - if(!highest_y || T.y > highest_y) - highest_y = T.y - if(!highest_x || T.x > highest_x) - highest_x = T.x - if(!lowest_y || T.y < lowest_y) - lowest_y = T.y - if(!lowest_x || T.x < lowest_x) - lowest_x = T.x - var/mean_y = Lerp(lowest_y, highest_y) - var/mean_x = Lerp(lowest_x, highest_x) - if(prob(50)) - mean_y = Ceiling(mean_y) + if(random_color) //random colors! + var/our_color = pick(screwdriver_colors) + add_atom_colour(screwdriver_colors[our_color], FIXED_COLOUR_PRIORITY) + update_icon() + if(prob(75)) + pixel_y = rand(0, 16) + +/obj/item/screwdriver/update_icon() + if(!random_color) //icon override + return + cut_overlays() + var/mutable_appearance/base_overlay = mutable_appearance(icon, "screwdriver_screwybits") + base_overlay.appearance_flags = RESET_COLOR + add_overlay(base_overlay) + +/obj/item/screwdriver/worn_overlays(isinhands = FALSE, icon_file) + . = list() + if(isinhands && random_color) + var/mutable_appearance/M = mutable_appearance(icon_file, "screwdriver_head") + M.appearance_flags = RESET_COLOR + . += M + +/obj/item/screwdriver/get_belt_overlay() + if(random_color) + var/mutable_appearance/body = mutable_appearance('icons/obj/clothing/belt_overlays.dmi', "screwdriver") + var/mutable_appearance/head = mutable_appearance('icons/obj/clothing/belt_overlays.dmi', "screwdriver_head") + body.color = color + head.add_overlay(body) + return head else - mean_y = Floor(mean_y) - if(prob(50)) - mean_x = Ceiling(mean_x) + return mutable_appearance('icons/obj/clothing/belt_overlays.dmi', icon_state) + +/obj/item/screwdriver/attack(mob/living/carbon/M, mob/living/carbon/user) + if(!istype(M)) + return ..() + if(user.zone_selected != "eyes" && user.zone_selected != "head") + return ..() + if(user.disabilities & CLUMSY && prob(50)) + M = user + return eyestab(M,user) + +/obj/item/screwdriver/brass + name = "brass screwdriver" + desc = "A screwdriver made of brass. The handle feels freezing cold." + resistance_flags = FIRE_PROOF | ACID_PROOF + icon_state = "screwdriver_brass" + item_state = "screwdriver_brass" + toolspeed = 0.5 + random_color = FALSE + +/obj/item/screwdriver/abductor + name = "alien screwdriver" + desc = "An ultrasonic screwdriver." + icon = 'icons/obj/abductor.dmi' + icon_state = "screwdriver_a" + item_state = "screwdriver_nuke" + usesound = 'sound/items/pshoom.ogg' + toolspeed = 0.1 + random_color = FALSE + +/obj/item/screwdriver/power + name = "hand drill" + desc = "A simple powered hand drill. It's fitted with a screw bit." + icon_state = "drill_screw" + item_state = "drill" + lefthand_file = 'icons/mob/inhands/equipment/tools_lefthand.dmi' + righthand_file = 'icons/mob/inhands/equipment/tools_righthand.dmi' + materials = list(MAT_METAL=150,MAT_SILVER=50,MAT_TITANIUM=25) + origin_tech = "materials=2;engineering=2" //done for balance reasons, making them high value for research, but harder to get + force = 8 //might or might not be too high, subject to change + w_class = WEIGHT_CLASS_SMALL + throwforce = 8 + throw_speed = 2 + throw_range = 3//it's heavier than a screw driver/wrench, so it does more damage, but can't be thrown as far + attack_verb = list("drilled", "screwed", "jabbed","whacked") + hitsound = 'sound/items/drill_hit.ogg' + usesound = 'sound/items/drill_use.ogg' + toolspeed = 0.25 + random_color = FALSE + +/obj/item/screwdriver/power/suicide_act(mob/user) + user.visible_message("[user] is putting [src] to [user.p_their()] temple. It looks like [user.p_theyre()] trying to commit suicide!") + return(BRUTELOSS) + +/obj/item/screwdriver/power/attack_self(mob/user) + playsound(get_turf(user),'sound/items/change_drill.ogg',50,1) + var/obj/item/wrench/power/b_drill = new /obj/item/wrench/power + to_chat(user, "You attach the bolt driver bit to [src].") + qdel(src) + user.put_in_active_hand(b_drill) + +/obj/item/screwdriver/cyborg + name = "powered screwdriver" + desc = "An electrical screwdriver, designed to be both precise and quick." + usesound = 'sound/items/drill_use.ogg' + toolspeed = 0.5 + +/* + * Wirecutters + */ +/obj/item/wirecutters + name = "wirecutters" + desc = "This cuts wires." + icon = 'icons/obj/tools.dmi' + icon_state = null + lefthand_file = 'icons/mob/inhands/equipment/tools_lefthand.dmi' + righthand_file = 'icons/mob/inhands/equipment/tools_righthand.dmi' + flags_1 = CONDUCT_1 + slot_flags = SLOT_BELT + force = 6 + throw_speed = 3 + throw_range = 7 + w_class = WEIGHT_CLASS_SMALL + materials = list(MAT_METAL=80) + attack_verb = list("pinched", "nipped") + hitsound = 'sound/items/wirecutter.ogg' + usesound = 'sound/items/wirecutter.ogg' + origin_tech = "materials=1;engineering=1" + toolspeed = 1 + armor = list(melee = 0, bullet = 0, laser = 0, energy = 0, bomb = 0, bio = 0, rad = 0, fire = 50, acid = 30) + + +/obj/item/wirecutters/New(loc, var/param_color = null) + ..() + if(!icon_state) + if(!param_color) + param_color = pick("yellow","red") + icon_state = "cutters_[param_color]" + +/obj/item/wirecutters/attack(mob/living/carbon/C, mob/user) + if(istype(C) && C.handcuffed && istype(C.handcuffed, /obj/item/restraints/handcuffs/cable)) + user.visible_message("[user] cuts [C]'s restraints with [src]!") + qdel(C.handcuffed) + C.handcuffed = null + if(C.buckled && C.buckled.buckle_requires_restraints) + C.buckled.unbuckle_mob(C) + C.update_handcuffed() + return else - mean_x = Floor(mean_x) - var/turf/semi_random_center_turf = locate(mean_x, mean_y, ZLEVEL_STATION) - for(var/t in getline(src, semi_random_center_turf)) - prism_turfs[t] = TRUE - var/placement_style = prob(50) - for(var/t in prism_turfs) - var/turf/T = t - if(placement_style) - if(IsOdd(T.x + T.y)) - seven_random_hexes(T, efficiency) - else if(prob(50 * efficiency)) - new /obj/effect/temp_visual/ratvar/prolonging_prism(T) + ..() + +/obj/item/wirecutters/suicide_act(mob/user) + user.visible_message("[user] is cutting at [user.p_their()] arteries with [src]! It looks like [user.p_theyre()] trying to commit suicide!") + playsound(loc, usesound, 50, 1, -1) + return (BRUTELOSS) + +/obj/item/wirecutters/brass + name = "brass wirecutters" + desc = "A pair of wirecutters made of brass. The handle feels freezing cold to the touch." + resistance_flags = FIRE_PROOF | ACID_PROOF + icon_state = "cutters_brass" + toolspeed = 0.5 + +/obj/item/wirecutters/abductor + name = "alien wirecutters" + desc = "Extremely sharp wirecutters, made out of a silvery-green metal." + icon = 'icons/obj/abductor.dmi' + icon_state = "cutters" + toolspeed = 0.1 + origin_tech = "materials=5;engineering=4;abductor=3" + +/obj/item/wirecutters/cyborg + name = "wirecutters" + desc = "This cuts wires." + toolspeed = 0.5 + +/obj/item/wirecutters/power + name = "jaws of life" + desc = "A set of jaws of life, compressed through the magic of science. It's fitted with a cutting head." + icon_state = "jaws_cutter" + item_state = "jawsoflife" + origin_tech = "materials=2;engineering=2" + materials = list(MAT_METAL=150,MAT_SILVER=50,MAT_TITANIUM=25) + usesound = 'sound/items/jaws_cut.ogg' + toolspeed = 0.25 + +/obj/item/wirecutters/power/suicide_act(mob/user) + user.visible_message("[user] is wrapping \the [src] around [user.p_their()] neck. It looks like [user.p_theyre()] trying to rip [user.p_their()] head off!") + playsound(loc, 'sound/items/jaws_cut.ogg', 50, 1, -1) + if(iscarbon(user)) + var/mob/living/carbon/C = user + var/obj/item/bodypart/BP = C.get_bodypart("head") + if(BP) + BP.drop_limb() + playsound(loc,pick('sound/misc/desceration-01.ogg','sound/misc/desceration-02.ogg','sound/misc/desceration-01.ogg') ,50, 1, -1) + return (BRUTELOSS) + +/obj/item/wirecutters/power/attack_self(mob/user) + playsound(get_turf(user), 'sound/items/change_jaws.ogg', 50, 1) + var/obj/item/crowbar/power/pryjaws = new /obj/item/crowbar/power + to_chat(user, "You attach the pry jaws to [src].") + qdel(src) + user.put_in_active_hand(pryjaws) +/* + * Welding Tool + */ +/obj/item/weldingtool + name = "welding tool" + desc = "A standard edition welder provided by Nanotrasen." + icon = 'icons/obj/tools.dmi' + icon_state = "welder" + item_state = "welder" + lefthand_file = 'icons/mob/inhands/equipment/tools_lefthand.dmi' + righthand_file = 'icons/mob/inhands/equipment/tools_righthand.dmi' + flags_1 = CONDUCT_1 + slot_flags = SLOT_BELT + force = 3 + throwforce = 5 + hitsound = "swing_hit" + usesound = 'sound/items/welder.ogg' + var/acti_sound = 'sound/items/welderactivate.ogg' + var/deac_sound = 'sound/items/welderdeactivate.ogg' + throw_speed = 3 + throw_range = 5 + w_class = WEIGHT_CLASS_SMALL + armor = list(melee = 0, bullet = 0, laser = 0, energy = 0, bomb = 0, bio = 0, rad = 0, fire = 100, acid = 30) + resistance_flags = FIRE_PROOF + + materials = list(MAT_METAL=70, MAT_GLASS=30) + origin_tech = "engineering=1;plasmatech=1" + var/welding = 0 //Whether or not the welding tool is off(0), on(1) or currently welding(2) + var/status = TRUE //Whether the welder is secured or unsecured (able to attach rods to it to make a flamethrower) + var/max_fuel = 20 //The max amount of fuel the welder can hold + var/change_icons = 1 + var/can_off_process = 0 + var/light_intensity = 2 //how powerful the emitted light is when used. + var/burned_fuel_for = 0 //when fuel was last removed + heat = 3800 + toolspeed = 1 + +/obj/item/weldingtool/Initialize() + . = ..() + create_reagents(max_fuel) + reagents.add_reagent("welding_fuel", max_fuel) + update_icon() + + +/obj/item/weldingtool/proc/update_torch() + if(welding) + add_overlay("[initial(icon_state)]-on") + item_state = "[initial(item_state)]1" + else + item_state = "[initial(item_state)]" + + +/obj/item/weldingtool/update_icon() + cut_overlays() + if(change_icons) + var/ratio = get_fuel() / max_fuel + ratio = Ceiling(ratio*4) * 25 + add_overlay("[initial(icon_state)][ratio]") + update_torch() + return + + +/obj/item/weldingtool/process() + switch(welding) + if(0) + force = 3 + damtype = "brute" + update_icon() + if(!can_off_process) + STOP_PROCESSING(SSobj, src) + return + //Welders left on now use up fuel, but lets not have them run out quite that fast + if(1) + force = 15 + damtype = "fire" + ++burned_fuel_for + if(burned_fuel_for >= WELDER_FUEL_BURN_INTERVAL) + remove_fuel(1) + update_icon() + + //This is to start fires. process() is only called if the welder is on. + open_flame() + + +/obj/item/weldingtool/suicide_act(mob/user) + user.visible_message("[user] welds [user.p_their()] every orifice closed! It looks like [user.p_theyre()] trying to commit suicide!") + return (FIRELOSS) + + +/obj/item/weldingtool/attackby(obj/item/I, mob/user, params) + if(istype(I, /obj/item/screwdriver)) + flamethrower_screwdriver(I, user) + else if(istype(I, /obj/item/stack/rods)) + flamethrower_rods(I, user) + else + return ..() + + +/obj/item/weldingtool/attack(mob/living/carbon/human/H, mob/user) + if(!istype(H)) + return ..() + + var/obj/item/bodypart/affecting = H.get_bodypart(check_zone(user.zone_selected)) + + if(affecting && affecting.status == BODYPART_ROBOTIC && user.a_intent != INTENT_HARM) + if(src.remove_fuel(1)) + playsound(loc, usesound, 50, 1) + if(user == H) + user.visible_message("[user] starts to fix some of the dents on [H]'s [affecting.name].", "You start fixing some of the dents on [H]'s [affecting.name].") + if(!do_mob(user, H, 50)) + return + item_heal_robotic(H, user, 15, 0) + else + return ..() + + +/obj/item/weldingtool/afterattack(atom/O, mob/user, proximity) + if(!proximity) return + + if(welding) + remove_fuel(1) + var/turf/location = get_turf(user) + location.hotspot_expose(700, 50, 1) + if(get_fuel() <= 0) + set_light(0) + + if(isliving(O)) + var/mob/living/L = O + if(L.IgniteMob()) + message_admins("[key_name_admin(user)] set [key_name_admin(L)] on fire") + log_game("[key_name(user)] set [key_name(L)] on fire") + + +/obj/item/weldingtool/attack_self(mob/user) + switched_on(user) + if(welding) + set_light(light_intensity) + + update_icon() + + +//Returns the amount of fuel in the welder +/obj/item/weldingtool/proc/get_fuel() + return reagents.get_reagent_amount("welding_fuel") + + +//Removes fuel from the welding tool. If a mob is passed, it will try to flash the mob's eyes. This should probably be renamed to use() +/obj/item/weldingtool/proc/remove_fuel(amount = 1, mob/living/M = null) + if(!welding || !check_fuel()) + return 0 + if(amount) + burned_fuel_for = 0 + if(get_fuel() >= amount) + reagents.remove_reagent("welding_fuel", amount) + check_fuel() + if(M) + M.flash_act(light_intensity) + return TRUE + else + if(M) + to_chat(M, "You need more welding fuel to complete this task!") + return FALSE + + +//Turns off the welder if there is no more fuel (does this really need to be its own proc?) +/obj/item/weldingtool/proc/check_fuel(mob/user) + if(get_fuel() <= 0 && welding) + switched_on(user) + update_icon() + //mob icon update + if(ismob(loc)) + var/mob/M = loc + M.update_inv_hands(0) + + return 0 + return 1 + +//Switches the welder on +/obj/item/weldingtool/proc/switched_on(mob/user) + if(!status) + to_chat(user, "[src] can't be turned on while unsecured!") + return + welding = !welding + if(welding) + if(get_fuel() >= 1) + to_chat(user, "You switch [src] on.") + playsound(loc, acti_sound, 50, 1) + force = 15 + damtype = "fire" + hitsound = 'sound/items/welder.ogg' + update_icon() + START_PROCESSING(SSobj, src) else - if(IsEven(T.x + T.y)) - seven_random_hexes(T, efficiency) - else if(prob(50 * efficiency)) - new /obj/effect/temp_visual/ratvar/prolonging_prism(T) - CHECK_TICK //we may be going over a hell of a lot of turfs + to_chat(user, "You need more fuel!") + switched_off(user) + else + to_chat(user, "You switch [src] off.") + playsound(loc, deac_sound, 50, 1) + switched_off(user) -/obj/structure/destructible/clockwork/powered/prolonging_prism/proc/get_delay_cost() - return Floor(delay_cost, MIN_CLOCKCULT_POWER) +//Switches the welder off +/obj/item/weldingtool/proc/switched_off(mob/user) + welding = 0 + set_light(0) -/obj/structure/destructible/clockwork/powered/prolonging_prism/proc/seven_random_hexes(turf/T, efficiency) - var/static/list/hex_states = list("prismhex1", "prismhex2", "prismhex3", "prismhex4", "prismhex5", "prismhex6", "prismhex7") - var/mutable_appearance/hex_combo - for(var/n in hex_states) //BUILD ME A HEXAGON - if(prob(50 * efficiency)) - if(!hex_combo) - hex_combo = mutable_appearance('icons/effects/64x64.dmi', n, RIPPLE_LAYER) - else - hex_combo.add_overlay(mutable_appearance('icons/effects/64x64.dmi', n, RIPPLE_LAYER)) - if(hex_combo) //YOU BUILT A HEXAGON - hex_combo.pixel_x = -16 - hex_combo.pixel_y = -16 - hex_combo.mouse_opacity = MOUSE_OPACITY_TRANSPARENT - hex_combo.plane = GAME_PLANE - new /obj/effect/temp_visual/ratvar/prolonging_prism(T, hex_combo) + force = 3 + damtype = "brute" + hitsound = "swing_hit" + update_icon() + + +/obj/item/weldingtool/examine(mob/user) + ..() + to_chat(user, "It contains [get_fuel()] unit\s of fuel out of [max_fuel].") + +/obj/item/weldingtool/is_hot() + return welding * heat + +//Returns whether or not the welding tool is currently on. +/obj/item/weldingtool/proc/isOn() + return welding + + +/obj/item/weldingtool/proc/flamethrower_screwdriver(obj/item/I, mob/user) + if(welding) + to_chat(user, "Turn it off first!") + return + status = !status + if(status) + to_chat(user, "You resecure [src].") + else + to_chat(user, "[src] can now be attached and modified.") + add_fingerprint(user) + +/obj/item/weldingtool/proc/flamethrower_rods(obj/item/I, mob/user) + if(!status) + var/obj/item/stack/rods/R = I + if (R.use(1)) + var/obj/item/flamethrower/F = new /obj/item/flamethrower(user.loc) + if(!remove_item_from_storage(F)) + user.transferItemToLoc(src, F, TRUE) + F.weldtool = src + add_fingerprint(user) + to_chat(user, "You add a rod to a welder, starting to build a flamethrower.") + user.put_in_hands(F) + else + to_chat(user, "You need one rod to start building a flamethrower!") + +/obj/item/weldingtool/ignition_effect(atom/A, mob/user) + if(welding && remove_fuel(1, user)) + . = "[user] casually lights [A] with [src], what a badass." + else + . = "" + +/obj/item/weldingtool/largetank + name = "industrial welding tool" + desc = "A slightly larger welder with a larger tank." + icon_state = "indwelder" + max_fuel = 40 + materials = list(MAT_GLASS=60) + origin_tech = "engineering=2;plasmatech=2" + +/obj/item/weldingtool/largetank/cyborg + name = "integrated welding tool" + desc = "An advanced welder designed to be used in robotic systems." + toolspeed = 0.5 + +/obj/item/weldingtool/largetank/flamethrower_screwdriver() + return + + +/obj/item/weldingtool/mini + name = "emergency welding tool" + desc = "A miniature welder used during emergencies." + icon_state = "miniwelder" + max_fuel = 10 + w_class = WEIGHT_CLASS_TINY + materials = list(MAT_METAL=30, MAT_GLASS=10) + change_icons = 0 + +/obj/item/weldingtool/mini/flamethrower_screwdriver() + return + +/obj/item/weldingtool/abductor + name = "alien welding tool" + desc = "An alien welding tool. Whatever fuel it uses, it never runs out." + icon = 'icons/obj/abductor.dmi' + icon_state = "welder" + toolspeed = 0.1 + light_intensity = 0 + change_icons = 0 + origin_tech = "plasmatech=5;engineering=5;abductor=3" + +/obj/item/weldingtool/abductor/process() + if(get_fuel() <= max_fuel) + reagents.add_reagent("welding_fuel", 1) + ..() + +/obj/item/weldingtool/hugetank + name = "upgraded industrial welding tool" + desc = "An upgraded welder based of the industrial welder." + icon_state = "upindwelder" + item_state = "upindwelder" + max_fuel = 80 + materials = list(MAT_METAL=70, MAT_GLASS=120) + origin_tech = "engineering=3;plasmatech=2" + +/obj/item/weldingtool/experimental + name = "experimental welding tool" + desc = "An experimental welder capable of self-fuel generation and less harmful to the eyes." + icon_state = "exwelder" + item_state = "exwelder" + max_fuel = 40 + materials = list(MAT_METAL=70, MAT_GLASS=120) + origin_tech = "materials=4;engineering=4;bluespace=3;plasmatech=4" + var/last_gen = 0 + change_icons = 0 + can_off_process = 1 + light_intensity = 1 + toolspeed = 0.5 + var/nextrefueltick = 0 + +/obj/item/weldingtool/experimental/brass + name = "brass welding tool" + desc = "A brass welder that seems to constantly refuel itself. It is faintly warm to the touch." + resistance_flags = FIRE_PROOF | ACID_PROOF + icon_state = "brasswelder" + item_state = "brasswelder" + + +/obj/item/weldingtool/experimental/process() + ..() + if(get_fuel() < max_fuel && nextrefueltick < world.time) + nextrefueltick = world.time + 10 + reagents.add_reagent("welding_fuel", 1) + + +/* + * Crowbar + */ + +/obj/item/crowbar + name = "pocket crowbar" + desc = "A small crowbar. This handy tool is useful for lots of things, such as prying floor tiles or opening unpowered doors." + icon = 'icons/obj/tools.dmi' + icon_state = "crowbar" + lefthand_file = 'icons/mob/inhands/equipment/tools_lefthand.dmi' + righthand_file = 'icons/mob/inhands/equipment/tools_righthand.dmi' + usesound = 'sound/items/crowbar.ogg' + flags_1 = CONDUCT_1 + slot_flags = SLOT_BELT + force = 5 + throwforce = 7 + w_class = WEIGHT_CLASS_SMALL + materials = list(MAT_METAL=50) + origin_tech = "engineering=1;combat=1" + attack_verb = list("attacked", "bashed", "battered", "bludgeoned", "whacked") + toolspeed = 1 + armor = list(melee = 0, bullet = 0, laser = 0, energy = 0, bomb = 0, bio = 0, rad = 0, fire = 50, acid = 30) + +/obj/item/crowbar/suicide_act(mob/user) + user.visible_message("[user] is beating [user.p_them()]self to death with [src]! It looks like [user.p_theyre()] trying to commit suicide!") + playsound(loc, 'sound/weapons/genhit.ogg', 50, 1, -1) + return (BRUTELOSS) + +/obj/item/crowbar/red + icon_state = "crowbar_red" + force = 8 + +/obj/item/crowbar/brass + name = "brass crowbar" + desc = "A brass crowbar. It feels faintly warm to the touch." + resistance_flags = FIRE_PROOF | ACID_PROOF + icon_state = "crowbar_brass" + toolspeed = 0.5 + +/obj/item/crowbar/abductor + name = "alien crowbar" + desc = "A hard-light crowbar. It appears to pry by itself, without any effort required." + icon = 'icons/obj/abductor.dmi' + usesound = 'sound/weapons/sonic_jackhammer.ogg' + icon_state = "crowbar" + toolspeed = 0.1 + origin_tech = "combat=4;engineering=4;abductor=3" + +/obj/item/crowbar/large + name = "crowbar" + desc = "It's a big crowbar. It doesn't fit in your pockets, because it's big." + force = 12 + w_class = WEIGHT_CLASS_NORMAL + throw_speed = 3 + throw_range = 3 + materials = list(MAT_METAL=70) + icon_state = "crowbar_large" + item_state = "crowbar" + toolspeed = 0.5 + +/obj/item/crowbar/cyborg + name = "hydraulic crowbar" + desc = "A hydraulic prying tool, compact but powerful. Designed to replace crowbar in construction cyborgs." + usesound = 'sound/items/jaws_pry.ogg' + force = 10 + toolspeed = 0.5 + +/obj/item/crowbar/power + name = "jaws of life" + desc = "A set of jaws of life, compressed through the magic of science. It's fitted with a prying head." + icon_state = "jaws_pry" + item_state = "jawsoflife" + lefthand_file = 'icons/mob/inhands/equipment/tools_lefthand.dmi' + righthand_file = 'icons/mob/inhands/equipment/tools_righthand.dmi' + materials = list(MAT_METAL=150,MAT_SILVER=50,MAT_TITANIUM=25) + origin_tech = "materials=2;engineering=2" + usesound = 'sound/items/jaws_pry.ogg' + force = 15 + toolspeed = 0.25 + +/obj/item/crowbar/power/suicide_act(mob/user) + user.visible_message("[user] is putting [user.p_their()] head in [src], it looks like [user.p_theyre()] trying to commit suicide!") + playsound(loc, 'sound/items/jaws_pry.ogg', 50, 1, -1) + return (BRUTELOSS) + +/obj/item/crowbar/power/attack_self(mob/user) + playsound(get_turf(user), 'sound/items/change_jaws.ogg', 50, 1) + var/obj/item/wirecutters/power/cutjaws = new /obj/item/wirecutters/power + to_chat(user, "You attach the cutting jaws to [src].") + qdel(src) + user.put_in_active_hand(cutjaws) + +#undef WELDER_FUEL_BURN_INTERVAL From 50587ea679a7df29066ac10d4675f9888e3491ee Mon Sep 17 00:00:00 2001 From: LetterJay Date: Sun, 10 Sep 2017 15:18:30 -0500 Subject: [PATCH 29/74] Update tools.dm --- code/game/objects/items/tools.dm | 1579 ------------------------------ 1 file changed, 1579 deletions(-) diff --git a/code/game/objects/items/tools.dm b/code/game/objects/items/tools.dm index 5c901ca4bd..d3f5a12faa 100644 --- a/code/game/objects/items/tools.dm +++ b/code/game/objects/items/tools.dm @@ -1,1580 +1 @@ -#define WELDER_FUEL_BURN_INTERVAL 13 -/* Tools! - * Note: Multitools are /obj/item/device - * - * Contains: - * Wrench - * Screwdriver - * Wirecutters - * Welding Tool - * Crowbar - */ - -/* - * Wrench - */ -/obj/item/wrench - name = "wrench" - desc = "A wrench with common uses. Can be found in your hand." - icon = 'icons/obj/tools.dmi' - icon_state = "wrench" - lefthand_file = 'icons/mob/inhands/equipment/tools_lefthand.dmi' - righthand_file = 'icons/mob/inhands/equipment/tools_righthand.dmi' - flags_1 = CONDUCT_1 - slot_flags = SLOT_BELT - force = 5 - throwforce = 7 - w_class = WEIGHT_CLASS_SMALL - usesound = 'sound/items/ratchet.ogg' - materials = list(MAT_METAL=150) - origin_tech = "materials=1;engineering=1" - attack_verb = list("bashed", "battered", "bludgeoned", "whacked") - toolspeed = 1 - armor = list(melee = 0, bullet = 0, laser = 0, energy = 0, bomb = 0, bio = 0, rad = 0, fire = 50, acid = 30) - -/obj/item/wrench/suicide_act(mob/user) - user.visible_message("[user] is beating [user.p_them()]self to death with [src]! It looks like [user.p_theyre()] trying to commit suicide!") - playsound(loc, 'sound/weapons/genhit.ogg', 50, 1, -1) - return (BRUTELOSS) - -/obj/item/wrench/cyborg - name = "automatic wrench" - desc = "An advanced robotic wrench. Can be found in construction cyborgs." - toolspeed = 0.5 - -/obj/item/wrench/brass - name = "brass wrench" - desc = "A brass wrench. It's faintly warm to the touch." - resistance_flags = FIRE_PROOF | ACID_PROOF - icon_state = "wrench_brass" - toolspeed = 0.5 - -/obj/item/wrench/abductor - name = "alien wrench" - desc = "A polarized wrench. It causes anything placed between the jaws to turn." - icon = 'icons/obj/abductor.dmi' - icon_state = "wrench" - usesound = 'sound/effects/empulse.ogg' - toolspeed = 0.1 - origin_tech = "materials=5;engineering=5;abductor=3" - -/obj/item/wrench/power - name = "hand drill" - desc = "A simple powered hand drill. It's fitted with a bolt bit." - icon_state = "drill_bolt" - item_state = "drill" - lefthand_file = 'icons/mob/inhands/equipment/tools_lefthand.dmi' - righthand_file = 'icons/mob/inhands/equipment/tools_righthand.dmi' - usesound = 'sound/items/drill_use.ogg' - materials = list(MAT_METAL=150,MAT_SILVER=50,MAT_TITANIUM=25) - origin_tech = "materials=2;engineering=2" //done for balance reasons, making them high value for research, but harder to get - force = 8 //might or might not be too high, subject to change - w_class = WEIGHT_CLASS_SMALL - throwforce = 8 - attack_verb = list("drilled", "screwed", "jabbed") - toolspeed = 0.25 - -/obj/item/wrench/power/attack_self(mob/user) - playsound(get_turf(user),'sound/items/change_drill.ogg',50,1) - var/obj/item/wirecutters/power/s_drill = new /obj/item/screwdriver/power - to_chat(user, "You attach the screw driver bit to [src].") - qdel(src) - user.put_in_active_hand(s_drill) - -/obj/item/wrench/power/suicide_act(mob/user) - user.visible_message("[user] is pressing [src] against [user.p_their()] head! It looks like [user.p_theyre()] trying to commit suicide!") - return (BRUTELOSS) - -/obj/item/wrench/medical - name = "medical wrench" - desc = "A medical wrench with common(medical?) uses. Can be found in your hand." - icon_state = "wrench_medical" - force = 2 //MEDICAL - throwforce = 4 - origin_tech = "materials=1;engineering=1;biotech=3" - attack_verb = list("wrenched", "medicaled", "tapped", "jabbed", "whacked") - -/obj/item/wrench/medical/suicide_act(mob/living/user) - user.visible_message("[user] is praying to the medical wrench to take [user.p_their()] soul. It looks like [user.p_theyre()] trying to commit suicide!") - // TODO Make them glow with the power of the M E D I C A L W R E N C H - // during their ascension - - // Stun stops them from wandering off - user.Stun(100, ignore_canstun = TRUE) - playsound(loc, 'sound/effects/pray.ogg', 50, 1, -1) - - // Let the sound effect finish playing - sleep(20) - - if(!user) - return - - for(var/obj/item/W in user) - user.dropItemToGround(W) - - var/obj/item/wrench/medical/W = new /obj/item/wrench/medical(loc) - W.add_fingerprint(user) - W.desc += " For some reason, it reminds you of [user.name]." - - if(!user) - return - - user.dust() - - return OXYLOSS - -/* - * Screwdriver - */ -/obj/item/screwdriver - name = "screwdriver" - desc = "You can be totally screwy with this." - icon = 'icons/obj/tools.dmi' - icon_state = "screwdriver" - item_state = "screwdriver" - lefthand_file = 'icons/mob/inhands/equipment/tools_lefthand.dmi' - righthand_file = 'icons/mob/inhands/equipment/tools_righthand.dmi' - flags_1 = CONDUCT_1 - slot_flags = SLOT_BELT - force = 5 - w_class = WEIGHT_CLASS_TINY - throwforce = 5 - throw_speed = 3 - throw_range = 5 - materials = list(MAT_METAL=75) - attack_verb = list("stabbed") - hitsound = 'sound/weapons/bladeslice.ogg' - usesound = 'sound/items/screwdriver.ogg' - toolspeed = 1 - armor = list(melee = 0, bullet = 0, laser = 0, energy = 0, bomb = 0, bio = 0, rad = 0, fire = 50, acid = 30) - var/random_color = TRUE //if the screwdriver uses random coloring - var/static/list/screwdriver_colors = list(\ - "blue" = rgb(24, 97, 213), \ - "red" = rgb(149, 23, 16), \ - "pink" = rgb(213, 24, 141), \ - "brown" = rgb(160, 82, 18), \ - "green" = rgb(14, 127, 27), \ - "cyan" = rgb(24, 162, 213), \ - "yellow" = rgb(213, 140, 24), \ - ) - -/obj/item/screwdriver/suicide_act(mob/user) - user.visible_message("[user] is stabbing [src] into [user.p_their()] [pick("temple", "heart")]! It looks like [user.p_theyre()] trying to commit suicide!") - return(BRUTELOSS) - -/obj/item/screwdriver/Initialize() - . = ..() - if(random_color) //random colors! - var/our_color = pick(screwdriver_colors) - add_atom_colour(screwdriver_colors[our_color], FIXED_COLOUR_PRIORITY) - update_icon() - if(prob(75)) - pixel_y = rand(0, 16) - -/obj/item/screwdriver/update_icon() - if(!random_color) //icon override - return - cut_overlays() - var/mutable_appearance/base_overlay = mutable_appearance(icon, "screwdriver_screwybits") - base_overlay.appearance_flags = RESET_COLOR - add_overlay(base_overlay) - -/obj/item/screwdriver/worn_overlays(isinhands = FALSE, icon_file) - . = list() - if(isinhands && random_color) - var/mutable_appearance/M = mutable_appearance(icon_file, "screwdriver_head") - M.appearance_flags = RESET_COLOR - . += M - -/obj/item/screwdriver/get_belt_overlay() - if(random_color) - var/mutable_appearance/body = mutable_appearance('icons/obj/clothing/belt_overlays.dmi', "screwdriver") - var/mutable_appearance/head = mutable_appearance('icons/obj/clothing/belt_overlays.dmi', "screwdriver_head") - body.color = color - head.overlays += body - return head - else - return mutable_appearance('icons/obj/clothing/belt_overlays.dmi', icon_state) - -/obj/item/screwdriver/attack(mob/living/carbon/M, mob/living/carbon/user) - if(!istype(M)) - return ..() - if(user.zone_selected != "eyes" && user.zone_selected != "head") - return ..() - if(user.disabilities & CLUMSY && prob(50)) - M = user - return eyestab(M,user) - -/obj/item/screwdriver/brass - name = "brass screwdriver" - desc = "A screwdriver made of brass. The handle feels freezing cold." - resistance_flags = FIRE_PROOF | ACID_PROOF - icon_state = "screwdriver_brass" - item_state = "screwdriver_brass" - toolspeed = 0.5 - random_color = FALSE - -/obj/item/screwdriver/abductor - name = "alien screwdriver" - desc = "An ultrasonic screwdriver." - icon = 'icons/obj/abductor.dmi' - icon_state = "screwdriver_a" - item_state = "screwdriver_nuke" - usesound = 'sound/items/pshoom.ogg' - toolspeed = 0.1 - random_color = FALSE - -/obj/item/screwdriver/power - name = "hand drill" - desc = "A simple powered hand drill. It's fitted with a screw bit." - icon_state = "drill_screw" - item_state = "drill" - lefthand_file = 'icons/mob/inhands/equipment/tools_lefthand.dmi' - righthand_file = 'icons/mob/inhands/equipment/tools_righthand.dmi' - materials = list(MAT_METAL=150,MAT_SILVER=50,MAT_TITANIUM=25) - origin_tech = "materials=2;engineering=2" //done for balance reasons, making them high value for research, but harder to get - force = 8 //might or might not be too high, subject to change - w_class = WEIGHT_CLASS_SMALL - throwforce = 8 - throw_speed = 2 - throw_range = 3//it's heavier than a screw driver/wrench, so it does more damage, but can't be thrown as far - attack_verb = list("drilled", "screwed", "jabbed","whacked") - hitsound = 'sound/items/drill_hit.ogg' - usesound = 'sound/items/drill_use.ogg' - toolspeed = 0.25 - random_color = FALSE - -/obj/item/screwdriver/power/suicide_act(mob/user) - user.visible_message("[user] is putting [src] to [user.p_their()] temple. It looks like [user.p_theyre()] trying to commit suicide!") - return(BRUTELOSS) - -/obj/item/screwdriver/power/attack_self(mob/user) - playsound(get_turf(user),'sound/items/change_drill.ogg',50,1) - var/obj/item/wrench/power/b_drill = new /obj/item/wrench/power - to_chat(user, "You attach the bolt driver bit to [src].") - qdel(src) - user.put_in_active_hand(b_drill) - -/obj/item/screwdriver/cyborg - name = "powered screwdriver" - desc = "An electrical screwdriver, designed to be both precise and quick." - usesound = 'sound/items/drill_use.ogg' - toolspeed = 0.5 - -/* - * Wirecutters - */ -/obj/item/wirecutters - name = "wirecutters" - desc = "This cuts wires." - icon = 'icons/obj/tools.dmi' - icon_state = null - lefthand_file = 'icons/mob/inhands/equipment/tools_lefthand.dmi' - righthand_file = 'icons/mob/inhands/equipment/tools_righthand.dmi' - flags_1 = CONDUCT_1 - slot_flags = SLOT_BELT - force = 6 - throw_speed = 3 - throw_range = 7 - w_class = WEIGHT_CLASS_SMALL - materials = list(MAT_METAL=80) - attack_verb = list("pinched", "nipped") - hitsound = 'sound/items/wirecutter.ogg' - usesound = 'sound/items/wirecutter.ogg' - origin_tech = "materials=1;engineering=1" - toolspeed = 1 - armor = list(melee = 0, bullet = 0, laser = 0, energy = 0, bomb = 0, bio = 0, rad = 0, fire = 50, acid = 30) - - -/obj/item/wirecutters/New(loc, var/param_color = null) - ..() - if(!icon_state) - if(!param_color) - param_color = pick("yellow","red") - icon_state = "cutters_[param_color]" - -/obj/item/wirecutters/attack(mob/living/carbon/C, mob/user) - if(istype(C) && C.handcuffed && istype(C.handcuffed, /obj/item/restraints/handcuffs/cable)) - user.visible_message("[user] cuts [C]'s restraints with [src]!") - qdel(C.handcuffed) - C.handcuffed = null - if(C.buckled && C.buckled.buckle_requires_restraints) - C.buckled.unbuckle_mob(C) - C.update_handcuffed() - return - else - ..() - -/obj/item/wirecutters/suicide_act(mob/user) - user.visible_message("[user] is cutting at [user.p_their()] arteries with [src]! It looks like [user.p_theyre()] trying to commit suicide!") - playsound(loc, usesound, 50, 1, -1) - return (BRUTELOSS) - -/obj/item/wirecutters/brass - name = "brass wirecutters" - desc = "A pair of wirecutters made of brass. The handle feels freezing cold to the touch." - resistance_flags = FIRE_PROOF | ACID_PROOF - icon_state = "cutters_brass" - toolspeed = 0.5 - -/obj/item/wirecutters/abductor - name = "alien wirecutters" - desc = "Extremely sharp wirecutters, made out of a silvery-green metal." - icon = 'icons/obj/abductor.dmi' - icon_state = "cutters" - toolspeed = 0.1 - origin_tech = "materials=5;engineering=4;abductor=3" - -/obj/item/wirecutters/cyborg - name = "wirecutters" - desc = "This cuts wires." - toolspeed = 0.5 - -/obj/item/wirecutters/power - name = "jaws of life" - desc = "A set of jaws of life, compressed through the magic of science. It's fitted with a cutting head." - icon_state = "jaws_cutter" - item_state = "jawsoflife" - origin_tech = "materials=2;engineering=2" - materials = list(MAT_METAL=150,MAT_SILVER=50,MAT_TITANIUM=25) - usesound = 'sound/items/jaws_cut.ogg' - toolspeed = 0.25 - -/obj/item/wirecutters/power/suicide_act(mob/user) - user.visible_message("[user] is wrapping \the [src] around [user.p_their()] neck. It looks like [user.p_theyre()] trying to rip [user.p_their()] head off!") - playsound(loc, 'sound/items/jaws_cut.ogg', 50, 1, -1) - if(iscarbon(user)) - var/mob/living/carbon/C = user - var/obj/item/bodypart/BP = C.get_bodypart("head") - if(BP) - BP.drop_limb() - playsound(loc,pick('sound/misc/desceration-01.ogg','sound/misc/desceration-02.ogg','sound/misc/desceration-01.ogg') ,50, 1, -1) - return (BRUTELOSS) - -/obj/item/wirecutters/power/attack_self(mob/user) - playsound(get_turf(user), 'sound/items/change_jaws.ogg', 50, 1) - var/obj/item/crowbar/power/pryjaws = new /obj/item/crowbar/power - to_chat(user, "You attach the pry jaws to [src].") - qdel(src) - user.put_in_active_hand(pryjaws) -/* - * Welding Tool - */ -/obj/item/weldingtool - name = "welding tool" - desc = "A standard edition welder provided by NanoTrasen." - icon = 'icons/obj/tools.dmi' - icon_state = "welder" - item_state = "welder" - lefthand_file = 'icons/mob/inhands/equipment/tools_lefthand.dmi' - righthand_file = 'icons/mob/inhands/equipment/tools_righthand.dmi' - flags_1 = CONDUCT_1 - slot_flags = SLOT_BELT - force = 3 - throwforce = 5 - hitsound = "swing_hit" - usesound = 'sound/items/welder.ogg' - var/acti_sound = 'sound/items/welderactivate.ogg' - var/deac_sound = 'sound/items/welderdeactivate.ogg' - throw_speed = 3 - throw_range = 5 - w_class = WEIGHT_CLASS_SMALL - armor = list(melee = 0, bullet = 0, laser = 0, energy = 0, bomb = 0, bio = 0, rad = 0, fire = 100, acid = 30) - resistance_flags = FIRE_PROOF - - materials = list(MAT_METAL=70, MAT_GLASS=30) - origin_tech = "engineering=1;plasmatech=1" - var/welding = 0 //Whether or not the welding tool is off(0), on(1) or currently welding(2) - var/status = TRUE //Whether the welder is secured or unsecured (able to attach rods to it to make a flamethrower) - var/max_fuel = 20 //The max amount of fuel the welder can hold - var/change_icons = 1 - var/can_off_process = 0 - var/light_intensity = 2 //how powerful the emitted light is when used. - var/burned_fuel_for = 0 //when fuel was last removed - heat = 3800 - toolspeed = 1 - -/obj/item/weldingtool/Initialize() - . = ..() - create_reagents(max_fuel) - reagents.add_reagent("welding_fuel", max_fuel) - update_icon() - - -/obj/item/weldingtool/proc/update_torch() - if(welding) - add_overlay("[initial(icon_state)]-on") - item_state = "[initial(item_state)]1" - else - item_state = "[initial(item_state)]" - - -/obj/item/weldingtool/update_icon() - cut_overlays() - if(change_icons) - var/ratio = get_fuel() / max_fuel - ratio = Ceiling(ratio*4) * 25 - add_overlay("[initial(icon_state)][ratio]") - update_torch() - return - - -/obj/item/weldingtool/process() - switch(welding) - if(0) - force = 3 - damtype = "brute" - update_icon() - if(!can_off_process) - STOP_PROCESSING(SSobj, src) - return - //Welders left on now use up fuel, but lets not have them run out quite that fast - if(1) - force = 15 - damtype = "fire" - ++burned_fuel_for - if(burned_fuel_for >= WELDER_FUEL_BURN_INTERVAL) - remove_fuel(1) - update_icon() - - //This is to start fires. process() is only called if the welder is on. - open_flame() - - -/obj/item/weldingtool/suicide_act(mob/user) - user.visible_message("[user] welds [user.p_their()] every orifice closed! It looks like [user.p_theyre()] trying to commit suicide!") - return (FIRELOSS) - - -/obj/item/weldingtool/attackby(obj/item/I, mob/user, params) - if(istype(I, /obj/item/screwdriver)) - flamethrower_screwdriver(I, user) - else if(istype(I, /obj/item/stack/rods)) - flamethrower_rods(I, user) - else - return ..() - - -/obj/item/weldingtool/attack(mob/living/carbon/human/H, mob/user) - if(!istype(H)) - return ..() - - var/obj/item/bodypart/affecting = H.get_bodypart(check_zone(user.zone_selected)) - - if(affecting && affecting.status == BODYPART_ROBOTIC && user.a_intent != INTENT_HARM) - if(src.remove_fuel(1)) - playsound(loc, usesound, 50, 1) - if(user == H) - user.visible_message("[user] starts to fix some of the dents on [H]'s [affecting.name].", "You start fixing some of the dents on [H]'s [affecting.name].") - if(!do_mob(user, H, 50)) - return - item_heal_robotic(H, user, 15, 0) - else - return ..() - - -/obj/item/weldingtool/afterattack(atom/O, mob/user, proximity) - if(!proximity) return - - if(welding) - remove_fuel(1) - var/turf/location = get_turf(user) - location.hotspot_expose(700, 50, 1) - if(get_fuel() <= 0) - set_light(0) - - if(isliving(O)) - var/mob/living/L = O - if(L.IgniteMob()) - message_admins("[key_name_admin(user)] set [key_name_admin(L)] on fire") - log_game("[key_name(user)] set [key_name(L)] on fire") - - -/obj/item/weldingtool/attack_self(mob/user) - switched_on(user) - if(welding) - set_light(light_intensity) - - update_icon() - - -//Returns the amount of fuel in the welder -/obj/item/weldingtool/proc/get_fuel() - return reagents.get_reagent_amount("welding_fuel") - - -//Removes fuel from the welding tool. If a mob is passed, it will try to flash the mob's eyes. This should probably be renamed to use() -/obj/item/weldingtool/proc/remove_fuel(amount = 1, mob/living/M = null) - if(!welding || !check_fuel()) - return 0 - if(amount) - burned_fuel_for = 0 - if(get_fuel() >= amount) - reagents.remove_reagent("welding_fuel", amount) - check_fuel() - if(M) - M.flash_act(light_intensity) - return TRUE - else - if(M) - to_chat(M, "You need more welding fuel to complete this task!") - return FALSE - - -//Turns off the welder if there is no more fuel (does this really need to be its own proc?) -/obj/item/weldingtool/proc/check_fuel(mob/user) - if(get_fuel() <= 0 && welding) - switched_on(user) - update_icon() - //mob icon update - if(ismob(loc)) - var/mob/M = loc - M.update_inv_hands(0) - - return 0 - return 1 - -//Switches the welder on -/obj/item/weldingtool/proc/switched_on(mob/user) - if(!status) - to_chat(user, "[src] can't be turned on while unsecured!") - return - welding = !welding - if(welding) - if(get_fuel() >= 1) - to_chat(user, "You switch [src] on.") - playsound(loc, acti_sound, 50, 1) - force = 15 - damtype = "fire" - hitsound = 'sound/items/welder.ogg' - update_icon() - START_PROCESSING(SSobj, src) - else - to_chat(user, "You need more fuel!") - switched_off(user) - else - to_chat(user, "You switch [src] off.") - playsound(loc, deac_sound, 50, 1) - switched_off(user) - -//Switches the welder off -/obj/item/weldingtool/proc/switched_off(mob/user) - welding = 0 - set_light(0) - - force = 3 - damtype = "brute" - hitsound = "swing_hit" - update_icon() - - -/obj/item/weldingtool/examine(mob/user) - ..() - to_chat(user, "It contains [get_fuel()] unit\s of fuel out of [max_fuel].") - -/obj/item/weldingtool/is_hot() - return welding * heat - -//Returns whether or not the welding tool is currently on. -/obj/item/weldingtool/proc/isOn() - return welding - - -/obj/item/weldingtool/proc/flamethrower_screwdriver(obj/item/I, mob/user) - if(welding) - to_chat(user, "Turn it off first!") - return - status = !status - if(status) - to_chat(user, "You resecure [src].") - else - to_chat(user, "[src] can now be attached and modified.") - add_fingerprint(user) - -/obj/item/weldingtool/proc/flamethrower_rods(obj/item/I, mob/user) - if(!status) - var/obj/item/stack/rods/R = I - if (R.use(1)) - var/obj/item/flamethrower/F = new /obj/item/flamethrower(user.loc) - if(!remove_item_from_storage(F)) - user.transferItemToLoc(src, F, TRUE) - F.weldtool = src - add_fingerprint(user) - to_chat(user, "You add a rod to a welder, starting to build a flamethrower.") - user.put_in_hands(F) - else - to_chat(user, "You need one rod to start building a flamethrower!") - -/obj/item/weldingtool/ignition_effect(atom/A, mob/user) - if(welding && remove_fuel(1, user)) - . = "[user] casually lights [A] with [src], what a badass." - else - . = "" - -/obj/item/weldingtool/largetank - name = "industrial welding tool" - desc = "A slightly larger welder with a larger tank." - icon_state = "indwelder" - max_fuel = 40 - materials = list(MAT_GLASS=60) - origin_tech = "engineering=2;plasmatech=2" - -/obj/item/weldingtool/largetank/cyborg - name = "integrated welding tool" - desc = "An advanced welder designed to be used in robotic systems." - toolspeed = 0.5 - -/obj/item/weldingtool/largetank/flamethrower_screwdriver() - return - - -/obj/item/weldingtool/mini - name = "emergency welding tool" - desc = "A miniature welder used during emergencies." - icon_state = "miniwelder" - max_fuel = 10 - w_class = WEIGHT_CLASS_TINY - materials = list(MAT_METAL=30, MAT_GLASS=10) - change_icons = 0 - -/obj/item/weldingtool/mini/flamethrower_screwdriver() - return - -/obj/item/weldingtool/abductor - name = "alien welding tool" - desc = "An alien welding tool. Whatever fuel it uses, it never runs out." - icon = 'icons/obj/abductor.dmi' - icon_state = "welder" - toolspeed = 0.1 - light_intensity = 0 - change_icons = 0 - origin_tech = "plasmatech=5;engineering=5;abductor=3" - -/obj/item/weldingtool/abductor/process() - if(get_fuel() <= max_fuel) - reagents.add_reagent("welding_fuel", 1) - ..() - -/obj/item/weldingtool/hugetank - name = "upgraded industrial welding tool" - desc = "An upgraded welder based of the industrial welder." - icon_state = "upindwelder" - item_state = "upindwelder" - max_fuel = 80 - materials = list(MAT_METAL=70, MAT_GLASS=120) - origin_tech = "engineering=3;plasmatech=2" - -/obj/item/weldingtool/experimental - name = "experimental welding tool" - desc = "An experimental welder capable of self-fuel generation and less harmful to the eyes." - icon_state = "exwelder" - item_state = "exwelder" - max_fuel = 40 - materials = list(MAT_METAL=70, MAT_GLASS=120) - origin_tech = "materials=4;engineering=4;bluespace=3;plasmatech=4" - var/last_gen = 0 - change_icons = 0 - can_off_process = 1 - light_intensity = 1 - toolspeed = 0.5 - var/nextrefueltick = 0 - -/obj/item/weldingtool/experimental/brass - name = "brass welding tool" - desc = "A brass welder that seems to constantly refuel itself. It is faintly warm to the touch." - resistance_flags = FIRE_PROOF | ACID_PROOF - icon_state = "brasswelder" - item_state = "brasswelder" - - -/obj/item/weldingtool/experimental/process() - ..() - if(get_fuel() < max_fuel && nextrefueltick < world.time) - nextrefueltick = world.time + 10 - reagents.add_reagent("welding_fuel", 1) - - -/* - * Crowbar - */ - -/obj/item/crowbar - name = "pocket crowbar" - desc = "A small crowbar. This handy tool is useful for lots of things, such as prying floor tiles or opening unpowered doors." - icon = 'icons/obj/tools.dmi' - icon_state = "crowbar" - lefthand_file = 'icons/mob/inhands/equipment/tools_lefthand.dmi' - righthand_file = 'icons/mob/inhands/equipment/tools_righthand.dmi' - usesound = 'sound/items/crowbar.ogg' - flags_1 = CONDUCT_1 - slot_flags = SLOT_BELT - force = 5 - throwforce = 7 - w_class = WEIGHT_CLASS_SMALL - materials = list(MAT_METAL=50) - origin_tech = "engineering=1;combat=1" - attack_verb = list("attacked", "bashed", "battered", "bludgeoned", "whacked") - toolspeed = 1 - armor = list(melee = 0, bullet = 0, laser = 0, energy = 0, bomb = 0, bio = 0, rad = 0, fire = 50, acid = 30) - -/obj/item/crowbar/suicide_act(mob/user) - user.visible_message("[user] is beating [user.p_them()]self to death with [src]! It looks like [user.p_theyre()] trying to commit suicide!") - playsound(loc, 'sound/weapons/genhit.ogg', 50, 1, -1) - return (BRUTELOSS) - -/obj/item/crowbar/red - icon_state = "crowbar_red" - force = 8 - -/obj/item/crowbar/brass - name = "brass crowbar" - desc = "A brass crowbar. It feels faintly warm to the touch." - resistance_flags = FIRE_PROOF | ACID_PROOF - icon_state = "crowbar_brass" - toolspeed = 0.5 - -/obj/item/crowbar/abductor - name = "alien crowbar" - desc = "A hard-light crowbar. It appears to pry by itself, without any effort required." - icon = 'icons/obj/abductor.dmi' - usesound = 'sound/weapons/sonic_jackhammer.ogg' - icon_state = "crowbar" - toolspeed = 0.1 - origin_tech = "combat=4;engineering=4;abductor=3" - -/obj/item/crowbar/large - name = "crowbar" - desc = "It's a big crowbar. It doesn't fit in your pockets, because it's big." - force = 12 - w_class = WEIGHT_CLASS_NORMAL - throw_speed = 3 - throw_range = 3 - materials = list(MAT_METAL=70) - icon_state = "crowbar_large" - item_state = "crowbar" - toolspeed = 0.5 - -/obj/item/crowbar/cyborg - name = "hydraulic crowbar" - desc = "A hydraulic prying tool, compact but powerful. Designed to replace crowbar in construction cyborgs." - usesound = 'sound/items/jaws_pry.ogg' - force = 10 - toolspeed = 0.5 - -/obj/item/crowbar/power - name = "jaws of life" - desc = "A set of jaws of life, compressed through the magic of science. It's fitted with a prying head." - icon_state = "jaws_pry" - item_state = "jawsoflife" - lefthand_file = 'icons/mob/inhands/equipment/tools_lefthand.dmi' - righthand_file = 'icons/mob/inhands/equipment/tools_righthand.dmi' - materials = list(MAT_METAL=150,MAT_SILVER=50,MAT_TITANIUM=25) - origin_tech = "materials=2;engineering=2" - usesound = 'sound/items/jaws_pry.ogg' - force = 15 - toolspeed = 0.25 - -/obj/item/crowbar/power/suicide_act(mob/user) - user.visible_message("[user] is putting [user.p_their()] head in [src], it looks like [user.p_theyre()] trying to commit suicide!") - playsound(loc, 'sound/items/jaws_pry.ogg', 50, 1, -1) - return (BRUTELOSS) - -/obj/item/crowbar/power/attack_self(mob/user) - playsound(get_turf(user), 'sound/items/change_jaws.ogg', 50, 1) - var/obj/item/wirecutters/power/cutjaws = new /obj/item/wirecutters/power - to_chat(user, "You attach the cutting jaws to [src].") - qdel(src) - user.put_in_active_hand(cutjaws) - -#undef WELDER_FUEL_BURN_INTERVAL -#define WELDER_FUEL_BURN_INTERVAL 13 - -/* Tools! - * Note: Multitools are /obj/item/device - * - * Contains: - * Wrench - * Screwdriver - * Wirecutters - * Welding Tool - * Crowbar - */ - -/* - * Wrench - */ -/obj/item/wrench - name = "wrench" - desc = "A wrench with common uses. Can be found in your hand." - icon = 'icons/obj/tools.dmi' - icon_state = "wrench" - lefthand_file = 'icons/mob/inhands/equipment/tools_lefthand.dmi' - righthand_file = 'icons/mob/inhands/equipment/tools_righthand.dmi' - flags_1 = CONDUCT_1 - slot_flags = SLOT_BELT - force = 5 - throwforce = 7 - w_class = WEIGHT_CLASS_SMALL - usesound = 'sound/items/ratchet.ogg' - materials = list(MAT_METAL=150) - origin_tech = "materials=1;engineering=1" - attack_verb = list("bashed", "battered", "bludgeoned", "whacked") - toolspeed = 1 - armor = list(melee = 0, bullet = 0, laser = 0, energy = 0, bomb = 0, bio = 0, rad = 0, fire = 50, acid = 30) - -/obj/item/wrench/suicide_act(mob/user) - user.visible_message("[user] is beating [user.p_them()]self to death with [src]! It looks like [user.p_theyre()] trying to commit suicide!") - playsound(loc, 'sound/weapons/genhit.ogg', 50, 1, -1) - return (BRUTELOSS) - -/obj/item/wrench/cyborg - name = "automatic wrench" - desc = "An advanced robotic wrench. Can be found in construction cyborgs." - toolspeed = 0.5 - -/obj/item/wrench/brass - name = "brass wrench" - desc = "A brass wrench. It's faintly warm to the touch." - resistance_flags = FIRE_PROOF | ACID_PROOF - icon_state = "wrench_brass" - toolspeed = 0.5 - -/obj/item/wrench/abductor - name = "alien wrench" - desc = "A polarized wrench. It causes anything placed between the jaws to turn." - icon = 'icons/obj/abductor.dmi' - icon_state = "wrench" - usesound = 'sound/effects/empulse.ogg' - toolspeed = 0.1 - origin_tech = "materials=5;engineering=5;abductor=3" - -/obj/item/wrench/power - name = "hand drill" - desc = "A simple powered hand drill. It's fitted with a bolt bit." - icon_state = "drill_bolt" - item_state = "drill" - lefthand_file = 'icons/mob/inhands/equipment/tools_lefthand.dmi' - righthand_file = 'icons/mob/inhands/equipment/tools_righthand.dmi' - usesound = 'sound/items/drill_use.ogg' - materials = list(MAT_METAL=150,MAT_SILVER=50,MAT_TITANIUM=25) - origin_tech = "materials=2;engineering=2" //done for balance reasons, making them high value for research, but harder to get - force = 8 //might or might not be too high, subject to change - w_class = WEIGHT_CLASS_SMALL - throwforce = 8 - attack_verb = list("drilled", "screwed", "jabbed") - toolspeed = 0.25 - -/obj/item/wrench/power/attack_self(mob/user) - playsound(get_turf(user),'sound/items/change_drill.ogg',50,1) - var/obj/item/wirecutters/power/s_drill = new /obj/item/screwdriver/power - to_chat(user, "You attach the screw driver bit to [src].") - qdel(src) - user.put_in_active_hand(s_drill) - -/obj/item/wrench/power/suicide_act(mob/user) - user.visible_message("[user] is pressing [src] against [user.p_their()] head! It looks like [user.p_theyre()] trying to commit suicide!") - return (BRUTELOSS) - -/obj/item/wrench/medical - name = "medical wrench" - desc = "A medical wrench with common(medical?) uses. Can be found in your hand." - icon_state = "wrench_medical" - force = 2 //MEDICAL - throwforce = 4 - origin_tech = "materials=1;engineering=1;biotech=3" - attack_verb = list("wrenched", "medicaled", "tapped", "jabbed", "whacked") - -/obj/item/wrench/medical/suicide_act(mob/living/user) - user.visible_message("[user] is praying to the medical wrench to take [user.p_their()] soul. It looks like [user.p_theyre()] trying to commit suicide!") - // TODO Make them glow with the power of the M E D I C A L W R E N C H - // during their ascension - - // Stun stops them from wandering off - user.Stun(100, ignore_canstun = TRUE) - playsound(loc, 'sound/effects/pray.ogg', 50, 1, -1) - - // Let the sound effect finish playing - sleep(20) - - if(!user) - return - - for(var/obj/item/W in user) - user.dropItemToGround(W) - - var/obj/item/wrench/medical/W = new /obj/item/wrench/medical(loc) - W.add_fingerprint(user) - W.desc += " For some reason, it reminds you of [user.name]." - - if(!user) - return - - user.dust() - - return OXYLOSS - -/* - * Screwdriver - */ -/obj/item/screwdriver - name = "screwdriver" - desc = "You can be totally screwy with this." - icon = 'icons/obj/tools.dmi' - icon_state = "screwdriver" - item_state = "screwdriver" - lefthand_file = 'icons/mob/inhands/equipment/tools_lefthand.dmi' - righthand_file = 'icons/mob/inhands/equipment/tools_righthand.dmi' - flags_1 = CONDUCT_1 - slot_flags = SLOT_BELT - force = 5 - w_class = WEIGHT_CLASS_TINY - throwforce = 5 - throw_speed = 3 - throw_range = 5 - materials = list(MAT_METAL=75) - attack_verb = list("stabbed") - hitsound = 'sound/weapons/bladeslice.ogg' - usesound = 'sound/items/screwdriver.ogg' - toolspeed = 1 - armor = list(melee = 0, bullet = 0, laser = 0, energy = 0, bomb = 0, bio = 0, rad = 0, fire = 50, acid = 30) - var/random_color = TRUE //if the screwdriver uses random coloring - var/static/list/screwdriver_colors = list(\ - "blue" = rgb(24, 97, 213), \ - "red" = rgb(149, 23, 16), \ - "pink" = rgb(213, 24, 141), \ - "brown" = rgb(160, 82, 18), \ - "green" = rgb(14, 127, 27), \ - "cyan" = rgb(24, 162, 213), \ - "yellow" = rgb(213, 140, 24), \ - ) - -/obj/item/screwdriver/suicide_act(mob/user) - user.visible_message("[user] is stabbing [src] into [user.p_their()] [pick("temple", "heart")]! It looks like [user.p_theyre()] trying to commit suicide!") - return(BRUTELOSS) - -/obj/item/screwdriver/Initialize() - . = ..() - if(random_color) //random colors! - var/our_color = pick(screwdriver_colors) - add_atom_colour(screwdriver_colors[our_color], FIXED_COLOUR_PRIORITY) - update_icon() - if(prob(75)) - pixel_y = rand(0, 16) - -/obj/item/screwdriver/update_icon() - if(!random_color) //icon override - return - cut_overlays() - var/mutable_appearance/base_overlay = mutable_appearance(icon, "screwdriver_screwybits") - base_overlay.appearance_flags = RESET_COLOR - add_overlay(base_overlay) - -/obj/item/screwdriver/worn_overlays(isinhands = FALSE, icon_file) - . = list() - if(isinhands && random_color) - var/mutable_appearance/M = mutable_appearance(icon_file, "screwdriver_head") - M.appearance_flags = RESET_COLOR - . += M - -/obj/item/screwdriver/get_belt_overlay() - if(random_color) - var/mutable_appearance/body = mutable_appearance('icons/obj/clothing/belt_overlays.dmi', "screwdriver") - var/mutable_appearance/head = mutable_appearance('icons/obj/clothing/belt_overlays.dmi', "screwdriver_head") - body.color = color - head.add_overlay(body) - return head - else - return mutable_appearance('icons/obj/clothing/belt_overlays.dmi', icon_state) - -/obj/item/screwdriver/attack(mob/living/carbon/M, mob/living/carbon/user) - if(!istype(M)) - return ..() - if(user.zone_selected != "eyes" && user.zone_selected != "head") - return ..() - if(user.disabilities & CLUMSY && prob(50)) - M = user - return eyestab(M,user) - -/obj/item/screwdriver/brass - name = "brass screwdriver" - desc = "A screwdriver made of brass. The handle feels freezing cold." - resistance_flags = FIRE_PROOF | ACID_PROOF - icon_state = "screwdriver_brass" - item_state = "screwdriver_brass" - toolspeed = 0.5 - random_color = FALSE - -/obj/item/screwdriver/abductor - name = "alien screwdriver" - desc = "An ultrasonic screwdriver." - icon = 'icons/obj/abductor.dmi' - icon_state = "screwdriver_a" - item_state = "screwdriver_nuke" - usesound = 'sound/items/pshoom.ogg' - toolspeed = 0.1 - random_color = FALSE - -/obj/item/screwdriver/power - name = "hand drill" - desc = "A simple powered hand drill. It's fitted with a screw bit." - icon_state = "drill_screw" - item_state = "drill" - lefthand_file = 'icons/mob/inhands/equipment/tools_lefthand.dmi' - righthand_file = 'icons/mob/inhands/equipment/tools_righthand.dmi' - materials = list(MAT_METAL=150,MAT_SILVER=50,MAT_TITANIUM=25) - origin_tech = "materials=2;engineering=2" //done for balance reasons, making them high value for research, but harder to get - force = 8 //might or might not be too high, subject to change - w_class = WEIGHT_CLASS_SMALL - throwforce = 8 - throw_speed = 2 - throw_range = 3//it's heavier than a screw driver/wrench, so it does more damage, but can't be thrown as far - attack_verb = list("drilled", "screwed", "jabbed","whacked") - hitsound = 'sound/items/drill_hit.ogg' - usesound = 'sound/items/drill_use.ogg' - toolspeed = 0.25 - random_color = FALSE - -/obj/item/screwdriver/power/suicide_act(mob/user) - user.visible_message("[user] is putting [src] to [user.p_their()] temple. It looks like [user.p_theyre()] trying to commit suicide!") - return(BRUTELOSS) - -/obj/item/screwdriver/power/attack_self(mob/user) - playsound(get_turf(user),'sound/items/change_drill.ogg',50,1) - var/obj/item/wrench/power/b_drill = new /obj/item/wrench/power - to_chat(user, "You attach the bolt driver bit to [src].") - qdel(src) - user.put_in_active_hand(b_drill) - -/obj/item/screwdriver/cyborg - name = "powered screwdriver" - desc = "An electrical screwdriver, designed to be both precise and quick." - usesound = 'sound/items/drill_use.ogg' - toolspeed = 0.5 - -/* - * Wirecutters - */ -/obj/item/wirecutters - name = "wirecutters" - desc = "This cuts wires." - icon = 'icons/obj/tools.dmi' - icon_state = null - lefthand_file = 'icons/mob/inhands/equipment/tools_lefthand.dmi' - righthand_file = 'icons/mob/inhands/equipment/tools_righthand.dmi' - flags_1 = CONDUCT_1 - slot_flags = SLOT_BELT - force = 6 - throw_speed = 3 - throw_range = 7 - w_class = WEIGHT_CLASS_SMALL - materials = list(MAT_METAL=80) - attack_verb = list("pinched", "nipped") - hitsound = 'sound/items/wirecutter.ogg' - usesound = 'sound/items/wirecutter.ogg' - origin_tech = "materials=1;engineering=1" - toolspeed = 1 - armor = list(melee = 0, bullet = 0, laser = 0, energy = 0, bomb = 0, bio = 0, rad = 0, fire = 50, acid = 30) - - -/obj/item/wirecutters/New(loc, var/param_color = null) - ..() - if(!icon_state) - if(!param_color) - param_color = pick("yellow","red") - icon_state = "cutters_[param_color]" - -/obj/item/wirecutters/attack(mob/living/carbon/C, mob/user) - if(istype(C) && C.handcuffed && istype(C.handcuffed, /obj/item/restraints/handcuffs/cable)) - user.visible_message("[user] cuts [C]'s restraints with [src]!") - qdel(C.handcuffed) - C.handcuffed = null - if(C.buckled && C.buckled.buckle_requires_restraints) - C.buckled.unbuckle_mob(C) - C.update_handcuffed() - return - else - ..() - -/obj/item/wirecutters/suicide_act(mob/user) - user.visible_message("[user] is cutting at [user.p_their()] arteries with [src]! It looks like [user.p_theyre()] trying to commit suicide!") - playsound(loc, usesound, 50, 1, -1) - return (BRUTELOSS) - -/obj/item/wirecutters/brass - name = "brass wirecutters" - desc = "A pair of wirecutters made of brass. The handle feels freezing cold to the touch." - resistance_flags = FIRE_PROOF | ACID_PROOF - icon_state = "cutters_brass" - toolspeed = 0.5 - -/obj/item/wirecutters/abductor - name = "alien wirecutters" - desc = "Extremely sharp wirecutters, made out of a silvery-green metal." - icon = 'icons/obj/abductor.dmi' - icon_state = "cutters" - toolspeed = 0.1 - origin_tech = "materials=5;engineering=4;abductor=3" - -/obj/item/wirecutters/cyborg - name = "wirecutters" - desc = "This cuts wires." - toolspeed = 0.5 - -/obj/item/wirecutters/power - name = "jaws of life" - desc = "A set of jaws of life, compressed through the magic of science. It's fitted with a cutting head." - icon_state = "jaws_cutter" - item_state = "jawsoflife" - origin_tech = "materials=2;engineering=2" - materials = list(MAT_METAL=150,MAT_SILVER=50,MAT_TITANIUM=25) - usesound = 'sound/items/jaws_cut.ogg' - toolspeed = 0.25 - -/obj/item/wirecutters/power/suicide_act(mob/user) - user.visible_message("[user] is wrapping \the [src] around [user.p_their()] neck. It looks like [user.p_theyre()] trying to rip [user.p_their()] head off!") - playsound(loc, 'sound/items/jaws_cut.ogg', 50, 1, -1) - if(iscarbon(user)) - var/mob/living/carbon/C = user - var/obj/item/bodypart/BP = C.get_bodypart("head") - if(BP) - BP.drop_limb() - playsound(loc,pick('sound/misc/desceration-01.ogg','sound/misc/desceration-02.ogg','sound/misc/desceration-01.ogg') ,50, 1, -1) - return (BRUTELOSS) - -/obj/item/wirecutters/power/attack_self(mob/user) - playsound(get_turf(user), 'sound/items/change_jaws.ogg', 50, 1) - var/obj/item/crowbar/power/pryjaws = new /obj/item/crowbar/power - to_chat(user, "You attach the pry jaws to [src].") - qdel(src) - user.put_in_active_hand(pryjaws) -/* - * Welding Tool - */ -/obj/item/weldingtool - name = "welding tool" - desc = "A standard edition welder provided by Nanotrasen." - icon = 'icons/obj/tools.dmi' - icon_state = "welder" - item_state = "welder" - lefthand_file = 'icons/mob/inhands/equipment/tools_lefthand.dmi' - righthand_file = 'icons/mob/inhands/equipment/tools_righthand.dmi' - flags_1 = CONDUCT_1 - slot_flags = SLOT_BELT - force = 3 - throwforce = 5 - hitsound = "swing_hit" - usesound = 'sound/items/welder.ogg' - var/acti_sound = 'sound/items/welderactivate.ogg' - var/deac_sound = 'sound/items/welderdeactivate.ogg' - throw_speed = 3 - throw_range = 5 - w_class = WEIGHT_CLASS_SMALL - armor = list(melee = 0, bullet = 0, laser = 0, energy = 0, bomb = 0, bio = 0, rad = 0, fire = 100, acid = 30) - resistance_flags = FIRE_PROOF - - materials = list(MAT_METAL=70, MAT_GLASS=30) - origin_tech = "engineering=1;plasmatech=1" - var/welding = 0 //Whether or not the welding tool is off(0), on(1) or currently welding(2) - var/status = TRUE //Whether the welder is secured or unsecured (able to attach rods to it to make a flamethrower) - var/max_fuel = 20 //The max amount of fuel the welder can hold - var/change_icons = 1 - var/can_off_process = 0 - var/light_intensity = 2 //how powerful the emitted light is when used. - var/burned_fuel_for = 0 //when fuel was last removed - heat = 3800 - toolspeed = 1 - -/obj/item/weldingtool/Initialize() - . = ..() - create_reagents(max_fuel) - reagents.add_reagent("welding_fuel", max_fuel) - update_icon() - - -/obj/item/weldingtool/proc/update_torch() - if(welding) - add_overlay("[initial(icon_state)]-on") - item_state = "[initial(item_state)]1" - else - item_state = "[initial(item_state)]" - - -/obj/item/weldingtool/update_icon() - cut_overlays() - if(change_icons) - var/ratio = get_fuel() / max_fuel - ratio = Ceiling(ratio*4) * 25 - add_overlay("[initial(icon_state)][ratio]") - update_torch() - return - - -/obj/item/weldingtool/process() - switch(welding) - if(0) - force = 3 - damtype = "brute" - update_icon() - if(!can_off_process) - STOP_PROCESSING(SSobj, src) - return - //Welders left on now use up fuel, but lets not have them run out quite that fast - if(1) - force = 15 - damtype = "fire" - ++burned_fuel_for - if(burned_fuel_for >= WELDER_FUEL_BURN_INTERVAL) - remove_fuel(1) - update_icon() - - //This is to start fires. process() is only called if the welder is on. - open_flame() - - -/obj/item/weldingtool/suicide_act(mob/user) - user.visible_message("[user] welds [user.p_their()] every orifice closed! It looks like [user.p_theyre()] trying to commit suicide!") - return (FIRELOSS) - - -/obj/item/weldingtool/attackby(obj/item/I, mob/user, params) - if(istype(I, /obj/item/screwdriver)) - flamethrower_screwdriver(I, user) - else if(istype(I, /obj/item/stack/rods)) - flamethrower_rods(I, user) - else - return ..() - - -/obj/item/weldingtool/attack(mob/living/carbon/human/H, mob/user) - if(!istype(H)) - return ..() - - var/obj/item/bodypart/affecting = H.get_bodypart(check_zone(user.zone_selected)) - - if(affecting && affecting.status == BODYPART_ROBOTIC && user.a_intent != INTENT_HARM) - if(src.remove_fuel(1)) - playsound(loc, usesound, 50, 1) - if(user == H) - user.visible_message("[user] starts to fix some of the dents on [H]'s [affecting.name].", "You start fixing some of the dents on [H]'s [affecting.name].") - if(!do_mob(user, H, 50)) - return - item_heal_robotic(H, user, 15, 0) - else - return ..() - - -/obj/item/weldingtool/afterattack(atom/O, mob/user, proximity) - if(!proximity) return - - if(welding) - remove_fuel(1) - var/turf/location = get_turf(user) - location.hotspot_expose(700, 50, 1) - if(get_fuel() <= 0) - set_light(0) - - if(isliving(O)) - var/mob/living/L = O - if(L.IgniteMob()) - message_admins("[key_name_admin(user)] set [key_name_admin(L)] on fire") - log_game("[key_name(user)] set [key_name(L)] on fire") - - -/obj/item/weldingtool/attack_self(mob/user) - switched_on(user) - if(welding) - set_light(light_intensity) - - update_icon() - - -//Returns the amount of fuel in the welder -/obj/item/weldingtool/proc/get_fuel() - return reagents.get_reagent_amount("welding_fuel") - - -//Removes fuel from the welding tool. If a mob is passed, it will try to flash the mob's eyes. This should probably be renamed to use() -/obj/item/weldingtool/proc/remove_fuel(amount = 1, mob/living/M = null) - if(!welding || !check_fuel()) - return 0 - if(amount) - burned_fuel_for = 0 - if(get_fuel() >= amount) - reagents.remove_reagent("welding_fuel", amount) - check_fuel() - if(M) - M.flash_act(light_intensity) - return TRUE - else - if(M) - to_chat(M, "You need more welding fuel to complete this task!") - return FALSE - - -//Turns off the welder if there is no more fuel (does this really need to be its own proc?) -/obj/item/weldingtool/proc/check_fuel(mob/user) - if(get_fuel() <= 0 && welding) - switched_on(user) - update_icon() - //mob icon update - if(ismob(loc)) - var/mob/M = loc - M.update_inv_hands(0) - - return 0 - return 1 - -//Switches the welder on -/obj/item/weldingtool/proc/switched_on(mob/user) - if(!status) - to_chat(user, "[src] can't be turned on while unsecured!") - return - welding = !welding - if(welding) - if(get_fuel() >= 1) - to_chat(user, "You switch [src] on.") - playsound(loc, acti_sound, 50, 1) - force = 15 - damtype = "fire" - hitsound = 'sound/items/welder.ogg' - update_icon() - START_PROCESSING(SSobj, src) - else - to_chat(user, "You need more fuel!") - switched_off(user) - else - to_chat(user, "You switch [src] off.") - playsound(loc, deac_sound, 50, 1) - switched_off(user) - -//Switches the welder off -/obj/item/weldingtool/proc/switched_off(mob/user) - welding = 0 - set_light(0) - - force = 3 - damtype = "brute" - hitsound = "swing_hit" - update_icon() - - -/obj/item/weldingtool/examine(mob/user) - ..() - to_chat(user, "It contains [get_fuel()] unit\s of fuel out of [max_fuel].") - -/obj/item/weldingtool/is_hot() - return welding * heat - -//Returns whether or not the welding tool is currently on. -/obj/item/weldingtool/proc/isOn() - return welding - - -/obj/item/weldingtool/proc/flamethrower_screwdriver(obj/item/I, mob/user) - if(welding) - to_chat(user, "Turn it off first!") - return - status = !status - if(status) - to_chat(user, "You resecure [src].") - else - to_chat(user, "[src] can now be attached and modified.") - add_fingerprint(user) - -/obj/item/weldingtool/proc/flamethrower_rods(obj/item/I, mob/user) - if(!status) - var/obj/item/stack/rods/R = I - if (R.use(1)) - var/obj/item/flamethrower/F = new /obj/item/flamethrower(user.loc) - if(!remove_item_from_storage(F)) - user.transferItemToLoc(src, F, TRUE) - F.weldtool = src - add_fingerprint(user) - to_chat(user, "You add a rod to a welder, starting to build a flamethrower.") - user.put_in_hands(F) - else - to_chat(user, "You need one rod to start building a flamethrower!") - -/obj/item/weldingtool/ignition_effect(atom/A, mob/user) - if(welding && remove_fuel(1, user)) - . = "[user] casually lights [A] with [src], what a badass." - else - . = "" - -/obj/item/weldingtool/largetank - name = "industrial welding tool" - desc = "A slightly larger welder with a larger tank." - icon_state = "indwelder" - max_fuel = 40 - materials = list(MAT_GLASS=60) - origin_tech = "engineering=2;plasmatech=2" - -/obj/item/weldingtool/largetank/cyborg - name = "integrated welding tool" - desc = "An advanced welder designed to be used in robotic systems." - toolspeed = 0.5 - -/obj/item/weldingtool/largetank/flamethrower_screwdriver() - return - - -/obj/item/weldingtool/mini - name = "emergency welding tool" - desc = "A miniature welder used during emergencies." - icon_state = "miniwelder" - max_fuel = 10 - w_class = WEIGHT_CLASS_TINY - materials = list(MAT_METAL=30, MAT_GLASS=10) - change_icons = 0 - -/obj/item/weldingtool/mini/flamethrower_screwdriver() - return - -/obj/item/weldingtool/abductor - name = "alien welding tool" - desc = "An alien welding tool. Whatever fuel it uses, it never runs out." - icon = 'icons/obj/abductor.dmi' - icon_state = "welder" - toolspeed = 0.1 - light_intensity = 0 - change_icons = 0 - origin_tech = "plasmatech=5;engineering=5;abductor=3" - -/obj/item/weldingtool/abductor/process() - if(get_fuel() <= max_fuel) - reagents.add_reagent("welding_fuel", 1) - ..() - -/obj/item/weldingtool/hugetank - name = "upgraded industrial welding tool" - desc = "An upgraded welder based of the industrial welder." - icon_state = "upindwelder" - item_state = "upindwelder" - max_fuel = 80 - materials = list(MAT_METAL=70, MAT_GLASS=120) - origin_tech = "engineering=3;plasmatech=2" - -/obj/item/weldingtool/experimental - name = "experimental welding tool" - desc = "An experimental welder capable of self-fuel generation and less harmful to the eyes." - icon_state = "exwelder" - item_state = "exwelder" - max_fuel = 40 - materials = list(MAT_METAL=70, MAT_GLASS=120) - origin_tech = "materials=4;engineering=4;bluespace=3;plasmatech=4" - var/last_gen = 0 - change_icons = 0 - can_off_process = 1 - light_intensity = 1 - toolspeed = 0.5 - var/nextrefueltick = 0 - -/obj/item/weldingtool/experimental/brass - name = "brass welding tool" - desc = "A brass welder that seems to constantly refuel itself. It is faintly warm to the touch." - resistance_flags = FIRE_PROOF | ACID_PROOF - icon_state = "brasswelder" - item_state = "brasswelder" - - -/obj/item/weldingtool/experimental/process() - ..() - if(get_fuel() < max_fuel && nextrefueltick < world.time) - nextrefueltick = world.time + 10 - reagents.add_reagent("welding_fuel", 1) - - -/* - * Crowbar - */ - -/obj/item/crowbar - name = "pocket crowbar" - desc = "A small crowbar. This handy tool is useful for lots of things, such as prying floor tiles or opening unpowered doors." - icon = 'icons/obj/tools.dmi' - icon_state = "crowbar" - lefthand_file = 'icons/mob/inhands/equipment/tools_lefthand.dmi' - righthand_file = 'icons/mob/inhands/equipment/tools_righthand.dmi' - usesound = 'sound/items/crowbar.ogg' - flags_1 = CONDUCT_1 - slot_flags = SLOT_BELT - force = 5 - throwforce = 7 - w_class = WEIGHT_CLASS_SMALL - materials = list(MAT_METAL=50) - origin_tech = "engineering=1;combat=1" - attack_verb = list("attacked", "bashed", "battered", "bludgeoned", "whacked") - toolspeed = 1 - armor = list(melee = 0, bullet = 0, laser = 0, energy = 0, bomb = 0, bio = 0, rad = 0, fire = 50, acid = 30) - -/obj/item/crowbar/suicide_act(mob/user) - user.visible_message("[user] is beating [user.p_them()]self to death with [src]! It looks like [user.p_theyre()] trying to commit suicide!") - playsound(loc, 'sound/weapons/genhit.ogg', 50, 1, -1) - return (BRUTELOSS) - -/obj/item/crowbar/red - icon_state = "crowbar_red" - force = 8 - -/obj/item/crowbar/brass - name = "brass crowbar" - desc = "A brass crowbar. It feels faintly warm to the touch." - resistance_flags = FIRE_PROOF | ACID_PROOF - icon_state = "crowbar_brass" - toolspeed = 0.5 - -/obj/item/crowbar/abductor - name = "alien crowbar" - desc = "A hard-light crowbar. It appears to pry by itself, without any effort required." - icon = 'icons/obj/abductor.dmi' - usesound = 'sound/weapons/sonic_jackhammer.ogg' - icon_state = "crowbar" - toolspeed = 0.1 - origin_tech = "combat=4;engineering=4;abductor=3" - -/obj/item/crowbar/large - name = "crowbar" - desc = "It's a big crowbar. It doesn't fit in your pockets, because it's big." - force = 12 - w_class = WEIGHT_CLASS_NORMAL - throw_speed = 3 - throw_range = 3 - materials = list(MAT_METAL=70) - icon_state = "crowbar_large" - item_state = "crowbar" - toolspeed = 0.5 - -/obj/item/crowbar/cyborg - name = "hydraulic crowbar" - desc = "A hydraulic prying tool, compact but powerful. Designed to replace crowbar in construction cyborgs." - usesound = 'sound/items/jaws_pry.ogg' - force = 10 - toolspeed = 0.5 - -/obj/item/crowbar/power - name = "jaws of life" - desc = "A set of jaws of life, compressed through the magic of science. It's fitted with a prying head." - icon_state = "jaws_pry" - item_state = "jawsoflife" - lefthand_file = 'icons/mob/inhands/equipment/tools_lefthand.dmi' - righthand_file = 'icons/mob/inhands/equipment/tools_righthand.dmi' - materials = list(MAT_METAL=150,MAT_SILVER=50,MAT_TITANIUM=25) - origin_tech = "materials=2;engineering=2" - usesound = 'sound/items/jaws_pry.ogg' - force = 15 - toolspeed = 0.25 - -/obj/item/crowbar/power/suicide_act(mob/user) - user.visible_message("[user] is putting [user.p_their()] head in [src], it looks like [user.p_theyre()] trying to commit suicide!") - playsound(loc, 'sound/items/jaws_pry.ogg', 50, 1, -1) - return (BRUTELOSS) - -/obj/item/crowbar/power/attack_self(mob/user) - playsound(get_turf(user), 'sound/items/change_jaws.ogg', 50, 1) - var/obj/item/wirecutters/power/cutjaws = new /obj/item/wirecutters/power - to_chat(user, "You attach the cutting jaws to [src].") - qdel(src) - user.put_in_active_hand(cutjaws) - -#undef WELDER_FUEL_BURN_INTERVAL From e5aed03bcb29a0865808e1b0e8777de585e17058 Mon Sep 17 00:00:00 2001 From: LetterJay Date: Sun, 10 Sep 2017 15:20:58 -0500 Subject: [PATCH 30/74] all of my HATE --- code/game/objects/items/tools.dm | 789 +++++++++++++++++++++++++++++++ 1 file changed, 789 insertions(+) diff --git a/code/game/objects/items/tools.dm b/code/game/objects/items/tools.dm index d3f5a12faa..8bfc90decb 100644 --- a/code/game/objects/items/tools.dm +++ b/code/game/objects/items/tools.dm @@ -1 +1,790 @@ +#define WELDER_FUEL_BURN_INTERVAL 13 +/* Tools! + * Note: Multitools are /obj/item/device + * + * Contains: + * Wrench + * Screwdriver + * Wirecutters + * Welding Tool + * Crowbar + */ + +/* + * Wrench + */ +/obj/item/wrench + name = "wrench" + desc = "A wrench with common uses. Can be found in your hand." + icon = 'icons/obj/tools.dmi' + icon_state = "wrench" + lefthand_file = 'icons/mob/inhands/equipment/tools_lefthand.dmi' + righthand_file = 'icons/mob/inhands/equipment/tools_righthand.dmi' + flags_1 = CONDUCT_1 + slot_flags = SLOT_BELT + force = 5 + throwforce = 7 + w_class = WEIGHT_CLASS_SMALL + usesound = 'sound/items/ratchet.ogg' + materials = list(MAT_METAL=150) + origin_tech = "materials=1;engineering=1" + attack_verb = list("bashed", "battered", "bludgeoned", "whacked") + toolspeed = 1 + armor = list(melee = 0, bullet = 0, laser = 0, energy = 0, bomb = 0, bio = 0, rad = 0, fire = 50, acid = 30) + +/obj/item/wrench/suicide_act(mob/user) + user.visible_message("[user] is beating [user.p_them()]self to death with [src]! It looks like [user.p_theyre()] trying to commit suicide!") + playsound(loc, 'sound/weapons/genhit.ogg', 50, 1, -1) + return (BRUTELOSS) + +/obj/item/wrench/cyborg + name = "automatic wrench" + desc = "An advanced robotic wrench. Can be found in construction cyborgs." + toolspeed = 0.5 + +/obj/item/wrench/brass + name = "brass wrench" + desc = "A brass wrench. It's faintly warm to the touch." + resistance_flags = FIRE_PROOF | ACID_PROOF + icon_state = "wrench_brass" + toolspeed = 0.5 + +/obj/item/wrench/abductor + name = "alien wrench" + desc = "A polarized wrench. It causes anything placed between the jaws to turn." + icon = 'icons/obj/abductor.dmi' + icon_state = "wrench" + usesound = 'sound/effects/empulse.ogg' + toolspeed = 0.1 + origin_tech = "materials=5;engineering=5;abductor=3" + +/obj/item/wrench/power + name = "hand drill" + desc = "A simple powered hand drill. It's fitted with a bolt bit." + icon_state = "drill_bolt" + item_state = "drill" + lefthand_file = 'icons/mob/inhands/equipment/tools_lefthand.dmi' + righthand_file = 'icons/mob/inhands/equipment/tools_righthand.dmi' + usesound = 'sound/items/drill_use.ogg' + materials = list(MAT_METAL=150,MAT_SILVER=50,MAT_TITANIUM=25) + origin_tech = "materials=2;engineering=2" //done for balance reasons, making them high value for research, but harder to get + force = 8 //might or might not be too high, subject to change + w_class = WEIGHT_CLASS_SMALL + throwforce = 8 + attack_verb = list("drilled", "screwed", "jabbed") + toolspeed = 0.25 + +/obj/item/wrench/power/attack_self(mob/user) + playsound(get_turf(user),'sound/items/change_drill.ogg',50,1) + var/obj/item/wirecutters/power/s_drill = new /obj/item/screwdriver/power + to_chat(user, "You attach the screw driver bit to [src].") + qdel(src) + user.put_in_active_hand(s_drill) + +/obj/item/wrench/power/suicide_act(mob/user) + user.visible_message("[user] is pressing [src] against [user.p_their()] head! It looks like [user.p_theyre()] trying to commit suicide!") + return (BRUTELOSS) + +/obj/item/wrench/medical + name = "medical wrench" + desc = "A medical wrench with common(medical?) uses. Can be found in your hand." + icon_state = "wrench_medical" + force = 2 //MEDICAL + throwforce = 4 + origin_tech = "materials=1;engineering=1;biotech=3" + attack_verb = list("wrenched", "medicaled", "tapped", "jabbed", "whacked") + +/obj/item/wrench/medical/suicide_act(mob/living/user) + user.visible_message("[user] is praying to the medical wrench to take [user.p_their()] soul. It looks like [user.p_theyre()] trying to commit suicide!") + // TODO Make them glow with the power of the M E D I C A L W R E N C H + // during their ascension + + // Stun stops them from wandering off + user.Stun(100, ignore_canstun = TRUE) + playsound(loc, 'sound/effects/pray.ogg', 50, 1, -1) + + // Let the sound effect finish playing + sleep(20) + + if(!user) + return + + for(var/obj/item/W in user) + user.dropItemToGround(W) + + var/obj/item/wrench/medical/W = new /obj/item/wrench/medical(loc) + W.add_fingerprint(user) + W.desc += " For some reason, it reminds you of [user.name]." + + if(!user) + return + + user.dust() + + return OXYLOSS + +/* + * Screwdriver + */ +/obj/item/screwdriver + name = "screwdriver" + desc = "You can be totally screwy with this." + icon = 'icons/obj/tools.dmi' + icon_state = "screwdriver" + item_state = "screwdriver" + lefthand_file = 'icons/mob/inhands/equipment/tools_lefthand.dmi' + righthand_file = 'icons/mob/inhands/equipment/tools_righthand.dmi' + flags_1 = CONDUCT_1 + slot_flags = SLOT_BELT + force = 5 + w_class = WEIGHT_CLASS_TINY + throwforce = 5 + throw_speed = 3 + throw_range = 5 + materials = list(MAT_METAL=75) + attack_verb = list("stabbed") + hitsound = 'sound/weapons/bladeslice.ogg' + usesound = 'sound/items/screwdriver.ogg' + toolspeed = 1 + armor = list(melee = 0, bullet = 0, laser = 0, energy = 0, bomb = 0, bio = 0, rad = 0, fire = 50, acid = 30) + var/random_color = TRUE //if the screwdriver uses random coloring + var/static/list/screwdriver_colors = list(\ + "blue" = rgb(24, 97, 213), \ + "red" = rgb(149, 23, 16), \ + "pink" = rgb(213, 24, 141), \ + "brown" = rgb(160, 82, 18), \ + "green" = rgb(14, 127, 27), \ + "cyan" = rgb(24, 162, 213), \ + "yellow" = rgb(213, 140, 24), \ + ) + +/obj/item/screwdriver/suicide_act(mob/user) + user.visible_message("[user] is stabbing [src] into [user.p_their()] [pick("temple", "heart")]! It looks like [user.p_theyre()] trying to commit suicide!") + return(BRUTELOSS) + +/obj/item/screwdriver/Initialize() + . = ..() + if(random_color) //random colors! + var/our_color = pick(screwdriver_colors) + add_atom_colour(screwdriver_colors[our_color], FIXED_COLOUR_PRIORITY) + update_icon() + if(prob(75)) + pixel_y = rand(0, 16) + +/obj/item/screwdriver/update_icon() + if(!random_color) //icon override + return + cut_overlays() + var/mutable_appearance/base_overlay = mutable_appearance(icon, "screwdriver_screwybits") + base_overlay.appearance_flags = RESET_COLOR + add_overlay(base_overlay) + +/obj/item/screwdriver/worn_overlays(isinhands = FALSE, icon_file) + . = list() + if(isinhands && random_color) + var/mutable_appearance/M = mutable_appearance(icon_file, "screwdriver_head") + M.appearance_flags = RESET_COLOR + . += M + +/obj/item/screwdriver/get_belt_overlay() + if(random_color) + var/mutable_appearance/body = mutable_appearance('icons/obj/clothing/belt_overlays.dmi', "screwdriver") + var/mutable_appearance/head = mutable_appearance('icons/obj/clothing/belt_overlays.dmi', "screwdriver_head") + body.color = color + head.add_overlay(body) + return head + else + return mutable_appearance('icons/obj/clothing/belt_overlays.dmi', icon_state) + +/obj/item/screwdriver/attack(mob/living/carbon/M, mob/living/carbon/user) + if(!istype(M)) + return ..() + if(user.zone_selected != "eyes" && user.zone_selected != "head") + return ..() + if(user.disabilities & CLUMSY && prob(50)) + M = user + return eyestab(M,user) + +/obj/item/screwdriver/brass + name = "brass screwdriver" + desc = "A screwdriver made of brass. The handle feels freezing cold." + resistance_flags = FIRE_PROOF | ACID_PROOF + icon_state = "screwdriver_brass" + item_state = "screwdriver_brass" + toolspeed = 0.5 + random_color = FALSE + +/obj/item/screwdriver/abductor + name = "alien screwdriver" + desc = "An ultrasonic screwdriver." + icon = 'icons/obj/abductor.dmi' + icon_state = "screwdriver_a" + item_state = "screwdriver_nuke" + usesound = 'sound/items/pshoom.ogg' + toolspeed = 0.1 + random_color = FALSE + +/obj/item/screwdriver/power + name = "hand drill" + desc = "A simple powered hand drill. It's fitted with a screw bit." + icon_state = "drill_screw" + item_state = "drill" + lefthand_file = 'icons/mob/inhands/equipment/tools_lefthand.dmi' + righthand_file = 'icons/mob/inhands/equipment/tools_righthand.dmi' + materials = list(MAT_METAL=150,MAT_SILVER=50,MAT_TITANIUM=25) + origin_tech = "materials=2;engineering=2" //done for balance reasons, making them high value for research, but harder to get + force = 8 //might or might not be too high, subject to change + w_class = WEIGHT_CLASS_SMALL + throwforce = 8 + throw_speed = 2 + throw_range = 3//it's heavier than a screw driver/wrench, so it does more damage, but can't be thrown as far + attack_verb = list("drilled", "screwed", "jabbed","whacked") + hitsound = 'sound/items/drill_hit.ogg' + usesound = 'sound/items/drill_use.ogg' + toolspeed = 0.25 + random_color = FALSE + +/obj/item/screwdriver/power/suicide_act(mob/user) + user.visible_message("[user] is putting [src] to [user.p_their()] temple. It looks like [user.p_theyre()] trying to commit suicide!") + return(BRUTELOSS) + +/obj/item/screwdriver/power/attack_self(mob/user) + playsound(get_turf(user),'sound/items/change_drill.ogg',50,1) + var/obj/item/wrench/power/b_drill = new /obj/item/wrench/power + to_chat(user, "You attach the bolt driver bit to [src].") + qdel(src) + user.put_in_active_hand(b_drill) + +/obj/item/screwdriver/cyborg + name = "powered screwdriver" + desc = "An electrical screwdriver, designed to be both precise and quick." + usesound = 'sound/items/drill_use.ogg' + toolspeed = 0.5 + +/* + * Wirecutters + */ +/obj/item/wirecutters + name = "wirecutters" + desc = "This cuts wires." + icon = 'icons/obj/tools.dmi' + icon_state = null + lefthand_file = 'icons/mob/inhands/equipment/tools_lefthand.dmi' + righthand_file = 'icons/mob/inhands/equipment/tools_righthand.dmi' + flags_1 = CONDUCT_1 + slot_flags = SLOT_BELT + force = 6 + throw_speed = 3 + throw_range = 7 + w_class = WEIGHT_CLASS_SMALL + materials = list(MAT_METAL=80) + attack_verb = list("pinched", "nipped") + hitsound = 'sound/items/wirecutter.ogg' + usesound = 'sound/items/wirecutter.ogg' + origin_tech = "materials=1;engineering=1" + toolspeed = 1 + armor = list(melee = 0, bullet = 0, laser = 0, energy = 0, bomb = 0, bio = 0, rad = 0, fire = 50, acid = 30) + + +/obj/item/wirecutters/New(loc, var/param_color = null) + ..() + if(!icon_state) + if(!param_color) + param_color = pick("yellow","red") + icon_state = "cutters_[param_color]" + +/obj/item/wirecutters/attack(mob/living/carbon/C, mob/user) + if(istype(C) && C.handcuffed && istype(C.handcuffed, /obj/item/restraints/handcuffs/cable)) + user.visible_message("[user] cuts [C]'s restraints with [src]!") + qdel(C.handcuffed) + C.handcuffed = null + if(C.buckled && C.buckled.buckle_requires_restraints) + C.buckled.unbuckle_mob(C) + C.update_handcuffed() + return + else + ..() + +/obj/item/wirecutters/suicide_act(mob/user) + user.visible_message("[user] is cutting at [user.p_their()] arteries with [src]! It looks like [user.p_theyre()] trying to commit suicide!") + playsound(loc, usesound, 50, 1, -1) + return (BRUTELOSS) + +/obj/item/wirecutters/brass + name = "brass wirecutters" + desc = "A pair of wirecutters made of brass. The handle feels freezing cold to the touch." + resistance_flags = FIRE_PROOF | ACID_PROOF + icon_state = "cutters_brass" + toolspeed = 0.5 + +/obj/item/wirecutters/abductor + name = "alien wirecutters" + desc = "Extremely sharp wirecutters, made out of a silvery-green metal." + icon = 'icons/obj/abductor.dmi' + icon_state = "cutters" + toolspeed = 0.1 + origin_tech = "materials=5;engineering=4;abductor=3" + +/obj/item/wirecutters/cyborg + name = "wirecutters" + desc = "This cuts wires." + toolspeed = 0.5 + +/obj/item/wirecutters/power + name = "jaws of life" + desc = "A set of jaws of life, compressed through the magic of science. It's fitted with a cutting head." + icon_state = "jaws_cutter" + item_state = "jawsoflife" + origin_tech = "materials=2;engineering=2" + materials = list(MAT_METAL=150,MAT_SILVER=50,MAT_TITANIUM=25) + usesound = 'sound/items/jaws_cut.ogg' + toolspeed = 0.25 + +/obj/item/wirecutters/power/suicide_act(mob/user) + user.visible_message("[user] is wrapping \the [src] around [user.p_their()] neck. It looks like [user.p_theyre()] trying to rip [user.p_their()] head off!") + playsound(loc, 'sound/items/jaws_cut.ogg', 50, 1, -1) + if(iscarbon(user)) + var/mob/living/carbon/C = user + var/obj/item/bodypart/BP = C.get_bodypart("head") + if(BP) + BP.drop_limb() + playsound(loc,pick('sound/misc/desceration-01.ogg','sound/misc/desceration-02.ogg','sound/misc/desceration-01.ogg') ,50, 1, -1) + return (BRUTELOSS) + +/obj/item/wirecutters/power/attack_self(mob/user) + playsound(get_turf(user), 'sound/items/change_jaws.ogg', 50, 1) + var/obj/item/crowbar/power/pryjaws = new /obj/item/crowbar/power + to_chat(user, "You attach the pry jaws to [src].") + qdel(src) + user.put_in_active_hand(pryjaws) +/* + * Welding Tool + */ +/obj/item/weldingtool + name = "welding tool" + desc = "A standard edition welder provided by Nanotrasen." + icon = 'icons/obj/tools.dmi' + icon_state = "welder" + item_state = "welder" + lefthand_file = 'icons/mob/inhands/equipment/tools_lefthand.dmi' + righthand_file = 'icons/mob/inhands/equipment/tools_righthand.dmi' + flags_1 = CONDUCT_1 + slot_flags = SLOT_BELT + force = 3 + throwforce = 5 + hitsound = "swing_hit" + usesound = 'sound/items/welder.ogg' + var/acti_sound = 'sound/items/welderactivate.ogg' + var/deac_sound = 'sound/items/welderdeactivate.ogg' + throw_speed = 3 + throw_range = 5 + w_class = WEIGHT_CLASS_SMALL + armor = list(melee = 0, bullet = 0, laser = 0, energy = 0, bomb = 0, bio = 0, rad = 0, fire = 100, acid = 30) + resistance_flags = FIRE_PROOF + + materials = list(MAT_METAL=70, MAT_GLASS=30) + origin_tech = "engineering=1;plasmatech=1" + var/welding = 0 //Whether or not the welding tool is off(0), on(1) or currently welding(2) + var/status = TRUE //Whether the welder is secured or unsecured (able to attach rods to it to make a flamethrower) + var/max_fuel = 20 //The max amount of fuel the welder can hold + var/change_icons = 1 + var/can_off_process = 0 + var/light_intensity = 2 //how powerful the emitted light is when used. + var/burned_fuel_for = 0 //when fuel was last removed + heat = 3800 + toolspeed = 1 + +/obj/item/weldingtool/Initialize() + . = ..() + create_reagents(max_fuel) + reagents.add_reagent("welding_fuel", max_fuel) + update_icon() + + +/obj/item/weldingtool/proc/update_torch() + if(welding) + add_overlay("[initial(icon_state)]-on") + item_state = "[initial(item_state)]1" + else + item_state = "[initial(item_state)]" + + +/obj/item/weldingtool/update_icon() + cut_overlays() + if(change_icons) + var/ratio = get_fuel() / max_fuel + ratio = Ceiling(ratio*4) * 25 + add_overlay("[initial(icon_state)][ratio]") + update_torch() + return + + +/obj/item/weldingtool/process() + switch(welding) + if(0) + force = 3 + damtype = "brute" + update_icon() + if(!can_off_process) + STOP_PROCESSING(SSobj, src) + return + //Welders left on now use up fuel, but lets not have them run out quite that fast + if(1) + force = 15 + damtype = "fire" + ++burned_fuel_for + if(burned_fuel_for >= WELDER_FUEL_BURN_INTERVAL) + remove_fuel(1) + update_icon() + + //This is to start fires. process() is only called if the welder is on. + open_flame() + + +/obj/item/weldingtool/suicide_act(mob/user) + user.visible_message("[user] welds [user.p_their()] every orifice closed! It looks like [user.p_theyre()] trying to commit suicide!") + return (FIRELOSS) + + +/obj/item/weldingtool/attackby(obj/item/I, mob/user, params) + if(istype(I, /obj/item/screwdriver)) + flamethrower_screwdriver(I, user) + else if(istype(I, /obj/item/stack/rods)) + flamethrower_rods(I, user) + else + return ..() + + +/obj/item/weldingtool/attack(mob/living/carbon/human/H, mob/user) + if(!istype(H)) + return ..() + + var/obj/item/bodypart/affecting = H.get_bodypart(check_zone(user.zone_selected)) + + if(affecting && affecting.status == BODYPART_ROBOTIC && user.a_intent != INTENT_HARM) + if(src.remove_fuel(1)) + playsound(loc, usesound, 50, 1) + if(user == H) + user.visible_message("[user] starts to fix some of the dents on [H]'s [affecting.name].", "You start fixing some of the dents on [H]'s [affecting.name].") + if(!do_mob(user, H, 50)) + return + item_heal_robotic(H, user, 15, 0) + else + return ..() + + +/obj/item/weldingtool/afterattack(atom/O, mob/user, proximity) + if(!proximity) return + + if(welding) + remove_fuel(1) + var/turf/location = get_turf(user) + location.hotspot_expose(700, 50, 1) + if(get_fuel() <= 0) + set_light(0) + + if(isliving(O)) + var/mob/living/L = O + if(L.IgniteMob()) + message_admins("[key_name_admin(user)] set [key_name_admin(L)] on fire") + log_game("[key_name(user)] set [key_name(L)] on fire") + + +/obj/item/weldingtool/attack_self(mob/user) + switched_on(user) + if(welding) + set_light(light_intensity) + + update_icon() + + +//Returns the amount of fuel in the welder +/obj/item/weldingtool/proc/get_fuel() + return reagents.get_reagent_amount("welding_fuel") + + +//Removes fuel from the welding tool. If a mob is passed, it will try to flash the mob's eyes. This should probably be renamed to use() +/obj/item/weldingtool/proc/remove_fuel(amount = 1, mob/living/M = null) + if(!welding || !check_fuel()) + return 0 + if(amount) + burned_fuel_for = 0 + if(get_fuel() >= amount) + reagents.remove_reagent("welding_fuel", amount) + check_fuel() + if(M) + M.flash_act(light_intensity) + return TRUE + else + if(M) + to_chat(M, "You need more welding fuel to complete this task!") + return FALSE + + +//Turns off the welder if there is no more fuel (does this really need to be its own proc?) +/obj/item/weldingtool/proc/check_fuel(mob/user) + if(get_fuel() <= 0 && welding) + switched_on(user) + update_icon() + //mob icon update + if(ismob(loc)) + var/mob/M = loc + M.update_inv_hands(0) + + return 0 + return 1 + +//Switches the welder on +/obj/item/weldingtool/proc/switched_on(mob/user) + if(!status) + to_chat(user, "[src] can't be turned on while unsecured!") + return + welding = !welding + if(welding) + if(get_fuel() >= 1) + to_chat(user, "You switch [src] on.") + playsound(loc, acti_sound, 50, 1) + force = 15 + damtype = "fire" + hitsound = 'sound/items/welder.ogg' + update_icon() + START_PROCESSING(SSobj, src) + else + to_chat(user, "You need more fuel!") + switched_off(user) + else + to_chat(user, "You switch [src] off.") + playsound(loc, deac_sound, 50, 1) + switched_off(user) + +//Switches the welder off +/obj/item/weldingtool/proc/switched_off(mob/user) + welding = 0 + set_light(0) + + force = 3 + damtype = "brute" + hitsound = "swing_hit" + update_icon() + + +/obj/item/weldingtool/examine(mob/user) + ..() + to_chat(user, "It contains [get_fuel()] unit\s of fuel out of [max_fuel].") + +/obj/item/weldingtool/is_hot() + return welding * heat + +//Returns whether or not the welding tool is currently on. +/obj/item/weldingtool/proc/isOn() + return welding + + +/obj/item/weldingtool/proc/flamethrower_screwdriver(obj/item/I, mob/user) + if(welding) + to_chat(user, "Turn it off first!") + return + status = !status + if(status) + to_chat(user, "You resecure [src].") + else + to_chat(user, "[src] can now be attached and modified.") + add_fingerprint(user) + +/obj/item/weldingtool/proc/flamethrower_rods(obj/item/I, mob/user) + if(!status) + var/obj/item/stack/rods/R = I + if (R.use(1)) + var/obj/item/flamethrower/F = new /obj/item/flamethrower(user.loc) + if(!remove_item_from_storage(F)) + user.transferItemToLoc(src, F, TRUE) + F.weldtool = src + add_fingerprint(user) + to_chat(user, "You add a rod to a welder, starting to build a flamethrower.") + user.put_in_hands(F) + else + to_chat(user, "You need one rod to start building a flamethrower!") + +/obj/item/weldingtool/ignition_effect(atom/A, mob/user) + if(welding && remove_fuel(1, user)) + . = "[user] casually lights [A] with [src], what a badass." + else + . = "" + +/obj/item/weldingtool/largetank + name = "industrial welding tool" + desc = "A slightly larger welder with a larger tank." + icon_state = "indwelder" + max_fuel = 40 + materials = list(MAT_GLASS=60) + origin_tech = "engineering=2;plasmatech=2" + +/obj/item/weldingtool/largetank/cyborg + name = "integrated welding tool" + desc = "An advanced welder designed to be used in robotic systems." + toolspeed = 0.5 + +/obj/item/weldingtool/largetank/flamethrower_screwdriver() + return + + +/obj/item/weldingtool/mini + name = "emergency welding tool" + desc = "A miniature welder used during emergencies." + icon_state = "miniwelder" + max_fuel = 10 + w_class = WEIGHT_CLASS_TINY + materials = list(MAT_METAL=30, MAT_GLASS=10) + change_icons = 0 + +/obj/item/weldingtool/mini/flamethrower_screwdriver() + return + +/obj/item/weldingtool/abductor + name = "alien welding tool" + desc = "An alien welding tool. Whatever fuel it uses, it never runs out." + icon = 'icons/obj/abductor.dmi' + icon_state = "welder" + toolspeed = 0.1 + light_intensity = 0 + change_icons = 0 + origin_tech = "plasmatech=5;engineering=5;abductor=3" + +/obj/item/weldingtool/abductor/process() + if(get_fuel() <= max_fuel) + reagents.add_reagent("welding_fuel", 1) + ..() + +/obj/item/weldingtool/hugetank + name = "upgraded industrial welding tool" + desc = "An upgraded welder based of the industrial welder." + icon_state = "upindwelder" + item_state = "upindwelder" + max_fuel = 80 + materials = list(MAT_METAL=70, MAT_GLASS=120) + origin_tech = "engineering=3;plasmatech=2" + +/obj/item/weldingtool/experimental + name = "experimental welding tool" + desc = "An experimental welder capable of self-fuel generation and less harmful to the eyes." + icon_state = "exwelder" + item_state = "exwelder" + max_fuel = 40 + materials = list(MAT_METAL=70, MAT_GLASS=120) + origin_tech = "materials=4;engineering=4;bluespace=3;plasmatech=4" + var/last_gen = 0 + change_icons = 0 + can_off_process = 1 + light_intensity = 1 + toolspeed = 0.5 + var/nextrefueltick = 0 + +/obj/item/weldingtool/experimental/brass + name = "brass welding tool" + desc = "A brass welder that seems to constantly refuel itself. It is faintly warm to the touch." + resistance_flags = FIRE_PROOF | ACID_PROOF + icon_state = "brasswelder" + item_state = "brasswelder" + + +/obj/item/weldingtool/experimental/process() + ..() + if(get_fuel() < max_fuel && nextrefueltick < world.time) + nextrefueltick = world.time + 10 + reagents.add_reagent("welding_fuel", 1) + + +/* + * Crowbar + */ + +/obj/item/crowbar + name = "pocket crowbar" + desc = "A small crowbar. This handy tool is useful for lots of things, such as prying floor tiles or opening unpowered doors." + icon = 'icons/obj/tools.dmi' + icon_state = "crowbar" + lefthand_file = 'icons/mob/inhands/equipment/tools_lefthand.dmi' + righthand_file = 'icons/mob/inhands/equipment/tools_righthand.dmi' + usesound = 'sound/items/crowbar.ogg' + flags_1 = CONDUCT_1 + slot_flags = SLOT_BELT + force = 5 + throwforce = 7 + w_class = WEIGHT_CLASS_SMALL + materials = list(MAT_METAL=50) + origin_tech = "engineering=1;combat=1" + attack_verb = list("attacked", "bashed", "battered", "bludgeoned", "whacked") + toolspeed = 1 + armor = list(melee = 0, bullet = 0, laser = 0, energy = 0, bomb = 0, bio = 0, rad = 0, fire = 50, acid = 30) + +/obj/item/crowbar/suicide_act(mob/user) + user.visible_message("[user] is beating [user.p_them()]self to death with [src]! It looks like [user.p_theyre()] trying to commit suicide!") + playsound(loc, 'sound/weapons/genhit.ogg', 50, 1, -1) + return (BRUTELOSS) + +/obj/item/crowbar/red + icon_state = "crowbar_red" + force = 8 + +/obj/item/crowbar/brass + name = "brass crowbar" + desc = "A brass crowbar. It feels faintly warm to the touch." + resistance_flags = FIRE_PROOF | ACID_PROOF + icon_state = "crowbar_brass" + toolspeed = 0.5 + +/obj/item/crowbar/abductor + name = "alien crowbar" + desc = "A hard-light crowbar. It appears to pry by itself, without any effort required." + icon = 'icons/obj/abductor.dmi' + usesound = 'sound/weapons/sonic_jackhammer.ogg' + icon_state = "crowbar" + toolspeed = 0.1 + origin_tech = "combat=4;engineering=4;abductor=3" + +/obj/item/crowbar/large + name = "crowbar" + desc = "It's a big crowbar. It doesn't fit in your pockets, because it's big." + force = 12 + w_class = WEIGHT_CLASS_NORMAL + throw_speed = 3 + throw_range = 3 + materials = list(MAT_METAL=70) + icon_state = "crowbar_large" + item_state = "crowbar" + toolspeed = 0.5 + +/obj/item/crowbar/cyborg + name = "hydraulic crowbar" + desc = "A hydraulic prying tool, compact but powerful. Designed to replace crowbar in construction cyborgs." + usesound = 'sound/items/jaws_pry.ogg' + force = 10 + toolspeed = 0.5 + +/obj/item/crowbar/power + name = "jaws of life" + desc = "A set of jaws of life, compressed through the magic of science. It's fitted with a prying head." + icon_state = "jaws_pry" + item_state = "jawsoflife" + lefthand_file = 'icons/mob/inhands/equipment/tools_lefthand.dmi' + righthand_file = 'icons/mob/inhands/equipment/tools_righthand.dmi' + materials = list(MAT_METAL=150,MAT_SILVER=50,MAT_TITANIUM=25) + origin_tech = "materials=2;engineering=2" + usesound = 'sound/items/jaws_pry.ogg' + force = 15 + toolspeed = 0.25 + +/obj/item/crowbar/power/suicide_act(mob/user) + user.visible_message("[user] is putting [user.p_their()] head in [src], it looks like [user.p_theyre()] trying to commit suicide!") + playsound(loc, 'sound/items/jaws_pry.ogg', 50, 1, -1) + return (BRUTELOSS) + +/obj/item/crowbar/power/attack_self(mob/user) + playsound(get_turf(user), 'sound/items/change_jaws.ogg', 50, 1) + var/obj/item/wirecutters/power/cutjaws = new /obj/item/wirecutters/power + to_chat(user, "You attach the cutting jaws to [src].") + qdel(src) + user.put_in_active_hand(cutjaws) + +#undef WELDER_FUEL_BURN_INTERVAL From 8ee6fdb76a6dac9f892287db2f48b8dd4dc2308e Mon Sep 17 00:00:00 2001 From: CitadelStationBot Date: Sun, 10 Sep 2017 22:29:12 -0500 Subject: [PATCH 31/74] [MIRROR] Fixes stop-sounds not force-stopping internet midis (#2692) * Fixes stop-sounds not force-stopping internet midis (#30571) * Update playsound.dm * Update preferences_toggles.dm (#17) * Fixes stop-sounds not force-stopping internet midis --- code/modules/admin/verbs/playsound.dm | 3 +++ code/modules/client/preferences_toggles.dm | 3 +++ 2 files changed, 6 insertions(+) diff --git a/code/modules/admin/verbs/playsound.dm b/code/modules/admin/verbs/playsound.dm index 20c1d91fd2..bfc4701012 100644 --- a/code/modules/admin/verbs/playsound.dm +++ b/code/modules/admin/verbs/playsound.dm @@ -135,4 +135,7 @@ for(var/mob/M in GLOB.player_list) if(M.client) SEND_SOUND(M, sound(null)) + var/client/C = M.client + if(C && C.chatOutput && !C.chatOutput.broken && C.chatOutput.loaded) + C.chatOutput.sendMusic(" ") SSblackbox.add_details("admin_verb","Stop All Playing Sounds") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! diff --git a/code/modules/client/preferences_toggles.dm b/code/modules/client/preferences_toggles.dm index 8e8690bde3..adf775f0e8 100644 --- a/code/modules/client/preferences_toggles.dm +++ b/code/modules/client/preferences_toggles.dm @@ -233,6 +233,9 @@ TOGGLE_CHECKBOX(/datum/verbs/menu/Settings/Sound, toggleprayersounds)() set category = "Preferences" set desc = "Stop Current Sounds" SEND_SOUND(usr, sound(null)) + var/client/C = usr.client + if(C && C.chatOutput && !C.chatOutput.broken && C.chatOutput.loaded) + C.chatOutput.sendMusic(" ") SSblackbox.add_details("preferences_verb","Stop Self Sounds") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! From 48e71cfbd5cb94a5523b1afd3bee4cd9e6697b02 Mon Sep 17 00:00:00 2001 From: LetterJay Date: Mon, 11 Sep 2017 13:04:28 -0500 Subject: [PATCH 32/74] Update Malf_Modules.dm --- code/game/gamemodes/malfunction/Malf_Modules.dm | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/code/game/gamemodes/malfunction/Malf_Modules.dm b/code/game/gamemodes/malfunction/Malf_Modules.dm index 5dfd8f7396..4f3b4c3ea2 100644 --- a/code/game/gamemodes/malfunction/Malf_Modules.dm +++ b/code/game/gamemodes/malfunction/Malf_Modules.dm @@ -309,8 +309,7 @@ GLOBAL_LIST_INIT(blacklisted_malf_machines, typecacheof(list( owner_AI.nuking = TRUE owner_AI.doomsday_device = DOOM owner_AI.doomsday_device.start() - for(var/pinpointer in GLOB.pinpointer_list) - var/obj/item/pinpointer/P = pinpointer + for(var/obj/item/pinpointer/nuke/P in GLOB.pinpointer_list) P.switch_mode_to(TRACK_MALF_AI) //Pinpointers start tracking the AI wherever it goes qdel(src) From 6a47a7011ade85c3c8c3f8ff86f60d0f6434ab5b Mon Sep 17 00:00:00 2001 From: LetterJay Date: Mon, 11 Sep 2017 13:05:22 -0500 Subject: [PATCH 33/74] Update nuclear.dm --- code/game/gamemodes/nuclear/nuclear.dm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/game/gamemodes/nuclear/nuclear.dm b/code/game/gamemodes/nuclear/nuclear.dm index 59650561a6..1b1bec68c1 100644 --- a/code/game/gamemodes/nuclear/nuclear.dm +++ b/code/game/gamemodes/nuclear/nuclear.dm @@ -325,7 +325,7 @@ gloves = /obj/item/clothing/gloves/combat back = /obj/item/storage/backpack ears = /obj/item/device/radio/headset/syndicate/alt - l_pocket = /obj/item/pinpointer/syndicate + l_pocket = /obj/item/pinpointer/nuke/syndicate id = /obj/item/card/id/syndicate belt = /obj/item/gun/ballistic/automatic/pistol backpack_contents = list(/obj/item/storage/box/syndie=1) From 052fdb70eafe8123bf5a0435e1a67cc0106e869e Mon Sep 17 00:00:00 2001 From: LetterJay Date: Mon, 11 Sep 2017 13:06:27 -0500 Subject: [PATCH 34/74] Update nuclearbomb.dm --- code/game/gamemodes/nuclear/nuclearbomb.dm | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/code/game/gamemodes/nuclear/nuclearbomb.dm b/code/game/gamemodes/nuclear/nuclearbomb.dm index ee611349f8..5245b00c35 100644 --- a/code/game/gamemodes/nuclear/nuclearbomb.dm +++ b/code/game/gamemodes/nuclear/nuclearbomb.dm @@ -362,9 +362,9 @@ if(safety) if(timing) set_security_level(previous_level) - for(var/obj/item/pinpointer/syndicate/S in GLOB.pinpointer_list) + for(var/obj/item/pinpointer/nuke/syndicate/S in GLOB.pinpointer_list) S.switch_mode_to(initial(S.mode)) - S.nuke_warning = FALSE + S.alert = FALSE timing = FALSE bomb_set = TRUE detonation_timer = null @@ -381,7 +381,7 @@ bomb_set = TRUE set_security_level("delta") detonation_timer = world.time + (timer_set * 10) - for(var/obj/item/pinpointer/syndicate/S in GLOB.pinpointer_list) + for(var/obj/item/pinpointer/nuke/syndicate/S in GLOB.pinpointer_list) S.switch_mode_to(TRACK_INFILTRATOR) countdown.start() else @@ -390,7 +390,7 @@ set_security_level(previous_level) for(var/obj/item/pinpointer/syndicate/S in GLOB.pinpointer_list) S.switch_mode_to(initial(S.mode)) - S.nuke_warning = FALSE + S.alert = FALSE countdown.stop() update_icon() From 26c6f5cc140cc6f57bdd77e1e5ccfee6f119599e Mon Sep 17 00:00:00 2001 From: LetterJay Date: Mon, 11 Sep 2017 13:07:35 -0500 Subject: [PATCH 35/74] Update pinpointer.dm --- code/game/gamemodes/nuclear/pinpointer.dm | 159 +++++----------------- 1 file changed, 34 insertions(+), 125 deletions(-) diff --git a/code/game/gamemodes/nuclear/pinpointer.dm b/code/game/gamemodes/nuclear/pinpointer.dm index 342bcac090..461ef78ef3 100644 --- a/code/game/gamemodes/nuclear/pinpointer.dm +++ b/code/game/gamemodes/nuclear/pinpointer.dm @@ -1,56 +1,7 @@ -//Pinpointers are used to track atoms from a distance as long as they're on the same z-level. The captain and nuke ops have ones that track the nuclear authentication disk. -/obj/item/pinpointer - name = "pinpointer" - desc = "A handheld tracking device that locks onto certain signals." - icon = 'icons/obj/device.dmi' - icon_state = "pinoff" - flags_1 = CONDUCT_1 - slot_flags = SLOT_BELT - w_class = WEIGHT_CLASS_SMALL - item_state = "electronic" - lefthand_file = 'icons/mob/inhands/misc/devices_lefthand.dmi' - righthand_file = 'icons/mob/inhands/misc/devices_righthand.dmi' - throw_speed = 3 - throw_range = 7 - materials = list(MAT_METAL = 500, MAT_GLASS = 250) - resistance_flags = INDESTRUCTIBLE | LAVA_PROOF | FIRE_PROOF | ACID_PROOF - var/active = FALSE - var/atom/movable/target = null //The thing we're searching for - var/atom/movable/constant_target = null //The thing we're always focused on, if we're in the right mode - var/target_x = 0 //The target coordinates if we're tracking those - var/target_y = 0 - var/minimum_range = 0 //at what range the pinpointer declares you to be at your destination - var/nuke_warning = FALSE // If we've set off a miniature alarm about an armed nuke - var/mode = TRACK_NUKE_DISK //What are we looking for? +/obj/item/pinpointer/nuke + var/mode = TRACK_NUKE_DISK -/obj/item/pinpointer/New() - ..() - GLOB.pinpointer_list += src - -/obj/item/pinpointer/Destroy() - STOP_PROCESSING(SSfastprocess, src) - GLOB.pinpointer_list -= src - return ..() - -/obj/item/pinpointer/attack_self(mob/living/user) - active = !active - user.visible_message("[user] [active ? "" : "de"]activates their pinpointer.", "You [active ? "" : "de"]activate your pinpointer.") - playsound(user, 'sound/items/screwdriver2.ogg', 50, 1) - icon_state = "pin[active ? "onnull" : "off"]" - if(active) - START_PROCESSING(SSfastprocess, src) - else - target = null //Restarting the pinpointer forces a target reset - STOP_PROCESSING(SSfastprocess, src) - -/obj/item/pinpointer/attackby(obj/item/I, mob/living/user, params) - if(mode != TRACK_ATOM) - return ..() - user.visible_message("[user] tunes [src] to [I].", "You fine-tune [src]'s tracking to track [I].") - playsound(src, 'sound/machines/click.ogg', 50, 1) - constant_target = I - -/obj/item/pinpointer/examine(mob/user) +/obj/item/pinpointer/nuke/examine(mob/user) ..() var/msg = "Its tracking indicator reads " switch(mode) @@ -67,22 +18,20 @@ if(bomb.timing) to_chat(user, "Extreme danger. Arming signal detected. Time remaining: [bomb.get_time_left()]") -/obj/item/pinpointer/process() - if(!active) - STOP_PROCESSING(SSfastprocess, src) - return - scan_for_target() - point_to_target() - my_god_jc_a_bomb() - addtimer(CALLBACK(src, .proc/refresh_target), 50, TIMER_UNIQUE) +/obj/item/pinpointer/nuke/process() + ..() + if(active) // If shit's going down + for(var/obj/machinery/nuclearbomb/bomb in GLOB.nuke_list) + if(bomb.timing) + if(!alert) + alert = TRUE + playsound(src, 'sound/items/nuke_toy_lowpower.ogg', 50, 0) + if(isliving(loc)) + var/mob/living/L = loc + to_chat(L, "Your [name] vibrates and lets out a tinny alarm. Uh oh.") -/obj/item/pinpointer/proc/scan_for_target() //Looks for whatever it's tracking - if(target) - if(isliving(target)) - var/mob/living/L = target - if(L.stat == DEAD) - target = null - return +/obj/item/pinpointer/nuke/scan_for_target() + target = null switch(mode) if(TRACK_NUKE_DISK) var/obj/item/disk/nuclear/N = locate() in GLOB.poi_list @@ -98,76 +47,36 @@ target = A if(TRACK_INFILTRATOR) target = SSshuttle.getShuttle("syndicate") - if(TRACK_OPERATIVES) - var/list/possible_targets = list() - var/turf/here = get_turf(src) - for(var/V in SSticker.mode.syndicates) - var/datum/mind/M = V - if(M.current && M.current.stat != DEAD) - possible_targets |= M.current - var/mob/living/closest_operative = get_closest_atom(/mob/living/carbon/human, possible_targets, here) - if(closest_operative) - target = closest_operative - if(TRACK_ATOM) - if(constant_target) - target = constant_target - if(TRACK_COORDINATES) - var/turf/T = get_turf(src) - target = locate(target_x, target_y, T.z) + ..() -/obj/item/pinpointer/proc/point_to_target() //If we found what we're looking for, show the distance and direction - if(!active) - return - if(!target || (mode == TRACK_ATOM && !constant_target)) - icon_state = "pinon[nuke_warning ? "alert" : ""]null" - return - var/turf/here = get_turf(src) - var/turf/there = get_turf(target) - if(here.z != there.z) - icon_state = "pinon[nuke_warning ? "alert" : ""]null" - return - if(get_dist_euclidian(here,there)<=minimum_range) - icon_state = "pinon[nuke_warning ? "alert" : ""]direct" - else - setDir(get_dir(here, there)) - switch(get_dist(here, there)) - if(1 to 8) - icon_state = "pinon[nuke_warning ? "alert" : "close"]" - if(9 to 16) - icon_state = "pinon[nuke_warning ? "alert" : "medium"]" - if(16 to INFINITY) - icon_state = "pinon[nuke_warning ? "alert" : "far"]" - -/obj/item/pinpointer/proc/my_god_jc_a_bomb() //If we should get the hell back to the ship - for(var/obj/machinery/nuclearbomb/bomb in GLOB.nuke_list) - if(bomb.timing) - if(!nuke_warning) - nuke_warning = TRUE - playsound(src, 'sound/items/nuke_toy_lowpower.ogg', 50, 0) - if(isliving(loc)) - var/mob/living/L = loc - to_chat(L, "Your [name] vibrates and lets out a tinny alarm. Uh oh.") - -/obj/item/pinpointer/proc/switch_mode_to(new_mode) //If we shouldn't be tracking what we are +/obj/item/pinpointer/nuke/proc/switch_mode_to(new_mode) if(isliving(loc)) var/mob/living/L = loc to_chat(L, "Your [name] beeps as it reconfigures its tracking algorithms.") playsound(L, 'sound/machines/triple_beep.ogg', 50, 1) mode = new_mode - target = null //Switch modes so we can find the new target + scan_for_target() -/obj/item/pinpointer/proc/refresh_target() //Periodically removes the target to allow the pinpointer to update (i.e. malf AI shunts, an operative dies) - target = null - -/obj/item/pinpointer/syndicate //Syndicate pinpointers automatically point towards the infiltrator once the nuke is active. +/obj/item/pinpointer/nuke/syndicate // Syndicate pinpointers automatically point towards the infiltrator once the nuke is active. name = "syndicate pinpointer" desc = "A handheld tracking device that locks onto certain signals. It's configured to switch tracking modes once it detects the activation signal of a nuclear device." + icon_state = "pinpointer_syndicate" -/obj/item/pinpointer/syndicate/cyborg //Cyborg pinpointers just look for a random operative. +/obj/item/pinpointer/syndicate_cyborg // Cyborg pinpointers just look for a random operative. name = "cyborg syndicate pinpointer" desc = "An integrated tracking device, jury-rigged to search for living Syndicate operatives." - mode = TRACK_OPERATIVES flags_1 = NODROP_1 - +/obj/item/pinpointer/syndicate_cyborg/scan_for_target() + target = null + var/list/possible_targets = list() + var/turf/here = get_turf(src) + for(var/V in SSticker.mode.syndicates) + var/datum/mind/M = V + if(M.current && M.current.stat != DEAD) + possible_targets |= M.current + var/mob/living/closest_operative = get_closest_atom(/mob/living/carbon/human, possible_targets, here) + if(closest_operative) + target = closest_operative + ..() From 489b2c6deba9d08a1390bcdbc2dab3f6b01fcba9 Mon Sep 17 00:00:00 2001 From: LetterJay Date: Mon, 11 Sep 2017 13:08:35 -0500 Subject: [PATCH 36/74] Update objective_items.dm --- code/game/gamemodes/objective_items.dm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/game/gamemodes/objective_items.dm b/code/game/gamemodes/objective_items.dm index 3cfede5f93..c1af4de9f0 100644 --- a/code/game/gamemodes/objective_items.dm +++ b/code/game/gamemodes/objective_items.dm @@ -186,7 +186,7 @@ return ..() //Old ninja objectives. -/datum/objective_item/special/pinpointer +/datum/objective_item/special/pinpointer/nuke name = "the captain's pinpointer." targetitem = /obj/item/pinpointer difficulty = 10 From ff17626ce7e86b464746c9a5218999e0310182fe Mon Sep 17 00:00:00 2001 From: LetterJay Date: Mon, 11 Sep 2017 13:09:30 -0500 Subject: [PATCH 37/74] Update death.dm --- code/modules/mob/living/silicon/ai/death.dm | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/code/modules/mob/living/silicon/ai/death.dm b/code/modules/mob/living/silicon/ai/death.dm index 52c06439fb..d41b6f5f29 100644 --- a/code/modules/mob/living/silicon/ai/death.dm +++ b/code/modules/mob/living/silicon/ai/death.dm @@ -35,9 +35,9 @@ if(nuking) set_security_level("red") nuking = FALSE - for(var/obj/item/pinpointer/P in GLOB.pinpointer_list) + for(var/obj/item/pinpointer/nuke/P in GLOB.pinpointer_list) P.switch_mode_to(TRACK_NUKE_DISK) //Party's over, back to work, everyone - P.nuke_warning = FALSE + P.alert = FALSE if(doomsday_device) doomsday_device.timing = FALSE From c1872907b1f9ae2c07253798b7aa1e4e349f8d43 Mon Sep 17 00:00:00 2001 From: LetterJay Date: Mon, 11 Sep 2017 13:10:18 -0500 Subject: [PATCH 38/74] Update robot_modules.dm --- code/modules/mob/living/silicon/robot/robot_modules.dm | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/code/modules/mob/living/silicon/robot/robot_modules.dm b/code/modules/mob/living/silicon/robot/robot_modules.dm index 41fbc69180..af6f3daf92 100644 --- a/code/modules/mob/living/silicon/robot/robot_modules.dm +++ b/code/modules/mob/living/silicon/robot/robot_modules.dm @@ -599,7 +599,7 @@ /obj/item/gun/ballistic/revolver/grenadelauncher/cyborg, /obj/item/card/emag, /obj/item/crowbar/cyborg, - /obj/item/pinpointer/syndicate/cyborg) + /obj/item/pinpointer/syndicate_cyborg) ratvar_modules = list( /obj/item/clockwork/slab/cyborg/security, @@ -625,7 +625,7 @@ /obj/item/roller/robo, /obj/item/card/emag, /obj/item/crowbar/cyborg, - /obj/item/pinpointer/syndicate/cyborg, + /obj/item/pinpointer/syndicate_cyborg, /obj/item/stack/medical/gauze/cyborg, /obj/item/gun/medbeam) ratvar_modules = list( From 6951e39d1304f5189a4fbe87f892a92c20bfdbaa Mon Sep 17 00:00:00 2001 From: LetterJay Date: Mon, 11 Sep 2017 13:10:54 -0500 Subject: [PATCH 39/74] Update apc.dm --- code/modules/power/apc.dm | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/code/modules/power/apc.dm b/code/modules/power/apc.dm index 3b070f1384..b0212e6155 100644 --- a/code/modules/power/apc.dm +++ b/code/modules/power/apc.dm @@ -874,9 +874,9 @@ occupier.loc = src.loc occupier.death() occupier.gib() - for(var/obj/item/pinpointer/P in GLOB.pinpointer_list) + for(var/obj/item/pinpointer/nuke/P in GLOB.pinpointer_list) P.switch_mode_to(TRACK_NUKE_DISK) //Pinpointers go back to tracking the nuke disk - P.nuke_warning = FALSE + P.alert = FALSE /obj/machinery/power/apc/transfer_ai(interaction, mob/user, mob/living/silicon/ai/AI, obj/item/device/aicard/card) if(card.AI) From a6e280cbad4e8109e3a9cb4cfefd5703e1cb2311 Mon Sep 17 00:00:00 2001 From: CitadelStationBot Date: Mon, 11 Sep 2017 13:16:16 -0500 Subject: [PATCH 40/74] Automatic changelog generation for PR #2600 [ci skip] --- html/changelogs/AutoChangeLog-pr-2600.yml | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 html/changelogs/AutoChangeLog-pr-2600.yml diff --git a/html/changelogs/AutoChangeLog-pr-2600.yml b/html/changelogs/AutoChangeLog-pr-2600.yml new file mode 100644 index 0000000000..79380038d4 --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-2600.yml @@ -0,0 +1,4 @@ +author: "Jay" +delete-after: True +changes: + - tweak: "Removes the lisp lizards have when talking" From af5ffcc83ae824da42e181b671b9f846ee8f6d63 Mon Sep 17 00:00:00 2001 From: Ashe Higgs Date: Mon, 11 Sep 2017 14:37:09 -0400 Subject: [PATCH 41/74] Adds departmental banners --- code/game/objects/items/religion.dm | 200 ++++++++++++++++++++++++++-- 1 file changed, 187 insertions(+), 13 deletions(-) diff --git a/code/game/objects/items/religion.dm b/code/game/objects/items/religion.dm index 1edbba1f56..007c590cac 100644 --- a/code/game/objects/items/religion.dm +++ b/code/game/objects/items/religion.dm @@ -1,27 +1,201 @@ /obj/item/banner name = "banner" + desc = "A banner with Nanotrasen's logo on it." icon = 'icons/obj/items_and_weapons.dmi' icon_state = "banner" item_state = "banner" + force = 8 + attack_verb = list("forcefully inspired", "violently encouraged", "relentlessly galvanized") lefthand_file = 'icons/mob/inhands/equipment/banners_lefthand.dmi' righthand_file = 'icons/mob/inhands/equipment/banners_righthand.dmi' - desc = "A banner with Nanotrasen's logo on it." - var/moralecooldown = 0 - var/moralewait = 600 + var/inspiration_available = TRUE //If this banner can be used to inspire crew + var/morale_time = 0 + var/morale_cooldown = 600 //How many deciseconds between uses + var/list/job_loyalties //Mobs with any of these assigned roles will be inspired + var/list/role_loyalties //Mobs with any of these special roles will be inspired + var/warcry + +/obj/item/banner/examine(mob/user) + ..() + if(inspiration_available) + to_chat(user, "Activate it in your hand to inspire nearby allies of this banner's allegiance!") /obj/item/banner/attack_self(mob/living/carbon/human/user) - if(moralecooldown + moralewait > world.time) + if(!inspiration_available) return - to_chat(user, "You increase the morale of your fellows!") - moralecooldown = world.time + if(morale_time > world.time) + to_chat(user, "You aren't feeling inspired enough to flourish [src] again yet.") + return + user.visible_message("[user] flourishes [src]!", \ + "You raise [src] skywards, inspiring your allies!") + playsound(src, "rustle", 100, FALSE) + if(warcry) + user.say("[warcry]") + var/old_transform = user.transform + user.transform *= 1.2 + animate(user, transform = old_transform, time = 10) + morale_time = world.time + morale_cooldown - for(var/mob/living/carbon/human/H in range(4,get_turf(src))) - to_chat(H, "Your morale is increased by [user]'s banner!") - H.adjustBruteLoss(-15) - H.adjustFireLoss(-15) - H.AdjustStun(-40) - H.AdjustKnockdown(-40) - H.AdjustUnconscious(-40) + var/list/inspired = list() + var/has_job_loyalties = LAZYLEN(job_loyalties) + var/has_role_loyalties = LAZYLEN(role_loyalties) + inspired += user //The user is always inspired, regardless of loyalties + for(var/mob/living/carbon/human/H in range(4, get_turf(src))) + if(H.stat == DEAD || H == user) + continue + if(H.mind && (has_job_loyalties || has_role_loyalties)) + if(has_job_loyalties && H.mind.assigned_role in job_loyalties) + inspired += H + else if(has_role_loyalties && H.mind.special_role in role_loyalties) + inspired += H + else if(check_inspiration(H)) + inspired += H + + for(var/V in inspired) + var/mob/living/carbon/human/H = V + if(H != user) + to_chat(H, "Your confidence surges as [user] flourishes [user.p_their()] [name]!") + inspiration(H) + special_inspiration(H) + +/obj/item/banner/proc/check_inspiration(mob/living/carbon/human/H) //Banner-specific conditions for being eligible + return + +/obj/item/banner/proc/inspiration(mob/living/carbon/human/H) + H.adjustBruteLoss(-15) + H.adjustFireLoss(-15) + H.AdjustStun(-40) + H.AdjustKnockdown(-40) + H.AdjustUnconscious(-40) + playsound(H, 'sound/magic/staff_healing.ogg', 25, FALSE) + +/obj/item/banner/proc/special_inspiration(mob/living/carbon/human/H) //Any banner-specific inspiration effects go here + return + +/obj/item/banner/security + name = "securistan banner" + desc = "The banner of Securistan, ruling the station with an iron fist." + icon_state = "banner_security" + job_loyalties = list("Security Officer", "Warden", "Detective", "Head of Security") + warcry = "EVERYONE DOWN ON THE GROUND!!" + +/obj/item/banner/security/mundane + inspiration_available = FALSE + +/datum/crafting_recipe/security_banner + name = "Securistan Banner" + result = /obj/item/banner/security/mundane + time = 40 + reqs = list(/obj/item/stack/rods = 2, + /obj/item/clothing/under/rank/security = 1) + category = CAT_MISC + +/obj/item/banner/medical + name = "meditopia banner" + desc = "The banner of Meditopia, generous benefactors that cure wounds and shelter the weak." + icon_state = "banner_medical" + job_loyalties = list("Medical Doctor", "Chemist", "Geneticist", "Virologist", "Chief Medical Officer") + warcry = "No wounds cannot be healed!" + +/obj/item/banner/medical/mundane + inspiration_available = FALSE + +/obj/item/banner/medical/check_inspiration(mob/living/carbon/human/H) + return H.stat //Meditopia is moved to help those in need + +/datum/crafting_recipe/medical_banner + name = "Meditopia Banner" + result = /obj/item/banner/medical/mundane + time = 40 + reqs = list(/obj/item/stack/rods = 2, + /obj/item/clothing/under/rank/medical = 1) + category = CAT_MISC + +/obj/item/banner/medical/special_inspiration(mob/living/carbon/human/H) + H.adjustToxLoss(-15) + H.setOxyLoss(0) + H.reagents.add_reagent("inaprovaline", 5) + +/obj/item/banner/science + name = "sciencia banner" + desc = "The banner of Sciencia, bold and daring thaumaturges and researchers that take the path less traveled." + icon_state = "banner_science" + job_loyalties = list("Scientist", "Roboticist", "Research Director") + warcry = "For Cuban Pete!" + +/obj/item/banner/science/mundane + inspiration_available = FALSE + +/obj/item/banner/science/check_inspiration(mob/living/carbon/human/H) + return H.on_fire //Sciencia is pleased by dedication to the art of Toxins + +/datum/crafting_recipe/science_banner + name = "Sciencia Banner" + result = /obj/item/banner/science/mundane + time = 40 + reqs = list(/obj/item/stack/rods = 2, + /obj/item/clothing/under/rank/scientist = 1) + category = CAT_MISC + +/obj/item/banner/cargo + name = "cargonia banner" + desc = "The banner of the eternal Cargonia, with the mystical power of conjuring any object into existence." + icon_state = "banner_cargo" + job_loyalties = list("Cargo Technician", "Shaft Miner", "Quartermaster") + warcry = "Hail Cargonia!" + +/obj/item/banner/cargo/mundane + inspiration_available = FALSE + +/datum/crafting_recipe/cargo_banner + name = "Cargonia Banner" + result = /obj/item/banner/cargo/mundane + time = 40 + reqs = list(/obj/item/stack/rods = 2, + /obj/item/clothing/under/rank/cargotech = 1) + category = CAT_MISC + +/obj/item/banner/engineering + name = "engitopia banner" + desc = "The banner of Engitopia, wielders of limitless power." + icon_state = "banner_engineering" + job_loyalties = list("Station Engineer", "Atmospheric Technician", "Chief Engineer") + warcry = "All hail lord Singuloth!!" + +/obj/item/banner/engineering/mundane + inspiration_available = FALSE + +/obj/item/banner/engineering/special_inspiration(mob/living/carbon/human/H) + H.radiation = 0 + +/datum/crafting_recipe/engineering_banner + name = "Engitopia Banner" + result = /obj/item/banner/engineering/mundane + time = 40 + reqs = list(/obj/item/stack/rods = 2, + /obj/item/clothing/under/rank/engineer = 1) + category = CAT_MISC + +/obj/item/banner/command + name = "command banner" + desc = "The banner of Command, a staunch and ancient line of bueraucratic kings and queens." + //No icon state here since the default one is the NT banner + job_loyalties = list("Captain", "Head of Personnel", "Chief Engineer", "Head of Security", "Research Director", "Chief Medical Officer") + warcry = "Hail Nanotrasen!" + +/obj/item/banner/command/mundane + inspiration_available = FALSE + +/obj/item/banner/command/check_inspiration(mob/living/carbon/human/H) + return H.isloyal() //Command is stalwart but rewards their allies. + +/datum/crafting_recipe/command_banner + name = "Command Banner" + result = /obj/item/banner/command/mundane + time = 40 + reqs = list(/obj/item/stack/rods = 2, + /obj/item/clothing/under/captainparade = 1) + category = CAT_MISC /obj/item/banner/red name = "red banner" From b008cdada03721c701a19833e6ac52f624f7caac Mon Sep 17 00:00:00 2001 From: LetterJay Date: Mon, 11 Sep 2017 13:47:33 -0500 Subject: [PATCH 42/74] oopsie woopsie --- .../clock_structures/prolonging_prism.dm | 905 +++--------------- 1 file changed, 125 insertions(+), 780 deletions(-) diff --git a/code/game/gamemodes/clock_cult/clock_structures/prolonging_prism.dm b/code/game/gamemodes/clock_cult/clock_structures/prolonging_prism.dm index c6692073b0..9ef7fa4ab7 100644 --- a/code/game/gamemodes/clock_cult/clock_structures/prolonging_prism.dm +++ b/code/game/gamemodes/clock_cult/clock_structures/prolonging_prism.dm @@ -1,790 +1,135 @@ -#define WELDER_FUEL_BURN_INTERVAL 13 +//Prolonging Prism: A prism that consumes power to delay the shuttle +/obj/structure/destructible/clockwork/powered/prolonging_prism + name = "prolonging prism" + desc = "A dark onyx prism, held in midair by spiraling tendrils of stone." + clockwork_desc = "A powerful prism that will delay the arrival of an emergency shuttle." + icon_state = "prolonging_prism_inactive" + active_icon = "prolonging_prism" + inactive_icon = "prolonging_prism_inactive" + unanchored_icon = "prolonging_prism_unwrenched" + construction_value = 20 + max_integrity = 125 + break_message = "The prism falls to the ground with a heavy thud!" + debris = list(/obj/item/clockwork/alloy_shards/small = 3, \ + /obj/item/clockwork/alloy_shards/medium = 1, \ + /obj/item/clockwork/alloy_shards/large = 1, \ + /obj/item/clockwork/component/vanguard_cogwheel/onyx_prism = 1) + var/static/list/component_refund = list(VANGUARD_COGWHEEL = 2, GEIS_CAPACITOR = 1, REPLICANT_ALLOY = 1) + var/static/delay_cost = 3000 + var/static/delay_cost_increase = 1250 + var/static/delay_remaining = 0 -/* Tools! - * Note: Multitools are /obj/item/device - * - * Contains: - * Wrench - * Screwdriver - * Wirecutters - * Welding Tool - * Crowbar - */ - -/* - * Wrench - */ -/obj/item/wrench - name = "wrench" - desc = "A wrench with common uses. Can be found in your hand." - icon = 'icons/obj/tools.dmi' - icon_state = "wrench" - lefthand_file = 'icons/mob/inhands/equipment/tools_lefthand.dmi' - righthand_file = 'icons/mob/inhands/equipment/tools_righthand.dmi' - flags_1 = CONDUCT_1 - slot_flags = SLOT_BELT - force = 5 - throwforce = 7 - w_class = WEIGHT_CLASS_SMALL - usesound = 'sound/items/ratchet.ogg' - materials = list(MAT_METAL=150) - origin_tech = "materials=1;engineering=1" - attack_verb = list("bashed", "battered", "bludgeoned", "whacked") - toolspeed = 1 - armor = list(melee = 0, bullet = 0, laser = 0, energy = 0, bomb = 0, bio = 0, rad = 0, fire = 50, acid = 30) - -/obj/item/wrench/suicide_act(mob/user) - user.visible_message("[user] is beating [user.p_them()]self to death with [src]! It looks like [user.p_theyre()] trying to commit suicide!") - playsound(loc, 'sound/weapons/genhit.ogg', 50, 1, -1) - return (BRUTELOSS) - -/obj/item/wrench/cyborg - name = "automatic wrench" - desc = "An advanced robotic wrench. Can be found in construction cyborgs." - toolspeed = 0.5 - -/obj/item/wrench/brass - name = "brass wrench" - desc = "A brass wrench. It's faintly warm to the touch." - resistance_flags = FIRE_PROOF | ACID_PROOF - icon_state = "wrench_brass" - toolspeed = 0.5 - -/obj/item/wrench/abductor - name = "alien wrench" - desc = "A polarized wrench. It causes anything placed between the jaws to turn." - icon = 'icons/obj/abductor.dmi' - icon_state = "wrench" - usesound = 'sound/effects/empulse.ogg' - toolspeed = 0.1 - origin_tech = "materials=5;engineering=5;abductor=3" - -/obj/item/wrench/power - name = "hand drill" - desc = "A simple powered hand drill. It's fitted with a bolt bit." - icon_state = "drill_bolt" - item_state = "drill" - lefthand_file = 'icons/mob/inhands/equipment/tools_lefthand.dmi' - righthand_file = 'icons/mob/inhands/equipment/tools_righthand.dmi' - usesound = 'sound/items/drill_use.ogg' - materials = list(MAT_METAL=150,MAT_SILVER=50,MAT_TITANIUM=25) - origin_tech = "materials=2;engineering=2" //done for balance reasons, making them high value for research, but harder to get - force = 8 //might or might not be too high, subject to change - w_class = WEIGHT_CLASS_SMALL - throwforce = 8 - attack_verb = list("drilled", "screwed", "jabbed") - toolspeed = 0.25 - -/obj/item/wrench/power/attack_self(mob/user) - playsound(get_turf(user),'sound/items/change_drill.ogg',50,1) - var/obj/item/wirecutters/power/s_drill = new /obj/item/screwdriver/power - to_chat(user, "You attach the screw driver bit to [src].") - qdel(src) - user.put_in_active_hand(s_drill) - -/obj/item/wrench/power/suicide_act(mob/user) - user.visible_message("[user] is pressing [src] against [user.p_their()] head! It looks like [user.p_theyre()] trying to commit suicide!") - return (BRUTELOSS) - -/obj/item/wrench/medical - name = "medical wrench" - desc = "A medical wrench with common(medical?) uses. Can be found in your hand." - icon_state = "wrench_medical" - force = 2 //MEDICAL - throwforce = 4 - origin_tech = "materials=1;engineering=1;biotech=3" - attack_verb = list("wrenched", "medicaled", "tapped", "jabbed", "whacked") - -/obj/item/wrench/medical/suicide_act(mob/living/user) - user.visible_message("[user] is praying to the medical wrench to take [user.p_their()] soul. It looks like [user.p_theyre()] trying to commit suicide!") - // TODO Make them glow with the power of the M E D I C A L W R E N C H - // during their ascension - - // Stun stops them from wandering off - user.Stun(100, ignore_canstun = TRUE) - playsound(loc, 'sound/effects/pray.ogg', 50, 1, -1) - - // Let the sound effect finish playing - sleep(20) - - if(!user) - return - - for(var/obj/item/W in user) - user.dropItemToGround(W) - - var/obj/item/wrench/medical/W = new /obj/item/wrench/medical(loc) - W.add_fingerprint(user) - W.desc += " For some reason, it reminds you of [user.name]." - - if(!user) - return - - user.dust() - - return OXYLOSS - -/* - * Screwdriver - */ -/obj/item/screwdriver - name = "screwdriver" - desc = "You can be totally screwy with this." - icon = 'icons/obj/tools.dmi' - icon_state = "screwdriver" - item_state = "screwdriver" - lefthand_file = 'icons/mob/inhands/equipment/tools_lefthand.dmi' - righthand_file = 'icons/mob/inhands/equipment/tools_righthand.dmi' - flags_1 = CONDUCT_1 - slot_flags = SLOT_BELT - force = 5 - w_class = WEIGHT_CLASS_TINY - throwforce = 5 - throw_speed = 3 - throw_range = 5 - materials = list(MAT_METAL=75) - attack_verb = list("stabbed") - hitsound = 'sound/weapons/bladeslice.ogg' - usesound = 'sound/items/screwdriver.ogg' - toolspeed = 1 - armor = list(melee = 0, bullet = 0, laser = 0, energy = 0, bomb = 0, bio = 0, rad = 0, fire = 50, acid = 30) - var/random_color = TRUE //if the screwdriver uses random coloring - var/static/list/screwdriver_colors = list(\ - "blue" = rgb(24, 97, 213), \ - "red" = rgb(149, 23, 16), \ - "pink" = rgb(213, 24, 141), \ - "brown" = rgb(160, 82, 18), \ - "green" = rgb(14, 127, 27), \ - "cyan" = rgb(24, 162, 213), \ - "yellow" = rgb(213, 140, 24), \ - ) - -/obj/item/screwdriver/suicide_act(mob/user) - user.visible_message("[user] is stabbing [src] into [user.p_their()] [pick("temple", "heart")]! It looks like [user.p_theyre()] trying to commit suicide!") - return(BRUTELOSS) - -/obj/item/screwdriver/Initialize() - . = ..() - if(random_color) //random colors! - var/our_color = pick(screwdriver_colors) - add_atom_colour(screwdriver_colors[our_color], FIXED_COLOUR_PRIORITY) - update_icon() - if(prob(75)) - pixel_y = rand(0, 16) - -/obj/item/screwdriver/update_icon() - if(!random_color) //icon override - return - cut_overlays() - var/mutable_appearance/base_overlay = mutable_appearance(icon, "screwdriver_screwybits") - base_overlay.appearance_flags = RESET_COLOR - add_overlay(base_overlay) - -/obj/item/screwdriver/worn_overlays(isinhands = FALSE, icon_file) - . = list() - if(isinhands && random_color) - var/mutable_appearance/M = mutable_appearance(icon_file, "screwdriver_head") - M.appearance_flags = RESET_COLOR - . += M - -/obj/item/screwdriver/get_belt_overlay() - if(random_color) - var/mutable_appearance/body = mutable_appearance('icons/obj/clothing/belt_overlays.dmi', "screwdriver") - var/mutable_appearance/head = mutable_appearance('icons/obj/clothing/belt_overlays.dmi', "screwdriver_head") - body.color = color - head.add_overlay(body) - return head - else - return mutable_appearance('icons/obj/clothing/belt_overlays.dmi', icon_state) - -/obj/item/screwdriver/attack(mob/living/carbon/M, mob/living/carbon/user) - if(!istype(M)) - return ..() - if(user.zone_selected != "eyes" && user.zone_selected != "head") - return ..() - if(user.disabilities & CLUMSY && prob(50)) - M = user - return eyestab(M,user) - -/obj/item/screwdriver/brass - name = "brass screwdriver" - desc = "A screwdriver made of brass. The handle feels freezing cold." - resistance_flags = FIRE_PROOF | ACID_PROOF - icon_state = "screwdriver_brass" - item_state = "screwdriver_brass" - toolspeed = 0.5 - random_color = FALSE - -/obj/item/screwdriver/abductor - name = "alien screwdriver" - desc = "An ultrasonic screwdriver." - icon = 'icons/obj/abductor.dmi' - icon_state = "screwdriver_a" - item_state = "screwdriver_nuke" - usesound = 'sound/items/pshoom.ogg' - toolspeed = 0.1 - random_color = FALSE - -/obj/item/screwdriver/power - name = "hand drill" - desc = "A simple powered hand drill. It's fitted with a screw bit." - icon_state = "drill_screw" - item_state = "drill" - lefthand_file = 'icons/mob/inhands/equipment/tools_lefthand.dmi' - righthand_file = 'icons/mob/inhands/equipment/tools_righthand.dmi' - materials = list(MAT_METAL=150,MAT_SILVER=50,MAT_TITANIUM=25) - origin_tech = "materials=2;engineering=2" //done for balance reasons, making them high value for research, but harder to get - force = 8 //might or might not be too high, subject to change - w_class = WEIGHT_CLASS_SMALL - throwforce = 8 - throw_speed = 2 - throw_range = 3//it's heavier than a screw driver/wrench, so it does more damage, but can't be thrown as far - attack_verb = list("drilled", "screwed", "jabbed","whacked") - hitsound = 'sound/items/drill_hit.ogg' - usesound = 'sound/items/drill_use.ogg' - toolspeed = 0.25 - random_color = FALSE - -/obj/item/screwdriver/power/suicide_act(mob/user) - user.visible_message("[user] is putting [src] to [user.p_their()] temple. It looks like [user.p_theyre()] trying to commit suicide!") - return(BRUTELOSS) - -/obj/item/screwdriver/power/attack_self(mob/user) - playsound(get_turf(user),'sound/items/change_drill.ogg',50,1) - var/obj/item/wrench/power/b_drill = new /obj/item/wrench/power - to_chat(user, "You attach the bolt driver bit to [src].") - qdel(src) - user.put_in_active_hand(b_drill) - -/obj/item/screwdriver/cyborg - name = "powered screwdriver" - desc = "An electrical screwdriver, designed to be both precise and quick." - usesound = 'sound/items/drill_use.ogg' - toolspeed = 0.5 - -/* - * Wirecutters - */ -/obj/item/wirecutters - name = "wirecutters" - desc = "This cuts wires." - icon = 'icons/obj/tools.dmi' - icon_state = null - lefthand_file = 'icons/mob/inhands/equipment/tools_lefthand.dmi' - righthand_file = 'icons/mob/inhands/equipment/tools_righthand.dmi' - flags_1 = CONDUCT_1 - slot_flags = SLOT_BELT - force = 6 - throw_speed = 3 - throw_range = 7 - w_class = WEIGHT_CLASS_SMALL - materials = list(MAT_METAL=80) - attack_verb = list("pinched", "nipped") - hitsound = 'sound/items/wirecutter.ogg' - usesound = 'sound/items/wirecutter.ogg' - origin_tech = "materials=1;engineering=1" - toolspeed = 1 - armor = list(melee = 0, bullet = 0, laser = 0, energy = 0, bomb = 0, bio = 0, rad = 0, fire = 50, acid = 30) - - -/obj/item/wirecutters/New(loc, var/param_color = null) +/obj/structure/destructible/clockwork/powered/prolonging_prism/examine(mob/user) ..() - if(!icon_state) - if(!param_color) - param_color = pick("yellow","red") - icon_state = "cutters_[param_color]" + if(is_servant_of_ratvar(user) || isobserver(user)) + if(SSshuttle.emergency.mode == SHUTTLE_DOCKED || SSshuttle.emergency.mode == SHUTTLE_IGNITING || SSshuttle.emergency.mode == SHUTTLE_STRANDED || SSshuttle.emergency.mode == SHUTTLE_ESCAPE) + to_chat(user, "An emergency shuttle has arrived and this prism is no longer useful; attempt to activate it to gain a partial refund of components used.") + else + var/efficiency = get_efficiency_mod(TRUE) + to_chat(user, "It requires at least [DisplayPower(get_delay_cost())] of power to attempt to delay the arrival of an emergency shuttle by [2 * efficiency] minutes.") + to_chat(user, "This cost increases by [DisplayPower(delay_cost_increase)] for every previous activation.") -/obj/item/wirecutters/attack(mob/living/carbon/C, mob/user) - if(istype(C) && C.handcuffed && istype(C.handcuffed, /obj/item/restraints/handcuffs/cable)) - user.visible_message("[user] cuts [C]'s restraints with [src]!") - qdel(C.handcuffed) - C.handcuffed = null - if(C.buckled && C.buckled.buckle_requires_restraints) - C.buckled.unbuckle_mob(C) - C.update_handcuffed() - return - else - ..() - -/obj/item/wirecutters/suicide_act(mob/user) - user.visible_message("[user] is cutting at [user.p_their()] arteries with [src]! It looks like [user.p_theyre()] trying to commit suicide!") - playsound(loc, usesound, 50, 1, -1) - return (BRUTELOSS) - -/obj/item/wirecutters/brass - name = "brass wirecutters" - desc = "A pair of wirecutters made of brass. The handle feels freezing cold to the touch." - resistance_flags = FIRE_PROOF | ACID_PROOF - icon_state = "cutters_brass" - toolspeed = 0.5 - -/obj/item/wirecutters/abductor - name = "alien wirecutters" - desc = "Extremely sharp wirecutters, made out of a silvery-green metal." - icon = 'icons/obj/abductor.dmi' - icon_state = "cutters" - toolspeed = 0.1 - origin_tech = "materials=5;engineering=4;abductor=3" - -/obj/item/wirecutters/cyborg - name = "wirecutters" - desc = "This cuts wires." - toolspeed = 0.5 - -/obj/item/wirecutters/power - name = "jaws of life" - desc = "A set of jaws of life, compressed through the magic of science. It's fitted with a cutting head." - icon_state = "jaws_cutter" - item_state = "jawsoflife" - origin_tech = "materials=2;engineering=2" - materials = list(MAT_METAL=150,MAT_SILVER=50,MAT_TITANIUM=25) - usesound = 'sound/items/jaws_cut.ogg' - toolspeed = 0.25 - -/obj/item/wirecutters/power/suicide_act(mob/user) - user.visible_message("[user] is wrapping \the [src] around [user.p_their()] neck. It looks like [user.p_theyre()] trying to rip [user.p_their()] head off!") - playsound(loc, 'sound/items/jaws_cut.ogg', 50, 1, -1) - if(iscarbon(user)) - var/mob/living/carbon/C = user - var/obj/item/bodypart/BP = C.get_bodypart("head") - if(BP) - BP.drop_limb() - playsound(loc,pick('sound/misc/desceration-01.ogg','sound/misc/desceration-02.ogg','sound/misc/desceration-01.ogg') ,50, 1, -1) - return (BRUTELOSS) - -/obj/item/wirecutters/power/attack_self(mob/user) - playsound(get_turf(user), 'sound/items/change_jaws.ogg', 50, 1) - var/obj/item/crowbar/power/pryjaws = new /obj/item/crowbar/power - to_chat(user, "You attach the pry jaws to [src].") - qdel(src) - user.put_in_active_hand(pryjaws) -/* - * Welding Tool - */ -/obj/item/weldingtool - name = "welding tool" - desc = "A standard edition welder provided by Nanotrasen." - icon = 'icons/obj/tools.dmi' - icon_state = "welder" - item_state = "welder" - lefthand_file = 'icons/mob/inhands/equipment/tools_lefthand.dmi' - righthand_file = 'icons/mob/inhands/equipment/tools_righthand.dmi' - flags_1 = CONDUCT_1 - slot_flags = SLOT_BELT - force = 3 - throwforce = 5 - hitsound = "swing_hit" - usesound = 'sound/items/welder.ogg' - var/acti_sound = 'sound/items/welderactivate.ogg' - var/deac_sound = 'sound/items/welderdeactivate.ogg' - throw_speed = 3 - throw_range = 5 - w_class = WEIGHT_CLASS_SMALL - armor = list(melee = 0, bullet = 0, laser = 0, energy = 0, bomb = 0, bio = 0, rad = 0, fire = 100, acid = 30) - resistance_flags = FIRE_PROOF - - materials = list(MAT_METAL=70, MAT_GLASS=30) - origin_tech = "engineering=1;plasmatech=1" - var/welding = 0 //Whether or not the welding tool is off(0), on(1) or currently welding(2) - var/status = TRUE //Whether the welder is secured or unsecured (able to attach rods to it to make a flamethrower) - var/max_fuel = 20 //The max amount of fuel the welder can hold - var/change_icons = 1 - var/can_off_process = 0 - var/light_intensity = 2 //how powerful the emitted light is when used. - var/burned_fuel_for = 0 //when fuel was last removed - heat = 3800 - toolspeed = 1 - -/obj/item/weldingtool/Initialize() - . = ..() - create_reagents(max_fuel) - reagents.add_reagent("welding_fuel", max_fuel) - update_icon() - - -/obj/item/weldingtool/proc/update_torch() - if(welding) - add_overlay("[initial(icon_state)]-on") - item_state = "[initial(item_state)]1" - else - item_state = "[initial(item_state)]" - - -/obj/item/weldingtool/update_icon() - cut_overlays() - if(change_icons) - var/ratio = get_fuel() / max_fuel - ratio = Ceiling(ratio*4) * 25 - add_overlay("[initial(icon_state)][ratio]") - update_torch() - return - - -/obj/item/weldingtool/process() - switch(welding) - if(0) - force = 3 - damtype = "brute" - update_icon() - if(!can_off_process) - STOP_PROCESSING(SSobj, src) - return - //Welders left on now use up fuel, but lets not have them run out quite that fast - if(1) - force = 15 - damtype = "fire" - ++burned_fuel_for - if(burned_fuel_for >= WELDER_FUEL_BURN_INTERVAL) - remove_fuel(1) - update_icon() - - //This is to start fires. process() is only called if the welder is on. - open_flame() - - -/obj/item/weldingtool/suicide_act(mob/user) - user.visible_message("[user] welds [user.p_their()] every orifice closed! It looks like [user.p_theyre()] trying to commit suicide!") - return (FIRELOSS) - - -/obj/item/weldingtool/attackby(obj/item/I, mob/user, params) - if(istype(I, /obj/item/screwdriver)) - flamethrower_screwdriver(I, user) - else if(istype(I, /obj/item/stack/rods)) - flamethrower_rods(I, user) - else - return ..() - - -/obj/item/weldingtool/attack(mob/living/carbon/human/H, mob/user) - if(!istype(H)) - return ..() - - var/obj/item/bodypart/affecting = H.get_bodypart(check_zone(user.zone_selected)) - - if(affecting && affecting.status == BODYPART_ROBOTIC && user.a_intent != INTENT_HARM) - if(src.remove_fuel(1)) - playsound(loc, usesound, 50, 1) - if(user == H) - user.visible_message("[user] starts to fix some of the dents on [H]'s [affecting.name].", "You start fixing some of the dents on [H]'s [affecting.name].") - if(!do_mob(user, H, 50)) - return - item_heal_robotic(H, user, 15, 0) - else - return ..() - - -/obj/item/weldingtool/afterattack(atom/O, mob/user, proximity) - if(!proximity) return - - if(welding) - remove_fuel(1) - var/turf/location = get_turf(user) - location.hotspot_expose(700, 50, 1) - if(get_fuel() <= 0) - set_light(0) - - if(isliving(O)) - var/mob/living/L = O - if(L.IgniteMob()) - message_admins("[key_name_admin(user)] set [key_name_admin(L)] on fire") - log_game("[key_name(user)] set [key_name(L)] on fire") - - -/obj/item/weldingtool/attack_self(mob/user) - switched_on(user) - if(welding) - set_light(light_intensity) - - update_icon() - - -//Returns the amount of fuel in the welder -/obj/item/weldingtool/proc/get_fuel() - return reagents.get_reagent_amount("welding_fuel") - - -//Removes fuel from the welding tool. If a mob is passed, it will try to flash the mob's eyes. This should probably be renamed to use() -/obj/item/weldingtool/proc/remove_fuel(amount = 1, mob/living/M = null) - if(!welding || !check_fuel()) - return 0 - if(amount) - burned_fuel_for = 0 - if(get_fuel() >= amount) - reagents.remove_reagent("welding_fuel", amount) - check_fuel() - if(M) - M.flash_act(light_intensity) +/obj/structure/destructible/clockwork/powered/prolonging_prism/forced_disable(bad_effects) + if(active) + if(bad_effects) + try_use_power(MIN_CLOCKCULT_POWER*4) + visible_message("[src] emits an airy chuckling sound and falls dark!") + toggle() return TRUE - else - if(M) - to_chat(M, "You need more welding fuel to complete this task!") - return FALSE +/obj/structure/destructible/clockwork/powered/prolonging_prism/attack_hand(mob/living/user) + if(user.canUseTopic(src, !issilicon(user), NO_DEXTERY) && is_servant_of_ratvar(user)) + if(SSshuttle.emergency.mode == SHUTTLE_DOCKED || SSshuttle.emergency.mode == SHUTTLE_IGNITING || SSshuttle.emergency.mode == SHUTTLE_STRANDED || SSshuttle.emergency.mode == SHUTTLE_ESCAPE) + to_chat(user, "You break [src] apart, refunding some of the components used.") + for(var/i in component_refund) + generate_cache_component(i, src) + take_damage(max_integrity) + return 0 + if(active) + return 0 + var/turf/T = get_turf(src) + if(!T || T.z != ZLEVEL_STATION) + to_chat(user, "[src] must be on the station to function!") + return 0 + if(SSshuttle.emergency.mode != SHUTTLE_CALL) + to_chat(user, "No emergency shuttles are attempting to arrive at the station!") + return 0 + if(!try_use_power(get_delay_cost())) + to_chat(user, "[src] needs more power to function!") + return 0 + delay_cost += delay_cost_increase + delay_remaining += PRISM_DELAY_DURATION + toggle(0, user) -//Turns off the welder if there is no more fuel (does this really need to be its own proc?) -/obj/item/weldingtool/proc/check_fuel(mob/user) - if(get_fuel() <= 0 && welding) - switched_on(user) - update_icon() - //mob icon update - if(ismob(loc)) - var/mob/M = loc - M.update_inv_hands(0) - - return 0 - return 1 - -//Switches the welder on -/obj/item/weldingtool/proc/switched_on(mob/user) - if(!status) - to_chat(user, "[src] can't be turned on while unsecured!") +/obj/structure/destructible/clockwork/powered/prolonging_prism/process() + var/turf/own_turf = get_turf(src) + if(SSshuttle.emergency.mode != SHUTTLE_CALL || delay_remaining <= 0 || !own_turf || own_turf.z != ZLEVEL_STATION) + forced_disable(FALSE) return - welding = !welding - if(welding) - if(get_fuel() >= 1) - to_chat(user, "You switch [src] on.") - playsound(loc, acti_sound, 50, 1) - force = 15 - damtype = "fire" - hitsound = 'sound/items/welder.ogg' - update_icon() - START_PROCESSING(SSobj, src) + . = ..() + var/delay_amount = 40 + delay_remaining -= delay_amount + var/efficiency = get_efficiency_mod() + SSshuttle.emergency.setTimer(SSshuttle.emergency.timeLeft(1) + (delay_amount * efficiency)) + var/highest_y + var/highest_x + var/lowest_y + var/lowest_x + var/list/prism_turfs = list() + for(var/t in SSshuttle.emergency.ripple_area(SSshuttle.getDock("emergency_home"))) + prism_turfs[t] = TRUE + var/turf/T = t + if(!highest_y || T.y > highest_y) + highest_y = T.y + if(!highest_x || T.x > highest_x) + highest_x = T.x + if(!lowest_y || T.y < lowest_y) + lowest_y = T.y + if(!lowest_x || T.x < lowest_x) + lowest_x = T.x + var/mean_y = Lerp(lowest_y, highest_y) + var/mean_x = Lerp(lowest_x, highest_x) + if(prob(50)) + mean_y = Ceiling(mean_y) + else + mean_y = Floor(mean_y) + if(prob(50)) + mean_x = Ceiling(mean_x) + else + mean_x = Floor(mean_x) + var/turf/semi_random_center_turf = locate(mean_x, mean_y, ZLEVEL_STATION) + for(var/t in getline(src, semi_random_center_turf)) + prism_turfs[t] = TRUE + var/placement_style = prob(50) + for(var/t in prism_turfs) + var/turf/T = t + if(placement_style) + if(IsOdd(T.x + T.y)) + seven_random_hexes(T, efficiency) + else if(prob(50 * efficiency)) + new /obj/effect/temp_visual/ratvar/prolonging_prism(T) else - to_chat(user, "You need more fuel!") - switched_off(user) - else - to_chat(user, "You switch [src] off.") - playsound(loc, deac_sound, 50, 1) - switched_off(user) + if(IsEven(T.x + T.y)) + seven_random_hexes(T, efficiency) + else if(prob(50 * efficiency)) + new /obj/effect/temp_visual/ratvar/prolonging_prism(T) + CHECK_TICK //we may be going over a hell of a lot of turfs -//Switches the welder off -/obj/item/weldingtool/proc/switched_off(mob/user) - welding = 0 - set_light(0) +/obj/structure/destructible/clockwork/powered/prolonging_prism/proc/get_delay_cost() + return Floor(delay_cost, MIN_CLOCKCULT_POWER) - force = 3 - damtype = "brute" - hitsound = "swing_hit" - update_icon() - - -/obj/item/weldingtool/examine(mob/user) - ..() - to_chat(user, "It contains [get_fuel()] unit\s of fuel out of [max_fuel].") - -/obj/item/weldingtool/is_hot() - return welding * heat - -//Returns whether or not the welding tool is currently on. -/obj/item/weldingtool/proc/isOn() - return welding - - -/obj/item/weldingtool/proc/flamethrower_screwdriver(obj/item/I, mob/user) - if(welding) - to_chat(user, "Turn it off first!") - return - status = !status - if(status) - to_chat(user, "You resecure [src].") - else - to_chat(user, "[src] can now be attached and modified.") - add_fingerprint(user) - -/obj/item/weldingtool/proc/flamethrower_rods(obj/item/I, mob/user) - if(!status) - var/obj/item/stack/rods/R = I - if (R.use(1)) - var/obj/item/flamethrower/F = new /obj/item/flamethrower(user.loc) - if(!remove_item_from_storage(F)) - user.transferItemToLoc(src, F, TRUE) - F.weldtool = src - add_fingerprint(user) - to_chat(user, "You add a rod to a welder, starting to build a flamethrower.") - user.put_in_hands(F) - else - to_chat(user, "You need one rod to start building a flamethrower!") - -/obj/item/weldingtool/ignition_effect(atom/A, mob/user) - if(welding && remove_fuel(1, user)) - . = "[user] casually lights [A] with [src], what a badass." - else - . = "" - -/obj/item/weldingtool/largetank - name = "industrial welding tool" - desc = "A slightly larger welder with a larger tank." - icon_state = "indwelder" - max_fuel = 40 - materials = list(MAT_GLASS=60) - origin_tech = "engineering=2;plasmatech=2" - -/obj/item/weldingtool/largetank/cyborg - name = "integrated welding tool" - desc = "An advanced welder designed to be used in robotic systems." - toolspeed = 0.5 - -/obj/item/weldingtool/largetank/flamethrower_screwdriver() - return - - -/obj/item/weldingtool/mini - name = "emergency welding tool" - desc = "A miniature welder used during emergencies." - icon_state = "miniwelder" - max_fuel = 10 - w_class = WEIGHT_CLASS_TINY - materials = list(MAT_METAL=30, MAT_GLASS=10) - change_icons = 0 - -/obj/item/weldingtool/mini/flamethrower_screwdriver() - return - -/obj/item/weldingtool/abductor - name = "alien welding tool" - desc = "An alien welding tool. Whatever fuel it uses, it never runs out." - icon = 'icons/obj/abductor.dmi' - icon_state = "welder" - toolspeed = 0.1 - light_intensity = 0 - change_icons = 0 - origin_tech = "plasmatech=5;engineering=5;abductor=3" - -/obj/item/weldingtool/abductor/process() - if(get_fuel() <= max_fuel) - reagents.add_reagent("welding_fuel", 1) - ..() - -/obj/item/weldingtool/hugetank - name = "upgraded industrial welding tool" - desc = "An upgraded welder based of the industrial welder." - icon_state = "upindwelder" - item_state = "upindwelder" - max_fuel = 80 - materials = list(MAT_METAL=70, MAT_GLASS=120) - origin_tech = "engineering=3;plasmatech=2" - -/obj/item/weldingtool/experimental - name = "experimental welding tool" - desc = "An experimental welder capable of self-fuel generation and less harmful to the eyes." - icon_state = "exwelder" - item_state = "exwelder" - max_fuel = 40 - materials = list(MAT_METAL=70, MAT_GLASS=120) - origin_tech = "materials=4;engineering=4;bluespace=3;plasmatech=4" - var/last_gen = 0 - change_icons = 0 - can_off_process = 1 - light_intensity = 1 - toolspeed = 0.5 - var/nextrefueltick = 0 - -/obj/item/weldingtool/experimental/brass - name = "brass welding tool" - desc = "A brass welder that seems to constantly refuel itself. It is faintly warm to the touch." - resistance_flags = FIRE_PROOF | ACID_PROOF - icon_state = "brasswelder" - item_state = "brasswelder" - - -/obj/item/weldingtool/experimental/process() - ..() - if(get_fuel() < max_fuel && nextrefueltick < world.time) - nextrefueltick = world.time + 10 - reagents.add_reagent("welding_fuel", 1) - - -/* - * Crowbar - */ - -/obj/item/crowbar - name = "pocket crowbar" - desc = "A small crowbar. This handy tool is useful for lots of things, such as prying floor tiles or opening unpowered doors." - icon = 'icons/obj/tools.dmi' - icon_state = "crowbar" - lefthand_file = 'icons/mob/inhands/equipment/tools_lefthand.dmi' - righthand_file = 'icons/mob/inhands/equipment/tools_righthand.dmi' - usesound = 'sound/items/crowbar.ogg' - flags_1 = CONDUCT_1 - slot_flags = SLOT_BELT - force = 5 - throwforce = 7 - w_class = WEIGHT_CLASS_SMALL - materials = list(MAT_METAL=50) - origin_tech = "engineering=1;combat=1" - attack_verb = list("attacked", "bashed", "battered", "bludgeoned", "whacked") - toolspeed = 1 - armor = list(melee = 0, bullet = 0, laser = 0, energy = 0, bomb = 0, bio = 0, rad = 0, fire = 50, acid = 30) - -/obj/item/crowbar/suicide_act(mob/user) - user.visible_message("[user] is beating [user.p_them()]self to death with [src]! It looks like [user.p_theyre()] trying to commit suicide!") - playsound(loc, 'sound/weapons/genhit.ogg', 50, 1, -1) - return (BRUTELOSS) - -/obj/item/crowbar/red - icon_state = "crowbar_red" - force = 8 - -/obj/item/crowbar/brass - name = "brass crowbar" - desc = "A brass crowbar. It feels faintly warm to the touch." - resistance_flags = FIRE_PROOF | ACID_PROOF - icon_state = "crowbar_brass" - toolspeed = 0.5 - -/obj/item/crowbar/abductor - name = "alien crowbar" - desc = "A hard-light crowbar. It appears to pry by itself, without any effort required." - icon = 'icons/obj/abductor.dmi' - usesound = 'sound/weapons/sonic_jackhammer.ogg' - icon_state = "crowbar" - toolspeed = 0.1 - origin_tech = "combat=4;engineering=4;abductor=3" - -/obj/item/crowbar/large - name = "crowbar" - desc = "It's a big crowbar. It doesn't fit in your pockets, because it's big." - force = 12 - w_class = WEIGHT_CLASS_NORMAL - throw_speed = 3 - throw_range = 3 - materials = list(MAT_METAL=70) - icon_state = "crowbar_large" - item_state = "crowbar" - toolspeed = 0.5 - -/obj/item/crowbar/cyborg - name = "hydraulic crowbar" - desc = "A hydraulic prying tool, compact but powerful. Designed to replace crowbar in construction cyborgs." - usesound = 'sound/items/jaws_pry.ogg' - force = 10 - toolspeed = 0.5 - -/obj/item/crowbar/power - name = "jaws of life" - desc = "A set of jaws of life, compressed through the magic of science. It's fitted with a prying head." - icon_state = "jaws_pry" - item_state = "jawsoflife" - lefthand_file = 'icons/mob/inhands/equipment/tools_lefthand.dmi' - righthand_file = 'icons/mob/inhands/equipment/tools_righthand.dmi' - materials = list(MAT_METAL=150,MAT_SILVER=50,MAT_TITANIUM=25) - origin_tech = "materials=2;engineering=2" - usesound = 'sound/items/jaws_pry.ogg' - force = 15 - toolspeed = 0.25 - -/obj/item/crowbar/power/suicide_act(mob/user) - user.visible_message("[user] is putting [user.p_their()] head in [src], it looks like [user.p_theyre()] trying to commit suicide!") - playsound(loc, 'sound/items/jaws_pry.ogg', 50, 1, -1) - return (BRUTELOSS) - -/obj/item/crowbar/power/attack_self(mob/user) - playsound(get_turf(user), 'sound/items/change_jaws.ogg', 50, 1) - var/obj/item/wirecutters/power/cutjaws = new /obj/item/wirecutters/power - to_chat(user, "You attach the cutting jaws to [src].") - qdel(src) - user.put_in_active_hand(cutjaws) - -#undef WELDER_FUEL_BURN_INTERVAL +/obj/structure/destructible/clockwork/powered/prolonging_prism/proc/seven_random_hexes(turf/T, efficiency) + var/static/list/hex_states = list("prismhex1", "prismhex2", "prismhex3", "prismhex4", "prismhex5", "prismhex6", "prismhex7") + var/mutable_appearance/hex_combo + for(var/n in hex_states) //BUILD ME A HEXAGON + if(prob(50 * efficiency)) + if(!hex_combo) + hex_combo = mutable_appearance('icons/effects/64x64.dmi', n, RIPPLE_LAYER) + else + hex_combo.add_overlay(mutable_appearance('icons/effects/64x64.dmi', n, RIPPLE_LAYER)) + if(hex_combo) //YOU BUILT A HEXAGON + hex_combo.pixel_x = -16 + hex_combo.pixel_y = -16 + hex_combo.mouse_opacity = MOUSE_OPACITY_TRANSPARENT + hex_combo.plane = GAME_PLANE + new /obj/effect/temp_visual/ratvar/prolonging_prism(T, hex_combo) From 447937477e391c299195cf418fdc6c33f7350664 Mon Sep 17 00:00:00 2001 From: LetterJay Date: Mon, 11 Sep 2017 13:50:49 -0500 Subject: [PATCH 43/74] more oopsies --- code/game/objects/items/weaponry.dm | 566 ---------------------------- 1 file changed, 566 deletions(-) diff --git a/code/game/objects/items/weaponry.dm b/code/game/objects/items/weaponry.dm index 443518ec0a..17bbb0a12f 100644 --- a/code/game/objects/items/weaponry.dm +++ b/code/game/objects/items/weaponry.dm @@ -23,572 +23,6 @@ else M.visible_message("[M] has been banned FOR NO REISIN by [user]", "You have been banned FOR NO REISIN by [user]", "you hear a banhammer banning someone") - playsound(loc, 'sound/effects/adminhelp.ogg', 15) //keep it at 15% volume so people don't jump out of their skin too much - -/obj/item/sord - name = "\improper SORD" - desc = "This thing is so unspeakably shitty you are having a hard time even holding it." - icon_state = "sord" - item_state = "sord" - lefthand_file = 'icons/mob/inhands/weapons/swords_lefthand.dmi' - righthand_file = 'icons/mob/inhands/weapons/swords_righthand.dmi' - slot_flags = SLOT_BELT - force = 2 - throwforce = 1 - w_class = WEIGHT_CLASS_NORMAL - hitsound = 'sound/weapons/bladeslice.ogg' - attack_verb = list("attacked", "slashed", "stabbed", "sliced", "torn", "ripped", "diced", "cut") - -/obj/item/sord/suicide_act(mob/user) - user.visible_message("[user] is trying to impale [user.p_them()]self with [src]! It might be a suicide attempt if it weren't so shitty.", \ - "You try to impale yourself with [src], but it's USELESS...") - return SHAME - -/obj/item/claymore - name = "claymore" - desc = "What are you standing around staring at this for? Get to killing!" - icon_state = "claymore" - item_state = "claymore" - lefthand_file = 'icons/mob/inhands/weapons/swords_lefthand.dmi' - righthand_file = 'icons/mob/inhands/weapons/swords_righthand.dmi' - hitsound = 'sound/weapons/bladeslice.ogg' - flags_1 = CONDUCT_1 - slot_flags = SLOT_BELT | SLOT_BACK - force = 40 - throwforce = 10 - w_class = WEIGHT_CLASS_NORMAL - attack_verb = list("attacked", "slashed", "stabbed", "sliced", "torn", "ripped", "diced", "cut") - block_chance = 50 - sharpness = IS_SHARP - max_integrity = 200 - armor = list(melee = 0, bullet = 0, laser = 0, energy = 0, bomb = 0, bio = 0, rad = 0, fire = 100, acid = 50) - resistance_flags = FIRE_PROOF - -/obj/item/claymore/suicide_act(mob/user) - user.visible_message("[user] is falling on [src]! It looks like [user.p_theyre()] trying to commit suicide!") - return(BRUTELOSS) - -/obj/item/claymore/highlander //ALL COMMENTS MADE REGARDING THIS SWORD MUST BE MADE IN ALL CAPS - desc = "THERE CAN BE ONLY ONE, AND IT WILL BE YOU!!!\nActivate it in your hand to point to the nearest victim." - flags_1 = CONDUCT_1 | NODROP_1 | DROPDEL_1 - slot_flags = null - block_chance = 0 //RNG WON'T HELP YOU NOW, PANSY - luminosity = 3 - attack_verb = list("brutalized", "eviscerated", "disemboweled", "hacked", "carved", "cleaved") //ONLY THE MOST VISCERAL ATTACK VERBS - var/notches = 0 //HOW MANY PEOPLE HAVE BEEN SLAIN WITH THIS BLADE - var/obj/item/disk/nuclear/nuke_disk //OUR STORED NUKE DISK - -/obj/item/claymore/highlander/Initialize() - . = ..() - START_PROCESSING(SSobj, src) - -/obj/item/claymore/highlander/Destroy() - if(nuke_disk) - nuke_disk.forceMove(get_turf(src)) - nuke_disk.visible_message("The nuke disk is vulnerable!") - nuke_disk = null - STOP_PROCESSING(SSobj, src) - return ..() - -/obj/item/claymore/highlander/process() - if(ishuman(loc)) - var/mob/living/carbon/human/H = loc - loc.layer = LARGE_MOB_LAYER //NO HIDING BEHIND PLANTS FOR YOU, DICKWEED (HA GET IT, BECAUSE WEEDS ARE PLANTS) - H.bleedsuppress = TRUE //AND WE WON'T BLEED OUT LIKE COWARDS - else - if(!admin_spawned) - qdel(src) - - -/obj/item/claymore/highlander/pickup(mob/living/user) - to_chat(user, "The power of Scotland protects you! You are shielded from all stuns and knockdowns.") - user.add_stun_absorption("highlander", INFINITY, 1, " is protected by the power of Scotland!", "The power of Scotland absorbs the stun!", " is protected by the power of Scotland!") - user.status_flags += IGNORESLOWDOWN - -/obj/item/claymore/highlander/dropped(mob/living/user) - user.status_flags -= IGNORESLOWDOWN - qdel(src) //If this ever happens, it's because you lost an arm - -/obj/item/claymore/highlander/examine(mob/user) - ..() - to_chat(user, "It has [!notches ? "nothing" : "[notches] notches"] scratched into the blade.") - if(nuke_disk) - to_chat(user, "It's holding the nuke disk!") - -/obj/item/claymore/highlander/attack(mob/living/target, mob/living/user) - . = ..() - if(target && target.stat == DEAD && target.mind && target.mind.special_role == "highlander") - user.fully_heal() //STEAL THE LIFE OF OUR FALLEN FOES - add_notch(user) - target.visible_message("[target] crumbles to dust beneath [user]'s blows!", "As you fall, your body crumbles to dust!") - target.dust() - -/obj/item/claymore/highlander/attack_self(mob/living/user) - var/closest_victim - var/closest_distance = 255 - for(var/mob/living/carbon/human/H in GLOB.player_list - user) - if(H.client && H.mind.special_role == "highlander" && (!closest_victim || get_dist(user, closest_victim) < closest_distance)) - closest_victim = H - if(!closest_victim) - to_chat(user, "[src] thrums for a moment and falls dark. Perhaps there's nobody nearby.") - return - to_chat(user, "[src] thrums and points to the [dir2text(get_dir(user, closest_victim))].") - -/obj/item/claymore/highlander/IsReflect() - return 1 //YOU THINK YOUR PUNY LASERS CAN STOP ME? - -/obj/item/claymore/highlander/proc/add_notch(mob/living/user) //DYNAMIC CLAYMORE PROGRESSION SYSTEM - THIS IS THE FUTURE - notches++ - force++ - var/new_name = name - switch(notches) - if(1) - to_chat(user, "Your first kill - hopefully one of many. You scratch a notch into [src]'s blade.") - to_chat(user, "You feel your fallen foe's soul entering your blade, restoring your wounds!") - new_name = "notched claymore" - if(2) - to_chat(user, "Another falls before you. Another soul fuses with your own. Another notch in the blade.") - new_name = "double-notched claymore" - add_atom_colour(rgb(255, 235, 235), ADMIN_COLOUR_PRIORITY) - if(3) - to_chat(user, "You're beginning to relish the thrill of battle.") - new_name = "triple-notched claymore" - add_atom_colour(rgb(255, 215, 215), ADMIN_COLOUR_PRIORITY) - if(4) - to_chat(user, "You've lost count of how many you've killed.") - new_name = "many-notched claymore" - add_atom_colour(rgb(255, 195, 195), ADMIN_COLOUR_PRIORITY) - if(5) - to_chat(user, "Five voices now echo in your mind, cheering the slaughter.") - new_name = "battle-tested claymore" - add_atom_colour(rgb(255, 175, 175), ADMIN_COLOUR_PRIORITY) - if(6) - to_chat(user, "Is this what the vikings felt like? Visions of glory fill your head as you slay your sixth foe.") - new_name = "battle-scarred claymore" - add_atom_colour(rgb(255, 155, 155), ADMIN_COLOUR_PRIORITY) - if(7) - to_chat(user, "Kill. Butcher. Conquer.") - new_name = "vicious claymore" - add_atom_colour(rgb(255, 135, 135), ADMIN_COLOUR_PRIORITY) - if(8) - to_chat(user, "IT NEVER GETS OLD. THE SCREAMING. THE BLOOD AS IT SPRAYS ACROSS YOUR FACE.") - new_name = "bloodthirsty claymore" - add_atom_colour(rgb(255, 115, 115), ADMIN_COLOUR_PRIORITY) - if(9) - to_chat(user, "ANOTHER ONE FALLS TO YOUR BLOWS. ANOTHER WEAKLING UNFIT TO LIVE.") - new_name = "gore-stained claymore" - add_atom_colour(rgb(255, 95, 95), ADMIN_COLOUR_PRIORITY) - if(10) - user.visible_message("[user]'s eyes light up with a vengeful fire!", \ - "YOU FEEL THE POWER OF VALHALLA FLOWING THROUGH YOU! THERE CAN BE ONLY ONE!!!") - user.update_icons() - new_name = "GORE-DRENCHED CLAYMORE OF [pick("THE WHIMSICAL SLAUGHTER", "A THOUSAND SLAUGHTERED CATTLE", "GLORY AND VALHALLA", "ANNIHILATION", "OBLITERATION")]" - icon_state = "claymore_valhalla" - item_state = "cultblade" - remove_atom_colour(ADMIN_COLOUR_PRIORITY) - - name = new_name - playsound(user, 'sound/items/screwdriver2.ogg', 50, 1) - -/obj/item/katana - name = "katana" - desc = "Woefully underpowered in D20" - icon_state = "katana" - item_state = "katana" - lefthand_file = 'icons/mob/inhands/weapons/swords_lefthand.dmi' - righthand_file = 'icons/mob/inhands/weapons/swords_righthand.dmi' - flags_1 = CONDUCT_1 - slot_flags = SLOT_BELT | SLOT_BACK - force = 40 - throwforce = 10 - w_class = WEIGHT_CLASS_NORMAL - hitsound = 'sound/weapons/bladeslice.ogg' - attack_verb = list("attacked", "slashed", "stabbed", "sliced", "torn", "ripped", "diced", "cut") - block_chance = 50 - sharpness = IS_SHARP - max_integrity = 200 - armor = list(melee = 0, bullet = 0, laser = 0, energy = 0, bomb = 0, bio = 0, rad = 0, fire = 100, acid = 50) - resistance_flags = FIRE_PROOF - -/obj/item/katana/cursed - slot_flags = null - -/obj/item/katana/suicide_act(mob/user) - user.visible_message("[user] is slitting [user.p_their()] stomach open with [src]! It looks like [user.p_theyre()] trying to commit seppuku!") - return(BRUTELOSS) - -/obj/item/wirerod - name = "wired rod" - desc = "A rod with some wire wrapped around the top. It'd be easy to attach something to the top bit." - icon_state = "wiredrod" - item_state = "rods" - flags_1 = CONDUCT_1 - force = 9 - throwforce = 10 - w_class = WEIGHT_CLASS_NORMAL - materials = list(MAT_METAL=1150, MAT_GLASS=75) - attack_verb = list("hit", "bludgeoned", "whacked", "bonked") - -/obj/item/wirerod/attackby(obj/item/I, mob/user, params) - if(istype(I, /obj/item/shard)) - var/obj/item/twohanded/spear/S = new /obj/item/twohanded/spear - - remove_item_from_storage(user) - qdel(I) - qdel(src) - - user.put_in_hands(S) - to_chat(user, "You fasten the glass shard to the top of the rod with the cable.") - - else if(istype(I, /obj/item/device/assembly/igniter) && !(I.flags_1 & NODROP_1)) - var/obj/item/melee/baton/cattleprod/P = new /obj/item/melee/baton/cattleprod - - remove_item_from_storage(user) - - to_chat(user, "You fasten [I] to the top of the rod with the cable.") - - qdel(I) - qdel(src) - - user.put_in_hands(P) - else - return ..() - - -/obj/item/throwing_star - name = "throwing star" - desc = "An ancient weapon still used to this day due to it's ease of lodging itself into victim's body parts" - icon_state = "throwingstar" - item_state = "eshield0" - lefthand_file = 'icons/mob/inhands/equipment/shields_lefthand.dmi' - righthand_file = 'icons/mob/inhands/equipment/shields_righthand.dmi' - force = 2 - throwforce = 20 //This is never used on mobs since this has a 100% embed chance. - throw_speed = 4 - embedded_pain_multiplier = 4 - w_class = WEIGHT_CLASS_SMALL - embed_chance = 100 - embedded_fall_chance = 0 //Hahaha! - sharpness = IS_SHARP - materials = list(MAT_METAL=500, MAT_GLASS=500) - resistance_flags = FIRE_PROOF - - -/obj/item/switchblade - name = "switchblade" - icon_state = "switchblade" - lefthand_file = 'icons/mob/inhands/weapons/swords_lefthand.dmi' - righthand_file = 'icons/mob/inhands/weapons/swords_righthand.dmi' - desc = "A sharp, concealable, spring-loaded knife." - flags_1 = CONDUCT_1 - force = 3 - w_class = WEIGHT_CLASS_SMALL - throwforce = 5 - throw_speed = 3 - throw_range = 6 - materials = list(MAT_METAL=12000) - origin_tech = "engineering=3;combat=2" - hitsound = 'sound/weapons/genhit.ogg' - attack_verb = list("stubbed", "poked") - resistance_flags = FIRE_PROOF - var/extended = 0 - -/obj/item/switchblade/attack_self(mob/user) - extended = !extended - playsound(src.loc, 'sound/weapons/batonextend.ogg', 50, 1) - if(extended) - force = 20 - w_class = WEIGHT_CLASS_NORMAL - throwforce = 23 - icon_state = "switchblade_ext" - attack_verb = list("slashed", "stabbed", "sliced", "torn", "ripped", "diced", "cut") - hitsound = 'sound/weapons/bladeslice.ogg' - sharpness = IS_SHARP - else - force = 3 - w_class = WEIGHT_CLASS_SMALL - throwforce = 5 - icon_state = "switchblade" - attack_verb = list("stubbed", "poked") - hitsound = 'sound/weapons/genhit.ogg' - sharpness = IS_BLUNT - -/obj/item/switchblade/suicide_act(mob/user) - user.visible_message("[user] is slitting [user.p_their()] own throat with [src]! It looks like [user.p_theyre()] trying to commit suicide!") - return (BRUTELOSS) - -/obj/item/phone - name = "red phone" - desc = "Should anything ever go wrong..." - icon = 'icons/obj/items_and_weapons.dmi' - icon_state = "red_phone" - force = 3 - throwforce = 2 - throw_speed = 3 - throw_range = 4 - w_class = WEIGHT_CLASS_SMALL - attack_verb = list("called", "rang") - hitsound = 'sound/weapons/ring.ogg' - -/obj/item/phone/suicide_act(mob/user) - if(locate(/obj/structure/chair/stool) in user.loc) - user.visible_message("[user] begins to tie a noose with [src]'s cord! It looks like [user.p_theyre()] trying to commit suicide!") - else - user.visible_message("[user] is strangling [user.p_them()]self with [src]'s cord! It looks like [user.p_theyre()] trying to commit suicide!") - return(OXYLOSS) - -/obj/item/cane - name = "cane" - desc = "A cane used by a true gentleman. Or a clown." - icon = 'icons/obj/items_and_weapons.dmi' - icon_state = "cane" - item_state = "stick" - lefthand_file = 'icons/mob/inhands/weapons/melee_lefthand.dmi' - righthand_file = 'icons/mob/inhands/weapons/melee_righthand.dmi' - force = 5 - throwforce = 5 - w_class = WEIGHT_CLASS_SMALL - materials = list(MAT_METAL=50) - attack_verb = list("bludgeoned", "whacked", "disciplined", "thrashed") - -/obj/item/staff - name = "wizard staff" - desc = "Apparently a staff used by the wizard." - icon = 'icons/obj/wizard.dmi' - icon_state = "staff" - lefthand_file = 'icons/mob/inhands/weapons/staves_lefthand.dmi' - righthand_file = 'icons/mob/inhands/weapons/staves_righthand.dmi' - force = 3 - throwforce = 5 - throw_speed = 2 - throw_range = 5 - w_class = WEIGHT_CLASS_SMALL - armour_penetration = 100 - attack_verb = list("bludgeoned", "whacked", "disciplined") - resistance_flags = FLAMMABLE - -/obj/item/staff/broom - name = "broom" - desc = "Used for sweeping, and flying into the night while cackling. Black cat not included." - icon = 'icons/obj/wizard.dmi' - icon_state = "broom" - resistance_flags = FLAMMABLE - -/obj/item/staff/stick - name = "stick" - desc = "A great tool to drag someone else's drinks across the bar." - icon = 'icons/obj/items_and_weapons.dmi' - icon_state = "stick" - item_state = "stick" - lefthand_file = 'icons/mob/inhands/weapons/melee_lefthand.dmi' - righthand_file = 'icons/mob/inhands/weapons/melee_righthand.dmi' - force = 3 - throwforce = 5 - throw_speed = 2 - throw_range = 5 - w_class = WEIGHT_CLASS_SMALL - -/obj/item/ectoplasm - name = "ectoplasm" - desc = "spooky" - gender = PLURAL - icon = 'icons/obj/wizard.dmi' - icon_state = "ectoplasm" - -/obj/item/ectoplasm/suicide_act(mob/user) - user.visible_message("[user] is inhaling [src]! It looks like [user.p_theyre()] trying to visit the astral plane.") - return (OXYLOSS) - -/obj/item/mounted_chainsaw - name = "mounted chainsaw" - desc = "A chainsaw that has replaced your arm." - icon_state = "chainsaw_on" - item_state = "mounted_chainsaw" - lefthand_file = 'icons/mob/inhands/weapons/chainsaw_lefthand.dmi' - righthand_file = 'icons/mob/inhands/weapons/chainsaw_righthand.dmi' - flags_1 = NODROP_1 | ABSTRACT_1 | DROPDEL_1 - w_class = WEIGHT_CLASS_HUGE - force = 21 - throwforce = 0 - throw_range = 0 - throw_speed = 0 - sharpness = IS_SHARP - attack_verb = list("sawed", "torn", "cut", "chopped", "diced") - hitsound = 'sound/weapons/chainsawhit.ogg' - -/obj/item/mounted_chainsaw/Destroy() - var/obj/item/bodypart/part - new /obj/item/twohanded/required/chainsaw(get_turf(src)) - if(iscarbon(loc)) - var/mob/living/carbon/holder = loc - var/index = holder.get_held_index_of_item(src) - if(index) - part = holder.hand_bodyparts[index] - . = ..() - if(part) - part.drop_limb() - -/obj/item/statuebust - name = "bust" - desc = "A priceless ancient marble bust, the kind that belongs in a museum." //or you can hit people with it - icon = 'icons/obj/statue.dmi' - icon_state = "bust" - force = 15 - throwforce = 10 - throw_speed = 5 - throw_range = 2 - attack_verb = list("busted") - -/obj/item/tailclub - name = "tail club" - desc = "For the beating to death of lizards with their own tails." - icon_state = "tailclub" - force = 14 - throwforce = 1 // why are you throwing a club do you even weapon - throw_speed = 1 - throw_range = 1 - attack_verb = list("clubbed", "bludgeoned") - -/obj/item/melee/chainofcommand/tailwhip - name = "liz o' nine tails" - desc = "A whip fashioned from the severed tails of lizards." - icon_state = "tailwhip" - origin_tech = "engineering=3;combat=3;biotech=3" - needs_permit = 0 - -/obj/item/melee/chainofcommand/tailwhip/kitty - name = "cat o' nine tails" - desc = "A whip fashioned from the severed tails of cats." - icon_state = "catwhip" - -/obj/item/melee/skateboard - name = "skateboard" - desc = "A skateboard. It can be placed on its wheels and ridden, or used as a strong weapon." - icon_state = "skateboard" - item_state = "skateboard" - force = 12 - throwforce = 4 - w_class = WEIGHT_CLASS_HUGE - attack_verb = list("smacked", "whacked", "slammed", "smashed") - -/obj/item/melee/skateboard/attack_self(mob/user) - new /obj/vehicle/scooter/skateboard(get_turf(user)) - qdel(src) - -/obj/item/melee/baseball_bat - name = "baseball bat" - desc = "There ain't a skull in the league that can withstand a swatter." - icon = 'icons/obj/items_and_weapons.dmi' - icon_state = "baseball_bat" - item_state = "baseball_bat" - lefthand_file = 'icons/mob/inhands/weapons/melee_lefthand.dmi' - righthand_file = 'icons/mob/inhands/weapons/melee_righthand.dmi' - force = 10 - throwforce = 12 - attack_verb = list("beat", "smacked") - w_class = WEIGHT_CLASS_HUGE - var/homerun_ready = 0 - var/homerun_able = 0 - -/obj/item/melee/baseball_bat/homerun - name = "home run bat" - desc = "This thing looks dangerous... Dangerously good at baseball, that is." - homerun_able = 1 - -/obj/item/melee/baseball_bat/attack_self(mob/user) - if(!homerun_able) - ..() - return - if(homerun_ready) - to_chat(user, "You're already ready to do a home run!") - ..() - return - to_chat(user, "You begin gathering strength...") - playsound(get_turf(src), 'sound/magic/lightning_chargeup.ogg', 65, 1) - if(do_after(user, 90, target = src)) - to_chat(user, "You gather power! Time for a home run!") - homerun_ready = 1 - ..() - -/obj/item/melee/baseball_bat/attack(mob/living/target, mob/living/user) - . = ..() - var/atom/throw_target = get_edge_target_turf(target, user.dir) - if(homerun_ready) - user.visible_message("It's a home run!") - target.throw_at(throw_target, rand(8,10), 14, user) - target.ex_act(EXPLODE_HEAVY) - playsound(get_turf(src), 'sound/weapons/homerun.ogg', 100, 1) - homerun_ready = 0 - return - else if(!target.anchored) - target.throw_at(throw_target, rand(1,2), 7, user) - -/obj/item/melee/baseball_bat/ablative - name = "metal baseball bat" - desc = "This bat is made of highly reflective, highly armored material." - icon_state = "baseball_bat_metal" - item_state = "baseball_bat_metal" - force = 12 - throwforce = 15 - -/obj/item/melee/baseball_bat/ablative/IsReflect()//some day this will reflect thrown items instead of lasers - var/picksound = rand(1,2) - var/turf = get_turf(src) - if(picksound == 1) - playsound(turf, 'sound/weapons/effects/batreflect1.ogg', 50, 1) - if(picksound == 2) - playsound(turf, 'sound/weapons/effects/batreflect2.ogg', 50, 1) - return 1 - -/obj/item/melee/flyswatter - name = "flyswatter" - desc = "Useful for killing insects of all sizes." - icon = 'icons/obj/items_and_weapons.dmi' - icon_state = "flyswatter" - item_state = "flyswatter" - lefthand_file = 'icons/mob/inhands/weapons/melee_lefthand.dmi' - righthand_file = 'icons/mob/inhands/weapons/melee_righthand.dmi' - force = 1 - throwforce = 1 - attack_verb = list("swatted", "smacked") - hitsound = 'sound/effects/snap.ogg' - w_class = WEIGHT_CLASS_SMALL - //Things in this list will be instantly splatted. Flyman weakness is handled in the flyman species weakness proc. - var/list/strong_against - -/obj/item/melee/flyswatter/Initialize() - . = ..() - strong_against = typecacheof(list( - /mob/living/simple_animal/hostile/poison/bees/, - /mob/living/simple_animal/butterfly, - /mob/living/simple_animal/cockroach, - /obj/item/queen_bee - )) - - -/obj/item/melee/flyswatter/afterattack(atom/target, mob/user, proximity_flag) - if(proximity_flag) - if(is_type_in_typecache(target, strong_against)) - new /obj/effect/decal/cleanable/deadcockroach(get_turf(target)) - to_chat(user, "You easily splat the [target].") - if(istype(target, /mob/living/)) - var/mob/living/bug = target - bug.death(1) - else - qdel(target) - -/obj/item/circlegame - name = "circled hand" - desc = "If somebody looks at this while it's below your waist, you get to bop them." - icon_state = "madeyoulook" - force = 0 - throwforce = 0 - flags_1 = DROPDEL_1 | ABSTRACT_1 - attack_verb = list("bopped") - -/obj/item/proc/can_trigger_gun(mob/living/user) - if(!user.can_use_guns(src)) - return FALSE playsound(loc, 'sound/effects/adminhelp.ogg', 15) //keep it at 15% volume so people don't jump out of their skin too much /obj/item/sord From 9e0cb0fa7c6a9a484f6a2eb82292bcbfc3eb5c61 Mon Sep 17 00:00:00 2001 From: LetterJay Date: Mon, 11 Sep 2017 13:53:18 -0500 Subject: [PATCH 44/74] Update datumvars.dm --- code/datums/datumvars.dm | 2282 +++++++++++++++++++------------------- 1 file changed, 1138 insertions(+), 1144 deletions(-) diff --git a/code/datums/datumvars.dm b/code/datums/datumvars.dm index cb9be25f05..6df724c737 100644 --- a/code/datums/datumvars.dm +++ b/code/datums/datumvars.dm @@ -1,492 +1,490 @@ -/datum - var/var_edited = FALSE //Warrenty void if seal is broken - var/fingerprintslast = null - -/datum/proc/can_vv_get(var_name) - return TRUE - -/datum/proc/vv_edit_var(var_name, var_value) //called whenever a var is edited - switch(var_name) - if ("vars") - return FALSE - if ("var_edited") - return FALSE - var_edited = TRUE - vars[var_name] = var_value - -/datum/proc/vv_get_var(var_name) - switch(var_name) - if ("vars") - return debug_variable(var_name, list(), 0, src) - return debug_variable(var_name, vars[var_name], 0, src) - -//please call . = ..() first and append to the result, that way parent items are always at the top and child items are further down +/datum + var/var_edited = FALSE //Warrenty void if seal is broken + var/fingerprintslast = null + +/datum/proc/can_vv_get(var_name) + return TRUE + +/datum/proc/vv_edit_var(var_name, var_value) //called whenever a var is edited + switch(var_name) + if ("vars") + return FALSE + if ("var_edited") + return FALSE + var_edited = TRUE + vars[var_name] = var_value + +/datum/proc/vv_get_var(var_name) + switch(var_name) + if ("vars") + return debug_variable(var_name, list(), 0, src) + return debug_variable(var_name, vars[var_name], 0, src) + +//please call . = ..() first and append to the result, that way parent items are always at the top and child items are further down //add separaters by doing . += "---" -<<<<<<< HEAD -/datum/proc/vv_get_dropdown() - . = list() - . += "---" - .["Call Proc"] = "?_src_=vars;proc_call=\ref[src]" - .["Mark Object"] = "?_src_=vars;mark_object=\ref[src]" - .["Delete"] = "?_src_=vars;delete=\ref[src]" - - -/datum/proc/on_reagent_change() - return - - -/client/proc/debug_variables(datum/D in world) - set category = "Debug" - set name = "View Variables" - //set src in world - var/static/cookieoffset = rand(1, 9999) //to force cookies to reset after the round. - - if(!usr.client || !usr.client.holder) - to_chat(usr, "You need to be an administrator to access this.") - return - - if(!D) - return - - var/islist = islist(D) - if (!islist && !istype(D)) - return - - var/title = "" - var/refid = "\ref[D]" - var/icon/sprite - var/hash - - var/type = /list - if (!islist) - type = D.type - - - +/datum/proc/vv_get_dropdown() + . = list() + . += "---" + .["Call Proc"] = "?_src_=vars;proc_call=\ref[src]" + .["Mark Object"] = "?_src_=vars;mark_object=\ref[src]" + .["Delete"] = "?_src_=vars;delete=\ref[src]" + + +/datum/proc/on_reagent_change() + return + + +/client/proc/debug_variables(datum/D in world) + set category = "Debug" + set name = "View Variables" + //set src in world + var/static/cookieoffset = rand(1, 9999) //to force cookies to reset after the round. + + if(!usr.client || !usr.client.holder) + to_chat(usr, "You need to be an administrator to access this.") + return + + if(!D) + return + + var/islist = islist(D) + if (!islist && !istype(D)) + return + + var/title = "" + var/refid = "\ref[D]" + var/icon/sprite + var/hash + + var/type = /list + if (!islist) + type = D.type + + + if(istype(D, /atom)) - var/atom/AT = D - if(AT.icon && AT.icon_state) - sprite = new /icon(AT.icon, AT.icon_state) - hash = md5(AT.icon) - hash = md5(hash + AT.icon_state) - usr << browse_rsc(sprite, "vv[hash].png") - - title = "[D] (\ref[D]) = [type]" - - var/sprite_text - if(sprite) - sprite_text = "" - var/list/atomsnowflake = list() - + var/atom/AT = D + if(AT.icon && AT.icon_state) + sprite = new /icon(AT.icon, AT.icon_state) + hash = md5(AT.icon) + hash = md5(hash + AT.icon_state) + usr << browse_rsc(sprite, "vv[hash].png") + + title = "[D] (\ref[D]) = [type]" + + var/sprite_text + if(sprite) + sprite_text = "" + var/list/atomsnowflake = list() + if(istype(D, /atom)) - var/atom/A = D - if(isliving(A)) - atomsnowflake += "[D]" - if(A.dir) - atomsnowflake += "
    << [dir2text(A.dir)] >>" - var/mob/living/M = A - atomsnowflake += {" -
    [M.ckey ? M.ckey : "No ckey"] / [M.real_name ? M.real_name : "No real name"] -
    - BRUTE:[M.getBruteLoss()] - FIRE:[M.getFireLoss()] - TOXIN:[M.getToxLoss()] - OXY:[M.getOxyLoss()] - CLONE:[M.getCloneLoss()] - BRAIN:[M.getBrainLoss()] - STAMINA:[M.getStaminaLoss()] - - "} - else - atomsnowflake += "[D]" - if(A.dir) - atomsnowflake += "
    << [dir2text(A.dir)] >>" - else - atomsnowflake += "[D]" - - var/formatted_type = "[type]" - if(length(formatted_type) > 25) - var/middle_point = length(formatted_type) / 2 - var/splitpoint = findtext(formatted_type,"/",middle_point) - if(splitpoint) - formatted_type = "[copytext(formatted_type,1,splitpoint)]
    [copytext(formatted_type,splitpoint)]" - else - formatted_type = "Type too long" //No suitable splitpoint (/) found. - - var/marked - if(holder.marked_datum && holder.marked_datum == D) - marked = "
    Marked Object" - var/varedited_line = "" - if(!islist && D.var_edited) - varedited_line = "
    Var Edited" - - var/list/dropdownoptions = list() - if (islist) - dropdownoptions = list( - "---", - "Add Item" = "?_src_=vars;listadd=[refid]", - "Remove Nulls" = "?_src_=vars;listnulls=[refid]", - "Remove Dupes" = "?_src_=vars;listdupes=[refid]", - "Set len" = "?_src_=vars;listlen=[refid]", - "Shuffle" = "?_src_=vars;listshuffle=[refid]" - ) - else - dropdownoptions = D.vv_get_dropdown() - var/list/dropdownoptions_html = list() - - for (var/name in dropdownoptions) - var/link = dropdownoptions[name] - if (link) - dropdownoptions_html += "" - else - dropdownoptions_html += "" - - var/list/names = list() - if (!islist) - for (var/V in D.vars) - names += V - sleep(1)//For some reason, without this sleep, VVing will cause client to disconnect on certain objects. - - var/list/variable_html = list() - if (islist) - var/list/L = D - for (var/i in 1 to L.len) - var/key = L[i] - var/value - if (IS_NORMAL_LIST(L) && !isnum(key)) - value = L[key] - variable_html += debug_variable(i, value, 0, D) - else - - names = sortList(names) - for (var/V in names) - if(D.can_vv_get(V)) - variable_html += D.vv_get_var(V) - - var/html = {" - - - [title] - - - - -
    - - - - - -
    - - - - -
    - [sprite_text] -
    - [atomsnowflake.Join()] -
    -
    -
    - [formatted_type] - [marked] - [varedited_line] -
    -
    -
    - Refresh -
    - -
    -
    -
    -
    -
    - - E - Edit, tries to determine the variable type by itself.
    - C - Change, asks you for the var type first.
    - M - Mass modify: changes this variable for all objects of this type.
    -
    -
    - - - - - -
    -
    - Search: -
    -
    - -
    -
    -
      - [variable_html.Join()] -
    - - - -"} - - usr << browse(html, "window=variables[refid];size=475x650") - - -#define VV_HTML_ENCODE(thing) ( sanitize ? html_encode(thing) : thing ) -/proc/debug_variable(name, value, level, datum/DA = null, sanitize = TRUE) - var/header - if(DA) - if (islist(DA)) - var/index = name - if (value) - name = DA[name] //name is really the index until this line - else - value = DA[name] - header = "
  • (E) (C) (-) " - else - header = "
  • (E) (C) (M) " - else - header = "
  • " - - var/item - if (isnull(value)) - item = "[VV_HTML_ENCODE(name)] = null" - - else if (istext(value)) - item = "[VV_HTML_ENCODE(name)] = \"[VV_HTML_ENCODE(value)]\"" - - else if (isicon(value)) - #ifdef VARSICON - var/icon/I = new/icon(value) - var/rnd = rand(1,10000) - var/rname = "tmp\ref[I][rnd].png" - usr << browse_rsc(I, rname) - item = "[VV_HTML_ENCODE(name)] = ([value]) " - #else - item = "[VV_HTML_ENCODE(name)] = /icon ([value])" - #endif - -/* else if (istype(value, /image)) - #ifdef VARSICON - var/rnd = rand(1, 10000) - var/image/I = value - - src << browse_rsc(I.icon, "tmp\ref[value][rnd].png") - html += "[name] = " - #else - html += "[name] = /image ([value])" - #endif -*/ - else if (isfile(value)) - item = "[VV_HTML_ENCODE(name)] = '[value]'" - - //else if (istype(value, /client)) - // var/client/C = value - // item = "[VV_HTML_ENCODE(name)] \ref[value] = [C] [C.type]" - - else if (istype(value, /datum)) - var/datum/D = value - if ("[D]" != "[D.type]") //if the thing as a name var, lets use it. - item = "[VV_HTML_ENCODE(name)] \ref[value] = [D] [D.type]" - else - item = "[VV_HTML_ENCODE(name)] \ref[value] = [D.type]" - - else if (islist(value)) - var/list/L = value - var/list/items = list() - - if (L.len > 0 && !(name == "underlays" || name == "overlays" || L.len > (IS_NORMAL_LIST(L) ? 50 : 150))) - for (var/i in 1 to L.len) - var/key = L[i] - var/val - if (IS_NORMAL_LIST(L) && !isnum(key)) - val = L[key] - if (!val) - val = key - key = i - - items += debug_variable(key, val, level + 1, sanitize = sanitize) - - item = "[VV_HTML_ENCODE(name)] = /list ([L.len])
      [items.Join()]
    " - else - item = "[VV_HTML_ENCODE(name)] = /list ([L.len])" - - else - item = "[VV_HTML_ENCODE(name)] = [VV_HTML_ENCODE(value)]" - - return "[header][item]
  • " - -#undef VV_HTML_ENCODE - -/client/proc/view_var_Topic(href, href_list, hsrc) - if( (usr.client != src) || !src.holder ) - return - if(href_list["Vars"]) - debug_variables(locate(href_list["Vars"])) - - else if(href_list["datumrefresh"]) - var/datum/DAT = locate(href_list["datumrefresh"]) - if(!DAT) //can't be an istype() because /client etc aren't datums - return - src.debug_variables(DAT) - - else if(href_list["mob_player_panel"]) - if(!check_rights(0)) - return - -======= + var/atom/A = D + if(isliving(A)) + atomsnowflake += "[D]" + if(A.dir) + atomsnowflake += "
    << [dir2text(A.dir)] >>" + var/mob/living/M = A + atomsnowflake += {" +
    [M.ckey ? M.ckey : "No ckey"] / [M.real_name ? M.real_name : "No real name"] +
    + BRUTE:[M.getBruteLoss()] + FIRE:[M.getFireLoss()] + TOXIN:[M.getToxLoss()] + OXY:[M.getOxyLoss()] + CLONE:[M.getCloneLoss()] + BRAIN:[M.getBrainLoss()] + STAMINA:[M.getStaminaLoss()] + + "} + else + atomsnowflake += "[D]" + if(A.dir) + atomsnowflake += "
    << [dir2text(A.dir)] >>" + else + atomsnowflake += "[D]" + + var/formatted_type = "[type]" + if(length(formatted_type) > 25) + var/middle_point = length(formatted_type) / 2 + var/splitpoint = findtext(formatted_type,"/",middle_point) + if(splitpoint) + formatted_type = "[copytext(formatted_type,1,splitpoint)]
    [copytext(formatted_type,splitpoint)]" + else + formatted_type = "Type too long" //No suitable splitpoint (/) found. + + var/marked + if(holder.marked_datum && holder.marked_datum == D) + marked = "
    Marked Object" + var/varedited_line = "" + if(!islist && D.var_edited) + varedited_line = "
    Var Edited" + + var/list/dropdownoptions = list() + if (islist) + dropdownoptions = list( + "---", + "Add Item" = "?_src_=vars;listadd=[refid]", + "Remove Nulls" = "?_src_=vars;listnulls=[refid]", + "Remove Dupes" = "?_src_=vars;listdupes=[refid]", + "Set len" = "?_src_=vars;listlen=[refid]", + "Shuffle" = "?_src_=vars;listshuffle=[refid]" + ) + else + dropdownoptions = D.vv_get_dropdown() + var/list/dropdownoptions_html = list() + + for (var/name in dropdownoptions) + var/link = dropdownoptions[name] + if (link) + dropdownoptions_html += "" + else + dropdownoptions_html += "" + + var/list/names = list() + if (!islist) + for (var/V in D.vars) + names += V + sleep(1)//For some reason, without this sleep, VVing will cause client to disconnect on certain objects. + + var/list/variable_html = list() + if (islist) + var/list/L = D + for (var/i in 1 to L.len) + var/key = L[i] + var/value + if (IS_NORMAL_LIST(L) && !isnum(key)) + value = L[key] + variable_html += debug_variable(i, value, 0, D) + else + + names = sortList(names) + for (var/V in names) + if(D.can_vv_get(V)) + variable_html += D.vv_get_var(V) + + var/html = {" + + + [title] + + + + +
    + + + + + +
    + + + + +
    + [sprite_text] +
    + [atomsnowflake.Join()] +
    +
    +
    + [formatted_type] + [marked] + [varedited_line] +
    +
    +
    + Refresh +
    + +
    +
    +
    +
    +
    + + E - Edit, tries to determine the variable type by itself.
    + C - Change, asks you for the var type first.
    + M - Mass modify: changes this variable for all objects of this type.
    +
    +
    + + + + + +
    +
    + Search: +
    +
    + +
    +
    +
      + [variable_html.Join()] +
    + + + +"} + + usr << browse(html, "window=variables[refid];size=475x650") + + +#define VV_HTML_ENCODE(thing) ( sanitize ? html_encode(thing) : thing ) +/proc/debug_variable(name, value, level, datum/DA = null, sanitize = TRUE) + var/header + if(DA) + if (islist(DA)) + var/index = name + if (value) + name = DA[name] //name is really the index until this line + else + value = DA[name] + header = "
  • (E) (C) (-) " + else + header = "
  • (E) (C) (M) " + else + header = "
  • " + + var/item + if (isnull(value)) + item = "[VV_HTML_ENCODE(name)] = null" + + else if (istext(value)) + item = "[VV_HTML_ENCODE(name)] = \"[VV_HTML_ENCODE(value)]\"" + + else if (isicon(value)) + #ifdef VARSICON + var/icon/I = new/icon(value) + var/rnd = rand(1,10000) + var/rname = "tmp\ref[I][rnd].png" + usr << browse_rsc(I, rname) + item = "[VV_HTML_ENCODE(name)] = ([value]) " + #else + item = "[VV_HTML_ENCODE(name)] = /icon ([value])" + #endif + +/* else if (istype(value, /image)) + #ifdef VARSICON + var/rnd = rand(1, 10000) + var/image/I = value + + src << browse_rsc(I.icon, "tmp\ref[value][rnd].png") + html += "[name] = " + #else + html += "[name] = /image ([value])" + #endif +*/ + else if (isfile(value)) + item = "[VV_HTML_ENCODE(name)] = '[value]'" + + //else if (istype(value, /client)) + // var/client/C = value + // item = "[VV_HTML_ENCODE(name)] \ref[value] = [C] [C.type]" + + else if (istype(value, /datum)) + var/datum/D = value + if ("[D]" != "[D.type]") //if the thing as a name var, lets use it. + item = "[VV_HTML_ENCODE(name)] \ref[value] = [D] [D.type]" + else + item = "[VV_HTML_ENCODE(name)] \ref[value] = [D.type]" + + else if (islist(value)) + var/list/L = value + var/list/items = list() + + if (L.len > 0 && !(name == "underlays" || name == "overlays" || L.len > (IS_NORMAL_LIST(L) ? 50 : 150))) + for (var/i in 1 to L.len) + var/key = L[i] + var/val + if (IS_NORMAL_LIST(L) && !isnum(key)) + val = L[key] + if (!val) + val = key + key = i + + items += debug_variable(key, val, level + 1, sanitize = sanitize) + + item = "[VV_HTML_ENCODE(name)] = /list ([L.len])
      [items.Join()]
    " + else + item = "[VV_HTML_ENCODE(name)] = /list ([L.len])" + + else + item = "[VV_HTML_ENCODE(name)] = [VV_HTML_ENCODE(value)]" + + return "[header][item]
  • " + +#undef VV_HTML_ENCODE + +/client/proc/view_var_Topic(href, href_list, hsrc) + if( (usr.client != src) || !src.holder ) + return + if(href_list["Vars"]) + debug_variables(locate(href_list["Vars"])) + + else if(href_list["datumrefresh"]) + var/datum/DAT = locate(href_list["datumrefresh"]) + if(!DAT) //can't be an istype() because /client etc aren't datums + return + src.debug_variables(DAT) + + else if(href_list["mob_player_panel"]) + if(!check_rights(0)) + return + /datum/proc/vv_get_dropdown() . = list() . += "---" @@ -951,81 +949,78 @@ if(!check_rights(0)) return ->>>>>>> 6656ce6... Gives admins the ability to show a read only vv window to a player (#30463) var/mob/M = locate(href_list["mob_player_panel"]) in GLOB.mob_list - if(!istype(M)) - to_chat(usr, "This can only be used on instances of type /mob") - return - - src.holder.show_player_panel(M) - href_list["datumrefresh"] = href_list["mob_player_panel"] - - else if(href_list["godmode"]) - if(!check_rights(R_ADMIN)) - return - + if(!istype(M)) + to_chat(usr, "This can only be used on instances of type /mob") + return + + src.holder.show_player_panel(M) + href_list["datumrefresh"] = href_list["mob_player_panel"] + + else if(href_list["godmode"]) + if(!check_rights(R_ADMIN)) + return + var/mob/M = locate(href_list["godmode"]) in GLOB.mob_list - if(!istype(M)) - to_chat(usr, "This can only be used on instances of type /mob") - return - - src.cmd_admin_godmode(M) - href_list["datumrefresh"] = href_list["godmode"] - - else if(href_list["mark_object"]) - if(!check_rights(0)) - return - - var/datum/D = locate(href_list["mark_object"]) - if(!istype(D)) - to_chat(usr, "This can only be done to instances of type /datum") - return - - src.holder.marked_datum = D - href_list["datumrefresh"] = href_list["mark_object"] - - else if(href_list["proc_call"]) - if(!check_rights(0)) - return - - var/T = locate(href_list["proc_call"]) - - if(T) - callproc_datum(T) - - else if(href_list["delete"]) - if(!check_rights(R_DEBUG, 0)) - return - - var/datum/D = locate(href_list["delete"]) - if(!D) - to_chat(usr, "Unable to locate item!") - admin_delete(D) - href_list["datumrefresh"] = href_list["delete"] - - else if(href_list["regenerateicons"]) - if(!check_rights(0)) - return - + if(!istype(M)) + to_chat(usr, "This can only be used on instances of type /mob") + return + + src.cmd_admin_godmode(M) + href_list["datumrefresh"] = href_list["godmode"] + + else if(href_list["mark_object"]) + if(!check_rights(0)) + return + + var/datum/D = locate(href_list["mark_object"]) + if(!istype(D)) + to_chat(usr, "This can only be done to instances of type /datum") + return + + src.holder.marked_datum = D + href_list["datumrefresh"] = href_list["mark_object"] + + else if(href_list["proc_call"]) + if(!check_rights(0)) + return + + var/T = locate(href_list["proc_call"]) + + if(T) + callproc_datum(T) + + else if(href_list["delete"]) + if(!check_rights(R_DEBUG, 0)) + return + + var/datum/D = locate(href_list["delete"]) + if(!D) + to_chat(usr, "Unable to locate item!") + admin_delete(D) + href_list["datumrefresh"] = href_list["delete"] + + else if(href_list["regenerateicons"]) + if(!check_rights(0)) + return + var/mob/M = locate(href_list["regenerateicons"]) in GLOB.mob_list -<<<<<<< HEAD - if(!ismob(M)) - to_chat(usr, "This can only be done to instances of type /mob") - return - M.regenerate_icons() - -//Needs +VAREDIT past this point - - else if(check_rights(R_VAREDIT)) - - - //~CARN: for renaming mobs (updates their name, real_name, mind.name, their ID/PDA and datacore records). - - if(href_list["rename"]) - if(!check_rights(0)) - return - -======= + if(!ismob(M)) + to_chat(usr, "This can only be done to instances of type /mob") + return + M.regenerate_icons() + +//Needs +VAREDIT past this point + + else if(check_rights(R_VAREDIT)) + + + //~CARN: for renaming mobs (updates their name, real_name, mind.name, their ID/PDA and datacore records). + + if(href_list["rename"]) + if(!check_rights(0)) + return + if(!ismob(M)) to_chat(usr, "This can only be done to instances of type /mob") return @@ -1062,379 +1057,378 @@ if(!check_rights(0)) return ->>>>>>> 6656ce6... Gives admins the ability to show a read only vv window to a player (#30463) var/mob/M = locate(href_list["rename"]) in GLOB.mob_list - if(!istype(M)) - to_chat(usr, "This can only be used on instances of type /mob") - return - - var/new_name = stripped_input(usr,"What would you like to name this mob?","Input a name",M.real_name,MAX_NAME_LEN) - if( !new_name || !M ) - return - - message_admins("Admin [key_name_admin(usr)] renamed [key_name_admin(M)] to [new_name].") - M.fully_replace_character_name(M.real_name,new_name) - href_list["datumrefresh"] = href_list["rename"] - - else if(href_list["varnameedit"] && href_list["datumedit"]) - if(!check_rights(0)) - return - - var/D = locate(href_list["datumedit"]) + if(!istype(M)) + to_chat(usr, "This can only be used on instances of type /mob") + return + + var/new_name = stripped_input(usr,"What would you like to name this mob?","Input a name",M.real_name,MAX_NAME_LEN) + if( !new_name || !M ) + return + + message_admins("Admin [key_name_admin(usr)] renamed [key_name_admin(M)] to [new_name].") + M.fully_replace_character_name(M.real_name,new_name) + href_list["datumrefresh"] = href_list["rename"] + + else if(href_list["varnameedit"] && href_list["datumedit"]) + if(!check_rights(0)) + return + + var/D = locate(href_list["datumedit"]) if(!istype(D, /datum)) - to_chat(usr, "This can only be used on datums") - return - - modify_variables(D, href_list["varnameedit"], 1) - - else if(href_list["varnamechange"] && href_list["datumchange"]) - if(!check_rights(0)) - return - - var/D = locate(href_list["datumchange"]) + to_chat(usr, "This can only be used on datums") + return + + modify_variables(D, href_list["varnameedit"], 1) + + else if(href_list["varnamechange"] && href_list["datumchange"]) + if(!check_rights(0)) + return + + var/D = locate(href_list["datumchange"]) if(!istype(D, /datum)) - to_chat(usr, "This can only be used on datums") - return - - modify_variables(D, href_list["varnamechange"], 0) - - else if(href_list["varnamemass"] && href_list["datummass"]) - if(!check_rights(0)) - return - - var/datum/D = locate(href_list["datummass"]) - if(!istype(D)) - to_chat(usr, "This can only be used on instances of type /datum") - return - - cmd_mass_modify_object_variables(D, href_list["varnamemass"]) - - else if(href_list["listedit"] && href_list["index"]) - var/index = text2num(href_list["index"]) - if (!index) - return - - var/list/L = locate(href_list["listedit"]) - if (!istype(L)) - to_chat(usr, "This can only be used on instances of type /list") - return - - mod_list(L, null, "list", "contents", index, autodetect_class = TRUE) - - else if(href_list["listchange"] && href_list["index"]) - var/index = text2num(href_list["index"]) - if (!index) - return - - var/list/L = locate(href_list["listchange"]) - if (!istype(L)) - to_chat(usr, "This can only be used on instances of type /list") - return - - mod_list(L, null, "list", "contents", index, autodetect_class = FALSE) - - else if(href_list["listremove"] && href_list["index"]) - var/index = text2num(href_list["index"]) - if (!index) - return - - var/list/L = locate(href_list["listremove"]) - if (!istype(L)) - to_chat(usr, "This can only be used on instances of type /list") - return - - var/variable = L[index] - var/prompt = alert("Do you want to remove item number [index] from list?", "Confirm", "Yes", "No") - if (prompt != "Yes") - return - L.Cut(index, index+1) - log_world("### ListVarEdit by [src]: /list's contents: REMOVED=[html_encode("[variable]")]") - log_admin("[key_name(src)] modified list's contents: REMOVED=[variable]") - message_admins("[key_name_admin(src)] modified list's contents: REMOVED=[variable]") - - else if(href_list["listadd"]) - var/list/L = locate(href_list["listadd"]) - if (!istype(L)) - to_chat(usr, "This can only be used on instances of type /list") - return - - mod_list_add(L, null, "list", "contents") - - else if(href_list["listdupes"]) - var/list/L = locate(href_list["listdupes"]) - if (!istype(L)) - to_chat(usr, "This can only be used on instances of type /list") - return - - uniqueList_inplace(L) - log_world("### ListVarEdit by [src]: /list contents: CLEAR DUPES") - log_admin("[key_name(src)] modified list's contents: CLEAR DUPES") - message_admins("[key_name_admin(src)] modified list's contents: CLEAR DUPES") - - else if(href_list["listnulls"]) - var/list/L = locate(href_list["listnulls"]) - if (!istype(L)) - to_chat(usr, "This can only be used on instances of type /list") - return - - listclearnulls(L) - log_world("### ListVarEdit by [src]: /list contents: CLEAR NULLS") - log_admin("[key_name(src)] modified list's contents: CLEAR NULLS") - message_admins("[key_name_admin(src)] modified list's contents: CLEAR NULLS") - - else if(href_list["listlen"]) - var/list/L = locate(href_list["listlen"]) - if (!istype(L)) - to_chat(usr, "This can only be used on instances of type /list") - return - var/value = vv_get_value(VV_NUM) - if (value["class"] != VV_NUM) - return - - L.len = value["value"] - log_world("### ListVarEdit by [src]: /list len: [L.len]") - log_admin("[key_name(src)] modified list's len: [L.len]") - message_admins("[key_name_admin(src)] modified list's len: [L.len]") - - else if(href_list["listshuffle"]) - var/list/L = locate(href_list["listshuffle"]) - if (!istype(L)) - to_chat(usr, "This can only be used on instances of type /list") - return - - shuffle_inplace(L) - log_world("### ListVarEdit by [src]: /list contents: SHUFFLE") - log_admin("[key_name(src)] modified list's contents: SHUFFLE") - message_admins("[key_name_admin(src)] modified list's contents: SHUFFLE") - - else if(href_list["give_spell"]) - if(!check_rights(0)) - return - + to_chat(usr, "This can only be used on datums") + return + + modify_variables(D, href_list["varnamechange"], 0) + + else if(href_list["varnamemass"] && href_list["datummass"]) + if(!check_rights(0)) + return + + var/datum/D = locate(href_list["datummass"]) + if(!istype(D)) + to_chat(usr, "This can only be used on instances of type /datum") + return + + cmd_mass_modify_object_variables(D, href_list["varnamemass"]) + + else if(href_list["listedit"] && href_list["index"]) + var/index = text2num(href_list["index"]) + if (!index) + return + + var/list/L = locate(href_list["listedit"]) + if (!istype(L)) + to_chat(usr, "This can only be used on instances of type /list") + return + + mod_list(L, null, "list", "contents", index, autodetect_class = TRUE) + + else if(href_list["listchange"] && href_list["index"]) + var/index = text2num(href_list["index"]) + if (!index) + return + + var/list/L = locate(href_list["listchange"]) + if (!istype(L)) + to_chat(usr, "This can only be used on instances of type /list") + return + + mod_list(L, null, "list", "contents", index, autodetect_class = FALSE) + + else if(href_list["listremove"] && href_list["index"]) + var/index = text2num(href_list["index"]) + if (!index) + return + + var/list/L = locate(href_list["listremove"]) + if (!istype(L)) + to_chat(usr, "This can only be used on instances of type /list") + return + + var/variable = L[index] + var/prompt = alert("Do you want to remove item number [index] from list?", "Confirm", "Yes", "No") + if (prompt != "Yes") + return + L.Cut(index, index+1) + log_world("### ListVarEdit by [src]: /list's contents: REMOVED=[html_encode("[variable]")]") + log_admin("[key_name(src)] modified list's contents: REMOVED=[variable]") + message_admins("[key_name_admin(src)] modified list's contents: REMOVED=[variable]") + + else if(href_list["listadd"]) + var/list/L = locate(href_list["listadd"]) + if (!istype(L)) + to_chat(usr, "This can only be used on instances of type /list") + return + + mod_list_add(L, null, "list", "contents") + + else if(href_list["listdupes"]) + var/list/L = locate(href_list["listdupes"]) + if (!istype(L)) + to_chat(usr, "This can only be used on instances of type /list") + return + + uniqueList_inplace(L) + log_world("### ListVarEdit by [src]: /list contents: CLEAR DUPES") + log_admin("[key_name(src)] modified list's contents: CLEAR DUPES") + message_admins("[key_name_admin(src)] modified list's contents: CLEAR DUPES") + + else if(href_list["listnulls"]) + var/list/L = locate(href_list["listnulls"]) + if (!istype(L)) + to_chat(usr, "This can only be used on instances of type /list") + return + + listclearnulls(L) + log_world("### ListVarEdit by [src]: /list contents: CLEAR NULLS") + log_admin("[key_name(src)] modified list's contents: CLEAR NULLS") + message_admins("[key_name_admin(src)] modified list's contents: CLEAR NULLS") + + else if(href_list["listlen"]) + var/list/L = locate(href_list["listlen"]) + if (!istype(L)) + to_chat(usr, "This can only be used on instances of type /list") + return + var/value = vv_get_value(VV_NUM) + if (value["class"] != VV_NUM) + return + + L.len = value["value"] + log_world("### ListVarEdit by [src]: /list len: [L.len]") + log_admin("[key_name(src)] modified list's len: [L.len]") + message_admins("[key_name_admin(src)] modified list's len: [L.len]") + + else if(href_list["listshuffle"]) + var/list/L = locate(href_list["listshuffle"]) + if (!istype(L)) + to_chat(usr, "This can only be used on instances of type /list") + return + + shuffle_inplace(L) + log_world("### ListVarEdit by [src]: /list contents: SHUFFLE") + log_admin("[key_name(src)] modified list's contents: SHUFFLE") + message_admins("[key_name_admin(src)] modified list's contents: SHUFFLE") + + else if(href_list["give_spell"]) + if(!check_rights(0)) + return + var/mob/M = locate(href_list["give_spell"]) in GLOB.mob_list - if(!istype(M)) - to_chat(usr, "This can only be used on instances of type /mob") - return - - src.give_spell(M) - href_list["datumrefresh"] = href_list["give_spell"] - - else if(href_list["remove_spell"]) - if(!check_rights(0)) - return - + if(!istype(M)) + to_chat(usr, "This can only be used on instances of type /mob") + return + + src.give_spell(M) + href_list["datumrefresh"] = href_list["give_spell"] + + else if(href_list["remove_spell"]) + if(!check_rights(0)) + return + var/mob/M = locate(href_list["remove_spell"]) in GLOB.mob_list - if(!istype(M)) - to_chat(usr, "This can only be used on instances of type /mob") - return - - remove_spell(M) - href_list["datumrefresh"] = href_list["remove_spell"] - - else if(href_list["give_disease"]) - if(!check_rights(0)) - return - + if(!istype(M)) + to_chat(usr, "This can only be used on instances of type /mob") + return + + remove_spell(M) + href_list["datumrefresh"] = href_list["remove_spell"] + + else if(href_list["give_disease"]) + if(!check_rights(0)) + return + var/mob/M = locate(href_list["give_disease"]) in GLOB.mob_list - if(!istype(M)) - to_chat(usr, "This can only be used on instances of type /mob") - return - - src.give_disease(M) - href_list["datumrefresh"] = href_list["give_spell"] - - else if(href_list["gib"]) - if(!check_rights(R_FUN)) - return - + if(!istype(M)) + to_chat(usr, "This can only be used on instances of type /mob") + return + + src.give_disease(M) + href_list["datumrefresh"] = href_list["give_spell"] + + else if(href_list["gib"]) + if(!check_rights(R_FUN)) + return + var/mob/M = locate(href_list["gib"]) in GLOB.mob_list - if(!istype(M)) - to_chat(usr, "This can only be used on instances of type /mob") - return - - src.cmd_admin_gib(M) - - else if(href_list["build_mode"]) - if(!check_rights(R_BUILDMODE)) - return - + if(!istype(M)) + to_chat(usr, "This can only be used on instances of type /mob") + return + + src.cmd_admin_gib(M) + + else if(href_list["build_mode"]) + if(!check_rights(R_BUILDMODE)) + return + var/mob/M = locate(href_list["build_mode"]) in GLOB.mob_list - if(!istype(M)) - to_chat(usr, "This can only be used on instances of type /mob") - return - - togglebuildmode(M) - href_list["datumrefresh"] = href_list["build_mode"] - - else if(href_list["drop_everything"]) - if(!check_rights(0)) - return - + if(!istype(M)) + to_chat(usr, "This can only be used on instances of type /mob") + return + + togglebuildmode(M) + href_list["datumrefresh"] = href_list["build_mode"] + + else if(href_list["drop_everything"]) + if(!check_rights(0)) + return + var/mob/M = locate(href_list["drop_everything"]) in GLOB.mob_list - if(!istype(M)) - to_chat(usr, "This can only be used on instances of type /mob") - return - - if(usr.client) - usr.client.cmd_admin_drop_everything(M) - - else if(href_list["direct_control"]) - if(!check_rights(0)) - return - + if(!istype(M)) + to_chat(usr, "This can only be used on instances of type /mob") + return + + if(usr.client) + usr.client.cmd_admin_drop_everything(M) + + else if(href_list["direct_control"]) + if(!check_rights(0)) + return + var/mob/M = locate(href_list["direct_control"]) in GLOB.mob_list - if(!istype(M)) - to_chat(usr, "This can only be used on instances of type /mob") - return - - if(usr.client) - usr.client.cmd_assume_direct_control(M) - - else if(href_list["offer_control"]) - if(!check_rights(0)) - return - + if(!istype(M)) + to_chat(usr, "This can only be used on instances of type /mob") + return + + if(usr.client) + usr.client.cmd_assume_direct_control(M) + + else if(href_list["offer_control"]) + if(!check_rights(0)) + return + var/mob/M = locate(href_list["offer_control"]) in GLOB.mob_list - if(!istype(M)) - to_chat(usr, "This can only be used on instances of type /mob") - return - offer_control(M) - - else if(href_list["delall"]) - if(!check_rights(R_DEBUG|R_SERVER)) - return - - var/obj/O = locate(href_list["delall"]) - if(!isobj(O)) - to_chat(usr, "This can only be used on instances of type /obj") - return - - var/action_type = alert("Strict type ([O.type]) or type and all subtypes?",,"Strict type","Type and subtypes","Cancel") - if(action_type == "Cancel" || !action_type) - return - - if(alert("Are you really sure you want to delete all objects of type [O.type]?",,"Yes","No") != "Yes") - return - - if(alert("Second confirmation required. Delete?",,"Yes","No") != "Yes") - return - - var/O_type = O.type - switch(action_type) - if("Strict type") - var/i = 0 - for(var/obj/Obj in world) - if(Obj.type == O_type) - i++ - qdel(Obj) - CHECK_TICK - if(!i) - to_chat(usr, "No objects of this type exist") - return - log_admin("[key_name(usr)] deleted all objects of type [O_type] ([i] objects deleted) ") - message_admins("[key_name(usr)] deleted all objects of type [O_type] ([i] objects deleted) ") - if("Type and subtypes") - var/i = 0 - for(var/obj/Obj in world) - if(istype(Obj,O_type)) - i++ - qdel(Obj) - CHECK_TICK - if(!i) - to_chat(usr, "No objects of this type exist") - return - log_admin("[key_name(usr)] deleted all objects of type or subtype of [O_type] ([i] objects deleted) ") - message_admins("[key_name(usr)] deleted all objects of type or subtype of [O_type] ([i] objects deleted) ") - - else if(href_list["addreagent"]) - if(!check_rights(0)) - return - - var/atom/A = locate(href_list["addreagent"]) - - if(!A.reagents) - var/amount = input(usr, "Specify the reagent size of [A]", "Set Reagent Size", 50) as num - if(amount) - A.create_reagents(amount) - - if(A.reagents) - var/chosen_id - var/list/reagent_options = sortList(GLOB.chemical_reagents_list) - switch(alert(usr, "Choose a method.", "Add Reagents", "Enter ID", "Choose ID")) - if("Enter ID") - var/valid_id - while(!valid_id) - chosen_id = stripped_input(usr, "Enter the ID of the reagent you want to add.") - if(!chosen_id) //Get me out of here! - break - for(var/ID in reagent_options) - if(ID == chosen_id) - valid_id = 1 - if(!valid_id) - to_chat(usr, "A reagent with that ID doesn't exist!") - if("Choose ID") - chosen_id = input(usr, "Choose a reagent to add.", "Choose a reagent.") as null|anything in reagent_options - if(chosen_id) - var/amount = input(usr, "Choose the amount to add.", "Choose the amount.", A.reagents.maximum_volume) as num - if(amount) - A.reagents.add_reagent(chosen_id, amount) - log_admin("[key_name(usr)] has added [amount] units of [chosen_id] to \the [A]") - message_admins("[key_name(usr)] has added [amount] units of [chosen_id] to \the [A]") - - href_list["datumrefresh"] = href_list["addreagent"] - - else if(href_list["explode"]) - if(!check_rights(R_FUN)) - return - - var/atom/A = locate(href_list["explode"]) - if(!isobj(A) && !ismob(A) && !isturf(A)) - to_chat(usr, "This can only be done to instances of type /obj, /mob and /turf") - return - - src.cmd_admin_explosion(A) - href_list["datumrefresh"] = href_list["explode"] - - else if(href_list["emp"]) - if(!check_rights(R_FUN)) - return - - var/atom/A = locate(href_list["emp"]) - if(!isobj(A) && !ismob(A) && !isturf(A)) - to_chat(usr, "This can only be done to instances of type /obj, /mob and /turf") - return - - src.cmd_admin_emp(A) - href_list["datumrefresh"] = href_list["emp"] - - else if(href_list["rotatedatum"]) - if(!check_rights(0)) - return - - var/atom/A = locate(href_list["rotatedatum"]) - if(!istype(A)) - to_chat(usr, "This can only be done to instances of type /atom") - return - - switch(href_list["rotatedir"]) - if("right") - A.setDir(turn(A.dir, -45)) - if("left") - A.setDir(turn(A.dir, 45)) - href_list["datumrefresh"] = href_list["rotatedatum"] - - else if(href_list["editorgans"]) - if(!check_rights(0)) - return - + if(!istype(M)) + to_chat(usr, "This can only be used on instances of type /mob") + return + offer_control(M) + + else if(href_list["delall"]) + if(!check_rights(R_DEBUG|R_SERVER)) + return + + var/obj/O = locate(href_list["delall"]) + if(!isobj(O)) + to_chat(usr, "This can only be used on instances of type /obj") + return + + var/action_type = alert("Strict type ([O.type]) or type and all subtypes?",,"Strict type","Type and subtypes","Cancel") + if(action_type == "Cancel" || !action_type) + return + + if(alert("Are you really sure you want to delete all objects of type [O.type]?",,"Yes","No") != "Yes") + return + + if(alert("Second confirmation required. Delete?",,"Yes","No") != "Yes") + return + + var/O_type = O.type + switch(action_type) + if("Strict type") + var/i = 0 + for(var/obj/Obj in world) + if(Obj.type == O_type) + i++ + qdel(Obj) + CHECK_TICK + if(!i) + to_chat(usr, "No objects of this type exist") + return + log_admin("[key_name(usr)] deleted all objects of type [O_type] ([i] objects deleted) ") + message_admins("[key_name(usr)] deleted all objects of type [O_type] ([i] objects deleted) ") + if("Type and subtypes") + var/i = 0 + for(var/obj/Obj in world) + if(istype(Obj,O_type)) + i++ + qdel(Obj) + CHECK_TICK + if(!i) + to_chat(usr, "No objects of this type exist") + return + log_admin("[key_name(usr)] deleted all objects of type or subtype of [O_type] ([i] objects deleted) ") + message_admins("[key_name(usr)] deleted all objects of type or subtype of [O_type] ([i] objects deleted) ") + + else if(href_list["addreagent"]) + if(!check_rights(0)) + return + + var/atom/A = locate(href_list["addreagent"]) + + if(!A.reagents) + var/amount = input(usr, "Specify the reagent size of [A]", "Set Reagent Size", 50) as num + if(amount) + A.create_reagents(amount) + + if(A.reagents) + var/chosen_id + var/list/reagent_options = sortList(GLOB.chemical_reagents_list) + switch(alert(usr, "Choose a method.", "Add Reagents", "Enter ID", "Choose ID")) + if("Enter ID") + var/valid_id + while(!valid_id) + chosen_id = stripped_input(usr, "Enter the ID of the reagent you want to add.") + if(!chosen_id) //Get me out of here! + break + for(var/ID in reagent_options) + if(ID == chosen_id) + valid_id = 1 + if(!valid_id) + to_chat(usr, "A reagent with that ID doesn't exist!") + if("Choose ID") + chosen_id = input(usr, "Choose a reagent to add.", "Choose a reagent.") as null|anything in reagent_options + if(chosen_id) + var/amount = input(usr, "Choose the amount to add.", "Choose the amount.", A.reagents.maximum_volume) as num + if(amount) + A.reagents.add_reagent(chosen_id, amount) + log_admin("[key_name(usr)] has added [amount] units of [chosen_id] to \the [A]") + message_admins("[key_name(usr)] has added [amount] units of [chosen_id] to \the [A]") + + href_list["datumrefresh"] = href_list["addreagent"] + + else if(href_list["explode"]) + if(!check_rights(R_FUN)) + return + + var/atom/A = locate(href_list["explode"]) + if(!isobj(A) && !ismob(A) && !isturf(A)) + to_chat(usr, "This can only be done to instances of type /obj, /mob and /turf") + return + + src.cmd_admin_explosion(A) + href_list["datumrefresh"] = href_list["explode"] + + else if(href_list["emp"]) + if(!check_rights(R_FUN)) + return + + var/atom/A = locate(href_list["emp"]) + if(!isobj(A) && !ismob(A) && !isturf(A)) + to_chat(usr, "This can only be done to instances of type /obj, /mob and /turf") + return + + src.cmd_admin_emp(A) + href_list["datumrefresh"] = href_list["emp"] + + else if(href_list["rotatedatum"]) + if(!check_rights(0)) + return + + var/atom/A = locate(href_list["rotatedatum"]) + if(!istype(A)) + to_chat(usr, "This can only be done to instances of type /atom") + return + + switch(href_list["rotatedir"]) + if("right") + A.setDir(turn(A.dir, -45)) + if("left") + A.setDir(turn(A.dir, 45)) + href_list["datumrefresh"] = href_list["rotatedatum"] + + else if(href_list["editorgans"]) + if(!check_rights(0)) + return + var/mob/living/carbon/C = locate(href_list["editorgans"]) in GLOB.mob_list - if(!istype(C)) - to_chat(usr, "This can only be done to instances of type /mob/living/carbon") - return - - manipulate_organs(C) - href_list["datumrefresh"] = href_list["editorgans"] - + if(!istype(C)) + to_chat(usr, "This can only be done to instances of type /mob/living/carbon") + return + + manipulate_organs(C) + href_list["datumrefresh"] = href_list["editorgans"] + else if(href_list["hallucinate"]) if(!check_rights(0)) return @@ -1455,238 +1449,238 @@ if(result) new result(C, TRUE) - else if(href_list["makehuman"]) - if(!check_rights(R_SPAWN)) - return - + else if(href_list["makehuman"]) + if(!check_rights(R_SPAWN)) + return + var/mob/living/carbon/monkey/Mo = locate(href_list["makehuman"]) in GLOB.mob_list - if(!istype(Mo)) - to_chat(usr, "This can only be done to instances of type /mob/living/carbon/monkey") - return - - if(alert("Confirm mob type change?",,"Transform","Cancel") != "Transform") - return - if(!Mo) - to_chat(usr, "Mob doesn't exist anymore") - return - holder.Topic(href, list("humanone"=href_list["makehuman"])) - - else if(href_list["makemonkey"]) - if(!check_rights(R_SPAWN)) - return - + if(!istype(Mo)) + to_chat(usr, "This can only be done to instances of type /mob/living/carbon/monkey") + return + + if(alert("Confirm mob type change?",,"Transform","Cancel") != "Transform") + return + if(!Mo) + to_chat(usr, "Mob doesn't exist anymore") + return + holder.Topic(href, list("humanone"=href_list["makehuman"])) + + else if(href_list["makemonkey"]) + if(!check_rights(R_SPAWN)) + return + var/mob/living/carbon/human/H = locate(href_list["makemonkey"]) in GLOB.mob_list - if(!istype(H)) - to_chat(usr, "This can only be done to instances of type /mob/living/carbon/human") - return - - if(alert("Confirm mob type change?",,"Transform","Cancel") != "Transform") - return - if(!H) - to_chat(usr, "Mob doesn't exist anymore") - return - holder.Topic(href, list("monkeyone"=href_list["makemonkey"])) - - else if(href_list["makerobot"]) - if(!check_rights(R_SPAWN)) - return - + if(!istype(H)) + to_chat(usr, "This can only be done to instances of type /mob/living/carbon/human") + return + + if(alert("Confirm mob type change?",,"Transform","Cancel") != "Transform") + return + if(!H) + to_chat(usr, "Mob doesn't exist anymore") + return + holder.Topic(href, list("monkeyone"=href_list["makemonkey"])) + + else if(href_list["makerobot"]) + if(!check_rights(R_SPAWN)) + return + var/mob/living/carbon/human/H = locate(href_list["makerobot"]) in GLOB.mob_list - if(!istype(H)) - to_chat(usr, "This can only be done to instances of type /mob/living/carbon/human") - return - - if(alert("Confirm mob type change?",,"Transform","Cancel") != "Transform") - return - if(!H) - to_chat(usr, "Mob doesn't exist anymore") - return - holder.Topic(href, list("makerobot"=href_list["makerobot"])) - - else if(href_list["makealien"]) - if(!check_rights(R_SPAWN)) - return - + if(!istype(H)) + to_chat(usr, "This can only be done to instances of type /mob/living/carbon/human") + return + + if(alert("Confirm mob type change?",,"Transform","Cancel") != "Transform") + return + if(!H) + to_chat(usr, "Mob doesn't exist anymore") + return + holder.Topic(href, list("makerobot"=href_list["makerobot"])) + + else if(href_list["makealien"]) + if(!check_rights(R_SPAWN)) + return + var/mob/living/carbon/human/H = locate(href_list["makealien"]) in GLOB.mob_list - if(!istype(H)) - to_chat(usr, "This can only be done to instances of type /mob/living/carbon/human") - return - - if(alert("Confirm mob type change?",,"Transform","Cancel") != "Transform") - return - if(!H) - to_chat(usr, "Mob doesn't exist anymore") - return - holder.Topic(href, list("makealien"=href_list["makealien"])) - - else if(href_list["makeslime"]) - if(!check_rights(R_SPAWN)) - return - + if(!istype(H)) + to_chat(usr, "This can only be done to instances of type /mob/living/carbon/human") + return + + if(alert("Confirm mob type change?",,"Transform","Cancel") != "Transform") + return + if(!H) + to_chat(usr, "Mob doesn't exist anymore") + return + holder.Topic(href, list("makealien"=href_list["makealien"])) + + else if(href_list["makeslime"]) + if(!check_rights(R_SPAWN)) + return + var/mob/living/carbon/human/H = locate(href_list["makeslime"]) in GLOB.mob_list - if(!istype(H)) - to_chat(usr, "This can only be done to instances of type /mob/living/carbon/human") - return - - if(alert("Confirm mob type change?",,"Transform","Cancel") != "Transform") - return - if(!H) - to_chat(usr, "Mob doesn't exist anymore") - return - holder.Topic(href, list("makeslime"=href_list["makeslime"])) - - else if(href_list["makeai"]) - if(!check_rights(R_SPAWN)) - return - + if(!istype(H)) + to_chat(usr, "This can only be done to instances of type /mob/living/carbon/human") + return + + if(alert("Confirm mob type change?",,"Transform","Cancel") != "Transform") + return + if(!H) + to_chat(usr, "Mob doesn't exist anymore") + return + holder.Topic(href, list("makeslime"=href_list["makeslime"])) + + else if(href_list["makeai"]) + if(!check_rights(R_SPAWN)) + return + var/mob/living/carbon/H = locate(href_list["makeai"]) in GLOB.mob_list - if(!istype(H)) - to_chat(usr, "This can only be done to instances of type /mob/living/carbon") - return - - if(alert("Confirm mob type change?",,"Transform","Cancel") != "Transform") - return - if(!H) - to_chat(usr, "Mob doesn't exist anymore") - return - holder.Topic(href, list("makeai"=href_list["makeai"])) - - else if(href_list["setspecies"]) - if(!check_rights(R_SPAWN)) - return - + if(!istype(H)) + to_chat(usr, "This can only be done to instances of type /mob/living/carbon") + return + + if(alert("Confirm mob type change?",,"Transform","Cancel") != "Transform") + return + if(!H) + to_chat(usr, "Mob doesn't exist anymore") + return + holder.Topic(href, list("makeai"=href_list["makeai"])) + + else if(href_list["setspecies"]) + if(!check_rights(R_SPAWN)) + return + var/mob/living/carbon/human/H = locate(href_list["setspecies"]) in GLOB.mob_list - if(!istype(H)) - to_chat(usr, "This can only be done to instances of type /mob/living/carbon/human") - return - - var/result = input(usr, "Please choose a new species","Species") as null|anything in GLOB.species_list - - if(!H) - to_chat(usr, "Mob doesn't exist anymore") - return - - if(result) - var/newtype = GLOB.species_list[result] - admin_ticket_log("[key_name_admin(usr)] has modified the bodyparts of [H] to [result]") - H.set_species(newtype) - - else if(href_list["editbodypart"]) - if(!check_rights(R_SPAWN)) - return - + if(!istype(H)) + to_chat(usr, "This can only be done to instances of type /mob/living/carbon/human") + return + + var/result = input(usr, "Please choose a new species","Species") as null|anything in GLOB.species_list + + if(!H) + to_chat(usr, "Mob doesn't exist anymore") + return + + if(result) + var/newtype = GLOB.species_list[result] + admin_ticket_log("[key_name_admin(usr)] has modified the bodyparts of [H] to [result]") + H.set_species(newtype) + + else if(href_list["editbodypart"]) + if(!check_rights(R_SPAWN)) + return + var/mob/living/carbon/C = locate(href_list["editbodypart"]) in GLOB.mob_list - if(!istype(C)) - to_chat(usr, "This can only be done to instances of type /mob/living/carbon") - return - - var/edit_action = input(usr, "What would you like to do?","Modify Body Part") as null|anything in list("add","remove", "augment") - if(!edit_action) - return - var/list/limb_list = list("head", "l_arm", "r_arm", "l_leg", "r_leg") - if(edit_action == "augment") - limb_list += "chest" - var/result = input(usr, "Please choose which body part to [edit_action]","[capitalize(edit_action)] Body Part") as null|anything in limb_list - - if(!C) - to_chat(usr, "Mob doesn't exist anymore") - return - - if(result) - var/obj/item/bodypart/BP = C.get_bodypart(result) - switch(edit_action) - if("remove") - if(BP) - BP.drop_limb() - else - to_chat(usr, "[C] doesn't have such bodypart.") - if("add") - if(BP) - to_chat(usr, "[C] already has such bodypart.") - else - if(!C.regenerate_limb(result)) - to_chat(usr, "[C] cannot have such bodypart.") - if("augment") - if(ishuman(C)) - if(BP) - BP.change_bodypart_status(BODYPART_ROBOTIC, TRUE, TRUE) - else - to_chat(usr, "[C] doesn't have such bodypart.") - else - to_chat(usr, "Only humans can be augmented.") - admin_ticket_log("[key_name_admin(usr)] has modified the bodyparts of [C]") - - - else if(href_list["purrbation"]) - if(!check_rights(R_SPAWN)) - return - + if(!istype(C)) + to_chat(usr, "This can only be done to instances of type /mob/living/carbon") + return + + var/edit_action = input(usr, "What would you like to do?","Modify Body Part") as null|anything in list("add","remove", "augment") + if(!edit_action) + return + var/list/limb_list = list("head", "l_arm", "r_arm", "l_leg", "r_leg") + if(edit_action == "augment") + limb_list += "chest" + var/result = input(usr, "Please choose which body part to [edit_action]","[capitalize(edit_action)] Body Part") as null|anything in limb_list + + if(!C) + to_chat(usr, "Mob doesn't exist anymore") + return + + if(result) + var/obj/item/bodypart/BP = C.get_bodypart(result) + switch(edit_action) + if("remove") + if(BP) + BP.drop_limb() + else + to_chat(usr, "[C] doesn't have such bodypart.") + if("add") + if(BP) + to_chat(usr, "[C] already has such bodypart.") + else + if(!C.regenerate_limb(result)) + to_chat(usr, "[C] cannot have such bodypart.") + if("augment") + if(ishuman(C)) + if(BP) + BP.change_bodypart_status(BODYPART_ROBOTIC, TRUE, TRUE) + else + to_chat(usr, "[C] doesn't have such bodypart.") + else + to_chat(usr, "Only humans can be augmented.") + admin_ticket_log("[key_name_admin(usr)] has modified the bodyparts of [C]") + + + else if(href_list["purrbation"]) + if(!check_rights(R_SPAWN)) + return + var/mob/living/carbon/human/H = locate(href_list["purrbation"]) in GLOB.mob_list - if(!istype(H)) - to_chat(usr, "This can only be done to instances of type /mob/living/carbon/human") - return - if(!ishumanbasic(H)) - to_chat(usr, "This can only be done to the basic human species at the moment.") - return - - if(!H) - to_chat(usr, "Mob doesn't exist anymore") - return - - var/success = purrbation_toggle(H) - if(success) - to_chat(usr, "Put [H] on purrbation.") - log_admin("[key_name(usr)] has put [key_name(H)] on purrbation.") - var/msg = "[key_name_admin(usr)] has put [key_name(H)] on purrbation." - message_admins(msg) - admin_ticket_log(H, msg) - - else - to_chat(usr, "Removed [H] from purrbation.") - log_admin("[key_name(usr)] has removed [key_name(H)] from purrbation.") - var/msg = "[key_name_admin(usr)] has removed [key_name(H)] from purrbation." - message_admins(msg) - admin_ticket_log(H, msg) - - else if(href_list["adjustDamage"] && href_list["mobToDamage"]) - if(!check_rights(0)) - return - + if(!istype(H)) + to_chat(usr, "This can only be done to instances of type /mob/living/carbon/human") + return + if(!ishumanbasic(H)) + to_chat(usr, "This can only be done to the basic human species at the moment.") + return + + if(!H) + to_chat(usr, "Mob doesn't exist anymore") + return + + var/success = purrbation_toggle(H) + if(success) + to_chat(usr, "Put [H] on purrbation.") + log_admin("[key_name(usr)] has put [key_name(H)] on purrbation.") + var/msg = "[key_name_admin(usr)] has put [key_name(H)] on purrbation." + message_admins(msg) + admin_ticket_log(H, msg) + + else + to_chat(usr, "Removed [H] from purrbation.") + log_admin("[key_name(usr)] has removed [key_name(H)] from purrbation.") + var/msg = "[key_name_admin(usr)] has removed [key_name(H)] from purrbation." + message_admins(msg) + admin_ticket_log(H, msg) + + else if(href_list["adjustDamage"] && href_list["mobToDamage"]) + if(!check_rights(0)) + return + var/mob/living/L = locate(href_list["mobToDamage"]) in GLOB.mob_list - if(!istype(L)) - return - - var/Text = href_list["adjustDamage"] - - var/amount = input("Deal how much damage to mob? (Negative values here heal)","Adjust [Text]loss",0) as num - - if(!L) - to_chat(usr, "Mob doesn't exist anymore") - return - - switch(Text) - if("brute") - L.adjustBruteLoss(amount) - if("fire") - L.adjustFireLoss(amount) - if("toxin") - L.adjustToxLoss(amount) - if("oxygen") - L.adjustOxyLoss(amount) - if("brain") - L.adjustBrainLoss(amount) - if("clone") - L.adjustCloneLoss(amount) - if("stamina") - L.adjustStaminaLoss(amount) - else - to_chat(usr, "You caused an error. DEBUG: Text:[Text] Mob:[L]") - return - - if(amount != 0) - log_admin("[key_name(usr)] dealt [amount] amount of [Text] damage to [L] ") - var/msg = "[key_name(usr)] dealt [amount] amount of [Text] damage to [L] " - message_admins(msg) - admin_ticket_log(L, msg) - href_list["datumrefresh"] = href_list["mobToDamage"] - + if(!istype(L)) + return + + var/Text = href_list["adjustDamage"] + + var/amount = input("Deal how much damage to mob? (Negative values here heal)","Adjust [Text]loss",0) as num + + if(!L) + to_chat(usr, "Mob doesn't exist anymore") + return + + switch(Text) + if("brute") + L.adjustBruteLoss(amount) + if("fire") + L.adjustFireLoss(amount) + if("toxin") + L.adjustToxLoss(amount) + if("oxygen") + L.adjustOxyLoss(amount) + if("brain") + L.adjustBrainLoss(amount) + if("clone") + L.adjustCloneLoss(amount) + if("stamina") + L.adjustStaminaLoss(amount) + else + to_chat(usr, "You caused an error. DEBUG: Text:[Text] Mob:[L]") + return + + if(amount != 0) + log_admin("[key_name(usr)] dealt [amount] amount of [Text] damage to [L] ") + var/msg = "[key_name(usr)] dealt [amount] amount of [Text] damage to [L] " + message_admins(msg) + admin_ticket_log(L, msg) + href_list["datumrefresh"] = href_list["mobToDamage"] + From 2f10e78ba7f8be726c18ecfecdd4738906bda2c8 Mon Sep 17 00:00:00 2001 From: LetterJay Date: Mon, 11 Sep 2017 13:56:28 -0500 Subject: [PATCH 45/74] Update on_move.dm --- code/modules/shuttle/on_move.dm | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/code/modules/shuttle/on_move.dm b/code/modules/shuttle/on_move.dm index e80b690737..f2c84a5aae 100644 --- a/code/modules/shuttle/on_move.dm +++ b/code/modules/shuttle/on_move.dm @@ -14,12 +14,9 @@ All ShuttleMove procs go here // Called from the new turf before anything has been moved // Only gets called if fromShuttleMove returns true first // returns the new move_mode (based on the old) -<<<<<<< HEAD /turf/proc/toShuttleMove(turf/oldT, shuttle_dir, move_mode) -======= /turf/proc/toShuttleMove(turf/oldT, move_mode, obj/docking_port/mobile/shuttle) var/shuttle_dir = shuttle.dir ->>>>>>> 9ac60a8... Typo for(var/i in contents) var/atom/movable/thing = i if(ismob(thing)) @@ -388,4 +385,4 @@ All ShuttleMove procs go here /obj/effect/abstract/proximity_checker/onShuttleMove(turf/newT, turf/oldT, rotation, list/movement_force, move_dir, old_dock) //timer so it only happens once - addtimer(CALLBACK(monitor, /datum/proximity_monitor/proc/SetRange, monitor.current_range, TRUE), 0, TIMER_UNIQUE) \ No newline at end of file + addtimer(CALLBACK(monitor, /datum/proximity_monitor/proc/SetRange, monitor.current_range, TRUE), 0, TIMER_UNIQUE) From ddd0d9a1fc71881596be7e274952a07893c2add8 Mon Sep 17 00:00:00 2001 From: CitadelStationBot Date: Mon, 11 Sep 2017 13:56:54 -0500 Subject: [PATCH 46/74] Automatic changelog generation for PR #2706 [ci skip] --- html/changelogs/AutoChangeLog-pr-2706.yml | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 html/changelogs/AutoChangeLog-pr-2706.yml diff --git a/html/changelogs/AutoChangeLog-pr-2706.yml b/html/changelogs/AutoChangeLog-pr-2706.yml new file mode 100644 index 0000000000..4db678dd9b --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-2706.yml @@ -0,0 +1,4 @@ +author: "Xhuis" +delete-after: True +changes: + - rscadd: "You can now use metal rods and departmental jumpsuits to craft departments for each banner." From 14aefe2e64e20f57ced285e782aaf8cec2c992f8 Mon Sep 17 00:00:00 2001 From: LetterJay Date: Mon, 11 Sep 2017 14:01:42 -0500 Subject: [PATCH 47/74] commit --- .../kitchen_machinery/smartfridge.dm | 131 +++++++++--------- tgui/assets/tgui.css | 2 +- tgui/assets/tgui.js | 32 ++--- tgui/src/interfaces/smartvend.ract | 48 +++++++ 4 files changed, 131 insertions(+), 82 deletions(-) create mode 100644 tgui/src/interfaces/smartvend.ract diff --git a/code/modules/food_and_drinks/kitchen_machinery/smartfridge.dm b/code/modules/food_and_drinks/kitchen_machinery/smartfridge.dm index e996429939..53b899f696 100644 --- a/code/modules/food_and_drinks/kitchen_machinery/smartfridge.dm +++ b/code/modules/food_and_drinks/kitchen_machinery/smartfridge.dm @@ -142,69 +142,55 @@ user.set_machine(src) interact(user) -/******************* -* SmartFridge Menu -********************/ -/obj/machinery/smartfridge/interact(mob/user) - if(stat) - return FALSE - var/dat = "Select an item:
    " +/obj/machinery/smartfridge/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = FALSE, datum/tgui/master_ui = null, datum/ui_state/state = GLOB.default_state) + ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open) + if(!ui) + ui = new(user, src, ui_key, "smartvend", name, 440, 550, master_ui, state) + ui.open() - if (contents.len == 0) - dat += "No product loaded!" - else - var/listofitems = list() - for (var/atom/movable/O in contents) - if (listofitems[O.name]) - listofitems[O.name]++ - else - listofitems[O.name] = 1 - sortList(listofitems) +/obj/machinery/smartfridge/ui_data(mob/user) + . = list() - for (var/O in listofitems) - if(listofitems[O] <= 0) - continue - var/N = listofitems[O] - var/itemName = url_encode(O) - dat += "[capitalize(O)]:" - dat += " [N] " - dat += "Vend " - if(N > 5) - dat += "(x5)" - if(N > 10) - dat += "(x10)" - if(N > 25) - dat += "(x25)" - if(N > 1) - dat += "(All)" + var/listofitems = list() + for (var/I in src) + var/atom/movable/O = I + if (listofitems[O.name]) + listofitems[O.name]["amount"]++ + else + listofitems[O.name] = list("name" = O.name, "type" = O.type, "amount" = 1) + sortList(listofitems) - dat += "
    " + .["contents"] = listofitems + .["name"] = name + .["isdryer"] = FALSE - dat += "
    " - user << browse("[src] supplies[dat]", "window=smartfridge") - onclose(user, "smartfridge") - return dat -/obj/machinery/smartfridge/Topic(var/href, var/list/href_list) - if(..()) +/obj/machinery/smartfridge/ui_act(action, params) + . = ..() + if(.) return - usr.set_machine(src) + switch(action) + if("Release") + var/desired = 0 - var/N = href_list["vend"] - var/amount = text2num(href_list["amount"]) + if (params["amount"]) + desired = text2num(params["amount"]) + else + desired = input("How many items?", "How many items would you like to take out?", 1) as null|num - var/i = amount - for(var/obj/O in contents) - if(i <= 0) - break - if(O.name == N) - O.loc = src.loc - i-- + if(QDELETED(src) || QDELETED(usr) || !usr.Adjacent(src)) // Sanity checkin' in case stupid stuff happens while we wait for input() + return FALSE - - updateUsrDialog() + for(var/obj/item/O in src) + if(desired <= 0) + break + if(O.name == params["name"]) + O.forceMove(drop_location()) + desired-- + return TRUE + return FALSE // ---------------------------- @@ -240,20 +226,35 @@ /obj/machinery/smartfridge/drying_rack/default_deconstruction_crowbar(obj/item/crowbar/C, ignore_panel = 1) ..() -/obj/machinery/smartfridge/drying_rack/interact(mob/user) - var/dat = ..() - if(dat) - dat += "
    " - dat += "Toggle Drying " - user << browse("[src] supplies[dat]", "window=smartfridge") - onclose(user, "smartfridge") +/obj/machinery/smartfridge/drying_rack/ui_data(mob/user) + . = list() -/obj/machinery/smartfridge/drying_rack/Topic(href, list/href_list) - ..() - if(href_list["dry"]) - toggle_drying(FALSE) - updateUsrDialog() - update_icon() + var/listofitems = list() + for (var/I in src) + var/atom/movable/O = I + + if (listofitems[O.name]) + listofitems[O.name]["amount"]++ + else + listofitems[O.name] = list("name" = O.name, "type" = O.type, "amount" = 1) + sortList(listofitems) + + .["contents"] = listofitems + .["name"] = name + .["isdryer"] = TRUE + .["verb"] = "Take" + .["drying"] = drying + + +/obj/machinery/smartfridge/drying_rack/ui_act(action, params) + . = ..() + if(.) + return + switch(action) + if("Dry") + toggle_drying(FALSE) + return TRUE + return FALSE /obj/machinery/smartfridge/drying_rack/power_change() if(powered() && anchored) diff --git a/tgui/assets/tgui.css b/tgui/assets/tgui.css index f19852971d..ffe61666b9 100644 --- a/tgui/assets/tgui.css +++ b/tgui/assets/tgui.css @@ -1 +1 @@ -@charset "utf-8";body,html{box-sizing:border-box;height:100%;margin:0}html{overflow:hidden;cursor:default}body{overflow:auto;font-family:Verdana,Geneva,sans-serif;font-size:12px;color:#fff;background-color:#2a2a2a;background-image:linear-gradient(180deg,#2a2a2a 0,#202020);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff2a2a2a',endColorstr='#ff202020',GradientType=0)}*,:after,:before{box-sizing:inherit}h1,h2,h3,h4{display:inline-block;margin:0;padding:6px 0}h1{font-size:18px}h2{font-size:16px}h3{font-size:14px}h4{font-size:12px}body.clockwork{background:linear-gradient(180deg,#b18b25 0,#5f380e);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffb18b25',endColorstr='#ff5f380e',GradientType=0)}body.clockwork .normal{color:#b18b25}body.clockwork .good{color:#cfba47}body.clockwork .average{color:#896b19}body.clockwork .bad{color:#5f380e}body.clockwork .highlight{color:#b18b25}body.clockwork main{display:block;margin-top:32px;padding:2px 6px 0}body.clockwork hr{height:2px;background-color:#b18b25;border:none}body.clockwork .hidden{display:none}body.clockwork .bar .barText,body.clockwork span.button{color:#b18b25;font-size:12px;font-weight:400;font-style:normal;text-decoration:none}body.clockwork .bold{font-weight:700}body.clockwork .italic{font-style:italic}body.clockwork [unselectable=on]{-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}body.clockwork div[data-tooltip],body.clockwork span[data-tooltip]{position:relative}body.clockwork div[data-tooltip]:after,body.clockwork span[data-tooltip]:after{position:absolute;display:block;z-index:2;width:250px;padding:10px;-ms-transform:translateX(-50%);transform:translateX(-50%);visibility:hidden;opacity:0;-ms-filter:"progid:DXImageTransform.Microsoft.Alpha(Opacity=0)";white-space:normal;text-align:left;content:attr(data-tooltip);transition:all .5s;border:1px solid #170800;background-color:#2d1400}body.clockwork div[data-tooltip]:hover:after,body.clockwork span[data-tooltip]:hover:after{visibility:visible;opacity:1;-ms-filter:"progid:DXImageTransform.Microsoft.Alpha(Opacity=100)"}body.clockwork div[data-tooltip].tooltip-top:after,body.clockwork span[data-tooltip].tooltip-top:after{bottom:100%;left:50%;-ms-transform:translateX(-50%) translateY(8px);transform:translateX(-50%) translateY(8px)}body.clockwork div[data-tooltip].tooltip-top:hover:after,body.clockwork span[data-tooltip].tooltip-top:hover:after{-ms-transform:translateX(-50%) translateY(-8px);transform:translateX(-50%) translateY(-8px)}body.clockwork div[data-tooltip].tooltip-bottom:after,body.clockwork span[data-tooltip].tooltip-bottom:after{top:100%;left:50%;-ms-transform:translateX(-50%) translateY(-8px);transform:translateX(-50%) translateY(-8px)}body.clockwork div[data-tooltip].tooltip-bottom:hover:after,body.clockwork span[data-tooltip].tooltip-bottom:hover:after{-ms-transform:translateX(-50%) translateY(8px);transform:translateX(-50%) translateY(8px)}body.clockwork div[data-tooltip].tooltip-left:after,body.clockwork span[data-tooltip].tooltip-left:after{top:50%;right:100%;-ms-transform:translateX(8px) translateY(-50%);transform:translateX(8px) translateY(-50%)}body.clockwork div[data-tooltip].tooltip-left:hover:after,body.clockwork span[data-tooltip].tooltip-left:hover:after{-ms-transform:translateX(-8px) translateY(-50%);transform:translateX(-8px) translateY(-50%)}body.clockwork div[data-tooltip].tooltip-right:after,body.clockwork span[data-tooltip].tooltip-right:after{top:50%;left:100%;-ms-transform:translateX(-8px) translateY(-50%);transform:translateX(-8px) translateY(-50%)}body.clockwork div[data-tooltip].tooltip-right:hover:after,body.clockwork span[data-tooltip].tooltip-right:hover:after{-ms-transform:translateX(8px) translateY(-50%);transform:translateX(8px) translateY(-50%)}body.clockwork .bar{display:inline-block;position:relative;vertical-align:middle;width:100%;height:20px;line-height:17px;padding:1px;border:1px solid #170800;background:#2d1400}body.clockwork .bar .barText{position:absolute;top:0;right:3px}body.clockwork .bar .barFill{display:block;height:100%;transition:background-color 1s;background-color:#b18b25}body.clockwork .bar .barFill.good{background-color:#cfba47}body.clockwork .bar .barFill.average{background-color:#896b19}body.clockwork .bar .barFill.bad{background-color:#5f380e}body.clockwork span.button{display:inline-block;vertical-align:middle;min-height:20px;line-height:17px;padding:0 5px;white-space:nowrap;border:1px solid #170800}body.clockwork span.button .fa{padding-right:2px}body.clockwork span.button.normal{transition:background-color .5s;background-color:#5f380e}body.clockwork span.button.normal.active:focus,body.clockwork span.button.normal.active:hover{transition:background-color .25s;background-color:#704211;outline:0}body.clockwork span.button.disabled{transition:background-color .5s;background-color:#2d1400}body.clockwork span.button.disabled.active:focus,body.clockwork span.button.disabled.active:hover{transition:background-color .25s;background-color:#441e00;outline:0}body.clockwork span.button.selected{transition:background-color .5s;background-color:#cfba47}body.clockwork span.button.selected.active:focus,body.clockwork span.button.selected.active:hover{transition:background-color .25s;background-color:#d1bd50;outline:0}body.clockwork span.button.toggle{transition:background-color .5s;background-color:#cfba47}body.clockwork span.button.toggle.active:focus,body.clockwork span.button.toggle.active:hover{transition:background-color .25s;background-color:#d1bd50;outline:0}body.clockwork span.button.caution{transition:background-color .5s;background-color:#be6209}body.clockwork span.button.caution.active:focus,body.clockwork span.button.caution.active:hover{transition:background-color .25s;background-color:#cd6a0a;outline:0}body.clockwork span.button.danger{transition:background-color .5s;background-color:#9a9d00}body.clockwork span.button.danger.active:focus,body.clockwork span.button.danger.active:hover{transition:background-color .25s;background-color:#abaf00;outline:0}body.clockwork span.button.gridable{width:125px;margin:2px 0}body.clockwork span.button.gridable.center{text-align:center;width:75px}body.clockwork span.button+span:not(.button),body.clockwork span:not(.button)+span.button{margin-left:5px}body.clockwork div.display{width:100%;padding:4px;margin:6px 0;background-color:#2d1400;-ms-filter:"progid:DXImageTransform.Microsoft.gradient(startColorStr=#e62d1400,endColorStr=#e62d1400)";filter:progid:DXImageTransform.Microsoft.gradient(startColorStr=#e62d1400,endColorStr=#e62d1400);background-color:rgba(45,20,0,.9);box-shadow:inset 0 0 5px rgba(0,0,0,.3)}body.clockwork div.display.tabular{padding:0;margin:0}body.clockwork div.display header,body.clockwork div.subdisplay header{display:block;position:relative;width:100%;padding:0 4px;margin-bottom:6px;color:#cfba47;border-bottom:2px solid #b18b25}body.clockwork div.display header .buttonRight,body.clockwork div.subdisplay header .buttonRight{position:absolute;bottom:6px;right:4px}body.clockwork div.display article,body.clockwork div.subdisplay article{display:table;width:100%;border-collapse:collapse}body.clockwork input{display:inline-block;vertical-align:middle;height:20px;line-height:17px;padding:0 5px;white-space:nowrap;color:#b18b25;background-color:#cfba47;border:1px solid #272727}body.clockwork input.number{width:35px}body.clockwork input::-webkit-input-placeholder{color:#999}body.clockwork input::-moz-placeholder{color:#999}body.clockwork input:-ms-input-placeholder{color:#999}body.clockwork input::placeholder{color:#999}body.clockwork input::-ms-clear{display:none}body.clockwork svg.linegraph{overflow:hidden}body.clockwork div.notice{margin:8px 0;padding:4px;box-shadow:none;color:#2d1400;font-weight:700;font-style:italic;background-color:#000;background-image:repeating-linear-gradient(-45deg,#000,#000 10px,#170800 0,#170800 20px)}body.clockwork div.notice .label{color:#2d1400}body.clockwork div.notice .content:only-of-type{padding:0}body.clockwork div.notice hr{background-color:#896b19}body.clockwork div.resize{position:fixed;bottom:0;right:0;width:0;height:0;border-style:solid;border-width:0 0 45px 45px;border-color:transparent transparent #5f380e;-ms-transform:rotate(1turn);transform:rotate(1turn)}body.clockwork section .cell,body.clockwork section .content,body.clockwork section .label,body.clockwork section .line,body.nanotrasen section .cell,body.nanotrasen section .content,body.nanotrasen section .label,body.nanotrasen section .line,body.syndicate section .cell,body.syndicate section .content,body.syndicate section .label,body.syndicate section .line{display:table-cell;margin:0;text-align:left;vertical-align:middle;padding:3px 2px}body.clockwork section{display:table-row;width:100%}body.clockwork section:not(:first-child){padding-top:4px}body.clockwork section.candystripe:nth-child(even){background-color:#000;-ms-filter:"progid:DXImageTransform.Microsoft.gradient(startColorStr=#33000000,endColorStr=#33000000)";filter:progid:DXImageTransform.Microsoft.gradient(startColorStr=#33000000,endColorStr=#33000000);background-color:rgba(0,0,0,.2)}body.clockwork section .label{width:1%;padding-right:32px;white-space:nowrap;color:#b18b25}body.clockwork section .content:not(:last-child){padding-right:16px}body.clockwork section .line{width:100%}body.clockwork section .cell:not(:first-child){text-align:center;padding-top:0}body.clockwork section .cell span.button{width:75px}body.clockwork section:not(:last-child){padding-right:4px}body.clockwork div.subdisplay{width:100%;margin:0}body.clockwork header.titlebar .close,body.clockwork header.titlebar .minimize{display:inline-block;position:relative;padding:7px;margin:-7px;color:#cfba47}body.clockwork header.titlebar .close:hover,body.clockwork header.titlebar .minimize:hover{color:#d1bd50}body.clockwork header.titlebar{position:fixed;z-index:1;top:0;left:0;width:100%;height:32px;background-color:#5f380e;border-bottom:1px solid #170800;box-shadow:0 3px 3px rgba(0,0,0,.1)}body.clockwork header.titlebar .statusicon{position:absolute;top:4px;left:12px;transition:color .5s}body.clockwork header.titlebar .title{position:absolute;top:6px;left:46px;color:#cfba47;font-size:16px;white-space:nowrap}body.clockwork header.titlebar .minimize{position:absolute;top:6px;right:46px}body.clockwork header.titlebar .close{position:absolute;top:4px;right:12px}body.nanotrasen{background:url("data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiIHN0YW5kYWxvbmU9Im5vIj8+DQo8c3ZnIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgdmVyc2lvbj0iMS4wIiB2aWV3Qm94PSIwIDAgNDI1IDIwMCIgb3BhY2l0eT0iLjMzIj4NCiAgPHBhdGggZD0ibSAxNzguMDAzOTksMC4wMzg2OSAtNzEuMjAzOTMsMCBhIDYuNzYxMzQyMiw2LjAyNTU0OTUgMCAwIDAgLTYuNzYxMzQsNi4wMjU1NSBsIDAsMTg3Ljg3MTQ3IGEgNi43NjEzNDIyLDYuMDI1NTQ5NSAwIDAgMCA2Ljc2MTM0LDYuMDI1NTQgbCA1My4xMDcyLDAgYSA2Ljc2MTM0MjIsNi4wMjU1NDk1IDAgMCAwIDYuNzYxMzUsLTYuMDI1NTQgbCAwLC0xMDEuNTQ0MDE4IDcyLjIxNjI4LDEwNC42OTkzOTggYSA2Ljc2MTM0MjIsNi4wMjU1NDk1IDAgMCAwIDUuNzYwMTUsMi44NzAxNiBsIDczLjU1NDg3LDAgYSA2Ljc2MTM0MjIsNi4wMjU1NDk1IDAgMCAwIDYuNzYxMzUsLTYuMDI1NTQgbCAwLC0xODcuODcxNDcgYSA2Ljc2MTM0MjIsNi4wMjU1NDk1IDAgMCAwIC02Ljc2MTM1LC02LjAyNTU1IGwgLTU0LjcxNjQ0LDAgYSA2Ljc2MTM0MjIsNi4wMjU1NDk1IDAgMCAwIC02Ljc2MTMzLDYuMDI1NTUgbCAwLDEwMi42MTkzNSBMIDE4My43NjQxMywyLjkwODg2IGEgNi43NjEzNDIyLDYuMDI1NTQ5NSAwIDAgMCAtNS43NjAxNCwtMi44NzAxNyB6IiAvPg0KICA8cGF0aCBkPSJNIDQuODQ0NjMzMywyMi4xMDg3NSBBIDEzLjQxMjAzOSwxMi41MDE4NDIgMCAwIDEgMTMuNDc3NTg4LDAuMDM5MjQgbCA2Ni4xMTgzMTUsMCBhIDUuMzY0ODE1OCw1LjAwMDczNyAwIDAgMSA1LjM2NDgyMyw1LjAwMDczIGwgMCw3OS44NzkzMSB6IiAvPg0KICA8cGF0aCBkPSJtIDQyMC4xNTUzNSwxNzcuODkxMTkgYSAxMy40MTIwMzgsMTIuNTAxODQyIDAgMCAxIC04LjYzMjk1LDIyLjA2OTUxIGwgLTY2LjExODMyLDAgYSA1LjM2NDgxNTIsNS4wMDA3MzcgMCAwIDEgLTUuMzY0ODIsLTUuMDAwNzQgbCAwLC03OS44NzkzMSB6IiAvPg0KPC9zdmc+DQo8IS0tIFRoaXMgd29yayBpcyBsaWNlbnNlZCB1bmRlciBhIENyZWF0aXZlIENvbW1vbnMgQXR0cmlidXRpb24tU2hhcmVBbGlrZSA0LjAgSW50ZXJuYXRpb25hbCBMaWNlbnNlLiAtLT4NCjwhLS0gaHR0cDovL2NyZWF0aXZlY29tbW9ucy5vcmcvbGljZW5zZXMvYnktc2EvNC4wLyAtLT4NCg==") no-repeat fixed 50%/70% 70%,linear-gradient(180deg,#2a2a2a 0,#202020);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff2a2a2a',endColorstr='#ff202020',GradientType=0)}body.nanotrasen .normal{color:#40628a}body.nanotrasen .good{color:#537d29}body.nanotrasen .average{color:#be6209}body.nanotrasen .bad{color:#b00e0e}body.nanotrasen .highlight{color:#8ba5c4}body.nanotrasen main{display:block;margin-top:32px;padding:2px 6px 0}body.nanotrasen hr{height:2px;background-color:#40628a;border:none}body.nanotrasen .hidden{display:none}body.nanotrasen .bar .barText,body.nanotrasen span.button{color:#fff;font-size:12px;font-weight:400;font-style:normal;text-decoration:none}body.nanotrasen .bold{font-weight:700}body.nanotrasen .italic{font-style:italic}body.nanotrasen [unselectable=on]{-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}body.nanotrasen div[data-tooltip],body.nanotrasen span[data-tooltip]{position:relative}body.nanotrasen div[data-tooltip]:after,body.nanotrasen span[data-tooltip]:after{position:absolute;display:block;z-index:2;width:250px;padding:10px;-ms-transform:translateX(-50%);transform:translateX(-50%);visibility:hidden;opacity:0;-ms-filter:"progid:DXImageTransform.Microsoft.Alpha(Opacity=0)";white-space:normal;text-align:left;content:attr(data-tooltip);transition:all .5s;border:1px solid #272727;background-color:#363636}body.nanotrasen div[data-tooltip]:hover:after,body.nanotrasen span[data-tooltip]:hover:after{visibility:visible;opacity:1;-ms-filter:"progid:DXImageTransform.Microsoft.Alpha(Opacity=100)"}body.nanotrasen div[data-tooltip].tooltip-top:after,body.nanotrasen span[data-tooltip].tooltip-top:after{bottom:100%;left:50%;-ms-transform:translateX(-50%) translateY(8px);transform:translateX(-50%) translateY(8px)}body.nanotrasen div[data-tooltip].tooltip-top:hover:after,body.nanotrasen span[data-tooltip].tooltip-top:hover:after{-ms-transform:translateX(-50%) translateY(-8px);transform:translateX(-50%) translateY(-8px)}body.nanotrasen div[data-tooltip].tooltip-bottom:after,body.nanotrasen span[data-tooltip].tooltip-bottom:after{top:100%;left:50%;-ms-transform:translateX(-50%) translateY(-8px);transform:translateX(-50%) translateY(-8px)}body.nanotrasen div[data-tooltip].tooltip-bottom:hover:after,body.nanotrasen span[data-tooltip].tooltip-bottom:hover:after{-ms-transform:translateX(-50%) translateY(8px);transform:translateX(-50%) translateY(8px)}body.nanotrasen div[data-tooltip].tooltip-left:after,body.nanotrasen span[data-tooltip].tooltip-left:after{top:50%;right:100%;-ms-transform:translateX(8px) translateY(-50%);transform:translateX(8px) translateY(-50%)}body.nanotrasen div[data-tooltip].tooltip-left:hover:after,body.nanotrasen span[data-tooltip].tooltip-left:hover:after{-ms-transform:translateX(-8px) translateY(-50%);transform:translateX(-8px) translateY(-50%)}body.nanotrasen div[data-tooltip].tooltip-right:after,body.nanotrasen span[data-tooltip].tooltip-right:after{top:50%;left:100%;-ms-transform:translateX(-8px) translateY(-50%);transform:translateX(-8px) translateY(-50%)}body.nanotrasen div[data-tooltip].tooltip-right:hover:after,body.nanotrasen span[data-tooltip].tooltip-right:hover:after{-ms-transform:translateX(8px) translateY(-50%);transform:translateX(8px) translateY(-50%)}body.nanotrasen .bar{display:inline-block;position:relative;vertical-align:middle;width:100%;height:20px;line-height:17px;padding:1px;border:1px solid #40628a;background:#272727}body.nanotrasen .bar .barText{position:absolute;top:0;right:3px}body.nanotrasen .bar .barFill{display:block;height:100%;transition:background-color 1s;background-color:#40628a}body.nanotrasen .bar .barFill.good{background-color:#537d29}body.nanotrasen .bar .barFill.average{background-color:#be6209}body.nanotrasen .bar .barFill.bad{background-color:#b00e0e}body.nanotrasen span.button{display:inline-block;vertical-align:middle;min-height:20px;line-height:17px;padding:0 5px;white-space:nowrap;border:1px solid #272727}body.nanotrasen span.button .fa{padding-right:2px}body.nanotrasen span.button.normal{transition:background-color .5s;background-color:#40628a}body.nanotrasen span.button.normal.active:focus,body.nanotrasen span.button.normal.active:hover{transition:background-color .25s;background-color:#4f78aa;outline:0}body.nanotrasen span.button.disabled{transition:background-color .5s;background-color:#999}body.nanotrasen span.button.disabled.active:focus,body.nanotrasen span.button.disabled.active:hover{transition:background-color .25s;background-color:#a8a8a8;outline:0}body.nanotrasen span.button.selected{transition:background-color .5s;background-color:#2f943c}body.nanotrasen span.button.selected.active:focus,body.nanotrasen span.button.selected.active:hover{transition:background-color .25s;background-color:#3ab84b;outline:0}body.nanotrasen span.button.toggle{transition:background-color .5s;background-color:#2f943c}body.nanotrasen span.button.toggle.active:focus,body.nanotrasen span.button.toggle.active:hover{transition:background-color .25s;background-color:#3ab84b;outline:0}body.nanotrasen span.button.caution{transition:background-color .5s;background-color:#9a9d00}body.nanotrasen span.button.caution.active:focus,body.nanotrasen span.button.caution.active:hover{transition:background-color .25s;background-color:#ced200;outline:0}body.nanotrasen span.button.danger{transition:background-color .5s;background-color:#9d0808}body.nanotrasen span.button.danger.active:focus,body.nanotrasen span.button.danger.active:hover{transition:background-color .25s;background-color:#ce0b0b;outline:0}body.nanotrasen span.button.gridable{width:125px;margin:2px 0}body.nanotrasen span.button.gridable.center{text-align:center;width:75px}body.nanotrasen span.button+span:not(.button),body.nanotrasen span:not(.button)+span.button{margin-left:5px}body.nanotrasen div.display{width:100%;padding:4px;margin:6px 0;background-color:#000;-ms-filter:"progid:DXImageTransform.Microsoft.gradient(startColorStr=#54000000,endColorStr=#54000000)";filter:progid:DXImageTransform.Microsoft.gradient(startColorStr=#54000000,endColorStr=#54000000);background-color:rgba(0,0,0,.33);box-shadow:inset 0 0 5px rgba(0,0,0,.5)}body.nanotrasen div.display.tabular{padding:0;margin:0}body.nanotrasen div.display header,body.nanotrasen div.subdisplay header{display:block;position:relative;width:100%;padding:0 4px;margin-bottom:6px;color:#fff;border-bottom:2px solid #40628a}body.nanotrasen div.display header .buttonRight,body.nanotrasen div.subdisplay header .buttonRight{position:absolute;bottom:6px;right:4px}body.nanotrasen div.display article,body.nanotrasen div.subdisplay article{display:table;width:100%;border-collapse:collapse}body.nanotrasen input{display:inline-block;vertical-align:middle;height:20px;line-height:17px;padding:0 5px;white-space:nowrap;color:#000;background-color:#fff;border:1px solid #272727}body.nanotrasen input.number{width:35px}body.nanotrasen input::-webkit-input-placeholder{color:#999}body.nanotrasen input::-moz-placeholder{color:#999}body.nanotrasen input:-ms-input-placeholder{color:#999}body.nanotrasen input::placeholder{color:#999}body.nanotrasen input::-ms-clear{display:none}body.nanotrasen svg.linegraph{overflow:hidden}body.nanotrasen div.notice{margin:8px 0;padding:4px;box-shadow:none;color:#000;font-weight:700;font-style:italic;background-color:#bb9b68;background-image:repeating-linear-gradient(-45deg,#bb9b68,#bb9b68 10px,#b1905d 0,#b1905d 20px)}body.nanotrasen div.notice .label{color:#000}body.nanotrasen div.notice .content:only-of-type{padding:0}body.nanotrasen div.notice hr{background-color:#272727}body.nanotrasen div.resize{position:fixed;bottom:0;right:0;width:0;height:0;border-style:solid;border-width:0 0 45px 45px;border-color:transparent transparent #363636;-ms-transform:rotate(1turn);transform:rotate(1turn)}body.nanotrasen section .cell,body.nanotrasen section .content,body.nanotrasen section .label,body.nanotrasen section .line,body.syndicate section .cell,body.syndicate section .content,body.syndicate section .label,body.syndicate section .line{display:table-cell;margin:0;text-align:left;vertical-align:middle;padding:3px 2px}body.nanotrasen section{display:table-row;width:100%}body.nanotrasen section:not(:first-child){padding-top:4px}body.nanotrasen section.candystripe:nth-child(even){background-color:#000;-ms-filter:"progid:DXImageTransform.Microsoft.gradient(startColorStr=#33000000,endColorStr=#33000000)";filter:progid:DXImageTransform.Microsoft.gradient(startColorStr=#33000000,endColorStr=#33000000);background-color:rgba(0,0,0,.2)}body.nanotrasen section .label{width:1%;padding-right:32px;white-space:nowrap;color:#8ba5c4}body.nanotrasen section .content:not(:last-child){padding-right:16px}body.nanotrasen section .line{width:100%}body.nanotrasen section .cell:not(:first-child){text-align:center;padding-top:0}body.nanotrasen section .cell span.button{width:75px}body.nanotrasen section:not(:last-child){padding-right:4px}body.nanotrasen div.subdisplay{width:100%;margin:0}body.nanotrasen header.titlebar .close,body.nanotrasen header.titlebar .minimize{display:inline-block;position:relative;padding:7px;margin:-7px;color:#8ba5c4}body.nanotrasen header.titlebar .close:hover,body.nanotrasen header.titlebar .minimize:hover{color:#9cb2cd}body.nanotrasen header.titlebar{position:fixed;z-index:1;top:0;left:0;width:100%;height:32px;background-color:#363636;border-bottom:1px solid #161616;box-shadow:0 3px 3px rgba(0,0,0,.1)}body.nanotrasen header.titlebar .statusicon{position:absolute;top:4px;left:12px;transition:color .5s}body.nanotrasen header.titlebar .title{position:absolute;top:6px;left:46px;color:#8ba5c4;font-size:16px;white-space:nowrap}body.nanotrasen header.titlebar .minimize{position:absolute;top:6px;right:46px}body.nanotrasen header.titlebar .close{position:absolute;top:4px;right:12px}body.syndicate{background:url("data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiIHN0YW5kYWxvbmU9Im5vIj8+DQo8c3ZnIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgdmVyc2lvbj0iMS4wIiB2aWV3Qm94PSIwIDAgMjAwIDI4OS43NDIiIG9wYWNpdHk9Ii4zMyI+DQogIDxwYXRoIGQ9Im0gOTMuNTM3Njc3LDAgYyAtMTguMTEzMTI1LDAgLTM0LjIyMDEzMywzLjExMTY0IC00OC4zMjM0ODQsOS4zMzQzNyAtMTMuOTY1MDkyLDYuMjIxNjcgLTI0LjYxMjQ0MiwxNS4wNzExNCAtMzEuOTQwNjUxLDI2LjU0NzEgLTcuMTg5OTM5OCwxMS4zMzc4OSAtMTAuMzAxMjI2NiwyNC43NDkxMSAtMTAuMzAxMjI2Niw0MC4yMzQ3OCAwLDEwLjY0NjYyIDIuNzI1MDAyNiwyMC40NjQ2NSA4LjE3NTExMTYsMjkuNDUyNTggNS42MTUyNzcsOC45ODY4NiAxNC4wMzgyNzcsMTcuMzUyMDQgMjUuMjY4ODIxLDI1LjA5NDM2IDExLjIzMDU0NCw3LjYwNTMxIDI2LjUwNzQyMSwxNS40MTgzNSA0NS44MzA1MTQsMjMuNDM3ODIgMTkuOTgzNzQ4LDguMjk1NTcgMzQuODQ4ODQ4LDE1LjU1NDcxIDQ0LjU5Mjk5OCwyMS43NzYzOCA5Ljc0NDE0LDYuMjIyNzMgMTYuNzYxNywxMi44NTg1IDIxLjA1NTcyLDE5LjkwOTUxIDQuMjk0MDQsNy4wNTIwOCA2LjQ0MTkzLDE1Ljc2NDA4IDYuNDQxOTMsMjYuMTM0NTkgMCwxNi4xNzcwMiAtNS4yMDE5NiwyOC40ODIyMiAtMTUuNjA2NzMsMzYuOTE2ODIgLTEwLjIzOTYsOC40MzQ3IC0yNS4wMjIwMywxMi42NTIzIC00NC4zNDUxNjksMTIuNjUyMyAtMTQuMDM4MTcxLDAgLTI1LjUxNTI0NywtMS42NTk0IC0zNC40MzM2MTgsLTQuOTc3NyAtOC45MTgzNywtMy40NTY2IC0xNi4xODU1NzIsLTguNzExMyAtMjEuODAwODM5LC0xNS43NjMzIC01LjYxNTI3NywtNy4wNTIxIC0xMC4wNzQ3OTUsLTE2LjY2MDg4IC0xMy4zNzc4OTksLTI4LjgyODEyIGwgLTI0Ljc3MzE2MjYyOTM5NDUsMCAwLDU2LjgyNjMyIEMgMzMuODU2NzY5LDI4Ni4wNzYwMSA2My43NDkwNCwyODkuNzQyMDEgODkuNjc4MzgzLDI4OS43NDIwMSBjIDE2LjAyMDAyNywwIDMwLjcxOTc4NywtMS4zODI3IDQ0LjA5NzMzNywtNC4xNDc5IDEzLjU0MjcyLC0yLjkwNDMgMjUuMTA0MSwtNy40Njc2IDM0LjY4MzA5LC0xMy42ODkzIDkuNzQ0MTMsLTYuMzU5NyAxNy4zNDA0MiwtMTQuNTE5NSAyMi43OTA1MiwtMjQuNDc0OCA1LjQ1MDEsLTEwLjA5MzMyIDguMTc1MTEsLTIyLjM5OTU5IDguMTc1MTEsLTM2LjkxNjgyIDAsLTEyLjk5NzY0IC0zLjMwMjEsLTI0LjMzNTM5IC05LjkwODI5LC0zNC4wMTQ2IC02LjQ0MTA1LC05LjgxNzI1IC0xNS41MjU0NSwtMTguNTI3MDcgLTI3LjI1MTQ2LC0yNi4xMzEzMyAtMTEuNTYwODUsLTcuNjA0MjcgLTI3LjkxMDgzLC0xNS44MzE0MiAtNDkuMDUwNjYsLTI0LjY4MDIyIC0xNy41MDY0NCwtNy4xOTAxMiAtMzAuNzE5NjY4LC0xMy42ODk0OCAtMzkuNjM4MDM4LC0xOS40OTcwMSAtOC45MTgzNzEsLTUuODA3NTIgLTE4LjYwNzQ3NCwtMTIuNDM0MDkgLTI0LjA5NjUyNCwtMTguODc0MTcgLTUuNDI2MDQzLC02LjM2NjE2IC05LjY1ODgyNiwtMTUuMDcwMDMgLTkuNjU4ODI2LC0yNC44ODcyOSAwLC05LjI2NDAxIDIuMDc1NDE0LC0xNy4yMTM0NSA2LjIyMzQ1NCwtMjMuODUwMzMgMTEuMDk4Mjk4LC0xNC4zOTc0OCA0MS4yODY2MzgsLTEuNzk1MDcgNDUuMDc1NjA5LDI0LjM0NzYyIDQuODM5MzkyLDYuNzc0OTEgOC44NDkzNSwxNi4yNDcyOSAxMi4wMjk1MTUsMjguNDE1NiBsIDIwLjUzMjM0LDAgMCwtNTUuOTk5NjcgYyAtNC40NzgyNSwtNS45MjQ0OCAtOS45NTQ4OCwtMTAuNjMyMjIgLTE1LjkwODM3LC0xNC4zNzQxMSAxLjY0MDU1LDAuNDc5MDUgMy4xOTAzOSwxLjAyMzc2IDQuNjM4NjUsMS42NDAyNCA2LjQ5ODYxLDIuNjI2MDcgMTIuMTY3OTMsNy4zMjc0NyAxNy4wMDczLDE0LjEwMzQ1IDQuODM5MzksNi43NzQ5MSA4Ljg0OTM1LDE2LjI0NTY3IDEyLjAyOTUyLDI4LjQxMzk3IDAsMCA4LjQ4MTI4LC0wLjEyODk0IDguNDg5NzgsLTAuMDAyIDAuNDE3NzYsNi40MTQ5NCAtMS43NTMzOSw5LjQ1Mjg2IC00LjEyMzQyLDEyLjU2MTA0IC0yLjQxNzQsMy4xNjk3OCAtNS4xNDQ4Niw2Ljc4OTczIC00LjAwMjc4LDEzLjAwMjkgMS41MDc4Niw4LjIwMzE4IDEwLjE4MzU0LDEwLjU5NjQyIDE0LjYyMTk0LDkuMzExNTQgLTMuMzE4NDIsLTAuNDk5MTEgLTUuMzE4NTUsLTEuNzQ5NDggLTUuMzE4NTUsLTEuNzQ5NDggMCwwIDEuODc2NDYsMC45OTg2OCA1LjY1MTE3LC0xLjM1OTgxIC0zLjI3Njk1LDAuOTU1NzEgLTEwLjcwNTI5LC0wLjc5NzM4IC0xMS44MDEyNSwtNi43NjMxMyAtMC45NTc1MiwtNS4yMDg2MSAwLjk0NjU0LC03LjI5NTE0IDMuNDAxMTMsLTEwLjUxNDgyIDIuNDU0NjIsLTMuMjE5NjggNS4yODQyNiwtNi45NTgzMSA0LjY4NDMsLTE0LjQ4ODI0IGwgMC4wMDMsMC4wMDIgOC45MjY3NiwwIDAsLTU1Ljk5OTY3IGMgLTE1LjA3MTI1LC0zLjg3MTY4IC0yNy42NTMxNCwtNi4zNjA0MiAtMzcuNzQ2NzEsLTcuNDY1ODYgLTkuOTU1MzEsLTEuMTA3NTUgLTIwLjE4ODIzLC0xLjY1OTgxIC0zMC42OTY2MTMsLTEuNjU5ODEgeiBtIDcwLjMyMTYwMywxNy4zMDg5MyAwLjIzODA1LDQwLjMwNDkgYyAxLjMxODA4LDEuMjI2NjYgMi40Mzk2NSwyLjI3ODE1IDMuMzQwODEsMy4xMDYwMiA0LjgzOTM5LDYuNzc0OTEgOC44NDkzNCwxNi4yNDU2NiAxMi4wMjk1MSwyOC40MTM5NyBsIDIwLjUzMjM0LDAgMCwtNTUuOTk5NjcgYyAtNi42NzczMSwtNC41OTM4MSAtMTkuODM2NDMsLTEwLjQ3MzA5IC0zNi4xNDA3MSwtMTUuODI1MjIgeiBtIC0yOC4xMjA0OSw1LjYwNTUxIDguNTY0NzksMTcuNzE2NTUgYyAtMTEuOTcwMzcsLTYuNDY2OTcgLTEzLjg0Njc4LC05LjcxNzI2IC04LjU2NDc5LC0xNy43MTY1NSB6IG0gMjIuNzk3MDUsMCBjIDIuNzcxNSw3Ljk5OTI5IDEuNzg3NDEsMTEuMjQ5NTggLTQuNDkzNTQsMTcuNzE2NTUgbCA0LjQ5MzU0LC0xNy43MTY1NSB6IG0gMTUuMjIxOTUsMjQuMDA4NDggOC41NjQ3OSwxNy43MTY1NSBjIC0xMS45NzAzOCwtNi40NjY5NyAtMTMuODQ2NzksLTkuNzE3MjYgLTguNTY0NzksLTE3LjcxNjU1IHogbSAyMi43OTcwNCwwIGMgMi43NzE1LDcuOTk5MjkgMS43ODc0MSwxMS4yNDk1OCAtNC40OTM1NCwxNy43MTY1NSBsIDQuNDkzNTQsLTE3LjcxNjU1IHogbSAtOTkuMTEzODQsMi4yMDc2NCA4LjU2NDc5LDE3LjcxNjU1IGMgLTExLjk3MDM4MiwtNi40NjY5NyAtMTMuODQ2NzgyLC05LjcxNzI2IC04LjU2NDc5LC0xNy43MTY1NSB6IG0gMjIuNzk1NDIsMCBjIDIuNzcxNSw3Ljk5OTI5IDEuNzg3NDEsMTEuMjQ5NTggLTQuNDkzNTQsMTcuNzE2NTUgbCA0LjQ5MzU0LC0xNy43MTY1NSB6IiAvPg0KPC9zdmc+DQo8IS0tIFRoaXMgd29yayBpcyBsaWNlbnNlZCB1bmRlciBhIENyZWF0aXZlIENvbW1vbnMgQXR0cmlidXRpb24tU2hhcmVBbGlrZSA0LjAgSW50ZXJuYXRpb25hbCBMaWNlbnNlLiAtLT4NCjwhLS0gaHR0cDovL2NyZWF0aXZlY29tbW9ucy5vcmcvbGljZW5zZXMvYnktc2EvNC4wLyAtLT4NCg==") no-repeat fixed 50%/70% 70%,linear-gradient(180deg,#750000 0,#340404);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff750000',endColorstr='#ff340404',GradientType=0)}body.syndicate .normal{color:#40628a}body.syndicate .good{color:#73e573}body.syndicate .average{color:#be6209}body.syndicate .bad{color:#b00e0e}body.syndicate .highlight{color:#000}body.syndicate main{display:block;margin-top:32px;padding:2px 6px 0}body.syndicate hr{height:2px;background-color:#272727;border:none}body.syndicate .hidden{display:none}body.syndicate .bar .barText,body.syndicate span.button{color:#fff;font-size:12px;font-weight:400;font-style:normal;text-decoration:none}body.syndicate .bold{font-weight:700}body.syndicate .italic{font-style:italic}body.syndicate [unselectable=on]{-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}body.syndicate div[data-tooltip],body.syndicate span[data-tooltip]{position:relative}body.syndicate div[data-tooltip]:after,body.syndicate span[data-tooltip]:after{position:absolute;display:block;z-index:2;width:250px;padding:10px;-ms-transform:translateX(-50%);transform:translateX(-50%);visibility:hidden;opacity:0;-ms-filter:"progid:DXImageTransform.Microsoft.Alpha(Opacity=0)";white-space:normal;text-align:left;content:attr(data-tooltip);transition:all .5s;border:1px solid #272727;background-color:#363636}body.syndicate div[data-tooltip]:hover:after,body.syndicate span[data-tooltip]:hover:after{visibility:visible;opacity:1;-ms-filter:"progid:DXImageTransform.Microsoft.Alpha(Opacity=100)"}body.syndicate div[data-tooltip].tooltip-top:after,body.syndicate span[data-tooltip].tooltip-top:after{bottom:100%;left:50%;-ms-transform:translateX(-50%) translateY(8px);transform:translateX(-50%) translateY(8px)}body.syndicate div[data-tooltip].tooltip-top:hover:after,body.syndicate span[data-tooltip].tooltip-top:hover:after{-ms-transform:translateX(-50%) translateY(-8px);transform:translateX(-50%) translateY(-8px)}body.syndicate div[data-tooltip].tooltip-bottom:after,body.syndicate span[data-tooltip].tooltip-bottom:after{top:100%;left:50%;-ms-transform:translateX(-50%) translateY(-8px);transform:translateX(-50%) translateY(-8px)}body.syndicate div[data-tooltip].tooltip-bottom:hover:after,body.syndicate span[data-tooltip].tooltip-bottom:hover:after{-ms-transform:translateX(-50%) translateY(8px);transform:translateX(-50%) translateY(8px)}body.syndicate div[data-tooltip].tooltip-left:after,body.syndicate span[data-tooltip].tooltip-left:after{top:50%;right:100%;-ms-transform:translateX(8px) translateY(-50%);transform:translateX(8px) translateY(-50%)}body.syndicate div[data-tooltip].tooltip-left:hover:after,body.syndicate span[data-tooltip].tooltip-left:hover:after{-ms-transform:translateX(-8px) translateY(-50%);transform:translateX(-8px) translateY(-50%)}body.syndicate div[data-tooltip].tooltip-right:after,body.syndicate span[data-tooltip].tooltip-right:after{top:50%;left:100%;-ms-transform:translateX(-8px) translateY(-50%);transform:translateX(-8px) translateY(-50%)}body.syndicate div[data-tooltip].tooltip-right:hover:after,body.syndicate span[data-tooltip].tooltip-right:hover:after{-ms-transform:translateX(8px) translateY(-50%);transform:translateX(8px) translateY(-50%)}body.syndicate .bar{display:inline-block;position:relative;vertical-align:middle;width:100%;height:20px;line-height:17px;padding:1px;border:1px solid #000;background:#272727}body.syndicate .bar .barText{position:absolute;top:0;right:3px}body.syndicate .bar .barFill{display:block;height:100%;transition:background-color 1s;background-color:#000}body.syndicate .bar .barFill.good{background-color:#73e573}body.syndicate .bar .barFill.average{background-color:#be6209}body.syndicate .bar .barFill.bad{background-color:#b00e0e}body.syndicate span.button{display:inline-block;vertical-align:middle;min-height:20px;line-height:17px;padding:0 5px;white-space:nowrap;border:1px solid #272727}body.syndicate span.button .fa{padding-right:2px}body.syndicate span.button.normal{transition:background-color .5s;background-color:#397439}body.syndicate span.button.normal.active:focus,body.syndicate span.button.normal.active:hover{transition:background-color .25s;background-color:#4a964a;outline:0}body.syndicate span.button.disabled{transition:background-color .5s;background-color:#363636}body.syndicate span.button.disabled.active:focus,body.syndicate span.button.disabled.active:hover{transition:background-color .25s;background-color:#545454;outline:0}body.syndicate span.button.selected{transition:background-color .5s;background-color:#9d0808}body.syndicate span.button.selected.active:focus,body.syndicate span.button.selected.active:hover{transition:background-color .25s;background-color:#ce0b0b;outline:0}body.syndicate span.button.toggle{transition:background-color .5s;background-color:#9d0808}body.syndicate span.button.toggle.active:focus,body.syndicate span.button.toggle.active:hover{transition:background-color .25s;background-color:#ce0b0b;outline:0}body.syndicate span.button.caution{transition:background-color .5s;background-color:#be6209}body.syndicate span.button.caution.active:focus,body.syndicate span.button.caution.active:hover{transition:background-color .25s;background-color:#eb790b;outline:0}body.syndicate span.button.danger{transition:background-color .5s;background-color:#9a9d00}body.syndicate span.button.danger.active:focus,body.syndicate span.button.danger.active:hover{transition:background-color .25s;background-color:#ced200;outline:0}body.syndicate span.button.gridable{width:125px;margin:2px 0}body.syndicate span.button.gridable.center{text-align:center;width:75px}body.syndicate span.button+span:not(.button),body.syndicate span:not(.button)+span.button{margin-left:5px}body.syndicate div.display{width:100%;padding:4px;margin:6px 0;background-color:#000;-ms-filter:"progid:DXImageTransform.Microsoft.gradient(startColorStr=#80000000,endColorStr=#80000000)";filter:progid:DXImageTransform.Microsoft.gradient(startColorStr=#80000000,endColorStr=#80000000);background-color:rgba(0,0,0,.5);box-shadow:inset 0 0 5px rgba(0,0,0,.75)}body.syndicate div.display.tabular{padding:0;margin:0}body.syndicate div.display header,body.syndicate div.subdisplay header{display:block;position:relative;width:100%;padding:0 4px;margin-bottom:6px;color:#fff;border-bottom:2px solid #272727}body.syndicate div.display header .buttonRight,body.syndicate div.subdisplay header .buttonRight{position:absolute;bottom:6px;right:4px}body.syndicate div.display article,body.syndicate div.subdisplay article{display:table;width:100%;border-collapse:collapse}body.syndicate input{display:inline-block;vertical-align:middle;height:20px;line-height:17px;padding:0 5px;white-space:nowrap;color:#fff;background-color:#9d0808;border:1px solid #272727}body.syndicate input.number{width:35px}body.syndicate input::-webkit-input-placeholder{color:#999}body.syndicate input::-moz-placeholder{color:#999}body.syndicate input:-ms-input-placeholder{color:#999}body.syndicate input::placeholder{color:#999}body.syndicate input::-ms-clear{display:none}body.syndicate svg.linegraph{overflow:hidden}body.syndicate div.notice{margin:8px 0;padding:4px;box-shadow:none;color:#000;font-weight:700;font-style:italic;background-color:#750000;background-image:repeating-linear-gradient(-45deg,#750000,#750000 10px,#910101 0,#910101 20px)}body.syndicate div.notice .label{color:#000}body.syndicate div.notice .content:only-of-type{padding:0}body.syndicate div.notice hr{background-color:#272727}body.syndicate div.resize{position:fixed;bottom:0;right:0;width:0;height:0;border-style:solid;border-width:0 0 45px 45px;border-color:transparent transparent #363636;-ms-transform:rotate(1turn);transform:rotate(1turn)}body.syndicate section .cell,body.syndicate section .content,body.syndicate section .label,body.syndicate section .line{display:table-cell;margin:0;text-align:left;vertical-align:middle;padding:3px 2px}body.syndicate section{display:table-row;width:100%}body.syndicate section:not(:first-child){padding-top:4px}body.syndicate section.candystripe:nth-child(even){background-color:#000;-ms-filter:"progid:DXImageTransform.Microsoft.gradient(startColorStr=#33000000,endColorStr=#33000000)";filter:progid:DXImageTransform.Microsoft.gradient(startColorStr=#33000000,endColorStr=#33000000);background-color:rgba(0,0,0,.2)}body.syndicate section .label{width:1%;padding-right:32px;white-space:nowrap;color:#fff}body.syndicate section .content:not(:last-child){padding-right:16px}body.syndicate section .line{width:100%}body.syndicate section .cell:not(:first-child){text-align:center;padding-top:0}body.syndicate section .cell span.button{width:75px}body.syndicate section:not(:last-child){padding-right:4px}body.syndicate div.subdisplay{width:100%;margin:0}body.syndicate header.titlebar .close,body.syndicate header.titlebar .minimize{display:inline-block;position:relative;padding:7px;margin:-7px;color:#e74242}body.syndicate header.titlebar .close:hover,body.syndicate header.titlebar .minimize:hover{color:#eb5e5e}body.syndicate header.titlebar{position:fixed;z-index:1;top:0;left:0;width:100%;height:32px;background-color:#363636;border-bottom:1px solid #161616;box-shadow:0 3px 3px rgba(0,0,0,.1)}body.syndicate header.titlebar .statusicon{position:absolute;top:4px;left:12px;transition:color .5s}body.syndicate header.titlebar .title{position:absolute;top:6px;left:46px;color:#e74242;font-size:16px;white-space:nowrap}body.syndicate header.titlebar .minimize{position:absolute;top:6px;right:46px}body.syndicate header.titlebar .close{position:absolute;top:4px;right:12px}.no-icons header.titlebar .statusicon{font-size:20px}.no-icons header.titlebar .statusicon:after{content:"O"}.no-icons header.titlebar .minimize{top:-2px;font-size:20px}.no-icons header.titlebar .minimize:after{content:"—"}.no-icons header.titlebar .close{font-size:20px}.no-icons header.titlebar .close:after{content:"X"} \ No newline at end of file +@charset "utf-8";body,html{box-sizing:border-box;height:100%;margin:0}html{overflow:hidden;cursor:default}body{overflow:auto;font-family:Verdana,Geneva,sans-serif;font-size:12px;color:#fff;background-color:#2a2a2a;background-image:linear-gradient(180deg,#2a2a2a 0,#202020);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr="#ff2a2a2a",endColorstr="#ff202020",GradientType=0)}*,:after,:before{box-sizing:inherit}h1,h2,h3,h4{display:inline-block;margin:0;padding:6px 0}h1{font-size:18px}h2{font-size:16px}h3{font-size:14px}h4{font-size:12px}body.clockwork{background:linear-gradient(180deg,#b18b25 0,#5f380e);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr="#ffb18b25",endColorstr="#ff5f380e",GradientType=0)}body.clockwork .normal{color:#b18b25}body.clockwork .good{color:#cfba47}body.clockwork .average{color:#896b19}body.clockwork .bad{color:#5f380e}body.clockwork .highlight{color:#b18b25}body.clockwork main{display:block;margin-top:32px;padding:2px 6px 0}body.clockwork hr{height:2px;background-color:#b18b25;border:none}body.clockwork .hidden{display:none}body.clockwork .bar .barText,body.clockwork span.button{color:#b18b25;font-size:12px;font-weight:400;font-style:normal;text-decoration:none}body.clockwork .bold{font-weight:700}body.clockwork .italic{font-style:italic}body.clockwork [unselectable=on]{-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}body.clockwork div[data-tooltip],body.clockwork span[data-tooltip]{position:relative}body.clockwork div[data-tooltip]:after,body.clockwork span[data-tooltip]:after{position:absolute;display:block;z-index:2;width:250px;padding:10px;-ms-transform:translateX(-50%);transform:translateX(-50%);visibility:hidden;opacity:0;-ms-filter:"progid:DXImageTransform.Microsoft.Alpha(Opacity=0)";white-space:normal;text-align:left;content:attr(data-tooltip);transition:all .5s;border:1px solid #170800;background-color:#2d1400}body.clockwork div[data-tooltip]:hover:after,body.clockwork span[data-tooltip]:hover:after{visibility:visible;opacity:1;-ms-filter:"progid:DXImageTransform.Microsoft.Alpha(Opacity=100)"}body.clockwork div[data-tooltip].tooltip-top:after,body.clockwork span[data-tooltip].tooltip-top:after{bottom:100%;left:50%;-ms-transform:translateX(-50%) translateY(8px);transform:translateX(-50%) translateY(8px)}body.clockwork div[data-tooltip].tooltip-top:hover:after,body.clockwork span[data-tooltip].tooltip-top:hover:after{-ms-transform:translateX(-50%) translateY(-8px);transform:translateX(-50%) translateY(-8px)}body.clockwork div[data-tooltip].tooltip-bottom:after,body.clockwork span[data-tooltip].tooltip-bottom:after{top:100%;left:50%;-ms-transform:translateX(-50%) translateY(-8px);transform:translateX(-50%) translateY(-8px)}body.clockwork div[data-tooltip].tooltip-bottom:hover:after,body.clockwork span[data-tooltip].tooltip-bottom:hover:after{-ms-transform:translateX(-50%) translateY(8px);transform:translateX(-50%) translateY(8px)}body.clockwork div[data-tooltip].tooltip-left:after,body.clockwork span[data-tooltip].tooltip-left:after{top:50%;right:100%;-ms-transform:translateX(8px) translateY(-50%);transform:translateX(8px) translateY(-50%)}body.clockwork div[data-tooltip].tooltip-left:hover:after,body.clockwork span[data-tooltip].tooltip-left:hover:after{-ms-transform:translateX(-8px) translateY(-50%);transform:translateX(-8px) translateY(-50%)}body.clockwork div[data-tooltip].tooltip-right:after,body.clockwork span[data-tooltip].tooltip-right:after{top:50%;left:100%;-ms-transform:translateX(-8px) translateY(-50%);transform:translateX(-8px) translateY(-50%)}body.clockwork div[data-tooltip].tooltip-right:hover:after,body.clockwork span[data-tooltip].tooltip-right:hover:after{-ms-transform:translateX(8px) translateY(-50%);transform:translateX(8px) translateY(-50%)}body.clockwork .bar{display:inline-block;position:relative;vertical-align:middle;width:100%;height:20px;line-height:17px;padding:1px;border:1px solid #170800;background:#2d1400}body.clockwork .bar .barText{position:absolute;top:0;right:3px}body.clockwork .bar .barFill{display:block;height:100%;transition:background-color 1s;background-color:#b18b25}body.clockwork .bar .barFill.good{background-color:#cfba47}body.clockwork .bar .barFill.average{background-color:#896b19}body.clockwork .bar .barFill.bad{background-color:#5f380e}body.clockwork span.button{display:inline-block;vertical-align:middle;min-height:20px;line-height:17px;padding:0 5px;white-space:nowrap;border:1px solid #170800}body.clockwork span.button .fa{padding-right:2px}body.clockwork span.button.normal{transition:background-color .5s;background-color:#5f380e}body.clockwork span.button.normal.active:focus,body.clockwork span.button.normal.active:hover{transition:background-color .25s;background-color:#704211;outline:0}body.clockwork span.button.disabled{transition:background-color .5s;background-color:#2d1400}body.clockwork span.button.disabled.active:focus,body.clockwork span.button.disabled.active:hover{transition:background-color .25s;background-color:#441e00;outline:0}body.clockwork span.button.selected{transition:background-color .5s;background-color:#cfba47}body.clockwork span.button.selected.active:focus,body.clockwork span.button.selected.active:hover{transition:background-color .25s;background-color:#d1bd50;outline:0}body.clockwork span.button.toggle{transition:background-color .5s;background-color:#cfba47}body.clockwork span.button.toggle.active:focus,body.clockwork span.button.toggle.active:hover{transition:background-color .25s;background-color:#d1bd50;outline:0}body.clockwork span.button.caution{transition:background-color .5s;background-color:#be6209}body.clockwork span.button.caution.active:focus,body.clockwork span.button.caution.active:hover{transition:background-color .25s;background-color:#cd6a0a;outline:0}body.clockwork span.button.danger{transition:background-color .5s;background-color:#9a9d00}body.clockwork span.button.danger.active:focus,body.clockwork span.button.danger.active:hover{transition:background-color .25s;background-color:#abaf00;outline:0}body.clockwork span.button.gridable{width:125px;margin:2px 0}body.clockwork span.button.gridable.center{text-align:center;width:75px}body.clockwork span.button+span:not(.button),body.clockwork span:not(.button)+span.button{margin-left:5px}body.clockwork div.display{width:100%;padding:4px;margin:6px 0;background-color:#2d1400;-ms-filter:"progid:DXImageTransform.Microsoft.gradient(startColorStr=#e62d1400,endColorStr=#e62d1400)";filter:progid:DXImageTransform.Microsoft.gradient(startColorStr=#e62d1400,endColorStr=#e62d1400);background-color:rgba(45,20,0,.9);box-shadow:inset 0 0 5px rgba(0,0,0,.3)}body.clockwork div.display.tabular{padding:0;margin:0}body.clockwork div.display header,body.clockwork div.subdisplay header{display:block;position:relative;width:100%;padding:0 4px;margin-bottom:6px;color:#cfba47;border-bottom:2px solid #b18b25}body.clockwork div.display header .buttonRight,body.clockwork div.subdisplay header .buttonRight{position:absolute;bottom:6px;right:4px}body.clockwork div.display article,body.clockwork div.subdisplay article{display:table;width:100%;border-collapse:collapse}body.clockwork input{display:inline-block;vertical-align:middle;height:20px;line-height:17px;padding:0 5px;white-space:nowrap;color:#b18b25;background-color:#cfba47;border:1px solid #272727}body.clockwork input.number{width:35px}body.clockwork input::-webkit-input-placeholder{color:#999}body.clockwork input:-ms-input-placeholder{color:#999}body.clockwork input::placeholder{color:#999}body.clockwork input::-ms-clear{display:none}body.clockwork svg.linegraph{overflow:hidden}body.clockwork div.notice{margin:8px 0;padding:4px;box-shadow:none;color:#2d1400;font-weight:700;font-style:italic;background-color:#000;background-image:repeating-linear-gradient(-45deg,#000,#000 10px,#170800 0,#170800 20px)}body.clockwork div.notice .label{color:#2d1400}body.clockwork div.notice .content:only-of-type{padding:0}body.clockwork div.notice hr{background-color:#896b19}body.clockwork div.resize{position:fixed;bottom:0;right:0;width:0;height:0;border-style:solid;border-width:0 0 45px 45px;border-color:transparent transparent #5f380e;-ms-transform:rotate(1turn);transform:rotate(1turn)}body.clockwork section .cell,body.clockwork section .content,body.clockwork section .label,body.clockwork section .line,body.nanotrasen section .cell,body.nanotrasen section .content,body.nanotrasen section .label,body.nanotrasen section .line,body.syndicate section .cell,body.syndicate section .content,body.syndicate section .label,body.syndicate section .line{display:table-cell;margin:0;text-align:left;vertical-align:middle;padding:3px 2px}body.clockwork section{display:table-row;width:100%}body.clockwork section:not(:first-child){padding-top:4px}body.clockwork section.candystripe:nth-child(2n){background-color:#000;-ms-filter:"progid:DXImageTransform.Microsoft.gradient(startColorStr=#33000000,endColorStr=#33000000)";filter:progid:DXImageTransform.Microsoft.gradient(startColorStr=#33000000,endColorStr=#33000000);background-color:rgba(0,0,0,.2)}body.clockwork section .label{width:1%;padding-right:32px;white-space:nowrap;color:#b18b25}body.clockwork section .content:not(:last-child){padding-right:16px}body.clockwork section .line{width:100%}body.clockwork section .cell:not(:first-child){text-align:center;padding-top:0}body.clockwork section .cell span.button{width:75px}body.clockwork section:not(:last-child){padding-right:4px}body.clockwork div.subdisplay{width:100%;margin:0}body.clockwork header.titlebar .close,body.clockwork header.titlebar .minimize{display:inline-block;position:relative;padding:7px;margin:-7px;color:#cfba47}body.clockwork header.titlebar .close:hover,body.clockwork header.titlebar .minimize:hover{color:#d1bd50}body.clockwork header.titlebar{position:fixed;z-index:1;top:0;left:0;width:100%;height:32px;background-color:#5f380e;border-bottom:1px solid #170800;box-shadow:0 3px 3px rgba(0,0,0,.1)}body.clockwork header.titlebar .statusicon{position:absolute;top:4px;left:12px;transition:color .5s}body.clockwork header.titlebar .title{position:absolute;top:6px;left:46px;color:#cfba47;font-size:16px;white-space:nowrap}body.clockwork header.titlebar .minimize{position:absolute;top:6px;right:46px}body.clockwork header.titlebar .close{position:absolute;top:4px;right:12px}body.nanotrasen{background:url("data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiIHN0YW5kYWxvbmU9Im5vIj8+DQo8c3ZnIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgdmVyc2lvbj0iMS4wIiB2aWV3Qm94PSIwIDAgNDI1IDIwMCIgb3BhY2l0eT0iLjMzIj4NCiAgPHBhdGggZD0ibSAxNzguMDAzOTksMC4wMzg2OSAtNzEuMjAzOTMsMCBhIDYuNzYxMzQyMiw2LjAyNTU0OTUgMCAwIDAgLTYuNzYxMzQsNi4wMjU1NSBsIDAsMTg3Ljg3MTQ3IGEgNi43NjEzNDIyLDYuMDI1NTQ5NSAwIDAgMCA2Ljc2MTM0LDYuMDI1NTQgbCA1My4xMDcyLDAgYSA2Ljc2MTM0MjIsNi4wMjU1NDk1IDAgMCAwIDYuNzYxMzUsLTYuMDI1NTQgbCAwLC0xMDEuNTQ0MDE4IDcyLjIxNjI4LDEwNC42OTkzOTggYSA2Ljc2MTM0MjIsNi4wMjU1NDk1IDAgMCAwIDUuNzYwMTUsMi44NzAxNiBsIDczLjU1NDg3LDAgYSA2Ljc2MTM0MjIsNi4wMjU1NDk1IDAgMCAwIDYuNzYxMzUsLTYuMDI1NTQgbCAwLC0xODcuODcxNDcgYSA2Ljc2MTM0MjIsNi4wMjU1NDk1IDAgMCAwIC02Ljc2MTM1LC02LjAyNTU1IGwgLTU0LjcxNjQ0LDAgYSA2Ljc2MTM0MjIsNi4wMjU1NDk1IDAgMCAwIC02Ljc2MTMzLDYuMDI1NTUgbCAwLDEwMi42MTkzNSBMIDE4My43NjQxMywyLjkwODg2IGEgNi43NjEzNDIyLDYuMDI1NTQ5NSAwIDAgMCAtNS43NjAxNCwtMi44NzAxNyB6IiAvPg0KICA8cGF0aCBkPSJNIDQuODQ0NjMzMywyMi4xMDg3NSBBIDEzLjQxMjAzOSwxMi41MDE4NDIgMCAwIDEgMTMuNDc3NTg4LDAuMDM5MjQgbCA2Ni4xMTgzMTUsMCBhIDUuMzY0ODE1OCw1LjAwMDczNyAwIDAgMSA1LjM2NDgyMyw1LjAwMDczIGwgMCw3OS44NzkzMSB6IiAvPg0KICA8cGF0aCBkPSJtIDQyMC4xNTUzNSwxNzcuODkxMTkgYSAxMy40MTIwMzgsMTIuNTAxODQyIDAgMCAxIC04LjYzMjk1LDIyLjA2OTUxIGwgLTY2LjExODMyLDAgYSA1LjM2NDgxNTIsNS4wMDA3MzcgMCAwIDEgLTUuMzY0ODIsLTUuMDAwNzQgbCAwLC03OS44NzkzMSB6IiAvPg0KPC9zdmc+DQo8IS0tIFRoaXMgd29yayBpcyBsaWNlbnNlZCB1bmRlciBhIENyZWF0aXZlIENvbW1vbnMgQXR0cmlidXRpb24tU2hhcmVBbGlrZSA0LjAgSW50ZXJuYXRpb25hbCBMaWNlbnNlLiAtLT4NCjwhLS0gaHR0cDovL2NyZWF0aXZlY29tbW9ucy5vcmcvbGljZW5zZXMvYnktc2EvNC4wLyAtLT4NCg==") no-repeat fixed 50%/70% 70%,linear-gradient(180deg,#2a2a2a 0,#202020);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr="#ff2a2a2a",endColorstr="#ff202020",GradientType=0)}body.nanotrasen .normal{color:#40628a}body.nanotrasen .good{color:#537d29}body.nanotrasen .average{color:#be6209}body.nanotrasen .bad{color:#b00e0e}body.nanotrasen .highlight{color:#8ba5c4}body.nanotrasen main{display:block;margin-top:32px;padding:2px 6px 0}body.nanotrasen hr{height:2px;background-color:#40628a;border:none}body.nanotrasen .hidden{display:none}body.nanotrasen .bar .barText,body.nanotrasen span.button{color:#fff;font-size:12px;font-weight:400;font-style:normal;text-decoration:none}body.nanotrasen .bold{font-weight:700}body.nanotrasen .italic{font-style:italic}body.nanotrasen [unselectable=on]{-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}body.nanotrasen div[data-tooltip],body.nanotrasen span[data-tooltip]{position:relative}body.nanotrasen div[data-tooltip]:after,body.nanotrasen span[data-tooltip]:after{position:absolute;display:block;z-index:2;width:250px;padding:10px;-ms-transform:translateX(-50%);transform:translateX(-50%);visibility:hidden;opacity:0;-ms-filter:"progid:DXImageTransform.Microsoft.Alpha(Opacity=0)";white-space:normal;text-align:left;content:attr(data-tooltip);transition:all .5s;border:1px solid #272727;background-color:#363636}body.nanotrasen div[data-tooltip]:hover:after,body.nanotrasen span[data-tooltip]:hover:after{visibility:visible;opacity:1;-ms-filter:"progid:DXImageTransform.Microsoft.Alpha(Opacity=100)"}body.nanotrasen div[data-tooltip].tooltip-top:after,body.nanotrasen span[data-tooltip].tooltip-top:after{bottom:100%;left:50%;-ms-transform:translateX(-50%) translateY(8px);transform:translateX(-50%) translateY(8px)}body.nanotrasen div[data-tooltip].tooltip-top:hover:after,body.nanotrasen span[data-tooltip].tooltip-top:hover:after{-ms-transform:translateX(-50%) translateY(-8px);transform:translateX(-50%) translateY(-8px)}body.nanotrasen div[data-tooltip].tooltip-bottom:after,body.nanotrasen span[data-tooltip].tooltip-bottom:after{top:100%;left:50%;-ms-transform:translateX(-50%) translateY(-8px);transform:translateX(-50%) translateY(-8px)}body.nanotrasen div[data-tooltip].tooltip-bottom:hover:after,body.nanotrasen span[data-tooltip].tooltip-bottom:hover:after{-ms-transform:translateX(-50%) translateY(8px);transform:translateX(-50%) translateY(8px)}body.nanotrasen div[data-tooltip].tooltip-left:after,body.nanotrasen span[data-tooltip].tooltip-left:after{top:50%;right:100%;-ms-transform:translateX(8px) translateY(-50%);transform:translateX(8px) translateY(-50%)}body.nanotrasen div[data-tooltip].tooltip-left:hover:after,body.nanotrasen span[data-tooltip].tooltip-left:hover:after{-ms-transform:translateX(-8px) translateY(-50%);transform:translateX(-8px) translateY(-50%)}body.nanotrasen div[data-tooltip].tooltip-right:after,body.nanotrasen span[data-tooltip].tooltip-right:after{top:50%;left:100%;-ms-transform:translateX(-8px) translateY(-50%);transform:translateX(-8px) translateY(-50%)}body.nanotrasen div[data-tooltip].tooltip-right:hover:after,body.nanotrasen span[data-tooltip].tooltip-right:hover:after{-ms-transform:translateX(8px) translateY(-50%);transform:translateX(8px) translateY(-50%)}body.nanotrasen .bar{display:inline-block;position:relative;vertical-align:middle;width:100%;height:20px;line-height:17px;padding:1px;border:1px solid #40628a;background:#272727}body.nanotrasen .bar .barText{position:absolute;top:0;right:3px}body.nanotrasen .bar .barFill{display:block;height:100%;transition:background-color 1s;background-color:#40628a}body.nanotrasen .bar .barFill.good{background-color:#537d29}body.nanotrasen .bar .barFill.average{background-color:#be6209}body.nanotrasen .bar .barFill.bad{background-color:#b00e0e}body.nanotrasen span.button{display:inline-block;vertical-align:middle;min-height:20px;line-height:17px;padding:0 5px;white-space:nowrap;border:1px solid #272727}body.nanotrasen span.button .fa{padding-right:2px}body.nanotrasen span.button.normal{transition:background-color .5s;background-color:#40628a}body.nanotrasen span.button.normal.active:focus,body.nanotrasen span.button.normal.active:hover{transition:background-color .25s;background-color:#4f78aa;outline:0}body.nanotrasen span.button.disabled{transition:background-color .5s;background-color:#999}body.nanotrasen span.button.disabled.active:focus,body.nanotrasen span.button.disabled.active:hover{transition:background-color .25s;background-color:#a8a8a8;outline:0}body.nanotrasen span.button.selected{transition:background-color .5s;background-color:#2f943c}body.nanotrasen span.button.selected.active:focus,body.nanotrasen span.button.selected.active:hover{transition:background-color .25s;background-color:#3ab84b;outline:0}body.nanotrasen span.button.toggle{transition:background-color .5s;background-color:#2f943c}body.nanotrasen span.button.toggle.active:focus,body.nanotrasen span.button.toggle.active:hover{transition:background-color .25s;background-color:#3ab84b;outline:0}body.nanotrasen span.button.caution{transition:background-color .5s;background-color:#9a9d00}body.nanotrasen span.button.caution.active:focus,body.nanotrasen span.button.caution.active:hover{transition:background-color .25s;background-color:#ced200;outline:0}body.nanotrasen span.button.danger{transition:background-color .5s;background-color:#9d0808}body.nanotrasen span.button.danger.active:focus,body.nanotrasen span.button.danger.active:hover{transition:background-color .25s;background-color:#ce0b0b;outline:0}body.nanotrasen span.button.gridable{width:125px;margin:2px 0}body.nanotrasen span.button.gridable.center{text-align:center;width:75px}body.nanotrasen span.button+span:not(.button),body.nanotrasen span:not(.button)+span.button{margin-left:5px}body.nanotrasen div.display{width:100%;padding:4px;margin:6px 0;background-color:#000;-ms-filter:"progid:DXImageTransform.Microsoft.gradient(startColorStr=#54000000,endColorStr=#54000000)";filter:progid:DXImageTransform.Microsoft.gradient(startColorStr=#54000000,endColorStr=#54000000);background-color:rgba(0,0,0,.33);box-shadow:inset 0 0 5px rgba(0,0,0,.5)}body.nanotrasen div.display.tabular{padding:0;margin:0}body.nanotrasen div.display header,body.nanotrasen div.subdisplay header{display:block;position:relative;width:100%;padding:0 4px;margin-bottom:6px;color:#fff;border-bottom:2px solid #40628a}body.nanotrasen div.display header .buttonRight,body.nanotrasen div.subdisplay header .buttonRight{position:absolute;bottom:6px;right:4px}body.nanotrasen div.display article,body.nanotrasen div.subdisplay article{display:table;width:100%;border-collapse:collapse}body.nanotrasen input{display:inline-block;vertical-align:middle;height:20px;line-height:17px;padding:0 5px;white-space:nowrap;color:#000;background-color:#fff;border:1px solid #272727}body.nanotrasen input.number{width:35px}body.nanotrasen input::-webkit-input-placeholder{color:#999}body.nanotrasen input:-ms-input-placeholder{color:#999}body.nanotrasen input::placeholder{color:#999}body.nanotrasen input::-ms-clear{display:none}body.nanotrasen svg.linegraph{overflow:hidden}body.nanotrasen div.notice{margin:8px 0;padding:4px;box-shadow:none;color:#000;font-weight:700;font-style:italic;background-color:#bb9b68;background-image:repeating-linear-gradient(-45deg,#bb9b68,#bb9b68 10px,#b1905d 0,#b1905d 20px)}body.nanotrasen div.notice .label{color:#000}body.nanotrasen div.notice .content:only-of-type{padding:0}body.nanotrasen div.notice hr{background-color:#272727}body.nanotrasen div.resize{position:fixed;bottom:0;right:0;width:0;height:0;border-style:solid;border-width:0 0 45px 45px;border-color:transparent transparent #363636;-ms-transform:rotate(1turn);transform:rotate(1turn)}body.nanotrasen section .cell,body.nanotrasen section .content,body.nanotrasen section .label,body.nanotrasen section .line,body.syndicate section .cell,body.syndicate section .content,body.syndicate section .label,body.syndicate section .line{display:table-cell;margin:0;text-align:left;vertical-align:middle;padding:3px 2px}body.nanotrasen section{display:table-row;width:100%}body.nanotrasen section:not(:first-child){padding-top:4px}body.nanotrasen section.candystripe:nth-child(2n){background-color:#000;-ms-filter:"progid:DXImageTransform.Microsoft.gradient(startColorStr=#33000000,endColorStr=#33000000)";filter:progid:DXImageTransform.Microsoft.gradient(startColorStr=#33000000,endColorStr=#33000000);background-color:rgba(0,0,0,.2)}body.nanotrasen section .label{width:1%;padding-right:32px;white-space:nowrap;color:#8ba5c4}body.nanotrasen section .content:not(:last-child){padding-right:16px}body.nanotrasen section .line{width:100%}body.nanotrasen section .cell:not(:first-child){text-align:center;padding-top:0}body.nanotrasen section .cell span.button{width:75px}body.nanotrasen section:not(:last-child){padding-right:4px}body.nanotrasen div.subdisplay{width:100%;margin:0}body.nanotrasen header.titlebar .close,body.nanotrasen header.titlebar .minimize{display:inline-block;position:relative;padding:7px;margin:-7px;color:#8ba5c4}body.nanotrasen header.titlebar .close:hover,body.nanotrasen header.titlebar .minimize:hover{color:#9cb2cd}body.nanotrasen header.titlebar{position:fixed;z-index:1;top:0;left:0;width:100%;height:32px;background-color:#363636;border-bottom:1px solid #161616;box-shadow:0 3px 3px rgba(0,0,0,.1)}body.nanotrasen header.titlebar .statusicon{position:absolute;top:4px;left:12px;transition:color .5s}body.nanotrasen header.titlebar .title{position:absolute;top:6px;left:46px;color:#8ba5c4;font-size:16px;white-space:nowrap}body.nanotrasen header.titlebar .minimize{position:absolute;top:6px;right:46px}body.nanotrasen header.titlebar .close{position:absolute;top:4px;right:12px}body.syndicate{background:url("data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiIHN0YW5kYWxvbmU9Im5vIj8+DQo8c3ZnIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgdmVyc2lvbj0iMS4wIiB2aWV3Qm94PSIwIDAgMjAwIDI4OS43NDIiIG9wYWNpdHk9Ii4zMyI+DQogIDxwYXRoIGQ9Im0gOTMuNTM3Njc3LDAgYyAtMTguMTEzMTI1LDAgLTM0LjIyMDEzMywzLjExMTY0IC00OC4zMjM0ODQsOS4zMzQzNyAtMTMuOTY1MDkyLDYuMjIxNjcgLTI0LjYxMjQ0MiwxNS4wNzExNCAtMzEuOTQwNjUxLDI2LjU0NzEgLTcuMTg5OTM5OCwxMS4zMzc4OSAtMTAuMzAxMjI2NiwyNC43NDkxMSAtMTAuMzAxMjI2Niw0MC4yMzQ3OCAwLDEwLjY0NjYyIDIuNzI1MDAyNiwyMC40NjQ2NSA4LjE3NTExMTYsMjkuNDUyNTggNS42MTUyNzcsOC45ODY4NiAxNC4wMzgyNzcsMTcuMzUyMDQgMjUuMjY4ODIxLDI1LjA5NDM2IDExLjIzMDU0NCw3LjYwNTMxIDI2LjUwNzQyMSwxNS40MTgzNSA0NS44MzA1MTQsMjMuNDM3ODIgMTkuOTgzNzQ4LDguMjk1NTcgMzQuODQ4ODQ4LDE1LjU1NDcxIDQ0LjU5Mjk5OCwyMS43NzYzOCA5Ljc0NDE0LDYuMjIyNzMgMTYuNzYxNywxMi44NTg1IDIxLjA1NTcyLDE5LjkwOTUxIDQuMjk0MDQsNy4wNTIwOCA2LjQ0MTkzLDE1Ljc2NDA4IDYuNDQxOTMsMjYuMTM0NTkgMCwxNi4xNzcwMiAtNS4yMDE5NiwyOC40ODIyMiAtMTUuNjA2NzMsMzYuOTE2ODIgLTEwLjIzOTYsOC40MzQ3IC0yNS4wMjIwMywxMi42NTIzIC00NC4zNDUxNjksMTIuNjUyMyAtMTQuMDM4MTcxLDAgLTI1LjUxNTI0NywtMS42NTk0IC0zNC40MzM2MTgsLTQuOTc3NyAtOC45MTgzNywtMy40NTY2IC0xNi4xODU1NzIsLTguNzExMyAtMjEuODAwODM5LC0xNS43NjMzIC01LjYxNTI3NywtNy4wNTIxIC0xMC4wNzQ3OTUsLTE2LjY2MDg4IC0xMy4zNzc4OTksLTI4LjgyODEyIGwgLTI0Ljc3MzE2MjYyOTM5NDUsMCAwLDU2LjgyNjMyIEMgMzMuODU2NzY5LDI4Ni4wNzYwMSA2My43NDkwNCwyODkuNzQyMDEgODkuNjc4MzgzLDI4OS43NDIwMSBjIDE2LjAyMDAyNywwIDMwLjcxOTc4NywtMS4zODI3IDQ0LjA5NzMzNywtNC4xNDc5IDEzLjU0MjcyLC0yLjkwNDMgMjUuMTA0MSwtNy40Njc2IDM0LjY4MzA5LC0xMy42ODkzIDkuNzQ0MTMsLTYuMzU5NyAxNy4zNDA0MiwtMTQuNTE5NSAyMi43OTA1MiwtMjQuNDc0OCA1LjQ1MDEsLTEwLjA5MzMyIDguMTc1MTEsLTIyLjM5OTU5IDguMTc1MTEsLTM2LjkxNjgyIDAsLTEyLjk5NzY0IC0zLjMwMjEsLTI0LjMzNTM5IC05LjkwODI5LC0zNC4wMTQ2IC02LjQ0MTA1LC05LjgxNzI1IC0xNS41MjU0NSwtMTguNTI3MDcgLTI3LjI1MTQ2LC0yNi4xMzEzMyAtMTEuNTYwODUsLTcuNjA0MjcgLTI3LjkxMDgzLC0xNS44MzE0MiAtNDkuMDUwNjYsLTI0LjY4MDIyIC0xNy41MDY0NCwtNy4xOTAxMiAtMzAuNzE5NjY4LC0xMy42ODk0OCAtMzkuNjM4MDM4LC0xOS40OTcwMSAtOC45MTgzNzEsLTUuODA3NTIgLTE4LjYwNzQ3NCwtMTIuNDM0MDkgLTI0LjA5NjUyNCwtMTguODc0MTcgLTUuNDI2MDQzLC02LjM2NjE2IC05LjY1ODgyNiwtMTUuMDcwMDMgLTkuNjU4ODI2LC0yNC44ODcyOSAwLC05LjI2NDAxIDIuMDc1NDE0LC0xNy4yMTM0NSA2LjIyMzQ1NCwtMjMuODUwMzMgMTEuMDk4Mjk4LC0xNC4zOTc0OCA0MS4yODY2MzgsLTEuNzk1MDcgNDUuMDc1NjA5LDI0LjM0NzYyIDQuODM5MzkyLDYuNzc0OTEgOC44NDkzNSwxNi4yNDcyOSAxMi4wMjk1MTUsMjguNDE1NiBsIDIwLjUzMjM0LDAgMCwtNTUuOTk5NjcgYyAtNC40NzgyNSwtNS45MjQ0OCAtOS45NTQ4OCwtMTAuNjMyMjIgLTE1LjkwODM3LC0xNC4zNzQxMSAxLjY0MDU1LDAuNDc5MDUgMy4xOTAzOSwxLjAyMzc2IDQuNjM4NjUsMS42NDAyNCA2LjQ5ODYxLDIuNjI2MDcgMTIuMTY3OTMsNy4zMjc0NyAxNy4wMDczLDE0LjEwMzQ1IDQuODM5MzksNi43NzQ5MSA4Ljg0OTM1LDE2LjI0NTY3IDEyLjAyOTUyLDI4LjQxMzk3IDAsMCA4LjQ4MTI4LC0wLjEyODk0IDguNDg5NzgsLTAuMDAyIDAuNDE3NzYsNi40MTQ5NCAtMS43NTMzOSw5LjQ1Mjg2IC00LjEyMzQyLDEyLjU2MTA0IC0yLjQxNzQsMy4xNjk3OCAtNS4xNDQ4Niw2Ljc4OTczIC00LjAwMjc4LDEzLjAwMjkgMS41MDc4Niw4LjIwMzE4IDEwLjE4MzU0LDEwLjU5NjQyIDE0LjYyMTk0LDkuMzExNTQgLTMuMzE4NDIsLTAuNDk5MTEgLTUuMzE4NTUsLTEuNzQ5NDggLTUuMzE4NTUsLTEuNzQ5NDggMCwwIDEuODc2NDYsMC45OTg2OCA1LjY1MTE3LC0xLjM1OTgxIC0zLjI3Njk1LDAuOTU1NzEgLTEwLjcwNTI5LC0wLjc5NzM4IC0xMS44MDEyNSwtNi43NjMxMyAtMC45NTc1MiwtNS4yMDg2MSAwLjk0NjU0LC03LjI5NTE0IDMuNDAxMTMsLTEwLjUxNDgyIDIuNDU0NjIsLTMuMjE5NjggNS4yODQyNiwtNi45NTgzMSA0LjY4NDMsLTE0LjQ4ODI0IGwgMC4wMDMsMC4wMDIgOC45MjY3NiwwIDAsLTU1Ljk5OTY3IGMgLTE1LjA3MTI1LC0zLjg3MTY4IC0yNy42NTMxNCwtNi4zNjA0MiAtMzcuNzQ2NzEsLTcuNDY1ODYgLTkuOTU1MzEsLTEuMTA3NTUgLTIwLjE4ODIzLC0xLjY1OTgxIC0zMC42OTY2MTMsLTEuNjU5ODEgeiBtIDcwLjMyMTYwMywxNy4zMDg5MyAwLjIzODA1LDQwLjMwNDkgYyAxLjMxODA4LDEuMjI2NjYgMi40Mzk2NSwyLjI3ODE1IDMuMzQwODEsMy4xMDYwMiA0LjgzOTM5LDYuNzc0OTEgOC44NDkzNCwxNi4yNDU2NiAxMi4wMjk1MSwyOC40MTM5NyBsIDIwLjUzMjM0LDAgMCwtNTUuOTk5NjcgYyAtNi42NzczMSwtNC41OTM4MSAtMTkuODM2NDMsLTEwLjQ3MzA5IC0zNi4xNDA3MSwtMTUuODI1MjIgeiBtIC0yOC4xMjA0OSw1LjYwNTUxIDguNTY0NzksMTcuNzE2NTUgYyAtMTEuOTcwMzcsLTYuNDY2OTcgLTEzLjg0Njc4LC05LjcxNzI2IC04LjU2NDc5LC0xNy43MTY1NSB6IG0gMjIuNzk3MDUsMCBjIDIuNzcxNSw3Ljk5OTI5IDEuNzg3NDEsMTEuMjQ5NTggLTQuNDkzNTQsMTcuNzE2NTUgbCA0LjQ5MzU0LC0xNy43MTY1NSB6IG0gMTUuMjIxOTUsMjQuMDA4NDggOC41NjQ3OSwxNy43MTY1NSBjIC0xMS45NzAzOCwtNi40NjY5NyAtMTMuODQ2NzksLTkuNzE3MjYgLTguNTY0NzksLTE3LjcxNjU1IHogbSAyMi43OTcwNCwwIGMgMi43NzE1LDcuOTk5MjkgMS43ODc0MSwxMS4yNDk1OCAtNC40OTM1NCwxNy43MTY1NSBsIDQuNDkzNTQsLTE3LjcxNjU1IHogbSAtOTkuMTEzODQsMi4yMDc2NCA4LjU2NDc5LDE3LjcxNjU1IGMgLTExLjk3MDM4MiwtNi40NjY5NyAtMTMuODQ2NzgyLC05LjcxNzI2IC04LjU2NDc5LC0xNy43MTY1NSB6IG0gMjIuNzk1NDIsMCBjIDIuNzcxNSw3Ljk5OTI5IDEuNzg3NDEsMTEuMjQ5NTggLTQuNDkzNTQsMTcuNzE2NTUgbCA0LjQ5MzU0LC0xNy43MTY1NSB6IiAvPg0KPC9zdmc+DQo8IS0tIFRoaXMgd29yayBpcyBsaWNlbnNlZCB1bmRlciBhIENyZWF0aXZlIENvbW1vbnMgQXR0cmlidXRpb24tU2hhcmVBbGlrZSA0LjAgSW50ZXJuYXRpb25hbCBMaWNlbnNlLiAtLT4NCjwhLS0gaHR0cDovL2NyZWF0aXZlY29tbW9ucy5vcmcvbGljZW5zZXMvYnktc2EvNC4wLyAtLT4NCg==") no-repeat fixed 50%/70% 70%,linear-gradient(180deg,#750000 0,#340404);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr="#ff750000",endColorstr="#ff340404",GradientType=0)}body.syndicate .normal{color:#40628a}body.syndicate .good{color:#73e573}body.syndicate .average{color:#be6209}body.syndicate .bad{color:#b00e0e}body.syndicate .highlight{color:#000}body.syndicate main{display:block;margin-top:32px;padding:2px 6px 0}body.syndicate hr{height:2px;background-color:#272727;border:none}body.syndicate .hidden{display:none}body.syndicate .bar .barText,body.syndicate span.button{color:#fff;font-size:12px;font-weight:400;font-style:normal;text-decoration:none}body.syndicate .bold{font-weight:700}body.syndicate .italic{font-style:italic}body.syndicate [unselectable=on]{-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}body.syndicate div[data-tooltip],body.syndicate span[data-tooltip]{position:relative}body.syndicate div[data-tooltip]:after,body.syndicate span[data-tooltip]:after{position:absolute;display:block;z-index:2;width:250px;padding:10px;-ms-transform:translateX(-50%);transform:translateX(-50%);visibility:hidden;opacity:0;-ms-filter:"progid:DXImageTransform.Microsoft.Alpha(Opacity=0)";white-space:normal;text-align:left;content:attr(data-tooltip);transition:all .5s;border:1px solid #272727;background-color:#363636}body.syndicate div[data-tooltip]:hover:after,body.syndicate span[data-tooltip]:hover:after{visibility:visible;opacity:1;-ms-filter:"progid:DXImageTransform.Microsoft.Alpha(Opacity=100)"}body.syndicate div[data-tooltip].tooltip-top:after,body.syndicate span[data-tooltip].tooltip-top:after{bottom:100%;left:50%;-ms-transform:translateX(-50%) translateY(8px);transform:translateX(-50%) translateY(8px)}body.syndicate div[data-tooltip].tooltip-top:hover:after,body.syndicate span[data-tooltip].tooltip-top:hover:after{-ms-transform:translateX(-50%) translateY(-8px);transform:translateX(-50%) translateY(-8px)}body.syndicate div[data-tooltip].tooltip-bottom:after,body.syndicate span[data-tooltip].tooltip-bottom:after{top:100%;left:50%;-ms-transform:translateX(-50%) translateY(-8px);transform:translateX(-50%) translateY(-8px)}body.syndicate div[data-tooltip].tooltip-bottom:hover:after,body.syndicate span[data-tooltip].tooltip-bottom:hover:after{-ms-transform:translateX(-50%) translateY(8px);transform:translateX(-50%) translateY(8px)}body.syndicate div[data-tooltip].tooltip-left:after,body.syndicate span[data-tooltip].tooltip-left:after{top:50%;right:100%;-ms-transform:translateX(8px) translateY(-50%);transform:translateX(8px) translateY(-50%)}body.syndicate div[data-tooltip].tooltip-left:hover:after,body.syndicate span[data-tooltip].tooltip-left:hover:after{-ms-transform:translateX(-8px) translateY(-50%);transform:translateX(-8px) translateY(-50%)}body.syndicate div[data-tooltip].tooltip-right:after,body.syndicate span[data-tooltip].tooltip-right:after{top:50%;left:100%;-ms-transform:translateX(-8px) translateY(-50%);transform:translateX(-8px) translateY(-50%)}body.syndicate div[data-tooltip].tooltip-right:hover:after,body.syndicate span[data-tooltip].tooltip-right:hover:after{-ms-transform:translateX(8px) translateY(-50%);transform:translateX(8px) translateY(-50%)}body.syndicate .bar{display:inline-block;position:relative;vertical-align:middle;width:100%;height:20px;line-height:17px;padding:1px;border:1px solid #000;background:#272727}body.syndicate .bar .barText{position:absolute;top:0;right:3px}body.syndicate .bar .barFill{display:block;height:100%;transition:background-color 1s;background-color:#000}body.syndicate .bar .barFill.good{background-color:#73e573}body.syndicate .bar .barFill.average{background-color:#be6209}body.syndicate .bar .barFill.bad{background-color:#b00e0e}body.syndicate span.button{display:inline-block;vertical-align:middle;min-height:20px;line-height:17px;padding:0 5px;white-space:nowrap;border:1px solid #272727}body.syndicate span.button .fa{padding-right:2px}body.syndicate span.button.normal{transition:background-color .5s;background-color:#397439}body.syndicate span.button.normal.active:focus,body.syndicate span.button.normal.active:hover{transition:background-color .25s;background-color:#4a964a;outline:0}body.syndicate span.button.disabled{transition:background-color .5s;background-color:#363636}body.syndicate span.button.disabled.active:focus,body.syndicate span.button.disabled.active:hover{transition:background-color .25s;background-color:#545454;outline:0}body.syndicate span.button.selected{transition:background-color .5s;background-color:#9d0808}body.syndicate span.button.selected.active:focus,body.syndicate span.button.selected.active:hover{transition:background-color .25s;background-color:#ce0b0b;outline:0}body.syndicate span.button.toggle{transition:background-color .5s;background-color:#9d0808}body.syndicate span.button.toggle.active:focus,body.syndicate span.button.toggle.active:hover{transition:background-color .25s;background-color:#ce0b0b;outline:0}body.syndicate span.button.caution{transition:background-color .5s;background-color:#be6209}body.syndicate span.button.caution.active:focus,body.syndicate span.button.caution.active:hover{transition:background-color .25s;background-color:#eb790b;outline:0}body.syndicate span.button.danger{transition:background-color .5s;background-color:#9a9d00}body.syndicate span.button.danger.active:focus,body.syndicate span.button.danger.active:hover{transition:background-color .25s;background-color:#ced200;outline:0}body.syndicate span.button.gridable{width:125px;margin:2px 0}body.syndicate span.button.gridable.center{text-align:center;width:75px}body.syndicate span.button+span:not(.button),body.syndicate span:not(.button)+span.button{margin-left:5px}body.syndicate div.display{width:100%;padding:4px;margin:6px 0;background-color:#000;-ms-filter:"progid:DXImageTransform.Microsoft.gradient(startColorStr=#80000000,endColorStr=#80000000)";filter:progid:DXImageTransform.Microsoft.gradient(startColorStr=#80000000,endColorStr=#80000000);background-color:rgba(0,0,0,.5);box-shadow:inset 0 0 5px rgba(0,0,0,.75)}body.syndicate div.display.tabular{padding:0;margin:0}body.syndicate div.display header,body.syndicate div.subdisplay header{display:block;position:relative;width:100%;padding:0 4px;margin-bottom:6px;color:#fff;border-bottom:2px solid #272727}body.syndicate div.display header .buttonRight,body.syndicate div.subdisplay header .buttonRight{position:absolute;bottom:6px;right:4px}body.syndicate div.display article,body.syndicate div.subdisplay article{display:table;width:100%;border-collapse:collapse}body.syndicate input{display:inline-block;vertical-align:middle;height:20px;line-height:17px;padding:0 5px;white-space:nowrap;color:#fff;background-color:#9d0808;border:1px solid #272727}body.syndicate input.number{width:35px}body.syndicate input::-webkit-input-placeholder{color:#999}body.syndicate input:-ms-input-placeholder{color:#999}body.syndicate input::placeholder{color:#999}body.syndicate input::-ms-clear{display:none}body.syndicate svg.linegraph{overflow:hidden}body.syndicate div.notice{margin:8px 0;padding:4px;box-shadow:none;color:#000;font-weight:700;font-style:italic;background-color:#750000;background-image:repeating-linear-gradient(-45deg,#750000,#750000 10px,#910101 0,#910101 20px)}body.syndicate div.notice .label{color:#000}body.syndicate div.notice .content:only-of-type{padding:0}body.syndicate div.notice hr{background-color:#272727}body.syndicate div.resize{position:fixed;bottom:0;right:0;width:0;height:0;border-style:solid;border-width:0 0 45px 45px;border-color:transparent transparent #363636;-ms-transform:rotate(1turn);transform:rotate(1turn)}body.syndicate section .cell,body.syndicate section .content,body.syndicate section .label,body.syndicate section .line{display:table-cell;margin:0;text-align:left;vertical-align:middle;padding:3px 2px}body.syndicate section{display:table-row;width:100%}body.syndicate section:not(:first-child){padding-top:4px}body.syndicate section.candystripe:nth-child(2n){background-color:#000;-ms-filter:"progid:DXImageTransform.Microsoft.gradient(startColorStr=#33000000,endColorStr=#33000000)";filter:progid:DXImageTransform.Microsoft.gradient(startColorStr=#33000000,endColorStr=#33000000);background-color:rgba(0,0,0,.2)}body.syndicate section .label{width:1%;padding-right:32px;white-space:nowrap;color:#fff}body.syndicate section .content:not(:last-child){padding-right:16px}body.syndicate section .line{width:100%}body.syndicate section .cell:not(:first-child){text-align:center;padding-top:0}body.syndicate section .cell span.button{width:75px}body.syndicate section:not(:last-child){padding-right:4px}body.syndicate div.subdisplay{width:100%;margin:0}body.syndicate header.titlebar .close,body.syndicate header.titlebar .minimize{display:inline-block;position:relative;padding:7px;margin:-7px;color:#e74242}body.syndicate header.titlebar .close:hover,body.syndicate header.titlebar .minimize:hover{color:#eb5e5e}body.syndicate header.titlebar{position:fixed;z-index:1;top:0;left:0;width:100%;height:32px;background-color:#363636;border-bottom:1px solid #161616;box-shadow:0 3px 3px rgba(0,0,0,.1)}body.syndicate header.titlebar .statusicon{position:absolute;top:4px;left:12px;transition:color .5s}body.syndicate header.titlebar .title{position:absolute;top:6px;left:46px;color:#e74242;font-size:16px;white-space:nowrap}body.syndicate header.titlebar .minimize{position:absolute;top:6px;right:46px}body.syndicate header.titlebar .close{position:absolute;top:4px;right:12px}.no-icons header.titlebar .statusicon{font-size:20px}.no-icons header.titlebar .statusicon:after{content:"O"}.no-icons header.titlebar .minimize{top:-2px;font-size:20px}.no-icons header.titlebar .minimize:after{content:"—"}.no-icons header.titlebar .close{font-size:20px}.no-icons header.titlebar .close:after{content:"X"} \ No newline at end of file diff --git a/tgui/assets/tgui.js b/tgui/assets/tgui.js index 5d42acb654..a41d648fe1 100644 --- a/tgui/assets/tgui.js +++ b/tgui/assets/tgui.js @@ -1,16 +1,16 @@ -require=function t(e,n,a){function r(o,s){if(!n[o]){if(!e[o]){var u="function"==typeof require&&require;if(!s&&u)return u(o,!0);if(i)return i(o,!0);var p=Error("Cannot find module '"+o+"'");throw p.code="MODULE_NOT_FOUND",p}var c=n[o]={exports:{}};e[o][0].call(c.exports,function(t){var n=e[o][1][t];return r(n?n:t)},c,c.exports,t,e,n,a)}return n[o].exports}for(var i="function"==typeof require&&require,o=0;o2?p[2]:void 0,l=Math.min((void 0===c?o:r(c,o))-u,o-s),f=1;for(s>u&&u+l>s&&(f=-1,u+=l-1,s+=l-1);l-- >0;)u in n?n[s]=n[u]:delete n[s],s+=f,u+=f;return n}},{76:76,79:79,80:80}],6:[function(t,e,n){"use strict";var a=t(80),r=t(76),i=t(79);e.exports=[].fill||function(t){for(var e=a(this),n=i(e.length),o=arguments,s=o.length,u=r(s>1?o[1]:void 0,n),p=s>2?o[2]:void 0,c=void 0===p?n:r(p,n);c>u;)e[u++]=t;return e}},{76:76,79:79,80:80}],7:[function(t,e,n){var a=t(78),r=t(79),i=t(76);e.exports=function(t){return function(e,n,o){var s,u=a(e),p=r(u.length),c=i(o,p);if(t&&n!=n){for(;p>c;)if(s=u[c++],s!=s)return!0}else for(;p>c;c++)if((t||c in u)&&u[c]===n)return t||c;return!t&&-1}}},{76:76,78:78,79:79}],8:[function(t,e,n){var a=t(17),r=t(34),i=t(80),o=t(79),s=t(9);e.exports=function(t){var e=1==t,n=2==t,u=3==t,p=4==t,c=6==t,l=5==t||c;return function(f,d,h){for(var m,v,g=i(f),b=r(g),y=a(d,h,3),x=o(b.length),_=0,w=e?s(f,x):n?s(f,0):void 0;x>_;_++)if((l||_ in b)&&(m=b[_],v=y(m,_,g),t))if(e)w[_]=v;else if(v)switch(t){case 3:return!0;case 5:return m;case 6:return _;case 2:w.push(m)}else if(p)return!1;return c?-1:u||p?p:w}}},{17:17,34:34,79:79,80:80,9:9}],9:[function(t,e,n){var a=t(38),r=t(36),i=t(83)("species");e.exports=function(t,e){var n;return r(t)&&(n=t.constructor,"function"!=typeof n||n!==Array&&!r(n.prototype)||(n=void 0),a(n)&&(n=n[i],null===n&&(n=void 0))),new(void 0===n?Array:n)(e)}},{36:36,38:38,83:83}],10:[function(t,e,n){var a=t(11),r=t(83)("toStringTag"),i="Arguments"==a(function(){return arguments}());e.exports=function(t){var e,n,o;return void 0===t?"Undefined":null===t?"Null":"string"==typeof(n=(e=Object(t))[r])?n:i?a(e):"Object"==(o=a(e))&&"function"==typeof e.callee?"Arguments":o}},{11:11,83:83}],11:[function(t,e,n){var a={}.toString;e.exports=function(t){return a.call(t).slice(8,-1)}},{}],12:[function(t,e,n){"use strict";var a=t(46),r=t(31),i=t(60),o=t(17),s=t(69),u=t(18),p=t(27),c=t(42),l=t(44),f=t(82)("id"),d=t(30),h=t(38),m=t(65),v=t(19),g=Object.isExtensible||h,b=v?"_s":"size",y=0,x=function(t,e){if(!h(t))return"symbol"==typeof t?t:("string"==typeof t?"S":"P")+t;if(!d(t,f)){if(!g(t))return"F";if(!e)return"E";r(t,f,++y)}return"O"+t[f]},_=function(t,e){var n,a=x(e);if("F"!==a)return t._i[a];for(n=t._f;n;n=n.n)if(n.k==e)return n};e.exports={getConstructor:function(t,e,n,r){var c=t(function(t,i){s(t,c,e),t._i=a.create(null),t._f=void 0,t._l=void 0,t[b]=0,void 0!=i&&p(i,n,t[r],t)});return i(c.prototype,{clear:function(){for(var t=this,e=t._i,n=t._f;n;n=n.n)n.r=!0,n.p&&(n.p=n.p.n=void 0),delete e[n.i];t._f=t._l=void 0,t[b]=0},"delete":function(t){var e=this,n=_(e,t);if(n){var a=n.n,r=n.p;delete e._i[n.i],n.r=!0,r&&(r.n=a),a&&(a.p=r),e._f==n&&(e._f=a),e._l==n&&(e._l=r),e[b]--}return!!n},forEach:function(t){for(var e,n=o(t,arguments.length>1?arguments[1]:void 0,3);e=e?e.n:this._f;)for(n(e.v,e.k,this);e&&e.r;)e=e.p},has:function(t){return!!_(this,t)}}),v&&a.setDesc(c.prototype,"size",{get:function(){return u(this[b])}}),c},def:function(t,e,n){var a,r,i=_(t,e);return i?i.v=n:(t._l=i={i:r=x(e,!0),k:e,v:n,p:a=t._l,n:void 0,r:!1},t._f||(t._f=i),a&&(a.n=i),t[b]++,"F"!==r&&(t._i[r]=i)),t},getEntry:_,setStrong:function(t,e,n){c(t,e,function(t,e){this._t=t,this._k=e,this._l=void 0},function(){for(var t=this,e=t._k,n=t._l;n&&n.r;)n=n.p;return t._t&&(t._l=n=n?n.n:t._t._f)?"keys"==e?l(0,n.k):"values"==e?l(0,n.v):l(0,[n.k,n.v]):(t._t=void 0,l(1))},n?"entries":"values",!n,!0),m(e)}}},{17:17,18:18,19:19,27:27,30:30,31:31,38:38,42:42,44:44,46:46,60:60,65:65,69:69,82:82}],13:[function(t,e,n){var a=t(27),r=t(10);e.exports=function(t){return function(){if(r(this)!=t)throw TypeError(t+"#toJSON isn't generic");var e=[];return a(this,!1,e.push,e),e}}},{10:10,27:27}],14:[function(t,e,n){"use strict";var a=t(31),r=t(60),i=t(4),o=t(38),s=t(69),u=t(27),p=t(8),c=t(30),l=t(82)("weak"),f=Object.isExtensible||o,d=p(5),h=p(6),m=0,v=function(t){return t._l||(t._l=new g)},g=function(){this.a=[]},b=function(t,e){return d(t.a,function(t){return t[0]===e})};g.prototype={get:function(t){var e=b(this,t);return e?e[1]:void 0},has:function(t){return!!b(this,t)},set:function(t,e){var n=b(this,t);n?n[1]=e:this.a.push([t,e])},"delete":function(t){var e=h(this.a,function(e){return e[0]===t});return~e&&this.a.splice(e,1),!!~e}},e.exports={getConstructor:function(t,e,n,a){var i=t(function(t,r){s(t,i,e),t._i=m++,t._l=void 0,void 0!=r&&u(r,n,t[a],t)});return r(i.prototype,{"delete":function(t){return o(t)?f(t)?c(t,l)&&c(t[l],this._i)&&delete t[l][this._i]:v(this)["delete"](t):!1},has:function(t){return o(t)?f(t)?c(t,l)&&c(t[l],this._i):v(this).has(t):!1}}),i},def:function(t,e,n){return f(i(e))?(c(e,l)||a(e,l,{}),e[l][t._i]=n):v(t).set(e,n),t},frozenStore:v,WEAK:l}},{27:27,30:30,31:31,38:38,4:4,60:60,69:69,8:8,82:82}],15:[function(t,e,n){"use strict";var a=t(29),r=t(22),i=t(61),o=t(60),s=t(27),u=t(69),p=t(38),c=t(24),l=t(43),f=t(66);e.exports=function(t,e,n,d,h,m){var v=a[t],g=v,b=h?"set":"add",y=g&&g.prototype,x={},_=function(t){var e=y[t];i(y,t,"delete"==t?function(t){return m&&!p(t)?!1:e.call(this,0===t?0:t)}:"has"==t?function(t){return m&&!p(t)?!1:e.call(this,0===t?0:t)}:"get"==t?function(t){return m&&!p(t)?void 0:e.call(this,0===t?0:t)}:"add"==t?function(t){return e.call(this,0===t?0:t),this}:function(t,n){return e.call(this,0===t?0:t,n),this})};if("function"==typeof g&&(m||y.forEach&&!c(function(){(new g).entries().next()}))){var w,k=new g,E=k[b](m?{}:-0,1)!=k,S=c(function(){k.has(1)}),C=l(function(t){new g(t)});C||(g=e(function(e,n){u(e,g,t);var a=new v;return void 0!=n&&s(n,h,a[b],a),a}),g.prototype=y,y.constructor=g),m||k.forEach(function(t,e){w=1/e===-(1/0)}),(S||w)&&(_("delete"),_("has"),h&&_("get")),(w||E)&&_(b),m&&y.clear&&delete y.clear}else g=d.getConstructor(e,t,h,b),o(g.prototype,n);return f(g,t),x[t]=g,r(r.G+r.W+r.F*(g!=v),x),m||d.setStrong(g,t,h),g}},{22:22,24:24,27:27,29:29,38:38,43:43,60:60,61:61,66:66,69:69}],16:[function(t,e,n){var a=e.exports={version:"1.2.6"};"number"==typeof __e&&(__e=a)},{}],17:[function(t,e,n){var a=t(2);e.exports=function(t,e,n){if(a(t),void 0===e)return t;switch(n){case 1:return function(n){return t.call(e,n)};case 2:return function(n,a){return t.call(e,n,a)};case 3:return function(n,a,r){return t.call(e,n,a,r)}}return function(){return t.apply(e,arguments)}}},{2:2}],18:[function(t,e,n){e.exports=function(t){if(void 0==t)throw TypeError("Can't call method on "+t);return t}},{}],19:[function(t,e,n){e.exports=!t(24)(function(){return 7!=Object.defineProperty({},"a",{get:function(){return 7}}).a})},{24:24}],20:[function(t,e,n){var a=t(38),r=t(29).document,i=a(r)&&a(r.createElement);e.exports=function(t){return i?r.createElement(t):{}}},{29:29,38:38}],21:[function(t,e,n){var a=t(46);e.exports=function(t){var e=a.getKeys(t),n=a.getSymbols;if(n)for(var r,i=n(t),o=a.isEnum,s=0;i.length>s;)o.call(t,r=i[s++])&&e.push(r);return e}},{46:46}],22:[function(t,e,n){var a=t(29),r=t(16),i=t(31),o=t(61),s=t(17),u="prototype",p=function(t,e,n){var c,l,f,d,h=t&p.F,m=t&p.G,v=t&p.S,g=t&p.P,b=t&p.B,y=m?a:v?a[e]||(a[e]={}):(a[e]||{})[u],x=m?r:r[e]||(r[e]={}),_=x[u]||(x[u]={});m&&(n=e);for(c in n)l=!h&&y&&c in y,f=(l?y:n)[c],d=b&&l?s(f,a):g&&"function"==typeof f?s(Function.call,f):f,y&&!l&&o(y,c,f),x[c]!=f&&i(x,c,d),g&&_[c]!=f&&(_[c]=f)};a.core=r,p.F=1,p.G=2,p.S=4,p.P=8,p.B=16,p.W=32,e.exports=p},{16:16,17:17,29:29,31:31,61:61}],23:[function(t,e,n){var a=t(83)("match");e.exports=function(t){var e=/./;try{"/./"[t](e)}catch(n){try{return e[a]=!1,!"/./"[t](e)}catch(r){}}return!0}},{83:83}],24:[function(t,e,n){e.exports=function(t){try{return!!t()}catch(e){return!0}}},{}],25:[function(t,e,n){"use strict";var a=t(31),r=t(61),i=t(24),o=t(18),s=t(83);e.exports=function(t,e,n){var u=s(t),p=""[t];i(function(){var e={};return e[u]=function(){return 7},7!=""[t](e)})&&(r(String.prototype,t,n(o,u,p)),a(RegExp.prototype,u,2==e?function(t,e){return p.call(t,this,e)}:function(t){return p.call(t,this)}))}},{18:18,24:24,31:31,61:61,83:83}],26:[function(t,e,n){"use strict";var a=t(4);e.exports=function(){var t=a(this),e="";return t.global&&(e+="g"),t.ignoreCase&&(e+="i"),t.multiline&&(e+="m"),t.unicode&&(e+="u"),t.sticky&&(e+="y"),e}},{4:4}],27:[function(t,e,n){var a=t(17),r=t(40),i=t(35),o=t(4),s=t(79),u=t(84);e.exports=function(t,e,n,p){var c,l,f,d=u(t),h=a(n,p,e?2:1),m=0;if("function"!=typeof d)throw TypeError(t+" is not iterable!");if(i(d))for(c=s(t.length);c>m;m++)e?h(o(l=t[m])[0],l[1]):h(t[m]);else for(f=d.call(t);!(l=f.next()).done;)r(f,h,l.value,e)}},{17:17,35:35,4:4,40:40,79:79,84:84}],28:[function(t,e,n){var a=t(78),r=t(46).getNames,i={}.toString,o="object"==typeof window&&Object.getOwnPropertyNames?Object.getOwnPropertyNames(window):[],s=function(t){try{return r(t)}catch(e){return o.slice()}};e.exports.get=function(t){return o&&"[object Window]"==i.call(t)?s(t):r(a(t))}},{46:46,78:78}],29:[function(t,e,n){var a=e.exports="undefined"!=typeof window&&window.Math==Math?window:"undefined"!=typeof self&&self.Math==Math?self:Function("return this")();"number"==typeof __g&&(__g=a)},{}],30:[function(t,e,n){var a={}.hasOwnProperty;e.exports=function(t,e){return a.call(t,e)}},{}],31:[function(t,e,n){var a=t(46),r=t(59);e.exports=t(19)?function(t,e,n){return a.setDesc(t,e,r(1,n))}:function(t,e,n){return t[e]=n,t}},{19:19,46:46,59:59}],32:[function(t,e,n){e.exports=t(29).document&&document.documentElement},{29:29}],33:[function(t,e,n){e.exports=function(t,e,n){var a=void 0===n;switch(e.length){case 0:return a?t():t.call(n);case 1:return a?t(e[0]):t.call(n,e[0]);case 2:return a?t(e[0],e[1]):t.call(n,e[0],e[1]);case 3:return a?t(e[0],e[1],e[2]):t.call(n,e[0],e[1],e[2]);case 4:return a?t(e[0],e[1],e[2],e[3]):t.call(n,e[0],e[1],e[2],e[3])}return t.apply(n,e)}},{}],34:[function(t,e,n){var a=t(11);e.exports=Object("z").propertyIsEnumerable(0)?Object:function(t){return"String"==a(t)?t.split(""):Object(t)}},{11:11}],35:[function(t,e,n){var a=t(45),r=t(83)("iterator"),i=Array.prototype;e.exports=function(t){return void 0!==t&&(a.Array===t||i[r]===t)}},{45:45,83:83}],36:[function(t,e,n){var a=t(11);e.exports=Array.isArray||function(t){return"Array"==a(t)}},{11:11}],37:[function(t,e,n){var a=t(38),r=Math.floor;e.exports=function(t){return!a(t)&&isFinite(t)&&r(t)===t}},{38:38}],38:[function(t,e,n){e.exports=function(t){return"object"==typeof t?null!==t:"function"==typeof t}},{}],39:[function(t,e,n){var a=t(38),r=t(11),i=t(83)("match");e.exports=function(t){var e;return a(t)&&(void 0!==(e=t[i])?!!e:"RegExp"==r(t))}},{11:11,38:38,83:83}],40:[function(t,e,n){var a=t(4);e.exports=function(t,e,n,r){try{return r?e(a(n)[0],n[1]):e(n)}catch(i){var o=t["return"];throw void 0!==o&&a(o.call(t)),i}}},{4:4}],41:[function(t,e,n){"use strict";var a=t(46),r=t(59),i=t(66),o={};t(31)(o,t(83)("iterator"),function(){return this}),e.exports=function(t,e,n){t.prototype=a.create(o,{next:r(1,n)}),i(t,e+" Iterator")}},{31:31,46:46,59:59,66:66,83:83}],42:[function(t,e,n){"use strict";var a=t(48),r=t(22),i=t(61),o=t(31),s=t(30),u=t(45),p=t(41),c=t(66),l=t(46).getProto,f=t(83)("iterator"),d=!([].keys&&"next"in[].keys()),h="@@iterator",m="keys",v="values",g=function(){return this};e.exports=function(t,e,n,b,y,x,_){p(n,e,b);var w,k,E=function(t){if(!d&&t in A)return A[t];switch(t){case m:return function(){return new n(this,t)};case v:return function(){return new n(this,t)}}return function(){return new n(this,t)}},S=e+" Iterator",C=y==v,P=!1,A=t.prototype,O=A[f]||A[h]||y&&A[y],T=O||E(y);if(O){var R=l(T.call(new t));c(R,S,!0),!a&&s(A,h)&&o(R,f,g),C&&O.name!==v&&(P=!0,T=function(){return O.call(this)})}if(a&&!_||!d&&!P&&A[f]||o(A,f,T),u[e]=T,u[S]=g,y)if(w={values:C?T:E(v),keys:x?T:E(m),entries:C?E("entries"):T},_)for(k in w)k in A||i(A,k,w[k]);else r(r.P+r.F*(d||P),e,w);return w}},{22:22,30:30,31:31,41:41,45:45,46:46,48:48,61:61,66:66,83:83}],43:[function(t,e,n){var a=t(83)("iterator"),r=!1;try{var i=[7][a]();i["return"]=function(){r=!0},Array.from(i,function(){throw 2})}catch(o){}e.exports=function(t,e){if(!e&&!r)return!1;var n=!1;try{var i=[7],o=i[a]();o.next=function(){return{done:n=!0}},i[a]=function(){return o},t(i)}catch(s){}return n}},{83:83}],44:[function(t,e,n){e.exports=function(t,e){return{value:e,done:!!t}}},{}],45:[function(t,e,n){e.exports={}},{}],46:[function(t,e,n){var a=Object;e.exports={create:a.create,getProto:a.getPrototypeOf,isEnum:{}.propertyIsEnumerable,getDesc:a.getOwnPropertyDescriptor,setDesc:a.defineProperty,setDescs:a.defineProperties,getKeys:a.keys,getNames:a.getOwnPropertyNames,getSymbols:a.getOwnPropertySymbols,each:[].forEach}},{}],47:[function(t,e,n){var a=t(46),r=t(78);e.exports=function(t,e){for(var n,i=r(t),o=a.getKeys(i),s=o.length,u=0;s>u;)if(i[n=o[u++]]===e)return n}},{46:46,78:78}],48:[function(t,e,n){e.exports=!1},{}],49:[function(t,e,n){e.exports=Math.expm1||function(t){return 0==(t=+t)?t:t>-1e-6&&1e-6>t?t+t*t/2:Math.exp(t)-1}},{}],50:[function(t,e,n){e.exports=Math.log1p||function(t){return(t=+t)>-1e-8&&1e-8>t?t-t*t/2:Math.log(1+t)}},{}],51:[function(t,e,n){e.exports=Math.sign||function(t){return 0==(t=+t)||t!=t?t:0>t?-1:1}},{}],52:[function(t,e,n){var a,r,i,o=t(29),s=t(75).set,u=o.MutationObserver||o.WebKitMutationObserver,p=o.process,c=o.Promise,l="process"==t(11)(p),f=function(){var t,e,n;for(l&&(t=p.domain)&&(p.domain=null,t.exit());a;)e=a.domain,n=a.fn,e&&e.enter(),n(),e&&e.exit(),a=a.next;r=void 0,t&&t.enter()};if(l)i=function(){p.nextTick(f)};else if(u){var d=1,h=document.createTextNode("");new u(f).observe(h,{characterData:!0}),i=function(){h.data=d=-d}}else i=c&&c.resolve?function(){c.resolve().then(f)}:function(){s.call(o,f)};e.exports=function(t){var e={fn:t,next:void 0,domain:l&&p.domain};r&&(r.next=e),a||(a=e,i()),r=e}},{11:11,29:29,75:75}],53:[function(t,e,n){var a=t(46),r=t(80),i=t(34);e.exports=t(24)(function(){var t=Object.assign,e={},n={},a=Symbol(),r="abcdefghijklmnopqrst";return e[a]=7,r.split("").forEach(function(t){n[t]=t}),7!=t({},e)[a]||Object.keys(t({},n)).join("")!=r})?function(t,e){for(var n=r(t),o=arguments,s=o.length,u=1,p=a.getKeys,c=a.getSymbols,l=a.isEnum;s>u;)for(var f,d=i(o[u++]),h=c?p(d).concat(c(d)):p(d),m=h.length,v=0;m>v;)l.call(d,f=h[v++])&&(n[f]=d[f]);return n}:Object.assign},{24:24,34:34,46:46,80:80}],54:[function(t,e,n){var a=t(22),r=t(16),i=t(24);e.exports=function(t,e){var n=(r.Object||{})[t]||Object[t],o={};o[t]=e(n),a(a.S+a.F*i(function(){n(1)}),"Object",o)}},{16:16,22:22,24:24}],55:[function(t,e,n){var a=t(46),r=t(78),i=a.isEnum;e.exports=function(t){return function(e){for(var n,o=r(e),s=a.getKeys(o),u=s.length,p=0,c=[];u>p;)i.call(o,n=s[p++])&&c.push(t?[n,o[n]]:o[n]);return c}}},{46:46,78:78}],56:[function(t,e,n){var a=t(46),r=t(4),i=t(29).Reflect;e.exports=i&&i.ownKeys||function(t){var e=a.getNames(r(t)),n=a.getSymbols;return n?e.concat(n(t)):e}},{29:29,4:4,46:46}],57:[function(t,e,n){"use strict";var a=t(58),r=t(33),i=t(2);e.exports=function(){for(var t=i(this),e=arguments.length,n=Array(e),o=0,s=a._,u=!1;e>o;)(n[o]=arguments[o++])===s&&(u=!0);return function(){var a,i=this,o=arguments,p=o.length,c=0,l=0;if(!u&&!p)return r(t,n,i);if(a=n.slice(),u)for(;e>c;c++)a[c]===s&&(a[c]=o[l++]);for(;p>l;)a.push(o[l++]);return r(t,a,i)}}},{2:2,33:33,58:58}],58:[function(t,e,n){e.exports=t(29)},{29:29}],59:[function(t,e,n){e.exports=function(t,e){return{enumerable:!(1&t),configurable:!(2&t),writable:!(4&t),value:e}}},{}],60:[function(t,e,n){var a=t(61);e.exports=function(t,e){for(var n in e)a(t,n,e[n]);return t}},{61:61}],61:[function(t,e,n){var a=t(29),r=t(31),i=t(82)("src"),o="toString",s=Function[o],u=(""+s).split(o);t(16).inspectSource=function(t){return s.call(t)},(e.exports=function(t,e,n,o){"function"==typeof n&&(n.hasOwnProperty(i)||r(n,i,t[e]?""+t[e]:u.join(e+"")),n.hasOwnProperty("name")||r(n,"name",e)),t===a?t[e]=n:(o||delete t[e],r(t,e,n))})(Function.prototype,o,function(){return"function"==typeof this&&this[i]||s.call(this)})},{16:16,29:29,31:31,82:82}],62:[function(t,e,n){e.exports=function(t,e){var n=e===Object(e)?function(t){return e[t]}:e;return function(e){return(e+"").replace(t,n)}}},{}],63:[function(t,e,n){e.exports=Object.is||function(t,e){return t===e?0!==t||1/t===1/e:t!=t&&e!=e}},{}],64:[function(t,e,n){var a=t(46).getDesc,r=t(38),i=t(4),o=function(t,e){if(i(t),!r(e)&&null!==e)throw TypeError(e+": can't set as prototype!")};e.exports={set:Object.setPrototypeOf||("__proto__"in{}?function(e,n,r){try{r=t(17)(Function.call,a(Object.prototype,"__proto__").set,2),r(e,[]),n=!(e instanceof Array)}catch(i){n=!0}return function(t,e){return o(t,e),n?t.__proto__=e:r(t,e),t}}({},!1):void 0),check:o}},{17:17,38:38,4:4,46:46}],65:[function(t,e,n){"use strict";var a=t(29),r=t(46),i=t(19),o=t(83)("species");e.exports=function(t){var e=a[t];i&&e&&!e[o]&&r.setDesc(e,o,{configurable:!0,get:function(){return this}})}},{19:19,29:29,46:46,83:83}],66:[function(t,e,n){var a=t(46).setDesc,r=t(30),i=t(83)("toStringTag");e.exports=function(t,e,n){t&&!r(t=n?t:t.prototype,i)&&a(t,i,{configurable:!0,value:e})}},{30:30,46:46,83:83}],67:[function(t,e,n){var a=t(29),r="__core-js_shared__",i=a[r]||(a[r]={});e.exports=function(t){return i[t]||(i[t]={})}},{29:29}],68:[function(t,e,n){var a=t(4),r=t(2),i=t(83)("species");e.exports=function(t,e){var n,o=a(t).constructor;return void 0===o||void 0==(n=a(o)[i])?e:r(n)}},{2:2,4:4,83:83}],69:[function(t,e,n){e.exports=function(t,e,n){if(!(t instanceof e))throw TypeError(n+": use the 'new' operator!");return t}},{}],70:[function(t,e,n){var a=t(77),r=t(18);e.exports=function(t){return function(e,n){var i,o,s=r(e)+"",u=a(n),p=s.length;return 0>u||u>=p?t?"":void 0:(i=s.charCodeAt(u),55296>i||i>56319||u+1===p||(o=s.charCodeAt(u+1))<56320||o>57343?t?s.charAt(u):i:t?s.slice(u,u+2):(i-55296<<10)+(o-56320)+65536)}}},{18:18,77:77}],71:[function(t,e,n){var a=t(39),r=t(18);e.exports=function(t,e,n){if(a(e))throw TypeError("String#"+n+" doesn't accept regex!");return r(t)+""}},{18:18,39:39}],72:[function(t,e,n){var a=t(79),r=t(73),i=t(18);e.exports=function(t,e,n,o){var s=i(t)+"",u=s.length,p=void 0===n?" ":n+"",c=a(e);if(u>=c)return s;""==p&&(p=" ");var l=c-u,f=r.call(p,Math.ceil(l/p.length));return f.length>l&&(f=f.slice(0,l)),o?f+s:s+f}},{18:18,73:73,79:79}],73:[function(t,e,n){"use strict";var a=t(77),r=t(18);e.exports=function(t){var e=r(this)+"",n="",i=a(t);if(0>i||i==1/0)throw RangeError("Count can't be negative");for(;i>0;(i>>>=1)&&(e+=e))1&i&&(n+=e);return n}},{18:18,77:77}],74:[function(t,e,n){var a=t(22),r=t(18),i=t(24),o=" \n\x0B\f\r  ᠎              \u2028\u2029\ufeff",s="["+o+"]",u="​…",p=RegExp("^"+s+s+"*"),c=RegExp(s+s+"*$"),l=function(t,e){var n={};n[t]=e(f),a(a.P+a.F*i(function(){return!!o[t]()||u[t]()!=u}),"String",n)},f=l.trim=function(t,e){return t=r(t)+"",1&e&&(t=t.replace(p,"")),2&e&&(t=t.replace(c,"")),t};e.exports=l},{18:18,22:22,24:24}],75:[function(t,e,n){var a,r,i,o=t(17),s=t(33),u=t(32),p=t(20),c=t(29),l=c.process,f=c.setImmediate,d=c.clearImmediate,h=c.MessageChannel,m=0,v={},g="onreadystatechange",b=function(){var t=+this;if(v.hasOwnProperty(t)){var e=v[t];delete v[t],e()}},y=function(t){b.call(t.data)};f&&d||(f=function(t){for(var e=[],n=1;arguments.length>n;)e.push(arguments[n++]);return v[++m]=function(){s("function"==typeof t?t:Function(t),e)},a(m),m},d=function(t){delete v[t]},"process"==t(11)(l)?a=function(t){l.nextTick(o(b,t,1))}:h?(r=new h,i=r.port2,r.port1.onmessage=y,a=o(i.postMessage,i,1)):c.addEventListener&&"function"==typeof postMessage&&!c.importScripts?(a=function(t){c.postMessage(t+"","*")},c.addEventListener("message",y,!1)):a=g in p("script")?function(t){u.appendChild(p("script"))[g]=function(){u.removeChild(this),b.call(t)}}:function(t){setTimeout(o(b,t,1),0)}),e.exports={set:f,clear:d}},{11:11,17:17,20:20,29:29,32:32,33:33}],76:[function(t,e,n){var a=t(77),r=Math.max,i=Math.min;e.exports=function(t,e){return t=a(t),0>t?r(t+e,0):i(t,e)}},{77:77}],77:[function(t,e,n){var a=Math.ceil,r=Math.floor;e.exports=function(t){return isNaN(t=+t)?0:(t>0?r:a)(t)}},{}],78:[function(t,e,n){var a=t(34),r=t(18);e.exports=function(t){return a(r(t))}},{18:18,34:34}],79:[function(t,e,n){var a=t(77),r=Math.min;e.exports=function(t){return t>0?r(a(t),9007199254740991):0}},{77:77}],80:[function(t,e,n){var a=t(18);e.exports=function(t){return Object(a(t))}},{18:18}],81:[function(t,e,n){var a=t(38);e.exports=function(t,e){if(!a(t))return t;var n,r;if(e&&"function"==typeof(n=t.toString)&&!a(r=n.call(t)))return r;if("function"==typeof(n=t.valueOf)&&!a(r=n.call(t)))return r;if(!e&&"function"==typeof(n=t.toString)&&!a(r=n.call(t)))return r;throw TypeError("Can't convert object to primitive value")}},{38:38}],82:[function(t,e,n){var a=0,r=Math.random();e.exports=function(t){return"Symbol(".concat(void 0===t?"":t,")_",(++a+r).toString(36))}},{}],83:[function(t,e,n){var a=t(67)("wks"),r=t(82),i=t(29).Symbol;e.exports=function(t){return a[t]||(a[t]=i&&i[t]||(i||r)("Symbol."+t))}},{29:29,67:67,82:82}],84:[function(t,e,n){var a=t(10),r=t(83)("iterator"),i=t(45);e.exports=t(16).getIteratorMethod=function(t){return void 0!=t?t[r]||t["@@iterator"]||i[a(t)]:void 0}},{10:10,16:16,45:45,83:83}],85:[function(t,e,n){"use strict";var a,r=t(46),i=t(22),o=t(19),s=t(59),u=t(32),p=t(20),c=t(30),l=t(11),f=t(33),d=t(24),h=t(4),m=t(2),v=t(38),g=t(80),b=t(78),y=t(77),x=t(76),_=t(79),w=t(34),k=t(82)("__proto__"),E=t(8),S=t(7)(!1),C=Object.prototype,P=Array.prototype,A=P.slice,O=P.join,T=r.setDesc,R=r.getDesc,j=r.setDescs,M={};o||(a=!d(function(){return 7!=T(p("div"),"a",{get:function(){return 7}}).a}),r.setDesc=function(t,e,n){if(a)try{return T(t,e,n)}catch(r){}if("get"in n||"set"in n)throw TypeError("Accessors not supported!");return"value"in n&&(h(t)[e]=n.value),t},r.getDesc=function(t,e){if(a)try{return R(t,e)}catch(n){}return c(t,e)?s(!C.propertyIsEnumerable.call(t,e),t[e]):void 0},r.setDescs=j=function(t,e){h(t);for(var n,a=r.getKeys(e),i=a.length,o=0;i>o;)r.setDesc(t,n=a[o++],e[n]);return t}),i(i.S+i.F*!o,"Object",{getOwnPropertyDescriptor:r.getDesc,defineProperty:r.setDesc,defineProperties:j});var L="constructor,hasOwnProperty,isPrototypeOf,propertyIsEnumerable,toLocaleString,toString,valueOf".split(","),D=L.concat("length","prototype"),N=L.length,F=function(){var t,e=p("iframe"),n=N,a=">";for(e.style.display="none",u.appendChild(e),e.src="javascript:",t=e.contentWindow.document,t.open(),t.write(" -
    - - - - - -
    - - - - -
    - [sprite_text] -
    - [atomsnowflake.Join()] -
    -
    -
    - [formatted_type] - [marked] - [varedited_line] -
    -
    -
    - Refresh -
    - -
    -
    -
    -
    -
    - - E - Edit, tries to determine the variable type by itself.
    - C - Change, asks you for the var type first.
    - M - Mass modify: changes this variable for all objects of this type.
    -
    -
    - - - - - -
    -
    - Search: -
    -
    - -
    -
    -
      - [variable_html.Join()] -
    - - - -"} - - usr << browse(html, "window=variables[refid];size=475x650") - - -#define VV_HTML_ENCODE(thing) ( sanitize ? html_encode(thing) : thing ) -/proc/debug_variable(name, value, level, datum/DA = null, sanitize = TRUE) - var/header - if(DA) - if (islist(DA)) - var/index = name - if (value) - name = DA[name] //name is really the index until this line - else - value = DA[name] - header = "
  • (E) (C) (-) " - else - header = "
  • (E) (C) (M) " - else - header = "
  • " - - var/item - if (isnull(value)) - item = "[VV_HTML_ENCODE(name)] = null" - - else if (istext(value)) - item = "[VV_HTML_ENCODE(name)] = \"[VV_HTML_ENCODE(value)]\"" - - else if (isicon(value)) - #ifdef VARSICON - var/icon/I = new/icon(value) - var/rnd = rand(1,10000) - var/rname = "tmp\ref[I][rnd].png" - usr << browse_rsc(I, rname) - item = "[VV_HTML_ENCODE(name)] = ([value]) " - #else - item = "[VV_HTML_ENCODE(name)] = /icon ([value])" - #endif - -/* else if (istype(value, /image)) - #ifdef VARSICON - var/rnd = rand(1, 10000) - var/image/I = value - - src << browse_rsc(I.icon, "tmp\ref[value][rnd].png") - html += "[name] = " - #else - html += "[name] = /image ([value])" - #endif -*/ - else if (isfile(value)) - item = "[VV_HTML_ENCODE(name)] = '[value]'" - - //else if (istype(value, /client)) - // var/client/C = value - // item = "[VV_HTML_ENCODE(name)] \ref[value] = [C] [C.type]" - - else if (istype(value, /datum)) - var/datum/D = value - if ("[D]" != "[D.type]") //if the thing as a name var, lets use it. - item = "[VV_HTML_ENCODE(name)] \ref[value] = [D] [D.type]" - else - item = "[VV_HTML_ENCODE(name)] \ref[value] = [D.type]" - - else if (islist(value)) - var/list/L = value - var/list/items = list() - - if (L.len > 0 && !(name == "underlays" || name == "overlays" || L.len > (IS_NORMAL_LIST(L) ? 50 : 150))) - for (var/i in 1 to L.len) - var/key = L[i] - var/val - if (IS_NORMAL_LIST(L) && !isnum(key)) - val = L[key] - if (!val) - val = key - key = i - - items += debug_variable(key, val, level + 1, sanitize = sanitize) - - item = "[VV_HTML_ENCODE(name)] = /list ([L.len])
      [items.Join()]
    " - else - item = "[VV_HTML_ENCODE(name)] = /list ([L.len])" - - else - item = "[VV_HTML_ENCODE(name)] = [VV_HTML_ENCODE(value)]" - - return "[header][item]
  • " - -#undef VV_HTML_ENCODE - -/client/proc/view_var_Topic(href, href_list, hsrc) - if( (usr.client != src) || !src.holder ) - return - if(href_list["Vars"]) - debug_variables(locate(href_list["Vars"])) - - else if(href_list["datumrefresh"]) - var/datum/DAT = locate(href_list["datumrefresh"]) - if(!DAT) //can't be an istype() because /client etc aren't datums - return - src.debug_variables(DAT) - - else if(href_list["mob_player_panel"]) - if(!check_rights(0)) - return - /datum/proc/vv_get_dropdown() . = list() . += "---" @@ -1009,22 +546,6 @@ to_chat(usr, "This can only be done to instances of type /mob") return M.regenerate_icons() - -//Needs +VAREDIT past this point - - else if(check_rights(R_VAREDIT)) - - - //~CARN: for renaming mobs (updates their name, real_name, mind.name, their ID/PDA and datacore records). - - if(href_list["rename"]) - if(!check_rights(0)) - return - - if(!ismob(M)) - to_chat(usr, "This can only be done to instances of type /mob") - return - M.regenerate_icons() else if(href_list["expose"]) if(!check_rights(R_ADMIN, FALSE)) return From 726b86f3a4d48ddb1d8ce61411fd1487a812c416 Mon Sep 17 00:00:00 2001 From: LetterJay Date: Mon, 11 Sep 2017 14:18:28 -0500 Subject: [PATCH 54/74] Update on_move.dm --- code/modules/shuttle/on_move.dm | 1 - 1 file changed, 1 deletion(-) diff --git a/code/modules/shuttle/on_move.dm b/code/modules/shuttle/on_move.dm index f2c84a5aae..77eec512d8 100644 --- a/code/modules/shuttle/on_move.dm +++ b/code/modules/shuttle/on_move.dm @@ -14,7 +14,6 @@ All ShuttleMove procs go here // Called from the new turf before anything has been moved // Only gets called if fromShuttleMove returns true first // returns the new move_mode (based on the old) -/turf/proc/toShuttleMove(turf/oldT, shuttle_dir, move_mode) /turf/proc/toShuttleMove(turf/oldT, move_mode, obj/docking_port/mobile/shuttle) var/shuttle_dir = shuttle.dir for(var/i in contents) From 6d88e3642b924c4c55a004063dd476bd86a09a06 Mon Sep 17 00:00:00 2001 From: LetterJay Date: Mon, 11 Sep 2017 14:27:28 -0500 Subject: [PATCH 55/74] Update suit_storage_unit.dm --- code/game/machinery/suit_storage_unit.dm | 1 - 1 file changed, 1 deletion(-) diff --git a/code/game/machinery/suit_storage_unit.dm b/code/game/machinery/suit_storage_unit.dm index 5d5539fc19..be89a3d2e6 100644 --- a/code/game/machinery/suit_storage_unit.dm +++ b/code/game/machinery/suit_storage_unit.dm @@ -583,7 +583,6 @@ return ..() ->>>>>>> d4d898f... Regularizes resisting out of containers (#30412) /obj/machinery/suit_storage_unit/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = FALSE, \ datum/tgui/master_ui = null, datum/ui_state/state = GLOB.notcontained_state) ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open) From 1553e26fe2eba880d8413f8b241c245dc58680b6 Mon Sep 17 00:00:00 2001 From: AnturK Date: Mon, 11 Sep 2017 21:36:22 +0200 Subject: [PATCH 56/74] I missed that in last fix. (#30590) --- code/modules/mob/living/carbon/monkey/punpun.dm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/modules/mob/living/carbon/monkey/punpun.dm b/code/modules/mob/living/carbon/monkey/punpun.dm index 711e771074..52ca8c8226 100644 --- a/code/modules/mob/living/carbon/monkey/punpun.dm +++ b/code/modules/mob/living/carbon/monkey/punpun.dm @@ -68,6 +68,6 @@ if(!ancestor_name) file_data["ancestor_name"] = name fdel(json_file) - WRITE_FILE(json_file, json_encode(json_file)) + WRITE_FILE(json_file, json_encode(file_data)) if(!dead) memory_saved = 1 \ No newline at end of file From 80dbaae65a48e4ee598d81e70bc2eef20976c5f1 Mon Sep 17 00:00:00 2001 From: LetterJay Date: Mon, 11 Sep 2017 14:37:55 -0500 Subject: [PATCH 58/74] fuck --- code/game/objects/items/weaponry.dm | 566 ---------------------------- 1 file changed, 566 deletions(-) diff --git a/code/game/objects/items/weaponry.dm b/code/game/objects/items/weaponry.dm index 60b019bcf7..9a9cdbdebe 100644 --- a/code/game/objects/items/weaponry.dm +++ b/code/game/objects/items/weaponry.dm @@ -399,572 +399,6 @@ user.visible_message("[user] is inhaling [src]! It looks like [user.p_theyre()] trying to visit the astral plane.") return (OXYLOSS) -/obj/item/mounted_chainsaw - name = "mounted chainsaw" - desc = "A chainsaw that has replaced your arm." - icon_state = "chainsaw_on" - item_state = "mounted_chainsaw" - lefthand_file = 'icons/mob/inhands/weapons/chainsaw_lefthand.dmi' - righthand_file = 'icons/mob/inhands/weapons/chainsaw_righthand.dmi' - flags_1 = NODROP_1 | ABSTRACT_1 | DROPDEL_1 - w_class = WEIGHT_CLASS_HUGE - force = 21 - throwforce = 0 - throw_range = 0 - throw_speed = 0 - sharpness = IS_SHARP - attack_verb = list("sawed", "torn", "cut", "chopped", "diced") - hitsound = 'sound/weapons/chainsawhit.ogg' - -/obj/item/mounted_chainsaw/Destroy() - var/obj/item/bodypart/part - new /obj/item/twohanded/required/chainsaw(get_turf(src)) - if(iscarbon(loc)) - var/mob/living/carbon/holder = loc - var/index = holder.get_held_index_of_item(src) - if(index) - part = holder.hand_bodyparts[index] - . = ..() - if(part) - part.drop_limb() - -/obj/item/statuebust - name = "bust" - desc = "A priceless ancient marble bust, the kind that belongs in a museum." //or you can hit people with it - icon = 'icons/obj/statue.dmi' - icon_state = "bust" - force = 15 - throwforce = 10 - throw_speed = 5 - throw_range = 2 - attack_verb = list("busted") - -/obj/item/tailclub - name = "tail club" - desc = "For the beating to death of lizards with their own tails." - icon_state = "tailclub" - force = 14 - throwforce = 1 // why are you throwing a club do you even weapon - throw_speed = 1 - throw_range = 1 - attack_verb = list("clubbed", "bludgeoned") - -/obj/item/melee/chainofcommand/tailwhip - name = "liz o' nine tails" - desc = "A whip fashioned from the severed tails of lizards." - icon_state = "tailwhip" - origin_tech = "engineering=3;combat=3;biotech=3" - needs_permit = 0 - -/obj/item/melee/chainofcommand/tailwhip/kitty - name = "cat o' nine tails" - desc = "A whip fashioned from the severed tails of cats." - icon_state = "catwhip" - -/obj/item/melee/skateboard - name = "skateboard" - desc = "A skateboard. It can be placed on its wheels and ridden, or used as a strong weapon." - icon_state = "skateboard" - item_state = "skateboard" - force = 12 - throwforce = 4 - w_class = WEIGHT_CLASS_HUGE - attack_verb = list("smacked", "whacked", "slammed", "smashed") - -/obj/item/melee/skateboard/attack_self(mob/user) - new /obj/vehicle/scooter/skateboard(get_turf(user)) - qdel(src) - -/obj/item/melee/baseball_bat - name = "baseball bat" - desc = "There ain't a skull in the league that can withstand a swatter." - icon = 'icons/obj/items_and_weapons.dmi' - icon_state = "baseball_bat" - item_state = "baseball_bat" - lefthand_file = 'icons/mob/inhands/weapons/melee_lefthand.dmi' - righthand_file = 'icons/mob/inhands/weapons/melee_righthand.dmi' - force = 10 - throwforce = 12 - attack_verb = list("beat", "smacked") - w_class = WEIGHT_CLASS_HUGE - var/homerun_ready = 0 - var/homerun_able = 0 - -/obj/item/melee/baseball_bat/homerun - name = "home run bat" - desc = "This thing looks dangerous... Dangerously good at baseball, that is." - homerun_able = 1 - -/obj/item/melee/baseball_bat/attack_self(mob/user) - if(!homerun_able) - ..() - return - if(homerun_ready) - to_chat(user, "You're already ready to do a home run!") - ..() - return - to_chat(user, "You begin gathering strength...") - playsound(get_turf(src), 'sound/magic/lightning_chargeup.ogg', 65, 1) - if(do_after(user, 90, target = src)) - to_chat(user, "You gather power! Time for a home run!") - homerun_ready = 1 - ..() - -/obj/item/melee/baseball_bat/attack(mob/living/target, mob/living/user) - . = ..() - var/atom/throw_target = get_edge_target_turf(target, user.dir) - if(homerun_ready) - user.visible_message("It's a home run!") - target.throw_at(throw_target, rand(8,10), 14, user) - target.ex_act(EXPLODE_HEAVY) - playsound(get_turf(src), 'sound/weapons/homerun.ogg', 100, 1) - homerun_ready = 0 - return - else if(!target.anchored) - target.throw_at(throw_target, rand(1,2), 7, user) - -/obj/item/melee/baseball_bat/ablative - name = "metal baseball bat" - desc = "This bat is made of highly reflective, highly armored material." - icon_state = "baseball_bat_metal" - item_state = "baseball_bat_metal" - force = 12 - throwforce = 15 - -/obj/item/melee/baseball_bat/ablative/IsReflect()//some day this will reflect thrown items instead of lasers - var/picksound = rand(1,2) - var/turf = get_turf(src) - if(picksound == 1) - playsound(turf, 'sound/weapons/effects/batreflect1.ogg', 50, 1) - if(picksound == 2) - playsound(turf, 'sound/weapons/effects/batreflect2.ogg', 50, 1) - return 1 - -/obj/item/melee/flyswatter - name = "flyswatter" - desc = "Useful for killing insects of all sizes." - icon = 'icons/obj/items_and_weapons.dmi' - icon_state = "flyswatter" - item_state = "flyswatter" - lefthand_file = 'icons/mob/inhands/weapons/melee_lefthand.dmi' - righthand_file = 'icons/mob/inhands/weapons/melee_righthand.dmi' - force = 1 - throwforce = 1 - attack_verb = list("swatted", "smacked") - hitsound = 'sound/effects/snap.ogg' - w_class = WEIGHT_CLASS_SMALL - //Things in this list will be instantly splatted. Flyman weakness is handled in the flyman species weakness proc. - var/list/strong_against - -/obj/item/melee/flyswatter/Initialize() - . = ..() - strong_against = typecacheof(list( - /mob/living/simple_animal/hostile/poison/bees/, - /mob/living/simple_animal/butterfly, - /mob/living/simple_animal/cockroach, - /obj/item/queen_bee - )) - - -/obj/item/melee/flyswatter/afterattack(atom/target, mob/user, proximity_flag) - if(proximity_flag) - if(is_type_in_typecache(target, strong_against)) - new /obj/effect/decal/cleanable/deadcockroach(get_turf(target)) - to_chat(user, "You easily splat the [target].") - if(istype(target, /mob/living/)) - var/mob/living/bug = target - bug.death(1) - else - qdel(target) - -/obj/item/circlegame - name = "circled hand" - desc = "If somebody looks at this while it's below your waist, you get to bop them." - icon_state = "madeyoulook" - force = 0 - throwforce = 0 - flags_1 = DROPDEL_1 | ABSTRACT_1 - attack_verb = list("bopped") - -/obj/item/proc/can_trigger_gun(mob/living/user) - if(!user.can_use_guns(src)) - return FALSE - playsound(loc, 'sound/effects/adminhelp.ogg', 15) //keep it at 15% volume so people don't jump out of their skin too much - -/obj/item/sord - name = "\improper SORD" - desc = "This thing is so unspeakably shitty you are having a hard time even holding it." - icon_state = "sord" - item_state = "sord" - lefthand_file = 'icons/mob/inhands/weapons/swords_lefthand.dmi' - righthand_file = 'icons/mob/inhands/weapons/swords_righthand.dmi' - slot_flags = SLOT_BELT - force = 2 - throwforce = 1 - w_class = WEIGHT_CLASS_NORMAL - hitsound = 'sound/weapons/bladeslice.ogg' - attack_verb = list("attacked", "slashed", "stabbed", "sliced", "torn", "ripped", "diced", "cut") - -/obj/item/sord/suicide_act(mob/user) - user.visible_message("[user] is trying to impale [user.p_them()]self with [src]! It might be a suicide attempt if it weren't so shitty.", \ - "You try to impale yourself with [src], but it's USELESS...") - return SHAME - -/obj/item/claymore - name = "claymore" - desc = "What are you standing around staring at this for? Get to killing!" - icon_state = "claymore" - item_state = "claymore" - lefthand_file = 'icons/mob/inhands/weapons/swords_lefthand.dmi' - righthand_file = 'icons/mob/inhands/weapons/swords_righthand.dmi' - hitsound = 'sound/weapons/bladeslice.ogg' - flags_1 = CONDUCT_1 - slot_flags = SLOT_BELT | SLOT_BACK - force = 40 - throwforce = 10 - w_class = WEIGHT_CLASS_NORMAL - attack_verb = list("attacked", "slashed", "stabbed", "sliced", "torn", "ripped", "diced", "cut") - block_chance = 50 - sharpness = IS_SHARP - max_integrity = 200 - armor = list(melee = 0, bullet = 0, laser = 0, energy = 0, bomb = 0, bio = 0, rad = 0, fire = 100, acid = 50) - resistance_flags = FIRE_PROOF - -/obj/item/claymore/suicide_act(mob/user) - user.visible_message("[user] is falling on [src]! It looks like [user.p_theyre()] trying to commit suicide!") - return(BRUTELOSS) - -/obj/item/claymore/highlander //ALL COMMENTS MADE REGARDING THIS SWORD MUST BE MADE IN ALL CAPS - desc = "THERE CAN BE ONLY ONE, AND IT WILL BE YOU!!!\nActivate it in your hand to point to the nearest victim." - flags_1 = CONDUCT_1 | NODROP_1 | DROPDEL_1 - slot_flags = null - block_chance = 0 //RNG WON'T HELP YOU NOW, PANSY - luminosity = 3 - attack_verb = list("brutalized", "eviscerated", "disemboweled", "hacked", "carved", "cleaved") //ONLY THE MOST VISCERAL ATTACK VERBS - var/notches = 0 //HOW MANY PEOPLE HAVE BEEN SLAIN WITH THIS BLADE - var/obj/item/disk/nuclear/nuke_disk //OUR STORED NUKE DISK - -/obj/item/claymore/highlander/Initialize() - . = ..() - START_PROCESSING(SSobj, src) - -/obj/item/claymore/highlander/Destroy() - if(nuke_disk) - nuke_disk.forceMove(get_turf(src)) - nuke_disk.visible_message("The nuke disk is vulnerable!") - nuke_disk = null - STOP_PROCESSING(SSobj, src) - return ..() - -/obj/item/claymore/highlander/process() - if(ishuman(loc)) - var/mob/living/carbon/human/H = loc - loc.layer = LARGE_MOB_LAYER //NO HIDING BEHIND PLANTS FOR YOU, DICKWEED (HA GET IT, BECAUSE WEEDS ARE PLANTS) - H.bleedsuppress = TRUE //AND WE WON'T BLEED OUT LIKE COWARDS - else - if(!admin_spawned) - qdel(src) - - -/obj/item/claymore/highlander/pickup(mob/living/user) - to_chat(user, "The power of Scotland protects you! You are shielded from all stuns and knockdowns.") - user.add_stun_absorption("highlander", INFINITY, 1, " is protected by the power of Scotland!", "The power of Scotland absorbs the stun!", " is protected by the power of Scotland!") - user.status_flags += IGNORESLOWDOWN - -/obj/item/claymore/highlander/dropped(mob/living/user) - user.status_flags -= IGNORESLOWDOWN - qdel(src) //If this ever happens, it's because you lost an arm - -/obj/item/claymore/highlander/examine(mob/user) - ..() - to_chat(user, "It has [!notches ? "nothing" : "[notches] notches"] scratched into the blade.") - if(nuke_disk) - to_chat(user, "It's holding the nuke disk!") - -/obj/item/claymore/highlander/attack(mob/living/target, mob/living/user) - . = ..() - if(!QDELETED(target) && iscarbon(target) && target.stat == DEAD && target.mind && target.mind.special_role == "highlander") - user.fully_heal() //STEAL THE LIFE OF OUR FALLEN FOES - add_notch(user) - target.visible_message("[target] crumbles to dust beneath [user]'s blows!", "As you fall, your body crumbles to dust!") - target.dust() - -/obj/item/claymore/highlander/attack_self(mob/living/user) - var/closest_victim - var/closest_distance = 255 - for(var/mob/living/carbon/human/H in GLOB.player_list - user) - if(H.client && H.mind.special_role == "highlander" && (!closest_victim || get_dist(user, closest_victim) < closest_distance)) - closest_victim = H - if(!closest_victim) - to_chat(user, "[src] thrums for a moment and falls dark. Perhaps there's nobody nearby.") - return - to_chat(user, "[src] thrums and points to the [dir2text(get_dir(user, closest_victim))].") - -/obj/item/claymore/highlander/IsReflect() - return 1 //YOU THINK YOUR PUNY LASERS CAN STOP ME? - -/obj/item/claymore/highlander/proc/add_notch(mob/living/user) //DYNAMIC CLAYMORE PROGRESSION SYSTEM - THIS IS THE FUTURE - notches++ - force++ - var/new_name = name - switch(notches) - if(1) - to_chat(user, "Your first kill - hopefully one of many. You scratch a notch into [src]'s blade.") - to_chat(user, "You feel your fallen foe's soul entering your blade, restoring your wounds!") - new_name = "notched claymore" - if(2) - to_chat(user, "Another falls before you. Another soul fuses with your own. Another notch in the blade.") - new_name = "double-notched claymore" - add_atom_colour(rgb(255, 235, 235), ADMIN_COLOUR_PRIORITY) - if(3) - to_chat(user, "You're beginning to relish the thrill of battle.") - new_name = "triple-notched claymore" - add_atom_colour(rgb(255, 215, 215), ADMIN_COLOUR_PRIORITY) - if(4) - to_chat(user, "You've lost count of how many you've killed.") - new_name = "many-notched claymore" - add_atom_colour(rgb(255, 195, 195), ADMIN_COLOUR_PRIORITY) - if(5) - to_chat(user, "Five voices now echo in your mind, cheering the slaughter.") - new_name = "battle-tested claymore" - add_atom_colour(rgb(255, 175, 175), ADMIN_COLOUR_PRIORITY) - if(6) - to_chat(user, "Is this what the vikings felt like? Visions of glory fill your head as you slay your sixth foe.") - new_name = "battle-scarred claymore" - add_atom_colour(rgb(255, 155, 155), ADMIN_COLOUR_PRIORITY) - if(7) - to_chat(user, "Kill. Butcher. Conquer.") - new_name = "vicious claymore" - add_atom_colour(rgb(255, 135, 135), ADMIN_COLOUR_PRIORITY) - if(8) - to_chat(user, "IT NEVER GETS OLD. THE SCREAMING. THE BLOOD AS IT SPRAYS ACROSS YOUR FACE.") - new_name = "bloodthirsty claymore" - add_atom_colour(rgb(255, 115, 115), ADMIN_COLOUR_PRIORITY) - if(9) - to_chat(user, "ANOTHER ONE FALLS TO YOUR BLOWS. ANOTHER WEAKLING UNFIT TO LIVE.") - new_name = "gore-stained claymore" - add_atom_colour(rgb(255, 95, 95), ADMIN_COLOUR_PRIORITY) - if(10) - user.visible_message("[user]'s eyes light up with a vengeful fire!", \ - "YOU FEEL THE POWER OF VALHALLA FLOWING THROUGH YOU! THERE CAN BE ONLY ONE!!!") - user.update_icons() - new_name = "GORE-DRENCHED CLAYMORE OF [pick("THE WHIMSICAL SLAUGHTER", "A THOUSAND SLAUGHTERED CATTLE", "GLORY AND VALHALLA", "ANNIHILATION", "OBLITERATION")]" - icon_state = "claymore_valhalla" - item_state = "cultblade" - remove_atom_colour(ADMIN_COLOUR_PRIORITY) - - name = new_name - playsound(user, 'sound/items/screwdriver2.ogg', 50, 1) - -/obj/item/katana - name = "katana" - desc = "Woefully underpowered in D20" - icon_state = "katana" - item_state = "katana" - lefthand_file = 'icons/mob/inhands/weapons/swords_lefthand.dmi' - righthand_file = 'icons/mob/inhands/weapons/swords_righthand.dmi' - flags_1 = CONDUCT_1 - slot_flags = SLOT_BELT | SLOT_BACK - force = 40 - throwforce = 10 - w_class = WEIGHT_CLASS_NORMAL - hitsound = 'sound/weapons/bladeslice.ogg' - attack_verb = list("attacked", "slashed", "stabbed", "sliced", "torn", "ripped", "diced", "cut") - block_chance = 50 - sharpness = IS_SHARP - max_integrity = 200 - armor = list(melee = 0, bullet = 0, laser = 0, energy = 0, bomb = 0, bio = 0, rad = 0, fire = 100, acid = 50) - resistance_flags = FIRE_PROOF - -/obj/item/katana/cursed - slot_flags = null - -/obj/item/katana/suicide_act(mob/user) - user.visible_message("[user] is slitting [user.p_their()] stomach open with [src]! It looks like [user.p_theyre()] trying to commit seppuku!") - return(BRUTELOSS) - -/obj/item/wirerod - name = "wired rod" - desc = "A rod with some wire wrapped around the top. It'd be easy to attach something to the top bit." - icon_state = "wiredrod" - item_state = "rods" - flags_1 = CONDUCT_1 - force = 9 - throwforce = 10 - w_class = WEIGHT_CLASS_NORMAL - materials = list(MAT_METAL=1150, MAT_GLASS=75) - attack_verb = list("hit", "bludgeoned", "whacked", "bonked") - -/obj/item/wirerod/attackby(obj/item/I, mob/user, params) - if(istype(I, /obj/item/shard)) - var/obj/item/twohanded/spear/S = new /obj/item/twohanded/spear - - remove_item_from_storage(user) - qdel(I) - qdel(src) - - user.put_in_hands(S) - to_chat(user, "You fasten the glass shard to the top of the rod with the cable.") - - else if(istype(I, /obj/item/device/assembly/igniter) && !(I.flags_1 & NODROP_1)) - var/obj/item/melee/baton/cattleprod/P = new /obj/item/melee/baton/cattleprod - - remove_item_from_storage(user) - - to_chat(user, "You fasten [I] to the top of the rod with the cable.") - - qdel(I) - qdel(src) - - user.put_in_hands(P) - else - return ..() - - -/obj/item/throwing_star - name = "throwing star" - desc = "An ancient weapon still used to this day due to it's ease of lodging itself into victim's body parts" - icon_state = "throwingstar" - item_state = "eshield0" - lefthand_file = 'icons/mob/inhands/equipment/shields_lefthand.dmi' - righthand_file = 'icons/mob/inhands/equipment/shields_righthand.dmi' - force = 2 - throwforce = 20 //This is never used on mobs since this has a 100% embed chance. - throw_speed = 4 - embedded_pain_multiplier = 4 - w_class = WEIGHT_CLASS_SMALL - embed_chance = 100 - embedded_fall_chance = 0 //Hahaha! - sharpness = IS_SHARP - materials = list(MAT_METAL=500, MAT_GLASS=500) - resistance_flags = FIRE_PROOF - - -/obj/item/switchblade - name = "switchblade" - icon_state = "switchblade" - lefthand_file = 'icons/mob/inhands/weapons/swords_lefthand.dmi' - righthand_file = 'icons/mob/inhands/weapons/swords_righthand.dmi' - desc = "A sharp, concealable, spring-loaded knife." - flags_1 = CONDUCT_1 - force = 3 - w_class = WEIGHT_CLASS_SMALL - throwforce = 5 - throw_speed = 3 - throw_range = 6 - materials = list(MAT_METAL=12000) - origin_tech = "engineering=3;combat=2" - hitsound = 'sound/weapons/genhit.ogg' - attack_verb = list("stubbed", "poked") - resistance_flags = FIRE_PROOF - var/extended = 0 - -/obj/item/switchblade/attack_self(mob/user) - extended = !extended - playsound(src.loc, 'sound/weapons/batonextend.ogg', 50, 1) - if(extended) - force = 20 - w_class = WEIGHT_CLASS_NORMAL - throwforce = 23 - icon_state = "switchblade_ext" - attack_verb = list("slashed", "stabbed", "sliced", "torn", "ripped", "diced", "cut") - hitsound = 'sound/weapons/bladeslice.ogg' - sharpness = IS_SHARP - else - force = 3 - w_class = WEIGHT_CLASS_SMALL - throwforce = 5 - icon_state = "switchblade" - attack_verb = list("stubbed", "poked") - hitsound = 'sound/weapons/genhit.ogg' - sharpness = IS_BLUNT - -/obj/item/switchblade/suicide_act(mob/user) - user.visible_message("[user] is slitting [user.p_their()] own throat with [src]! It looks like [user.p_theyre()] trying to commit suicide!") - return (BRUTELOSS) - -/obj/item/phone - name = "red phone" - desc = "Should anything ever go wrong..." - icon = 'icons/obj/items_and_weapons.dmi' - icon_state = "red_phone" - force = 3 - throwforce = 2 - throw_speed = 3 - throw_range = 4 - w_class = WEIGHT_CLASS_SMALL - attack_verb = list("called", "rang") - hitsound = 'sound/weapons/ring.ogg' - -/obj/item/phone/suicide_act(mob/user) - if(locate(/obj/structure/chair/stool) in user.loc) - user.visible_message("[user] begins to tie a noose with [src]'s cord! It looks like [user.p_theyre()] trying to commit suicide!") - else - user.visible_message("[user] is strangling [user.p_them()]self with [src]'s cord! It looks like [user.p_theyre()] trying to commit suicide!") - return(OXYLOSS) - -/obj/item/cane - name = "cane" - desc = "A cane used by a true gentleman. Or a clown." - icon = 'icons/obj/items_and_weapons.dmi' - icon_state = "cane" - item_state = "stick" - lefthand_file = 'icons/mob/inhands/weapons/melee_lefthand.dmi' - righthand_file = 'icons/mob/inhands/weapons/melee_righthand.dmi' - force = 5 - throwforce = 5 - w_class = WEIGHT_CLASS_SMALL - materials = list(MAT_METAL=50) - attack_verb = list("bludgeoned", "whacked", "disciplined", "thrashed") - -/obj/item/staff - name = "wizard staff" - desc = "Apparently a staff used by the wizard." - icon = 'icons/obj/wizard.dmi' - icon_state = "staff" - lefthand_file = 'icons/mob/inhands/weapons/staves_lefthand.dmi' - righthand_file = 'icons/mob/inhands/weapons/staves_righthand.dmi' - force = 3 - throwforce = 5 - throw_speed = 2 - throw_range = 5 - w_class = WEIGHT_CLASS_SMALL - armour_penetration = 100 - attack_verb = list("bludgeoned", "whacked", "disciplined") - resistance_flags = FLAMMABLE - -/obj/item/staff/broom - name = "broom" - desc = "Used for sweeping, and flying into the night while cackling. Black cat not included." - icon = 'icons/obj/wizard.dmi' - icon_state = "broom" - resistance_flags = FLAMMABLE - -/obj/item/staff/stick - name = "stick" - desc = "A great tool to drag someone else's drinks across the bar." - icon = 'icons/obj/items_and_weapons.dmi' - icon_state = "stick" - item_state = "stick" - lefthand_file = 'icons/mob/inhands/weapons/melee_lefthand.dmi' - righthand_file = 'icons/mob/inhands/weapons/melee_righthand.dmi' - force = 3 - throwforce = 5 - throw_speed = 2 - throw_range = 5 - w_class = WEIGHT_CLASS_SMALL - -/obj/item/ectoplasm - name = "ectoplasm" - desc = "spooky" - gender = PLURAL - icon = 'icons/obj/wizard.dmi' - icon_state = "ectoplasm" - -/obj/item/ectoplasm/suicide_act(mob/user) - user.visible_message("[user] is inhaling [src]! It looks like [user.p_theyre()] trying to visit the astral plane.") - return (OXYLOSS) - /obj/item/mounted_chainsaw name = "mounted chainsaw" desc = "A chainsaw that has replaced your arm." From a4236145f480dfb394eb9f68aebb4cd5c663b1a0 Mon Sep 17 00:00:00 2001 From: CitadelStationBot Date: Mon, 11 Sep 2017 15:22:28 -0500 Subject: [PATCH 59/74] Automatic changelog generation for PR #2641 [ci skip] --- html/changelogs/AutoChangeLog-pr-2641.yml | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 html/changelogs/AutoChangeLog-pr-2641.yml diff --git a/html/changelogs/AutoChangeLog-pr-2641.yml b/html/changelogs/AutoChangeLog-pr-2641.yml new file mode 100644 index 0000000000..a888615c05 --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-2641.yml @@ -0,0 +1,4 @@ +author: "CitadelStationBot" +delete-after: True +changes: + - rscadd: "Admins may now show the variables interface to players to help contributors debug their new additions" From b6e2f9bfa1e2e54fc36fa2cef06160a4c735db09 Mon Sep 17 00:00:00 2001 From: CitadelStationBot Date: Mon, 11 Sep 2017 15:22:51 -0500 Subject: [PATCH 60/74] Automatic changelog generation for PR #2650 [ci skip] --- html/changelogs/AutoChangeLog-pr-2650.yml | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 html/changelogs/AutoChangeLog-pr-2650.yml diff --git a/html/changelogs/AutoChangeLog-pr-2650.yml b/html/changelogs/AutoChangeLog-pr-2650.yml new file mode 100644 index 0000000000..4e062b977c --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-2650.yml @@ -0,0 +1,4 @@ +author: "Naksu" +delete-after: True +changes: + - rscadd: "Added TGUI interfaces to various smartfridges of different kinds, drying racks and the disk compartmentalizer" From 9adcc174b3d5bf5da98fbc53883b7f8566a986f7 Mon Sep 17 00:00:00 2001 From: LetterJay Date: Mon, 11 Sep 2017 17:09:44 -0500 Subject: [PATCH 61/74] Update shuttle.dm --- code/modules/shuttle/shuttle.dm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/modules/shuttle/shuttle.dm b/code/modules/shuttle/shuttle.dm index f035777df5..4326e6298e 100644 --- a/code/modules/shuttle/shuttle.dm +++ b/code/modules/shuttle/shuttle.dm @@ -570,7 +570,7 @@ move_mode = moving_atom.beforeShuttleMove(newT, rotation, move_mode) //atoms move_mode = oldT.fromShuttleMove(newT, underlying_turf_type, baseturf_cache, move_mode) //turfs - move_mode = newT.toShuttleMove(oldT, dir, move_mode) //turfs + move_mode = newT.toShuttleMove(oldT, move_mode , src) //turfs if(move_mode & MOVE_AREA) areas_to_move[old_area] = TRUE From ea82bf9bfaf5cce8393c0c29485d5caf7dca5044 Mon Sep 17 00:00:00 2001 From: LetterJay Date: Mon, 11 Sep 2017 17:47:48 -0500 Subject: [PATCH 62/74] Update suit_storage_unit.dm --- code/game/machinery/suit_storage_unit.dm | 244 ----------------------- 1 file changed, 244 deletions(-) diff --git a/code/game/machinery/suit_storage_unit.dm b/code/game/machinery/suit_storage_unit.dm index be89a3d2e6..a78fa50a6a 100644 --- a/code/game/machinery/suit_storage_unit.dm +++ b/code/game/machinery/suit_storage_unit.dm @@ -26,100 +26,6 @@ var/uv = FALSE var/uv_super = FALSE var/uv_cycles = 6 - -/obj/machinery/suit_storage_unit/standard_unit - suit_type = /obj/item/clothing/suit/space/eva - helmet_type = /obj/item/clothing/head/helmet/space/eva - mask_type = /obj/item/clothing/mask/breath - -/obj/machinery/suit_storage_unit/captain - suit_type = /obj/item/clothing/suit/space/hardsuit/captain - mask_type = /obj/item/clothing/mask/gas/sechailer - storage_type = /obj/item/tank/jetpack/oxygen/captain - -/obj/machinery/suit_storage_unit/engine - suit_type = /obj/item/clothing/suit/space/hardsuit/engine - mask_type = /obj/item/clothing/mask/breath - -/obj/machinery/suit_storage_unit/ce - suit_type = /obj/item/clothing/suit/space/hardsuit/engine/elite - mask_type = /obj/item/clothing/mask/breath - storage_type= /obj/item/clothing/shoes/magboots/advance - -/obj/machinery/suit_storage_unit/security - suit_type = /obj/item/clothing/suit/space/hardsuit/security - mask_type = /obj/item/clothing/mask/gas/sechailer - -/obj/machinery/suit_storage_unit/hos - suit_type = /obj/item/clothing/suit/space/hardsuit/security/hos - mask_type = /obj/item/clothing/mask/gas/sechailer - storage_type = /obj/item/tank/internals/oxygen - -/obj/machinery/suit_storage_unit/atmos - suit_type = /obj/item/clothing/suit/space/hardsuit/engine/atmos - mask_type = /obj/item/clothing/mask/gas - storage_type = /obj/item/watertank/atmos - -/obj/machinery/suit_storage_unit/mining - suit_type = /obj/item/clothing/suit/hooded/explorer - mask_type = /obj/item/clothing/mask/gas/explorer - -/obj/machinery/suit_storage_unit/mining/eva - suit_type = /obj/item/clothing/suit/space/hardsuit/mining - mask_type = /obj/item/clothing/mask/breath - -/obj/machinery/suit_storage_unit/cmo - suit_type = /obj/item/clothing/suit/space/hardsuit/medical - mask_type = /obj/item/clothing/mask/breath - -/obj/machinery/suit_storage_unit/rd - suit_type = /obj/item/clothing/suit/space/hardsuit/rd - mask_type = /obj/item/clothing/mask/breath - -/obj/machinery/suit_storage_unit/syndicate - suit_type = /obj/item/clothing/suit/space/hardsuit/syndi - mask_type = /obj/item/clothing/mask/gas/syndicate - storage_type = /obj/item/tank/jetpack/oxygen/harness - -/obj/machinery/suit_storage_unit/ert/command - suit_type = /obj/item/clothing/suit/space/hardsuit/ert - mask_type = /obj/item/clothing/mask/breath - storage_type = /obj/item/tank/internals/emergency_oxygen/double - -/obj/machinery/suit_storage_unit/ert/security - suit_type = /obj/item/clothing/suit/space/hardsuit/ert/sec - mask_type = /obj/item/clothing/mask/breath - storage_type = /obj/item/tank/internals/emergency_oxygen/double - -/obj/machinery/suit_storage_unit/ert/engineer - suit_type = /obj/item/clothing/suit/space/hardsuit/ert/engi - mask_type = /obj/item/clothing/mask/breath - storage_type = /obj/item/tank/internals/emergency_oxygen/double - -/obj/machinery/suit_storage_unit/ert/medical - suit_type = /obj/item/clothing/suit/space/hardsuit/ert/med - mask_type = /obj/item/clothing/mask/breath - storage_type = /obj/item/tank/internals/emergency_oxygen/double - max_integrity = 250 - - var/obj/item/clothing/suit/space/suit = null - var/obj/item/clothing/head/helmet/space/helmet = null - var/obj/item/clothing/mask/mask = null - var/obj/item/storage = null - - var/suit_type = null - var/helmet_type = null - var/mask_type = null - var/storage_type = null - - state_open = FALSE - var/locked = FALSE - panel_open = FALSE - var/safeties = TRUE - - var/uv = FALSE - var/uv_super = FALSE - var/uv_cycles = 6 var/message_cooldown var/breakout_time = 0.5 @@ -344,156 +250,6 @@ if(electrocute_mob(user, src, src, 1, TRUE)) return 1 -/obj/machinery/suit_storage_unit/relaymove(mob/user) - container_resist(user) - -/obj/machinery/suit_storage_unit/container_resist(mob/living/user) - add_fingerprint(user) - if(locked) - visible_message("You see [user] kicking against the doors of [src]!", "You start kicking against the doors...") - addtimer(CALLBACK(src, .proc/resist_open, user), 300) - else - open_machine() - dump_contents() - -/obj/machinery/suit_storage_unit/proc/resist_open(mob/user) - if(!state_open && occupant && (user in src) && user.stat == 0) // Check they're still here. - visible_message("You see [user] bursts out of [src]!", "You escape the cramped confines of [src]!") - open_machine() - -/obj/machinery/suit_storage_unit/attackby(obj/item/I, mob/user, params) - if(state_open && is_operational()) - if(istype(I, /obj/item/clothing/suit/space)) - if(suit) - to_chat(user, "The unit already contains a suit!.") - return - if(!user.drop_item()) - return - suit = I - else if(istype(I, /obj/item/clothing/head/helmet)) - if(helmet) - to_chat(user, "The unit already contains a helmet!") - return - if(!user.drop_item()) - return - helmet = I - else if(istype(I, /obj/item/clothing/mask)) - if(mask) - to_chat(user, "The unit already contains a mask!") - return - if(!user.drop_item()) - return - mask = I - else - if(storage) - to_chat(user, "The auxiliary storage compartment is full!") - return - if(!user.drop_item()) - return - storage = I - - I.loc = src - visible_message("[user] inserts [I] into [src]", "You load [I] into [src].") - update_icon() - return - - if(panel_open && is_wire_tool(I)) - wires.interact(user) - if(!state_open) - if(default_deconstruction_screwdriver(user, "panel", "close", I)) - return - if(default_pry_open(I)) - dump_contents() - return - - return ..() - - open_machine() - dump_contents() - new /obj/item/stack/sheet/metal (loc, 2) - qdel(src) - -/obj/machinery/suit_storage_unit/MouseDrop_T(atom/A, mob/user) - if(user.stat || user.lying || !Adjacent(user) || !Adjacent(A) || !isliving(A)) - return - var/mob/living/target = A - if(!state_open) - to_chat(user, "The unit's doors are shut!") - return - if(!is_operational()) - to_chat(user, "The unit is not operational!") - return - if(occupant || helmet || suit || storage) - to_chat(user, "It's too cluttered inside to fit in!") - return - - if(target == user) - user.visible_message("[user] starts squeezing into [src]!", "You start working your way into [src]...") - else - target.visible_message("[user] starts shoving [target] into [src]!", "[user] starts shoving you into [src]!") - - if(do_mob(user, target, 30)) - if(occupant || helmet || suit || storage) - return - if(target == user) - user.visible_message("[user] slips into [src] and closes the door behind them!", "You slip into [src]'s cramped space and shut its door.") - else - target.visible_message("[user] pushes [target] into [src] and shuts its door!", "[user] shoves you into [src] and shuts the door!") - close_machine(target) - add_fingerprint(user) - -/obj/machinery/suit_storage_unit/proc/cook() - if(uv_cycles) - uv_cycles-- - uv = TRUE - locked = TRUE - update_icon() - if(occupant) - var/mob/living/mob_occupant = occupant - if(uv_super) - mob_occupant.adjustFireLoss(rand(20, 36)) - else - mob_occupant.adjustFireLoss(rand(10, 16)) - mob_occupant.emote("scream") - addtimer(CALLBACK(src, .proc/cook), 50) - else - uv_cycles = initial(uv_cycles) - uv = FALSE - locked = FALSE - if(uv_super) - visible_message("[src]'s door creaks open with a loud whining noise. A cloud of foul black smoke escapes from its chamber.") - playsound(src, 'sound/machines/airlock_alien_prying.ogg', 50, 1) - helmet = null - qdel(helmet) - suit = null - qdel(suit) // Delete everything but the occupant. - mask = null - qdel(mask) - storage = null - qdel(storage) - // The wires get damaged too. - wires.cut_all() - else - if(!occupant) - visible_message("[src]'s door slides open. The glowing yellow lights dim to a gentle green.") - else - visible_message("[src]'s door slides open, barraging you with the nauseating smell of charred flesh.") - playsound(src, 'sound/machines/airlockclose.ogg', 25, 1) - for(var/obj/item/I in src) //Scorches away blood and forensic evidence, although the SSU itself is unaffected - I.clean_blood() - I.fingerprints = list() - open_machine(FALSE) - if(occupant) - dump_contents() - -/obj/machinery/suit_storage_unit/proc/shock(mob/user, prb) - if(!prob(prb)) - var/datum/effect_system/spark_spread/s = new /datum/effect_system/spark_spread - s.set_up(5, 1, src) - s.start() - if(electrocute_mob(user, src, src, 1, TRUE)) - return 1 - /obj/machinery/suit_storage_unit/relaymove(mob/user) if(locked) if(message_cooldown <= world.time) From c42304737a762acd0e9160b7c7b1b9b46a069933 Mon Sep 17 00:00:00 2001 From: LetterJay Date: Mon, 11 Sep 2017 17:47:55 -0500 Subject: [PATCH 63/74] Update implantchair.dm --- .../objects/items/implants/implantchair.dm | 188 ------------------ 1 file changed, 188 deletions(-) diff --git a/code/game/objects/items/implants/implantchair.dm b/code/game/objects/items/implants/implantchair.dm index 30a55ab54e..2f59020cbe 100644 --- a/code/game/objects/items/implants/implantchair.dm +++ b/code/game/objects/items/implants/implantchair.dm @@ -1,191 +1,3 @@ - -/obj/machinery/implantchair - name = "mindshield implanter" - desc = "Used to implant occupants with mindshield implants." - icon = 'icons/obj/machines/implantchair.dmi' - icon_state = "implantchair" - density = TRUE - opacity = 0 - anchored = TRUE - - var/ready = TRUE - var/replenishing = FALSE - - var/ready_implants = 5 - var/max_implants = 5 - var/injection_cooldown = 600 - var/replenish_cooldown = 6000 - var/implant_type = /obj/item/implant/mindshield - var/auto_inject = FALSE - var/auto_replenish = TRUE - var/special = FALSE - var/special_name = "special function" - -/obj/machinery/implantchair/Initialize() - . = ..() - open_machine() - update_icon() - - -/obj/machinery/implantchair/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = FALSE, datum/tgui/master_ui = null, datum/ui_state/state = GLOB.notcontained_state) - ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open) - if(!ui) - ui = new(user, src, ui_key, "implantchair", name, 375, 280, master_ui, state) - ui.open() - - -/obj/machinery/implantchair/ui_data() - var/list/data = list() - data["occupied"] = occupant ? 1 : 0 - data["open"] = state_open - - data["occupant"] = list() - if(occupant) - var/mob/living/mob_occupant = occupant - data["occupant"]["name"] = mob_occupant.name - data["occupant"]["stat"] = mob_occupant.stat - - data["special_name"] = special ? special_name : null - data["ready_implants"] = ready_implants - data["ready"] = ready - data["replenishing"] = replenishing - - return data - -/obj/machinery/implantchair/ui_act(action, params) - if(..()) - return - switch(action) - if("door") - if(state_open) - close_machine() - else - open_machine() - . = TRUE - if("implant") - implant(occupant,usr) - . = TRUE - -/obj/machinery/implantchair/proc/implant(mob/living/M,mob/user) - if (!istype(M)) - return - if(!ready_implants || !ready) - return - if(implant_action(M,user)) - ready_implants-- - if(!replenishing && auto_replenish) - replenishing = TRUE - addtimer(CALLBACK(src,"replenish"),replenish_cooldown) - if(injection_cooldown > 0) - ready = FALSE - addtimer(CALLBACK(src,"set_ready"),injection_cooldown) - else - playsound(get_turf(src), 'sound/machines/buzz-sigh.ogg', 25, 1) - update_icon() - -/obj/machinery/implantchair/proc/implant_action(mob/living/M) - var/obj/item/implant/I = new implant_type - if(I.implant(M)) - visible_message("[M] has been implanted by the [name].") - return 1 - -/obj/machinery/implantchair/update_icon() - icon_state = initial(icon_state) - if(state_open) - icon_state += "_open" - if(occupant) - icon_state += "_occupied" - if(ready) - add_overlay("ready") - else - cut_overlays() - -/obj/machinery/implantchair/proc/replenish() - if(ready_implants < max_implants) - ready_implants++ - if(ready_implants < max_implants) - addtimer(CALLBACK(src,"replenish"),replenish_cooldown) - else - replenishing = FALSE - -/obj/machinery/implantchair/proc/set_ready() - ready = TRUE - update_icon() - -/obj/machinery/implantchair/container_resist(mob/living/user) - if(state_open) - return - user.changeNext_move(CLICK_CD_BREAKOUT) - user.last_special = world.time + CLICK_CD_BREAKOUT - to_chat(user, "You lean on the back of [src] and start pushing the door open... (this will take about about a minute.)") - audible_message("You hear a metallic creaking from [src]!",hearing_distance = 2) - - if(do_after(user, 600, target = src)) - if(!user || user.stat != CONSCIOUS || user.loc != src || state_open) - return - visible_message("[user] successfully broke out of [src]!") - to_chat(user, "You successfully break out of [src]!") - open_machine() - -/obj/machinery/implantchair/relaymove(mob/user) - container_resist(user) - -/obj/machinery/implantchair/MouseDrop_T(mob/target, mob/user) - if(user.stat || user.lying || !Adjacent(user) || !user.Adjacent(target) || !isliving(target) || !user.IsAdvancedToolUser()) - return - close_machine(target) - -/obj/machinery/implantchair/close_machine(mob/living/user) - if((isnull(user) || istype(user)) && state_open) - ..(user) - if(auto_inject && ready && ready_implants > 0) - implant(user,null) - -/obj/machinery/implantchair/genepurge - name = "Genetic purifier" - desc = "Used to purge human genome of foreign influences" - special = TRUE - special_name = "Purge genome" - injection_cooldown = 0 - replenish_cooldown = 300 - -/obj/machinery/implantchair/genepurge/implant_action(mob/living/carbon/human/H,mob/user) - if(!istype(H)) - return 0 - H.set_species(/datum/species/human, 1)//lizards go home - purrbation_remove(H)//remove cats - H.dna.remove_all_mutations()//hulks out - return 1 - - -/obj/machinery/implantchair/brainwash - name = "Neural Imprinter" - desc = "Used to indoctrinate rehabilitate hardened recidivists." - special_name = "Imprint" - injection_cooldown = 3000 - auto_inject = FALSE - auto_replenish = FALSE - special = TRUE - var/objective = "Obey the law. Praise Nanotrasen." - var/custom = FALSE - -/obj/machinery/implantchair/brainwash/implant_action(mob/living/C,mob/user) - if(!istype(C) || !C.mind) // I don't know how this makes any sense for silicons but laws trump objectives anyway. - return 0 - if(custom) - if(!user || !user.Adjacent(src)) - return 0 - objective = stripped_input(usr,"What order do you want to imprint on [C]?","Enter the order","",120) - message_admins("[key_name_admin(user)] set brainwash machine objective to '[objective]'.") - log_game("[key_name_admin(user)] set brainwash machine objective to '[objective]'.") - var/datum/objective/custom_objective = new/datum/objective(objective) - custom_objective.owner = C.mind - C.mind.objectives += custom_objective - C.mind.announce_objectives() - message_admins("[key_name_admin(user)] brainwashed [key_name_admin(C)] with objective '[objective]'.") - log_game("[key_name_admin(user)] brainwashed [key_name_admin(C)] with objective '[objective]'.") - return 1 - /obj/machinery/implantchair name = "mindshield implanter" desc = "Used to implant occupants with mindshield implants." From c3a1c08206f7fc1adf3cb3aca2bb86705bcfde9b Mon Sep 17 00:00:00 2001 From: LetterJay Date: Mon, 11 Sep 2017 17:51:49 -0500 Subject: [PATCH 64/74] Update smartfridge.dm --- .../kitchen_machinery/smartfridge.dm | 94 ++++--------------- 1 file changed, 17 insertions(+), 77 deletions(-) diff --git a/code/modules/food_and_drinks/kitchen_machinery/smartfridge.dm b/code/modules/food_and_drinks/kitchen_machinery/smartfridge.dm index 491da12a81..806fbc1f90 100644 --- a/code/modules/food_and_drinks/kitchen_machinery/smartfridge.dm +++ b/code/modules/food_and_drinks/kitchen_machinery/smartfridge.dm @@ -142,55 +142,8 @@ user.set_machine(src) interact(user) -/******************* -* SmartFridge Menu -********************/ -/obj/machinery/smartfridge/interact(mob/user) - if(stat) - return FALSE -<<<<<<< HEAD - var/dat = "Select an item:
    " - - if (contents.len == 0) - dat += "No product loaded!" - else - var/listofitems = list() - for (var/atom/movable/O in contents) - if (listofitems[O.name]) - listofitems[O.name]++ - else - listofitems[O.name] = 1 - sortList(listofitems) - - for (var/O in listofitems) - if(listofitems[O] <= 0) - continue - var/N = listofitems[O] - var/itemName = url_encode(O) - dat += "[capitalize(O)]:" - dat += " [N] " - dat += "Vend " - if(N > 5) - dat += "(x5)" - if(N > 10) - dat += "(x10)" - if(N > 25) - dat += "(x25)" - if(N > 1) - dat += "(All)" - - dat += "
    " - - dat += "
    " - user << browse("[src] supplies[dat]", "window=smartfridge") - onclose(user, "smartfridge") - return dat - -/obj/machinery/smartfridge/Topic(var/href, var/list/href_list) - if(..()) -======= /obj/machinery/smartfridge/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = FALSE, datum/tgui/master_ui = null, datum/ui_state/state = GLOB.default_state) ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open) if(!ui) @@ -222,23 +175,27 @@ /obj/machinery/smartfridge/ui_act(action, params) . = ..() if(.) ->>>>>>> 5f6b2a9... Merge pull request #30519 from vuonojenmustaturska/smartfridges2electricboogaloo return - usr.set_machine(src) + switch(action) + if("Release") + var/desired = 0 - var/N = href_list["vend"] - var/amount = text2num(href_list["amount"]) + if (params["amount"]) + desired = text2num(params["amount"]) + else + desired = input("How many items?", "How many items would you like to take out?", 1) as null|num - var/i = amount - for(var/obj/O in contents) - if(i <= 0) - break - if(O.name == N) - O.loc = src.loc - i-- + if(QDELETED(src) || QDELETED(usr) || !usr.Adjacent(src)) // Sanity checkin' in case stupid stuff happens while we wait for input() + return FALSE - - updateUsrDialog() + for(var/obj/item/O in src) + if(desired <= 0) + break + if(O.name == params["name"]) + O.forceMove(drop_location()) + desired-- + return TRUE + return FALSE // ---------------------------- @@ -274,22 +231,6 @@ /obj/machinery/smartfridge/drying_rack/default_deconstruction_crowbar(obj/item/crowbar/C, ignore_panel = 1) ..() -<<<<<<< HEAD -/obj/machinery/smartfridge/drying_rack/interact(mob/user) - var/dat = ..() - if(dat) - dat += "
    " - dat += "Toggle Drying " - user << browse("[src] supplies[dat]", "window=smartfridge") - onclose(user, "smartfridge") - -/obj/machinery/smartfridge/drying_rack/Topic(href, list/href_list) - ..() - if(href_list["dry"]) - toggle_drying(FALSE) - updateUsrDialog() - update_icon() -======= /obj/machinery/smartfridge/drying_rack/ui_data(mob/user) . = ..() .["isdryer"] = TRUE @@ -307,7 +248,6 @@ toggle_drying(FALSE) return TRUE return FALSE ->>>>>>> 5f6b2a9... Merge pull request #30519 from vuonojenmustaturska/smartfridges2electricboogaloo /obj/machinery/smartfridge/drying_rack/power_change() if(powered() && anchored) From bfe633540a6296842f1abf5d01b6eeac1f5af8ca Mon Sep 17 00:00:00 2001 From: LetterJay Date: Mon, 11 Sep 2017 17:55:35 -0500 Subject: [PATCH 65/74] Update human_movement.dm --- .../mob/living/carbon/human/human_movement.dm | 80 +++---------------- 1 file changed, 12 insertions(+), 68 deletions(-) diff --git a/code/modules/mob/living/carbon/human/human_movement.dm b/code/modules/mob/living/carbon/human/human_movement.dm index d01048c69a..06f3007e6b 100644 --- a/code/modules/mob/living/carbon/human/human_movement.dm +++ b/code/modules/mob/living/carbon/human/human_movement.dm @@ -1,72 +1,17 @@ -/mob/living/carbon/human/movement_delay() - . = 0 - . += ..() - . += config.human_delay - . += dna.species.movement_delay(src) - -/mob/living/carbon/human/slip(knockdown_amount, obj/O, lube) +/mob/living/carbon/human/movement_delay() + . = 0 + . += ..() + . += config.human_delay + . += dna.species.movement_delay(src) + +/mob/living/carbon/human/slip(knockdown_amount, obj/O, lube) if(isobj(shoes) && (shoes.flags_1&NOSLIP_1) && !(lube&GALOSHES_DONT_HELP)) - return 0 - return ..() - -/mob/living/carbon/human/experience_pressure_difference() - playsound(src, 'sound/effects/space_wind.ogg', 50, 1) + return 0 + return ..() + +/mob/living/carbon/human/experience_pressure_difference() + playsound(src, 'sound/effects/space_wind.ogg', 50, 1) if(shoes && shoes.flags_1&NOSLIP_1) -<<<<<<< HEAD - return 0 - return ..() - -/mob/living/carbon/human/mob_has_gravity() - . = ..() - if(!.) - if(mob_negates_gravity()) - . = 1 - -/mob/living/carbon/human/mob_negates_gravity() - return ((shoes && shoes.negates_gravity()) || dna.species.negates_gravity(src)) - -/mob/living/carbon/human/Move(NewLoc, direct) - . = ..() - for(var/datum/mutation/human/HM in dna.mutations) - HM.on_move(src, NewLoc) - if(shoes) - if(!lying && !buckled) - if(loc == NewLoc) - if(!has_gravity(loc)) - return - var/obj/item/clothing/shoes/S = shoes - - //Bloody footprints - var/turf/T = get_turf(src) - if(S.bloody_shoes && S.bloody_shoes[S.blood_state]) - var/obj/effect/decal/cleanable/blood/footprints/oldFP = locate(/obj/effect/decal/cleanable/blood/footprints) in T - if(oldFP && oldFP.blood_state == S.blood_state) - return - else - //No oldFP or it's a different kind of blood - S.bloody_shoes[S.blood_state] = max(0, S.bloody_shoes[S.blood_state]-BLOOD_LOSS_PER_STEP) - var/obj/effect/decal/cleanable/blood/footprints/FP = new /obj/effect/decal/cleanable/blood/footprints(T) - FP.blood_state = S.blood_state - FP.entered_dirs |= dir - FP.bloodiness = S.bloody_shoes[S.blood_state] - if(S.blood_DNA && S.blood_DNA.len) - FP.transfer_blood_dna(S.blood_DNA) - FP.update_icon() - update_inv_shoes() - //End bloody footprints - - S.step_action() - -/mob/living/carbon/human/Moved() - . = ..() - if(buckled_mobs && buckled_mobs.len && riding_datum) - riding_datum.on_vehicle_move() - -/mob/living/carbon/human/Process_Spacemove(movement_dir = 0) //Temporary laziness thing. Will change to handles by species reee. - if(..()) - return 1 - return dna.species.space_move(src) -======= return 0 return ..() @@ -120,4 +65,3 @@ if(..()) return 1 return dna.species.space_move(src) ->>>>>>> 96a55aa... People in soft crit will leave blood trails when dragging themselves/Will take less damage in soft crit (#30482) From 933d9f5f6925e6c33e7da9a9e812988d2354b5f7 Mon Sep 17 00:00:00 2001 From: LetterJay Date: Mon, 11 Sep 2017 18:09:03 -0500 Subject: [PATCH 66/74] Delete tgstation.dme.rej --- tgstation.dme.rej | 9 --------- 1 file changed, 9 deletions(-) delete mode 100644 tgstation.dme.rej diff --git a/tgstation.dme.rej b/tgstation.dme.rej deleted file mode 100644 index 82c613607a..0000000000 --- a/tgstation.dme.rej +++ /dev/null @@ -1,9 +0,0 @@ -diff a/tgstation.dme b/tgstation.dme (rejected hunks) -@@ -793,7 +794,6 @@ - #include "code\game\objects\items\devices\megaphone.dm" - #include "code\game\objects\items\devices\multitool.dm" - #include "code\game\objects\items\devices\paicard.dm" --#include "code\game\objects\items\devices\pinpointer.dm" - #include "code\game\objects\items\devices\pipe_painter.dm" - #include "code\game\objects\items\devices\powersink.dm" - #include "code\game\objects\items\devices\pressureplates.dm" From bf5094cf19504604de9ba9373eb360fdccb55b27 Mon Sep 17 00:00:00 2001 From: LetterJay Date: Mon, 11 Sep 2017 18:40:30 -0500 Subject: [PATCH 67/74] Update nuclearbomb.dm --- code/game/gamemodes/nuclear/nuclearbomb.dm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/game/gamemodes/nuclear/nuclearbomb.dm b/code/game/gamemodes/nuclear/nuclearbomb.dm index 5245b00c35..95fc735ec6 100644 --- a/code/game/gamemodes/nuclear/nuclearbomb.dm +++ b/code/game/gamemodes/nuclear/nuclearbomb.dm @@ -388,7 +388,7 @@ bomb_set = FALSE detonation_timer = null set_security_level(previous_level) - for(var/obj/item/pinpointer/syndicate/S in GLOB.pinpointer_list) + for(var/obj/item/pinpointer/nuke/syndicate/S in GLOB.pinpointer_list) S.switch_mode_to(initial(S.mode)) S.alert = FALSE countdown.stop() From 37600510746186798e6486ae51cfbd1506aad422 Mon Sep 17 00:00:00 2001 From: CitadelStationBot Date: Mon, 11 Sep 2017 18:45:24 -0500 Subject: [PATCH 68/74] Automatic changelog generation for PR #2678 [ci skip] --- html/changelogs/AutoChangeLog-pr-2678.yml | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 html/changelogs/AutoChangeLog-pr-2678.yml diff --git a/html/changelogs/AutoChangeLog-pr-2678.yml b/html/changelogs/AutoChangeLog-pr-2678.yml new file mode 100644 index 0000000000..cf518a6179 --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-2678.yml @@ -0,0 +1,5 @@ +author: "Kor" +delete-after: True +changes: + - rscadd: "People in soft crit will take oxyloss more slowly than people in full crit if they remain still." + - rscadd: "People dragging themselves in critical condition will now leave blood trails. This will rapidly deal oxyloss to you." From 2629d3b87ddf5405f9b09279e9adaf025d99ce72 Mon Sep 17 00:00:00 2001 From: Poojawa Date: Mon, 11 Sep 2017 20:22:21 -0500 Subject: [PATCH 69/74] Adds horse, cow tails, Sergal ears/tails also (#2695) * Adds horse, sergal, cow tails * Slight tweaks before bed * sprite tweaks --- .../new_player/sprite_accessories_Citadel.dm | 263 +++++++++++------- icons/mob/mam_bodyparts.dmi | Bin 49503 -> 50903 bytes 2 files changed, 163 insertions(+), 100 deletions(-) diff --git a/code/modules/mob/dead/new_player/sprite_accessories_Citadel.dm b/code/modules/mob/dead/new_player/sprite_accessories_Citadel.dm index 648e6170fa..228c9fe6e7 100644 --- a/code/modules/mob/dead/new_player/sprite_accessories_Citadel.dm +++ b/code/modules/mob/dead/new_player/sprite_accessories_Citadel.dm @@ -1,8 +1,8 @@ /datum/sprite_accessory - var/extra = 0 + var/extra = FALSE var/extra_icon = 'icons/mob/mam_bodyparts.dmi' var/extra_color_src = MUTCOLORS2 //The color source for the extra overlay. - var/extra2 = 0 + var/extra2 = FALSE var/extra2_icon = 'icons/mob/mam_bodyparts.dmi' var/extra2_color_src = MUTCOLORS3 // var/list/ckeys_allowed = null @@ -13,6 +13,10 @@ icon = 'icons/mob/mam_bodyparts.dmi' */ +/***************** Alphabetical Order please *************** +************* Keep it to Ears, Tails, Tails Animated *********/ + + /datum/sprite_accessory/tails/lizard/none name = "None" icon_state = "None" @@ -31,12 +35,17 @@ color_src = 0 icon = 'icons/mob/mam_bodyparts.dmi' +/datum/sprite_accessory/ears/human/bear + name = "Bear" + icon_state = "bear" + icon = 'icons/mob/mam_bodyparts.dmi' + /datum/sprite_accessory/tails/human/bear name = "Bear" icon_state = "bear" icon = 'icons/mob/mam_bodyparts.dmi' -/datum/sprite_accessory/ears/human/bear +/datum/sprite_accessory/tails_animated/human/bear name = "Bear" icon_state = "bear" icon = 'icons/mob/mam_bodyparts.dmi' @@ -51,10 +60,27 @@ icon_state = "catbig" icon = 'icons/mob/mam_bodyparts.dmi' +/datum/sprite_accessory/ears/human/cow + name = "Cow" + icon_state = "cow" + icon = 'icons/mob/mam_bodyparts.dmi' + gender_specific = 1 + +/datum/sprite_accessory/tails/human/cow + name = "Cow" + icon_state = "cow" + icon = 'icons/mob/mam_bodyparts.dmi' + +/datum/sprite_accessory/tails_animated/human/cow + name = "Cow" + icon_state = "cow" + icon = 'icons/mob/mam_bodyparts.dmi' + /datum/sprite_accessory/ears/fennec name = "Fennec" icon_state = "fennec" icon = 'icons/mob/mam_bodyparts.dmi' + hasinner = 1 /datum/sprite_accessory/tails/human/fennec name = "Fennec" @@ -76,37 +102,49 @@ name = "Fox" icon_state = "fox" icon = 'icons/mob/mam_bodyparts.dmi' - extra = 1 + extra = TRUE /datum/sprite_accessory/tails_animated/human/fox name = "Fox" icon_state = "fox" icon = 'icons/mob/mam_bodyparts.dmi' - extra = 1 + extra = TRUE + +/datum/sprite_accessory/tails/human/horse + name = "Horse" + icon_state = "horse" + icon = 'icons/mob/mam_bodyparts.dmi' + color_src = HAIR + +/datum/sprite_accessory/tails_animated/human/horse + name = "Horse" + icon_state = "horse" + icon = 'icons/mob/mam_bodyparts.dmi' + color_src = HAIR /datum/sprite_accessory/tails/human/husky name = "Husky" icon_state = "husky" icon = 'icons/mob/mam_bodyparts.dmi' - extra = 1 + extra = TRUE /datum/sprite_accessory/tails_animated/human/husky name = "Husky" icon_state = "husky" icon = 'icons/mob/mam_bodyparts.dmi' - extra = 1 + extra = TRUE /datum/sprite_accessory/tails/human/kitsune name = "Kitsune" icon_state = "kitsune" - extra = 1 + extra = TRUE extra_color_src = MUTCOLORS2 icon = 'icons/mob/mam_bodyparts.dmi' /datum/sprite_accessory/tails_animated/human/kitsune name = "Kitsune" icon_state = "kitsune" - extra = 1 + extra = TRUE extra_color_src = MUTCOLORS2 icon = 'icons/mob/mam_bodyparts.dmi' @@ -146,6 +184,24 @@ name = "Otusian" icon_state = "otie" +/datum/sprite_accessory/ears/human/rabbit + name = "Rabbit" + icon_state = "rabbit" + hasinner= 1 + icon = 'icons/mob/mam_bodyparts.dmi' + +/datum/sprite_accessory/tails/human/rabbit + name = "Rabbit" + icon_state = "rabbit" + color_src = 0 + icon = 'icons/mob/mam_bodyparts.dmi' + +/datum/sprite_accessory/tails_animated/human/rabbit + name = "Rabbit" + icon_state = "rabbit" + color_src = 0 + icon = 'icons/mob/mam_bodyparts.dmi' + /datum/sprite_accessory/ears/human/skunk name = "skunk" icon_state = "skunk" @@ -191,7 +247,7 @@ /datum/sprite_accessory/ears/wolf name = "Wolf" icon_state = "wolf" - extra = 1 + hasinner = 1 /datum/sprite_accessory/tails/human/wolf name = "Wolf" @@ -203,18 +259,6 @@ icon_state = "wolf" icon = 'icons/mob/mam_bodyparts.dmi' -/datum/sprite_accessory/tails/human/rabbit - name = "Rabbit" - icon_state = "rabbit" - color_src = 0 - icon = 'icons/mob/mam_bodyparts.dmi' - -/datum/sprite_accessory/ears/human/rabbit - name = "Rabbit" - icon_state = "rabbit" - hasinner= 1 - icon = 'icons/mob/mam_bodyparts.dmi' - /****************************************** *************** Body Parts **************** *******************************************/ @@ -248,36 +292,37 @@ name = "Beak" icon_state = "bird" icon = 'icons/mob/mam_bodyparts.dmi' + color_src = MUTCOLORS3 /datum/sprite_accessory/snouts/lcanid name = "Fox, Long" icon_state = "lcanid" icon = 'icons/mob/mam_bodyparts.dmi' - extra = 1 + extra = TRUE /datum/sprite_accessory/snouts/scanid name = "Fox, Short" icon_state = "scanid" icon = 'icons/mob/mam_bodyparts.dmi' - extra = 1 + extra = TRUE /datum/sprite_accessory/snouts/wolf name = "Wolf" icon_state = "wolf" icon = 'icons/mob/mam_bodyparts.dmi' - extra = 1 + extra = TRUE /datum/sprite_accessory/snouts/husky name = "Husky" icon_state = "husky" icon = 'icons/mob/mam_bodyparts.dmi' - extra = 1 + extra = TRUE /datum/sprite_accessory/snouts/otie name = "Otie" icon_state = "otie" icon = 'icons/mob/mam_bodyparts.dmi' - extra = 1 + extra = TRUE /****************************************** ************ Actual Species *************** @@ -286,31 +331,30 @@ /datum/sprite_accessory/mam_tails/ailurus name = "Ailurus" icon_state = "ailurus" - extra = 1 - extra_color_src = MUTCOLORS2 + extra = TRUE /datum/sprite_accessory/mam_tails_animated/ailurus name = "Ailurus" icon_state = "ailurus" - extra = 1 - extra_color_src = MUTCOLORS2 - -/datum/sprite_accessory/mam_tails/bear - name = "Bear" - icon_state = "bear" - icon = 'icons/mob/mam_bodyparts.dmi' + extra = TRUE /datum/sprite_accessory/mam_ears/bear name = "Bear" icon_state = "bear" - icon = 'icons/mob/mam_bodyparts.dmi' + +/datum/sprite_accessory/mam_tails/bear + name = "Bear" + icon_state = "bear" + +/datum/sprite_accessory/mam_tails_animated/bear + name = "Bear" + icon_state = "bear" /datum/sprite_accessory/mam_ears/catbig name = "Cat, Big" icon_state = "cat" hasinner = 1 - icon = 'icons/mob/mutant_bodyparts.dmi' - + /datum/sprite_accessory/mam_tails/catbig name = "Cat, Big" icon_state = "catbig" @@ -323,6 +367,14 @@ name = "Cow" icon_state = "cow" gender_specific = 1 + +/datum/sprite_accessory/mam_tail/cow + name = "Cow" + icon_state = "cow" + +/datum/sprite_accessory/mam_tails_animated/cow + name = "Cow" + icon_state = "cow" /datum/sprite_accessory/mam_ears/deer name = "Deer" @@ -331,8 +383,7 @@ /datum/sprite_accessory/mam_tails/eevee name = "Eevee" icon_state = "eevee" - extra = 1 - extra_color_src = MUTCOLORS2 + extra = TRUE /datum/sprite_accessory/mam_ears/eevee name = "Eevee" @@ -341,8 +392,7 @@ /datum/sprite_accessory/mam_tails_animated/eevee name = "Eevee" icon_state = "eevee" - extra = 1 - extra_color_src = MUTCOLORS2 + extra = TRUE /datum/sprite_accessory/mam_ears/fennec name = "Fennec" @@ -360,25 +410,17 @@ /datum/sprite_accessory/mam_ears/fox name = "Fox" icon_state = "fox" - hasinner = 0 + hasinner = 1 /datum/sprite_accessory/mam_tails/fox name = "Fox" icon_state = "fox" - extra = 1 - extra_color_src = MUTCOLORS2 + extra = TRUE /datum/sprite_accessory/mam_tails_animated/fox name = "Fox" icon_state = "fox" - extra = 1 - extra_color_src = MUTCOLORS2 - -/datum/sprite_accessory/mam_ears/husky - name = "Husky" - icon_state = "wolf" - icon = 'icons/mob/mam_bodyparts.dmi' - extra = 1 + extra = TRUE /datum/sprite_accessory/mam_tails/hawk name = "Hawk" @@ -388,20 +430,36 @@ name = "Hawk" icon_state = "hawk" +/datum/sprite_accessory/mam_tails/horse + name = "Horse" + icon_state = "horse" + color_src = HAIR + +/datum/sprite_accessory/mam_tails_animated/horse + name = "Horse" + icon_state = "Horse" + color_src = HAIR + +/datum/sprite_accessory/mam_ears/husky + name = "Husky" + icon_state = "wolf" + icon = 'icons/mob/mam_bodyparts.dmi' + extra = TRUE + /datum/sprite_accessory/mam_tails/husky name = "Husky" icon_state = "husky" - extra = 1 + extra = TRUE /datum/sprite_accessory/mam_tails_animated/husky name = "Husky" icon_state = "husky" - extra = 1 + extra = TRUE /datum/sprite_accessory/mam_ears/kangaroo name = "kangaroo" icon_state = "kangaroo" - extra = 1 + extra = TRUE /datum/sprite_accessory/mam_tails/kangaroo name = "kangaroo" @@ -414,14 +472,12 @@ /datum/sprite_accessory/mam_tails/kitsune name = "Kitsune" icon_state = "kitsune" - extra = 1 - extra_color_src = MUTCOLORS2 + extra = TRUE /datum/sprite_accessory/mam_tails_animated/kitsune name = "Kitsune" icon_state = "kitsune" - extra = 1 - extra_color_src = MUTCOLORS2 + extra = TRUE /datum/sprite_accessory/mam_ears/lab name = "Dog, Long" @@ -462,6 +518,32 @@ name = "Otusian" icon_state = "otie" +/datum/sprite_accessory/mam_ears/rabbit + name = "Rabbit" + icon_state = "rabbit" + hasinner= 1 + +/datum/sprite_accessory/mam_tails/rabbit + name = "Rabbit" + icon_state = "rabbit" + +/datum/sprite_accessory/mam_tails_animated/rabbit + name = "Rabbit" + icon_state = "rabbit" + +/datum/sprite_accessory/mam_ears/sergal + name = "Sergal" + icon_state = "sergal" + hasinner= 1 + +/datum/sprite_accessory/mam_tails/sergal + name = "Sergal" + icon_state = "sergal" + +/datum/sprite_accessory/mam_tails_animated/sergal + name = "Sergal" + icon_state = "sergal" + /datum/sprite_accessory/mam_ears/skunk name = "skunk" icon_state = "skunk" @@ -470,13 +552,13 @@ name = "skunk" icon_state = "skunk" color_src = 0 - extra = 1 + extra = TRUE /datum/sprite_accessory/mam_tails_animated/skunk name = "skunk" icon_state = "skunk" color_src = 0 - extra = 1 + extra = TRUE /datum/sprite_accessory/mam_tails/shark name = "Shark" @@ -486,19 +568,19 @@ /datum/sprite_accessory/mam_tails_animated/shark name = "Shark" icon_state = "shark" - color_src = 0 + color_src = MUTCOLORS /datum/sprite_accessory/mam_tails/shepherd name = "Shepherd" icon_state = "shepherd" - extra = 1 - extra2 = 1 + extra = TRUE + extra2 = TRUE /datum/sprite_accessory/mam_tails_animated/shepherd name = "Shepherd" icon_state = "shepherd" - extra = 1 - extra2 = 1 + extra = TRUE + extra2 = TRUE /datum/sprite_accessory/mam_ears/squirrel name = "Squirrel" @@ -516,7 +598,7 @@ /datum/sprite_accessory/mam_ears/wolf name = "Wolf" icon_state = "wolf" - extra = 1 + hasinner = 1 /datum/sprite_accessory/mam_tails/wolf name = "Wolf" @@ -526,26 +608,13 @@ name = "Wolf" icon_state = "wolf" -/datum/sprite_accessory/mam_tails/rabbit - name = "Rabbit" - icon_state = "rabbit" - -/datum/sprite_accessory/mam_tails_animated/rabbit - name = "Rabbit" - icon_state = "rabbit" - -/datum/sprite_accessory/mam_ears/rabbit - name = "Rabbit" - icon_state = "rabbit" - hasinner= 1 - /****************************************** ************ Body Markings **************** *******************************************/ /datum/sprite_accessory/mam_body_markings - extra = 1 - extra2 = 1 + extra = TRUE + extra2 = TRUE icon = 'icons/mob/mam_body_markings.dmi' /datum/sprite_accessory/mam_body_markings/none @@ -555,8 +624,6 @@ /datum/sprite_accessory/mam_body_markings/ailurus name = "Red Panda" icon_state = "ailurus" - extra_color_src = MUTCOLORS2 - extra2_color_src = MUTCOLORS3 gender_specific = 1 /datum/sprite_accessory/mam_body_markings/belly @@ -598,13 +665,11 @@ /datum/sprite_accessory/mam_body_markings/fennec name = "Fennec" icon_state = "Fennec" - extra_color_src = MUTCOLORS3 gender_specific = 1 /datum/sprite_accessory/mam_body_markings/fox name = "Fox" icon_state = "fox" - extra_color_src = MUTCOLORS3 gender_specific = 1 /datum/sprite_accessory/mam_body_markings/hawk @@ -668,9 +733,9 @@ /datum/sprite_accessory/taur icon = 'icons/mob/mam_taur.dmi' extra_icon = 'icons/mob/mam_taur.dmi' - extra = 1 + extra = TRUE extra2_icon = 'icons/mob/mam_taur.dmi' - extra2 = 1 + extra2 = TRUE center = TRUE dimension_x = 64 @@ -805,19 +870,17 @@ /datum/sprite_accessory/mam_body_markings/guilmon name = "Guilmon" icon_state = "guilmon" - extra_color_src = MUTCOLORS2 - extra2_color_src = MUTCOLORS3 gender_specific = 1 /datum/sprite_accessory/mam_tails/guilmon name = "Guilmon" icon_state = "guilmon" - extra = 1 + extra = TRUE /datum/sprite_accessory/mam_tails_animated/guilmon name = "Guilmon" icon_state = "guilmon" - extra = 1 + extra = TRUE /datum/sprite_accessory/mam_ears/guilmon name = "Guilmon" @@ -834,33 +897,33 @@ name = "DataShark" icon_state = "datashark" color_src = 0 - + /* //Till I get my snowflake only ckey lock, these are locked-locked :D /datum/sprite_accessory/mam_ears/sabresune name = "sabresune" icon_state = "sabresune" - extra = 1 + extra = TRUE extra_color_src = MUTCOLORS3 locked = TRUE /datum/sprite_accessory/mam_tails/sabresune name = "sabresune" icon_state = "sabresune" - extra = 1 + extra = TRUE locked = TRUE /datum/sprite_accessory/mam_tails_animated/sabresune name = "sabresune" icon_state = "sabresune" - extra = 1 + extra = TRUE /datum/sprite_accessory/mam_body_markings/sabresune name = "Sabresune" icon_state = "sabresune" color_src = MUTCOLORS2 - extra = 0 - extra2 = 0 + extra = FALSE + extra2 = FALSE locked = TRUE */ diff --git a/icons/mob/mam_bodyparts.dmi b/icons/mob/mam_bodyparts.dmi index 8adb82544e63385d9ea08ed94e850c54876b09cc..b8491525a7ade06848bca62bd54734b814218894 100644 GIT binary patch literal 50903 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 literal 49503 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 uflt)3Vq}>CzfsUH7WA6q(*H?6_K@=~{A1sh Date: Mon, 11 Sep 2017 20:22:24 -0500 Subject: [PATCH 70/74] Automatic changelog generation for PR #2695 [ci skip] --- html/changelogs/AutoChangeLog-pr-2695.yml | 7 +++++++ 1 file changed, 7 insertions(+) create mode 100644 html/changelogs/AutoChangeLog-pr-2695.yml diff --git a/html/changelogs/AutoChangeLog-pr-2695.yml b/html/changelogs/AutoChangeLog-pr-2695.yml new file mode 100644 index 0000000000..64cedc7d0d --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-2695.yml @@ -0,0 +1,7 @@ +author: "Poojawa" +delete-after: True +changes: + - rscadd: "Added Horse and Cow tails" + - rscadd: "Added Sergal ears and tails." + - tweak: "Fennec Ears a bit cleaner" + - tweak: "TRUE/FALSE in Citadel Sprites" From 4383f5e70fa92c19948dec339ea8bec6fa3df4ef Mon Sep 17 00:00:00 2001 From: Jordan Brown Date: Mon, 11 Sep 2017 21:59:51 -0400 Subject: [PATCH 71/74] Gives the webhook processor the ability to self update --- .../github_webhook_processor.php | 49 ++++++++++++++----- tools/WebhookProcessor/secret.php | 49 +++++++++++++++++++ 2 files changed, 86 insertions(+), 12 deletions(-) rename tools/{ => WebhookProcessor}/github_webhook_processor.php (93%) create mode 100644 tools/WebhookProcessor/secret.php diff --git a/tools/github_webhook_processor.php b/tools/WebhookProcessor/github_webhook_processor.php similarity index 93% rename from tools/github_webhook_processor.php rename to tools/WebhookProcessor/github_webhook_processor.php index a915c76ad2..6d62309f03 100644 --- a/tools/github_webhook_processor.php +++ b/tools/WebhookProcessor/github_webhook_processor.php @@ -17,20 +17,11 @@ //CONFIG START (all defaults are random examples, do change them) //Use single quotes for config options that are strings. - -//Github lets you have it sign the message with a secret that you can validate. This prevents people from faking events. -//This var should match the secret you configured for this webhook on github. -//This is required as otherwise somebody could trick the script into leaking the api key. + +//These are all default settings that are described in secret.php $hookSecret = '08ajh0qj93209qj90jfq932j32r'; - -$trackPRBalance = true; //set this to false to disable PR balance tracking -$prBalanceJson = ''; //Set this to the path you'd like the writable pr balance file to be stored, not setting it writes it to the working directory -$startingPRBalance = 3; //Starting balance for never before seen users -//team 133041: tgstation/commit-access -$maintainer_team_id = 133041; //org team id that is exempt from PR balance system, setting this to null will use anyone with write access to the repo. Get from https://api.github.com/orgs/:org/teams - -//Api key for pushing changelogs. $apiKey = '209ab8d879c0f987d06a09b9d879c0f987d06a09b9d8787d0a089c'; +<<<<<<< HEAD:tools/github_webhook_processor.php //servers to announce PRs to. $servers = array(); @@ -44,6 +35,22 @@ $servers[1]['address'] = 'game.tgstation13.org'; $servers[1]['port'] = '2337'; $servers[1]['comskey'] = '89aj90cq2fm0amc90832mn9rm90'; */ +======= +$repoOwnerAndName = "tgstation/tgstation"; +$servers = array(); +$enable_live_tracking = true; +$path_to_script = 'tools/WebhookProcessor/github_webhook_processor.php'; +$tracked_branch = "master"; +$trackPRBalance = true; +$prBalanceJson = ''; +$startingPRBalance = 3; +$maintainer_team_id = 133041; +$validation = "org"; +$validation_count = 1; +$tracked_branch = 'master'; + +require_once 'secret.php'; +>>>>>>> 07c1c4a... Gives the webhook processor the ability to self update (#30448):tools/WebhookProcessor/github_webhook_processor.php //CONFIG END set_error_handler(function($severity, $message, $file, $line) { @@ -221,6 +228,7 @@ function handle_pr($payload) { } else { $action = 'merged'; + auto_update($payload); checkchangelog($payload, true, true); update_pr_balance($payload); $validated = TRUE; //pr merged events always get announced. @@ -349,6 +357,23 @@ function update_pr_balance($payload) { fclose($balances_file); } +function auto_update($payload){ + global $enable_live_tracking; + global $path_to_script; + global $repoOwnerAndName; + global $tracked_branch; + if(!$enable_live_tracking || !has_tree_been_edited($payload, $path_to_script) || $payload['pull_request']['base']['ref'] != $tracked_branch) + return; + + $content = file_get_contents('https://raw.githubusercontent.com/' . $repoOwnerAndName . '/' . $tracked_branch . '/'. $path_to_script); + + create_comment($payload, "Edit detected. Self updating... Here is my new code:\n``" . "`HTML+PHP\n" . $content . "\n``" . '`'); + + $code_file = fopen(basename($path_to_script), 'w'); + fwrite($code_file, $content); + fclose($code_file); +} + function has_tree_been_edited($payload, $tree){ //go to the diff url $url = $payload['pull_request']['diff_url']; diff --git a/tools/WebhookProcessor/secret.php b/tools/WebhookProcessor/secret.php new file mode 100644 index 0000000000..abea10564f --- /dev/null +++ b/tools/WebhookProcessor/secret.php @@ -0,0 +1,49 @@ + Date: Mon, 11 Sep 2017 22:28:26 -0500 Subject: [PATCH 72/74] Update github_webhook_processor.php --- .../github_webhook_processor.php | 16 ---------------- 1 file changed, 16 deletions(-) diff --git a/tools/WebhookProcessor/github_webhook_processor.php b/tools/WebhookProcessor/github_webhook_processor.php index 6d62309f03..0ee66acabf 100644 --- a/tools/WebhookProcessor/github_webhook_processor.php +++ b/tools/WebhookProcessor/github_webhook_processor.php @@ -21,21 +21,6 @@ //These are all default settings that are described in secret.php $hookSecret = '08ajh0qj93209qj90jfq932j32r'; $apiKey = '209ab8d879c0f987d06a09b9d879c0f987d06a09b9d8787d0a089c'; -<<<<<<< HEAD:tools/github_webhook_processor.php - -//servers to announce PRs to. -$servers = array(); -/* -$servers[0] = array(); -$servers[0]['address'] = 'game.tgstation13.org'; -$servers[0]['port'] = '1337'; -$servers[0]['comskey'] = '89aj90cq2fm0amc90832mn9rm90'; -$servers[1] = array(); -$servers[1]['address'] = 'game.tgstation13.org'; -$servers[1]['port'] = '2337'; -$servers[1]['comskey'] = '89aj90cq2fm0amc90832mn9rm90'; -*/ -======= $repoOwnerAndName = "tgstation/tgstation"; $servers = array(); $enable_live_tracking = true; @@ -50,7 +35,6 @@ $validation_count = 1; $tracked_branch = 'master'; require_once 'secret.php'; ->>>>>>> 07c1c4a... Gives the webhook processor the ability to self update (#30448):tools/WebhookProcessor/github_webhook_processor.php //CONFIG END set_error_handler(function($severity, $message, $file, $line) { From 1257a2035dbe00f2637996783e2b158ea02375ff Mon Sep 17 00:00:00 2001 From: CitadelStationBot Date: Mon, 11 Sep 2017 22:41:25 -0500 Subject: [PATCH 73/74] Automatic changelog generation for PR #2566 [ci skip] --- html/changelogs/AutoChangeLog-pr-2566.yml | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 html/changelogs/AutoChangeLog-pr-2566.yml diff --git a/html/changelogs/AutoChangeLog-pr-2566.yml b/html/changelogs/AutoChangeLog-pr-2566.yml new file mode 100644 index 0000000000..6059f590d5 --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-2566.yml @@ -0,0 +1,5 @@ +author: "Pubby" +delete-after: True +changes: + - rscadd: "Crew-tracking pinpointers to replace laggy crew monitoring console functionality" + - rscadd: "Crew-tracking pinpointers in medical vendors and the detective's office" From 39687189b64d92b027da2131c78b88ec707a83b8 Mon Sep 17 00:00:00 2001 From: LetterJay Date: Mon, 11 Sep 2017 22:47:27 -0500 Subject: [PATCH 74/74] donation --- code/citadel/custom_loadout/custom_items.dm | 25 +++++++++++++++++++- icons/mob/neck.dmi | Bin 36568 -> 39181 bytes icons/obj/clothing/neck.dmi | Bin 2555 -> 2764 bytes 3 files changed, 24 insertions(+), 1 deletion(-) diff --git a/code/citadel/custom_loadout/custom_items.dm b/code/citadel/custom_loadout/custom_items.dm index 6495d38a0f..da81dfb37c 100644 --- a/code/citadel/custom_loadout/custom_items.dm +++ b/code/citadel/custom_loadout/custom_items.dm @@ -10,6 +10,9 @@ w_class = WEIGHT_CLASS_TINY flags_1 = NOBLUDGEON_1 + +/*Inferno707*/ + /obj/item/clothing/neck/cloak/inferno name = "Kiara's Cloak" desc = "The design on this seems a little too familiar." @@ -19,6 +22,16 @@ w_class = WEIGHT_CLASS_SMALL body_parts_covered = CHEST|GROIN|LEGS|ARMS +/obj/item/clothing/neck/petcollar/inferno + name = "Kiara's Collar" + desc = "A soft black collar that seems to stretch to fit whoever wears it." + icon_state = "infcollar" + item_state = "infcollar" + item_color = null + tagname = null + +/*DirtyOldHarry*/ + /obj/item/lighter/gold name = "\improper Engraved Zippo" desc = "A shiny and relatively expensive zippo lighter. There's a small etched in verse on the bottom that reads, 'No Gods, No Masters, Only Man.'" @@ -30,4 +43,14 @@ slot_flags = SLOT_BELT heat = 1500 resistance_flags = FIRE_PROOF - light_color = LIGHT_COLOR_FIRE \ No newline at end of file + light_color = LIGHT_COLOR_FIRE + + +/*Zombierobin*/ + +/obj/item/clothing/neck/scarf/zomb //Default white color, same functionality as beanies. + name = "A special scarf" + icon_state = "zombscarf" + desc = "A fashionable collar" + item_color = "zombscarf" + dog_fashion = /datum/dog_fashion/head \ No newline at end of file diff --git a/icons/mob/neck.dmi b/icons/mob/neck.dmi index 4618dee14bbe3f2f39095298abe0cbe2130e4cb2..e7c2d4025d5640faab2915fe602ca9e6e0022cdf 100644 GIT binary patch literal 39181 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 literal 36568 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�U}**_8I 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 diff --git a/icons/obj/clothing/neck.dmi b/icons/obj/clothing/neck.dmi index 0f3668ce102b10edb3d8771d178df6bcd28f1bf6..40c4aa03bc72c8232368f640c2d77576b4ff33bd 100644 GIT binary patch delta 2668 zcmV-y3X}Ew6U-GMiBL{Q4GJ0x0000DNk~Le0001>0001h2m=5B0K2`CDUl%*IT#oi zAz_0caE^l^BaR>{f1CiWpa3W+C@n259#?{bB_5=s03;+NlAr)oR8$;GfPgF<>+90I~o8OG`jIJsnb3DNRr&Y-?PIhID;=YmuZUJeB|emX?+?Gcy5l00V#k za{vG*CnvuE07y$DLq;JzMo<V=-0C=30lfiDnFbsyz%~M3>41&Rx3j!ey>pM89+gPMc<# zwr9lgt&RW4-dZTx>G%o7rx<}Xq(HA1E>n4!5q=aw(>U*?v3q^!!k(Jr{eMIJ0T7?+ z$qODjv;Y7IaY;l$RCt{2*Ns=&NDu(<0I?{3peXUYUh5rddqR||g>sxCDA$%qR47I5 zm-zqx6F0NFfk1XPR@;Pk$HZswtuenhyED6L+9dw35s9eBqfzyEEcUqf>$-Y8GWA3$ zjK-&x!q`mWQ9^xoPA!bgtAB;j1+_4iOe7y8)ECvl$khD&lmZxyFD%3rz*r)=L<3VP zU*GKF;;b6DJU_1lt}HAlfeCt!)7m|N#^Ry^2nk%CUtT5)1roTju(CoH3QX|K(o9lT zC~5ZHM+gZt77c?gl*p5*`3NjSDv8nQ_(BwxA(6z`QZfm;rNoR!n133&k-)jxMIDwQ zl|)e?5h{bCLZUcFRO$v&eq@BuWK?LWDcfxDW*OB z?Wtt^9zd)RUGaV`vW#=Px=M{lS8#6E);zu#>M)q^soVGL+5LsOfpbf~KN4A9Ru*t{ zWktI7V$fSKcPvIG_kUR`<~63Ha2K4u&SK2NRxJ|ZN5 zj0g3r=8*{$Jb41K^+EOWERF*ISWgWmIYs#dk1XB@Y#%73iZ=?|2MQ_Q(hMds>G6Ru zv+>OJV=A*L<-zuWLb7xINOI}7a( zTeKVq=NBQQeA7ZG?S2SM@L6U>>=E*uZ9=$y9P-TxA>m`ZsVCGH9A&)tG_eK8c>ZvM z!$s%?Zm|@;%s_0)fI8#N&XHTNlR$F!5DBDq5558uY!ym;ob)oYh15+MP$ZDtJ$M4? z`sE2EPcR~bVt*0Jfau~Y5k72XMn**f=>{0#Ji7mJ9(ls*FF^oG6Uc;^KnCO=+(6D# zG-%v^eNL#Ve?vGBr#UGr5h2Wo`-?wE$JqX>JfV_D7XhS>E)EcbWl(yCafGT7W6y( z#t&E!gMFL0@VAJ>=`%Byo6%2nkBV3}c;0 zfqvtVz-;~C;B8i(L4&7|Y&50`IAx=$R-l8tCf{$=ipAm^tYa#Hr{!|_Z>(ck0(oK_V9BCwgv}zkOY8$W!$xQ^;;2|tRVzA#|290n?2o-|Fe9q}Kk}3gUm43bdc>OqA zr^W`bK_hen!6k@0&XGn2ET{xVt+WAskbjPo)1$)^5-7G{*HjMy+0+8j6pfJRGX(|E ze_ZS&6wuK56!(i|2$OWssv>y~Z`ZliPuF^j_X% zxdf~HR9#j1?lE4c*Px~b?rOWaogAV7$aFwfzwF0`!7sxF)!e{$aP49qakBGx2Y+%1 zKqr&hDDXX8?-&YjIlLn|;4nPbaJ(0J?LXSG@_xsdbhcDo&p&|DauMSUEB{;7RPhKVP zr&&By=<~dF0YcGeq`*rMibf*^;@@ZY2MYb3w=BRZ8jWoOPSt4ofA`@))qnF)AVBOl zn$BpWfdThT-^3BZo_6!0lYiBk1O$(^YGK%SPJ_- z{4D>KTB%louUa4;Pk;1?&w~IOi;#pp;&VUH$L=8sU8Ql`ll?;96%z2SFT8ax$3fuw zbKe7xJKkTMZsQG@+tT`aNz8N@amN}p!P8K<{`~oRcs>lD4v4^DAXM~x#@9pkY4rS# zMcj__SwUm{rFS>Z!k+Urt^wKWg>CSOF<*n2!?9k2x8uGBdnG+EDz>`t<4(C1Pht{3 aBmM=y5Ivq9J!tg+0000-i# zLnRI~k~XKZ6-vypRh%hHmc}#YnR8w~FTTs?y07cLuKV5nr}CyEDa*&pRaQz(3IHJM z?&jntPWT^TCB*)nSMZ~Nq_mq9l1_|cr;~QEiMydHaJLp{9!yKq(Y$#B6xITNe}8ok z7&cH}SXd~CvBasWs!}KvLqkJtZEYfvSim7ezXMPTz)i82mYSKFAx;Ac7@PrsOeS*x z@bIA7*lG9$=-IjWs8IG3_e3*ntwS}?*?QRhKDrtf#~~d|bW|WC>(aCz^W;+q*ady0%#8CF+Dg|kV@OJyXh>(l3ywmX7%`N&*qochW*a$I@U zcirM)>xbz%y9x3db5KTA!vqHarqSKW!9S^rUoL$_%~c7?e3X^;y!ZWZowKJDLgtbJ z+WFUzu&_=*LRlm(ibPpg&CD9^*@TyR44$kx{k*8x^YQv?tI3KTQ%eR5lZTHsrHp?% zkhdw6p2q|fqq=yv3%MMX!&kUF0~9yjy+v)gQGUm!TH)m|N}!7;Nby1NaL$$ya74Tm z%&=}mv7n|VeFXixnzk()Flh$rIRy?ViK&Gp>m5!E_{Bn#1d7G~U%U9(uF6I~=f{VE-`shCJ3|ufOMcFAvR9IF*19LS5~9Ex`8+gffI1CG-fF~| zSxM%Cqu`Nr06baaLfB5)_t|keL&A-gF^Ty=Q1B7#jEbN?sl%aORP&n&H(nHbLiTug z?U|vQ98X&En(&mg7T_Wt$gE+LY+uYg$?JG?T%ex@4+blv2EV$(_+a!qlqHh-NojaA zZ(86GoG&{1niP^-2g~Qt`qScNuO-MCv+Ph2W*XVfb+;9JB zc-zx+OZ$B!VODNz@B{R87|B*#uTH;OwgD5J}rK4S&;?sGDhgb zdy0|Px#@_vf{BUB+k*&Q+>bIT+T~7dd;7#d1C`(qf{$cXY2WO~D5e!bKl(F#tJJ&J z_Won`^lIn)&hoBfTm4C6G78Thau0XG1aIiV#k-96sb7Zd;{2$im%j|Hc!!(zZ?&Q2 zfpSC-vU6Zh?g(z3&1Qej#lN<9pj9F6@1x&;HOEdQqGohiJ4P?#^Lrw7Ym!NJNKaTz zxb%8@wddy`lV~+suoI(lfRJxv#OG3JBQL&mZ*9BtMwWQ%C#<@GPhL)SKHx3Cg!E~5 z{Cu~~u=7gfVDv31Oq?jOJ$1NPF4I%aE z%w!jTbq4G$g4XX&mPx33ZV5NLA?8t_o2NtWudpqx;xd;RXB5m^6Y?Y?e$m|#J6}!3 z^q&nfoiJ^ekYlPowH5FsF-`zGCN(oIQt?3GJVkO76+e;LWYgsa*Vs7w|gte)1p*VxX6Oeypy__*@FQP4XWA!{Od(v>{sH0IOYYD%-_e27l0ED*diHKw`1D+|d?GEfgNF zsn#5O(g{l>+L}*sCs=J;)7~~99*%H|M*n}FBf#qq6B8dE(`iK8L11ML804sc&xmp> z4D(Pcpy9ZG>;Zk(Z_3BUe5Iam+x5K}V+|*3d(DU9;=qbq)$lV-9+)ej6ghygnot~5 zF@m2tmQ|`mN6KFtGPfBhq`MKd;*XplD?IDgxQ1&-{`IG=0vXT_600g*r%>Rt)Fo;0 z8ouq+JBc(%*Al4@S~T(T&GHOH`6|q0Yg0XW9x0xY zlY*{^LE~QtPYSvrh9EH*fMDKgK~`FlL=EdZBlxe?EOA%-r%&=$E5u#8hGialL7p0S z%ITNJrpFi~wp-Ea{ta%geB_)!i}?4H?&E{>aiQLX|(kKh{ z5ZRz&&a+!bu#QG~-@Zahsmq(fbZVCXnl+NW3@ujcFT)+MWrwiS$B%Z4!p(usO4P2EvLoo0MBnO?z8y4N;45xFU*?Jn_ugp0AIy(Gr6?Kn bWe9e5eI*;8$sRBi|0lrR*~{rJotgGOlG{`&