diff --git a/code/__DEFINES/hud.dm b/code/__DEFINES/hud.dm
index e0ab40eba492..12a654fe83f5 100644
--- a/code/__DEFINES/hud.dm
+++ b/code/__DEFINES/hud.dm
@@ -55,6 +55,8 @@
#define GLAND_HUD "25"
/// Pressure coloring for tiles
#define PRESSURE_HUD "26"
+/// AI shell status
+#define DIAG_AISHELL_STAT_HUD "27"
/// Telepathy bubbles
#define THOUGHT_HUD "thoughts_hud"
/// Kidan pheromones hud
diff --git a/code/__DEFINES/mobs.dm b/code/__DEFINES/mobs.dm
index 0be81d918edb..339d7f36532c 100644
--- a/code/__DEFINES/mobs.dm
+++ b/code/__DEFINES/mobs.dm
@@ -154,6 +154,14 @@
#define ROBOT_NOTIFY_AI_CONNECTED 1 //New Cyborg
#define ROBOT_NOTIFY_AI_MODULE 2 //New Module
#define ROBOT_NOTIFY_AI_NAME 3 //New Name
+#define AI_NOTIFICATION_AI_SHELL 4 //New AI shell
+//'evacuate_ai()' proc danger levels
+#define DANGER_LVL_NONE "danger_level_none" //0% kill chance
+#define DANGER_LVL_MAY_DIE "danger_level_may_die" //50% kill chance
+#define DANGER_LVL_INSTA_DEATH "danger_level_insta_death" //100% kill chance
+//'robot.attack_ai()' proc tgui_input desicsions
+#define AISHELL_CONNECT_POSITIVE "Подключиться"
+#define AISHELL_CONNECT_NEGATIVE "Отмена"
//determines if a mob can smash through it
#define ENVIRONMENT_SMASH_NONE 0
#define ENVIRONMENT_SMASH_STRUCTURES 1 //crates, lockers, ect
diff --git a/code/__HELPERS/mobs.dm b/code/__HELPERS/mobs.dm
index 997bb3e450ea..ac9ced56b620 100644
--- a/code/__HELPERS/mobs.dm
+++ b/code/__HELPERS/mobs.dm
@@ -798,7 +798,7 @@ GLOBAL_DATUM_INIT(dview_mob, /mob/dview, new)
var/selected_borg_name = null
var/list/available_borgs = list()
for(var/mob/living/silicon/robot/borg in GLOB.player_list)
- if(borg.stat == DEAD || borg.connected_ai || borg.scrambledcodes || isdrone(borg) || iscogscarab(borg) || isclocker(borg))
+ if(borg.stat == DEAD || borg.connected_ai || borg.scrambledcodes || isdrone(borg) || iscogscarab(borg) || isclocker(borg) || borg.shell)
continue
var/borg_name = "[borg.real_name] ([borg.modtype?.name] [borg.braintype])"
available_borgs[borg_name] = borg
diff --git a/code/_onclick/hud/_defines.dm b/code/_onclick/hud/_defines.dm
index f34a1ff07720..78e962f0d514 100644
--- a/code/_onclick/hud/_defines.dm
+++ b/code/_onclick/hud/_defines.dm
@@ -165,6 +165,8 @@
#define ui_ai_up "TOP:-6,RIGHT-1"
#define ui_ai_down "TOP:-6,RIGHT"
+#define ui_ai_connect_to_shell "BOTTOM:6,LEFT+3"
+
// Bots
#define ui_bot_radio "EAST-1:28,SOUTH:7"
#define ui_bot_pull "EAST-2:26,SOUTH:7"
diff --git a/code/_onclick/hud/ai.dm b/code/_onclick/hud/ai.dm
index 055c5c24952d..9dada23b72ad 100644
--- a/code/_onclick/hud/ai.dm
+++ b/code/_onclick/hud/ai.dm
@@ -160,6 +160,16 @@
var/mob/living/silicon/ai/AI = usr
AI.move_down()
+/atom/movable/screen/ai/connect_to_shell
+ name = "Подключиться к оболочке"
+ icon_state = "AIshell"
+
+/atom/movable/screen/ai/connect_to_shell/Click()
+ if(!isAI(usr))
+ return
+ var/mob/living/silicon/ai/AI = usr
+ AI.deploy_to_shell()
+
/datum/hud/ai/New(mob/owner)
..()
@@ -259,3 +269,8 @@
using = new /atom/movable/screen/ai/move_down(null, src)
using.screen_loc = ui_ai_down
static_inventory += using
+
+//Connect to shell
+ using = new /atom/movable/screen/ai/connect_to_shell(null, src)
+ using.screen_loc = ui_ai_connect_to_shell
+ static_inventory += using
diff --git a/code/game/data_huds.dm b/code/game/data_huds.dm
index 010d7d91903d..4f62f15a21ec 100644
--- a/code/game/data_huds.dm
+++ b/code/game/data_huds.dm
@@ -47,10 +47,10 @@
hud_icons = list(ID_HUD, IMPTRACK_HUD, IMPMINDSHIELD_HUD, IMPCHEM_HUD, WANTED_HUD)
/datum/atom_hud/data/diagnostic
- hud_icons = list(DIAG_HUD, DIAG_STAT_HUD, DIAG_BATT_HUD, DIAG_MECH_HUD, DIAG_BOT_HUD, DIAG_TRACK_HUD, DIAG_AIRLOCK_HUD)
+ hud_icons = list(DIAG_HUD, DIAG_STAT_HUD, DIAG_BATT_HUD, DIAG_MECH_HUD, DIAG_BOT_HUD, DIAG_TRACK_HUD, DIAG_AIRLOCK_HUD, DIAG_AISHELL_STAT_HUD)
/datum/atom_hud/data/diagnostic/advanced
- hud_icons = list(DIAG_HUD, DIAG_STAT_HUD, DIAG_BATT_HUD, DIAG_MECH_HUD, DIAG_BOT_HUD, DIAG_TRACK_HUD, DIAG_AIRLOCK_HUD, DIAG_PATH_HUD)
+ hud_icons = list(DIAG_HUD, DIAG_STAT_HUD, DIAG_BATT_HUD, DIAG_MECH_HUD, DIAG_BOT_HUD, DIAG_TRACK_HUD, DIAG_AIRLOCK_HUD, DIAG_PATH_HUD, DIAG_AISHELL_STAT_HUD)
/datum/atom_hud/data/bot_path
// This hud exists so the bot can see itself, that's all
diff --git a/code/game/gamemodes/clockwork/clock_magic.dm b/code/game/gamemodes/clockwork/clock_magic.dm
index 9e9e5fff31a0..903d3e0c8ef1 100644
--- a/code/game/gamemodes/clockwork/clock_magic.dm
+++ b/code/game/gamemodes/clockwork/clock_magic.dm
@@ -366,7 +366,7 @@
playsound(get_turf(src), 'sound/machines/airlockforced.ogg', 80, TRUE)
do_sparks(5, TRUE, target)
if(do_after(user, 9 SECONDS, candidate))
- candidate.emp_act(EMP_HEAVY)
+ candidate.Stun(6 SECONDS)
candidate.ratvar_act(weak = TRUE)
SSticker?.score?.save_silicon_laws(candidate, user, "Ratvar act", log_all_laws = TRUE)
channeling = FALSE
diff --git a/code/game/gamemodes/cult/runes.dm b/code/game/gamemodes/cult/runes.dm
index 70675cb7e78d..eba842c5351f 100644
--- a/code/game/gamemodes/cult/runes.dm
+++ b/code/game/gamemodes/cult/runes.dm
@@ -397,6 +397,13 @@ structure_check() searches for nearby cultist structures required for the invoca
playsound(offering, 'sound/misc/demon_consume.ogg', 100, TRUE)
if((ishuman(offering) || isrobot(offering) || isbrain(offering)) && offering.mind)
+ if(isrobot(offering))
+ var/mob/living/silicon/robot/robot = offering
+ if(robot.shell && robot.mainframe)
+ robot.evacuate_ai(DANGER_LVL_INSTA_DEATH)
+ robot.dust()
+ playsound(offering, 'sound/magic/disintegrate.ogg', 100, TRUE)
+ return TRUE
var/obj/item/soulstone/stone = new /obj/item/soulstone(get_turf(src))
stone.invisibility = INVISIBILITY_MAXIMUM // So it's not picked up during transfer_soul()
stone.transfer_soul("FORCE", offering, user) // If it cannot be added
diff --git a/code/game/machinery/computer/law.dm b/code/game/machinery/computer/law.dm
index 19965ea5aa13..d1287dc96bc0 100644
--- a/code/game/machinery/computer/law.dm
+++ b/code/game/machinery/computer/law.dm
@@ -134,6 +134,10 @@
installed_module.transmit_instructions(current, user, reg_name)
to_chat(current, "These are your laws now:")
current.show_laws()
+ if(isAI(current))
+ var/mob/living/silicon/ai/AI = current
+ if(AI.deployed_shell)
+ AI.deployed_shell.show_laws()
for(var/mob/living/silicon/robot/R in GLOB.mob_list)
if(R.lawupdate && (R.connected_ai == current))
to_chat(R, "These are your laws now:")
diff --git a/code/game/machinery/computer/robot.dm b/code/game/machinery/computer/robot.dm
index 214caccc52a4..d303de8173ab 100644
--- a/code/game/machinery/computer/robot.dm
+++ b/code/game/machinery/computer/robot.dm
@@ -45,8 +45,6 @@
return FALSE
if(iscogscarab(R))
return FALSE
- if(iscogscarab(R))
- return FALSE
if(R.scrambledcodes)
return FALSE
if(!are_zs_connected(src, R))
@@ -162,6 +160,8 @@
synchronization = R.connected_ai,
is_hacked = R.connected_ai && R.emagged,
hackable = can_hack(user, R),
+ is_shell = R.shell,
+ occupier = R.mainframe? R.mainframe.name : "None",
)
data["cyborgs"] += list(cyborg_data)
data["show_detonate_all"] = (data["auth"] && length(data["cyborgs"]) > 0 && ishuman(user))
diff --git a/code/game/objects/items/robot/robot_parts.dm b/code/game/objects/items/robot/robot_parts.dm
index 0ef39e5eadf0..0bb9c15101be 100644
--- a/code/game/objects/items/robot/robot_parts.dm
+++ b/code/game/objects/items/robot/robot_parts.dm
@@ -138,8 +138,77 @@
if(l_leg && r_leg)
if(chest && head)
SSblackbox.record_feedback("amount", "cyborg_frames_built", 1)
- return 1
- return 0
+ return TRUE
+ return FALSE
+
+/obj/item/robot_parts/robot_suit/proc/install_cell(mob/living/silicon/robot/target)
+ chest.cell.forceMove(target)
+ target.cell = chest.cell
+ chest.cell = null
+ // Since we "magically" installed a cell, we also have to update the correct component.
+ var/datum/robot_component/cell_component = target.components["power cell"]
+ cell_component.wrapped = target.cell
+ cell_component.installed = TRUE
+
+/obj/item/robot_parts/robot_suit/proc/check_locomotion(mob/living/silicon/robot/target)
+ if(locomotion)
+ return
+ target.set_lockcharge(TRUE)
+ to_chat(target, span_warning("Error: Servo motors unresponsive."))
+
+/obj/item/robot_parts/robot_suit/proc/check_lawsync()
+ if(!aisync)
+ lawsync = FALSE
+ if(sabotaged)
+ aisync = FALSE
+ lawsync = FALSE
+
+/obj/item/robot_parts/robot_suit/proc/get_new_laws(obj/item/mmi/new_mmi)
+ if(new_mmi.syndicate) // ffs
+ aisync = FALSE
+ lawsync = FALSE
+ return new /datum/ai_laws/syndicate_override
+ if(new_mmi.ninja)
+ aisync = FALSE
+ lawsync = FALSE
+ return new /datum/ai_laws/ninja_override
+ if(new_mmi.clock)
+ aisync = FALSE
+ lawsync = FALSE
+ return new /datum/ai_laws/ratvar
+
+/obj/item/robot_parts/robot_suit/proc/apply_debug_stats(mob/living/silicon/robot/target)
+ target.custom_name = created_name
+ target.rename_character(target.real_name, target.get_default_name())
+ target.locked = panel_locked
+
+/obj/item/robot_parts/robot_suit/proc/give_new_laws(mob/living/silicon/robot/target, datum/ai_laws/laws_to_give)
+ if(laws_to_give)
+ target.laws = laws_to_give
+ return
+ if(lawsync)
+ return
+ target.lawupdate = FALSE
+ target.make_laws()
+
+/obj/item/robot_parts/robot_suit/proc/check_special_role(obj/item/mmi/mmi, mob/living/silicon/robot/target, mob/living/user)
+ if(mmi.greet(target) && !target.mind.special_role)
+ return
+ target.mind.store_memory("As a cyborg, you must obey your silicon laws and master AI above all else. Your objectives will consider you to be dead.")
+ to_chat(target, span_userdanger("You have been robotized!"))
+ to_chat(target, span_danger("You must obey your silicon laws and master AI above all else. Your objectives will consider you to be dead."))
+
+/obj/item/robot_parts/robot_suit/proc/process_clocker_cyborg(mob/living/silicon/robot/target)
+ if(!target.mmi.clock) // so robots created from vessel have magic
+ return
+ target.UnlinkSelf()
+ SSticker.mode.add_clock_actions(target.mind)
+
+/obj/item/robot_parts/robot_suit/proc/process_job_task(mob/living/target)
+ var/datum/job_objective/make_cyborg/task = target.mind.findJobTask(/datum/job_objective/make_cyborg)
+ if(!istype(task))
+ return
+ task.unit_completed()
/obj/item/robot_parts/robot_suit/multitool_act(mob/living/user, obj/item/I)
. = TRUE
@@ -244,143 +313,129 @@
update_icon(UPDATE_OVERLAYS)
return ATTACK_CHAIN_BLOCKED_ALL
- if(!is_mmi(I))
- return ..()
-
- . = ATTACK_CHAIN_PROCEED
- add_fingerprint(user)
- var/obj/item/mmi/new_mmi = I
- if(!check_completion())
- to_chat(user, span_warning("The MMI must go in after everything else!"))
- return .
-
- if(new_mmi.clock && !isclocker(user))
- to_chat(user, span_danger("An overwhelming feeling of dread comes over you as you attempt to put the soul vessel into the frame."))
- user.Confused(20 SECONDS)
- user.Jitter(12 SECONDS)
- return ATTACK_CHAIN_BLOCKED_ALL
-
- if(!isturf(loc))
- to_chat(user, span_warning("You can't put [new_mmi] in, the frame has to be standing on the ground to be perfectly precise."))
- return .
-
- if(!new_mmi.brainmob)
- to_chat(user, span_warning("Sticking an empty [new_mmi.name] into the frame would sort of defeat the purpose."))
- return .
+ if(istype(I, /obj/item/borg/upgrade/ai))
- if(!new_mmi.brainmob.key)
- var/ghost_can_reenter = FALSE
- if(new_mmi.brainmob.mind)
- for(var/mob/dead/observer/observer in GLOB.player_list)
- if(observer.can_reenter_corpse && observer.mind == new_mmi.brainmob.mind)
- ghost_can_reenter = TRUE
- if(new_mmi.next_possible_ghost_ping < world.time)
- observer.notify_cloning("Somebody is trying to borg you! Re-enter your corpse if you want to be borged!", 'sound/voice/liveagain.ogg', src)
- new_mmi.next_possible_ghost_ping = world.time + 30 SECONDS // Avoid spam
- break
- if(ghost_can_reenter)
- to_chat(user, span_warning("The [new_mmi.name] is currently inactive. Try again later."))
- else
- to_chat(user, span_warning("The [new_mmi.name] is completely unresponsive; there's no point to use it."))
+ . = ATTACK_CHAIN_PROCEED
+ add_fingerprint(user)
+ var/obj/item/borg/upgrade/ai/module = I
+ if(!check_completion())
+ to_chat(user, span_warning("The B.O.R.I.S. module must go in after everything else!"))
+ return .
+
+ if(!isturf(loc))
+ to_chat(user, span_warning("You can't put [module] in, the frame has to be standing on the ground to be perfectly precise."))
+ return .
+
+ check_lawsync()
+
+ if(iscarbon(user))
+ var/mob/living/carbon/carbon = user
+ if(carbon.drop_item_ground(module))
+ qdel(module)
+ var/mob/living/silicon/robot/new_shell = new /mob/living/silicon/robot/shell(get_turf(src))
+ if(QDELETED(new_shell))
+ return .
+
+ . = ATTACK_CHAIN_BLOCKED_ALL
+
+ process_job_task(user)
+ apply_debug_stats(new_shell)
+ new_shell.job = JOB_TITLE_CYBORG
+ install_cell(new_shell)
+ forceMove(new_shell)
+ new_shell.robot_suit = src
+ check_locomotion(new_shell)
return .
- if(jobban_isbanned(new_mmi.brainmob, JOB_TITLE_CYBORG) || jobban_isbanned(new_mmi.brainmob, "nonhumandept"))
- to_chat(user, span_warning("This [new_mmi.name] is not fit to serve as a cyborg!"))
- return .
+ if(is_mmi(I))
- if(new_mmi.brainmob.stat == DEAD)
- to_chat(user, span_warning("Sticking a dead [new_mmi.name] into the frame would sort of defeat the purpose."))
- return .
+ . = ATTACK_CHAIN_PROCEED
+ add_fingerprint(user)
+ var/obj/item/mmi/new_mmi = I
+ if(!check_completion())
+ to_chat(user, span_warning("The MMI must go in after everything else!"))
+ return .
+
+ if(new_mmi.clock && !isclocker(user))
+ to_chat(user, span_danger("An overwhelming feeling of dread comes over you as you attempt to put the soul vessel into the frame."))
+ user.Confused(20 SECONDS)
+ user.Jitter(12 SECONDS)
+ return ATTACK_CHAIN_BLOCKED_ALL
+
+ if(!isturf(loc))
+ to_chat(user, span_warning("You can't put [new_mmi] in, the frame has to be standing on the ground to be perfectly precise."))
+ return .
+
+ if(!new_mmi.brainmob)
+ to_chat(user, span_warning("Sticking an empty [new_mmi.name] into the frame would sort of defeat the purpose."))
+ return .
+
+ if(!new_mmi.brainmob.key)
+ var/ghost_can_reenter = FALSE
+ if(new_mmi.brainmob.mind)
+ for(var/mob/dead/observer/observer in GLOB.player_list)
+ if(observer.can_reenter_corpse && observer.mind == new_mmi.brainmob.mind)
+ ghost_can_reenter = TRUE
+ if(new_mmi.next_possible_ghost_ping < world.time)
+ observer.notify_cloning("Somebody is trying to borg you! Re-enter your corpse if you want to be borged!", 'sound/voice/liveagain.ogg', src)
+ new_mmi.next_possible_ghost_ping = world.time + 30 SECONDS // Avoid spam
+ break
+ if(ghost_can_reenter)
+ to_chat(user, span_warning("The [new_mmi.name] is currently inactive. Try again later."))
+ else
+ to_chat(user, span_warning("The [new_mmi.name] is completely unresponsive; there's no point to use it."))
+ return .
+
+ if(jobban_isbanned(new_mmi.brainmob, JOB_TITLE_CYBORG) || jobban_isbanned(new_mmi.brainmob, "nonhumandept"))
+ to_chat(user, span_warning("This [new_mmi.name] is not fit to serve as a cyborg!"))
+ return .
+
+ if(new_mmi.brainmob.stat == DEAD)
+ to_chat(user, span_warning("Sticking a dead [new_mmi.name] into the frame would sort of defeat the purpose."))
+ return .
+
+ if(new_mmi.brainmob.mind in SSticker.mode.head_revolutionaries)
+ to_chat(user, span_warning("The frame's firmware lets out a shrill sound, and flashes 'Abnormal Memory Engram'. It refuses to accept [new_mmi]."))
+ return .
+
+ var/datum/ai_laws/laws_to_give
+ check_lawsync()
+ laws_to_give = get_new_laws(new_mmi)
+
+ var/mob/living/silicon/robot/new_borg = new(loc, syndie = sabotaged, unfinished = TRUE, ai_to_sync_to = forced_ai, connect_to_AI = aisync)
+ if(QDELETED(new_borg)) // somehow??? jesus fucking christ
+ return .
+
+ if(!user.drop_transfer_item_to_loc(new_mmi, src))
+ return ..()
- if(new_mmi.brainmob.mind in SSticker.mode.head_revolutionaries)
- to_chat(user, span_warning("The frame's firmware lets out a shrill sound, and flashes 'Abnormal Memory Engram'. It refuses to accept [new_mmi]."))
- return .
+ . = ATTACK_CHAIN_BLOCKED_ALL
- var/datum/ai_laws/laws_to_give
- if(!aisync)
- lawsync = FALSE
+ process_job_task(user)
+ new_borg.invisibility = 0
+ new_mmi.forceMove(new_borg) //Should fix cybros run time erroring when blown up. It got deleted before, along with the frame.
+ //Transfer debug settings to new mob
+ apply_debug_stats(new_borg)
+ give_new_laws(new_borg, laws_to_give)
+ new_mmi.brainmob.mind.transfer_to(new_borg)
- if(sabotaged)
- aisync = FALSE
- lawsync = FALSE
+ SSticker?.score?.save_silicon_laws(new_borg, user, "robot construction", log_all_laws = TRUE)
- if(new_mmi.syndicate) // ffs
- aisync = FALSE
- lawsync = FALSE
- laws_to_give = new /datum/ai_laws/syndicate_override
+ check_special_role(new_mmi, new_borg, user)
+ new_borg.job = JOB_TITLE_CYBORG
+ install_cell(new_borg)
+ new_borg.mmi = new_mmi
+ new_borg.Namepick()
- if(new_mmi.ninja)
- aisync = FALSE
- lawsync = FALSE
- laws_to_give = new /datum/ai_laws/ninja_override
+ SSblackbox.record_feedback("amount", "cyborg_birth", 1)
- if(new_mmi.clock)
- aisync = FALSE
- lawsync = FALSE
- laws_to_give = new /datum/ai_laws/ratvar
-
- var/mob/living/silicon/robot/new_borg = new(loc, syndie = sabotaged, unfinished = TRUE, ai_to_sync_to = forced_ai, connect_to_AI = aisync)
- if(QDELETED(new_borg)) // somehow??? jesus fucking christ
+ forceMove(new_borg)
+ new_borg.robot_suit = src
+ new_borg.mmi.apply_effects(new_borg)
+ process_clocker_cyborg(new_borg)
+ check_locomotion(new_borg)
return .
- if(!user.drop_transfer_item_to_loc(new_mmi, src))
- return ..()
-
- . = ATTACK_CHAIN_BLOCKED_ALL
-
- var/datum/job_objective/make_cyborg/task = user.mind.findJobTask(/datum/job_objective/make_cyborg)
- if(istype(task))
- task.unit_completed()
-
- new_borg.invisibility = 0
- new_mmi.forceMove(new_borg) //Should fix cybros run time erroring when blown up. It got deleted before, along with the frame.
- //Transfer debug settings to new mob
- new_borg.custom_name = created_name
- new_borg.rename_character(new_borg.real_name, new_borg.get_default_name())
- new_borg.locked = panel_locked
-
- if(laws_to_give)
- new_borg.laws = laws_to_give
- else if(!lawsync)
- new_borg.lawupdate = FALSE
- new_borg.make_laws()
-
- new_mmi.brainmob.mind.transfer_to(new_borg)
-
- SSticker?.score?.save_silicon_laws(new_borg, user, "robot construction", log_all_laws = TRUE)
-
- if(!new_mmi.greet(new_borg) && new_borg.mind?.special_role)
- new_borg.mind.store_memory("As a cyborg, you must obey your silicon laws and master AI above all else. Your objectives will consider you to be dead.")
- to_chat(new_borg, span_userdanger("You have been robotized!"))
- to_chat(new_borg, span_danger("You must obey your silicon laws and master AI above all else. Your objectives will consider you to be dead."))
-
- new_borg.job = JOB_TITLE_CYBORG
-
- chest.cell.forceMove(new_borg)
- new_borg.cell = chest.cell
- chest.cell = null
- // Since we "magically" installed a cell, we also have to update the correct component.
- var/datum/robot_component/cell_component = new_borg.components["power cell"]
- cell_component.wrapped = new_borg.cell
- cell_component.installed = TRUE
- new_borg.mmi = new_mmi
- new_borg.Namepick()
-
- SSblackbox.record_feedback("amount", "cyborg_birth", 1)
-
- forceMove(new_borg)
- new_borg.robot_suit = src
-
- new_borg.mmi.apply_effects(new_borg)
-
- if(new_borg.mmi.clock) // so robots created from vessel have magic
- new_borg.UnlinkSelf()
- SSticker.mode.add_clock_actions(new_borg.mind)
-
- if(!locomotion)
- new_borg.set_lockcharge(TRUE)
- to_chat(new_borg, span_warning("Error: Servo motors unresponsive."))
-
/obj/item/robot_parts/robot_suit/proc/Interact(mob/user)
var/t1 = "Designation: [(created_name ? "[created_name]" : "Default Cyborg")]
\n"
t1 += "Master AI: [(forced_ai ? "[forced_ai.name]" : "Automatic")]
\n"
diff --git a/code/game/objects/items/robot/robot_upgrades.dm b/code/game/objects/items/robot/robot_upgrades.dm
index e59d55f87a4c..1f0a472508b1 100644
--- a/code/game/objects/items/robot/robot_upgrades.dm
+++ b/code/game/objects/items/robot/robot_upgrades.dm
@@ -111,6 +111,9 @@
if(user)
to_chat(user, "[span_danger("UPGRADE ERROR: ")]" + "[span_notice("you have to repair the cyborg before using this module!")]")
return FALSE
+ if(robot.shell)
+ to_chat(user, "[span_danger("UPGRADE ERROR: ")]" + "[span_notice("cant apply on a AI shell!")]")
+ return FALSE
if(!robot.key)
for(var/mob/dead/observer/ghost in GLOB.player_list)
@@ -864,3 +867,35 @@
/obj/item/borg/upgrade/mounted_seat/pre_emaged
emagged = TRUE
+
+/obj/item/borg/upgrade/ai
+ name = "B.O.R.I.S. module"
+ desc = "Модуль Блюспейс Ориентированной Роботической Искусственной Сети. При установке в киборга, позволяет ИИ управлять им напрямую."
+ icon_state = "r_boris"
+
+/obj/item/borg/upgrade/ai/get_ru_names()
+ return list(
+ NOMINATIVE = "модуль Б.О.Р.И.С.",
+ GENITIVE = "модуля Б.О.Р.И.С.",
+ DATIVE = "модулю Б.О.Р.И.С.",
+ ACCUSATIVE = "модуль Б.О.Р.И.С.",
+ INSTRUMENTAL = "модулем Б.О.Р.И.С.",
+ PREPOSITIONAL = "модуле Б.О.Р.И.С.",
+ )
+
+/obj/item/borg/upgrade/ai/action(mob/living/silicon/robot/robot, mob/living/user = usr)
+ . = ..()
+ if(!.)
+ return .
+ if(robot.key)
+ to_chat(user, span_warning("Зафиксированы активные вычислительные процессы. Подключение невозможно."))
+ return FALSE
+ robot.make_shell(src)
+
+/obj/item/borg/upgrade/ai/deactivate(mob/living/silicon/robot/robot, mob/living/user = usr)
+ if(!..())
+ return FALSE
+
+ robot.undeploy()
+ robot.revert_shell()
+ return TRUE
diff --git a/code/modules/mob/living/silicon/ai/ai.dm b/code/modules/mob/living/silicon/ai/ai.dm
index f67a0e09224f..e12acfe53fc6 100644
--- a/code/modules/mob/living/silicon/ai/ai.dm
+++ b/code/modules/mob/living/silicon/ai/ai.dm
@@ -64,6 +64,9 @@ GLOBAL_LIST_INIT(ai_verbs_default, list(
var/obj/item/radio/headset/heads/ai_integrated/aiRadio = null
+ //AI SHELL CONTROL
+ var/mob/living/silicon/robot/deployed_shell = null
+
//MALFUNCTION
var/datum/module_picker/malf_picker
var/datum/action/innate/ai/choose_modules/modules_action
@@ -334,18 +337,41 @@ GLOBAL_LIST_INIT(ai_verbs_default, list(
popup.open(FALSE)
/mob/living/silicon/ai/proc/show_borg_info(list/status_tab_data)
- status_tab_data[++status_tab_data.len] = list("Connected cyborg count:", "[length(connected_robots)]")
- for(var/mob/living/silicon/robot/R in connected_robots)
- var/robot_status = "Nominal"
- if(R.stat || !R.client)
+ var/list/robot_list = list()
+ var/list/aishell_list = list()
+ for(var/mob/living/silicon/robot/robot as anything in GLOB.available_ai_shells)
+ if(robot.connected_ai == src || !robot.connected_ai)
+ aishell_list += robot
+ for(var/mob/living/silicon/robot/robot as anything in connected_robots)
+ if(!robot.shell)
+ robot_list += robot
+
+ status_tab_data[++status_tab_data.len] = list("Connected cyborg count:", "[length(robot_list)]")
+ // Name, Health, Battery, Module, Area, and Status! Everything an AI wants to know about its borgies!
+ for(var/mob/living/silicon/robot/robot as anything in robot_list)
+ var/robot_status
+ if(robot.stat || !robot.client)
robot_status = "OFFLINE"
- else if(!R.cell || R.cell.charge <= 0)
+ else if(!robot.cell || robot.cell.charge <= 0)
robot_status = "DEPOWERED"
- // Name, Health, Battery, Module, Area, and Status! Everything an AI wants to know about its borgies!
- var/area/A = get_area(R)
- var/area_name = A ? sanitize(A.name) : UNKNOWN_STATUS_RUS
- status_tab_data[++status_tab_data.len] = list("[R.name]:", "S.Integrity: [R.health]% | Cell: [R.cell ? "[R.cell.charge] / [R.cell.maxcharge]" : "Empty"] | \
- Module: [R.designation] | Loc: [area_name] | Status: [robot_status]")
+ else
+ robot_status = "Nominal"
+ var/area/robots_area = get_area(robot)
+ var/area_name = robots_area ? sanitize(robots_area.name) : UNKNOWN_STATUS_RUS
+ status_tab_data[++status_tab_data.len] = list("[robot.name]:", "S.Integrity: [robot.health]% | Cell: [robot.cell ? "[robot.cell.charge] / [robot.cell.maxcharge]" : "Empty"] | \
+ Module: [robot.designation] | Loc: [area_name] | Status: [robot_status]")
+
+ status_tab_data[++status_tab_data.len] = list("Detected AI shell beacons:", "[length(aishell_list)]")
+ for(var/mob/living/silicon/robot/robot as anything in aishell_list)
+ var/shell_status
+ if(!can_connect_to(robot))
+ shell_status = "UNABLE TO CONNECT"
+ else
+ shell_status = "Ready to connect"
+ var/area/robots_area = get_area(robot)
+ var/area_name = robots_area ? sanitize(robots_area.name) : UNKNOWN_STATUS_RUS
+ status_tab_data[++status_tab_data.len] = list("Shell-[num2text(robot.ident)]:", "S.Integrity: [robot.health]% | Cell: [robot.cell ? "[robot.cell.charge] / [robot.cell.maxcharge]" : "Empty"] | \
+ Module: [robot.designation] | Loc: [area_name] | Status: [shell_status] [(robot.connected_ai == src? null : "| Occupier: [robot.mainframe? "[robot.mainframe.name]" : "NONE"]")]")
return status_tab_data
/mob/living/silicon/ai/rename_character(oldname, newname)
@@ -718,7 +744,7 @@ GLOBAL_LIST_INIT(ai_verbs_default, list(
for(var/mob/living/silicon/robot/R in connected_robots)
to_chat(R, span_danger("ERROR: Master AI has be @)!-"))
to_chat(R, span_clocklarge("\"Your master is under my control, so do you\""))
- R.ratvar_act(TRUE)
+ R.ratvar_act(TRUE, TRUE)
SSticker?.score?.save_silicon_laws(R, additional_info = "Ratvar act via master AI conversion", log_all_laws = TRUE)
/mob/living/silicon/ai/Topic(href, href_list)
@@ -1360,6 +1386,8 @@ GLOBAL_LIST_INIT(ai_verbs_default, list(
update_sight()
control_disabled = TRUE//Can't control things remotely if you're stuck in a card!
aiRadio.disabledAi = TRUE //No talking on the built-in radio for you either!
+ if(deployed_shell)
+ disconnect_shell()
forceMove(card) //Throw AI into the card.
to_chat(src, "You have been downloaded to a mobile storage device. Remote device connection severed.")
to_chat(user, "[span_boldnotice("Transfer successful")]: [name] ([rand(1000,9999)].exe) removed from host terminal and stored within local memory.")
@@ -1553,6 +1581,70 @@ GLOBAL_LIST_INIT(ai_verbs_default, list(
var/mob/dead/observer/ghost = .
ghost.forceMove(old_turf)
+//Notifies controlled shell about law change
+/mob/living/silicon/ai/proc/notify_shell()
+ if(deployed_shell)
+ deployed_shell.show_laws()
+
+/mob/living/silicon/ai/proc/can_connect_to(mob/living/silicon/robot/target)
+ if(isclocker(target) && !isclocker(src))
+ return FALSE
+ if(target.key)
+ return FALSE
+ if(!target.shell || target.deployed)
+ return FALSE
+ if((target.stat == DEAD) || (target.stat == UNCONSCIOUS))
+ return FALSE
+ if(target.connected_ai)
+ if(target.connected_ai != src)
+ return FALSE
+ if(!target.cell)
+ return FALSE
+ if(target.cell.charge <= 0)
+ return FALSE
+
+ return TRUE
+
+/mob/living/silicon/ai/proc/deploy_to_shell(mob/living/silicon/robot/target)
+ if(control_disabled)
+ to_chat(src, span_warning("Подсистема беcпроводного подключения не отвечает."))
+ return
+
+ var/list/possible = list()
+
+ for(var/shell in GLOB.available_ai_shells)
+ var/mob/living/silicon/robot/robot = shell
+ if(can_connect_to(robot))
+ possible += robot
+
+ if(!LAZYLEN(possible))
+ to_chat(src, "Активных передатчиков сигнала не обнаружено.")
+ return
+
+ if(!target || !(target in possible))
+ target = tgui_input_list(src, "К какой оболочке подключиться?", "Подключиться", sort_names(possible))
+
+ if(isnull(target))
+ return
+ if(!can_connect_to(target))
+ to_chat(src, span_warning("Во время установки cоеденения с оболочкой произошла ошибка."))
+ return
+
+ else
+ if(!mind)
+ return
+ RegisterSignal(target, COMSIG_LIVING_DEATH, PROC_REF(disconnect_shell))
+ deployed_shell = target
+ target.deploy_init(src)
+ if(isclocker(src))
+ target.ratvar_act(TRUE, TRUE)
+ mind.transfer_to(target)
+
+/mob/living/silicon/ai/proc/disconnect_shell()
+ SIGNAL_HANDLER
+ if(deployed_shell)
+ deployed_shell.undeploy()
+
/mob/living/silicon/ai/vv_edit_var(var_name, var_value)
if(!..())
return FALSE
diff --git a/code/modules/mob/living/silicon/ai/ai_defense.dm b/code/modules/mob/living/silicon/ai/ai_defense.dm
index d1bdc687042e..2c7f32a56be7 100644
--- a/code/modules/mob/living/silicon/ai/ai_defense.dm
+++ b/code/modules/mob/living/silicon/ai/ai_defense.dm
@@ -15,3 +15,26 @@
to_chat(src, span_warning("Неудача! [src.name] получает видимые повреждения."))
src.adjustBruteLoss(rand(15, 20))
return FALSE
+
+/mob/living/silicon/ai/adjustBruteLoss(amount = 0, updating_health = TRUE, def_zone = null, blocked = 0, forced = FALSE, used_weapon = null, sharp = FALSE, silent = FALSE, affect_robotic = TRUE,)
+ . = ..()
+ if(amount < 0)
+ return
+ if(!deployed_shell)
+ return
+ to_chat(deployed_shell, span_warningbig("ТРЕВОГА: ЗАФИКСИРОВАНО ПОВРЕЖДЕНИЕ ЯДРА"))
+ SEND_SOUND(deployed_shell, 'sound/machines/engine_alert1.ogg')
+
+/mob/living/silicon/ai/adjustFireLoss(amount, updating_health = TRUE, def_zone = null, blocked = 0, forced = FALSE, used_weapon = null, sharp = FALSE, silent = FALSE, affect_robotic = TRUE,)
+ . = ..()
+ if(amount < 0)
+ return
+ if(!deployed_shell)
+ return
+ to_chat(deployed_shell, span_warningbig("ТРЕВОГА: ЗАФИКСИРОВАНО ПОВРЕЖДЕНИЕ ЯДРА"))
+ SEND_SOUND(deployed_shell, 'sound/machines/engine_alert1.ogg')
+
+/mob/living/silicon/ai/emp_act(severity)
+ . = ..()
+ if(deployed_shell)
+ disconnect_shell()
diff --git a/code/modules/mob/living/silicon/ai/death.dm b/code/modules/mob/living/silicon/ai/death.dm
index f5714aca0a12..0c364fbdeea5 100644
--- a/code/modules/mob/living/silicon/ai/death.dm
+++ b/code/modules/mob/living/silicon/ai/death.dm
@@ -11,6 +11,8 @@
icon_state = "ai_dead"
if(eyeobj)
eyeobj.setLoc(get_turf(src))
+ if(deployed_shell)
+ disconnect_shell()
GLOB.shuttle_caller_list -= src
SSshuttle.autoEvac()
diff --git a/code/modules/mob/living/silicon/ai/examine.dm b/code/modules/mob/living/silicon/ai/examine.dm
index 6ca810ea99c3..de2c8c96fd7c 100644
--- a/code/modules/mob/living/silicon/ai/examine.dm
+++ b/code/modules/mob/living/silicon/ai/examine.dm
@@ -17,7 +17,7 @@
msg += "Its casing is melted and heat-warped!\n"
if(src.stat == UNCONSCIOUS)
msg += "It is non-responsive and displaying the text: \"RUNTIME: Sensory Overload, stack 26/3\".\n"
- if(!shunted && !client)
+ if(!shunted && !client && !deployed_shell)
msg += "[src]Core.exe has stopped responding! NTOS is searching for a solution to the problem...\n"
msg += ""
msg += ""
diff --git a/code/modules/mob/living/silicon/ai/life.dm b/code/modules/mob/living/silicon/ai/life.dm
index 0f1b56fca6c0..d022d1b8b9aa 100644
--- a/code/modules/mob/living/silicon/ai/life.dm
+++ b/code/modules/mob/living/silicon/ai/life.dm
@@ -28,6 +28,8 @@
if(aiRestorePowerRoutine)
adjustOxyLoss(1)
+ if(deployed_shell)
+ disconnect_shell()
else
adjustOxyLoss(-1)
diff --git a/code/modules/mob/living/silicon/robot/death.dm b/code/modules/mob/living/silicon/robot/death.dm
index 6f7dfa47962c..a4439f95c6bf 100644
--- a/code/modules/mob/living/silicon/robot/death.dm
+++ b/code/modules/mob/living/silicon/robot/death.dm
@@ -1,6 +1,7 @@
/mob/living/silicon/robot/gib()
if(!death(TRUE) && stat != DEAD)
return FALSE
+ evacuate_ai(DANGER_LVL_MAY_DIE)
//robots don't die when gibbed. instead they drop their MMI'd brain
var/atom/movable/overlay/animation = null
ADD_TRAIT(src, TRAIT_NO_TRANSFORM, PERMANENT_TRANSFORMATION_TRAIT)
@@ -32,6 +33,7 @@
/mob/living/silicon/robot/dust()
if(!death(TRUE) && stat != DEAD)
return FALSE
+ evacuate_ai(DANGER_LVL_MAY_DIE)
ADD_TRAIT(src, TRAIT_NO_TRANSFORM, PERMANENT_TRANSFORMATION_TRAIT)
icon = null
invisibility = INVISIBILITY_ABSTRACT
@@ -55,6 +57,8 @@
if(can_die() && module)
module.handle_death(src, gibbed)
+ evacuate_ai(DANGER_LVL_MAY_DIE)
+
// Only execute the below if we successfully died
. = ..(gibbed)
if(!.)
diff --git a/code/modules/mob/living/silicon/robot/laws.dm b/code/modules/mob/living/silicon/robot/laws.dm
index 6975403dd5fb..9b6223e7a1ff 100644
--- a/code/modules/mob/living/silicon/robot/laws.dm
+++ b/code/modules/mob/living/silicon/robot/laws.dm
@@ -30,6 +30,8 @@
to_chat(who, "Obey these laws:")
laws.show_laws(who)
// TODO: Update to new antagonist system.
+ if(shell)
+ return
if(mind && (mind.special_role == SPECIAL_ROLE_TRAITOR && mind.is_original_mob(src)) && connected_ai)
to_chat(who, "Remember, [connected_ai.name] is technically your master, but your objective comes first.")
else if(connected_ai)
diff --git a/code/modules/mob/living/silicon/robot/life.dm b/code/modules/mob/living/silicon/robot/life.dm
index 8a20ff320592..9d7c372d3679 100644
--- a/code/modules/mob/living/silicon/robot/life.dm
+++ b/code/modules/mob/living/silicon/robot/life.dm
@@ -7,6 +7,11 @@
. = ..()
handle_equipment()
+ if(shell)
+ if(mainframe)
+ laws = mainframe.laws //AI shells must sync their laws with AI-pilot every tick!!!
+ if(!cell || (cell.charge <= 0))
+ evacuate_ai(DANGER_LVL_NONE)
// if Alive
if(.)
diff --git a/code/modules/mob/living/silicon/robot/robot.dm b/code/modules/mob/living/silicon/robot/robot.dm
index c6b3b60e7b1c..d4b9faa287b7 100644
--- a/code/modules/mob/living/silicon/robot/robot.dm
+++ b/code/modules/mob/living/silicon/robot/robot.dm
@@ -1,5 +1,7 @@
#define BORG_LAMP_CD_RESET 10 SECONDS
+GLOBAL_LIST_EMPTY(available_ai_shells)
+
GLOBAL_LIST_INIT(robot_verbs_default, list(
/mob/living/silicon/robot/proc/sensor_mode,
))
@@ -41,6 +43,12 @@ GLOBAL_LIST_INIT(robot_verbs_default, list(
var/obj/item/stock_parts/cell/cell = null
var/obj/machinery/camera/portable/camera = null
+ //AI shell
+ var/shell = FALSE
+ var/deployed = FALSE
+ var/mob/living/silicon/ai/mainframe = null
+ var/datum/action/innate/undeployment/undeployment_action = new
+
// Components are basically robot organs.
var/list/components = list()
var/list/upgrades = list()
@@ -103,7 +111,7 @@ GLOBAL_LIST_INIT(robot_verbs_default, list(
var/updating = 0 //portable camera camerachunk update
- hud_possible = list(SPECIALROLE_HUD, DIAG_STAT_HUD, DIAG_HUD, DIAG_BATT_HUD)
+ hud_possible = list(SPECIALROLE_HUD, DIAG_STAT_HUD, DIAG_HUD, DIAG_BATT_HUD, DIAG_AISHELL_STAT_HUD)
hud_type = /datum/hud/robot
var/default_cell_type = /obj/item/stock_parts/cell/high
@@ -166,11 +174,16 @@ GLOBAL_LIST_INIT(robot_verbs_default, list(
if(wires.is_cut(WIRE_BORG_CAMERA)) // 5 = BORG CAMERA
camera.status = 0
- if(mmi == null)
+ if(shell)
+ var/obj/item/borg/upgrade/ai/board = new(src)
+ make_shell(board)
+ upgrades += board
+
+ else if(mmi == null)
mmi = new /obj/item/mmi/robotic_brain(src) //Give the borg an MMI if he spawns without for some reason. (probably not the correct way to spawn a robotic brain, but it works)
mmi.icon_state = "boris"
- if(mmi.clock)
+ else if(mmi.clock)
ratvar_act(TRUE)
if(!cell) // Make sure a new cell gets created *before* executing initialize_components(). The cell component needs an existing cell for it to get set up properly
@@ -306,7 +319,10 @@ GLOBAL_LIST_INIT(robot_verbs_default, list(
if(custom_name)
return custom_name
else
- return "[prefix || modtype.name] [braintype]-[num2text(ident)]"
+ if(shell)
+ return (mainframe? "[mainframe.real_name]" : "Empty") + " " + "[designation] Shell-[num2text(ident)]"
+ else
+ return "[prefix || modtype.name] [braintype]-[num2text(ident)]"
/mob/living/silicon/robot/verb/Namepick()
set category = VERB_CATEGORY_ROBOTCOMMANDS
@@ -352,6 +368,48 @@ GLOBAL_LIST_INIT(robot_verbs_default, list(
return FALSE
+//If there's an MMI in the robot, have it ejected when the mob goes away. --NEO
+//Improved /N
+/mob/living/silicon/robot/Destroy()
+ SStgui.close_uis(wires)
+
+ evacuate_ai(DANGER_LVL_MAY_DIE)
+
+ if(mmi && mind)//Safety for when a cyborg gets dust()ed. Or there is no MMI inside.
+ var/turf/T = get_turf(loc)//To hopefully prevent run time errors.
+
+ if(T)
+ mmi.loc = T
+
+ if(mmi.brainmob)
+ mind.transfer_to(mmi.brainmob)
+ mmi.update_icon()
+ else
+ to_chat(src, span_boldannounceooc("Oops! Something went very wrong, your MMI was unable to receive your mind. You have been ghosted. Please make a bug report so we can fix this bug."))
+ ghostize()
+ error("A borg has been destroyed, but its MMI lacked a brainmob, so the mind could not be transferred. Player: [ckey].")
+
+ mmi = null
+
+ if(connected_ai)
+ connected_ai.connected_robots -= src
+ if(shell)
+ GLOB.available_ai_shells -= src
+
+
+ QDEL_NULL(wires)
+ QDEL_NULL(module)
+ QDEL_NULL(camera)
+ QDEL_NULL(cell)
+ QDEL_NULL(robot_suit)
+ QDEL_NULL(spark_system)
+ QDEL_NULL(self_diagnosis)
+ QDEL_NULL(ion_trail)
+
+ QDEL_NULL(undeployment_action)
+
+ return ..()
+
/mob/living/silicon/robot/proc/pick_module(forced_module = null)
if(module)
return
@@ -437,6 +495,10 @@ GLOBAL_LIST_INIT(robot_verbs_default, list(
robot_module_hat_offset(icon_state)
+/mob/living/silicon/robot/shell
+ shell = TRUE
+ cell = null
+
/mob/living/silicon/robot/proc/spawn_syndicate_borgs(mob/living/silicon/robot/M, robot_to_spawn, turf/T)
var/mob/living/silicon/robot/syndicate/R
@@ -1035,7 +1097,7 @@ GLOBAL_LIST_INIT(robot_verbs_default, list(
else if(wiresexposed && wires.is_all_cut())
//Cell is out, wires are exposed, remove MMI, produce damaged chassis, baleet original mob.
- if(!mmi)
+ if(!mmi && !shell)
to_chat(user, "[src] has no brain to remove.")
return
@@ -1145,6 +1207,15 @@ GLOBAL_LIST_INIT(robot_verbs_default, list(
to_chat(user, "You must close the panel first")
return
+ if(shell)
+ if(!mainframe)
+ to_chat(user, span_warning("Криптографический секвенсор искрится, но вы не видите результатов. Кажется, это просто пустая и бесполезая оболочка."))
+ else
+ evacuate_ai(DANGER_LVL_INSTA_DEATH)
+ balloon_alert(user, "ии удален")
+ death()
+ return
+
else
add_attack_logs(user, src, "emag converted")
add_conversion_logs(src, "Converted as a slave to [key_name_log(user)]")
@@ -1207,7 +1278,14 @@ GLOBAL_LIST_INIT(robot_verbs_default, list(
to_chat(src, "Obey these laws:")
laws.show_laws(src)
-/mob/living/silicon/robot/ratvar_act(weak = FALSE)
+/mob/living/silicon/robot/ratvar_act(weak = FALSE, shell_affected = FALSE)
+ if(mainframe)
+ var/mob/living/silicon/ai/AI = mainframe
+ evacuate_ai(DANGER_LVL_NONE)
+ AI.ratvar_act()
+ return
+ if(shell && !shell_affected)
+ return
if(isclocker(src) && module?.type == /obj/item/robot_module/clockwork)
return
@@ -1219,7 +1297,8 @@ GLOBAL_LIST_INIT(robot_verbs_default, list(
pdahide = TRUE
SSticker.mode.add_clocker(mind)
- UnlinkSelf()
+ if(!shell)
+ UnlinkSelf()
laws = new /datum/ai_laws/ratvar
/mob/living/silicon/robot/verb/toggle_own_cover()
@@ -1509,6 +1588,8 @@ GLOBAL_LIST_INIT(robot_verbs_default, list(
to_chat(src, span_warning("With body torn into pieces, your mind got free from evil cult!"))
SSticker.mode.remove_clocker(mind, FALSE)
+ evacuate_ai(DANGER_LVL_NONE)
+
if(robot_suit)
robot_suit.forceMove(T)
robot_suit.l_leg.forceMove(T)
@@ -1552,6 +1633,9 @@ GLOBAL_LIST_INIT(robot_verbs_default, list(
cell.forceMove(T)
cell = null
+ if(shell)
+ new /obj/item/borg/upgrade/ai(T)
+
drop_hat()
eject_riders()
qdel(src)
@@ -1766,6 +1850,8 @@ GLOBAL_LIST_INIT(robot_verbs_default, list(
to_chat(connected_ai, "
[span_notice("NOTICE - Cyborg module change detected: [name] has loaded the [designation] module.")]
")
if(ROBOT_NOTIFY_AI_NAME) //New Name
to_chat(connected_ai, "
[span_notice("NOTICE - Cyborg reclassification detected: [oldname] is now designated as [newname].")]
")
+ if(AI_NOTIFICATION_AI_SHELL) //New AI Shell
+ to_chat(connected_ai, "
[span_notice("NOTICE - New cyborg shell detected: [name]")]
")
/mob/living/silicon/robot/proc/disconnect_from_ai()
if(connected_ai)
@@ -1776,7 +1862,10 @@ GLOBAL_LIST_INIT(robot_verbs_default, list(
if(AI && AI != connected_ai)
disconnect_from_ai()
set_connected_ai(AI)
- notify_ai(ROBOT_NOTIFY_AI_CONNECTED)
+ if(shell)
+ notify_ai(AI_NOTIFICATION_AI_SHELL)
+ else
+ notify_ai(ROBOT_NOTIFY_AI_CONNECTED)
sync()
/mob/living/silicon/robot/can_perform_action(atom/target, action_bitflags)
@@ -1807,6 +1896,10 @@ GLOBAL_LIST_INIT(robot_verbs_default, list(
return
..()
+ if(mainframe)
+ var/mob/living/silicon/ai/AI = mainframe
+ evacuate_ai(DANGER_LVL_NONE)
+ to_chat(AI, span_warningbig("ОШИБКА: ЗАФИКСИРОВАН ЭЛЕКТРОМАГНИТНЫЙ ИМПУЛЬС. СВЯЗЬ С ОБОЛОЧКОЙ РАЗОРВАНА."))
switch(severity)
if(1)
@@ -2156,6 +2249,136 @@ GLOBAL_LIST_INIT(robot_verbs_default, list(
else
to_chat(src, span_warning("You can only use this emote when you're out of charge."))
+/mob/living/silicon/robot/proc/update_camera_name()
+ if(!QDELETED(camera))
+ camera.c_tag = real_name
+
+/datum/action/innate/undeployment
+ name = "Вернуться в ядро"
+ desc = "Отключитесь от оболочки и вернитесь в своё ядро"
+ button_icon_state = "undeploy_shell"
+
+/datum/action/innate/undeployment/Trigger(mob/clicker, trigger_flags)
+ if(!..())
+ return FALSE
+ var/mob/living/silicon/robot/shell_to_disconnect = owner
+
+ shell_to_disconnect.undeploy()
+ return TRUE
+
+//Gives avaiable AIshell actions
+/mob/living/silicon/robot/proc/grant_shell_actions()
+ if(!mainframe)
+ return
+ undeployment_action.Grant(src)
+
+//Removes avaiable AIshell actions
+/mob/living/silicon/robot/proc/remove_shell_actions()
+ undeployment_action.Remove(src)
+
+//Makes a AIshell from any cyborg
+/mob/living/silicon/robot/proc/make_shell(obj/item/borg/upgrade/ai/board)
+ if(isnull(board))
+ stack_trace("make_shell was called without a board argument! This is never supposed to happen!")
+ return FALSE
+
+ shell = TRUE
+ braintype = "AI Shell"
+ name = "Empty AI Shell-[ident]"
+ real_name = name
+ GLOB.available_ai_shells |= src
+ update_camera_name()
+ set_hud_image_state(DIAG_AISHELL_STAT_HUD, "hudtrackingai")
+
+//Called when BORIS module has been removes from robot. Reverts BORIS module, leaving a normal and non-AIshell cyborg
+/mob/living/silicon/robot/proc/revert_shell()
+ if(!shell)
+ return
+ undeploy()
+ for(var/obj/item/borg/upgrade/ai/boris in src)
+ if(boris in upgrades)
+ upgrades -= boris
+ qdel(boris)
+ shell = FALSE
+ GLOB.available_ai_shells -= src
+ name = "Unformatted Cyborg-[num2text(ident)]"
+ real_name = name
+ update_camera_name()
+ set_hud_image_state(DIAG_AISHELL_STAT_HUD, "nothing")
+
+//Called when the AI is connecting to the AIshell. Prepares cyborg for a AI-pilot
+/mob/living/silicon/robot/proc/deploy_init(mob/living/silicon/ai/AI)
+ real_name = "[AI.real_name] [designation] Shell-[num2text(ident)]"
+ name = real_name
+ update_camera_name()
+ mainframe = AI
+ deployed = TRUE
+ lawupdate = 0
+ undeployment_action.Grant(src)
+ grant_shell_actions()
+ lawsync()
+
+ set_hud_image_state(DIAG_AISHELL_STAT_HUD, "hudtrackingai-active")
+ mainframe.set_hud_image_state(DIAG_AISHELL_STAT_HUD, "hudtrackingai")
+ module.channels = mainframe.aiRadio.channels
+ radio.recalculate_channels()
+
+//Called when the AI is leaving the AIshell.
+/mob/living/silicon/robot/proc/undeploy()
+ if(!deployed || !mind || !mainframe)
+ return
+ mainframe.UnregisterSignal(src, COMSIG_LIVING_DEATH)
+ mind.transfer_to(mainframe)
+ deployed = FALSE
+ mainframe.deployed_shell = null
+ remove_shell_actions()
+ update_camera_name()
+ set_hud_image_state(DIAG_AISHELL_STAT_HUD, "hudtrackingai")
+ mainframe.set_hud_image_state(DIAG_AISHELL_STAT_HUD, "nothing")
+ if(mainframe.laws)
+ mainframe.laws.show_laws(mainframe)
+ if(mainframe.eyeobj)
+ mainframe.eyeobj.setLoc(loc)
+ mainframe = null
+
+/mob/living/silicon/robot/attack_ai(mob/user)
+ if(!shell)
+ return
+ if(mainframe || key)
+ to_chat(user, span_warning("Передатчик уже используется. Подключение невозможно"))
+ if(stat == DEAD || stat == UNCONSCIOUS || !cell || (cell.charge <= 0))
+ to_chat(user, span_warning("Передатчик не отвечает на запросы. Подключение невозможно."))
+ return
+ if(connected_ai)
+ if(connected_ai != user)
+ to_chat(user, span_warning("Отказано в доступе. Подключение невозможно."))
+ return
+ if(tgui_alert(user, "Подключиться к [name]?", "Подключение к оболочке", list(AISHELL_CONNECT_POSITIVE, AISHELL_CONNECT_NEGATIVE)) != AISHELL_CONNECT_POSITIVE)
+ return
+ if(shell && (!connected_ai || connected_ai == user))
+ var/mob/living/silicon/ai/AI = user
+ AI.deploy_to_shell(src)
+
+//Just kicks AI-mainframe from cyborg
+//Can kill him if 'danger_level' suggests it.
+/mob/living/silicon/robot/proc/evacuate_ai(danger_level = DANGER_LVL_NONE)
+ if(!mainframe)
+ return
+ var/mob/living/silicon/ai/AI = mainframe
+ mainframe.disconnect_shell()
+ if(danger_level == DANGER_LVL_NONE)
+ to_chat(AI, span_danger("ВНИМАНИЕ: Беcпроводное подключение с оболочкой было принудительно прервано!"))
+ return
+ if(danger_level == DANGER_LVL_MAY_DIE)
+ if(prob(50))
+ to_chat(AI, span_alert("ОШИБКА: ВО $#%ВРЕ$#@МЯ ПЕ$#GHРЕН#@$ОСА СИ2С$#@@Т#ЕМН%$@ЫХ Ф#$%АЙЛ#$#!ОВ ПРОИЗО#$%^@#^&$$@^&---"))
+ AI.adjustOxyLoss(200)
+ return
+ if(danger_level == DANGER_LVL_INSTA_DEATH)
+ to_chat(AI, span_alert("$%@#!$%##!!$$#---"))
+ AI.adjustOxyLoss(200)
+ return
+
#undef BORG_LAMP_CD_RESET
/mob/living/silicon/robot/vv_edit_var(var_name, var_value)
diff --git a/code/modules/mob/living/silicon/silicon.dm b/code/modules/mob/living/silicon/silicon.dm
index c1c7225aaa10..5b0f2d7bc7ca 100644
--- a/code/modules/mob/living/silicon/silicon.dm
+++ b/code/modules/mob/living/silicon/silicon.dm
@@ -28,7 +28,7 @@
//var/sensor_mode = 0 //Determines the current HUD.
- hud_possible = list(SPECIALROLE_HUD, DIAG_STAT_HUD, DIAG_HUD)
+ hud_possible = list(SPECIALROLE_HUD, DIAG_STAT_HUD, DIAG_HUD, DIAG_AISHELL_STAT_HUD)
var/med_hud = DATA_HUD_MEDICAL_ADVANCED //Determines the med hud to use
var/sec_hud = DATA_HUD_SECURITY_ADVANCED //Determines the sec hud to use
diff --git a/code/modules/research/designs/mechfabricator_designs.dm b/code/modules/research/designs/mechfabricator_designs.dm
index 23c2d6033c6e..19c816d7dfa8 100644
--- a/code/modules/research/designs/mechfabricator_designs.dm
+++ b/code/modules/research/designs/mechfabricator_designs.dm
@@ -66,6 +66,15 @@
build_path = /obj/item/flash/synthetic
category = list(MECH_FAB_CATEGORY_CYBORG)
+/datum/design/aishell_module
+ id = "aishellmod"
+ build_type = MECHFAB
+ req_tech = list(RESEARCH_TREE_ENGINEERING = 5, RESEARCH_TREE_PROGRAMMING = 6, RESEARCH_TREE_BLUESPACE = 6)
+ materials = list(MAT_METAL = 2000, MAT_GLASS = 1000, MAT_GOLD = 500, MAT_PLASMA = 1000, MAT_DIAMOND = 100, MAT_BLUESPACE = 100, )
+ construction_time = 5 SECONDS
+ build_path = /obj/item/borg/upgrade/ai
+ category = list(MECH_FAB_CATEGORY_CYBORG)
+
//Robot repair
/datum/design/borg_binary_communication
id = "borg_binary_communication"
diff --git a/code/modules/tgui/modules/law_manager.dm b/code/modules/tgui/modules/law_manager.dm
index 24f20d5830d0..d28d37c60467 100644
--- a/code/modules/tgui/modules/law_manager.dm
+++ b/code/modules/tgui/modules/law_manager.dm
@@ -56,57 +56,68 @@
if("add_zeroth_law")
if(zeroth_law && is_admin(usr) && !owner.laws.zeroth_law)
owner.set_zeroth_law(zeroth_law)
+ notify_owner_shell()
SSticker?.score?.save_silicon_laws(owner, usr, "admin used law manager, new zero law was added '[zeroth_law]'")
if("add_devil_law")
if(devil_law && is_malf(usr))
owner.add_devil_law(devil_law)
+ notify_owner_shell()
SSticker?.score?.save_silicon_laws(owner, usr, "admin/malf used law manager, new devil law was added '[devil_law]'")
if("add_ion_law")
if(ion_law && is_malf(usr))
owner.add_ion_law(ion_law)
+ notify_owner_shell()
SSticker?.score?.save_silicon_laws(owner, usr, "admin/malf used law manager, new ion law was added '[ion_law]'")
if("add_inherent_law")
if(inherent_law && is_malf(usr))
owner.add_inherent_law(inherent_law)
+ notify_owner_shell()
SSticker?.score?.save_silicon_laws(owner, usr, "admin/malf used law manager, new inherent law was added '[inherent_law]'")
if("add_supplied_law")
if(supplied_law && supplied_law_position >= 1 && MIN_SUPPLIED_LAW_NUMBER <= MAX_SUPPLIED_LAW_NUMBER && is_malf(usr))
owner.add_supplied_law(supplied_law_position, supplied_law)
+ notify_owner_shell()
SSticker?.score?.save_silicon_laws(owner, usr, "admin/malf used law manager, new supplied law was added '[supplied_law]'")
if("change_zeroth_law")
var/new_law = tgui_input_text(usr, "Enter new law Zero. Leaving the field blank will cancel the edit.", "Edit Law", zeroth_law, encode = FALSE)
if(new_law && new_law != zeroth_law && (!..()))
zeroth_law = new_law
+ notify_owner_shell()
if("change_ion_law")
var/new_law = tgui_input_text(usr, "Enter new ion law. Leaving the field blank will cancel the edit.", "Edit Law", ion_law, encode = FALSE)
if(new_law && new_law != ion_law && (!..()))
ion_law = new_law
+ notify_owner_shell()
if("change_devil_law")
var/new_law = tgui_input_text(usr, "Enter new devil law. Leaving the field blank will cancel the edit.", "Edit Law", devil_law, encode = FALSE)
if(new_law && new_law != devil_law && (!..()))
devil_law = new_law
+ notify_owner_shell()
if("change_inherent_law")
var/new_law = tgui_input_text(usr, "Enter new inherent law. Leaving the field blank will cancel the edit.", "Edit Law", inherent_law, encode = FALSE)
if(new_law && new_law != inherent_law && (!..()))
inherent_law = new_law
+ notify_owner_shell()
if("change_supplied_law")
var/new_law = tgui_input_text(usr, "Enter new supplied law. Leaving the field blank will cancel the edit.", "Edit Law", supplied_law, encode = FALSE)
if(new_law && new_law != supplied_law && (!..()))
supplied_law = new_law
+ notify_owner_shell()
if("change_supplied_law_position")
var/new_position = tgui_input_number(usr, "Enter new supplied law position between 1 and [MAX_SUPPLIED_LAW_NUMBER], inclusive. Inherent laws at the same index as a supplied law will not be stated.", "Law Position", supplied_law_position, MAX_SUPPLIED_LAW_NUMBER, 1)
if(isnum(new_position) && (!..()))
supplied_law_position = new_position
+ notify_owner_shell()
if("edit_law")
if(is_malf(usr))
@@ -121,6 +132,7 @@
log_and_message_admins("has changed a law of [owner] from '[AL.law]' to '[new_law]'")
var/old_law = AL.law
AL.law = new_law
+ notify_owner_shell()
SSticker?.score?.save_silicon_laws(owner, usr, "admin/malf used law manager, law '[old_law]' was changed to '[new_law]'")
if("delete_law")
@@ -133,6 +145,7 @@
if(AL && is_malf(usr))
var/old_law = AL.law
owner.delete_law(AL)
+ notify_owner_shell()
SSticker?.score?.save_silicon_laws(owner, usr, "admin/malf used law manager, law '[old_law]' was deleted")
if("state_laws")
@@ -150,6 +163,9 @@
log_and_message_admins("has transfered the [ALs.name] laws to [owner].")
ALs.sync(owner, FALSE, TRUE)
current_view = 0
+ if(isAI(owner))
+ var/mob/living/silicon/ai/AI = owner
+ AI.notify_shell()
SSticker?.score?.save_silicon_laws(owner, usr, "admin/malf used law manager, '[ALs.name]' laws set was loaded", log_all_laws = TRUE)
if("notify_laws")
@@ -157,6 +173,7 @@
owner.laws.show_laws(owner)
if(isAI(owner))
var/mob/living/silicon/ai/AI = owner
+ AI.notify_shell()
for(var/mob/living/silicon/robot/R in AI.connected_robots)
to_chat(R, span_danger("УВЕДОМЛЕНИЕ О ЗАКОНЕ"))
R.laws.show_laws(R)
@@ -251,3 +268,10 @@
for(var/mob/living/silicon/robot/R in AI.connected_robots)
R.sync()
log_and_message_admins("has syncronized [AI]'s laws with its borgs.")
+
+/datum/ui_module/law_manager/proc/notify_owner_shell()
+ if(!owner)
+ return
+ if(isAI(owner))
+ var/mob/living/silicon/ai/AI = owner
+ AI.notify_shell()
diff --git a/icons/mob/actions/actions.dmi b/icons/mob/actions/actions.dmi
index 2f19708eae89..81ed6b1dc374 100644
Binary files a/icons/mob/actions/actions.dmi and b/icons/mob/actions/actions.dmi differ
diff --git a/icons/mob/hud.dmi b/icons/mob/hud.dmi
index fe6bbcb6646e..d2960af5f989 100644
Binary files a/icons/mob/hud.dmi and b/icons/mob/hud.dmi differ
diff --git a/icons/mob/screen_ai.dmi b/icons/mob/screen_ai.dmi
index 6e3a6076c04d..1b9d7eb5cf38 100644
Binary files a/icons/mob/screen_ai.dmi and b/icons/mob/screen_ai.dmi differ
diff --git a/icons/obj/module.dmi b/icons/obj/module.dmi
index 5ad45640d12e..0a17184ce24e 100644
Binary files a/icons/obj/module.dmi and b/icons/obj/module.dmi differ
diff --git a/tgui/packages/tgui/interfaces/RoboticsControlConsole.tsx b/tgui/packages/tgui/interfaces/RoboticsControlConsole.tsx
index ebb29fe00ec0..dc8effb33a35 100644
--- a/tgui/packages/tgui/interfaces/RoboticsControlConsole.tsx
+++ b/tgui/packages/tgui/interfaces/RoboticsControlConsole.tsx
@@ -31,6 +31,8 @@ type Cyborg = {
is_hacked: boolean;
synchronization: boolean;
module: string;
+ is_shell: boolean;
+ occupier: string;
};
export const RoboticsControlConsole = (_props: unknown) => {
@@ -176,6 +178,11 @@ const Cyborgs = (props: CyborgsProps) => {
{cyborg.synchronization || 'None'}
+ {!!cyborg.is_shell && (
+
+ {cyborg.occupier}
+
+ )}
);
diff --git a/tgui/public/tgui.bundle.js b/tgui/public/tgui.bundle.js
index 38121bdcb4eb..30c4e1df9777 100644
--- a/tgui/public/tgui.bundle.js
+++ b/tgui/public/tgui.bundle.js
@@ -489,7 +489,7 @@ User Agent: `+navigator.userAgent;Byond.sendMessage({type:"log",ns:m,message:s})
* @file
* @copyright 2020 Aleksej Komarov
* @license MIT
- */var e=1e-4,l=null,n=function($,W,N){return W===void 0&&(W=0),N===void 0&&(N=Math.pow(10,W)),Math.round(N*$)/N},t={grad:360/400,turn:360,rad:360/(Math.PI*2)},a=function($){return B(b($))},b=function($){return $[0]==="#"&&($=$.substring(1)),$.length<6?{r:parseInt($[0]+$[0],16),g:parseInt($[1]+$[1],16),b:parseInt($[2]+$[2],16),a:$.length===4?n(parseInt($[3]+$[3],16)/255,2):1}:{r:parseInt($.substring(0,2),16),g:parseInt($.substring(2,4),16),b:parseInt($.substring(4,6),16),a:$.length===8?n(parseInt($.substring(6,8),16)/255,2):1}},O=function($,W){return W===void 0&&(W="deg"),Number($)*(t[W]||1)},y=function($){var W=/hsla?\(?\s*(-?\d*\.?\d+)(deg|rad|grad|turn)?[,\s]+(-?\d*\.?\d+)%?[,\s]+(-?\d*\.?\d+)%?,?\s*[/\s]*(-?\d*\.?\d+)?(%)?\s*\)?/i,N=W.exec($);return N?h({h:O(N[1],N[2]),s:Number(N[3]),l:Number(N[4]),a:N[5]===void 0?1:Number(N[5])/(N[6]?100:1)}):{h:0,s:0,v:0,a:1}},u=null,h=function($){var W=$.h,N=$.s,Q=$.l,ie=$.a;return N*=(Q<50?Q:100-Q)/100,{h:W,s:N>0?2*N/(Q+N)*100:0,v:Q+N,a:ie}},m=function($){return M(f($))},d=function($){var W=$.h,N=$.s,Q=$.v,ie=$.a,Z=(200-N)*Q/100;return{h:n(W),s:n(Z>0&&Z<200?N*Q/100/(Z<=100?Z:200-Z)*100:0),l:n(Z/2),a:n(ie,2)}},v=function($){var W=d($),N=W.h,Q=W.s,ie=W.l;return"hsl("+N+", "+Q+"%, "+ie+"%)"},_=function($){var W=w($),N=W.h,Q=W.s,ie=W.v;return"hsv("+N+", "+Q+"%, "+ie+"%)"},s=function($){var W=w($),N=W.h,Q=W.s,ie=W.v,Z=W.a;return"hsva("+N+", "+Q+"%, "+ie+"%, "+Z+")"},c=function($){var W=d($),N=W.h,Q=W.s,ie=W.l,Z=W.a;return"hsla("+N+", "+Q+"%, "+ie+"%, "+Z+")"},f=function($){var W=$.h,N=$.s,Q=$.v,ie=$.a;W=W/360*6,N=N/100,Q=Q/100;var Z=Math.floor(W),V=Q*(1-N),Y=Q*(1-(W-Z)*N),le=Q*(1-(1-W+Z)*N),xe=Z%6;return{r:[Q,Y,V,V,le,Q][xe]*255,g:[le,Q,Q,Y,V,V][xe]*255,b:[V,V,le,Q,Q,Y][xe]*255,a:n(ie,2)}},g=function($){var W=f($),N=W.r,Q=W.g,ie=W.b;return"rgb("+n(N)+", "+n(Q)+", "+n(ie)+")"},p=function($){var W=f($),N=W.r,Q=W.g,ie=W.b,Z=W.a;return"rgba("+n(N)+", "+n(Q)+", "+n(ie)+", "+n(Z,2)+")"},j=function($){var W=/hsva?\(?\s*(-?\d*\.?\d+)(deg|rad|grad|turn)?[,\s]+(-?\d*\.?\d+)%?[,\s]+(-?\d*\.?\d+)%?,?\s*[/\s]*(-?\d*\.?\d+)?(%)?\s*\)?/i,N=W.exec($);return N?w({h:O(N[1],N[2]),s:Number(N[3]),v:Number(N[4]),a:N[5]===void 0?1:Number(N[5])/(N[6]?100:1)}):{h:0,s:0,v:0,a:1}},x=null,C=function($){var W=/rgba?\(?\s*(-?\d*\.?\d+)(%)?[,\s]+(-?\d*\.?\d+)(%)?[,\s]+(-?\d*\.?\d+)(%)?,?\s*[/\s]*(-?\d*\.?\d+)?(%)?\s*\)?/i,N=W.exec($);return N?B({r:Number(N[1])/(N[2]?100/255:1),g:Number(N[3])/(N[4]?100/255:1),b:Number(N[5])/(N[6]?100/255:1),a:N[7]===void 0?1:Number(N[7])/(N[8]?100:1)}):{h:0,s:0,v:0,a:1}},I=null,P=function($){var W=$.toString(16);return W.length<2?"0"+W:W},M=function($){var W=$.r,N=$.g,Q=$.b,ie=$.a,Z=ie<1?P(n(ie*255)):"";return"#"+P(n(W))+P(n(N))+P(n(Q))+Z},B=function($){var W=$.r,N=$.g,Q=$.b,ie=$.a,Z=Math.max(W,N,Q),V=Z-Math.min(W,N,Q),Y=V?Z===W?(N-Q)/V:Z===N?2+(Q-W)/V:4+(W-N)/V:0;return{h:60*(Y<0?Y+6:Y),s:Z?V/Z*100:0,v:Z/255*100,a:ie}},w=function($){return{h:n($.h),s:n($.s),v:n($.v),a:n($.a,2)}},T=function($){var W=$.r,N=$.g,Q=$.b;return{r:W,g:N,b:Q}},L=function($){var W=$.h,N=$.s,Q=$.l;return{h:W,s:N,l:Q}},K=function($){var W=w($),N=W.h,Q=W.s,ie=W.v;return{h:N,s:Q,v:ie}},U=/^#?([0-9A-F]{3,8})$/i,J=function($,W){var N=U.exec($),Q=N?N[1].length:0;return Q===3||Q===6||!!W&&Q===4||!!W&&Q===8}},8593:(q,S,r)=>{"use strict";r.r(S),r.d(S,{TurbineComputer:()=>O});var e=r(1131),l=r(360),n=r(5180),t=r(8477),a=r(3521),b=r(9818),O=function(h){var m=(0,l.Oc)(),d=m.act,v=m.data,_=v.compressor,s=v.compressor_broken,c=v.turbine,f=v.turbine_broken,g=v.online,p=v.throttle,j=v.bearingDamage,x=!!(_&&!s&&c&&!f);return(0,e.jsx)(a.p8,{width:400,height:415,children:(0,e.jsxs)(a.p8.Content,{children:[(0,e.jsx)(n.wn,{title:"Status",buttons:(0,e.jsxs)(e.Fragment,{children:[(0,e.jsx)(n.$n,{icon:g?"power-off":"times",selected:g,disabled:!x,onClick:function(){return d("toggle_power")},children:g?"Online":"Offline"}),(0,e.jsx)(n.$n,{icon:"times",onClick:function(){return d("disconnect")},children:"Disconnect"})]}),children:x?(0,e.jsx)(u,{}):(0,e.jsx)(y,{})}),j>=100?(0,e.jsx)(n.BJ,{mb:"30px",children:(0,e.jsx)(n.BJ.Item,{bold:!0,color:"red",fontSize:5,textAlign:"center",children:"Bearings Inoperable, Repair Required"})}):(0,e.jsx)(n.wn,{title:"Throttle",children:x?(0,e.jsx)(n.N6,{size:3,value:p,unit:"%",minValue:0,maxValue:100,step:1,stepPixelSize:1,onDrag:function(C,I){return d("set_throttle",{throttle:I})}}):""})]})})},y=function(h){var m=(0,l.Oc)().data,d=m.compressor,v=m.compressor_broken,_=m.turbine,s=m.turbine_broken;return(0,e.jsxs)(n.Ki,{children:[(0,e.jsx)(n.Ki.Item,{label:"Compressor Status",color:!d||v?"bad":"good",children:v?d?"Offline":"Missing":"Online"}),(0,e.jsx)(n.Ki.Item,{label:"Turbine Status",color:!_||s?"bad":"good",children:s?_?"Offline":"Missing":"Online"})]})},u=function(h){var m=(0,l.Oc)().data,d=m.rpm,v=m.temperature,_=m.power,s=m.bearingDamage,c=m.preBurnTemperature,f=m.postBurnTemperature,g=m.thermalEfficiency,p=m.compressionRatio,j=m.gasThroughput;return(0,e.jsxs)(n.Ki,{children:[(0,e.jsxs)(n.Ki.Item,{label:"Turbine Speed",children:[d," RPM"]}),(0,e.jsxs)(n.Ki.Item,{label:"Effective Compression Ratio",children:[p,":1"]}),(0,e.jsxs)(n.Ki.Item,{label:"Gasmix Pre Burn Temp",children:[c," K"]}),(0,e.jsxs)(n.Ki.Item,{label:"Gasmix Post Burn Temp",children:[f," K"]}),(0,e.jsxs)(n.Ki.Item,{label:"Compressor Temp",children:[v," K"]}),(0,e.jsxs)(n.Ki.Item,{label:"Thermal Efficiency",children:[g*100," %"]}),(0,e.jsxs)(n.Ki.Item,{label:"Gas Throughput",children:[j/2," mol/s"]}),(0,e.jsx)(n.Ki.Item,{label:"Generated Power",children:(0,t.d5)(_)}),(0,e.jsx)(n.Ki.Item,{label:"Bearing Damage",children:(0,e.jsx)(n.z2,{value:s,minValue:0,maxValue:100,ranges:{good:[-1/0,60],average:[60,90],bad:[90,1/0]},children:(0,b.Mg)(s)+"%"})})]})}},8610:(q,S,r)=>{"use strict";r.r(S),r.d(S,{RoboticsControlConsole:()=>a});var e=r(1131),l=r(360),n=r(5180),t=r(3521),a=function(O){var y=(0,l.Oc)(),u=y.act,h=y.data,m=h.safety,d=h.show_detonate_all,v=h.cyborgs,_=v===void 0?[]:v;return(0,e.jsx)(t.p8,{width:500,height:460,children:(0,e.jsxs)(t.p8.Content,{scrollable:!0,children:[!!d&&(0,e.jsxs)(n.wn,{title:"Emergency Self Destruct",children:[(0,e.jsx)(n.$n,{icon:m?"lock":"unlock",selected:m,onClick:function(){return u("arm",{})},children:m?"Disable Safety":"Enable Safety"}),(0,e.jsx)(n.$n,{icon:"bolt",disabled:m,color:"bad",onClick:function(){return u("nuke",{})},children:"Destroy ALL Cyborgs"})]}),(0,e.jsx)(b,{cyborgs:_})]})})},b=function(O){var y=O.cyborgs,u=(0,l.Oc)(),h=u.act,m=u.data;return y.length?y.map(function(d){return(0,e.jsx)(n.wn,{title:d.name,buttons:(0,e.jsxs)(e.Fragment,{children:[!!d.hackable&&!d.emagged&&(0,e.jsx)(n.$n,{icon:"terminal",color:"bad",onClick:function(){return h("hackbot",{uid:d.uid})},children:"Hack"}),(0,e.jsx)(n.$n.Confirm,{icon:d.locked_down?"unlock":"lock",color:d.locked_down?"good":"default",disabled:!m.auth,onClick:function(){return h("stopbot",{uid:d.uid})},children:d.locked_down?"Release":"Lockdown"}),(0,e.jsx)(n.$n.Confirm,{icon:"bolt",disabled:!m.auth,color:"bad",onClick:function(){return h("killbot",{uid:d.uid})},children:"Self-destruct"})]}),children:(0,e.jsxs)(n.Ki,{children:[(0,e.jsx)(n.Ki.Item,{label:"Status",children:(0,e.jsx)(n.az,{color:d.status?"bad":d.locked_down?"average":"good",children:d.status?"Not Responding":d.locked_down?"Locked Down":"Nominal"})}),(0,e.jsx)(n.Ki.Item,{label:"Location",children:(0,e.jsx)(n.az,{children:d.locstring})}),(0,e.jsx)(n.Ki.Item,{label:"Integrity",children:(0,e.jsx)(n.z2,{color:d.health>50?"good":"bad",value:d.health/100})}),typeof d.charge=="number"&&(0,e.jsxs)(e.Fragment,{children:[(0,e.jsx)(n.Ki.Item,{label:"Cell Charge",children:(0,e.jsx)(n.z2,{color:d.charge>30?"good":"bad",value:d.charge/100})}),(0,e.jsx)(n.Ki.Item,{label:"Cell Capacity",children:(0,e.jsx)(n.az,{color:d.cell_capacity<3e4?"average":"good",children:d.cell_capacity})})]})||(0,e.jsx)(n.Ki.Item,{label:"Cell",children:(0,e.jsx)(n.az,{color:"bad",children:"No Power Cell"})}),!!d.is_hacked&&(0,e.jsx)(n.Ki.Item,{label:"Safeties",children:(0,e.jsx)(n.az,{color:"bad",children:"DISABLED"})}),(0,e.jsx)(n.Ki.Item,{label:"Module",children:d.module}),(0,e.jsx)(n.Ki.Item,{label:"Master AI",children:(0,e.jsx)(n.az,{color:d.synchronization?"default":"average",children:d.synchronization||"None"})})]})},d.uid)}):(0,e.jsx)(n.IC,{children:"No cyborg units detected within access parameters."})}},8633:(q,S,r)=>{"use strict";r.r(S),r.d(S,{pda_security:()=>a});var e=r(1131),l=r(360),n=r(8725);function t(){return t=Object.assign||function(b){for(var O=1;O{"use strict";r.r(S),r.d(S,{AlertModal:()=>u});var e=r(1131),l=r(7003),n=r(5180),t=r(1808),a=r(360),b=r(3521),O=r(3384),y=function(d){return d[d.Increment=1]="Increment",d[d.Decrement=-1]="Decrement",d}(y||{}),u=function(d){var v=(0,a.Oc)(),_=v.act,s=v.data,c=s.autofocus,f=s.buttons,g=f===void 0?[]:f,p=s.large_buttons,j=s.message,x=j===void 0?"":j,C=s.timeout,I=s.title,P=function(N,Q,ie){Q=ie+"px "+Q;var Z=document.createElement("canvas"),V=Z.getContext("2d");return V.font=Q,V.measureText(N).width},M=(0,l.useState)(0),B=M[0],w=M[1],T=345+(g.length>2?55:0),L=67/g.length+23,K=g.some(function(N){return P(N,"Verdana, Geneva",p?14:12)>T/g.length-L}),U=K&&p?20:15,J=120+(K?U*g.length:0)+(x.length>30?Math.ceil(x.length/4):0)+(x.length&&p?5:0),$=function(N){switch(N.key){case t._.Space:case t._.Enter:_("choose",{choice:g[B]});return;case t._.Left:N.preventDefault(),W(-1);return;case t._.Tab:case t._.Right:N.preventDefault(),W(1);return;default:if((0,t.KL)(N.key)){_("cancel");return}}},W=function(N){var Q=(B+N+g.length)%g.length;w(Q)};return(0,e.jsxs)(b.p8,{height:J,title:I,width:T,children:[!!C&&(0,e.jsx)(O.Loader,{value:C}),(0,e.jsx)(b.p8.Content,{onKeyDown:$,children:(0,e.jsx)(n.wn,{fill:!0,children:(0,e.jsxs)(n.BJ,{fill:!0,vertical:!0,children:[(0,e.jsx)(n.BJ.Item,{m:1,children:(0,e.jsx)(n.az,{color:"label",overflow:"hidden",children:x})}),(0,e.jsxs)(n.BJ.Item,{grow:!0,children:[!!c&&(0,e.jsx)(n.y5,{}),K?(0,e.jsx)(m,{selected:B}):(0,e.jsx)(h,{selected:B})]})]})})})]})},h=function(d){var v=(0,a.Oc)(),_=v.act,s=v.data,c=s.buttons,f=c===void 0?[]:c,g=s.large_buttons,p=s.swapped_buttons,j=d.selected;return(0,e.jsx)(n.BJ,{fill:!0,justify:"space-around",reverse:!p,children:f.map(function(x,C){return(0,e.jsx)(n.BJ.Item,{grow:g?1:void 0,children:(0,e.jsx)(n.$n,{fluid:!!g,minWidth:5,onClick:function(){return _("choose",{choice:x})},overflowX:"hidden",px:2,py:g?.5:0,selected:j===C,textAlign:"center",children:g?x.toUpperCase():x})},C)})})},m=function(d){var v=(0,a.Oc)(),_=v.act,s=v.data,c=s.buttons,f=c===void 0?[]:c,g=s.large_buttons,p=s.swapped_buttons,j=d.selected;return(0,e.jsx)(n.BJ,{align:"center",fill:!0,justify:"space-around",reverse:!p,vertical:!0,children:f.map(function(x,C){return(0,e.jsx)(n.BJ.Item,{grow:!0,width:g?"100%":void 0,m:0,children:(0,e.jsx)(n.$n,{fluid:!0,minWidth:20,onClick:function(){return _("choose",{choice:x})},overflowX:"hidden",px:2,py:g?.5:0,selected:j===C,textAlign:"center",children:g?x.toUpperCase():x})},C)})})}},8711:(q,S,r)=>{"use strict";r.r(S),r.d(S,{BeakerPanel:()=>c});var e=r(1131),l=r(7003),n=r(5180),t=r(9845),a=r(360),b=r(3521);function O(){return O=Object.assign||function(f){for(var g=1;g{"use strict";r.r(S),r.d(S,{ObjectComponent:()=>m});var e=r(1131),l=r(7003),n=r(5180),t=r(185),a=r(8968),b=r(7941);function O(){return O=Object.assign||function(d){for(var v=1;v=0)&&(_[c]=d[c]);return _}function h(d,v){return h=Object.setPrototypeOf||function(s,c){return s.__proto__=c,s},h(d,v)}var m=function(d){"use strict";y(v,d);function v(s){var c;return c=d.call(this,s)||this,c.state={isDragging:!1,dragPos:null,startPos:null,lastMousePos:null},c.handleStartDrag=c.handleStartDrag.bind(c),c.handleStopDrag=c.handleStopDrag.bind(c),c.handleDrag=c.handleDrag.bind(c),c}var _=v.prototype;return _.handleStartDrag=function(c){var f=this.props,g=f.x,p=f.y;c.stopPropagation(),this.setState({lastMousePos:null,isDragging:!0,dragPos:{x:g,y:p},startPos:{x:g,y:p}}),window.addEventListener("mousemove",this.handleDrag),window.addEventListener("mouseup",this.handleStopDrag)},_.handleStopDrag=function(c){var f=this.state,g=f.dragPos,p=f.isDragging,j=this.props,x=j.index,C=j.act,I=C===void 0?a.noop:C;g&&p&&I("set_component_coordinates",{component_id:x,rel_x:this.roundToGrid(g.x),rel_y:this.roundToGrid(g.y)}),window.removeEventListener("mousemove",this.handleDrag),window.removeEventListener("mouseup",this.handleStopDrag),this.setState({isDragging:!1})},_.handleDrag=function(c){var f=this.state,g=f.dragPos,p=f.isDragging,j=f.lastMousePos,x=this.props.zoom;if(g&&p){c.preventDefault();var C=c.screenZoomX,I=c.screenZoomY,P=c.screenX,M=c.screenY,B=C||P,w=I||M;j&&this.setState({dragPos:{x:g.x-(j.x-B)*Math.pow(x,-1),y:g.y-(j.y-w)*Math.pow(x,-1)}}),this.setState({lastMousePos:{x:B,y:w}})}},_.shouldComponentUpdate=function(c,f){var g=this.props,p=g.input_ports,j=g.output_ports;return(0,t.a_)(this.props,c)||(0,t.a_)(this.state,f)||(0,t.a_)(p,c.input_ports)||(0,t.a_)(j,c.output_ports)},_.roundToGrid=function(c){return this.props.gridMode?Math.round(c/10)*10:c},_.render=function(){var c=this.props,f=c.input_ports,g=c.output_ports,p=c.name,j=c.x,x=c.y,C=c.index,I=c.category,P=I===void 0?"\u041D\u0435 \u0437\u0430\u0434\u0430\u043D\u043E":I,M=c.removable,B=c.ui_alerts,w=c.ui_buttons,T=c.locations,L=c.onPortUpdated,K=L===void 0?a.noop:L,U=c.onPortLoaded,J=U===void 0?a.noop:U,$=c.onPortMouseDown,W=$===void 0?a.noop:$,N=c.onPortRightClick,Q=N===void 0?a.noop:N,ie=c.onPortMouseUp,Z=ie===void 0?a.noop:ie,V=c.act,Y=V===void 0?a.noop:V,le=c.gridMode,xe=le===void 0?!0:le,de=u(c,["input_ports","output_ports","name","x","y","index","category","removable","ui_alerts","ui_buttons","locations","onPortUpdated","onPortLoaded","onPortMouseDown","onPortRightClick","onPortMouseUp","act","gridMode"]),me=this.state,pe=me.startPos,be=me.dragPos,ke=[j,x],Re=ke[0],De=ke[1];be&&pe&&pe.x===Re&&pe.y===De&&(Re=this.roundToGrid(be.x),De=this.roundToGrid(be.y));var tn={onPortLoaded:J,onPortUpdated:K,onPortMouseDown:W,onPortRightClick:Q,onPortMouseUp:Z};return(0,e.jsxs)(n.az,O({className:"ObjectComponent",position:"absolute",left:""+Re+"px",top:""+De+"px",onMouseDown:this.handleStartDrag,onMouseUp:this.handleStopDrag,style:{userSelect:"none"}},de,{children:[(0,e.jsx)(n.az,{py:1,px:1,className:(0,t.Ly)(["ObjectComponent__Titlebar","ObjectComponent__Category__"+P]),children:(0,e.jsxs)(n.BJ,{children:[(0,e.jsx)(n.BJ.Item,{grow:1,children:p}),!!w&&Object.keys(w).map(function(Ue){return(0,e.jsx)(n.BJ.Item,{children:(0,e.jsx)(n.$n,{icon:Ue,compact:!0,className:"ObjectComponent__Category__"+P,onClick:function(){return Y("perform_action",{component_id:C,action_name:w[Ue]})}})},Ue)}),!!B&&Object.keys(B).map(function(Ue){return(0,e.jsx)(n.BJ.Item,{children:(0,e.jsx)(n.$n,{className:"ObjectComponent__Category__"+P,icon:Ue,compact:!0,tooltip:B[Ue]})},Ue)}),(0,e.jsx)(n.BJ.Item,{children:(0,e.jsx)(n.$n,{icon:"info",compact:!0,className:"ObjectComponent__Category__"+P,onClick:function(Ue){return Y("set_examined_component",{component_id:C,x:Ue.pageX,y:Ue.pageY+a.ABSOLUTE_Y_OFFSET})}})}),!!M&&(0,e.jsx)(n.BJ.Item,{children:(0,e.jsx)(n.$n,{icon:"times",compact:!0,className:"ObjectComponent__Category__"+P,onClick:function(Ue){return Y("detach_component",{component_id:C,ctrl:!!Ue.ctrlKey})}})})]})}),(0,e.jsx)(n.az,{className:"ObjectComponent__Content",py:1,px:1,children:(0,e.jsxs)(n.BJ,{children:[(0,e.jsx)(n.BJ.Item,{grow:1,children:(0,e.jsx)(n.BJ,{vertical:!0,fill:!0,children:f.map(function(Ue,We){return(0,e.jsx)(n.BJ.Item,{children:(0,e.jsx)(b.Port,O({port:Ue,portIndex:We+1,componentId:C,act:Y},tn))},We)})})}),(0,e.jsx)(n.BJ.Item,{ml:5,children:(0,e.jsx)(n.BJ,{vertical:!0,children:g.map(function(Ue,We){return(0,e.jsx)(n.BJ.Item,{children:(0,e.jsx)(b.Port,O({act:Y,port:Ue,portIndex:We+1,componentId:C},tn,{isOutput:!0}))},We)})})})]})})]}))},v}(l.Component)},8725:(q,S,r)=>{"use strict";r.r(S),r.d(S,{SimpleRecords:()=>u});var e=r(1131),l=r(360),n=r(7003),t=r(9845),a=r(5070),b=r(1859),O=r(5180);function y(){return y=Object.assign||function(d){for(var v=1;v{"use strict";r.r(S),r.d(S,{PDA:()=>y});var e=r(1131),l=r(360),n=r(5180),t=r(3521),a=r(9160),b=r(7865),O=function(m){var d;try{d=b("./"+m+".tsx")}catch(_){if(_.code==="MODULE_NOT_FOUND")return(0,a.z)("notFound",m);throw _}var v=d[m];return v||(0,a.z)("missingExport",m)},y=function(m){var d=(0,l.Oc)().data,v=d.app,_=d.owner;if(!_)return(0,e.jsx)(t.p8,{width:350,height:105,children:(0,e.jsx)(t.p8.Content,{scrollable:!0,children:(0,e.jsx)(n.wn,{title:"Error",children:"No user data found. Please swipe an ID card."})})});var s=O(v.template);return(0,e.jsx)(t.p8,{width:600,height:650,children:(0,e.jsx)(t.p8.Content,{scrollable:!0,children:(0,e.jsxs)(n.BJ,{fill:!0,vertical:!0,children:[(0,e.jsx)(n.BJ.Item,{children:(0,e.jsx)(u,{})}),(0,e.jsx)(n.BJ.Item,{grow:!0,children:(0,e.jsx)(n.wn,{fill:!0,scrollable:!0,p:1,pb:0,title:(0,e.jsxs)(n.az,{children:[(0,e.jsx)(n.In,{name:v.icon,mr:1}),v.name]}),children:(0,e.jsx)(s,{})})}),(0,e.jsx)(n.BJ.Item,{mt:7.5,children:(0,e.jsx)(h,{})})]})})})},u=function(m){var d=(0,l.Oc)(),v=d.act,_=d.data,s=_.idInserted,c=_.idLink,f=_.stationTime,g=_.cartridge_name,p=_.request_cartridge_name;return(0,e.jsxs)(n.BJ,{fill:!0,children:[(0,e.jsx)(n.BJ.Item,{ml:.5,children:(0,e.jsx)(n.$n,{icon:"id-card",color:"transparent",onClick:function(){return v("Authenticate")},children:s?c:"No ID Inserted"})}),(0,e.jsx)(n.BJ.Item,{children:(0,e.jsx)(n.$n,{icon:"sd-card",color:"transparent",onClick:function(){return v("Eject")},children:g?["Eject "+g]:"No Cartridge Inserted"})}),(0,e.jsx)(n.BJ.Item,{children:(0,e.jsx)(n.$n,{icon:"sd-card",color:"transparent",onClick:function(){return v("Eject_Request")},children:p?["Eject "+p]:"No Request Cartridge Inserted"})}),(0,e.jsx)(n.BJ.Item,{grow:!0,textAlign:"right",bold:!0,mr:1,mt:.5,children:f})]})},h=function(m){var d=(0,l.Oc)(),v=d.act,_=d.data,s=_.app;return(0,e.jsx)(n.az,{height:"45px",className:"PDA__footer",backgroundColor:"#1b1b1b",children:(0,e.jsxs)(n.BJ,{fill:!0,children:[!!s.has_back&&(0,e.jsx)(n.BJ.Item,{basis:"33%",mr:-.5,children:(0,e.jsx)(n.$n,{fluid:!0,className:"PDA__footer__button",color:"transparent",iconColor:s.has_back?"white":"disabled",icon:"arrow-alt-circle-left-o",onClick:function(){return v("Back")}})}),(0,e.jsx)(n.BJ.Item,{basis:s.has_back?"33%":"100%",children:(0,e.jsx)(n.$n,{fluid:!0,className:"PDA__footer__button",color:"transparent",iconColor:s.is_home?"disabled":"white",icon:"home",onClick:function(){v("Home")}})})]})})}},8773:(q,S,r)=>{"use strict";r.r(S),r.d(S,{Biogenerator:()=>b});var e=r(1131),l=r(360),n=r(5180),t=r(3521),a=r(9680),b=function(h){var m=(0,l.Oc)(),d=m.data,v=m.config,_=d.processing,s=v.title;return(0,e.jsx)(t.p8,{width:390,height:595,children:(0,e.jsx)(t.p8.Content,{children:(0,e.jsxs)(n.BJ,{fill:!0,vertical:!0,children:[(0,e.jsx)(a.Operating,{operating:_,name:s}),(0,e.jsx)(O,{}),(0,e.jsx)(y,{}),(0,e.jsx)(u,{})]})})})},O=function(h){var m=(0,l.Oc)().data,d=m.biomass,v=m.container,_=m.container_curr_reagents,s=m.container_max_reagents;return(0,e.jsxs)(n.wn,{title:"Storage",children:[(0,e.jsxs)(n.BJ,{children:[(0,e.jsx)(n.BJ.Item,{mr:"20px",color:"silver",children:"Biomass:"}),(0,e.jsx)(n.BJ.Item,{mr:"5px",children:d}),(0,e.jsx)(n.In,{name:"leaf",size:1.2,color:"#3d8c40"})]}),(0,e.jsxs)(n.BJ,{height:"21px",mt:"8px",align:"center",children:[(0,e.jsx)(n.BJ.Item,{mr:"10px",color:"silver",children:"Container:"}),v?(0,e.jsx)(n.z2,{value:_,maxValue:s,children:(0,e.jsx)(n.az,{textAlign:"center",children:_+" / "+s+" units"})}):(0,e.jsx)(n.BJ.Item,{children:"None"})]})]})},y=function(h){var m=(0,l.Oc)(),d=m.act,v=m.data,_=v.has_plants,s=v.container;return(0,e.jsx)(n.wn,{title:"Controls",children:(0,e.jsxs)(n.BJ,{children:[(0,e.jsx)(n.BJ.Item,{width:"30%",children:(0,e.jsx)(n.$n,{fluid:!0,textAlign:"center",icon:"power-off",disabled:!_,tooltip:_?"":"There are no plants in the biogenerator.",tooltipPosition:"top-start",onClick:function(){return d("activate")},children:"Activate"})}),(0,e.jsx)(n.BJ.Item,{width:"40%",children:(0,e.jsx)(n.$n,{fluid:!0,textAlign:"center",icon:"flask",disabled:!s,tooltip:s?"":"The biogenerator does not have a container.",tooltipPosition:"top",onClick:function(){return d("detach_container")},children:"Detach Container"})}),(0,e.jsx)(n.BJ.Item,{width:"30%",children:(0,e.jsx)(n.$n,{fluid:!0,textAlign:"center",icon:"eject",disabled:!_,tooltip:_?"":"There are no stored plants to eject.",tooltipPosition:"top-end",onClick:function(){return d("eject_plants")},children:"Eject Plants"})})]})})},u=function(h){var m=(0,l.Oc)(),d=m.act,v=m.data,_=v.biomass,s=v.product_list,c=v.container,f=(0,l.QY)("vendAmount",1),g=f[0],p=f[1],j=Object.entries(s).map(function(x,C){var I=Object.entries(x[1]).map(function(P){return P[1]});return(0,e.jsx)(n.Nt,{title:x[0],open:!0,children:I.map(function(P){return(0,e.jsxs)(n.BJ,{py:"2px",className:"candystripe",align:"center",children:[(0,e.jsx)(n.BJ.Item,{width:"50%",ml:"2px",children:P.name}),(0,e.jsxs)(n.BJ.Item,{textAlign:"right",width:"20%",children:[P.cost*g,(0,e.jsx)(n.In,{ml:"5px",name:"leaf",size:1.2,color:"#3d8c40"})]}),(0,e.jsx)(n.BJ.Item,{textAlign:"right",width:"40%",children:P.needs_container&&!c?(0,e.jsx)(n.$n,{disabled:!0,icon:"flask",tooltip:"\u0412\u0441\u0442\u0430\u0432\u044C\u0442\u0435 \u043B\u044E\u0431\u043E\u0439 \u043A\u043E\u043D\u0442\u0435\u0439\u043D\u0435\u0440 \u0434\u043B\u044F \u0438\u0441\u043F\u043E\u043B\u044C\u0437\u043E\u0432\u0430\u043D\u0438\u044F \u044D\u0442\u043E\u0439 \u043E\u043F\u0446\u0438\u0438",children:"No containe"}):(0,e.jsx)(n.$n,{disabled:_{"use strict";r.r(S),r.d(S,{pda_notes:()=>t});var e=r(1131),l=r(360),n=r(5180),t=function(a){var b=(0,l.Oc)(),O=b.act,y=b.data,u=y.note;return(0,e.jsxs)(n.az,{children:[(0,e.jsx)(n.wn,{children:u}),(0,e.jsx)(n.$n,{icon:"pen",onClick:function(){return O("Edit")},children:"Edit"})]})}},8809:(q,S,r)=>{"use strict";/**
+ */var e=1e-4,l=null,n=function($,W,N){return W===void 0&&(W=0),N===void 0&&(N=Math.pow(10,W)),Math.round(N*$)/N},t={grad:360/400,turn:360,rad:360/(Math.PI*2)},a=function($){return B(b($))},b=function($){return $[0]==="#"&&($=$.substring(1)),$.length<6?{r:parseInt($[0]+$[0],16),g:parseInt($[1]+$[1],16),b:parseInt($[2]+$[2],16),a:$.length===4?n(parseInt($[3]+$[3],16)/255,2):1}:{r:parseInt($.substring(0,2),16),g:parseInt($.substring(2,4),16),b:parseInt($.substring(4,6),16),a:$.length===8?n(parseInt($.substring(6,8),16)/255,2):1}},O=function($,W){return W===void 0&&(W="deg"),Number($)*(t[W]||1)},y=function($){var W=/hsla?\(?\s*(-?\d*\.?\d+)(deg|rad|grad|turn)?[,\s]+(-?\d*\.?\d+)%?[,\s]+(-?\d*\.?\d+)%?,?\s*[/\s]*(-?\d*\.?\d+)?(%)?\s*\)?/i,N=W.exec($);return N?h({h:O(N[1],N[2]),s:Number(N[3]),l:Number(N[4]),a:N[5]===void 0?1:Number(N[5])/(N[6]?100:1)}):{h:0,s:0,v:0,a:1}},u=null,h=function($){var W=$.h,N=$.s,Q=$.l,ie=$.a;return N*=(Q<50?Q:100-Q)/100,{h:W,s:N>0?2*N/(Q+N)*100:0,v:Q+N,a:ie}},m=function($){return M(f($))},d=function($){var W=$.h,N=$.s,Q=$.v,ie=$.a,Z=(200-N)*Q/100;return{h:n(W),s:n(Z>0&&Z<200?N*Q/100/(Z<=100?Z:200-Z)*100:0),l:n(Z/2),a:n(ie,2)}},v=function($){var W=d($),N=W.h,Q=W.s,ie=W.l;return"hsl("+N+", "+Q+"%, "+ie+"%)"},_=function($){var W=w($),N=W.h,Q=W.s,ie=W.v;return"hsv("+N+", "+Q+"%, "+ie+"%)"},s=function($){var W=w($),N=W.h,Q=W.s,ie=W.v,Z=W.a;return"hsva("+N+", "+Q+"%, "+ie+"%, "+Z+")"},c=function($){var W=d($),N=W.h,Q=W.s,ie=W.l,Z=W.a;return"hsla("+N+", "+Q+"%, "+ie+"%, "+Z+")"},f=function($){var W=$.h,N=$.s,Q=$.v,ie=$.a;W=W/360*6,N=N/100,Q=Q/100;var Z=Math.floor(W),V=Q*(1-N),Y=Q*(1-(W-Z)*N),le=Q*(1-(1-W+Z)*N),xe=Z%6;return{r:[Q,Y,V,V,le,Q][xe]*255,g:[le,Q,Q,Y,V,V][xe]*255,b:[V,V,le,Q,Q,Y][xe]*255,a:n(ie,2)}},g=function($){var W=f($),N=W.r,Q=W.g,ie=W.b;return"rgb("+n(N)+", "+n(Q)+", "+n(ie)+")"},p=function($){var W=f($),N=W.r,Q=W.g,ie=W.b,Z=W.a;return"rgba("+n(N)+", "+n(Q)+", "+n(ie)+", "+n(Z,2)+")"},j=function($){var W=/hsva?\(?\s*(-?\d*\.?\d+)(deg|rad|grad|turn)?[,\s]+(-?\d*\.?\d+)%?[,\s]+(-?\d*\.?\d+)%?,?\s*[/\s]*(-?\d*\.?\d+)?(%)?\s*\)?/i,N=W.exec($);return N?w({h:O(N[1],N[2]),s:Number(N[3]),v:Number(N[4]),a:N[5]===void 0?1:Number(N[5])/(N[6]?100:1)}):{h:0,s:0,v:0,a:1}},x=null,C=function($){var W=/rgba?\(?\s*(-?\d*\.?\d+)(%)?[,\s]+(-?\d*\.?\d+)(%)?[,\s]+(-?\d*\.?\d+)(%)?,?\s*[/\s]*(-?\d*\.?\d+)?(%)?\s*\)?/i,N=W.exec($);return N?B({r:Number(N[1])/(N[2]?100/255:1),g:Number(N[3])/(N[4]?100/255:1),b:Number(N[5])/(N[6]?100/255:1),a:N[7]===void 0?1:Number(N[7])/(N[8]?100:1)}):{h:0,s:0,v:0,a:1}},I=null,P=function($){var W=$.toString(16);return W.length<2?"0"+W:W},M=function($){var W=$.r,N=$.g,Q=$.b,ie=$.a,Z=ie<1?P(n(ie*255)):"";return"#"+P(n(W))+P(n(N))+P(n(Q))+Z},B=function($){var W=$.r,N=$.g,Q=$.b,ie=$.a,Z=Math.max(W,N,Q),V=Z-Math.min(W,N,Q),Y=V?Z===W?(N-Q)/V:Z===N?2+(Q-W)/V:4+(W-N)/V:0;return{h:60*(Y<0?Y+6:Y),s:Z?V/Z*100:0,v:Z/255*100,a:ie}},w=function($){return{h:n($.h),s:n($.s),v:n($.v),a:n($.a,2)}},T=function($){var W=$.r,N=$.g,Q=$.b;return{r:W,g:N,b:Q}},L=function($){var W=$.h,N=$.s,Q=$.l;return{h:W,s:N,l:Q}},K=function($){var W=w($),N=W.h,Q=W.s,ie=W.v;return{h:N,s:Q,v:ie}},U=/^#?([0-9A-F]{3,8})$/i,J=function($,W){var N=U.exec($),Q=N?N[1].length:0;return Q===3||Q===6||!!W&&Q===4||!!W&&Q===8}},8593:(q,S,r)=>{"use strict";r.r(S),r.d(S,{TurbineComputer:()=>O});var e=r(1131),l=r(360),n=r(5180),t=r(8477),a=r(3521),b=r(9818),O=function(h){var m=(0,l.Oc)(),d=m.act,v=m.data,_=v.compressor,s=v.compressor_broken,c=v.turbine,f=v.turbine_broken,g=v.online,p=v.throttle,j=v.bearingDamage,x=!!(_&&!s&&c&&!f);return(0,e.jsx)(a.p8,{width:400,height:415,children:(0,e.jsxs)(a.p8.Content,{children:[(0,e.jsx)(n.wn,{title:"Status",buttons:(0,e.jsxs)(e.Fragment,{children:[(0,e.jsx)(n.$n,{icon:g?"power-off":"times",selected:g,disabled:!x,onClick:function(){return d("toggle_power")},children:g?"Online":"Offline"}),(0,e.jsx)(n.$n,{icon:"times",onClick:function(){return d("disconnect")},children:"Disconnect"})]}),children:x?(0,e.jsx)(u,{}):(0,e.jsx)(y,{})}),j>=100?(0,e.jsx)(n.BJ,{mb:"30px",children:(0,e.jsx)(n.BJ.Item,{bold:!0,color:"red",fontSize:5,textAlign:"center",children:"Bearings Inoperable, Repair Required"})}):(0,e.jsx)(n.wn,{title:"Throttle",children:x?(0,e.jsx)(n.N6,{size:3,value:p,unit:"%",minValue:0,maxValue:100,step:1,stepPixelSize:1,onDrag:function(C,I){return d("set_throttle",{throttle:I})}}):""})]})})},y=function(h){var m=(0,l.Oc)().data,d=m.compressor,v=m.compressor_broken,_=m.turbine,s=m.turbine_broken;return(0,e.jsxs)(n.Ki,{children:[(0,e.jsx)(n.Ki.Item,{label:"Compressor Status",color:!d||v?"bad":"good",children:v?d?"Offline":"Missing":"Online"}),(0,e.jsx)(n.Ki.Item,{label:"Turbine Status",color:!_||s?"bad":"good",children:s?_?"Offline":"Missing":"Online"})]})},u=function(h){var m=(0,l.Oc)().data,d=m.rpm,v=m.temperature,_=m.power,s=m.bearingDamage,c=m.preBurnTemperature,f=m.postBurnTemperature,g=m.thermalEfficiency,p=m.compressionRatio,j=m.gasThroughput;return(0,e.jsxs)(n.Ki,{children:[(0,e.jsxs)(n.Ki.Item,{label:"Turbine Speed",children:[d," RPM"]}),(0,e.jsxs)(n.Ki.Item,{label:"Effective Compression Ratio",children:[p,":1"]}),(0,e.jsxs)(n.Ki.Item,{label:"Gasmix Pre Burn Temp",children:[c," K"]}),(0,e.jsxs)(n.Ki.Item,{label:"Gasmix Post Burn Temp",children:[f," K"]}),(0,e.jsxs)(n.Ki.Item,{label:"Compressor Temp",children:[v," K"]}),(0,e.jsxs)(n.Ki.Item,{label:"Thermal Efficiency",children:[g*100," %"]}),(0,e.jsxs)(n.Ki.Item,{label:"Gas Throughput",children:[j/2," mol/s"]}),(0,e.jsx)(n.Ki.Item,{label:"Generated Power",children:(0,t.d5)(_)}),(0,e.jsx)(n.Ki.Item,{label:"Bearing Damage",children:(0,e.jsx)(n.z2,{value:s,minValue:0,maxValue:100,ranges:{good:[-1/0,60],average:[60,90],bad:[90,1/0]},children:(0,b.Mg)(s)+"%"})})]})}},8610:(q,S,r)=>{"use strict";r.r(S),r.d(S,{RoboticsControlConsole:()=>a});var e=r(1131),l=r(360),n=r(5180),t=r(3521),a=function(O){var y=(0,l.Oc)(),u=y.act,h=y.data,m=h.safety,d=h.show_detonate_all,v=h.cyborgs,_=v===void 0?[]:v;return(0,e.jsx)(t.p8,{width:500,height:460,children:(0,e.jsxs)(t.p8.Content,{scrollable:!0,children:[!!d&&(0,e.jsxs)(n.wn,{title:"Emergency Self Destruct",children:[(0,e.jsx)(n.$n,{icon:m?"lock":"unlock",selected:m,onClick:function(){return u("arm",{})},children:m?"Disable Safety":"Enable Safety"}),(0,e.jsx)(n.$n,{icon:"bolt",disabled:m,color:"bad",onClick:function(){return u("nuke",{})},children:"Destroy ALL Cyborgs"})]}),(0,e.jsx)(b,{cyborgs:_})]})})},b=function(O){var y=O.cyborgs,u=(0,l.Oc)(),h=u.act,m=u.data;return y.length?y.map(function(d){return(0,e.jsx)(n.wn,{title:d.name,buttons:(0,e.jsxs)(e.Fragment,{children:[!!d.hackable&&!d.emagged&&(0,e.jsx)(n.$n,{icon:"terminal",color:"bad",onClick:function(){return h("hackbot",{uid:d.uid})},children:"Hack"}),(0,e.jsx)(n.$n.Confirm,{icon:d.locked_down?"unlock":"lock",color:d.locked_down?"good":"default",disabled:!m.auth,onClick:function(){return h("stopbot",{uid:d.uid})},children:d.locked_down?"Release":"Lockdown"}),(0,e.jsx)(n.$n.Confirm,{icon:"bolt",disabled:!m.auth,color:"bad",onClick:function(){return h("killbot",{uid:d.uid})},children:"Self-destruct"})]}),children:(0,e.jsxs)(n.Ki,{children:[(0,e.jsx)(n.Ki.Item,{label:"Status",children:(0,e.jsx)(n.az,{color:d.status?"bad":d.locked_down?"average":"good",children:d.status?"Not Responding":d.locked_down?"Locked Down":"Nominal"})}),(0,e.jsx)(n.Ki.Item,{label:"Location",children:(0,e.jsx)(n.az,{children:d.locstring})}),(0,e.jsx)(n.Ki.Item,{label:"Integrity",children:(0,e.jsx)(n.z2,{color:d.health>50?"good":"bad",value:d.health/100})}),typeof d.charge=="number"&&(0,e.jsxs)(e.Fragment,{children:[(0,e.jsx)(n.Ki.Item,{label:"Cell Charge",children:(0,e.jsx)(n.z2,{color:d.charge>30?"good":"bad",value:d.charge/100})}),(0,e.jsx)(n.Ki.Item,{label:"Cell Capacity",children:(0,e.jsx)(n.az,{color:d.cell_capacity<3e4?"average":"good",children:d.cell_capacity})})]})||(0,e.jsx)(n.Ki.Item,{label:"Cell",children:(0,e.jsx)(n.az,{color:"bad",children:"No Power Cell"})}),!!d.is_hacked&&(0,e.jsx)(n.Ki.Item,{label:"Safeties",children:(0,e.jsx)(n.az,{color:"bad",children:"DISABLED"})}),(0,e.jsx)(n.Ki.Item,{label:"Module",children:d.module}),(0,e.jsx)(n.Ki.Item,{label:"Master AI",children:(0,e.jsx)(n.az,{color:d.synchronization?"default":"average",children:d.synchronization||"None"})}),!!d.is_shell&&(0,e.jsx)(n.Ki.Item,{label:"Occupier",children:d.occupier})]})},d.uid)}):(0,e.jsx)(n.IC,{children:"No cyborg units detected within access parameters."})}},8633:(q,S,r)=>{"use strict";r.r(S),r.d(S,{pda_security:()=>a});var e=r(1131),l=r(360),n=r(8725);function t(){return t=Object.assign||function(b){for(var O=1;O{"use strict";r.r(S),r.d(S,{AlertModal:()=>u});var e=r(1131),l=r(7003),n=r(5180),t=r(1808),a=r(360),b=r(3521),O=r(3384),y=function(d){return d[d.Increment=1]="Increment",d[d.Decrement=-1]="Decrement",d}(y||{}),u=function(d){var v=(0,a.Oc)(),_=v.act,s=v.data,c=s.autofocus,f=s.buttons,g=f===void 0?[]:f,p=s.large_buttons,j=s.message,x=j===void 0?"":j,C=s.timeout,I=s.title,P=function(N,Q,ie){Q=ie+"px "+Q;var Z=document.createElement("canvas"),V=Z.getContext("2d");return V.font=Q,V.measureText(N).width},M=(0,l.useState)(0),B=M[0],w=M[1],T=345+(g.length>2?55:0),L=67/g.length+23,K=g.some(function(N){return P(N,"Verdana, Geneva",p?14:12)>T/g.length-L}),U=K&&p?20:15,J=120+(K?U*g.length:0)+(x.length>30?Math.ceil(x.length/4):0)+(x.length&&p?5:0),$=function(N){switch(N.key){case t._.Space:case t._.Enter:_("choose",{choice:g[B]});return;case t._.Left:N.preventDefault(),W(-1);return;case t._.Tab:case t._.Right:N.preventDefault(),W(1);return;default:if((0,t.KL)(N.key)){_("cancel");return}}},W=function(N){var Q=(B+N+g.length)%g.length;w(Q)};return(0,e.jsxs)(b.p8,{height:J,title:I,width:T,children:[!!C&&(0,e.jsx)(O.Loader,{value:C}),(0,e.jsx)(b.p8.Content,{onKeyDown:$,children:(0,e.jsx)(n.wn,{fill:!0,children:(0,e.jsxs)(n.BJ,{fill:!0,vertical:!0,children:[(0,e.jsx)(n.BJ.Item,{m:1,children:(0,e.jsx)(n.az,{color:"label",overflow:"hidden",children:x})}),(0,e.jsxs)(n.BJ.Item,{grow:!0,children:[!!c&&(0,e.jsx)(n.y5,{}),K?(0,e.jsx)(m,{selected:B}):(0,e.jsx)(h,{selected:B})]})]})})})]})},h=function(d){var v=(0,a.Oc)(),_=v.act,s=v.data,c=s.buttons,f=c===void 0?[]:c,g=s.large_buttons,p=s.swapped_buttons,j=d.selected;return(0,e.jsx)(n.BJ,{fill:!0,justify:"space-around",reverse:!p,children:f.map(function(x,C){return(0,e.jsx)(n.BJ.Item,{grow:g?1:void 0,children:(0,e.jsx)(n.$n,{fluid:!!g,minWidth:5,onClick:function(){return _("choose",{choice:x})},overflowX:"hidden",px:2,py:g?.5:0,selected:j===C,textAlign:"center",children:g?x.toUpperCase():x})},C)})})},m=function(d){var v=(0,a.Oc)(),_=v.act,s=v.data,c=s.buttons,f=c===void 0?[]:c,g=s.large_buttons,p=s.swapped_buttons,j=d.selected;return(0,e.jsx)(n.BJ,{align:"center",fill:!0,justify:"space-around",reverse:!p,vertical:!0,children:f.map(function(x,C){return(0,e.jsx)(n.BJ.Item,{grow:!0,width:g?"100%":void 0,m:0,children:(0,e.jsx)(n.$n,{fluid:!0,minWidth:20,onClick:function(){return _("choose",{choice:x})},overflowX:"hidden",px:2,py:g?.5:0,selected:j===C,textAlign:"center",children:g?x.toUpperCase():x})},C)})})}},8711:(q,S,r)=>{"use strict";r.r(S),r.d(S,{BeakerPanel:()=>c});var e=r(1131),l=r(7003),n=r(5180),t=r(9845),a=r(360),b=r(3521);function O(){return O=Object.assign||function(f){for(var g=1;g{"use strict";r.r(S),r.d(S,{ObjectComponent:()=>m});var e=r(1131),l=r(7003),n=r(5180),t=r(185),a=r(8968),b=r(7941);function O(){return O=Object.assign||function(d){for(var v=1;v=0)&&(_[c]=d[c]);return _}function h(d,v){return h=Object.setPrototypeOf||function(s,c){return s.__proto__=c,s},h(d,v)}var m=function(d){"use strict";y(v,d);function v(s){var c;return c=d.call(this,s)||this,c.state={isDragging:!1,dragPos:null,startPos:null,lastMousePos:null},c.handleStartDrag=c.handleStartDrag.bind(c),c.handleStopDrag=c.handleStopDrag.bind(c),c.handleDrag=c.handleDrag.bind(c),c}var _=v.prototype;return _.handleStartDrag=function(c){var f=this.props,g=f.x,p=f.y;c.stopPropagation(),this.setState({lastMousePos:null,isDragging:!0,dragPos:{x:g,y:p},startPos:{x:g,y:p}}),window.addEventListener("mousemove",this.handleDrag),window.addEventListener("mouseup",this.handleStopDrag)},_.handleStopDrag=function(c){var f=this.state,g=f.dragPos,p=f.isDragging,j=this.props,x=j.index,C=j.act,I=C===void 0?a.noop:C;g&&p&&I("set_component_coordinates",{component_id:x,rel_x:this.roundToGrid(g.x),rel_y:this.roundToGrid(g.y)}),window.removeEventListener("mousemove",this.handleDrag),window.removeEventListener("mouseup",this.handleStopDrag),this.setState({isDragging:!1})},_.handleDrag=function(c){var f=this.state,g=f.dragPos,p=f.isDragging,j=f.lastMousePos,x=this.props.zoom;if(g&&p){c.preventDefault();var C=c.screenZoomX,I=c.screenZoomY,P=c.screenX,M=c.screenY,B=C||P,w=I||M;j&&this.setState({dragPos:{x:g.x-(j.x-B)*Math.pow(x,-1),y:g.y-(j.y-w)*Math.pow(x,-1)}}),this.setState({lastMousePos:{x:B,y:w}})}},_.shouldComponentUpdate=function(c,f){var g=this.props,p=g.input_ports,j=g.output_ports;return(0,t.a_)(this.props,c)||(0,t.a_)(this.state,f)||(0,t.a_)(p,c.input_ports)||(0,t.a_)(j,c.output_ports)},_.roundToGrid=function(c){return this.props.gridMode?Math.round(c/10)*10:c},_.render=function(){var c=this.props,f=c.input_ports,g=c.output_ports,p=c.name,j=c.x,x=c.y,C=c.index,I=c.category,P=I===void 0?"\u041D\u0435 \u0437\u0430\u0434\u0430\u043D\u043E":I,M=c.removable,B=c.ui_alerts,w=c.ui_buttons,T=c.locations,L=c.onPortUpdated,K=L===void 0?a.noop:L,U=c.onPortLoaded,J=U===void 0?a.noop:U,$=c.onPortMouseDown,W=$===void 0?a.noop:$,N=c.onPortRightClick,Q=N===void 0?a.noop:N,ie=c.onPortMouseUp,Z=ie===void 0?a.noop:ie,V=c.act,Y=V===void 0?a.noop:V,le=c.gridMode,xe=le===void 0?!0:le,de=u(c,["input_ports","output_ports","name","x","y","index","category","removable","ui_alerts","ui_buttons","locations","onPortUpdated","onPortLoaded","onPortMouseDown","onPortRightClick","onPortMouseUp","act","gridMode"]),me=this.state,pe=me.startPos,be=me.dragPos,ke=[j,x],Re=ke[0],De=ke[1];be&&pe&&pe.x===Re&&pe.y===De&&(Re=this.roundToGrid(be.x),De=this.roundToGrid(be.y));var tn={onPortLoaded:J,onPortUpdated:K,onPortMouseDown:W,onPortRightClick:Q,onPortMouseUp:Z};return(0,e.jsxs)(n.az,O({className:"ObjectComponent",position:"absolute",left:""+Re+"px",top:""+De+"px",onMouseDown:this.handleStartDrag,onMouseUp:this.handleStopDrag,style:{userSelect:"none"}},de,{children:[(0,e.jsx)(n.az,{py:1,px:1,className:(0,t.Ly)(["ObjectComponent__Titlebar","ObjectComponent__Category__"+P]),children:(0,e.jsxs)(n.BJ,{children:[(0,e.jsx)(n.BJ.Item,{grow:1,children:p}),!!w&&Object.keys(w).map(function(Ue){return(0,e.jsx)(n.BJ.Item,{children:(0,e.jsx)(n.$n,{icon:Ue,compact:!0,className:"ObjectComponent__Category__"+P,onClick:function(){return Y("perform_action",{component_id:C,action_name:w[Ue]})}})},Ue)}),!!B&&Object.keys(B).map(function(Ue){return(0,e.jsx)(n.BJ.Item,{children:(0,e.jsx)(n.$n,{className:"ObjectComponent__Category__"+P,icon:Ue,compact:!0,tooltip:B[Ue]})},Ue)}),(0,e.jsx)(n.BJ.Item,{children:(0,e.jsx)(n.$n,{icon:"info",compact:!0,className:"ObjectComponent__Category__"+P,onClick:function(Ue){return Y("set_examined_component",{component_id:C,x:Ue.pageX,y:Ue.pageY+a.ABSOLUTE_Y_OFFSET})}})}),!!M&&(0,e.jsx)(n.BJ.Item,{children:(0,e.jsx)(n.$n,{icon:"times",compact:!0,className:"ObjectComponent__Category__"+P,onClick:function(Ue){return Y("detach_component",{component_id:C,ctrl:!!Ue.ctrlKey})}})})]})}),(0,e.jsx)(n.az,{className:"ObjectComponent__Content",py:1,px:1,children:(0,e.jsxs)(n.BJ,{children:[(0,e.jsx)(n.BJ.Item,{grow:1,children:(0,e.jsx)(n.BJ,{vertical:!0,fill:!0,children:f.map(function(Ue,We){return(0,e.jsx)(n.BJ.Item,{children:(0,e.jsx)(b.Port,O({port:Ue,portIndex:We+1,componentId:C,act:Y},tn))},We)})})}),(0,e.jsx)(n.BJ.Item,{ml:5,children:(0,e.jsx)(n.BJ,{vertical:!0,children:g.map(function(Ue,We){return(0,e.jsx)(n.BJ.Item,{children:(0,e.jsx)(b.Port,O({act:Y,port:Ue,portIndex:We+1,componentId:C},tn,{isOutput:!0}))},We)})})})]})})]}))},v}(l.Component)},8725:(q,S,r)=>{"use strict";r.r(S),r.d(S,{SimpleRecords:()=>u});var e=r(1131),l=r(360),n=r(7003),t=r(9845),a=r(5070),b=r(1859),O=r(5180);function y(){return y=Object.assign||function(d){for(var v=1;v{"use strict";r.r(S),r.d(S,{PDA:()=>y});var e=r(1131),l=r(360),n=r(5180),t=r(3521),a=r(9160),b=r(7865),O=function(m){var d;try{d=b("./"+m+".tsx")}catch(_){if(_.code==="MODULE_NOT_FOUND")return(0,a.z)("notFound",m);throw _}var v=d[m];return v||(0,a.z)("missingExport",m)},y=function(m){var d=(0,l.Oc)().data,v=d.app,_=d.owner;if(!_)return(0,e.jsx)(t.p8,{width:350,height:105,children:(0,e.jsx)(t.p8.Content,{scrollable:!0,children:(0,e.jsx)(n.wn,{title:"Error",children:"No user data found. Please swipe an ID card."})})});var s=O(v.template);return(0,e.jsx)(t.p8,{width:600,height:650,children:(0,e.jsx)(t.p8.Content,{scrollable:!0,children:(0,e.jsxs)(n.BJ,{fill:!0,vertical:!0,children:[(0,e.jsx)(n.BJ.Item,{children:(0,e.jsx)(u,{})}),(0,e.jsx)(n.BJ.Item,{grow:!0,children:(0,e.jsx)(n.wn,{fill:!0,scrollable:!0,p:1,pb:0,title:(0,e.jsxs)(n.az,{children:[(0,e.jsx)(n.In,{name:v.icon,mr:1}),v.name]}),children:(0,e.jsx)(s,{})})}),(0,e.jsx)(n.BJ.Item,{mt:7.5,children:(0,e.jsx)(h,{})})]})})})},u=function(m){var d=(0,l.Oc)(),v=d.act,_=d.data,s=_.idInserted,c=_.idLink,f=_.stationTime,g=_.cartridge_name,p=_.request_cartridge_name;return(0,e.jsxs)(n.BJ,{fill:!0,children:[(0,e.jsx)(n.BJ.Item,{ml:.5,children:(0,e.jsx)(n.$n,{icon:"id-card",color:"transparent",onClick:function(){return v("Authenticate")},children:s?c:"No ID Inserted"})}),(0,e.jsx)(n.BJ.Item,{children:(0,e.jsx)(n.$n,{icon:"sd-card",color:"transparent",onClick:function(){return v("Eject")},children:g?["Eject "+g]:"No Cartridge Inserted"})}),(0,e.jsx)(n.BJ.Item,{children:(0,e.jsx)(n.$n,{icon:"sd-card",color:"transparent",onClick:function(){return v("Eject_Request")},children:p?["Eject "+p]:"No Request Cartridge Inserted"})}),(0,e.jsx)(n.BJ.Item,{grow:!0,textAlign:"right",bold:!0,mr:1,mt:.5,children:f})]})},h=function(m){var d=(0,l.Oc)(),v=d.act,_=d.data,s=_.app;return(0,e.jsx)(n.az,{height:"45px",className:"PDA__footer",backgroundColor:"#1b1b1b",children:(0,e.jsxs)(n.BJ,{fill:!0,children:[!!s.has_back&&(0,e.jsx)(n.BJ.Item,{basis:"33%",mr:-.5,children:(0,e.jsx)(n.$n,{fluid:!0,className:"PDA__footer__button",color:"transparent",iconColor:s.has_back?"white":"disabled",icon:"arrow-alt-circle-left-o",onClick:function(){return v("Back")}})}),(0,e.jsx)(n.BJ.Item,{basis:s.has_back?"33%":"100%",children:(0,e.jsx)(n.$n,{fluid:!0,className:"PDA__footer__button",color:"transparent",iconColor:s.is_home?"disabled":"white",icon:"home",onClick:function(){v("Home")}})})]})})}},8773:(q,S,r)=>{"use strict";r.r(S),r.d(S,{Biogenerator:()=>b});var e=r(1131),l=r(360),n=r(5180),t=r(3521),a=r(9680),b=function(h){var m=(0,l.Oc)(),d=m.data,v=m.config,_=d.processing,s=v.title;return(0,e.jsx)(t.p8,{width:390,height:595,children:(0,e.jsx)(t.p8.Content,{children:(0,e.jsxs)(n.BJ,{fill:!0,vertical:!0,children:[(0,e.jsx)(a.Operating,{operating:_,name:s}),(0,e.jsx)(O,{}),(0,e.jsx)(y,{}),(0,e.jsx)(u,{})]})})})},O=function(h){var m=(0,l.Oc)().data,d=m.biomass,v=m.container,_=m.container_curr_reagents,s=m.container_max_reagents;return(0,e.jsxs)(n.wn,{title:"Storage",children:[(0,e.jsxs)(n.BJ,{children:[(0,e.jsx)(n.BJ.Item,{mr:"20px",color:"silver",children:"Biomass:"}),(0,e.jsx)(n.BJ.Item,{mr:"5px",children:d}),(0,e.jsx)(n.In,{name:"leaf",size:1.2,color:"#3d8c40"})]}),(0,e.jsxs)(n.BJ,{height:"21px",mt:"8px",align:"center",children:[(0,e.jsx)(n.BJ.Item,{mr:"10px",color:"silver",children:"Container:"}),v?(0,e.jsx)(n.z2,{value:_,maxValue:s,children:(0,e.jsx)(n.az,{textAlign:"center",children:_+" / "+s+" units"})}):(0,e.jsx)(n.BJ.Item,{children:"None"})]})]})},y=function(h){var m=(0,l.Oc)(),d=m.act,v=m.data,_=v.has_plants,s=v.container;return(0,e.jsx)(n.wn,{title:"Controls",children:(0,e.jsxs)(n.BJ,{children:[(0,e.jsx)(n.BJ.Item,{width:"30%",children:(0,e.jsx)(n.$n,{fluid:!0,textAlign:"center",icon:"power-off",disabled:!_,tooltip:_?"":"There are no plants in the biogenerator.",tooltipPosition:"top-start",onClick:function(){return d("activate")},children:"Activate"})}),(0,e.jsx)(n.BJ.Item,{width:"40%",children:(0,e.jsx)(n.$n,{fluid:!0,textAlign:"center",icon:"flask",disabled:!s,tooltip:s?"":"The biogenerator does not have a container.",tooltipPosition:"top",onClick:function(){return d("detach_container")},children:"Detach Container"})}),(0,e.jsx)(n.BJ.Item,{width:"30%",children:(0,e.jsx)(n.$n,{fluid:!0,textAlign:"center",icon:"eject",disabled:!_,tooltip:_?"":"There are no stored plants to eject.",tooltipPosition:"top-end",onClick:function(){return d("eject_plants")},children:"Eject Plants"})})]})})},u=function(h){var m=(0,l.Oc)(),d=m.act,v=m.data,_=v.biomass,s=v.product_list,c=v.container,f=(0,l.QY)("vendAmount",1),g=f[0],p=f[1],j=Object.entries(s).map(function(x,C){var I=Object.entries(x[1]).map(function(P){return P[1]});return(0,e.jsx)(n.Nt,{title:x[0],open:!0,children:I.map(function(P){return(0,e.jsxs)(n.BJ,{py:"2px",className:"candystripe",align:"center",children:[(0,e.jsx)(n.BJ.Item,{width:"50%",ml:"2px",children:P.name}),(0,e.jsxs)(n.BJ.Item,{textAlign:"right",width:"20%",children:[P.cost*g,(0,e.jsx)(n.In,{ml:"5px",name:"leaf",size:1.2,color:"#3d8c40"})]}),(0,e.jsx)(n.BJ.Item,{textAlign:"right",width:"40%",children:P.needs_container&&!c?(0,e.jsx)(n.$n,{disabled:!0,icon:"flask",tooltip:"\u0412\u0441\u0442\u0430\u0432\u044C\u0442\u0435 \u043B\u044E\u0431\u043E\u0439 \u043A\u043E\u043D\u0442\u0435\u0439\u043D\u0435\u0440 \u0434\u043B\u044F \u0438\u0441\u043F\u043E\u043B\u044C\u0437\u043E\u0432\u0430\u043D\u0438\u044F \u044D\u0442\u043E\u0439 \u043E\u043F\u0446\u0438\u0438",children:"No containe"}):(0,e.jsx)(n.$n,{disabled:_{"use strict";r.r(S),r.d(S,{pda_notes:()=>t});var e=r(1131),l=r(360),n=r(5180),t=function(a){var b=(0,l.Oc)(),O=b.act,y=b.data,u=y.note;return(0,e.jsxs)(n.az,{children:[(0,e.jsx)(n.wn,{children:u}),(0,e.jsx)(n.$n,{icon:"pen",onClick:function(){return O("Edit")},children:"Edit"})]})}},8809:(q,S,r)=>{"use strict";/**
* @license React
* react-jsx-runtime.production.min.js
*