diff --git a/code/game/machinery/cryo.dm b/code/game/machinery/cryo.dm index 163c5f6bae1..98d93cafd8b 100644 --- a/code/game/machinery/cryo.dm +++ b/code/game/machinery/cryo.dm @@ -13,8 +13,6 @@ var/current_heat_capacity = 50 - - /obj/machinery/atmospherics/unary/cryo_cell/New() ..() initialize_directions = dir @@ -65,17 +63,22 @@ ui_interact(user) /obj/machinery/atmospherics/unary/cryo_cell/ui_interact(mob/user, ui_key = "main") - + + if(user == occupant || user.stat) + return + var/data[0] data["isOperating"] = on data["hasOccupant"] = occupant ? 1 : 0 - + var/occupantData[0] if (!occupant) occupantData["name"] = null occupantData["stat"] = null occupantData["health"] = null + occupantData["maxHealth"] = null + occupantData["minHealth"] = null occupantData["bruteLoss"] = null occupantData["oxyLoss"] = null occupantData["toxLoss"] = null @@ -84,12 +87,14 @@ else occupantData["name"] = occupant.name occupantData["stat"] = occupant.stat - occupantData["health"] = round(occupant.health) - occupantData["bruteLoss"] = round(occupant.getBruteLoss()) - occupantData["oxyLoss"] = round(occupant.getOxyLoss()) - occupantData["toxLoss"] = round(occupant.getToxLoss()) - occupantData["fireLoss"] = round(occupant.getFireLoss()) - occupantData["bodyTemperature"] = round(occupant.bodytemperature) + occupantData["health"] = occupant.health + occupantData["maxHealth"] = occupant.maxHealth + occupantData["minHealth"] = config.health_threshold_dead + occupantData["bruteLoss"] = occupant.getBruteLoss() + occupantData["oxyLoss"] = occupant.getOxyLoss() + occupantData["toxLoss"] = occupant.getToxLoss() + occupantData["fireLoss"] = occupant.getFireLoss() + occupantData["bodyTemperature"] = occupant.bodytemperature data["occupant"] = occupantData; data["cellTemperature"] = round(air_contents.temperature) @@ -103,9 +108,9 @@ var beakerContents[0] if(beaker && beaker:reagents && beaker:reagents.reagent_list.len) for(var/datum/reagent/R in beaker:reagents.reagent_list) - beakerContents.Add(list(list("name" = R.name, "volume" = R.volume))) // list in a list because Byond merges the first list... + beakerContents.Add(list(list("name" = R.name, "volume" = R.volume))) // list in a list because Byond merges the first list... data["beakerContents"] = beakerContents - + //user << list2json(data) var/datum/nanoui/ui = nanomanager.get_open_ui(user, src, ui_key) @@ -123,19 +128,33 @@ //user.set_machine(src) /obj/machinery/atmospherics/unary/cryo_cell/Topic(href, href_list) - if ((get_dist(src, usr) <= 1) || istype(usr, /mob/living/silicon/ai)) - if(href_list["start"]) - on = !on - update_icon() - if(href_list["eject"]) - if (beaker) - var/obj/item/weapon/reagent_containers/glass/B = beaker - B.loc = get_step(loc, SOUTH) - beaker = null + if(usr == occupant) + return 0 // don't update UIs attached to this object - nanomanager.update_uis(src) // update all UIs attached to this object - add_fingerprint(usr) - return + if(..()) + return 0 // don't update UIs attached to this object + + if(href_list["switchOn"]) + on = 1 + update_icon() + + if(href_list["switchOff"]) + on = 0 + update_icon() + + if(href_list["ejectBeaker"]) + if(beaker) + var/obj/item/weapon/reagent_containers/glass/B = beaker + B.loc = get_step(loc, SOUTH) + beaker = null + + if(href_list["ejectOccupant"]) + if(!occupant || isslime(usr) || ispAI(usr)) + return 0 // don't update UIs attached to this object + go_out() + + add_fingerprint(usr) + return 1 // update UIs attached to this object /obj/machinery/atmospherics/unary/cryo_cell/attackby(var/obj/item/weapon/G as obj, var/mob/user as mob) if(istype(G, /obj/item/weapon/reagent_containers/glass)) diff --git a/code/game/machinery/kitchen/gibber.dm b/code/game/machinery/kitchen/gibber.dm index 0a8bde59dde..bea6169ddc4 100644 --- a/code/game/machinery/kitchen/gibber.dm +++ b/code/game/machinery/kitchen/gibber.dm @@ -82,9 +82,19 @@ if(src.occupant) user << "\red The gibber is full, empty it first!" return - if (!( istype(G, /obj/item/weapon/grab)) || !(istype(G.affecting, /mob/living/carbon/human))) + + if( !(istype(G, /obj/item/weapon/grab)) ) user << "\red This item is not suitable for the gibber!" return + + if( !(istype(G.affecting, /mob/living/carbon)) && !(istype(G.affecting, /mob/living/simple_animal)) ) + user << "\red This item is not suitable for the gibber!" + return + + if(G.state < 2) + user << "\red You need a better grip to do that!" + return + if(G.affecting.abiotic(1)) user << "\red Subject may not have abiotic items on." return @@ -137,29 +147,69 @@ visible_message("\red You hear a loud squelchy grinding sound.") src.operating = 1 update_icon() - var/sourcename = src.occupant.real_name - var/sourcejob = src.occupant.job - var/sourcenutriment = src.occupant.nutrition / 15 - var/sourcetotalreagents = src.occupant.reagents.total_volume + var/totalslabs = 3 + var/obj/item/weapon/reagent_containers/food/snacks/meat/allmeat[totalslabs] - var/obj/item/weapon/reagent_containers/food/snacks/meat/human/allmeat[totalslabs] - for (var/i=1 to totalslabs) - var/obj/item/weapon/reagent_containers/food/snacks/meat/human/newmeat = new - newmeat.name = sourcename + newmeat.name - newmeat.subjectname = sourcename - newmeat.subjectjob = sourcejob - newmeat.reagents.add_reagent ("nutriment", sourcenutriment / totalslabs) // Thehehe. Fat guys go first - src.occupant.reagents.trans_to (newmeat, round (sourcetotalreagents / totalslabs, 1)) // Transfer all the reagents from the - allmeat[i] = newmeat + if( istype(src.occupant, /mob/living/carbon/human/) ) + var/sourcename = src.occupant.real_name + var/sourcejob = src.occupant.job + var/sourcenutriment = src.occupant.nutrition / 15 + var/sourcetotalreagents = src.occupant.reagents.total_volume - src.occupant.attack_log += "\[[time_stamp()]\] Was gibbed by [user]/[user.ckey]" //One shall not simply gib a mob unnoticed! - user.attack_log += "\[[time_stamp()]\] Gibbed [src.occupant]/[src.occupant.ckey]" - log_attack("\[[time_stamp()]\] [user]/[user.ckey] gibbed [src.occupant]/[src.occupant.ckey]") + for(var/i=1 to totalslabs) + var/obj/item/weapon/reagent_containers/food/snacks/meat/human/newmeat = new + newmeat.name = sourcename + newmeat.name + newmeat.subjectname = sourcename + newmeat.subjectjob = sourcejob + newmeat.reagents.add_reagent("nutriment", sourcenutriment / totalslabs) // Thehehe. Fat guys go first + src.occupant.reagents.trans_to(newmeat, round (sourcetotalreagents / totalslabs, 1)) // Transfer all the reagents from the + allmeat[i] = newmeat + + src.occupant.attack_log += "\[[time_stamp()]\] Was gibbed by [user]/[user.ckey]" //One shall not simply gib a mob unnoticed! + user.attack_log += "\[[time_stamp()]\] Gibbed [src.occupant]/[src.occupant.ckey]" + log_attack("\[[time_stamp()]\] [user]/[user.ckey] gibbed [src.occupant]/[src.occupant.ckey]") + + src.occupant.death(1) + src.occupant.ghostize() + + else if( istype(src.occupant, /mob/living/carbon/) || istype(src.occupant, /mob/living/simple_animal/ ) ) + + var/sourcename = src.occupant.name + var/sourcenutriment = src.occupant.nutrition / 15 + var/sourcetotalreagents = 0 + + if( istype(src.occupant, /mob/living/carbon/monkey/) || istype(src.occupant, /mob/living/carbon/alien/) ) // why are you gibbing aliens? oh well + totalslabs = 3 + sourcetotalreagents = src.occupant.reagents.total_volume + else if( istype(src.occupant, /mob/living/simple_animal/cow) || istype(src.occupant, /mob/living/simple_animal/hostile/bear) ) + totalslabs = 2 + else + totalslabs = 1 + sourcenutriment = src.occupant.nutrition / 30 // small animals don't have as much nutrition + + for(var/i=1 to totalslabs) + var/obj/item/weapon/reagent_containers/food/snacks/meat/newmeat = new + newmeat.name = "[sourcename]-[newmeat.name]" + + newmeat.reagents.add_reagent("nutriment", sourcenutriment / totalslabs) + + // Transfer reagents from the old mob to the meat + if( istype(src.occupant, /mob/living/carbon/) ) + src.occupant.reagents.trans_to(newmeat, round(sourcetotalreagents / totalslabs, 1)) + + allmeat[i] = newmeat + + if(src.occupant.client) // Gibbed a cow with a client in it? log that shit + src.occupant.attack_log += "\[[time_stamp()]\] Was gibbed by [user]/[user.ckey]" + user.attack_log += "\[[time_stamp()]\] Gibbed [src.occupant]/[src.occupant.ckey]" + log_attack("\[[time_stamp()]\] [user]/[user.ckey] gibbed [src.occupant]/[src.occupant.ckey]") + + src.occupant.death(1) + src.occupant.ghostize() - src.occupant.death(1) - src.occupant.ghostize() del(src.occupant) + spawn(src.gibtime) playsound(src.loc, 'sound/effects/splat.ogg', 50, 1) operating = 0 diff --git a/code/modules/mob/living/silicon/robot/laws.dm b/code/modules/mob/living/silicon/robot/laws.dm index 98fea6f7498..bff875a0d66 100644 --- a/code/modules/mob/living/silicon/robot/laws.dm +++ b/code/modules/mob/living/silicon/robot/laws.dm @@ -98,4 +98,83 @@ /mob/living/silicon/robot/proc/clear_ion_laws() laws_sanity_check() - laws.clear_ion_laws() \ No newline at end of file + laws.clear_ion_laws() + +/mob/living/silicon/robot/proc/statelaws() // -- TLE +// set category = "AI Commands" +// set name = "State Laws" + src.say("Current Active Laws:") + //src.laws_sanity_check() + //src.laws.show_laws(world) + var/number = 1 + sleep(10) + + if (src.laws.zeroth) + if (src.lawcheck[1] == "Yes") //This line and the similar lines below make sure you don't state a law unless you want to. --NeoFite + src.say("0. [src.laws.zeroth]") + sleep(10) + + for (var/index = 1, index <= src.laws.ion.len, index++) + var/law = src.laws.ion[index] + var/num = ionnum() + if (length(law) > 0) + if (src.ioncheck[index] == "Yes") + src.say("[num]. [law]") + sleep(10) + + for (var/index = 1, index <= src.laws.inherent.len, index++) + var/law = src.laws.inherent[index] + if (length(law) > 0) + if (src.lawcheck[index+1] == "Yes") + src.say("[number]. [law]") + sleep(10) + number++ + + for (var/index = 1, index <= src.laws.supplied.len, index++) + var/law = src.laws.supplied[index] + + if (length(law) > 0) + if(src.lawcheck.len >= number+1) + if (src.lawcheck[number+1] == "Yes") + src.say("[number]. [law]") + sleep(10) + number++ + +/mob/living/silicon/robot/verb/checklaws() //Gives you a link-driven interface for deciding what laws the statelaws() proc will share with the crew. --NeoFite + set category = "Robot Commands" + set name = "State Laws" + var/list = "Which laws do you want to include when stating them for the crew?

" + + if (src.laws.zeroth) + if (!src.lawcheck[1]) + src.lawcheck[1] = "No" //Given Law 0's usual nature, it defaults to NOT getting reported. --NeoFite + list += {"[src.lawcheck[1]] 0: [src.laws.zeroth]
"} + + for (var/index = 1, index <= src.laws.ion.len, index++) + var/law = src.laws.ion[index] + if (length(law) > 0) + if (!src.ioncheck[index]) + src.ioncheck[index] = "Yes" + list += {"[src.ioncheck[index]] [ionnum()]: [law]
"} + src.ioncheck.len += 1 + + var/number = 1 + for (var/index = 1, index <= src.laws.inherent.len, index++) + var/law = src.laws.inherent[index] + if (length(law) > 0) + src.lawcheck.len += 1 + if (!src.lawcheck[number+1]) + src.lawcheck[number+1] = "Yes" + list += {"[src.lawcheck[number+1]] [number]: [law]
"} + number++ + + for (var/index = 1, index <= src.laws.supplied.len, index++) + var/law = src.laws.supplied[index] + if (length(law) > 0) + src.lawcheck.len += 1 + if (!src.lawcheck[number+1]) + src.lawcheck[number+1] = "Yes" + list += {"[src.lawcheck[number+1]] [number]: [law]
"} + number++ + list += {"

State Laws"} + usr << browse(list, "window=laws") \ No newline at end of file diff --git a/code/modules/mob/living/silicon/robot/robot.dm b/code/modules/mob/living/silicon/robot/robot.dm index 2521f1b613a..492a64d04c2 100644 --- a/code/modules/mob/living/silicon/robot/robot.dm +++ b/code/modules/mob/living/silicon/robot/robot.dm @@ -59,6 +59,8 @@ var/weapon_lock = 0 var/weaponlock_time = 120 var/lawupdate = 1 //Cyborgs will sync their laws with their AI by default + var/lawcheck[1] //For stating laws. + var/ioncheck[1] //Ditto. var/lockcharge //Used when locking down a borg to preserve cell charge var/speed = 0 //Cause sec borgs gotta go fast //No they dont! var/scrambledcodes = 0 // Used to determine if a borg shows up on the robotics console. Setting to one hides them. @@ -1129,6 +1131,25 @@ else src << "Module isn't activated" installed_modules() + + if (href_list["lawc"]) // Toggling whether or not a law gets stated by the State Laws verb --NeoFite + var/L = text2num(href_list["lawc"]) + switch(lawcheck[L+1]) + if ("Yes") lawcheck[L+1] = "No" + if ("No") lawcheck[L+1] = "Yes" +// src << text ("Switching Law [L]'s report status to []", lawcheck[L+1]) + checklaws() + + if (href_list["lawi"]) // Toggling whether or not a law gets stated by the State Laws verb --NeoFite + var/L = text2num(href_list["lawi"]) + switch(ioncheck[L]) + if ("Yes") ioncheck[L] = "No" + if ("No") ioncheck[L] = "Yes" +// src << text ("Switching Law [L]'s report status to []", lawcheck[L+1]) + checklaws() + + if (href_list["laws"]) // With how my law selection code works, I changed statelaws from a verb to a proc, and call it through my law selection panel. --NeoFite + statelaws() return /mob/living/silicon/robot/proc/radio_menu() diff --git a/code/modules/nano/nanoui.dm b/code/modules/nano/nanoui.dm index add6437c3be..565295d3f99 100644 --- a/code/modules/nano/nanoui.dm +++ b/code/modules/nano/nanoui.dm @@ -1,3 +1,7 @@ +#define STATUS_INTERACTIVE 2 // GREEN Visability +#define STATUS_UPDATE 1 // ORANGE Visability +#define STATUS_DISABLED 0 // RED Visability + /datum/nanoui var/mob/user var/atom/movable/src_object @@ -19,7 +23,10 @@ var/content = "
" // the #mainTemplate div will contain the compiled "main" template html var/list/initial_data[0] var/is_auto_updating = 0 - var/status = 2 + var/status = STATUS_INTERACTIVE + + // Only allow users with a certain user.stat to get updates. Defaults to 0 (concious) + var/allowed_user_stat = 0 // -1 = ignore, 0 = alive, 1 = unconcious or alive, 2 = dead concious or alive /datum/nanoui/New(nuser, nsrc_object, nui_key, ntemplate, ntitle = 0, nwidth = 0, nheight = 0, var/atom/nref = null) @@ -39,7 +46,7 @@ if (nref) ref = nref - add_common_assets() + add_common_assets() /datum/nanoui/proc/add_common_assets() add_script("libraries.min.js") // The jQuery library @@ -49,13 +56,42 @@ add_stylesheet("shared.css") // this CSS sheet is common to all UIs add_stylesheet("icons.css") // this CSS sheet is common to all UIs -/datum/nanoui/proc/set_status(state) +/datum/nanoui/proc/set_status(state, push_update) if (state != status) status = state - push_data(list(), 1) // Update the UI + if (push_update || !status) + push_data(list(), 1) // Update the UI, force the update in case the status is 0 else status = state +/datum/nanoui/proc/update_status(push_update = 0) + if (istype(user, /mob/living/silicon/ai)) + set_status(STATUS_INTERACTIVE, push_update) // interactive (green visibility) + else if (istype(user, /mob/living/silicon/robot)) + if (src_object in view(7, user)) // robots can see and interact with things they can see within 7 tiles + set_status(STATUS_INTERACTIVE, push_update) // interactive (green visibility) + else + set_status(STATUS_DISABLED, push_update) // no updates, completely disabled (red visibility) + else + var/dist = get_dist(src_object, user) + + if (dist > 4) + close() + return + + if ((allowed_user_stat > -1) && (user.stat > allowed_user_stat)) + set_status(STATUS_DISABLED, push_update) // no updates, completely disabled (red visibility) + else if (user.restrained() || user.lying) + set_status(STATUS_UPDATE, push_update) // update only (orange visibility) + else if (!(src_object in view(4, user))) // If the src object is not in visable, set status to 0 + set_status(STATUS_DISABLED, push_update) // interactive (green visibility) + else if (dist <= 1) + set_status(STATUS_INTERACTIVE, push_update) // interactive (green visibility) + else if (dist <= 2) + set_status(STATUS_UPDATE, push_update) // update only (orange visibility) + else if (dist <= 4) + set_status(STATUS_DISABLED, push_update) // no updates, completely disabled (red visibility) + /datum/nanoui/proc/set_auto_update(state = 1) is_auto_updating = state @@ -109,7 +145,7 @@ if (initial_data.len > 0) initial_data_json = list2json(initial_data) - var/url_parameters_json = list2json(list("src" = "\ref[src_object]")) + var/url_parameters_json = list2json(list("src" = "\ref[src]")) return {" @@ -145,6 +181,14 @@ [title ? "
[title]
" : ""]
"} + +/datum/nanoui/Topic(href, href_list) + update_status(0) // update the status + if (status != STATUS_INTERACTIVE || user != usr) // If UI is not interactive or usr calling Topic is not the UI user + return + + if (src_object.Topic(href, href_list)) + nanomanager.update_uis(src_object) // update all UIs attached to src_object /datum/nanoui/proc/get_footer() var/scriptsContent = "" @@ -170,6 +214,7 @@ var/window_size = "" if (width && height) window_size = "size=[width]x[height];" + update_status(0) user << browse(get_content(), "window=[window_id];[window_size][window_options]") on_close_winset() //onclose(user, window_id) @@ -188,21 +233,11 @@ winset(user, window_id, "on-close=\"nanoclose [params]\"") -/datum/nanoui/proc/process(update = 0) - var/dist = get_dist(src_object, user) - if (dist <= 1) - set_status(2) // interactive - else if (dist <= 2) - set_status(1) // update only - else if (dist <= 3) - set_status(0) // no updates, completely disabled - return // don't auto update +/datum/nanoui/proc/process(update = 0) + if (status && (update || is_auto_updating)) + src_object.ui_interact(user, ui_key) // Update the UI (update_status() is called whenever a UI is updated) else - close() - return - - if (update || is_auto_updating) - src_object.ui_interact(user, ui_key) + update_status(1) // Not updating UI, so lets check here if status has changed /datum/nanoui/proc/modify_data(data) data["ui"] = list( @@ -213,9 +248,9 @@ return data /datum/nanoui/proc/push_data(data, force_push = 0) - if (!status && !force_push) - user << "Cannot update UI, user out of range (status [status])" - return + update_status(0) + if (status == STATUS_DISABLED && !force_push) + return // Cannot update UI, no visibility data = modify_data(data) diff --git a/nano/css/shared.css b/nano/css/shared.css index 4d96bf988f5..b8c75eac04c 100644 --- a/nano/css/shared.css +++ b/nano/css/shared.css @@ -322,6 +322,12 @@ div.notice height: 100%; background: #40628a; overflow: hidden; + float: left; +} + +.progressFill.alignRight +{ + float: right; } .progressFill.good @@ -342,6 +348,8 @@ div.notice background: #ee0000; } + + .progressFill.highlight { color: #ffffff; diff --git a/nano/js/nano_base_helpers.js b/nano/js/nano_base_helpers.js index 61ca5267b9c..d1c4e358807 100644 --- a/nano/js/nano_base_helpers.js +++ b/nano/js/nano_base_helpers.js @@ -46,7 +46,7 @@ NanoBaseHelpers = function () string: function() { if (arguments.length == 0) { - return ""; + return ''; } else if (arguments.length == 1) { @@ -61,7 +61,42 @@ NanoBaseHelpers = function () } return arguments[0].format(stringArgs); } - return + return ''; + }, + // Display a bar. Used to show health, capacity, etc. + displayBar: function(value, rangeMin, rangeMax, styleClass) { + + if (rangeMin < rangeMax) + { + if (value < rangeMin) + { + value = rangeMin; + } + else if (value > rangeMax) + { + value = rangeMax; + } + } + else + { + if (value > rangeMin) + { + value = rangeMin; + } + else if (value < rangeMax) + { + value = rangeMax; + } + } + + if (typeof styleClass == 'undefined') + { + styleClass = ''; + } + + var percentage = Math.round((value - rangeMin) / (rangeMax - rangeMin) * 100); + + return '
'; } }); } diff --git a/nano/templates/cryo.tmpl b/nano/templates/cryo.tmpl index 3399876ac0d..d55aa448415 100644 --- a/nano/templates/cryo.tmpl +++ b/nano/templates/cryo.tmpl @@ -14,16 +14,46 @@ DEAD {{/if}}
-
Health:
{^{:~string('
', [occupant.health])}}
{^{:occupant.health}}%
-
=> Brute Damage:
{^{:~string('
', [occupant.bruteLoss])}}
{^{:occupant.bruteLoss}}%
-
=> Resp. Damage:
{^{:~string('
', [occupant.oxyLoss])}}
{^{:occupant.oxyLoss}}%
-
=> Toxin Content:
{^{:~string('
', [occupant.toxLoss])}}
{^{:occupant.toxLoss}}%
-
=> Burn Severity:
{^{:~string('
', [occupant.fireLoss])}}
{^{:occupant.fireLoss}}%
-
Body Temperature:
{^{:occupant.bodyTemperature}} K
+ + {^{if occupant.stat < 2}} +
+
Health:
+ {^{if occupant.health >= 0}} + {^{:~displayBar(occupant.health, 0, occupant.maxHealth, 'good')}} + {{else}} + {^{:~displayBar(occupant.health, 0, occupant.minHealth, 'average alignRight')}} + {{/if}} +
{^{:~round(occupant.health)}}
+
+ +
+
=> Brute Damage:
+ {^{:~displayBar(occupant.bruteLoss, 0, occupant.maxHealth, 'bad')}} +
{^{:~round(occupant.bruteLoss)}}
+
+ +
+
=> Resp. Damage:
+ {^{:~displayBar(occupant.oxyLoss, 0, occupant.maxHealth, 'bad')}} +
{^{:~round(occupant.oxyLoss)}}
+
+ +
+
=> Toxin Damage:
+ {^{:~displayBar(occupant.toxLoss, 0, occupant.maxHealth, 'bad')}} +
{^{:~round(occupant.toxLoss)}}
+
+ +
+
=> Burn Severity:
+ {^{:~displayBar(occupant.fireLoss, 0, occupant.maxHealth, 'bad')}} +
{^{:~round(occupant.fireLoss)}}
+
+ {{/if}} {{/if}}
Cell Temperature:
- {^{:~string('{1} K', cellTemperatureStatus, cellTemperature)}} + {^{:~string('{1} K', cellTemperatureStatus, cellTemperature)}}
@@ -32,8 +62,11 @@
Cryo Cell Status:
-
- {^{:~link('On', 'power', {'start' : 1}, isOperating ? 'selected' : null)}}{^{:~link('Off', 'close', {'start' : 1}, isOperating ? null : 'selected')}} +
+ {^{:~link('On', 'power', {'switchOn' : 1}, isOperating ? 'selected' : null)}}{^{:~link('Off', 'close', {'switchOff' : 1}, isOperating ? null : 'selected')}} +
+
+ {^{:~link('Eject Occupant', 'arrowreturnthick-1-s', {'ejectOccupant' : 1}, hasOccupant ? null : 'disabled')}}
 
@@ -53,6 +86,6 @@ {{/if}}
- {^{:~link('Eject Beaker', 'eject', {'eject' : 1}, isBeakerLoaded ? null : 'disabled')}} + {^{:~link('Eject Beaker', 'eject', {'ejectBeaker' : 1}, isBeakerLoaded ? null : 'disabled')}}
\ No newline at end of file