diff --git a/code/game/machinery/atmoalter/canister.dm b/code/game/machinery/atmoalter/canister.dm index c79bce5a9b9..27a825e2d5c 100644 --- a/code/game/machinery/atmoalter/canister.dm +++ b/code/game/machinery/atmoalter/canister.dm @@ -374,6 +374,9 @@ update_flag /obj/machinery/portable_atmospherics/canister/attack_alien(mob/living/carbon/alien/humanoid/user) return + +/obj/machinery/portable_atmospherics/canister/attack_ghost(var/mob/user as mob) + return src.ui_interact(user) /obj/machinery/portable_atmospherics/canister/attack_hand(var/mob/user as mob) return src.ui_interact(user) @@ -408,7 +411,7 @@ update_flag 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, "canister.tmpl", "Canister", 480, 400) + ui = new(user, src, ui_key, "canister.tmpl", "Canister", 480, 400, state = physical_state) // when the ui is first opened this is the data it will use ui.set_initial_data(data) // open the new ui window diff --git a/code/game/machinery/atmoalter/portable_atmospherics.dm b/code/game/machinery/atmoalter/portable_atmospherics.dm index b1b13220d56..56c39e8ef27 100644 --- a/code/game/machinery/atmoalter/portable_atmospherics.dm +++ b/code/game/machinery/atmoalter/portable_atmospherics.dm @@ -11,84 +11,83 @@ var/maximum_pressure = 90*ONE_ATMOSPHERE - New() - ..() +/obj/machinery/portable_atmospherics/New() + ..() - air_contents.volume = volume - air_contents.temperature = T20C + air_contents.volume = volume + air_contents.temperature = T20C - return 1 + return 1 - initialize() - . = ..() - spawn() - var/obj/machinery/atmospherics/portables_connector/port = locate() in loc - if(port) - connect(port) - update_icon() - - process() - if(!connected_port) //only react when pipe_network will ont it do it for you - //Allow for reactions - air_contents.react() - else +/obj/machinery/portable_atmospherics/initialize() + . = ..() + spawn() + var/obj/machinery/atmospherics/portables_connector/port = locate() in loc + if(port) + connect(port) update_icon() - Destroy() - qdel(air_contents) +/obj/machinery/portable_atmospherics/process() + if(!connected_port) //only react when pipe_network will ont it do it for you + //Allow for reactions + air_contents.react() + else + update_icon() - return ..() +/obj/machinery/portable_atmospherics/Destroy() + qdel(air_contents) + qdel(holding) + + return ..() - update_icon() - return null +/obj/machinery/portable_atmospherics/update_icon() + return null - proc +/obj/machinery/portable_atmospherics/proc/connect(obj/machinery/atmospherics/portables_connector/new_port) + //Make sure not already connected to something else + if(connected_port || !new_port || new_port.connected_device) + return 0 - connect(obj/machinery/atmospherics/portables_connector/new_port) - //Make sure not already connected to something else - if(connected_port || !new_port || new_port.connected_device) - return 0 + //Make sure are close enough for a valid connection + if(new_port.loc != loc) + return 0 - //Make sure are close enough for a valid connection - if(new_port.loc != loc) - return 0 + //Perform the connection + connected_port = new_port + connected_port.connected_device = src - //Perform the connection - connected_port = new_port - connected_port.connected_device = src + anchored = 1 //Prevent movement - anchored = 1 //Prevent movement + //Actually enforce the air sharing + var/datum/pipe_network/network = connected_port.return_network(src) + if(network && !network.gases.Find(air_contents)) + network.gases += air_contents + network.update = 1 - //Actually enforce the air sharing - var/datum/pipe_network/network = connected_port.return_network(src) - if(network && !network.gases.Find(air_contents)) - network.gases += air_contents - network.update = 1 + return 1 - return 1 +/obj/machinery/portable_atmospherics/proc/update_connected_network() + if(!connected_port) + return - update_connected_network() - if(!connected_port) - return + var/datum/pipe_network/network = connected_port.return_network(src) + if (network) + network.update = 1 - var/datum/pipe_network/network = connected_port.return_network(src) - if (network) - network.update = 1 +/obj/machinery/portable_atmospherics/proc/disconnect() + if(!connected_port) + return 0 - disconnect() - if(!connected_port) - return 0 + var/datum/pipe_network/network = connected_port.return_network(src) + if(network) + network.gases -= air_contents - var/datum/pipe_network/network = connected_port.return_network(src) - if(network) - network.gases -= air_contents + anchored = 0 - anchored = 0 + connected_port.connected_device = null + connected_port = null - connected_port.connected_device = null - connected_port = null - - return 1 + return 1 /obj/machinery/portable_atmospherics/attackby(var/obj/item/weapon/W as obj, var/mob/user as mob, params) if ((istype(W, /obj/item/weapon/tank) && !( src.destroyed ))) diff --git a/code/game/machinery/atmoalter/pump.dm b/code/game/machinery/atmoalter/pump.dm index e5b39164cc3..e9fb01b034c 100644 --- a/code/game/machinery/atmoalter/pump.dm +++ b/code/game/machinery/atmoalter/pump.dm @@ -8,6 +8,9 @@ var/on = 0 var/direction_out = 0 //0 = siphoning, 1 = releasing var/target_pressure = 100 + + var/pressuremin = 0 + var/pressuremax = 10 * ONE_ATMOSPHERE volume = 1000 @@ -95,61 +98,61 @@ /obj/machinery/portable_atmospherics/pump/attack_ai(var/mob/user as mob) src.add_hiddenprint(user) return src.attack_hand(user) + +/obj/machinery/portable_atmospherics/pump/attack_ghost(var/mob/user) + return src.attack_hand(user) /obj/machinery/portable_atmospherics/pump/attack_hand(var/mob/user as mob) + ui_interact(user) + +/obj/machinery/portable_atmospherics/pump/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null) + var/list/data[0] + data["portConnected"] = connected_port ? 1 : 0 + data["tankPressure"] = round(air_contents.return_pressure() > 0 ? air_contents.return_pressure() : 0) + data["targetpressure"] = round(target_pressure) + data["pump_dir"] = direction_out + data["minpressure"] = round(pressuremin) + data["maxpressure"] = round(pressuremax) + data["on"] = on ? 1 : 0 - user.set_machine(src) - var/holding_text + data["hasHoldingTank"] = holding ? 1 : 0 + if (holding) + data["holdingTank"] = list("name" = holding.name, "tankPressure" = round(holding.air_contents.return_pressure() > 0 ? holding.air_contents.return_pressure() : 0)) - if(holding) - holding_text = {"
Tank Pressure: [holding.air_contents.return_pressure()] KPa
-Remove Tank
-"} - var/pumppressure = max(0,air_contents.return_pressure()) - var/output_text = {"[name]
-Pressure: [pumppressure] KPa
-Port Status: [(connected_port)?("Connected"):("Disconnected")] -[holding_text] -
-Power Switch: [on?("On"):("Off")]
-Pump Direction: [direction_out?("Out"):("In")]
-Target Pressure: - - - - [target_pressure] + + + +
-
-Close
-"} - - user << browse(output_text, "window=pump;size=600x300") - onclose(user, "pump") - - return + // 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) + 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, "portpump.tmpl", "Portable Pump", 480, 400, state = physical_state) + // 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/portable_atmospherics/pump/Topic(href, href_list) - ..() - if (usr.stat || usr.restrained()) - return + if(..()) + return 1 - if (((get_dist(src, usr) <= 1) && istype(src.loc, /turf))) - usr.set_machine(src) - - if(href_list["power"]) - on = !on - - if(href_list["direction"]) - direction_out = !direction_out - - if (href_list["remove_tank"]) - if(holding) - holding.loc = loc - holding = null - - if (href_list["pressure_adj"]) - var/diff = text2num(href_list["pressure_adj"]) - target_pressure = min(10*ONE_ATMOSPHERE, max(0, target_pressure+diff)) - - src.updateUsrDialog() - src.add_fingerprint(usr) + if(href_list["power"]) + on = !on update_icon() - else - usr << browse(null, "window=pump") - return - return \ No newline at end of file + + if(href_list["direction"]) + direction_out = !direction_out + + if (href_list["remove_tank"]) + if(holding) + holding.loc = loc + holding = null + update_icon() + + if (href_list["pressure_adj"]) + var/diff = text2num(href_list["pressure_adj"]) + target_pressure = Clamp(target_pressure+diff, pressuremin, pressuremax) + update_icon() + + src.add_fingerprint(usr) + \ No newline at end of file diff --git a/code/game/machinery/atmoalter/scrubber.dm b/code/game/machinery/atmoalter/scrubber.dm index 02abbe87d92..f47c121e5a1 100644 --- a/code/game/machinery/atmoalter/scrubber.dm +++ b/code/game/machinery/atmoalter/scrubber.dm @@ -9,6 +9,9 @@ var/volume_rate = 800 volume = 750 + + var/minrate = 0//probably useless, but whatever + var/maxrate = 10 * ONE_ATMOSPHERE /obj/machinery/portable_atmospherics/scrubber/emp_act(severity) if(stat & (BROKEN|NOPOWER)) @@ -149,56 +152,55 @@ /obj/machinery/portable_atmospherics/scrubber/attack_ai(var/mob/user as mob) src.add_hiddenprint(user) return src.attack_hand(user) + +/obj/machinery/portable_atmospherics/scrubber/attack_ghost(var/mob/user) + return src.attack_hand(user) /obj/machinery/portable_atmospherics/scrubber/attack_hand(var/mob/user as mob) - - user.set_machine(src) - var/holding_text - - if(holding) - holding_text = {"
Tank Pressure: [holding.air_contents.return_pressure()] KPa
-Remove Tank
-"} - var/output_text = {"[name]
-Pressure: [air_contents.return_pressure()] KPa
-Port Status: [(connected_port)?("Connected"):("Disconnected")] -[holding_text] -
-Power Switch: [on?("On"):("Off")]
-Power regulator: - - - - [volume_rate] + + + +
- -
-Close
-"} - - user << browse(output_text, "window=scrubber;size=600x300") - onclose(user, "scrubber") + ui_interact(user) return +/obj/machinery/portable_atmospherics/scrubber/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null) + var/list/data[0] + data["portConnected"] = connected_port ? 1 : 0 + data["tankPressure"] = round(air_contents.return_pressure() > 0 ? air_contents.return_pressure() : 0) + data["rate"] = round(volume_rate) + data["minrate"] = round(minrate) + data["maxrate"] = round(maxrate) + data["on"] = on ? 1 : 0 + + data["hasHoldingTank"] = holding ? 1 : 0 + if (holding) + data["holdingTank"] = list("name" = holding.name, "tankPressure" = round(holding.air_contents.return_pressure() > 0 ? holding.air_contents.return_pressure() : 0)) + + // 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) + 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, "portscrubber.tmpl", "Portable Scrubber", 480, 400, state = physical_state) + // 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/portable_atmospherics/scrubber/Topic(href, href_list) - ..() - if (usr.stat || usr.restrained()) - return + if(..()) + return 1 - if (((get_dist(src, usr) <= 1) && istype(src.loc, /turf))) - usr.set_machine(src) - - if(href_list["power"]) - on = !on - - if (href_list["remove_tank"]) - if(holding) - holding.loc = loc - holding = null - - if (href_list["volume_adj"]) - var/diff = text2num(href_list["volume_adj"]) - volume_rate = min(10*ONE_ATMOSPHERE, max(0, volume_rate+diff)) - - src.updateUsrDialog() - src.add_fingerprint(usr) + if(href_list["power"]) + on = !on update_icon() - else - usr << browse(null, "window=scrubber") - return - return \ No newline at end of file + + if(href_list["remove_tank"]) + if(holding) + holding.loc = loc + holding = null + + if(href_list["volume_adj"]) + var/diff = text2num(href_list["volume_adj"]) + volume_rate = Clamp(volume_rate+diff, minrate, maxrate) + + src.add_fingerprint(usr) \ No newline at end of file diff --git a/code/modules/nano/interaction/default.dm b/code/modules/nano/interaction/default.dm index 74866333c1c..a1498bf8189 100644 --- a/code/modules/nano/interaction/default.dm +++ b/code/modules/nano/interaction/default.dm @@ -21,10 +21,10 @@ return ..() /mob/living/silicon/robot/default_can_use_topic(var/src_object) - if(stat || !client) - return STATUS_CLOSE - if(lockcharge || stunned || weakened) - return STATUS_DISABLED + . = shared_nano_interaction() + if(. <= STATUS_DISABLED) + return + // robots can interact with things they can see within their view range if((src_object in view(src)) && get_dist(src_object, src) <= src.client.view) return STATUS_INTERACTIVE // interactive (green visibility) @@ -46,8 +46,10 @@ return STATUS_UPDATE /mob/living/silicon/ai/default_can_use_topic(var/src_object) - if(!client || check_unable(1)) - return STATUS_CLOSE + . = shared_nano_interaction() + if(. != STATUS_INTERACTIVE) + return + // Prevents the AI from using Topic on admin levels (by for example viewing through the court/thunderdome cameras) // unless it's on the same level as the object it's interacting with. var/turf/T = get_turf(src_object) @@ -61,9 +63,10 @@ // If we're installed in a chassi, rather than transfered to an inteliCard or other container, then check if we have camera view if(is_in_chassis()) //stop AIs from leaving windows open and using then after they lose vision - //apc_override is needed here because AIs use their own APC when powerless if(cameranet && !cameranet.checkTurfVis(get_turf(src_object))) - return apc_override ? STATUS_INTERACTIVE : STATUS_CLOSE + return STATUS_CLOSE + return STATUS_INTERACTIVE + else if(get_dist(src_object, src) <= client.view) // View does not return what one would expect while installed in an inteliCard return STATUS_INTERACTIVE return STATUS_CLOSE @@ -87,15 +90,15 @@ /mob/living/default_can_use_topic(var/src_object) . = shared_nano_interaction(src_object) - if(. == STATUS_INTERACTIVE) + if(. != STATUS_CLOSE) if(loc) - . = loc.contents_nano_distance(src_object, src) + . = min(., loc.contents_nano_distance(src_object, src)) if(STATUS_INTERACTIVE) return STATUS_UPDATE /mob/living/carbon/human/default_can_use_topic(var/src_object) . = shared_nano_interaction(src_object) - if(. == STATUS_INTERACTIVE) - . = shared_living_nano_distance(src_object) + if(. != STATUS_CLOSE) + . = min(., shared_living_nano_distance(src_object)) if(. == STATUS_UPDATE && (TK in mutations)) // If we have telekinesis and remain close enough, allow interaction. return STATUS_INTERACTIVE diff --git a/code/modules/nano/interaction/physical.dm b/code/modules/nano/interaction/physical.dm new file mode 100644 index 00000000000..424ea3a6304 --- /dev/null +++ b/code/modules/nano/interaction/physical.dm @@ -0,0 +1,18 @@ +/var/global/datum/topic_state/physical/physical_state = new() + +/datum/topic_state/physical/can_use_topic(var/src_object, var/mob/user) + . = user.shared_nano_interaction(src_object) + if(. > STATUS_CLOSE) + return min(., user.check_physical_distance(src_object)) + +/mob/proc/check_physical_distance(var/src_object) + return STATUS_CLOSE + +/mob/dead/observer/check_physical_distance(var/src_object) + return default_can_use_topic(src_object) + +/mob/living/check_physical_distance(var/src_object) + return shared_living_nano_distance(src_object) + +/mob/living/silicon/check_physical_distance(var/src_object) + return max(STATUS_UPDATE, shared_living_nano_distance(src_object)) diff --git a/code/modules/recycling/disposal.dm b/code/modules/recycling/disposal.dm index 8c77b8faba5..972cf959d04 100644 --- a/code/modules/recycling/disposal.dm +++ b/code/modules/recycling/disposal.dm @@ -7,7 +7,7 @@ // Toilets are a type of disposal bin for small objects only and work on magic. By magic, I mean torque rotation #define SEND_PRESSURE 0.05*ONE_ATMOSPHERE -/obj/machinery/disposal/ +/obj/machinery/disposal name = "disposal unit" desc = "A pneumatic waste disposal unit." icon = 'icons/obj/pipes/disposal.dmi' @@ -208,6 +208,10 @@ // ai as human but can't flush /obj/machinery/disposal/attack_ai(mob/user as mob) + src.add_hiddenprint(user) + ui_interact(user) + +/obj/machinery/disposal/attack_ghost(mob/user as mob) ui_interact(user) // human interact with machine @@ -241,10 +245,10 @@ data["mode"] = mode if(mode <= 0) data["pumpstatus"] = "" - else if(mode == 1 && pressure_round != "100") + else if(mode == 1) data["pumpstatus"] = "(pressurizing)" else if(mode == 2) - data["pumpstatus"] = "(flushing)" + data["pumpstatus"] = "(ready)" else data["pumpstatus"] = "(idle)" data["pressure"] = pressure_round diff --git a/nano/templates/portpump.tmpl b/nano/templates/portpump.tmpl new file mode 100644 index 00000000000..15c54bff42d --- /dev/null +++ b/nano/templates/portpump.tmpl @@ -0,0 +1,84 @@ +

Pump Status

+
+
+ Tank Pressure: +
+
+ {{:data.tankPressure}} kPa +
+
+ +
+
+ Port Status: +
+
+ {{:data.portConnected ? 'Connected' : 'Disconnected'}} +
+
+ +

Holding Tank Status

+{{if data.hasHoldingTank}} +
+
+ Tank Label: +
+
+
{{:data.holdingTank.name}}
{{:helper.link('Eject', 'eject', {'remove_tank' : 1})}} +
+
+ +
+
+ Tank Pressure: +
+
+ {{:data.holdingTank.tankPressure}} kPa +
+
+{{else}} +
No holding tank inserted.
+
 
+{{/if}} + + +

Power Regulator Status

+
+
+ Target Pressure: +
+
+ {{:helper.displayBar(data.targetpressure, data.minpressure, data.maxpressure)}} +
+ {{:helper.link('-', null, {'pressure_adj' : -1000}, (data.targetpressure > data.minpressure) ? null : 'disabled')}} + {{:helper.link('-', null, {'pressure_adj' : -100}, (data.targetpressure > data.minpressure) ? null : 'disabled')}} + {{:helper.link('-', null, {'pressure_adj' : -10}, (data.targetpressure > data.minpressure) ? null : 'disabled')}} + {{:helper.link('-', null, {'pressure_adj' : -1}, (data.targetpressure > data.minpressure) ? null : 'disabled')}} +
 {{:data.targetpressure}} kPa 
+ {{:helper.link('+', null, {'pressure_adj' : 1}, (data.targetpressure < data.maxpressure) ? null : 'disabled')}} + {{:helper.link('+', null, {'pressure_adj' : 10}, (data.targetpressure < data.maxpressure) ? null : 'disabled')}} + {{:helper.link('+', null, {'pressure_adj' : 100}, (data.targetpressure < data.maxpressure) ? null : 'disabled')}} + {{:helper.link('+', null, {'pressure_adj' : 1000}, (data.targetpressure < data.maxpressure) ? null : 'disabled')}} +
+
+
+ +
+
+ Power Switch: +
+
+ {{:helper.link('On', 'unlocked', {'power' : 1}, data.on ? 'selected' : null)}}{{:helper.link('Off', 'locked', {'power' : 1}, data.on ? null : 'selected')}} +
+
+ +
+
+ Pump Direction: +
+
+ {{:helper.link('Out', 'arrowreturn-1-e', {'direction' : 1}, data.pump_dir ? 'selected' : null)}}{{:helper.link('In', 'arrowreturn-1-w', {'direction' : 1}, data.pump_dir ? null : 'selected')}} +
+
+ + diff --git a/nano/templates/portscrubber.tmpl b/nano/templates/portscrubber.tmpl new file mode 100644 index 00000000000..8537ae4d5d4 --- /dev/null +++ b/nano/templates/portscrubber.tmpl @@ -0,0 +1,74 @@ +

Scrubber Status

+
+
+ Tank Pressure: +
+
+ {{:data.tankPressure}} kPa +
+
+ +
+
+ Port Status: +
+
+ {{:data.portConnected ? 'Connected' : 'Disconnected'}} +
+
+ +

Holding Tank Status

+{{if data.hasHoldingTank}} +
+
+ Tank Label: +
+
+
{{:data.holdingTank.name}}
{{:helper.link('Eject', 'eject', {'remove_tank' : 1})}} +
+
+ +
+
+ Tank Pressure: +
+
+ {{:data.holdingTank.tankPressure}} kPa +
+
+{{else}} +
No holding tank inserted.
+
 
+{{/if}} + + +

Power Regulator Status

+
+
+ Volume Rate: +
+
+ {{:helper.displayBar(data.rate, data.minrate, data.maxrate)}} +
+ {{:helper.link('-', null, {'volume_adj' : -1000}, (data.rate > data.minrate) ? null : 'disabled')}} + {{:helper.link('-', null, {'volume_adj' : -100}, (data.rate > data.minrate) ? null : 'disabled')}} + {{:helper.link('-', null, {'volume_adj' : -10}, (data.rate > data.minrate) ? null : 'disabled')}} + {{:helper.link('-', null, {'volume_adj' : -1}, (data.rate > data.minrate) ? null : 'disabled')}} +
 {{:data.rate}} kPa 
+ {{:helper.link('+', null, {'volume_adj' : 1}, (data.rate < data.maxrate) ? null : 'disabled')}} + {{:helper.link('+', null, {'volume_adj' : 10}, (data.rate < data.maxrate) ? null : 'disabled')}} + {{:helper.link('+', null, {'volume_adj' : 100}, (data.rate < data.maxrate) ? null : 'disabled')}} + {{:helper.link('+', null, {'volume_adj' : 1000}, (data.rate < data.maxrate) ? null : 'disabled')}} +
+
+
+ +
+
+ Power Switch: +
+
+ {{:helper.link('On', 'unlocked', {'power' : 1}, data.on ? 'selected' : null)}}{{:helper.link('Off', 'locked', {'power' : 1}, data.on ? null : 'selected')}} +
+
+ diff --git a/paradise.dme b/paradise.dme index 4b6229b447e..4e385cdc312 100644 --- a/paradise.dme +++ b/paradise.dme @@ -1478,6 +1478,7 @@ #include "code\modules\nano\interaction\contained.dm" #include "code\modules\nano\interaction\default.dm" #include "code\modules\nano\interaction\inventory.dm" +#include "code\modules\nano\interaction\physical.dm" #include "code\modules\nano\interaction\zlevel.dm" #include "code\modules\nano\modules\crew_monitor.dm" #include "code\modules\nano\modules\nano_module.dm"