From cdd20308117c28dc1a4a8b32b2c6d32d984b1cd6 Mon Sep 17 00:00:00 2001 From: Arokha Sieyes Date: Sun, 18 Feb 2018 13:03:41 -0600 Subject: [PATCH 1/2] POLARIS: Ports Bay's wall-mounted air pumps --- code/game/machinery/OpTable.dm | 1 + code/game/machinery/oxygen_pump.dm | 243 ++++++++++++++++++++++++++ code/modules/clothing/masks/breath.dm | 14 ++ icons/obj/walllocker.dmi | Bin 1514 -> 2947 bytes nano/templates/Oxygen_pump.tmpl | 42 +++++ polaris.dme | 1 + 6 files changed, 301 insertions(+) create mode 100644 code/game/machinery/oxygen_pump.dm create mode 100644 nano/templates/Oxygen_pump.tmpl diff --git a/code/game/machinery/OpTable.dm b/code/game/machinery/OpTable.dm index 5696892ddc8..ccf3f69529e 100644 --- a/code/game/machinery/OpTable.dm +++ b/code/game/machinery/OpTable.dm @@ -9,6 +9,7 @@ idle_power_usage = 1 active_power_usage = 5 surgery_odds = 100 + throwpass = 1 var/mob/living/carbon/human/victim = null var/strapped = 0.0 var/obj/machinery/computer/operating/computer = null diff --git a/code/game/machinery/oxygen_pump.dm b/code/game/machinery/oxygen_pump.dm new file mode 100644 index 00000000000..7039f9445a5 --- /dev/null +++ b/code/game/machinery/oxygen_pump.dm @@ -0,0 +1,243 @@ +#define TANK_MAX_RELEASE_PRESSURE (3*ONE_ATMOSPHERE) +#define TANK_DEFAULT_RELEASE_PRESSURE ONE_ATMOSPHERE + +/obj/machinery/oxygen_pump + name = "emergency oxygen pump" + icon = 'icons/obj/walllocker.dmi' + desc = "A wall mounted oxygen pump with a retractable face mask that you can pull over your face in case of emergencies." + icon_state = "oxygen_tank" + + anchored = TRUE + + var/obj/item/weapon/tank/tank + var/mob/living/carbon/breather + var/obj/item/clothing/mask/breath/contained + + var/spawn_type = /obj/item/weapon/tank/emergency/oxygen/engi + var/mask_type = /obj/item/clothing/mask/breath/emergency + var/icon_state_open = "oxygen_tank_open" + var/icon_state_closed = "oxygen_tank" + + power_channel = ENVIRON + idle_power_usage = 10 + active_power_usage = 120 // No idea what the realistic amount would be. + +/obj/machinery/oxygen_pump/initialize() + . = ..() + tank = new spawn_type (src) + contained = new mask_type (src) + +/obj/machinery/oxygen_pump/Destroy() + if(breather) + breather.internal = null + if(breather.internals) + breather.internals.icon_state = "internal0" + if(tank) + qdel(tank) + if(breather) + breather.remove_from_mob(contained) + src.visible_message("The mask rapidly retracts just before /the [src] is destroyed!") + qdel(contained) + contained = null + breather = null + return ..() + +/obj/machinery/oxygen_pump/MouseDrop(var/mob/living/carbon/human/target, src_location, over_location) + ..() + if(istype(target) && CanMouseDrop(target)) + if(!can_apply_to_target(target, usr)) // There is no point in attempting to apply a mask if it's impossible. + return + usr.visible_message("\The [usr] begins placing the mask onto [target]..") + if(!do_mob(usr, target, 25) || !can_apply_to_target(target, usr)) + return + // place mask and add fingerprints + usr.visible_message("\The [usr] has placed \the mask on [target]'s mouth.") + attach_mask(target) + src.add_fingerprint(usr) + +/obj/machinery/oxygen_pump/attack_hand(mob/user as mob) + if((stat & MAINT) && tank) + user.visible_message("\The [user] removes \the [tank] from \the [src].", "You remove \the [tank] from \the [src].") + user.put_in_hands(tank) + src.add_fingerprint(user) + tank.add_fingerprint(user) + tank = null + return + if (!tank) + to_chat(user, "There is no tank in \the [src]!") + return + if(breather) + if(tank) + tank.forceMove(src) + breather.remove_from_mob(contained) + contained.forceMove(src) + src.visible_message("\The [user] makes \The [contained] rapidly retracts back into \the [src]!") + if(breather.internals) + breather.internals.icon_state = "internal0" + breather = null + use_power = 1 + +/obj/machinery/oxygen_pump/attack_ai(mob/user as mob) + ui_interact(user) + +/obj/machinery/oxygen_pump/proc/attach_mask(var/mob/living/carbon/C) + if(C && istype(C)) + contained.forceMove(get_turf(C)) + C.equip_to_slot(contained, slot_wear_mask) + if(tank) + tank.forceMove(C) + breather = C + spawn(1) + if(!breather.internal && tank) + breather.internal = tank + if(breather.internals) + breather.internals.icon_state = "internal1" + use_power = 2 + +/obj/machinery/oxygen_pump/proc/can_apply_to_target(var/mob/living/carbon/human/target, mob/user as mob) + if(!user) + user = target + // Check target validity + if(!target.organs_by_name[BP_HEAD]) + to_chat(user, "\The [target] doesn't have a head.") + return + if(!target.check_has_mouth()) + to_chat(user, "\The [target] doesn't have a mouth.") + return + if(target.wear_mask && target != breather) + to_chat(user, "\The [target] is already wearing a mask.") + return + if(target.head && (target.head.body_parts_covered & FACE)) + to_chat(user, "Remove their [target.head] first.") + return + if(!tank) + to_chat(user, "There is no tank in \the [src].") + return + if(stat & MAINT) + to_chat(user, "Please close \the maintenance hatch first.") + return + if(!Adjacent(target)) + to_chat(user, "Please stay close to \the [src].") + return + //when there is a breather: + if(breather && target != breather) + to_chat(user, "\The pump is already in use.") + return + //Checking if breather is still valid + if(target == breather && target.wear_mask != contained) + to_chat(user, "\The [target] is not using the supplied mask.") + return + return 1 + +/obj/machinery/oxygen_pump/attackby(obj/item/weapon/W as obj, mob/user as mob) + if(istype(W,/obj/item/weapon/screwdriver)) + stat ^= MAINT + user.visible_message("\The [user] [stat & MAINT ? "opens" : "closes"] \the [src].", "You [stat & MAINT ? "open" : "close"] \the [src].") + if(stat & MAINT) + icon_state = icon_state_open + if(!stat) + icon_state = icon_state_closed + //TO-DO: Open icon + if(istype(W, /obj/item/weapon/tank) && (stat & MAINT)) + if(tank) + to_chat(user, "\The [src] already has a tank installed!") + else + user.drop_item() + W.forceMove(src) + tank = W + user.visible_message("\The [user] installs \the [tank] into \the [src].", "You install \the [tank] into \the [src].") + src.add_fingerprint(user) + if(istype(W, /obj/item/weapon/tank) && !stat) + to_chat(user, "Please open the maintenance hatch first.") + +/obj/machinery/oxygen_pump/examine(var/mob/user) + . = ..() + if(tank) + to_chat(user, "The meter shows [round(tank.air_contents.return_pressure())]") + else + to_chat(user, "It is missing a tank!") + + +/obj/machinery/oxygen_pump/process() + if(breather) + if(!can_apply_to_target(breather)) + if(tank) + tank.forceMove(src) + breather.remove_from_mob(contained) + contained.forceMove(src) + src.visible_message("\The [contained] rapidly retracts back into \the [src]!") + breather = null + use_power = 1 + else if(!breather.internal && tank) + breather.internal = tank + if(breather.internals) + breather.internals.icon_state = "internal0" + +//Create rightclick to view tank settings +/obj/machinery/oxygen_pump/verb/settings() + set src in oview(1) + set category = "Object" + set name = "Show Tank Settings" + ui_interact(usr) + +//GUI Tank Setup +/obj/machinery/oxygen_pump/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1) + var/data[0] + if(!tank) + to_chat(usr, "It is missing a tank!") + data["tankPressure"] = 0 + data["releasePressure"] = 0 + data["defaultReleasePressure"] = 0 + data["maxReleasePressure"] = 0 + data["maskConnected"] = 0 + data["tankInstalled"] = 0 + // this is the data which will be sent to the ui + if(tank) + data["tankPressure"] = round(tank.air_contents.return_pressure() ? tank.air_contents.return_pressure() : 0) + data["releasePressure"] = round(tank.distribute_pressure ? tank.distribute_pressure : 0) + data["defaultReleasePressure"] = round(TANK_DEFAULT_RELEASE_PRESSURE) + data["maxReleasePressure"] = round(TANK_MAX_RELEASE_PRESSURE) + data["maskConnected"] = 0 + data["tankInstalled"] = 1 + + if(!breather) + data["maskConnected"] = 0 + if(breather) + data["maskConnected"] = 1 + + + // update the ui if it exists, returns null if no ui is passed/found + ui = nanomanager.try_update_ui(user, src, ui_key, ui, data, force_open) + if (!ui) + // the ui does not exist, so we'll create a new() one + // for a list of parameters and their descriptions see the code docs in \code\modules\nano\nanoui.dm + ui = new(user, src, ui_key, "Oxygen_pump.tmpl", "Tank", 500, 300) + // when the ui is first opened this is the data it will use + ui.set_initial_data(data) + // open the new ui window + ui.open() + // auto update every Master Controller tick + ui.set_auto_update(1) + +/obj/machinery/oxygen_pump/Topic(href, href_list) + if(..()) + return 1 + + if (href_list["dist_p"]) + if (href_list["dist_p"] == "reset") + tank.distribute_pressure = TANK_DEFAULT_RELEASE_PRESSURE + else if (href_list["dist_p"] == "max") + tank.distribute_pressure = TANK_MAX_RELEASE_PRESSURE + else + var/cp = text2num(href_list["dist_p"]) + tank.distribute_pressure += cp + tank.distribute_pressure = min(max(round(tank.distribute_pressure), 0), TANK_MAX_RELEASE_PRESSURE) + return 1 + +/obj/machinery/oxygen_pump/anesthetic + name = "anesthetic pump" + spawn_type = /obj/item/weapon/tank/anesthetic + icon_state = "anesthetic_tank" + icon_state_closed = "anesthetic_tank" + icon_state_open = "anesthetic_tank_open" + mask_type = /obj/item/clothing/mask/breath/anesthetic diff --git a/code/modules/clothing/masks/breath.dm b/code/modules/clothing/masks/breath.dm index 48d24bb8c29..ea3e6c7cf4e 100644 --- a/code/modules/clothing/masks/breath.dm +++ b/code/modules/clothing/masks/breath.dm @@ -45,3 +45,17 @@ icon_state = "medical" item_state_slots = list(slot_r_hand_str = "medical", slot_l_hand_str = "medical") permeability_coefficient = 0.01 + +/obj/item/clothing/mask/breath/emergency + desc = "A close-fitting mask that is used by the wallmounted emergency oxygen pump." + name = "emergency mask" + icon_state = "breath" + item_state = "breath" + permeability_coefficient = 0.50 + +/obj/item/clothing/mask/breath/anesthetic + desc = "A close-fitting sterile mask that is used by the anesthetic wallmounted pump." + name = "anesthetic mask" + icon_state = "medical" + item_state = "medical" + permeability_coefficient = 0.01 diff --git a/icons/obj/walllocker.dmi b/icons/obj/walllocker.dmi index 8d43670829d85819d38627c805052b606a974f75..d4d5ced3d253113d52945e4a9f1316fd415808a4 100644 GIT binary patch delta 2914 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 Yi;v?C5GDI+e*gdg07*qoM6N<$f^>YAjQ{`u diff --git a/nano/templates/Oxygen_pump.tmpl b/nano/templates/Oxygen_pump.tmpl new file mode 100644 index 00000000000..9fff202658d --- /dev/null +++ b/nano/templates/Oxygen_pump.tmpl @@ -0,0 +1,42 @@ +{{if data.maskConnected}} +
This pump is connected to a person.
+{{else}} +
This pump is NOT connected to a person.
+{{/if}} + +{{if data.tankInstalled}} +
+
+ Tank Pressure: +
+
+ {{:helper.displayBar(data.tankPressure, 0, 1013, (data.tankPressure > 200) ? 'good' : ((data.tankPressure > 100) ? 'average' : 'bad'))}} +
+ {{:data.tankPressure}} kPa +
+
+
+ +
 
+ +
+
+ Mask Release Pressure: +
+
+ {{:helper.displayBar(data.releasePressure, 0, data.maxReleasePressure, (data.releasePressure >= 23) ? null : ((data.releasePressure >= 17) ? 'average' : 'bad'))}} +
+ {{:helper.link('-', null, {'dist_p' : -10}, (data.releasePressure > 0) ? null : 'disabled')}} + {{:helper.link('-', null, {'dist_p' : -1}, (data.releasePressure > 0) ? null : 'disabled')}} +
 {{:data.releasePressure}} kPa 
+ {{:helper.link('+', null, {'dist_p' : 1}, (data.releasePressure < data.maxReleasePressure) ? null : 'disabled')}} + {{:helper.link('+', null, {'dist_p' : 10}, (data.releasePressure < data.maxReleasePressure) ? null : 'disabled')}} + {{:helper.link('Max', null, {'dist_p' : 'max'}, (data.releasePressure < data.maxReleasePressure) ? null : 'disabled')}} + {{:helper.link('Reset', null, {'dist_p' : 'reset'}, (data.releasePressure != data.defaultReleasePressure) ? null : 'disabled')}} +
+
+
+ +{{else}} +
This pump has no tank installed.
+{{/if}} \ No newline at end of file diff --git a/polaris.dme b/polaris.dme index e026cf9978b..00213716488 100644 --- a/polaris.dme +++ b/polaris.dme @@ -614,6 +614,7 @@ #include "code\game\machinery\nuclear_bomb.dm" #include "code\game\machinery\OpTable.dm" #include "code\game\machinery\overview.dm" +#include "code\game\machinery\oxygen_pump.dm" #include "code\game\machinery\pda_multicaster.dm" #include "code\game\machinery\portable_turret.dm" #include "code\game\machinery\recharger.dm" From 734ef81a18b67fd62a37f6020495a89313f742ed Mon Sep 17 00:00:00 2001 From: Arokha Sieyes Date: Mon, 19 Feb 2018 16:57:31 -0500 Subject: [PATCH 2/2] Improve Destroy() on oxygen_pump --- code/game/machinery/oxygen_pump.dm | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/code/game/machinery/oxygen_pump.dm b/code/game/machinery/oxygen_pump.dm index 7039f9445a5..36db3f83f3c 100644 --- a/code/game/machinery/oxygen_pump.dm +++ b/code/game/machinery/oxygen_pump.dm @@ -32,14 +32,12 @@ breather.internal = null if(breather.internals) breather.internals.icon_state = "internal0" - if(tank) - qdel(tank) - if(breather) breather.remove_from_mob(contained) - src.visible_message("The mask rapidly retracts just before /the [src] is destroyed!") - qdel(contained) - contained = null - breather = null + visible_message("The mask rapidly retracts just before /the [src] is destroyed!") + breather = null + + qdel_null(tank) + qdel_null(contained) return ..() /obj/machinery/oxygen_pump/MouseDrop(var/mob/living/carbon/human/target, src_location, over_location)