diff --git a/code/__DEFINES/machines.dm b/code/__DEFINES/machines.dm index 5b38b592ac6..35701e7f5b3 100644 --- a/code/__DEFINES/machines.dm +++ b/code/__DEFINES/machines.dm @@ -81,4 +81,14 @@ #define TARGET_DEPT_SEC 2 #define TARGET_DEPT_MED 3 #define TARGET_DEPT_SCI 4 -#define TARGET_DEPT_ENG 5 \ No newline at end of file +#define TARGET_DEPT_ENG 5 + +// These are used by supermatter and supermatter monitor program, mostly for UI updating purposes. Higher should always be worse! +#define SUPERMATTER_ERROR -1 // Unknown status, shouldn't happen but just in case. +#define SUPERMATTER_INACTIVE 0 // No or minimal energy +#define SUPERMATTER_NORMAL 1 // Normal operation +#define SUPERMATTER_NOTIFY 2 // Ambient temp > 80% of CRITICAL_TEMPERATURE +#define SUPERMATTER_WARNING 3 // Ambient temp > CRITICAL_TEMPERATURE OR integrity damaged +#define SUPERMATTER_DANGER 4 // Integrity < 50% +#define SUPERMATTER_EMERGENCY 5 // Integrity < 25% +#define SUPERMATTER_DELAMINATING 6 // Pretty obvious. diff --git a/code/modules/modular_computers/computers/machinery/console_presets.dm b/code/modules/modular_computers/computers/machinery/console_presets.dm index 6e0be3b385f..5dd324945fa 100644 --- a/code/modules/modular_computers/computers/machinery/console_presets.dm +++ b/code/modules/modular_computers/computers/machinery/console_presets.dm @@ -36,6 +36,7 @@ var/obj/item/computer_hardware/hard_drive/hard_drive = cpu.all_components[MC_HDD] hard_drive.store_file(new/datum/computer_file/program/power_monitor()) hard_drive.store_file(new/datum/computer_file/program/alarm_monitor()) + hard_drive.store_file(new/datum/computer_file/program/supermatter_monitor()) // ===== RESEARCH CONSOLE ===== /obj/machinery/modular_computer/console/preset/research diff --git a/code/modules/modular_computers/file_system/programs/engineering/sm_monitor.dm b/code/modules/modular_computers/file_system/programs/engineering/sm_monitor.dm new file mode 100644 index 00000000000..b05783e2bcb --- /dev/null +++ b/code/modules/modular_computers/file_system/programs/engineering/sm_monitor.dm @@ -0,0 +1,137 @@ +/datum/computer_file/program/supermatter_monitor + filename = "smmonitor" + filedesc = "Supermatter Monitoring" + ui_header = "smmon_0.gif" + program_icon_state = "smmon_0" + extended_desc = "This program connects to specially calibrated supermatter sensors to provide information on the status of supermatter-based engines." + requires_ntnet = TRUE + transfer_access = access_engine + network_destination = "supermatter monitoring system" + size = 5 + requires_ntnet = 1 + var/last_status = SUPERMATTER_INACTIVE + var/list/supermatters + var/obj/machinery/power/supermatter_shard/active // Currently selected supermatter crystal. + + +/datum/computer_file/program/supermatter_monitor/process_tick() + ..() + var/new_status = get_status() + if(last_status != new_status) + last_status = new_status + ui_header = "smmon_[last_status].gif" + program_icon_state = "smmon_[last_status]" + update_computer_icon() + +/datum/computer_file/program/supermatter_monitor/run_program(mob/living/user) + . = ..(user) + refresh() + +/datum/computer_file/program/supermatter_monitor/kill_program(forced = FALSE) + active = null + supermatters = null + ..() + +// Refreshes list of active supermatter crystals +/datum/computer_file/program/supermatter_monitor/proc/refresh() + supermatters = list() + var/turf/T = get_turf(nano_host()) + if(!T) + return + for(var/obj/machinery/power/supermatter_shard/S in atmos_machinery) + // Delaminating, not within coverage, not on a tile. + if(!(S.z == 1 || S.z == 5 || S.z == T.z) || !istype(S.loc, /turf/simulated/)) + continue + supermatters.Add(S) + + if(!(active in supermatters)) + active = null + +/datum/computer_file/program/supermatter_monitor/proc/get_status() + . = SUPERMATTER_INACTIVE + for(var/obj/machinery/power/supermatter_shard/S in supermatters) + . = max(., S.get_status()) + +/datum/computer_file/program/supermatter_monitor/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1) + ui = nanomanager.try_update_ui(user, src, ui_key, ui, force_open) + if(!ui) + var/datum/asset/assets = get_asset_datum(/datum/asset/simple/headers) + assets.send(user) + ui = new(user, src, ui_key, "supermatter_monitor.tmpl", "Supermatter Monitoring", 600, 400) + ui.set_auto_update(TRUE) + ui.set_layout_key("program") + ui.open() + +/datum/computer_file/program/supermatter_monitor/ui_data() + var/list/data = get_header_data() + + if(istype(active)) + var/turf/T = get_turf(active) + if(!T) + active = null + refresh() + return + var/datum/gas_mixture/air = T.return_air() + if(!air) + active = null + return + + data["active"] = TRUE + data["SM_integrity"] = active.get_integrity() + data["SM_power"] = active.power + data["SM_ambienttemp"] = air.temperature + data["SM_ambientpressure"] = air.return_pressure() + //data["SM_EPR"] = round((air.total_moles / air.group_multiplier) / 23.1, 0.01) + var/other_moles = 0.0 + for(var/datum/gas/G in air.trace_gases) + other_moles+=G.moles + var/TM = air.total_moles() + if(TM) + data["SM_gas_O2"] = round(100*air.oxygen/TM,0.01) + data["SM_gas_CO2"] = round(100*air.carbon_dioxide/TM,0.01) + data["SM_gas_N2"] = round(100*air.nitrogen/TM,0.01) + data["SM_gas_PL"] = round(100*air.toxins/TM,0.01) + if(other_moles) + data["SM_gas_OTHER"] = round(100*other_moles/TM,0.01) + else + data["SM_gas_OTHER"] = 0 + else + data["SM_gas_O2"] = 0 + data["SM_gas_CO2"] = 0 + data["SM_gas_N2"] = 0 + data["SM_gas_PH"] = 0 + data["SM_gas_OTHER"] = 0 + else + var/list/SMS = list() + for(var/obj/machinery/power/supermatter_shard/S in supermatters) + var/area/A = get_area(S) + if(!A) + continue + + SMS.Add(list(list( + "area_name" = A.name, + "integrity" = S.get_integrity(), + "uid" = S.uid + ))) + + data["active"] = FALSE + data["supermatters"] = SMS + + return data + + +/datum/computer_file/program/supermatter_monitor/Topic(href, href_list) + if(..()) + return 1 + if( href_list["clear"] ) + active = null + return 1 + if( href_list["refresh"] ) + refresh() + return 1 + if( href_list["set"] ) + var/newuid = text2num(href_list["set"]) + for(var/obj/machinery/power/supermatter_shard/S in supermatters) + if(S.uid == newuid) + active = S + return 1 \ No newline at end of file diff --git a/code/modules/power/supermatter/supermatter.dm b/code/modules/power/supermatter/supermatter.dm index 43d418aadf7..c6cce90a278 100644 --- a/code/modules/power/supermatter/supermatter.dm +++ b/code/modules/power/supermatter/supermatter.dm @@ -16,6 +16,12 @@ #define WARNING_DELAY 30 //seconds between warnings. +//If integrity percent remaining is less than these values, the monitor sets off the relevant alarm. +#define SUPERMATTER_DELAM_PERCENT 5 +#define SUPERMATTER_EMERGENCY_PERCENT 25 +#define SUPERMATTER_DANGER_PERCENT 50 +#define SUPERMATTER_WARNING_PERCENT 100 + /obj/machinery/power/supermatter_shard name = "supermatter shard" desc = "A strangely translucent and iridescent crystal that looks like it used to be part of a larger structure. You get headaches just from looking at it." @@ -62,9 +68,23 @@ var/has_been_powered = 0 var/has_reached_emergency = 0 +/obj/machinery/power/supermatter_shard/crystal + name = "supermatter crystal" + desc = "A strangely translucent and iridescent crystal." + base_icon_state = "darkmatter" + icon_state = "darkmatter" + anchored = TRUE + warning_point = 200 + emergency_point = 2000 + explosion_point = 3600 + gasefficency = 0.15 + explosion_power = 35 + + /obj/machinery/power/supermatter_shard/New() . = ..() poi_list |= src + atmos_machinery += src radio = new(src) radio.listening = 0 investigate_log("has been created.", "supermatter") @@ -74,15 +94,16 @@ investigate_log("has been destroyed.", "supermatter") QDEL_NULL(radio) poi_list.Remove(src) + atmos_machinery -= src return ..() /obj/machinery/power/supermatter_shard/proc/explode() investigate_log("has exploded.", "supermatter") - explosion(get_turf(src), explosion_power, explosion_power * 2, explosion_power * 3, explosion_power * 4, 1) + explosion(get_turf(src), explosion_power, explosion_power * 1.2, explosion_power * 1.5, explosion_power * 2, 1, 1) qdel(src) return -/obj/machinery/power/supermatter_shard/process() +/obj/machinery/power/supermatter_shard/process_atmos() var/turf/L = loc if(isnull(L)) // We have a null turf...something is wrong, stop processing this entity. @@ -96,6 +117,7 @@ if(damage > warning_point) // while the core is still damaged and it's still worth noting its status if((world.timeofday - lastwarning) / 10 >= WARNING_DELAY) + alarm() var/stability = num2text(round((damage / explosion_point) * 100)) if(damage > emergency_point) @@ -136,12 +158,12 @@ var/datum/gas_mixture/removed = env.remove(gasefficency * env.total_moles()) if(!removed || !removed.total_moles()) - damage += max((power-1600)/10, 0) + damage += max((power-1600)/2, 0) power = min(power, 1600) return 1 damage_archived = damage - damage = max( damage + ( (removed.temperature - 800) / 150 ) , 0 ) + damage = max( damage + ( (removed.temperature - 800) / 50 ) , 0 ) //Ok, 100% oxygen atmosphere = best reaction //Maxes out at 100% oxygen pressure oxygen = max(min((removed.oxygen - (removed.nitrogen * NITROGEN_RETARDATION_FACTOR)) / MOLES_CELLSTANDARD, 1), 0) @@ -181,6 +203,8 @@ env.merge(removed) + air_update_turf() + for(var/mob/living/carbon/human/l in view(src, min(7, round(sqrt(power/6))))) // If they can see it without mesons on. Bad on them. if(l.glasses && istype(l.glasses, /obj/item/clothing/glasses/meson)) @@ -306,7 +330,6 @@ user.apply_effect(150, IRRADIATE) - /obj/machinery/power/supermatter_shard/Bumped(atom/AM as mob|obj) if(istype(AM, /mob/living)) AM.visible_message("\The [AM] slams into \the [src] inducing a resonance... [AM.p_their(TRUE)] body starts to glow and catch flame before flashing into ash.",\ @@ -346,3 +369,44 @@ "The unearthly ringing subsides and you notice you have new radiation burns.", 2) else L.show_message("You hear an uneartly ringing and notice your skin is covered in fresh radiation burns.", 2) + +#define CRITICAL_TEMPERATURE 10000 + +/obj/machinery/power/supermatter_shard/proc/get_status() + var/turf/T = get_turf(src) + if(!T) + return SUPERMATTER_ERROR + var/datum/gas_mixture/air = T.return_air() + if(!air) + return SUPERMATTER_ERROR + + if(get_integrity() < SUPERMATTER_DELAM_PERCENT) + return SUPERMATTER_DELAMINATING + + if(get_integrity() < SUPERMATTER_EMERGENCY_PERCENT) + return SUPERMATTER_EMERGENCY + + if(get_integrity() < SUPERMATTER_DANGER_PERCENT) + return SUPERMATTER_DANGER + + if((get_integrity() < SUPERMATTER_WARNING_PERCENT) || (air.temperature > CRITICAL_TEMPERATURE)) + return SUPERMATTER_WARNING + + if(air.temperature > (CRITICAL_TEMPERATURE * 0.8)) + return SUPERMATTER_NOTIFY + + if(power > 5) + return SUPERMATTER_NORMAL + return SUPERMATTER_INACTIVE + +/obj/machinery/power/supermatter_shard/proc/alarm() + switch(get_status()) + if(SUPERMATTER_DELAMINATING) + playsound(src, 'sound/misc/bloblarm.ogg', 100) + if(SUPERMATTER_EMERGENCY) + playsound(src, 'sound/machines/engine_alert1.ogg', 100) + if(SUPERMATTER_DANGER) + playsound(src, 'sound/machines/engine_alert2.ogg', 100) + if(SUPERMATTER_WARNING) + playsound(src, 'sound/machines/terminal_alert.ogg', 75) + diff --git a/icons/obj/modular_console.dmi b/icons/obj/modular_console.dmi index 85d6026617f..fba8ad59431 100644 Binary files a/icons/obj/modular_console.dmi and b/icons/obj/modular_console.dmi differ diff --git a/icons/obj/modular_laptop.dmi b/icons/obj/modular_laptop.dmi index 2daeee0c7a4..d04e68c2041 100644 Binary files a/icons/obj/modular_laptop.dmi and b/icons/obj/modular_laptop.dmi differ diff --git a/icons/obj/modular_tablet.dmi b/icons/obj/modular_tablet.dmi index 2438f375f65..d1357a58406 100644 Binary files a/icons/obj/modular_tablet.dmi and b/icons/obj/modular_tablet.dmi differ diff --git a/icons/program_icons/smmon_0.gif b/icons/program_icons/smmon_0.gif new file mode 100644 index 00000000000..7b716c4e1c5 Binary files /dev/null and b/icons/program_icons/smmon_0.gif differ diff --git a/icons/program_icons/smmon_1.gif b/icons/program_icons/smmon_1.gif new file mode 100644 index 00000000000..bbe319b820f Binary files /dev/null and b/icons/program_icons/smmon_1.gif differ diff --git a/icons/program_icons/smmon_2.gif b/icons/program_icons/smmon_2.gif new file mode 100644 index 00000000000..9c58edd340e Binary files /dev/null and b/icons/program_icons/smmon_2.gif differ diff --git a/icons/program_icons/smmon_3.gif b/icons/program_icons/smmon_3.gif new file mode 100644 index 00000000000..dc7c8734eed Binary files /dev/null and b/icons/program_icons/smmon_3.gif differ diff --git a/icons/program_icons/smmon_4.gif b/icons/program_icons/smmon_4.gif new file mode 100644 index 00000000000..8a75e6e1184 Binary files /dev/null and b/icons/program_icons/smmon_4.gif differ diff --git a/icons/program_icons/smmon_5.gif b/icons/program_icons/smmon_5.gif new file mode 100644 index 00000000000..59356beda0a Binary files /dev/null and b/icons/program_icons/smmon_5.gif differ diff --git a/icons/program_icons/smmon_6.gif b/icons/program_icons/smmon_6.gif new file mode 100644 index 00000000000..aea2f87921d Binary files /dev/null and b/icons/program_icons/smmon_6.gif differ diff --git a/nano/templates/supermatter_monitor.tmpl b/nano/templates/supermatter_monitor.tmpl new file mode 100644 index 00000000000..3bc87984d79 --- /dev/null +++ b/nano/templates/supermatter_monitor.tmpl @@ -0,0 +1,111 @@ +{{if data.active}} + {{:helper.link('Back to Menu', null, {'clear' : 1})}}
+
+
+ Core Integrity: +
+
+ {{:helper.displayBar(data.SM_integrity, 0, 100, (data.SM_integrity == 100) ? 'good' : (data.SM_integrity >= 50) ? 'average' : 'bad')}} {{:data.SM_integrity}}% +
+
+ Relative EER: +
+
+ {{if data.SM_power > 300}} + {{:data.SM_power}} MeV/cm3 + {{else data.SM_power > 150}} + {{:data.SM_power}} MeV/cm3 + {{else}} + {{:data.SM_power}} MeV/cm3 + {{/if}} +
+
+ Temperature: +
+
+ {{if data.SM_ambienttemp > 5000}} + {{:data.SM_ambienttemp}} K + {{else data.SM_ambienttemp > 4000}} + {{:data.SM_ambienttemp}} K + {{else}} + {{:data.SM_ambienttemp}} K + {{/if}} +
+
+ Pressure: +
+
+ {{if data.SM_ambientpressure > 10000}} + {{:data.SM_ambientpressure}} kPa + {{else data.SM_ambientpressure > 5000}} + {{:data.SM_ambientpressure}} kPa + {{else}} + {{:data.SM_ambientpressure}} kPa + {{/if}} +
+
+

+
+ Gas Composition: +
+
+
+
+ O2: +
+
+ {{:data.SM_gas_O2}} % +
+
+ CO2: +
+
+ {{:data.SM_gas_CO2}} % +
+
+ N2: +
+
+ {{:data.SM_gas_N2}} % +
+
+ PL: +
+
+ {{:data.SM_gas_PL}} % +
+
+ OTHER: +
+
+ {{:data.SM_gas_OTHER}} % +
+
+
+ +{{else}} + {{:helper.link('Refresh', null, {'refresh' : 1})}}
+ {{for data.supermatters}} +
+
+ Area: +
+
+ {{:value.area_name}} +
+
+ Integrity: +
+
+ {{:value.integrity}} % +
+
+ Options: +
+
+ {{:helper.link('View Details', null, {'set' : value.uid})}} +
+
+ {{/for}} +{{/if}} diff --git a/sound/machines/engine_alert2.ogg b/sound/machines/engine_alert2.ogg new file mode 100644 index 00000000000..83f693617a7 Binary files /dev/null and b/sound/machines/engine_alert2.ogg differ