diff --git a/baystation12.dme b/baystation12.dme index cc0918516d7..9de1e153ca6 100644 --- a/baystation12.dme +++ b/baystation12.dme @@ -324,7 +324,6 @@ #include "code\game\machinery\turrets.dm" #include "code\game\machinery\vending.dm" #include "code\game\machinery\washing_machine.dm" -#include "code\game\machinery\wishgranter.dm" #include "code\game\machinery\atmoalter\area_atmos_computer.dm" #include "code\game\machinery\atmoalter\canister.dm" #include "code\game\machinery\atmoalter\meter.dm" @@ -1153,6 +1152,7 @@ #include "code\WorkInProgress\Cael_Aislinn\Supermatter\SuperMatter.dm" #include "code\WorkInProgress\Cael_Aislinn\Supermatter\ZeroPointLaser.dm" #include "code\WorkInProgress\Chinsky\ashtray.dm" +#include "code\WorkInProgress\Mini\atmos_control.dm" #include "code\WorkInProgress\Ported\policetape.dm" #include "code\WorkInProgress\SkyMarshal\Ultralight_procs.dm" #include "code\WorkInProgress\Susan\susan_desert_turfs.dm" diff --git a/code/ATMOSPHERICS/components/unary/vent_pump.dm b/code/ATMOSPHERICS/components/unary/vent_pump.dm index 7b9444d8902..9aae6910c7c 100644 --- a/code/ATMOSPHERICS/components/unary/vent_pump.dm +++ b/code/ATMOSPHERICS/components/unary/vent_pump.dm @@ -5,13 +5,14 @@ name = "Air Vent" desc = "Has a valve and pump attached to it" - var/area/initial_loc level = 1 var/area_uid - var/id_tag = null + var/id_tag + power_channel = ENVIRON var/on = 0 var/pump_direction = 1 //0 = siphoning, 1 = releasing + var/pump_speed = 1 //Used to adjust speed for siphons var/external_pressure_bound = ONE_ATMOSPHERE var/internal_pressure_bound = 0 @@ -42,25 +43,27 @@ icon_state = "in" New() - initial_loc = get_area(loc) - if (initial_loc.master) - initial_loc = initial_loc.master - area_uid = initial_loc.uid + var/area/A = get_area(loc) + if (A.master) + A = A.master + area_uid = A.uid if (!id_tag) assign_uid() id_tag = num2text(uid) if(ticker && ticker.current_state == 3)//if the game is running - src.initialize() - src.broadcast_status() + initialize() + broadcast_status() ..() high_volume name = "Large Air Vent" power_channel = EQUIP + New() ..() air_contents.volume = 1000 + update_icon() if(welded) icon_state = "[level == 1 && istype(loc, /turf/simulated) ? "h" : "" ]weld" @@ -77,11 +80,12 @@ process() ..() +// broadcast_status() if(stat & (NOPOWER|BROKEN)) return if (!node) on = 0 - //broadcast_status() // from now air alarm/control computer should request update purposely --rastaf0 + if(!on) return 0 @@ -101,7 +105,7 @@ if(pressure_delta > 0) if(air_contents.temperature > 0) - var/transfer_moles = pressure_delta*environment.volume/(air_contents.temperature * R_IDEAL_GAS_EQUATION) + var/transfer_moles = pressure_delta*environment.volume*environment.group_multiplier*pump_speed/(air_contents.temperature * R_IDEAL_GAS_EQUATION) var/datum/gas_mixture/removed = air_contents.remove(transfer_moles) @@ -119,7 +123,7 @@ if(pressure_delta > 0) if(environment.temperature > 0) - var/transfer_moles = pressure_delta*air_contents.volume/(environment.temperature * R_IDEAL_GAS_EQUATION) + var/transfer_moles = pressure_delta*air_contents.volume*air_contents.group_multiplier*pump_speed/(environment.temperature * R_IDEAL_GAS_EQUATION) var/datum/gas_mixture/removed = loc.remove_air(transfer_moles) if (isnull(removed)) //in space @@ -132,39 +136,42 @@ return 1 + + + //Radio remote control - proc - set_frequency(new_frequency) - radio_controller.remove_object(src, frequency) - frequency = new_frequency - if(frequency) - radio_connection = radio_controller.add_object(src, frequency,radio_filter_in) + proc/set_frequency(new_frequency) + radio_controller.remove_object(src, frequency) + frequency = new_frequency + if(frequency) + radio_connection = radio_controller.add_object(src, frequency,radio_filter_in) - broadcast_status() - if(!radio_connection) - return 0 + proc/broadcast_status() + if(!radio_connection) + return 0 - var/datum/signal/signal = new - signal.transmission_method = 1 //radio signal - signal.source = src + var/datum/signal/signal = new + signal.transmission_method = 1 //radio signal + signal.source = src - signal.data = list( - "area" = src.area_uid, - "tag" = src.id_tag, - "device" = "AVP", - "power" = on, - "direction" = pump_direction?("release"):("siphon"), - "checks" = pressure_checks, - "internal" = internal_pressure_bound, - "external" = external_pressure_bound, - "timestamp" = world.time, - "sigtype" = "status" - ) + signal.data = list( + "area" = src.area_uid, + "tag" = src.id_tag, + "device" = "AVP", + "power" = on, + "direction" = pump_direction?("release"):("siphon"), + "checks" = pressure_checks, + "internal" = internal_pressure_bound, + "external" = external_pressure_bound, + "timestamp" = world.time, + "sigtype" = "status", + "setting" = pump_speed + ) - radio_connection.post_signal(src, signal, radio_filter_out) + radio_connection.post_signal(src, signal, radio_filter_out) - return 1 + return 1 initialize() @@ -176,6 +183,7 @@ if(frequency) set_frequency(frequency) + receive_signal(datum/signal/signal) if(stat & (NOPOWER|BROKEN)) return @@ -203,47 +211,29 @@ if("checks_toggle" in signal.data) pressure_checks = (pressure_checks?0:3) - if("direction" in signal.data) + if("direction" in signal) pump_direction = text2num(signal.data["direction"]) if("set_internal_pressure" in signal.data) - internal_pressure_bound = between( - 0, - text2num(signal.data["set_internal_pressure"]), - ONE_ATMOSPHERE*50 - ) + internal_pressure_bound = between(0, text2num(signal.data["set_internal_pressure"]), ONE_ATMOSPHERE*50) if("set_external_pressure" in signal.data) - external_pressure_bound = between( - 0, - text2num(signal.data["set_external_pressure"]), - ONE_ATMOSPHERE*50 - ) + external_pressure_bound = between(0, text2num(signal.data["set_external_pressure"]), ONE_ATMOSPHERE*50) if("adjust_internal_pressure" in signal.data) - internal_pressure_bound = between( - 0, - internal_pressure_bound + text2num(signal.data["adjust_internal_pressure"]), - ONE_ATMOSPHERE*50 - ) + internal_pressure_bound = between(0, internal_pressure_bound + text2num(signal.data["adjust_internal_pressure"]), ONE_ATMOSPHERE*50) if("adjust_external_pressure" in signal.data) - external_pressure_bound = between( - 0, - external_pressure_bound + text2num(signal.data["adjust_external_pressure"]), - ONE_ATMOSPHERE*50 - ) + external_pressure_bound = between(0, external_pressure_bound + text2num(signal.data["adjust_external_pressure"]), ONE_ATMOSPHERE*50) if("init" in signal.data) name = signal.data["init"] return - if("status" in signal.data) - spawn(2) - broadcast_status() - return //do not update_icon + if("setting" in signal.data) + pump_speed = text2num(signal.data["setting"]) - //log_admin("DEBUG \[[world.timeofday]\]: vent_pump/receive_signal: unknown command \"[signal.data["command"]]\"\n[signal.debug_print()]") + //log_admin("DEBUG \[[world.timeofday]\]: vent_pump/receive_signal: unknown command \"[signal["command"]]\"\n[signal.debug_print()]") spawn(2) broadcast_status() update_icon() @@ -284,6 +274,7 @@ else user << "\blue You need more welding fuel to complete this task." return 1 + examine() set src in oview(1) ..() @@ -321,10 +312,4 @@ "\blue You have unfastened \the [src].", \ "You hear ratchet.") new /obj/item/pipe(loc, make_from=src) - del(src) - - /obj/machinery/atmospherics/unary/vent_pump/Del() - if (initial_loc.air_scrub_info) - initial_loc.air_scrub_info -= id_tag - ..() - return + del(src) \ No newline at end of file diff --git a/code/ATMOSPHERICS/components/unary/vent_scrubber.dm b/code/ATMOSPHERICS/components/unary/vent_scrubber.dm index 84378df3d14..b9c26d32511 100644 --- a/code/ATMOSPHERICS/components/unary/vent_scrubber.dm +++ b/code/ATMOSPHERICS/components/unary/vent_scrubber.dm @@ -7,34 +7,36 @@ level = 1 - var/area/initial_loc var/id_tag = null - var/frequency = 1439 - var/datum/radio_frequency/radio_connection var/on = 0 var/scrubbing = 1 //0 = siphoning, 1 = scrubbing var/scrub_CO2 = 1 var/scrub_Toxins = 0 var/scrub_N2O = 0 + var/scrub_rate = 1 var/volume_rate = 120 var/panic = 0 //is this scrubber panicked? var/area_uid + + var/frequency = 1439 + var/datum/radio_frequency/radio_connection var/radio_filter_out var/radio_filter_in + New() - initial_loc = get_area(loc) - if (initial_loc.master) - initial_loc = initial_loc.master - area_uid = initial_loc.uid + var/area/A = get_area(loc) + if (A.master) + A = A.master + area_uid = A.uid if (!id_tag) assign_uid() id_tag = num2text(uid) if(ticker && ticker.current_state == 3)//if the game is running - src.initialize() - src.broadcast_status() + initialize() + broadcast_status() ..() update_icon() @@ -86,20 +88,20 @@ process() ..() +// broadcast_status() if(stat & (NOPOWER|BROKEN)) return if (!node) on = 0 - //broadcast_status() + if(!on) return 0 - var/datum/gas_mixture/environment = loc.return_air() if(scrubbing) if((environment.toxins>0) || (environment.carbon_dioxide>0) || (environment.trace_gases.len>0)) - var/transfer_moles = min(1, volume_rate/environment.volume)*environment.total_moles() + var/transfer_moles = min(1, volume_rate*scrub_rate/environment.volume)*environment.total_moles //Take a gas sample var/datum/gas_mixture/removed = loc.remove_air(transfer_moles) @@ -118,15 +120,14 @@ if(removed.trace_gases.len>0) for(var/datum/gas/trace_gas in removed.trace_gases) - if(istype(trace_gas, /datum/gas/oxygen_agent_b)) - removed.trace_gases -= trace_gas - filtered_out.trace_gases += trace_gas - else if(istype(trace_gas, /datum/gas/sleeping_agent) && scrub_N2O) + if(istype(trace_gas, /datum/gas/sleeping_agent) && scrub_N2O) removed.trace_gases -= trace_gas filtered_out.trace_gases += trace_gas //Remix the resulting gases + filtered_out.update_values() + removed.update_values() air_contents.merge(filtered_out) loc.assume_air(removed) @@ -138,7 +139,7 @@ if (air_contents.return_pressure()>=50*ONE_ATMOSPHERE) return - var/transfer_moles = environment.total_moles()*(volume_rate/environment.volume) + var/transfer_moles = environment.total_moles*(volume_rate*scrub_rate/environment.volume) var/datum/gas_mixture/removed = loc.remove_air(transfer_moles) @@ -220,6 +221,9 @@ broadcast_status() return //do not update_icon + if("setting" in signal.data) + scrub_rate = text2num(signal.data["setting"]) + // log_admin("DEBUG \[[world.timeofday]\]: vent_scrubber/receive_signal: unknown command \"[signal.data["command"]]\"\n[signal.debug_print()]") spawn(2) broadcast_status() @@ -227,7 +231,7 @@ return power_change() - if(powered(power_channel)) + if(powered(ENVIRON)) stat &= ~NOPOWER else stat |= NOPOWER @@ -257,10 +261,4 @@ "\blue You have unfastened \the [src].", \ "You hear ratchet.") new /obj/item/pipe(loc, make_from=src) - del(src) - - /obj/machinery/atmospherics/unary/vent_scrubber/Del() - if (initial_loc.air_scrub_info) - initial_loc.air_scrub_info -= id_tag - ..() - return + del(src) \ No newline at end of file diff --git a/code/WorkInProgress/Mini/atmos_control.dm b/code/WorkInProgress/Mini/atmos_control.dm index 6c06a16b799..506258cdf9b 100644 --- a/code/WorkInProgress/Mini/atmos_control.dm +++ b/code/WorkInProgress/Mini/atmos_control.dm @@ -16,7 +16,7 @@ /obj/machinery/computer/atmoscontrol/attack_hand(mob/user) if(..()) return - user.machine = src + user.set_machine(src) if(allowed(user)) overridden = 1 else if(!emagged) @@ -139,6 +139,12 @@ src.updateUsrDialog() return + if(href_list["atmos_unlock"]) + switch(href_list["atmos_unlock"]) + if("0") + current.air_doors_close(1) + if("1") + current.air_doors_open(1) if(href_list["atmos_alarm"]) if (current.alarm_area.atmosalert(2)) @@ -187,6 +193,8 @@ output += "PANIC SYPHON ACTIVE
turn syphoning off" else output += "ACTIVATE PANIC SYPHON IN AREA" + + output += "

Atmospheric Lockdown: [current.alarm_area.air_doors_activated ? "ENABLED" : "Disabled"]" if (AALARM_SCREEN_VENT) var/sensor_data = "" if(current.alarm_area.air_vent_names.len) diff --git a/code/defines/obj/vending.dm b/code/defines/obj/vending.dm index ac89893befe..efd1d0b5bd6 100755 --- a/code/defines/obj/vending.dm +++ b/code/defines/obj/vending.dm @@ -214,8 +214,8 @@ desc = "A plant nutrients vendor" icon_state = "nutri" icon_deny = "nutri-deny" - product_paths = "/obj/item/nutrient/ez;/obj/item/nutrient/l4z;/obj/item/nutrient/rh;/obj/item/weapon/pestspray;/obj/item/weapon/reagent_containers/syringe;/obj/item/weapon/plantbag" - product_amounts = "35;25;15;20;5;5" + product_paths = "/obj/item/nutrient/ez;/obj/item/nutrient/l4z;/obj/item/nutrient/rh;/obj/item/weapon/pestspray;/obj/item/weapon/reagent_containers/syringe;/obj/item/weapon/plantbag;/obj/item/weapon/seedbag" + product_amounts = "35;25;15;20;5;5;5" product_slogans = "Aren't you glad you don't have to fertilize the natural way?;Now with 50% less stink!;Plants are people too!" product_hidden = "/obj/item/weapon/reagent_containers/glass/bottle/ammonia;/obj/item/weapon/reagent_containers/glass/bottle/diethylamine" product_hideamt = "10;5" diff --git a/code/game/area/Space Station 13 areas.dm b/code/game/area/Space Station 13 areas.dm index 8bb76ec226f..6d41985202e 100755 --- a/code/game/area/Space Station 13 areas.dm +++ b/code/game/area/Space Station 13 areas.dm @@ -49,6 +49,8 @@ NOTE: there are two lists of areas in the end of this file: centcom and station // (original area before splitting due to sd_DAL) var/list/related // the other areas of the same type as this // var/list/lights // list of all lights on this area + var/list/all_doors = list() //Added by Strumpetplaya - Alarm Change - Contains a list of doors adjacent to this area + var/air_doors_activated = 0 /*Adding a wizard area teleport list because motherfucking lag -- Urist*/ /*I am far too lazy to make it a proper list of areas so I'll just make it run the usual telepot routine at the start of the game*/ diff --git a/code/game/area/areas.dm b/code/game/area/areas.dm index e0e15c0ecd3..3d59d9016da 100644 --- a/code/game/area/areas.dm +++ b/code/game/area/areas.dm @@ -10,7 +10,7 @@ /area/New() icon_state = "" layer = 10 - master = src //moved outside the spawn(1) to avoid runtimes in lighting.dm when it references src.loc.loc.master ~Carn + master = src //moved outside the spawn(1) to avoid runtimes in lighting.dm when it references loc.loc.master ~Carn uid = ++global_uid related = list(src) @@ -62,44 +62,44 @@ return /area/proc/atmosalert(danger_level) -// if(src.type==/area) //No atmos alarms in space +// if(type==/area) //No atmos alarms in space // return 0 //redudant - if(danger_level != src.atmosalm) - //src.updateicon() - //src.mouse_opacity = 0 + if(danger_level != atmosalm) + //updateicon() + //mouse_opacity = 0 if (danger_level==2) var/list/cameras = list() - for(var/area/RA in src.related) - //src.updateicon() + for(var/area/RA in related) + //updateicon() for(var/obj/machinery/camera/C in RA) cameras += C for(var/mob/living/silicon/aiPlayer in player_list) aiPlayer.triggerAlarm("Atmosphere", src, cameras, src) for(var/obj/machinery/computer/station_alert/a in world) a.triggerAlarm("Atmosphere", src, cameras, src) - else if (src.atmosalm == 2) + else if (atmosalm == 2) for(var/mob/living/silicon/aiPlayer in player_list) aiPlayer.cancelAlarm("Atmosphere", src, src) for(var/obj/machinery/computer/station_alert/a in world) a.cancelAlarm("Atmosphere", src, src) - src.atmosalm = danger_level + atmosalm = danger_level return 1 return 0 /area/proc/firealert() - if(src.name == "Space") //no fire alarms in space + if(name == "Space") //no fire alarms in space return - if (!( src.fire )) - src.fire = 1 - src.updateicon() - src.mouse_opacity = 0 - for(var/obj/machinery/door/firedoor/D in src) + if( !fire ) + fire = 1 + updateicon() + mouse_opacity = 0 + for(var/obj/machinery/door/firedoor/D in all_doors) if(!D.blocked) if(D.operating) D.nextstate = CLOSED else if(!D.density) - spawn(0) - D.close() + spawn() + D.close() var/list/cameras = list() for (var/obj/machinery/camera/C in src) cameras += C @@ -107,14 +107,13 @@ aiPlayer.triggerAlarm("Fire", src, cameras, src) for (var/obj/machinery/computer/station_alert/a in world) a.triggerAlarm("Fire", src, cameras, src) - return /area/proc/firereset() - if (src.fire) - src.fire = 0 - src.mouse_opacity = 0 - src.updateicon() - for(var/obj/machinery/door/firedoor/D in src) + if (fire) + fire = 0 + mouse_opacity = 0 + updateicon() + for(var/obj/machinery/door/firedoor/D in all_doors) if(!D.blocked) if(D.operating) D.nextstate = OPEN @@ -125,7 +124,6 @@ aiPlayer.cancelAlarm("Fire", src, src) for (var/obj/machinery/computer/station_alert/a in world) a.cancelAlarm("Fire", src, src) - return /area/proc/readyalert() if(name == "Space") @@ -142,19 +140,19 @@ return /area/proc/partyalert() - if(src.name == "Space") //no parties in space!!! + if(name == "Space") //no parties in space!!! return - if (!( src.party )) - src.party = 1 - src.updateicon() - src.mouse_opacity = 0 + if (!( party )) + party = 1 + updateicon() + mouse_opacity = 0 return /area/proc/partyreset() - if (src.party) - src.party = 0 - src.mouse_opacity = 0 - src.updateicon() + if (party) + party = 0 + mouse_opacity = 0 + updateicon() for(var/obj/machinery/door/firedoor/D in src) if(!D.blocked) if(D.operating) @@ -273,7 +271,7 @@ A:client:ambience_playing = 1 A << sound('sound/ambience/shipambience.ogg', repeat = 1, wait = 0, volume = 35, channel = 2) - switch(src.name) + switch(name) if ("Chapel") sound = pick('sound/ambience/ambicha1.ogg','sound/ambience/ambicha2.ogg','sound/ambience/ambicha3.ogg','sound/ambience/ambicha4.ogg') if ("Morgue") sound = pick('sound/ambience/ambimo1.ogg','sound/ambience/ambimo2.ogg','sound/music/title2.ogg') if ("Space") sound = pick('sound/ambience/ambispace.ogg','sound/music/title2.ogg',) diff --git a/code/game/jobs/access.dm b/code/game/jobs/access.dm index a465147daa7..b83774e381d 100644 --- a/code/game/jobs/access.dm +++ b/code/game/jobs/access.dm @@ -517,3 +517,32 @@ return jobName return "Unknown" + +proc/FindNameFromID(var/mob/living/carbon/human/H) + ASSERT(istype(H)) + var/obj/item/weapon/card/id/C = H.get_active_hand() + if( istype(C) || istype(C, /obj/item/device/pda) ) + var/obj/item/weapon/card/id/ID = C + + if( istype(C, /obj/item/device/pda) ) + var/obj/item/device/pda/pda = C + ID = pda.id + if(!istype(ID)) + ID = null + + if(ID) + return ID.registered_name + + C = H.wear_id + + if( istype(C) || istype(C, /obj/item/device/pda) ) + var/obj/item/weapon/card/id/ID = C + + if( istype(C, /obj/item/device/pda) ) + var/obj/item/device/pda/pda = C + ID = pda.id + if(!istype(ID)) + ID = null + + if(ID) + return ID.registered_name diff --git a/code/game/machinery/alarm.dm b/code/game/machinery/alarm.dm index 2f586ef0e99..85843cca50f 100644 --- a/code/game/machinery/alarm.dm +++ b/code/game/machinery/alarm.dm @@ -1,5 +1,6 @@ -//This file was auto-corrected by findeclaration.exe on 25.5.2012 20:42:31 - +//////////////////////////////////////// +//CONTAINS: Air Alarms and Fire Alarms// +//////////////////////////////////////// /proc/RandomAAlarmWires() //to make this not randomize the wires, just set index to 1 and increment it in the flag for loop (after doing everything else). @@ -21,119 +22,29 @@ flagIndex+=1 return AAlarmwires +#define AALARM_WIRE_IDSCAN 1 //Added wires +#define AALARM_WIRE_POWER 2 +#define AALARM_WIRE_SYPHON 3 +#define AALARM_WIRE_AI_CONTROL 4 +#define AALARM_WIRE_AALARM 5 +#define AALARM_MODE_SCRUBBING 1 +#define AALARM_MODE_REPLACEMENT 2 //like scrubbing, but faster. +#define AALARM_MODE_PANIC 3 //constantly sucks all air +#define AALARM_MODE_CYCLE 4 //sucks off all air, then refill and swithes to scrubbing +#define AALARM_MODE_FILL 5 //emergency fill -// A datum for dealing with threshold limit values -// used in /obj/machinery/alarm -/datum/tlv - var/min2 - var/min1 - var/max1 - var/max2 - New(_min2 as num, _min1 as num, _max1 as num, _max2 as num) - min2 = _min2 - min1 = _min1 - max1 = _max1 - max2 = _max2 - proc/get_danger_level(curval as num) - if (max2 >=0 && curval>=max2) - return 2 - if (min2 >=0 && curval<=min2) - return 2 - if (max1 >=0 && curval>=max1) - return 1 - if (min1 >=0 && curval<=min1) - return 1 - return 0 - proc/CopyFrom(datum/tlv/other) - min2 = other.min2 - min1 = other.min1 - max1 = other.max1 - max2 = other.max2 +#define AALARM_SCREEN_MAIN 1 +#define AALARM_SCREEN_VENT 2 +#define AALARM_SCREEN_SCRUB 3 +#define AALARM_SCREEN_MODE 4 +#define AALARM_SCREEN_SENSORS 5 -/obj/machinery/alarm - name = "alarm" - icon = 'icons/obj/monitors.dmi' - icon_state = "alarm0" - anchored = 1 - use_power = 1 - idle_power_usage = 4 - active_power_usage = 8 - power_channel = ENVIRON - req_access = list(access_atmospherics) - var/frequency = 1439 - //var/skipprocess = 0 //Experimenting - var/alarm_frequency = 1437 #define AALARM_REPORT_TIMEOUT 100 - var/datum/radio_frequency/radio_connection - var/locked = 1 - var/wiresexposed = 0 // If it's been screwdrivered open. - var/aidisabled = 0 - var/AAlarmwires = 31 - var/shorted = 0 - var/remote_control = 0 - // Uses code from apc.dm - -#define AALARM_WIRE_IDSCAN 1 //Added wires -#define AALARM_WIRE_POWER 2 -#define AALARM_WIRE_SYPHON 3 -#define AALARM_WIRE_AI_CONTROL 4 -#define AALARM_WIRE_AALARM 5 - - -#define AALARM_MODE_SCRUBBING 1 -#define AALARM_MODE_VENTING 2 //makes draught -#define AALARM_MODE_PANIC 3 //constantly sucks all air -#define AALARM_MODE_REPLACEMENT 4 //sucks off all air, then refill and swithes to scrubbing -#define AALARM_MODE_OFF 5 - var/mode = AALARM_MODE_SCRUBBING - -#define AALARM_SCREEN_MAIN 1 -#define AALARM_SCREEN_VENT 2 -#define AALARM_SCREEN_SCRUB 3 -#define AALARM_SCREEN_MODE 4 -#define AALARM_SCREEN_SENSORS 5 - var/screen = AALARM_SCREEN_MAIN - var/area_uid - var/area/alarm_area - var/danger_level = 0 - - // breathable air according to human/Life() - var/list/TLV = list( - "oxygen" = new/datum/tlv( 16, 19, 135, 140), // Partial pressure, kpa - "carbon dioxide" = new/datum/tlv(-1.0, -1.0, 5, 10), // Partial pressure, kpa - "plasma" = new/datum/tlv(-1.0, -1.0, 0.2, 0.5), // Partial pressure, kpa - "other" = new/datum/tlv(-1.0, -1.0, 0.5, 1.0), // Partial pressure, kpa - "pressure" = new/datum/tlv(ONE_ATMOSPHERE*0.80,ONE_ATMOSPHERE*0.90,ONE_ATMOSPHERE*1.10,ONE_ATMOSPHERE*1.20), /* kpa */ - "temperature" = new/datum/tlv(T0C, T0C+10, T0C+40, T0C+66), // K - ) - -/* - // breathable air according to wikipedia - "oxygen" = new/datum/tlv( 9, 12, 158, 296), // Partial pressure, kpa - "carbon dioxide" = new/datum/tlv(-1.0,-1.0, 0.5, 1), // Partial pressure, kpa -*/ -/obj/machinery/alarm/server - //req_access = list(access_rd) //no, let departaments to work together - TLV = list( - "oxygen" = new/datum/tlv(-1.0, -1.0,-1.0,-1.0), // Partial pressure, kpa - "carbon dioxide" = new/datum/tlv(-1.0, -1.0, 5, 10), // Partial pressure, kpa - "plasma" = new/datum/tlv(-1.0, -1.0, 0.2, 0.5), // Partial pressure, kpa - "other" = new/datum/tlv(-1.0, -1.0, 0.5, 1.0), // Partial pressure, kpa - "pressure" = new/datum/tlv(ONE_ATMOSPHERE*0.80,ONE_ATMOSPHERE*0.90,ONE_ATMOSPHERE*1.40,ONE_ATMOSPHERE*1.60), /* kpa */ - "temperature" = new/datum/tlv(40, 60, 100, 120), // K - ) - -/obj/machinery/alarm/kitchen_cold_room - TLV = list( - "oxygen" = new/datum/tlv( 16, 19, 135, 140), // Partial pressure, kpa - "carbon dioxide" = new/datum/tlv(-1.0, -1.0, 5, 10), // Partial pressure, kpa - "plasma" = new/datum/tlv(-1.0, -1.0, 0.2, 0.5), // Partial pressure, kpa - "other" = new/datum/tlv(-1.0, -1.0, 0.5, 1.0), // Partial pressure, kpa - "pressure" = new/datum/tlv(ONE_ATMOSPHERE*0.80,ONE_ATMOSPHERE*0.90,ONE_ATMOSPHERE*1.50,ONE_ATMOSPHERE*1.60), /* kpa */ - "temperature" = new/datum/tlv(200, 210, 273.15, 283.15), // K - ) +#define RCON_NO 1 +#define RCON_AUTO 2 +#define RCON_YES 3 //all air alarms in area are connected via magic /area @@ -143,508 +54,737 @@ var/list/air_vent_info var/list/air_scrub_info -/obj/machinery/alarm/New() - ..() - alarm_area = get_area(loc) - if (alarm_area.master) - alarm_area = alarm_area.master - area_uid = alarm_area.uid - if (name == "alarm") - name = "[alarm_area.name] Air Alarm" +/obj/machinery/alarm + name = "alarm" + icon = 'monitors.dmi' + icon_state = "alarm0" + anchored = 1 + use_power = 1 + idle_power_usage = 4 + active_power_usage = 8 + power_channel = ENVIRON + req_access = list(access_atmospherics, access_engine_equip) + var/frequency = 1439 + //var/skipprocess = 0 //Experimenting + var/alarm_frequency = 1437 + var/remote_control = 0 + var/rcon_setting = 2 + var/rcon_time = 0 + var/locked = 1 + var/wiresexposed = 0 // If it's been screwdrivered open. + var/aidisabled = 0 + var/AAlarmwires = 31 + var/shorted = 0 -/obj/machinery/alarm/initialize() - set_frequency(frequency) - if (!master_is_operating()) - elect_master() + var/mode = AALARM_MODE_SCRUBBING + var/screen = AALARM_SCREEN_MAIN + var/area_uid + var/area/alarm_area + var/danger_level = 0 -/obj/machinery/alarm/proc/master_is_operating() - return alarm_area.master_air_alarm && !(alarm_area.master_air_alarm.stat & (NOPOWER|BROKEN)) + var/datum/radio_frequency/radio_connection -/obj/machinery/alarm/proc/elect_master() - for (var/area/A in alarm_area.related) - for (var/obj/machinery/alarm/AA in A) - if (!(AA.stat & (NOPOWER|BROKEN))) - alarm_area.master_air_alarm = AA - if (!alarm_area.air_vent_names) - alarm_area.air_vent_names = new - alarm_area.air_scrub_names = new - alarm_area.air_vent_info = new - alarm_area.air_scrub_info = new - return 1 - return 0 + var/list/TLV = list() -/obj/machinery/alarm/attack_hand(mob/user) - . = ..() - if (.) - return - user.set_machine(src) + server/New() + ..() + req_access = list(access_rd, access_atmospherics, access_engine_equip) + TLV["oxygen"] = list(-1.0, -1.0,-1.0,-1.0) // Partial pressure, kpa + TLV["carbon dioxide"] = list(-1.0, -1.0, 5, 10) // Partial pressure, kpa + TLV["plasma"] = list(-1.0, -1.0, 0.2, 0.5) // Partial pressure, kpa + TLV["other"] = list(-1.0, -1.0, 0.5, 1.0) // Partial pressure, kpa + TLV["pressure"] = list(0,ONE_ATMOSPHERE*0.10,ONE_ATMOSPHERE*1.40,ONE_ATMOSPHERE*1.60) /* kpa */ + TLV["temperature"] = list(20, 40, 140, 160) // K - if ( (get_dist(src, user) > 1 )) - if (!istype(user, /mob/living/silicon)) - user.unset_machine() - user << browse(null, "window=air_alarm") - user << browse(null, "window=AAlarmwires") + New() + ..() + alarm_area = get_area(src) + if (alarm_area.master) + alarm_area = alarm_area.master + area_uid = alarm_area.uid + if (name == "alarm") + name = "[alarm_area.name] Air Alarm" + + // breathable air according to human/Life() + TLV["oxygen"] = list(16, 19, 135, 140) // Partial pressure, kpa + TLV["carbon dioxide"] = list(-1.0, -1.0, 5, 10) // Partial pressure, kpa + TLV["plasma"] = list(-1.0, -1.0, 0.2, 0.5) // Partial pressure, kpa + TLV["other"] = list(-1.0, -1.0, 0.5, 1.0) // Partial pressure, kpa + TLV["pressure"] = list(ONE_ATMOSPHERE*0.80,ONE_ATMOSPHERE*0.90,ONE_ATMOSPHERE*1.10,ONE_ATMOSPHERE*1.20) /* kpa */ + TLV["temperature"] = list(T0C, T0C+10, T0C+40, T0C+66) // K + + initialize() + set_frequency(frequency) + if (!master_is_operating()) + elect_master() + + + process() + if((stat & (NOPOWER|BROKEN)) || shorted) return + var/turf/simulated/location = loc + ASSERT(istype(location)) - else if (istype(user, /mob/living/silicon) && src.aidisabled) - user << "AI control for this Air Alarm interface has been disabled." - user << browse(null, "window=air_alarm") - return + var/datum/gas_mixture/environment = location.return_air() + var/partial_pressure = R_IDEAL_GAS_EQUATION*environment.temperature/environment.volume - if(wiresexposed && (!istype(user, /mob/living/silicon))) - var/t1 = text("[alarm_area.name] Air Alarm WiresAccess Panel
\n") - var/list/AAlarmwires = list( - "Orange" = 1, - "Dark red" = 2, - "White" = 3, - "Yellow" = 4, - "Black" = 5, - ) - for(var/wiredesc in AAlarmwires) - var/is_uncut = src.AAlarmwires & AAlarmWireColorToFlag[AAlarmwires[wiredesc]] - t1 += "[wiredesc] wire: " - if(!is_uncut) - t1 += "Mend" + var/list/current_settings = TLV["pressure"] + var/environment_pressure = environment.return_pressure() + var/pressure_dangerlevel = get_danger_level(environment_pressure, current_settings) - else - t1 += "Cut " - t1 += "Pulse " + current_settings = TLV["oxygen"] + var/oxygen_dangerlevel = get_danger_level(environment.oxygen*partial_pressure, current_settings) - t1 += "
" - t1 += text("
\n[(src.locked ? "The Air Alarm is locked." : "The Air Alarm is unlocked.")]
\n[((src.shorted || (stat & (NOPOWER|BROKEN))) ? "The Air Alarm is offline." : "The Air Alarm is working properly!")]
\n[(src.aidisabled ? "The 'AI control allowed' light is off." : "The 'AI control allowed' light is on.")]") - t1 += text("

Close

") - user << browse(t1, "window=AAlarmwires") - onclose(user, "AAlarmwires") + current_settings = TLV["carbon dioxide"] + var/co2_dangerlevel = get_danger_level(environment.carbon_dioxide*partial_pressure, current_settings) - if(!shorted) - user << browse(return_text(),"window=air_alarm") - onclose(user, "air_alarm") - refresh_all() + current_settings = TLV["plasma"] + var/plasma_dangerlevel = get_danger_level(environment.toxins*partial_pressure, current_settings) - return + current_settings = TLV["other"] + var/other_moles = 0.0 + for(var/datum/gas/G in environment.trace_gases) + other_moles+=G.moles + var/other_dangerlevel = get_danger_level(other_moles*partial_pressure, current_settings) + current_settings = TLV["temperature"] + var/temperature_dangerlevel = get_danger_level(environment.temperature, current_settings) -/obj/machinery/alarm/proc/isWireColorCut(var/wireColor) - var/wireFlag = AAlarmWireColorToFlag[wireColor] - return ((src.AAlarmwires & wireFlag) == 0) + var/old_danger_level = danger_level + danger_level = max(pressure_dangerlevel, + oxygen_dangerlevel, + co2_dangerlevel, + plasma_dangerlevel, + other_dangerlevel, + temperature_dangerlevel) -/obj/machinery/alarm/proc/isWireCut(var/wireIndex) - var/wireFlag = AAlarmIndexToFlag[wireIndex] - return ((src.AAlarmwires & wireFlag) == 0) + if (old_danger_level != danger_level) + apply_danger_level(danger_level) -/obj/machinery/alarm/proc/cut(var/wireColor) - var/wireFlag = AAlarmWireColorToFlag[wireColor] - var/wireIndex = AAlarmWireColorToIndex[wireColor] - AAlarmwires &= ~wireFlag - switch(wireIndex) - if(AALARM_WIRE_IDSCAN) - src.locked = 1 - //world << "Idscan wire cut" - - if(AALARM_WIRE_POWER) - src.shock(usr, 50) - src.shorted = 1 - update_icon() - //world << "Power wire cut" - - if (AALARM_WIRE_AI_CONTROL) - if (src.aidisabled == 0) - src.aidisabled = 1 - //world << "AI Control Wire Cut" - - if(AALARM_WIRE_SYPHON) - mode = AALARM_MODE_PANIC + if (mode==AALARM_MODE_CYCLE && environment_pressure= danger_levels[4] || current_value <= danger_levels[1]) + return 2 + if(current_value >= danger_levels[3] || current_value <= danger_levels[2]) + return 1 + return 0 + + update_icon() + if(wiresexposed) + icon_state = "alarmx" + return + if((stat & (NOPOWER|BROKEN)) || shorted) + icon_state = "alarmp" + return + switch(max(danger_level, alarm_area.atmosalm)) + if (0) + icon_state = "alarm0" + if (1) + icon_state = "alarm2" //yes, alarm2 is yellow alarm + if (2) + icon_state = "alarm1" + + receive_signal(datum/signal/signal) + if(stat & (NOPOWER|BROKEN)) + return + if (alarm_area.master_air_alarm != src) + if (master_is_operating()) + return + elect_master() + if (alarm_area.master_air_alarm != src) + return + if(!signal || signal.encryption) + return + var/id_tag = signal.data["tag"] + if (!id_tag) + return + if (signal.data["area"] != area_uid) + return + if (signal.data["sigtype"] != "status") + return + + var/dev_type = signal.data["device"] + if(!(id_tag in alarm_area.air_scrub_names) && !(id_tag in alarm_area.air_vent_names)) + register_env_machine(id_tag, dev_type) + if(dev_type == "AScr") + alarm_area.air_scrub_info[id_tag] = signal.data + else if(dev_type == "AVP") + alarm_area.air_vent_info[id_tag] = signal.data + + proc/register_env_machine(var/m_id, var/device_type) + var/new_name + if (device_type=="AVP") + new_name = "[alarm_area.name] Vent Pump #[alarm_area.air_vent_names.len+1]" + alarm_area.air_vent_names[m_id] = new_name + else if (device_type=="AScr") + new_name = "[alarm_area.name] Air Scrubber #[alarm_area.air_scrub_names.len+1]" + alarm_area.air_scrub_names[m_id] = new_name + else + return + spawn (10) + send_signal(m_id, list("init" = new_name) ) + + proc/refresh_all() + for(var/id_tag in alarm_area.air_vent_names) + var/list/I = alarm_area.air_vent_info[id_tag] + if (I && I["timestamp"]+AALARM_REPORT_TIMEOUT/2 > world.time) + continue + send_signal(id_tag, list("status") ) + for(var/id_tag in alarm_area.air_scrub_names) + var/list/I = alarm_area.air_scrub_info[id_tag] + if (I && I["timestamp"]+AALARM_REPORT_TIMEOUT/2 > world.time) + continue + send_signal(id_tag, list("status") ) + + proc/set_frequency(new_frequency) + radio_controller.remove_object(src, frequency) + frequency = new_frequency + radio_connection = radio_controller.add_object(src, frequency, RADIO_TO_AIRALARM) + + proc/send_signal(var/target, var/list/command)//sends signal 'command' to 'target'. Returns 0 if no radio connection, 1 otherwise + if(!radio_connection) + return 0 + + var/datum/signal/signal = new + signal.transmission_method = 1 //radio signal + signal.source = src + + signal.data = command + signal.data["tag"] = target + signal.data["sigtype"] = "command" + + radio_connection.post_signal(src, signal, RADIO_FROM_AIRALARM) + // world << text("Signal [] Broadcasted to []", command, target) + + return 1 + + proc/apply_mode() + var/current_pressures = TLV["pressure"] + var/target_pressure = (current_pressures[2] + current_pressures[3])/2 + switch(mode) + if(AALARM_MODE_SCRUBBING) + for(var/device_id in alarm_area.air_scrub_names) + send_signal(device_id, list("power"= 1, "co2_scrub"= 1, "setting"= 1, "scrubbing"= 1, "panic_siphon"= 0) ) + for(var/device_id in alarm_area.air_vent_names) + send_signal(device_id, list("power"= 1, "checks"= 1, "setting"= 1, "set_external_pressure"= target_pressure) ) + + if(AALARM_MODE_PANIC, AALARM_MODE_CYCLE) + for(var/device_id in alarm_area.air_scrub_names) + send_signal(device_id, list("power"= 1, "panic_siphon"= 1) ) + for(var/device_id in alarm_area.air_vent_names) + send_signal(device_id, list("power"= 0) ) + + if(AALARM_MODE_REPLACEMENT) + for(var/device_id in alarm_area.air_scrub_names) + send_signal(device_id, list("power"= 1, "co2_scrub"= 1, "setting"= 3, "scrubbing"= 1, "panic_siphon"= 0) ) + for(var/device_id in alarm_area.air_vent_names) + send_signal(device_id, list("power"= 1, "checks"= 1, "setting"= 3, "set_external_pressure"= target_pressure) ) + + if(AALARM_MODE_FILL) + for(var/device_id in alarm_area.air_scrub_names) + send_signal(device_id, list("power"= 0) ) + for(var/device_id in alarm_area.air_vent_names) + send_signal(device_id, list("power"= 1, "checks"= 1, "setting"= 3, "set_external_pressure"= target_pressure) ) + + proc/apply_danger_level(var/new_danger_level) + alarm_area.atmosalm = new_danger_level + + for (var/area/A in alarm_area.related) + for (var/obj/machinery/alarm/AA in A) + if ( !(AA.stat & (NOPOWER|BROKEN)) && !AA.shorted && AA.danger_level != new_danger_level) + AA.update_icon() + + if(danger_level > 1) + air_doors_close(0) + else + air_doors_open(0) + + update_icon() + + proc/air_doors_close(manual) + var/area/A = get_area(src) + if(!A.master.air_doors_activated) + A.master.air_doors_activated = 1 + for(var/obj/machinery/door/E in A.master.all_doors) + if(istype(E,/obj/machinery/door/firedoor)) + if(!E:blocked) + if(E.operating) + E:nextstate = CLOSED + else if(!E.density) + spawn(0) + E.close() + continue + +/* if(istype(E, /obj/machinery/door/airlock)) + if((!E:arePowerSystemsOn()) || (E.stat & NOPOWER) || E:air_locked) continue + if(!E.density) + spawn(0) + E.close() + spawn(10) + if(E.density) + E:air_locked = E.req_access + E:req_access = list(ACCESS_ENGINE, ACCESS_ATMOSPHERICS) + E.update_icon() + else if(E.operating) + spawn(10) + E.close() + if(E.density) + E:air_locked = E.req_access + E:req_access = list(ACCESS_ENGINE, ACCESS_ATMOSPHERICS) + E.update_icon() + else if(!E:locked) //Don't lock already bolted doors. + E:air_locked = E.req_access + E:req_access = list(ACCESS_ENGINE, ACCESS_ATMOSPHERICS) + E.update_icon()*/ + + proc/air_doors_open(manual) + var/area/A = get_area(loc) + if(A.master.air_doors_activated) + A.master.air_doors_activated = 0 + for(var/obj/machinery/door/E in A.master.all_doors) + if(istype(E, /obj/machinery/door/firedoor)) + if(!E:blocked) + if(E.operating) + E:nextstate = OPEN + else if(E.density) + spawn(0) + E.open() + continue + +/* if(istype(E, /obj/machinery/door/airlock)) + if((!E:arePowerSystemsOn()) || (E.stat & NOPOWER)) continue + if(!isnull(E:air_locked)) //Don't mess with doors locked for other reasons. + E:req_access = E:air_locked + E:air_locked = null + E.update_icon()*/ + +/////////// +//HACKING// +/////////// + proc/isWireColorCut(var/wireColor) + var/wireFlag = AAlarmWireColorToFlag[wireColor] + return ((AAlarmwires & wireFlag) == 0) + + proc/isWireCut(var/wireIndex) + var/wireFlag = AAlarmIndexToFlag[wireIndex] + return ((AAlarmwires & wireFlag) == 0) + + proc/cut(var/wireColor) + var/wireFlag = AAlarmWireColorToFlag[wireColor] + var/wireIndex = AAlarmWireColorToIndex[wireColor] + AAlarmwires &= ~wireFlag + switch(wireIndex) + if(AALARM_WIRE_IDSCAN) + locked = 1 + + if(AALARM_WIRE_POWER) + shock(usr, 50) shorted = 1 update_icon() - spawn(1200) - if(shorted == 1) - shorted = 0 + if (AALARM_WIRE_AI_CONTROL) + if (aidisabled == 0) + aidisabled = 1 + + if(AALARM_WIRE_SYPHON) + mode = AALARM_MODE_PANIC + apply_mode() + + if(AALARM_WIRE_AALARM) + + if (alarm_area.atmosalert(2)) + apply_danger_level(2) + spawn(1) + updateUsrDialog() + update_icon() + + updateDialog() + + return + + proc/mend(var/wireColor) + var/wireFlag = AAlarmWireColorToFlag[wireColor] + var/wireIndex = AAlarmWireColorToIndex[wireColor] //not used in this function + AAlarmwires |= wireFlag + switch(wireIndex) + if(AALARM_WIRE_IDSCAN) + + if(AALARM_WIRE_POWER) + shorted = 0 + shock(usr, 50) + update_icon() + + if(AALARM_WIRE_AI_CONTROL) + if (aidisabled == 1) + aidisabled = 0 + + updateDialog() + return + + proc/pulse(var/wireColor) + //var/wireFlag = AAlarmWireColorToFlag[wireColor] //not used in this function + var/wireIndex = AAlarmWireColorToIndex[wireColor] + switch(wireIndex) + if(AALARM_WIRE_IDSCAN) //unlocks for 30 seconds, if you have a better way to hack I'm all ears + locked = 0 + spawn(300) + locked = 1 + + if (AALARM_WIRE_POWER) + if(shorted == 0) + shorted = 1 update_icon() + spawn(1200) + if(shorted == 1) + shorted = 0 + update_icon() - if (AALARM_WIRE_AI_CONTROL) - // world << "AI Control wire pulsed" - if (src.aidisabled == 0) - src.aidisabled = 1 - src.updateDialog() - spawn(10) - if (src.aidisabled == 1) - src.aidisabled = 0 - src.updateDialog() - if(AALARM_WIRE_SYPHON) - // world << "Syphon wire pulsed" - mode = AALARM_MODE_REPLACEMENT - apply_mode() + if (AALARM_WIRE_AI_CONTROL) + if (aidisabled == 0) + aidisabled = 1 + updateDialog() + spawn(10) + if (aidisabled == 1) + aidisabled = 0 + updateDialog() - if(AALARM_WIRE_AALARM) - // world << "Aalarm wire pulsed" - if (alarm_area.atmosalert(0)) - post_alert(0) - spawn(1) - src.updateUsrDialog() - update_icon() + if(AALARM_WIRE_SYPHON) + mode = AALARM_MODE_REPLACEMENT + apply_mode() - src.updateDialog() - return + if(AALARM_WIRE_AALARM) + if (alarm_area.atmosalert(0)) + apply_danger_level(0) + spawn(1) + updateUsrDialog() + update_icon() -/obj/machinery/alarm/proc/shock(mob/user, prb) - if((stat & (NOPOWER))) // unpowered, no shock - return 0 - if(!prob(prb)) - return 0 //you lucked out, no shock for you - var/datum/effect/effect/system/spark_spread/s = new /datum/effect/effect/system/spark_spread - s.set_up(5, 1, src) - s.start() //sparks always. - if (electrocute_mob(user, get_area(src), src)) - return 1 - else - return 0 - -/obj/machinery/alarm/receive_signal(datum/signal/signal) - if(stat & (NOPOWER|BROKEN)) + updateDialog() return - if (alarm_area.master_air_alarm != src) - if (master_is_operating()) + + proc/shock(mob/user, prb) + if((stat & (NOPOWER))) // unpowered, no shock + return 0 + if(!prob(prb)) + return 0 //you lucked out, no shock for you + var/datum/effect/effect/system/spark_spread/s = new /datum/effect/effect/system/spark_spread + s.set_up(5, 1, src) + s.start() //sparks always. + if (electrocute_mob(user, get_area(src), src)) + return 1 + else + return 0 +/////////////// +//END HACKING// +/////////////// + + + attack_hand(mob/user) + . = ..() + if (.) return - elect_master() - if (alarm_area.master_air_alarm != src) - return - if(!signal || signal.encryption) - return - var/id_tag = signal.data["tag"] - if (!id_tag) - return - if (signal.data["area"] != area_uid) - return - if (signal.data["sigtype"] != "status") + user.set_machine(src) + + if ( (get_dist(src, user) > 1 )) + if (!istype(user, /mob/living/silicon)) + user.machine = null + user << browse(null, "window=air_alarm") + user << browse(null, "window=AAlarmwires") + return + + + else if (istype(user, /mob/living/silicon) && aidisabled) + user << "AI control for this Air Alarm interface has been disabled." + user << browse(null, "window=air_alarm") + return + + if(wiresexposed && (!istype(user, /mob/living/silicon))) + var/t1 = text("[alarm_area.name] Air Alarm WiresAccess Panel
\n") + var/list/AAlarmwires = list( + "Orange" = 1, + "Dark red" = 2, + "White" = 3, + "Yellow" = 4, + "Black" = 5, + ) + for(var/wiredesc in AAlarmwires) + var/is_uncut = AAlarmwires & AAlarmWireColorToFlag[AAlarmwires[wiredesc]] + t1 += "[wiredesc] wire: " + if(!is_uncut) + t1 += "Mend" + + else + t1 += "Cut " + t1 += "Pulse " + + t1 += "
" + t1 += text("
\n[(locked ? "The Air Alarm is locked." : "The Air Alarm is unlocked.")]
\n[((shorted || (stat & (NOPOWER|BROKEN))) ? "The Air Alarm is offline." : "The Air Alarm is working properly!")]
\n[(aidisabled ? "The 'AI control allowed' light is off." : "The 'AI control allowed' light is on.")]") + t1 += text("

Close

") + user << browse(t1, "window=AAlarmwires") + onclose(user, "AAlarmwires") + + if(!shorted) + user << browse(return_text(user),"window=air_alarm") + onclose(user, "air_alarm") + return - var/dev_type = signal.data["device"] - if(!(id_tag in alarm_area.air_scrub_names) && !(id_tag in alarm_area.air_vent_names)) - register_env_machine(id_tag, dev_type) - if(dev_type == "AScr") - alarm_area.air_scrub_info[id_tag] = signal.data - else if(dev_type == "AVP") - alarm_area.air_vent_info[id_tag] = signal.data + proc/return_text(mob/user) + if(!(istype(user, /mob/living/silicon)) && locked) + return "\The [src][return_status()]
[rcon_text()]
(Swipe ID card to unlock interface)" + else + return "\The [src][return_status()]
[rcon_text()]
[return_controls()]" -/obj/machinery/alarm/proc/register_env_machine(var/m_id, var/device_type) - var/new_name - if (device_type=="AVP") - new_name = "[alarm_area.name] Vent Pump #[alarm_area.air_vent_names.len+1]" - alarm_area.air_vent_names[m_id] = new_name - else if (device_type=="AScr") - new_name = "[alarm_area.name] Air Scrubber #[alarm_area.air_scrub_names.len+1]" - alarm_area.air_scrub_names[m_id] = new_name - else - return - spawn (10) - send_signal(m_id, list("init" = new_name) ) + proc/return_status() + var/turf/location = get_turf(src) + var/datum/gas_mixture/environment = location.return_air() + var/total = environment.oxygen + environment.carbon_dioxide + environment.toxins + environment.nitrogen + var/output = "Air Status:
" -/obj/machinery/alarm/proc/refresh_all() - for(var/id_tag in alarm_area.air_vent_names) - var/list/I = alarm_area.air_vent_info[id_tag] - if (I && I["timestamp"]+AALARM_REPORT_TIMEOUT/2 > world.time) - continue - send_signal(id_tag, list("status") ) - for(var/id_tag in alarm_area.air_scrub_names) - var/list/I = alarm_area.air_scrub_info[id_tag] - if (I && I["timestamp"]+AALARM_REPORT_TIMEOUT/2 > world.time) - continue - send_signal(id_tag, list("status") ) + if(total == 0) + output += "Warning: Cannot obtain air sample for analysis." + return output -/obj/machinery/alarm/proc/set_frequency(new_frequency) - radio_controller.remove_object(src, frequency) - frequency = new_frequency - radio_connection = radio_controller.add_object(src, frequency, RADIO_TO_AIRALARM) - -/obj/machinery/alarm/proc/send_signal(var/target, var/list/command)//sends signal 'command' to 'target'. Returns 0 if no radio connection, 1 otherwise - if(!radio_connection) - return 0 - - var/datum/signal/signal = new - signal.transmission_method = 1 //radio signal - signal.source = src - - signal.data = command - signal.data["tag"] = target - signal.data["sigtype"] = "command" - - radio_connection.post_signal(src, signal, RADIO_FROM_AIRALARM) -// world << text("Signal [] Broadcasted to []", command, target) - - return 1 - -/obj/machinery/alarm/proc/return_text() - if(!(istype(usr, /mob/living/silicon)) && locked) - return "[src][return_status()]
(Swipe ID card to unlock interface)" - else - return "[src][return_status()]
[return_controls()]" - -/obj/machinery/alarm/proc/return_status() - var/turf/location = src.loc - var/datum/gas_mixture/environment = location.return_air() - var/total = environment.oxygen + environment.carbon_dioxide + environment.toxins + environment.nitrogen - var/output = "Air Status:
" - - if(total == 0) - output +={"Warning: Cannot obtain air sample for analysis."} - return output - - output += {" + output += {" "} - var/datum/tlv/cur_tlv - var/GET_PP = R_IDEAL_GAS_EQUATION*environment.temperature/environment.volume - cur_tlv = TLV["pressure"] - var/environment_pressure = environment.return_pressure() - var/pressure_dangerlevel = cur_tlv.get_danger_level(environment_pressure) + var/partial_pressure = R_IDEAL_GAS_EQUATION*environment.temperature/environment.volume - cur_tlv = TLV["oxygen"] - var/oxygen_dangerlevel = cur_tlv.get_danger_level(environment.oxygen*GET_PP) - var/oxygen_percent = round(environment.oxygen / total * 100, 2) + var/list/current_settings = TLV["pressure"] + var/environment_pressure = environment.return_pressure() + var/pressure_dangerlevel = get_danger_level(environment_pressure, current_settings) - cur_tlv = TLV["carbon dioxide"] - var/co2_dangerlevel = cur_tlv.get_danger_level(environment.carbon_dioxide*GET_PP) - var/co2_percent = round(environment.carbon_dioxide / total * 100, 2) + current_settings = TLV["oxygen"] + var/oxygen_dangerlevel = get_danger_level(environment.oxygen*partial_pressure, current_settings) + var/oxygen_percent = round(environment.oxygen / total * 100, 2) - cur_tlv = TLV["plasma"] - var/plasma_dangerlevel = cur_tlv.get_danger_level(environment.toxins*GET_PP) - var/plasma_percent = round(environment.toxins / total * 100, 2) + current_settings = TLV["carbon dioxide"] + var/co2_dangerlevel = get_danger_level(environment.carbon_dioxide*partial_pressure, current_settings) + var/co2_percent = round(environment.carbon_dioxide / total * 100, 2) - cur_tlv = TLV["other"] - var/other_moles = 0.0 - for(var/datum/gas/G in environment.trace_gases) - other_moles+=G.moles - var/other_dangerlevel = cur_tlv.get_danger_level(other_moles*GET_PP) + current_settings = TLV["plasma"] + var/plasma_dangerlevel = get_danger_level(environment.toxins*partial_pressure, current_settings) + var/plasma_percent = round(environment.toxins / total * 100, 2) - cur_tlv = TLV["temperature"] - var/temperature_dangerlevel = cur_tlv.get_danger_level(environment.temperature) + current_settings = TLV["other"] + var/other_moles = 0.0 + for(var/datum/gas/G in environment.trace_gases) + other_moles+=G.moles + var/other_dangerlevel = get_danger_level(other_moles*partial_pressure, current_settings) - output += {" + current_settings = TLV["temperature"] + var/temperature_dangerlevel = get_danger_level(environment.temperature, current_settings) + + output += {" Pressure: [environment_pressure]kPa
Oxygen: [oxygen_percent]%
Carbon dioxide: [co2_percent]%
Toxins: [plasma_percent]%
"} - if (other_dangerlevel==2) - output += {"Notice: High Concentration of Unknown Particles Detected
"} - else if (other_dangerlevel==1) - output += {"Notice: Low Concentration of Unknown Particles Detected
"} + if (other_dangerlevel==2) + output += "Notice: High Concentration of Unknown Particles Detected
" + else if (other_dangerlevel==1) + output += "Notice: Low Concentration of Unknown Particles Detected
" - output += {" -Temperature: [environment.temperature]K
-"} + output += "Temperature: [environment.temperature]K
" - var/display_danger_level = max( - pressure_dangerlevel, - oxygen_dangerlevel, - co2_dangerlevel, - plasma_dangerlevel, - other_dangerlevel, - temperature_dangerlevel - ) + //Overall status + output += "Local Status: " + switch(max(pressure_dangerlevel,oxygen_dangerlevel,co2_dangerlevel,plasma_dangerlevel,other_dangerlevel,temperature_dangerlevel)) + if(2) + output += "DANGER: Internals Required" + if(1) + output += "Caution" + if(0) + if(alarm_area.atmosalm) + output += {"Caution: Atmos alert in area"} + else + output += {"Optimal"} - //Overall status - output += {"Local Status: "} - if(display_danger_level == 2) - output += {"DANGER: Internals Required"} - else if(display_danger_level == 1) - output += {"Caution"} - else if (alarm_area.atmosalm) - output += {"Caution: Atmos alert in area"} - else - output += {"Optimal"} + return output - return output + proc/rcon_text() + var/dat = "Remote Control:
" + if(rcon_setting == RCON_NO) + dat += "Off" + else + dat += "Off" + dat += " | " + if(rcon_setting == RCON_AUTO) + dat += "Auto" + else + dat += "Auto" + dat += " | " + if(rcon_setting == RCON_YES) + dat += "On" + else + dat += "On" + return dat -/obj/machinery/alarm/proc/return_controls() - var/output = ""//"[alarm_zone] Air [name]
" + proc/return_controls() + var/output = ""//"[alarm_zone] Air [name]
" - switch(screen) - if (AALARM_SCREEN_MAIN) - if(alarm_area.atmosalm) - output += {"Reset - Atmospheric Alarm
"} - else - output += {"Activate - Atmospheric Alarm
"} + switch(screen) + if (AALARM_SCREEN_MAIN) + if(alarm_area.atmosalm) + output += "Reset - Atmospheric Alarm
" + else + output += "Activate - Atmospheric Alarm
" - output += {" + output += {" Scrubbers Control
Vents Control
Set environmentals mode
Sensor Settings

"} - if (mode==AALARM_MODE_PANIC) - output += "PANIC SYPHON ACTIVE
Turn syphoning off" - else - output += "ACTIVATE PANIC SYPHON IN AREA" - if (AALARM_SCREEN_VENT) - var/sensor_data = "" - if(alarm_area.air_vent_names.len) - for(var/id_tag in alarm_area.air_vent_names) - var/long_name = alarm_area.air_vent_names[id_tag] - var/list/data = alarm_area.air_vent_info[id_tag] - if(!data) - continue; - var/state = "" - - sensor_data += {" -[long_name][state]
-Operating: -[data["power"]?"on":"off"] -
-Pressure checks: -external -internal -
-External pressure bound: -- -- -- -- -[data["external"]] -+ -+ -+ -+ - (reset) -
-"} - if (data["direction"] == "siphon") - sensor_data += {" -Direction: -siphoning -
-"} - sensor_data += {"
"} - else - sensor_data = "No vents connected.
" - output = {"Main menu
[sensor_data]"} - if (AALARM_SCREEN_SCRUB) - var/sensor_data = "" - if(alarm_area.air_scrub_names.len) - for(var/id_tag in alarm_area.air_scrub_names) - var/long_name = alarm_area.air_scrub_names[id_tag] - var/list/data = alarm_area.air_scrub_info[id_tag] - if(!data) - continue; - var/state = "" - - sensor_data += {" -[long_name][state]
-Operating: -[data["power"]?"on":"off"]
-Type: -[data["scrubbing"]?"scrubbing":"syphoning"]
-"} - - if(data["scrubbing"]) - sensor_data += {" -Filtering: -Carbon Dioxide -[data["filter_co2"]?"on":"off"]; -Toxins -[data["filter_toxins"]?"on":"off"]; -Nitrous Oxide -[data["filter_n2o"]?"on":"off"] -
-"} - sensor_data += {" -Panic syphon: [data["panic"]?"PANIC SYPHON ACTIVATED":""] -Dea":"red'>A")]ctivate
-
-"} - else - sensor_data = "No scrubbers connected.
" - output = {"Main menu
[sensor_data]"} - - if (AALARM_SCREEN_MODE) - output += {" -Main menu
-Air machinery mode for the area:" - if (AALARM_SCREEN_SENSORS) - output += {" + output += "ACTIVATE PANIC SYPHON IN AREA" + + + if (AALARM_SCREEN_VENT) + var/sensor_data = "" + if(alarm_area.air_vent_names.len) + for(var/id_tag in alarm_area.air_vent_names) + var/long_name = alarm_area.air_vent_names[id_tag] + var/list/data = alarm_area.air_vent_info[id_tag] + if(!data) + continue; + var/state = "" + + sensor_data += {" + [long_name][state]
+ Operating: + [data["power"]?"on":"off"] +
+ Pressure checks: + external + internal +
+ External pressure bound: + - + - + - + - + [data["external"]] + + + + + + + + + (reset) +
+ "} + if (data["direction"] == "siphon") + sensor_data += {" + Direction: + siphoning +
+ "} + sensor_data += {"
"} + else + sensor_data = "No vents connected.
" + output = {"Main menu
[sensor_data]"} + if (AALARM_SCREEN_SCRUB) + var/sensor_data = "" + if(alarm_area.air_scrub_names.len) + for(var/id_tag in alarm_area.air_scrub_names) + var/long_name = alarm_area.air_scrub_names[id_tag] + var/list/data = alarm_area.air_scrub_info[id_tag] + if(!data) + continue; + var/state = "" + + sensor_data += {" + [long_name][state]
+ Operating: + [data["power"]?"on":"off"]
+ Type: + [data["scrubbing"]?"scrubbing":"syphoning"]
+ "} + + if(data["scrubbing"]) + sensor_data += {" + Filtering: + Carbon Dioxide + [data["filter_co2"]?"on":"off"]; + Toxins + [data["filter_toxins"]?"on":"off"]; + Nitrous Oxide + [data["filter_n2o"]?"on":"off"] +
+ "} + sensor_data += {" + Panic syphon: [data["panic"]?"PANIC SYPHON ACTIVATED":""] + Dea":"red'>A")]ctivate
+
+ "} + else + sensor_data = "No scrubbers connected.
" + output = {"Main menu
[sensor_data]"} + + if (AALARM_SCREEN_MODE) + output += "Main menu
Air machinery mode for the area:" + + if (AALARM_SCREEN_SENSORS) + output += {" Main menu
Alarm thresholds:
Partial pressure for gases @@ -660,318 +800,165 @@ table tr:first-child th:first-child { border: none;} "} - var/list/gases = list( - "oxygen" = "O2", - "carbon dioxide" = "CO2", - "plasma" = "Toxin", - "other" = "Other", - ) - var/list/thresholds = list("min2", "min1", "max1", "max2") - var/datum/tlv/tlv - for (var/g in gases) - output += {" - -"} - tlv = TLV[g] - for (var/v in thresholds) - output += {" - -"} - output += {" - -"} - tlv = TLV["pressure"] - output += {" - -"} - for (var/v in thresholds) - output += {" - -"} - output += {" - -"} - tlv = TLV["temperature"] - output += {" - -"} - for (var/v in thresholds) - output += {" - -"} - output += {" - -"} - output += {"
min2min1max1max2
[gases[g]] -[tlv.vars[v]>=0?tlv.vars[v]:"OFF"] -
Pressure -[tlv.vars[v]>=0?tlv.vars[v]:"OFF"] -
Temperature -[tlv.vars[v]>=0?tlv.vars[v]:"OFF"] -
"} + var/list/gases = list( + "oxygen" = "O2", + "carbon dioxide" = "CO2", + "plasma" = "Toxin", + "other" = "Other",) - return output + var/list/selected + for (var/g in gases) + output += "[gases[g]]" + selected = TLV[g] + for(var/i = 1, i <= 4, i++) + output += "[selected[i] >= 0 ? selected[i] :"OFF"]" + output += "" -/obj/machinery/alarm/Topic(href, href_list) - if(..()) - return - src.add_fingerprint(usr) - usr.set_machine(src) + selected = TLV["pressure"] + output += " Pressure" + for(var/i = 1, i <= 4, i++) + output += "[selected[i] >= 0 ? selected[i] :"OFF"]" + output += "" - if ( (get_dist(src, usr) > 1 )) - if (!istype(usr, /mob/living/silicon)) - usr.unset_machine() - usr << browse(null, "window=air_alarm") - usr << browse(null, "window=AAlarmwires") - return + selected = TLV["temperature"] + output += "Temperature" + for(var/i = 1, i <= 4, i++) + output += "[selected[i] >= 0 ? selected[i] :"OFF"]" + output += "" - if (href_list["AAlarmwires"]) - var/t1 = text2num(href_list["AAlarmwires"]) - if (!( istype(usr.get_active_hand(), /obj/item/weapon/wirecutters) )) - usr << "You need wirecutters!" - return - if (src.isWireColorCut(t1)) - src.mend(t1) - else - src.cut(t1) - else if (href_list["pulse"]) - var/t1 = text2num(href_list["pulse"]) - if (!istype(usr.get_active_hand(), /obj/item/device/multitool)) - usr << "You need a multitool!" - return - if (src.isWireColorCut(t1)) - usr << "You can't pulse a cut wire." - return - else - src.pulse(t1) + return output + Topic(href, href_list) + if(href_list["rcon"]) + rcon_setting = text2num(href_list["rcon"]) - if(href_list["command"]) - var/device_id = href_list["id_tag"] - switch(href_list["command"]) - if( - "power", - "adjust_external_pressure", - "set_external_pressure", - "checks", - "co2_scrub", - "tox_scrub", - "n2o_scrub", - "panic_siphon", - "scrubbing" - ) - send_signal(device_id, list (href_list["command"] = text2num(href_list["val"]))) - spawn(3) - src.updateUsrDialog() + if ( (get_dist(src, usr) > 1 )) + if (!istype(usr, /mob/living/silicon)) + usr.machine = null + usr << browse(null, "window=air_alarm") + usr << browse(null, "window=AAlarmwires") + return - //if("adjust_threshold") //was a good idea but required very wide window - if("set_threshold") - var/env = href_list["env"] - var/varname = href_list["var"] - var/datum/tlv/tlv = TLV[env] - var/newval = input("Enter [varname] for env", "Alarm triggers", tlv.vars[varname]) as num|null + add_fingerprint(usr) + usr.machine = src - if (isnull(newval) || ..() || (locked && !issilicon(usr))) - return - if (newval<0) - tlv.vars[varname] = -1.0 - else if (env=="temperature" && newval>5000) - tlv.vars[varname] = 5000 - else if (env=="pressure" && newval>50*ONE_ATMOSPHERE) - tlv.vars[varname] = 50*ONE_ATMOSPHERE - else if (env!="temperature" && env!="pressure" && newval>200) - tlv.vars[varname] = 200 - else - newval = round(newval,0.01) - tlv.vars[varname] = newval - spawn(1) - src.updateUsrDialog() + if(href_list["command"]) + var/device_id = href_list["id_tag"] + switch(href_list["command"]) + if( "power", + "adjust_external_pressure", + "set_external_pressure", + "checks", + "co2_scrub", + "tox_scrub", + "n2o_scrub", + "panic_siphon", + "scrubbing") - if(href_list["screen"]) - screen = text2num(href_list["screen"]) - spawn(1) - src.updateUsrDialog() + send_signal(device_id, list(href_list["command"] = text2num(href_list["val"]) ) ) + if("set_threshold") + var/env = href_list["env"] + var/threshold = text2num(href_list["var"]) + var/list/selected = TLV[env] + var/list/thresholds = list("lower bound", "low warning", "high warning", "upper bound") + var/newval = input("Enter [thresholds[threshold]] for [env]", "Alarm triggers", selected[threshold]) as null|num + if (isnull(newval) || ..() || (locked && issilicon(usr))) + return + if (newval<0) + selected[threshold] = -1.0 + else if (env=="temperature" && newval>5000) + selected[threshold] = 5000 + else if (env=="pressure" && newval>50*ONE_ATMOSPHERE) + selected[threshold] = 50*ONE_ATMOSPHERE + else if (env!="temperature" && env!="pressure" && newval>200) + selected[threshold] = 200 + else + newval = round(newval,0.01) + selected[threshold] = newval + if(threshold == 1) + if(selected[1] > selected[2]) + selected[2] = selected[1] + if(selected[1] > selected[3]) + selected[3] = selected[1] + if(selected[1] > selected[4]) + selected[4] = selected[1] + if(threshold == 2) + if(selected[1] > selected[2]) + selected[1] = selected[2] + if(selected[2] > selected[3]) + selected[3] = selected[2] + if(selected[2] > selected[4]) + selected[4] = selected[2] + if(threshold == 3) + if(selected[1] > selected[3]) + selected[1] = selected[3] + if(selected[2] > selected[3]) + selected[2] = selected[3] + if(selected[3] > selected[4]) + selected[4] = selected[3] + if(threshold == 4) + if(selected[1] > selected[4]) + selected[1] = selected[4] + if(selected[2] > selected[4]) + selected[2] = selected[4] + if(selected[3] > selected[4]) + selected[3] = selected[4] + apply_mode() - if(href_list["atmos_alarm"]) - if (alarm_area.atmosalert(2)) - post_alert(2) - spawn(1) - src.updateUsrDialog() - update_icon() - if(href_list["atmos_reset"]) - if (alarm_area.atmosalert(0)) - post_alert(0) - spawn(1) - src.updateUsrDialog() - update_icon() + if(href_list["screen"]) + screen = text2num(href_list["screen"]) - if(href_list["mode"]) - mode = text2num(href_list["mode"]) - apply_mode() - spawn(5) - src.updateUsrDialog() + if(href_list["atmos_unlock"]) + switch(href_list["atmos_unlock"]) + if("0") + air_doors_close(1) + if("1") + air_doors_open(1) - return + if(href_list["atmos_alarm"]) + if (alarm_area.atmosalert(2)) + apply_danger_level(2) + update_icon() -/obj/machinery/alarm/proc/apply_mode() - switch(mode) - if(AALARM_MODE_SCRUBBING) - for(var/device_id in alarm_area.air_scrub_names) - send_signal(device_id, list( - "power"= 1, - "co2_scrub"= 1, - "scrubbing"= 1, - "panic_siphon"= 0, - )) - for(var/device_id in alarm_area.air_vent_names) - send_signal(device_id, list( - "power"= 1, - "checks"= 1, - "set_external_pressure"= ONE_ATMOSPHERE - )) + if(href_list["atmos_reset"]) + if (alarm_area.atmosalert(0)) + apply_danger_level(0) + update_icon() - if(AALARM_MODE_VENTING) - for(var/device_id in alarm_area.air_scrub_names) - send_signal(device_id, list( - "power"= 1, - "panic_siphon"= 0, - "scrubbing"= 0 - )) - for(var/device_id in alarm_area.air_vent_names) - send_signal(device_id, list( - "power"= 1, - "checks"= 1, - "set_external_pressure"= ONE_ATMOSPHERE - )) - if( - AALARM_MODE_PANIC, - AALARM_MODE_REPLACEMENT - ) - for(var/device_id in alarm_area.air_scrub_names) - send_signal(device_id, list( - "power"= 1, - "panic_siphon"= 1 - )) - for(var/device_id in alarm_area.air_vent_names) - send_signal(device_id, list( - "power"= 0 - )) - /*if(AALARM_MODE_OFF) Commented out cause the "turn off panic" uses scrubbing mode now instead. - for(var/device_id in alarm_area.air_scrub_names) - send_signal(device_id, list( - "panic_siphon" = 0 - )) - for(var/device_id in alarm_area.air_vent_names) - send_signal(device_id, list( - "power"= 1 - ))*/ + if(href_list["mode"]) + mode = text2num(href_list["mode"]) + apply_mode() -/obj/machinery/alarm/update_icon() - if(wiresexposed) - icon_state = "alarmx" - return - if((stat & (NOPOWER|BROKEN)) || shorted) - icon_state = "alarmp" - return - switch(max(danger_level, alarm_area.atmosalm)) - if (0) - src.icon_state = "alarm0" - if (1) - src.icon_state = "alarm2" //yes, alarm2 is yellow alarm - if (2) - src.icon_state = "alarm1" + if (href_list["AAlarmwires"]) + var/t1 = text2num(href_list["AAlarmwires"]) + if (!( istype(usr.equipped(), /obj/item/weapon/wirecutters) )) + usr << "You need wirecutters!" + return + if (isWireColorCut(t1)) + mend(t1) + else + cut(t1) -/obj/machinery/alarm/process() - if((stat & (NOPOWER|BROKEN)) || shorted) - return + else if (href_list["pulse"]) + var/t1 = text2num(href_list["pulse"]) + if (!istype(usr.equipped(), /obj/item/device/multitool)) + usr << "You need a multitool!" + return + if (isWireColorCut(t1)) + usr << "You can't pulse a cut wire." + return + else + pulse(t1) - var/turf/simulated/location = src.loc - if (!istype(location)) - return 0 + updateUsrDialog() - var/datum/gas_mixture/environment = location.return_air() - - var/datum/tlv/cur_tlv - var/GET_PP = R_IDEAL_GAS_EQUATION*environment.temperature/environment.volume - - cur_tlv = TLV["pressure"] - var/environment_pressure = environment.return_pressure() - var/pressure_dangerlevel = cur_tlv.get_danger_level(environment_pressure) - - cur_tlv = TLV["oxygen"] - var/oxygen_dangerlevel = cur_tlv.get_danger_level(environment.oxygen*GET_PP) - - cur_tlv = TLV["carbon dioxide"] - var/co2_dangerlevel = cur_tlv.get_danger_level(environment.carbon_dioxide*GET_PP) - - cur_tlv = TLV["plasma"] - var/plasma_dangerlevel = cur_tlv.get_danger_level(environment.toxins*GET_PP) - - cur_tlv = TLV["other"] - var/other_moles = 0.0 - for(var/datum/gas/G in environment.trace_gases) - other_moles+=G.moles - var/other_dangerlevel = cur_tlv.get_danger_level(other_moles*GET_PP) - - cur_tlv = TLV["temperature"] - var/temperature_dangerlevel = cur_tlv.get_danger_level(environment.temperature) - - var/old_danger_level = danger_level - danger_level = max( - pressure_dangerlevel, - oxygen_dangerlevel, - co2_dangerlevel, - plasma_dangerlevel, - other_dangerlevel, - temperature_dangerlevel - ) - if (old_danger_level!=danger_level) - apply_danger_level() - - if (mode==AALARM_MODE_REPLACEMENT && environment_pressure T0C+200) - src.alarm() // added check of detector status here + alarm() // added check of detector status here return /obj/machinery/firealarm/attack_ai(mob/user as mob) - return src.attack_hand(user) + return attack_hand(user) /obj/machinery/firealarm/bullet_act(BLAH) - return src.alarm() + return alarm() /obj/machinery/firealarm/attack_paw(mob/user as mob) - return src.attack_hand(user) + return attack_hand(user) /obj/machinery/firealarm/emp_act(severity) if(prob(50/severity)) alarm() @@ -1033,38 +1017,36 @@ table tr:first-child th:first-child { border: none;} /obj/machinery/firealarm/attackby(obj/item/weapon/W as obj, mob/user as mob) if (istype(W, /obj/item/weapon/wirecutters)) - src.detecting = !( src.detecting ) - if (src.detecting) - user.visible_message("\red [user] has reconnected [src]'s detecting unit!", "You have reconnected [src]'s detecting unit.") - else - user.visible_message("\red [user] has disconnected [src]'s detecting unit!", "You have disconnected [src]'s detecting unit.") + detecting = !detecting + user.visible_message("\red \The [user] has [detecting ? "re" : "dis" ]connected \the [src]'s detecting unit!",\ + "You have [detecting ? "re" : "dis" ]connected \the [src]'s detecting unit.") else - src.alarm() - src.add_fingerprint(user) + alarm() + add_fingerprint(user) return -/obj/machinery/firealarm/process()//Note: this processing was mostly phased out due to other code, and only runs when needed +/obj/machinery/firealarm/process() if(stat & (NOPOWER|BROKEN)) return -// var/area/A = src.loc -// A = A.loc + var/area/A = get_area(src) + ASSERT(isarea(A)) + if(A.master) + A = A.master -// if(A.fire) -// src.icon_state = "fire1" -// else -// src.icon_state = "fire0" + if(A.fire) + icon_state = "fire1" + else + icon_state = "fire0" - if(src.timing) - if(src.time > 0) - src.time = src.time - ((world.timeofday - last_process)/10) + if (timing) + if (time > 0) + time = round(time) - 1 else - src.alarm() - src.time = 0 - src.timing = 0 - processing_objects.Remove(src) - src.updateDialog() - last_process = world.timeofday + alarm() + time = 0 + timing = 0 + updateDialog() return /obj/machinery/firealarm/power_change() @@ -1080,38 +1062,39 @@ table tr:first-child th:first-child { border: none;} if(user.stat || stat & (NOPOWER|BROKEN)) return - user.set_machine(src) - var/area/A = src.loc + user.machine = src + var/area/A = get_area(src) + ASSERT(isarea(A)) + if(A.master) + A = A.master var/d1 var/d2 if (istype(user, /mob/living/carbon/human) || istype(user, /mob/living/silicon)) - A = A.loc if (A.fire) d1 = text("Reset - Lockdown", src) else d1 = text("Alarm - Lockdown", src) - if (src.timing) + if (timing) d2 = text("Stop Time Lock", src) else d2 = text("Initiate Time Lock", src) - var/second = round(src.time) % 60 - var/minute = (round(src.time) - second) / 60 + var/second = time % 60 + var/minute = (time - second) / 60 var/dat = "Fire alarm [d1]\n
The current alert level is: [get_security_level()]

\nTimer System: [d2]
\nTime Left: [(minute ? "[minute]:" : null)][second] - - + +\n
" user << browse(dat, "window=firealarm") onclose(user, "firealarm") else - A = A.loc if (A.fire) d1 = text("[]", src, stars("Reset - Lockdown")) else d1 = text("[]", src, stars("Alarm - Lockdown")) - if (src.timing) + if (timing) d2 = text("[]", src, stars("Stop Time Lock")) else d2 = text("[]", src, stars("Initiate Time Lock")) - var/second = round(src.time) % 60 - var/minute = (round(src.time) - second) / 60 + var/second = time % 60 + var/minute = (time - second) / 60 var/dat = "[stars("Fire alarm")] [d1]\n
The current alert level is: [stars(get_security_level())]

\nTimer System: [d2]
\nTime Left: [(minute ? text("[]:", minute) : null)][second] - - + +\n
" user << browse(dat, "window=firealarm") onclose(user, "firealarm") @@ -1121,114 +1104,114 @@ table tr:first-child th:first-child { border: none;} ..() if (usr.stat || stat & (BROKEN|NOPOWER)) return - if ((usr.contents.Find(src) || ((get_dist(src, usr) <= 1) && istype(src.loc, /turf))) || (istype(usr, /mob/living/silicon))) - usr.set_machine(src) + if ((usr.contents.Find(src) || ((get_dist(src, usr) <= 1) && istype(loc, /turf))) || (istype(usr, /mob/living/silicon))) + usr.machine = src if (href_list["reset"]) - src.reset() + reset() else if (href_list["alarm"]) - src.alarm() + alarm() else if (href_list["time"]) - src.timing = text2num(href_list["time"]) - last_process = world.timeofday - processing_objects.Add(src) + timing = text2num(href_list["time"]) else if (href_list["tp"]) var/tp = text2num(href_list["tp"]) - src.time += tp - src.time = min(max(round(src.time), 0), 120) - src.updateUsrDialog() + time += tp + time = min(max(round(time), 0), 120) + updateUsrDialog() - src.add_fingerprint(usr) + add_fingerprint(usr) else usr << browse(null, "window=firealarm") return return /obj/machinery/firealarm/proc/reset() - if (!( src.working )) - return - var/area/A = src.loc - A = A.loc - if (!( istype(A, /area) )) + if (!working) return + var/area/A = get_area(src) + ASSERT(isarea(A)) + if(A.master) + A = A.master for(var/area/RA in A.related) RA.firereset() return /obj/machinery/firealarm/proc/alarm() - if (!( src.working )) - return - var/area/A = src.loc - A = A.loc - if (!( istype(A, /area) )) + if (!( working )) return + var/area/A = get_area(src) + ASSERT(isarea(A)) + if(A.master) + A = A.master for(var/area/RA in A.related) RA.firealert() - //playsound(src.loc, 'sound/ambience/signal.ogg', 75, 0) + //playsound(loc, 'signal.ogg', 75, 0) return /obj/machinery/partyalarm/attack_paw(mob/user as mob) - return src.attack_hand(user) + return attack_hand(user) + /obj/machinery/partyalarm/attack_hand(mob/user as mob) if(user.stat || stat & (NOPOWER|BROKEN)) return - user.set_machine(src) - var/area/A = src.loc + user.machine = src + var/area/A = get_area(src) + ASSERT(isarea(A)) + if(A.master) + A = A.master var/d1 var/d2 if (istype(user, /mob/living/carbon/human) || istype(user, /mob/living/silicon/ai)) - A = A.loc if (A.party) d1 = text("No Party :(", src) else d1 = text("PARTY!!!", src) - if (src.timing) + if (timing) d2 = text("Stop Time Lock", src) else d2 = text("Initiate Time Lock", src) - var/second = src.time % 60 - var/minute = (src.time - second) / 60 + var/second = time % 60 + var/minute = (time - second) / 60 var/dat = text("Party Button []\n
\nTimer System: []
\nTime Left: [][] - - + +\n
", d1, d2, (minute ? text("[]:", minute) : null), second, src, src, src, src) user << browse(dat, "window=partyalarm") onclose(user, "partyalarm") else - A = A.loc if (A.fire) d1 = text("[]", src, stars("No Party :(")) else d1 = text("[]", src, stars("PARTY!!!")) - if (src.timing) + if (timing) d2 = text("[]", src, stars("Stop Time Lock")) else d2 = text("[]", src, stars("Initiate Time Lock")) - var/second = src.time % 60 - var/minute = (src.time - second) / 60 + var/second = time % 60 + var/minute = (time - second) / 60 var/dat = text("[] []\n
\nTimer System: []
\nTime Left: [][] - - + +\n
", stars("Party Button"), d1, d2, (minute ? text("[]:", minute) : null), second, src, src, src, src) user << browse(dat, "window=partyalarm") onclose(user, "partyalarm") return /obj/machinery/partyalarm/proc/reset() - if (!( src.working )) - return - var/area/A = src.loc - A = A.loc - if (!( istype(A, /area) )) + if (!( working )) return + var/area/A = get_area(src) + ASSERT(isarea(A)) + if(A.master) + A = A.master A.partyreset() return /obj/machinery/partyalarm/proc/alarm() - if (!( src.working )) - return - var/area/A = src.loc - A = A.loc - if (!( istype(A, /area) )) + if (!( working )) return + var/area/A = get_area(src) + ASSERT(isarea(A)) + if(A.master) + A = A.master A.partyalert() return @@ -1236,25 +1219,25 @@ table tr:first-child th:first-child { border: none;} ..() if (usr.stat || stat & (BROKEN|NOPOWER)) return - if ((usr.contents.Find(src) || ((get_dist(src, usr) <= 1) && istype(src.loc, /turf))) || (istype(usr, /mob/living/silicon/ai))) - usr.set_machine(src) + if ((usr.contents.Find(src) || ((get_dist(src, usr) <= 1) && istype(loc, /turf))) || (istype(usr, /mob/living/silicon/ai))) + usr.machine = src if (href_list["reset"]) - src.reset() + reset() else if (href_list["alarm"]) - src.alarm() + alarm() else if (href_list["time"]) - src.timing = text2num(href_list["time"]) + timing = text2num(href_list["time"]) else if (href_list["tp"]) var/tp = text2num(href_list["tp"]) - src.time += tp - src.time = min(max(round(src.time), 0), 120) - src.updateUsrDialog() + time += tp + time = min(max(round(time), 0), 120) + updateUsrDialog() - src.add_fingerprint(usr) + add_fingerprint(usr) else usr << browse(null, "window=partyalarm") return - return + return \ No newline at end of file diff --git a/code/game/machinery/computer/ai_core.dm b/code/game/machinery/computer/ai_core.dm index 616a62c78b6..c3e0941b101 100644 --- a/code/game/machinery/computer/ai_core.dm +++ b/code/game/machinery/computer/ai_core.dm @@ -117,16 +117,16 @@ laws.add_inherent_law(M.newFreeFormLaw) usr << "Added a freeform law." - if(istype(P, /obj/item/device/mmi)) + if(istype(P, /obj/item/device/mmi) || istype(P, /obj/item/device/posibrain)) if(!P:brainmob) - user << "\red Sticking an empty MMI into the frame would sort of defeat the purpose." + user << "\red Sticking an empty [P] into the frame would sort of defeat the purpose." return if(P:brainmob.stat == 2) - user << "\red Sticking a dead brain into the frame would sort of defeat the purpose." + user << "\red Sticking a dead [P] into the frame would sort of defeat the purpose." return if(jobban_isbanned(P:brainmob, "AI")) - user << "\red This MMI does not seem to fit." + user << "\red This [P] does not seem to fit." return if(P:brainmob.mind) @@ -136,7 +136,7 @@ user.drop_item() P.loc = src brain = P - usr << "Added a brain." + usr << "Added [P]." icon_state = "3b" if(istype(P, /obj/item/weapon/crowbar) && brain) diff --git a/code/game/machinery/doors/firedoor.dm b/code/game/machinery/doors/firedoor.dm index 14e544dcb05..b755f16d0a0 100644 --- a/code/game/machinery/doors/firedoor.dm +++ b/code/game/machinery/doors/firedoor.dm @@ -1,52 +1,188 @@ /var/const/OPEN = 1 /var/const/CLOSED = 2 - /obj/machinery/door/firedoor - name = "Firelock" - desc = "Apply crowbar" - icon = 'icons/obj/doors/Doorfire.dmi' + name = "\improper Emergency Shutter" + desc = "Emergency air-tight shutter, capable of sealing off breached areas." + icon = 'DoorHazard.dmi' icon_state = "door_open" + req_one_access = list(access_atmospherics, access_engine_equip) opacity = 0 density = 0 - power_channel = ENVIRON + var/blocked = 0 var/nextstate = null + var/net_id + var/list/areas_added + var/list/users_to_open + + New() + . = ..() + var/area/A = get_area(src) + ASSERT(istype(A)) + + A.all_doors.Add(src) + areas_added = list(A) + + for(var/direction in cardinal) + A = get_area(get_step(src,direction)) + if(istype(A) && !(A in areas_added)) + A.all_doors.Add(src) + areas_added += A + + + Del() + for(var/area/A in areas_added) + A.all_doors.Remove(src) + . = ..() + + + examine() + set src in view() + . = ..() + if( islist(users_to_open) && users_to_open.len) + var/users_to_open_string = users_to_open[1] + if(users_to_open.len >= 2) + for(var/i = 2 to users_to_open.len) + users_to_open_string += ", [users_to_open[i]]" + usr << "These people have opened \the [src] during an alert: [users_to_open_string]." Bumped(atom/AM) - if(p_open || operating) return - if(!density) return ..() + if(p_open || operating) + return + if(!density) + return ..() return 0 power_change() - if(powered(power_channel)) + if(powered(ENVIRON)) stat &= ~NOPOWER else stat |= NOPOWER return + attack_hand(mob/user as mob) + return attackby(null, user) + + attackby(obj/item/weapon/C as obj, mob/user as mob) add_fingerprint(user) - if(operating) return//Already doing something. + if(operating) + return//Already doing something. if(istype(C, /obj/item/weapon/weldingtool)) var/obj/item/weapon/weldingtool/W = C if(W.remove_fuel(0, user)) blocked = !blocked - user << text("\red You [blocked?"welded":"unwelded"] the [src]") + user.visible_message("\red \The [user] [blocked ? "welds" : "unwelds"] \the [src] with \a [W].",\ + "You [blocked ? "weld" : "unweld"] \the [src] with \the [W].",\ + "You hear something being welded.") update_icon() return - if(istype(C, /obj/item/weapon/crowbar) || (istype(C,/obj/item/weapon/twohanded/fireaxe) && C:wielded == 1)) - if(blocked || operating) return + if(blocked) + user << "\red \The [src] is welded solid!" + return + + var/area/A = get_area(src) + ASSERT(istype(A)) + if(A.master) + A = A.master + var/alarmed = A.air_doors_activated || A.fire + + if( istype(C, /obj/item/weapon/crowbar) || ( istype(C,/obj/item/weapon/twohanded/fireaxe) && C:wielded == 1 ) ) + if(operating) + return + if( blocked && istype(C, /obj/item/weapon/crowbar) ) + user.visible_message("\red \The [user] pries at \the [src] with \a [C], but \the [src] is welded in place!",\ + "You try to pry \the [src] [density ? "open" : "closed"], but it is welded in place!",\ + "You hear someone struggle and metal straining.") + return + if( istype(C, /obj/item/weapon/crowbar) ) + if( stat & (BROKEN|NOPOWER) || !density || !alarmed ) + user.visible_message("\red \The [user] forces \the [src] [density ? "open" : "closed"] with \a [C]!",\ + "You force \the [src] [density ? "open" : "closed"] with \the [C]!",\ + "You hear metal strain, and a door [density ? "open" : "close"].") + else if( allowed(user) ) + user.visible_message("\blue \The [user] lifts \the [src] with \a [C].",\ + "\The [src] scans your ID, and obediently opens as you apply your [C].",\ + "You hear metal move, and a door [density ? "open" : "close"].") + else + user.visible_message("\blue \The [user] pries at \the [src] with \a [C], but \the [src] resists being opened.",\ + "\red You pry at \the [src], but it actively resists your efforts. Maybe use your ID, perhaps?",\ + "You hear someone struggling and metal straining") + return + else + user.visible_message("\red \The [user] forces \the [ blocked ? "welded" : "" ] [src] [density ? "open" : "closed"] with \a [C]!",\ + "You force \the [ blocked ? "welded" : "" ] [src] [density ? "open" : "closed"] with \the [C]!",\ + "You hear metal strain and groan, and a door [density ? "open" : "close"].") if(density) + spawn(0) + open() + else + spawn(0) + close() + + var/access_granted = 0 + var/users_name + if(!istype(C, /obj)) //If someone hit it with their hand. We need to see if they are allowed. + if(allowed(user)) + access_granted = 1 + if(ishuman(user)) + users_name = FindNameFromID(user) + else + users_name = "Unknown" + + if( !stat && ( istype(C, /obj/item/weapon/card/id) || istype(C, /obj/item/device/pda) ) ) + var/obj/item/weapon/card/id/ID = C + + if( istype(C, /obj/item/device/pda) ) + var/obj/item/device/pda/pda = C + ID = pda.id + if(!istype(ID)) + ID = null + + if(ID) + users_name = ID.registered_name + + if(check_access(ID)) + access_granted = 1 + + var/answer = alert(user, "Would you like to [density ? "open" : "close"] this [src.name]?[ alarmed && density && !access_granted ? "\nNote that by doing so, you acknowledge any damages from opening this\n[src.name] as being your own fault, and you will be held accountable under the law." : ""]",\ + "\The [src]", "Yes, [density ? "open" : "close"]", "No") + if(answer == "No") + return + if(user.stat || !user.canmove || user.stunned || user.weakened || user.paralysis || get_dist(src, user) > 1) + user << "Sorry, you must remain able bodied and close to \the [src] in order to use it." + return + + if(alarmed && density && !access_granted && !( users_name in users_to_open ) ) + user.visible_message("\red \The [src] opens for \the [user], but only after they acknowledged responsibility for the consequences.",\ + "\The [src] opens after you acknowledge the consequences.",\ + "You hear a beep, and a door opening.") + if(!users_to_open) + users_to_open = list() + users_to_open += users_name + else + user.visible_message("\blue \The [src] [density ? "open" : "close"]s for \the [user].",\ + "\The [src] [density ? "open" : "close"]s.",\ + "You hear a beep, and a door opening.") + + var/needs_to_close = 0 + if(density) + if(alarmed) + needs_to_close = 1 + spawn() open() - return - else //close it up again //fucking 10/10 commenting here einstein + else + spawn() close() - return - return + + if(needs_to_close) + spawn(50) + if(alarmed) + nextstate = CLOSED process() @@ -54,9 +190,11 @@ return switch(nextstate) if(OPEN) - open() + spawn() + open() if(CLOSED) - close() + spawn() + close() nextstate = null return @@ -83,6 +221,4 @@ return - -//border_only fire doors are special when it comes to air groups /obj/machinery/door/firedoor/border_only \ No newline at end of file diff --git a/code/game/machinery/doors/unpowered.dm b/code/game/machinery/doors/unpowered.dm index b4992059f6f..dce2ab37bda 100644 --- a/code/game/machinery/doors/unpowered.dm +++ b/code/game/machinery/doors/unpowered.dm @@ -4,7 +4,8 @@ Bumped(atom/AM) - if(src.locked) return + if(src.locked) + return ..() return diff --git a/code/game/mecha/mecha.dm b/code/game/mecha/mecha.dm index 84fd6c7ae9f..f3e14d0b291 100644 --- a/code/game/mecha/mecha.dm +++ b/code/game/mecha/mecha.dm @@ -668,7 +668,7 @@ /obj/mecha/attackby(obj/item/weapon/W as obj, mob/user as mob) - if(istype(W, /obj/item/device/mmi)) + if(istype(W, /obj/item/device/mmi) || istype(W, /obj/item/device/posibrain)) if(mmi_move_inside(W,user)) user << "[src]-MMI interface initialized successfuly" else @@ -1804,4 +1804,4 @@ //src.health = initial(src.health)/2.2 //src.check_for_internal_damage(list(MECHA_INT_FIRE,MECHA_INT_TEMP_CONTROL,MECHA_INT_TANK_BREACH,MECHA_INT_CONTROL_LOST)) return -*/ +*/ diff --git a/code/game/objects/items/robot/robot_parts.dm b/code/game/objects/items/robot/robot_parts.dm index acd210f5ddc..189aad862a7 100644 --- a/code/game/objects/items/robot/robot_parts.dm +++ b/code/game/objects/items/robot/robot_parts.dm @@ -161,14 +161,14 @@ else user << "\blue You need to attach a flash to it first!" - if(istype(W, /obj/item/device/mmi)) + if(istype(W, /obj/item/device/mmi) || istype(W, /obj/item/device/posibrain)) var/obj/item/device/mmi/M = W if(check_completion()) if(!istype(loc,/turf)) - user << "\red You can't put the MMI in, the frame has to be standing on the ground to be perfectly precise." + user << "\red You can't put the [W] in, the frame has to be standing on the ground to be perfectly precise." return if(!M.brainmob) - user << "\red Sticking an empty MMI into the frame would sort of defeat the purpose." + user << "\red Sticking an empty [W] into the frame would sort of defeat the purpose." return if(!M.brainmob.key) var/ghost_can_reenter = 0 @@ -178,19 +178,19 @@ ghost_can_reenter = 1 break if(!ghost_can_reenter) - user << "The mmi indicates that their mind is completely unresponsive; there's no point." + user << "The [W] is completely unresponsive; there's no point." return if(M.brainmob.stat == DEAD) - user << "\red Sticking a dead brain into the frame would sort of defeat the purpose." + user << "\red Sticking a dead [W] into the frame would sort of defeat the purpose." return if(M.brainmob.mind in ticker.mode.head_revolutionaries) - user << "\red The frame's firmware lets out a shrill sound, and flashes 'Abnormal Memory Engram'. It refuses to accept the MMI." + user << "\red The frame's firmware lets out a shrill sound, and flashes 'Abnormal Memory Engram'. It refuses to accept the [W]." return if(jobban_isbanned(M.brainmob, "Cyborg")) - user << "\red This MMI does not seem to fit." + user << "\red This [W] does not seem to fit." return var/mob/living/silicon/robot/O = new /mob/living/silicon/robot(get_turf(loc)) diff --git a/code/game/objects/items/weapons/hydroponics.dm b/code/game/objects/items/weapons/hydroponics.dm index 9ebb60804fa..619828f68ce 100644 --- a/code/game/objects/items/weapons/hydroponics.dm +++ b/code/game/objects/items/weapons/hydroponics.dm @@ -38,6 +38,118 @@ if(0) usr << "The bag now picks up one plant at a time." +/* + * SeedBag + */ + +/obj/item/weapon/seedbag + icon = 'icons/obj/hydroponics.dmi' + icon_state = "seedbag" + name = "Seed Bag" + desc = "A small satchel made for organizing seeds." + var/mode = 1; //0 = pick one at a time, 1 = pick all on tile + var/capacity = 500; //the number of seeds it can carry. + flags = FPRINT | TABLEPASS + slot_flags = SLOT_BELT + w_class = 1 + var/list/item_quants = list() + +/obj/item/weapon/seedbag/attack_self(mob/user as mob) + user.machine = src + interact(user) + +/obj/item/weapon/seedbag/verb/toggle_mode() + set name = "Switch Bagging Method" + set category = "Object" + + mode = !mode + switch (mode) + if(1) + usr << "The bag now picks up all seeds in a tile at once." + if(0) + usr << "The bag now picks up one seed pouch at a time." + +/obj/item/seeds/attackby(var/obj/item/O as obj, var/mob/user as mob) + ..() + if (istype(O, /obj/item/weapon/seedbag)) + var/obj/item/weapon/seedbag/S = O + if (S.mode == 1) + for (var/obj/item/seeds/G in locate(src.x,src.y,src.z)) + if (S.contents.len < S.capacity) + S.contents += G; + if(S.item_quants[G.name]) + S.item_quants[G.name]++ + else + S.item_quants[G.name] = 1 + else + user << "\blue The seed bag is full." + S.updateUsrDialog() + return + user << "\blue You pick up all the seeds." + else + if (S.contents.len < S.capacity) + S.contents += src; + if(S.item_quants[name]) + S.item_quants[name]++ + else + S.item_quants[name] = 1 + else + user << "\blue The seed bag is full." + S.updateUsrDialog() + return + +/obj/item/weapon/seedbag/interact(mob/user as mob) + + var/dat = "Select an item:
" + + if (contents.len == 0) + dat += "No seeds loaded!" + else + for (var/O in item_quants) + if(item_quants[O] > 0) + var/N = item_quants[O] + dat += "[capitalize(O)]:" + dat += " [N] " + dat += "Vend" + dat += "
" + + dat += "
Unload All" + dat += "
" + user << browse("Seedbag Supplies[dat]", "window=seedbag") + onclose(user, "seedbag") + return + +/obj/item/weapon/seedbag/Topic(href, href_list) + if(..()) + return + + usr.machine = src + if ( href_list["vend"] ) + var/N = href_list["vend"] + + if(item_quants[N] <= 0) // Sanity check, there are probably ways to press the button when it shouldn't be possible. + return + + item_quants[N] -= 1 + for(var/obj/O in contents) + if(O.name == N) + O.loc = get_turf(src) + usr.put_in_hands(O) + break + + else if ( href_list["unload"] ) + item_quants.Cut() + for(var/obj/O in contents ) + O.loc = get_turf(src) + + src.updateUsrDialog() + return + +/obj/item/weapon/seedbag/updateUsrDialog() + var/list/nearby = range(1, src) + for(var/mob/M in nearby) + if ((M.client && M.machine == src)) + src.attack_self(M) /* * Sunflower diff --git a/code/game/objects/structures/crates_lockers/closets/secure/hydroponics.dm b/code/game/objects/structures/crates_lockers/closets/secure/hydroponics.dm index f96c0bdce34..b9c963ab0f8 100644 --- a/code/game/objects/structures/crates_lockers/closets/secure/hydroponics.dm +++ b/code/game/objects/structures/crates_lockers/closets/secure/hydroponics.dm @@ -17,6 +17,7 @@ new /obj/item/clothing/suit/apron(src) if(2) new /obj/item/clothing/suit/apron/overalls(src) + new /obj/item/weapon/seedbag(src) new /obj/item/weapon/plantbag(src) new /obj/item/clothing/under/rank/hydroponics(src) new /obj/item/device/analyzer/plant_analyzer(src) diff --git a/code/modules/mob/living/carbon/brain/posibrain.dm b/code/modules/mob/living/carbon/brain/posibrain.dm new file mode 100644 index 00000000000..bff5a6e192f --- /dev/null +++ b/code/modules/mob/living/carbon/brain/posibrain.dm @@ -0,0 +1,118 @@ +/obj/item/device/posibrain + name = "positronic brain" + desc = "A cube of shining metal, four inches to a side and covered in shallow grooves." + icon = 'icons/obj/assemblies.dmi' + icon_state = "posibrain" + w_class = 3 + origin_tech = "engineering=4;materials=4;bluespace=2;programming=6" + + var/list/construction_cost = list("metal"=500,"glass"=500,"silver"=200,"gold"=200,"plasma"=100,"diamond"=10) + var/construction_time = 75 + var/searching = 0 + var/askDelay = 10 * 60 * 1 + + req_access = list(access_robotics) + var/locked = 0 + var/mob/living/carbon/brain/brainmob = null//The current occupant. + var/obj/mecha = null//This does not appear to be used outside of reference in mecha.dm. + + attack_self(mob/user as mob) + if(!brainmob && searching == 0) + //Start the process of searching for a new user. + user << "\blue You carefully locate the manual activation switch and start the positronic brain's boot process." + icon_state = "posibrain-searching" + src.searching = 1 + src.request_player() + spawn(600) reset_search() + + proc/request_player() + for(var/mob/dead/observer/O in player_list) + if(jobban_isbanned(O, "pAI")) + continue + if(O.client) + if(O.client.be_pai) + question(O.client) + + proc/question(var/client/C) + spawn(0) + if(!C) return + var/response = alert(C, "Someone is requesting a personality for a positronic brain. Would you like to play as one?", "Positronic brain request", "Yes", "No", "Never for this round") + if(!C || brainmob) return //handle logouts that happen whilst the alert is waiting for a response, and responses issued after a brain has been located. + if(response == "Yes") + transfer_personality(C.mob) + else if (response == "Never for this round") + C.be_pai = 0 + + + proc/transfer_personality(var/mob/candidate) + + var/mob/living/carbon/brain/B = new(src) + + src.searching = 0 + + src.brainmob = B + src.brainmob.mind = candidate.mind + + src.brainmob.name = "PBU-[rand(100, 999)]" + src.brainmob.real_name = "PBU-[rand(100, 999)]" + src.brainmob.loc = src + src.brainmob.container = src + src.brainmob.stat = 0 + src.brainmob.silent = 0 + src.brainmob.brain_op_stage = 4.0 + src.brainmob.key = candidate.key + + dead_mob_list -= src.brainmob + living_mob_list += src.brainmob + + var/turf/T = get_turf_or_move(src.loc) + for (var/mob/M in viewers(T)) + M.show_message("\blue The positronic brain chimes quietly.") + icon_state = "posibrain-occupied" + + proc/reset_search() //We give the players sixty seconds to decide, then reset the timer. + + if(brainmob) return + + src.searching = 0 + icon_state = "posibrain" + + var/turf/T = get_turf_or_move(src.loc) + for (var/mob/M in viewers(T)) + M.show_message("\blue The positronic brain buzzes quietly, and the golden lights fade away. Perhaps you could try again?") + +/obj/item/device/posibrain/examine() + + set src in oview() + + if(!usr || !src) return + if( (usr.sdisabilities & BLIND || usr.blinded || usr.stat) && !istype(usr,/mob/dead/observer) ) + usr << "Something is there but you can't see it." + return + + var/msg = "*---------*\nThis is \icon[src] \a [src]!\n[desc]\n" + msg += "" + + if(src.brainmob) + switch(src.brainmob.stat) + if(CONSCIOUS) + if(!src.brainmob.client) msg += "It appears to be in stand-by mode.\n" //afk + if(UNCONSCIOUS) msg += "It doesn't seem to be responsive.\n" + if(DEAD) msg += "It appears to be completely inactive.\n" + else + msg += "*---------*" + usr << msg + return + +/obj/item/device/posibrain/emp_act(severity) + if(!brainmob) + return + else + switch(severity) + if(1) + brainmob.emp_damage += rand(20,30) + if(2) + brainmob.emp_damage += rand(10,20) + if(3) + brainmob.emp_damage += rand(0,10) + ..() \ No newline at end of file diff --git a/code/modules/mob/living/carbon/brain/say.dm b/code/modules/mob/living/carbon/brain/say.dm index 4b8174cc21b..c4d9a865da2 100644 --- a/code/modules/mob/living/carbon/brain/say.dm +++ b/code/modules/mob/living/carbon/brain/say.dm @@ -2,7 +2,7 @@ if (silent) return - if(!(container && istype(container, /obj/item/device/mmi))) + if(!(container && (istype(container, /obj/item/device/mmi) || istype(container, /obj/item/device/posibrain)))) return //No MMI, can't speak, bucko./N else if(prob(emp_damage*4)) diff --git a/icons/obj/assemblies.dmi b/icons/obj/assemblies.dmi index a0c27d7816b..a4a72b0a380 100644 Binary files a/icons/obj/assemblies.dmi and b/icons/obj/assemblies.dmi differ diff --git a/icons/obj/hydroponics.dmi b/icons/obj/hydroponics.dmi index e45d28d3c2c..03a8c72bc02 100644 Binary files a/icons/obj/hydroponics.dmi and b/icons/obj/hydroponics.dmi differ diff --git a/maps/tgstation.2.0.9.1.dmm b/maps/tgstation.2.0.9.1.dmm index e7e4ab656f0..1bce8a84949 100644 --- a/maps/tgstation.2.0.9.1.dmm +++ b/maps/tgstation.2.0.9.1.dmm @@ -5066,7 +5066,7 @@ "bTv" = (/obj/machinery/atmospherics/pipe/manifold{color = "red"; dir = 1; icon_state = "manifold-r"; level = 2},/obj/machinery/meter,/turf/simulated/wall,/area/atmos) "bTw" = (/obj/machinery/atmospherics/pipe/simple{color = "red"; dir = 4; icon_state = "intact-r"; level = 2},/obj/machinery/light,/turf/simulated/floor,/area/atmos) "bTx" = (/obj/machinery/atmospherics/pipe/simple/supply/hidden,/obj/machinery/atmospherics/pipe/simple{color = "red"; dir = 4; icon_state = "intact-r"; level = 2},/turf/simulated/wall/r_wall,/area/atmos) -"bTy" = (/obj/item/device/radio/intercom{dir = 1; name = "Station Intercom (General)"; pixel_x = -28; pixel_y = 0},/obj/machinery/requests_console{department = "Atmospherics"; departmentType = 4; name = "Atmos RC"; pixel_x = -30; pixel_y = 0},/obj/machinery/atmospherics/pipe/simple{color = "red"; dir = 4; icon_state = "intact-r"; level = 2},/turf/simulated/floor,/area/atmos) +"bTy" = (/obj/structure/rack{dir = 8; layer = 2.9},/obj/item/clothing/suit/storage/hazardvest,/obj/item/clothing/suit/storage/hazardvest,/obj/item/weapon/tank/emergency_oxygen/engi,/obj/item/weapon/tank/emergency_oxygen/engi,/obj/item/device/radio/intercom{dir = 4; name = "Station Intercom (General)"; pixel_x = 31},/turf/simulated/floor{dir = 4; icon_state = "yellowcorner"},/area/engine/engineering) "bTz" = (/obj/effect/landmark/start{name = "Atmospheric Technician"},/obj/structure/stool/bed/chair/office/dark,/obj/machinery/atmospherics/pipe/simple{color = "red"; dir = 4; icon_state = "intact-r"; level = 2},/turf/simulated/floor,/area/atmos) "bTA" = (/obj/machinery/atmospherics/pipe/simple{color = "red"; dir = 4; icon_state = "intact-r"; level = 2},/obj/machinery/meter,/turf/simulated/floor,/area/atmos) "bTB" = (/obj/machinery/door/firedoor/border_only,/obj/machinery/door/airlock/glass_atmos{name = "Monitoring Room"; req_access_txt = "24"},/obj/machinery/atmospherics/pipe/simple{color = "red"; dir = 4; icon_state = "intact-r"; level = 2},/turf/simulated/floor,/area/atmos) @@ -5074,7 +5074,7 @@ "bTD" = (/obj/machinery/atmospherics/pipe/manifold{tag = "icon-manifold-r (EAST)"; icon_state = "manifold-r"; dir = 4; level = 2; color = "red"},/turf/simulated/floor,/area/atmos) "bTE" = (/obj/structure/reagent_dispensers/watertank,/turf/simulated/floor,/area/atmos) "bTF" = (/obj/structure/reagent_dispensers/fueltank,/turf/simulated/floor,/area/atmos) -"bTG" = (/obj/structure/rack{dir = 8; layer = 2.9},/obj/machinery/light,/obj/item/clothing/suit/storage/hazardvest,/obj/item/clothing/suit/storage/hazardvest,/obj/item/clothing/suit/storage/hazardvest,/obj/item/clothing/suit/storage/hazardvest,/turf/simulated/floor,/area/atmos) +"bTG" = (/obj/item/device/radio/intercom{dir = 1; name = "Station Intercom (General)"; pixel_x = -28; pixel_y = 0},/obj/machinery/requests_console{department = "Atmospherics"; departmentType = 4; name = "Atmos RC"; pixel_x = -30; pixel_y = 0},/obj/machinery/atmospherics/pipe/simple{color = "red"; dir = 4; icon_state = "intact-r"; level = 2},/obj/machinery/computer/atmoscontrol,/turf/simulated/floor,/area/atmos) "bTH" = (/obj/machinery/atmospherics/pipe/manifold{dir = 8; icon_state = "manifold"; level = 2},/turf/simulated/floor,/area/atmos) "bTI" = (/obj/machinery/atmospherics/pipe/manifold{icon_state = "manifold"; level = 2},/obj/machinery/meter,/turf/simulated/floor,/area/atmos) "bTJ" = (/obj/machinery/atmospherics/pipe/manifold{dir = 4; icon_state = "manifold"; initialize_directions = 11; level = 2},/turf/simulated/floor,/area/atmos) @@ -5884,7 +5884,7 @@ "cjh" = (/obj/structure/grille,/obj/structure/window/reinforced{dir = 4},/obj/structure/window/reinforced{dir = 1},/obj/machinery/door/poddoor{density = 0; icon_state = "pdoor0"; id = "Singularity"; layer = 2.8; name = "Singularity Shutters"; opacity = 0},/turf/simulated/floor/plating,/area/engine/engineering) "cji" = (/obj/structure/rack{dir = 8; layer = 2.9},/obj/item/weapon/storage/belt/utility,/obj/item/weapon/wrench,/obj/item/weapon/weldingtool,/obj/item/clothing/head/welding{pixel_x = -3; pixel_y = 5},/turf/simulated/floor,/area/engine/engineering) "cjj" = (/obj/structure/rack{dir = 8; layer = 2.9},/obj/item/clothing/gloves/yellow,/obj/item/weapon/storage/belt/utility,/turf/simulated/floor,/area/engine/engineering) -"cjk" = (/obj/structure/rack{dir = 8; layer = 2.9},/obj/item/clothing/suit/storage/hazardvest,/obj/item/clothing/suit/storage/hazardvest,/obj/item/weapon/tank/emergency_oxygen/engi,/obj/item/weapon/tank/emergency_oxygen/engi,/obj/item/device/radio/intercom{dir = 4; name = "Station Intercom (General)"; pixel_x = 31},/turf/simulated/floor{dir = 4; icon_state = "yellowcorner"},/area/engine/engineering) +"cjk" = (/obj/structure/rack{dir = 8; layer = 2.9},/obj/machinery/light,/obj/item/clothing/suit/storage/hazardvest,/obj/item/clothing/suit/storage/hazardvest,/obj/item/clothing/suit/storage/hazardvest,/obj/item/clothing/suit/storage/hazardvest,/turf/simulated/floor,/area/atmos) "cjl" = (/obj/structure/cable{d1 = 2; d2 = 4; icon_state = "2-4"; tag = ""},/obj/structure/cable{d1 = 1; d2 = 4; icon_state = "1-4"; tag = ""},/turf/simulated/floor/plating/airless,/area/solar/starboard) "cjm" = (/obj/structure/cable{d1 = 2; d2 = 4; icon_state = "2-4"; tag = ""},/obj/structure/cable{d1 = 1; d2 = 4; icon_state = "1-4"; tag = ""},/obj/structure/cable{d1 = 4; d2 = 8; icon_state = "4-8"; pixel_x = 0; tag = ""},/turf/simulated/floor/plating/airless,/area/solar/starboard) "cjn" = (/obj/structure/cable{d2 = 8; icon_state = "0-8"},/turf/simulated/floor/plating/airless,/area/solar/starboard) @@ -8989,7 +8989,7 @@ "dqS" = (/obj/structure/grille,/obj/structure/window/reinforced,/obj/structure/window/reinforced{dir = 8},/obj/structure/disposalpipe/segment{dir = 2; icon_state = "pipe-c"},/turf/simulated/floor/plating,/area/maintenance/disposal) "dqT" = (/obj/machinery/conveyor{dir = 1; id = "garbage"},/obj/effect/sign/vacuum{pixel_x = -32},/obj/machinery/light/small{dir = 8},/turf/simulated/floor/plating{dir = 2; icon_state = "warnplate"; tag = "icon-warnplate (NORTH)"},/area/maintenance/disposal) "dqU" = (/turf/space,/obj/structure/shuttle/engine/propulsion{tag = "icon-propulsion_l (WEST)"; icon_state = "propulsion_l"; dir = 8},/turf/simulated/shuttle/wall{dir = 3; icon_state = "swall_f10"; layer = 2; tag = "icon-swall_f10"},/area/shuttle/transport1/centcom) - + (1,1,1) = {" aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa @@ -9152,7 +9152,7 @@ aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaafaaaaaaaaaaaaaaaaafaafaafaaaaaaaaabPCbLjbPDbJLbJLbJLbOAbOAbOAbOAbOAbPEbOAbOAbOAbPFbPGbvZbMAbvZbPHbPIbNGbKsbPJbPKbHsbHsbHsbHsbPLbPMbPNbLGbPObPPbPQbPRbPSbPTbPUbPTbPVaafbLPbLPbLPbLPbLPaafaafaafbjIbPWbpGbIQbPXbPYbdpbPZbmxbQabQbbQcbQdbQebQfbQgbQhbQibQjbQibQkbLYbQlbQmbQnbQobQlbLYbQpbQqbNkbQrbQsbQtbQubQtbQvbQtbQwbQxbQxbQybQzbQAbccbccaafaafaafaafaafaafaafaafaafaafaafaafaafaafaafaafaafaafaafaafaafaafaafbAsbAtbJxbJvbJvbBNbBNbBNbBNbBNbBNbBNbBNbAtbAtaafaafaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaafaafaaaaafaaaaaaaaabQCbLjbPDbJLaafaaabOAbQDbQEbQFbQGbQHbQIbQJbOAbOAbQKbQLbJYbvZbPHbQMbQNbMDbQObQPbQQbQRbQSbHsbQTbPMbLGbQUbLNbQVbQWbQXbQYbQZbRabRbbRcbMSbMTbRdbRebRebLPaafaaaaaablkbKvbdnbRfbEXbdnbdnbdnbRgbRhbRibRjbRkbRlbRmbRnbRobRpbRqbRrbRsbLYbLYbLYbLYbLYbLYbLYbRtbRubNkbRvbRwbRxbRybRzbRAbRBbRCbRDbREbRFbKObRGbQBbccbccbccaaaaaaaafaaaaaaaafagQagQagQaaaaaaaaaaafaaaaaaaafaaaaaaaafaaaaaabEfbAtbCSbAtbAtbBNbBNbBNbBNbBNbBNbBNbAtbAtaafaafaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaafaafaaaaaabJLbJLbJLbJLbJLbLjbRSbRTbRUbRVbRWbRXbRYbRZbSabSbbQJbQJbScbSdbSebvZbMAbvZbSfbSgbLNbLNbShbSibSjbLNbSkbSlbSmbSnbLNbSobSpbSqbSrbSsbLGbStbSubSvbNRaafbNSbSwbSxbSybLPaafaaaaaablkbKvbdnbSzbSAbSBbSCbSDbdpbRhbSEbNbbSFbSGbQfbSHbSIbSJbSKbSLbRsbSMbSNbSObSPbSQbSRbSSbSTbSUbNkbSVbSWbSXbSYbSZbTabTbbTcbSYbTdbSVbKObTebRHbRIbRJbRKbRLbRMbRMbRMbRMbRMbRMbRMbRMbRMbRMbRMbRMbRMbRMbRMbRMbRMbRMbRMbRNbRObRPbRPbRQbAtbAtbBNbBNbRRbBNbBNbAtbAtaafaafaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa -aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaafaafaafaafaaabPCbTkbTlbTmbTnbTobTpbTnbTqbTrbTsbTtbQJbQJbQJbQJbQJbQJbScbSdbSebvZbMAbvZbTubTvbOKbTwbOKbTxbTybTzbTAbTBbTCbTDbTEbTFbTGbTHbTIbTJbLGbStbTKbTLbTMbOTbMTbTNbRebRebLPaafaafaafblkbKvbdnbTObTPbTQbTRbTSbdpbRhbTTbNbbNbbNbbNcbNbbNbbTUbNbbNbbRsbTVbTWbTVbTXbTYbTZbUabUabUbbNkbNkbKObUcbUdbUdbUdbUebUdbUfbKObKObKObUgbTfbccbTgbccaaaaaabThaaaaaaaafagQagQagQaaaaaaaaaaafaaaaaaaafaaaaaaaafaafaafbTibTjbBLbCTbAsbAtbAtbBNbBObBNbAtbAtaafaafaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaafaafaafaafaaabPCbTkbTlbTmbTnbTobTpbTnbTqbTrbTsbTtbQJbQJbQJbQJbQJbQJbScbSdbSebvZbMAbvZbTubTvbOKbTwbOKbTxbTGbTzbTAbTBbTCbTDbTEbTFcjkbTHbTIbTJbLGbStbTKbTLbTMbOTbMTbTNbRebRebLPaafaafaafblkbKvbdnbTObTPbTQbTRbTSbdpbRhbTTbNbbNbbNbbNcbNbbNbbTUbNbbNbbRsbTVbTWbTVbTXbTYbTZbUabUabUbbNkbNkbKObUcbUdbUdbUdbUebUdbUfbKObKObKObUgbTfbccbTgbccaaaaaabThaaaaaaaafagQagQagQaaaaaaaaaaafaaaaaaaafaaaaaaaafaafaafbTibTjbBLbCTbAsbAtbAtbBNbBObBNbAtbAtaafaafaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaafaafaaaaaaaafaaabQCbUlbUmbUnbIpbIpbJLbLgbUobLibOAbUpbQJbQFbQFbQFbQJbUqbOAbOAbQKbUrbMAbvZbTubUsbUtbHsbUubQPbUvbUwbUxbHsbUybUzbHsbHsbHsbUAbLGbUBbLGbStbSubUCbNRaafbLPbLPbLPbLPbLPaafaaaaaabNVbKvbdnbdnbdnbdnbdnbdnbUDbUEbdpbsDbUFbUGbUHbUIbUJbUKbULbUMbRsbUNbTVbUObTXbUPbUQbURbURbUSbUTbUUbKObUVbUWbUdbUXbUYbUWbUdbKObUZbVabVbbUhbUibUjaafaafaafaafaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaafaafbUkbAqbAqbArbAsbAsbAtbAtbAtbAtbAtaafaafaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaeaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaafaafaaaaaaaaabJLbJLbJLbJLbIpbUnbIpbIpbJLaaabVdaaabOAbVebQJbRZbSabSbbQJbQJbQJbQJbVfbvZbMAbVgbzvbHsbHsbHsbVhbVibVjbVkbVlbKcbNJbPMbVmbVnbVobTHbVpbTHbVqbVrbVsbVtbRcbMSbMTbVubVvbVwbLPaafaaaaaabccbVxbVybVybVybVybVzbdnbVAbRhbdpbdpbVBbQibVCbQibQibVDbQibVEbRsbVFbVGbVHbVIbVJbVGbVKbVLbVMbVNbVNbKObUdbVObUdbUdbUdbVObUdbKObTebccbVPbVQbccaafaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaafaafaafaafaafaaaaaaaaaaaaaafaafaafaafaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaafaafaaaaaaaaaaaabJLbVRbVSbVTbVUbVVbVWbVXbVWaaabVdaaabOAbVYbQJbQJbQJbVZbQJbWabWbbQJbWcbWdbLxbWdbWebWfbWgbWfbWhbWibWjbMFbLGbKcbNJbPMbWkbLGbWlbWmbVpbTHbVqbStbSubWnbNRaafbNSbWobWpbWqbLPaafaafaafbccbccbWrbWsbVQbccbWtbpGbPYbWubWvbWwbUFbWxbWxbWybWxbQibWzbWAbRsbWBbVGbVGbWCbVGbVGbWDbWEbWFbWGbWHbKObKObKObKObKObKObKObKObKObTebccaafaafaafaaaaaaaaaaaaaaaaaaaaeaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaDxaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa @@ -9172,7 +9172,7 @@ aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaajlaafbYVcglbYXaaabYVcglbYXaaabYVcglbYXaafaaaaaaaaaaaaaafaafaaaaaaaaaaaaaaaaaaaaaaaaaaaaafaaabJLbIpchFbLjcdCcgZcgZchacdCchGchGchHchIchJchKchLchMchNchOchPchQchRchScdMchTchUchVcdQcdQcdQbLPchtchWchtbLPchvchXchvbLPchzchYchzbLPaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaachZaaaaaabZxciacibciccidciecifcigciecigcifbZxaaaaaaaaaaaaaZvaZvaZvcihaafaafaafaafchEaafaafaafaafaafajXaZvaZvaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaajlaafbYVcglbYXaaabYVcglbYXaafbYVcglbYXaafaafaafaaaaafaafaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaafaaacdCciicdCcijcdCcgZchachacdCcikcilcimcincheciocipciqcircfQciociscitcfQciocirciucivciwcixcdCbLPbLPbLPbLPbLPbLPbLPbLPbLPbLPbLPbLPbLPaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabZxbZxciycizbZxbZxbZxbZxbZxbZxbZxbZxaaaaaaaaaaaaaZvaaaaafaaaaafaaaaaaaaaciAaaaaafaafaaaaaaaaaaaaaZvaaaaaaaaeaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaajXaafbYVciBbYXaaabYVciBbYXaaabYVciBbYXaafajlaafaafaafaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaafaaacdCciCcdCciDcdCcdCcdCcdCciEciFciGciHciHciHciGciIciGciJciKciLciMciNciOciGciGciPciGciQciRcdCaaaaaaaaaaaaaafaafaaaaaaaafaaaaaaaaaaafaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaafbZxbZxbZxbZxaaaaafaafaafaafaafaaaaaaaaaaaaaaaaZvaaaciSciSciSciSciSaafciTaafciSciSciSciSciSaaaaZvaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa -aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaajlaaaaafaaaaaaaaaaafaafaafaaaaaaaafaafaaaajlaafaafaaaaaaaaaaaaaaaaaaaaaaaaaafaafaafaafaafaafcdCchfchfcfQciUciVciWciXciGciYchfciZcjachfcjbcjccjdcjecjfcjecjgcjhcjbcjicjjchfchfciucjkcdCcdCchGchGchGcdCaaaaafaafaafaafaafaafaafaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaafaaaaaaaaaaaaaaaaaaaaaaafaaaaafaaaaaaaaaaaaaaaaZvaafcjlcjmcjmcjmcjmcjnciTcjocjpcjpcjpcjpcjqaafaZvaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaajlaaaaafaaaaaaaaaaafaafaafaaaaaaaafaafaaaajlaafaafaaaaaaaaaaaaaaaaaaaaaaaaaafaafaafaafaafaafcdCchfchfcfQciUciVciWciXciGciYchfciZcjachfcjbcjccjdcjecjfcjecjgcjhcjbcjicjjchfchfciubTycdCcdCchGchGchGcdCaaaaafaafaafaafaafaafaafaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaafaaaaaaaaaaaaaaaaaaaaaaafaaaaafaaaaaaaaaaaaaaaaZvaafcjlcjmcjmcjmcjmcjnciTcjocjpcjpcjpcjpcjqaafaZvaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaajmajmajlajmajmajXajlajlajlajlajmajlajlajmcjraafaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaafaaaaaacdCcjschfcjtcjucjvcjwcjxcjyciuchfcjzchfchfcjAcjBcjCcjDcjEcjDcjFcjBcjGcjHcjIchfchfciuchfcjJchGcjKcjLcjMcjMcjNaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaafaaaaafaaaaaaaaaaaaaaaaZvaafcjOcjOcjOcjOcjOaaaciTaaacjOcjOcjOcjOcjOaafaZvaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaafaafaafcdCcdCcjPcjQchechfcjRcjScjTciucjachfcjUcjVcjVcjWcjXcjYcjZcfHckacjWciJciJckbchfchfckcchfckdckecfFckfckgckhckiaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaZvaaaaafaaaaafaafaafaaaciTaaaaafaaaaafaaaaafaaaaZvaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaeaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaafaaaaaackjckkcklchfckmcknckockpckqckrckscktckucdCckvckwckxcjackycdCckzckAckAckrckBckCckockDchGckEckFcjMcjMckGaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaeaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaZvaaaciSciSciSciSciSaafciTaafciSciSciSciSciSaafaZvaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa