Please show this to Bibby: \
+ Averted crash in os-cpu loop. Following vars used: total_cpu: [total_cpu], previous_cpu: [previous_cpu], cpu_assigned length: [cpu_assigned.len]
")
+ else
+ message_admins("
Averted crash in os-cpu loop. Following vars used: total_cpu: [total_cpu], previous_cpu: [previous_cpu], cpu_assigned length: [cpu_assigned.len]
Please show this to Bibby: \
+ Averted crash in os-ram loop. Following vars used: total_ram: [total_ram], previous_ram: [previous_ram], ram_assigned length: [ram_assigned.len]
")
+ else
+ message_admins("
Averted crash in os-ram loop. Following vars used: total_ram: [total_ram], previous_ram: [previous_ram], ram_assigned length: [ram_assigned.len]
Please show this to Bibby: \
+ Averted crash in dashboard-ram loop. Following vars used: ram_used: [total_ram_used], current_ram: [current_ram], ram_usage length: [ram_usage.len]
")
+ else
+ message_admins("
Averted crash in dashboard-ram loop. Following vars used: ram_used: [total_ram_used], current_ram: [current_ram], ram_usage length: [ram_usage.len]
Please show this to Bibby: \
+ Averted crash in dashboard-cpu loop. Following vars used: cpu_used: [total_cpu_used], current_cpu: [current_cpu], cpu_usage length: [cpu_usage.len]
")
+ else
+ message_admins("
Averted crash in dashboard-cpu loop. Following vars used: cpu_used: [total_cpu_used], current_cpu: [current_cpu], cpu_usage length: [cpu_usage.len]
")
+ break
for(var/I in cpu_usage)
if(cpu_usage[I] > 0)
cpu_usage[I]--
From c3705c757e21748726af0e4a63379b3d8339e6e8 Mon Sep 17 00:00:00 2001
From: TheGamerdk <5618080+TheGamerdk@users.noreply.github.com>
Date: Mon, 6 Dec 2021 16:44:48 +0100
Subject: [PATCH 49/93] this should actually fix the crashes, for good
---
.../mob/living/silicon/ai/decentralized/decentralized_os.dm | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/code/modules/mob/living/silicon/ai/decentralized/decentralized_os.dm b/code/modules/mob/living/silicon/ai/decentralized/decentralized_os.dm
index afe888139109..3e0ab3811335 100644
--- a/code/modules/mob/living/silicon/ai/decentralized/decentralized_os.dm
+++ b/code/modules/mob/living/silicon/ai/decentralized/decentralized_os.dm
@@ -79,7 +79,7 @@ GLOBAL_DATUM_INIT(ai_os, /datum/ai_os, new)
message_admins("
Averted crash in os-cpu loop. Following vars used: total_cpu: [total_cpu], previous_cpu: [previous_cpu], cpu_assigned length: [cpu_assigned.len]
Please show this to Bibby: \
- Averted crash in os-cpu loop. Following vars used: total_cpu: [total_cpu], previous_cpu: [previous_cpu], cpu_assigned length: [cpu_assigned.len]
")
+ Averted crash in os-cpu loop. Following vars used: total_cpu: [total_cpu], previous_cpu: [previous_cpu], cpu_assigned length: [cpu_assigned.len] round: [GLOB.round_id]")
else
- message_admins("
Averted crash in os-cpu loop. Following vars used: total_cpu: [total_cpu], previous_cpu: [previous_cpu], cpu_assigned length: [cpu_assigned.len]
")
+ message_admins("
Averted crash in os-cpu loop. Following vars used: total_cpu: [total_cpu], previous_cpu: [previous_cpu], cpu_assigned length: [cpu_assigned.len] round: [GLOB.round_id]
Please show this to Bibby: \
- Averted crash in os-ram loop. Following vars used: total_ram: [total_ram], previous_ram: [previous_ram], ram_assigned length: [ram_assigned.len]
")
+ Averted crash in os-ram loop. Following vars used: total_ram: [total_ram], previous_ram: [previous_ram], ram_assigned length: [ram_assigned.len] round: [GLOB.round_id]")
else
- message_admins("
Averted crash in os-ram loop. Following vars used: total_ram: [total_ram], previous_ram: [previous_ram], ram_assigned length: [ram_assigned.len]
")
+ message_admins("
Averted crash in os-ram loop. Following vars used: total_ram: [total_ram], previous_ram: [previous_ram], ram_assigned length: [ram_assigned.len] round: [GLOB.round_id]
Please show this to Bibby: \
- Averted crash in dashboard-ram loop. Following vars used: ram_used: [total_ram_used], current_ram: [current_ram], ram_usage length: [ram_usage.len]
")
+ Averted crash in dashboard-ram loop. Following vars used: ram_used: [total_ram_used], current_ram: [current_ram], ram_usage length: [ram_usage.len] round: [GLOB.round_id]")
else
- message_admins("
Averted crash in dashboard-ram loop. Following vars used: ram_used: [total_ram_used], current_ram: [current_ram], ram_usage length: [ram_usage.len]
")
+ message_admins("
Averted crash in dashboard-ram loop. Following vars used: ram_used: [total_ram_used], current_ram: [current_ram], ram_usage length: [ram_usage.len] round: [GLOB.round_id]
Please show this to Bibby: \
- Averted crash in dashboard-cpu loop. Following vars used: cpu_used: [total_cpu_used], current_cpu: [current_cpu], cpu_usage length: [cpu_usage.len]
")
+ Averted crash in dashboard-cpu loop. Following vars used: cpu_used: [total_cpu_used], current_cpu: [current_cpu], cpu_usage length: [cpu_usage.len] round: [GLOB.round_id]")
else
- message_admins("
Averted crash in dashboard-cpu loop. Following vars used: cpu_used: [total_cpu_used], current_cpu: [current_cpu], cpu_usage length: [cpu_usage.len]
")
+ message_admins("
Averted crash in dashboard-cpu loop. Following vars used: cpu_used: [total_cpu_used], current_cpu: [current_cpu], cpu_usage length: [cpu_usage.len] round: [GLOB.round_id]
")
+ for(var/I in cpu_usage)
+ log_game("[I] + cpu usage: [ram_usage[I]]")
break
for(var/I in cpu_usage)
if(cpu_usage[I] > 0)
From 1f8cad33f047ab7535cbeecb5f7e4923234b0c4c Mon Sep 17 00:00:00 2001
From: TheGamerdk <5618080+TheGamerdk@users.noreply.github.com>
Date: Tue, 14 Dec 2021 16:34:06 +0100
Subject: [PATCH 63/93] lots of bug fixes
---
code/__DEFINES/is_helpers.dm | 4 ++
.../circuitboards/machine_circuitboards.dm | 10 +++++
.../traitor/equipment/Malf_Modules.dm | 2 +-
code/modules/mob/living/silicon/ai/ai.dm | 2 -
.../silicon/ai/decentralized/_ai_machinery.dm | 19 +++++++++
.../silicon/ai/decentralized/ai_data_core.dm | 41 ++++++++++++++++++-
.../ai/decentralized/expansion_card_holder.dm | 19 ---------
.../management/ai_controlpanel.dm | 16 +++++++-
.../management/resource_distribution.dm | 16 +++++++-
.../modules/mob/living/silicon/robot/robot.dm | 1 +
.../research/designs/machine_designs.dm | 8 ++++
code/modules/research/techweb/all_nodes.dm | 2 +-
12 files changed, 113 insertions(+), 27 deletions(-)
diff --git a/code/__DEFINES/is_helpers.dm b/code/__DEFINES/is_helpers.dm
index 40b7a0d550d1..e5eccb2d2e36 100644
--- a/code/__DEFINES/is_helpers.dm
+++ b/code/__DEFINES/is_helpers.dm
@@ -44,6 +44,10 @@ GLOBAL_LIST_INIT(turfs_without_ground, typecacheof(list(
#define isplatingturf(A) (istype(A, /turf/open/floor/plating))
+#define isaicore(A) (istype(A, /obj/machinery/ai/data_core))
+
+#define isvalidAIloc(A) ((isturf(A) || isaicore(A)))
+
//Mobs
#define isliving(A) (istype(A, /mob/living))
diff --git a/code/game/objects/items/circuitboards/machine_circuitboards.dm b/code/game/objects/items/circuitboards/machine_circuitboards.dm
index 067cfe1ce802..96319ee7c04a 100644
--- a/code/game/objects/items/circuitboards/machine_circuitboards.dm
+++ b/code/game/objects/items/circuitboards/machine_circuitboards.dm
@@ -961,6 +961,16 @@
/obj/item/stock_parts/manipulator = 2,
/obj/item/stack/sheet/glass = 2)
+/obj/item/circuitboard/machine/ai_data_core
+ name = "AI Data Core (Machine Board)"
+ icon_state = "science"
+ build_path = /obj/machinery/ai/data_core
+ req_components = list(
+ /obj/item/stock_parts/capacitor = 4,
+ /obj/item/stock_parts/matter_bin = 2,
+ /obj/item/stack/sheet/glass = 2,
+ /obj/item/stack/cable_coil = 2)
+
//Security
diff --git a/code/modules/antagonists/traitor/equipment/Malf_Modules.dm b/code/modules/antagonists/traitor/equipment/Malf_Modules.dm
index a9781badac8f..5183b1778834 100644
--- a/code/modules/antagonists/traitor/equipment/Malf_Modules.dm
+++ b/code/modules/antagonists/traitor/equipment/Malf_Modules.dm
@@ -591,7 +591,7 @@ GLOBAL_LIST_INIT(malf_modules, subtypesof(/datum/AI_Module))
C.images -= I
/mob/living/silicon/ai/proc/can_place_transformer(datum/action/innate/ai/place_transformer/action)
- if(!eyeobj || !isturf(loc) || incapacitated() || !action)
+ if(!eyeobj || !isvalidAIloc(loc) || incapacitated() || !action)
return
var/turf/middle = get_turf(eyeobj)
var/list/turfs = list(middle, locate(middle.x - 1, middle.y, middle.z), locate(middle.x + 1, middle.y, middle.z))
diff --git a/code/modules/mob/living/silicon/ai/ai.dm b/code/modules/mob/living/silicon/ai/ai.dm
index da1686ff6e9a..8358bbf40963 100644
--- a/code/modules/mob/living/silicon/ai/ai.dm
+++ b/code/modules/mob/living/silicon/ai/ai.dm
@@ -890,8 +890,6 @@
if(isturf(loc) || istype(loc, /obj/machinery/ai/data_core)) //AI in core, check if on cameras
//get_turf_pixel() is because APCs in maint aren't actually in view of the inner camera
//apc_override is needed here because AIs use their own APC when depowered
- if(istype(loc, /obj/machinery/ai/data_core))
- A = get_turf(loc)
return (GLOB.cameranet && GLOB.cameranet.checkTurfVis(get_turf_pixel(A))) || apc_override
//AI is carded/shunted
//view(src) returns nothing for carded/shunted AIs and they have X-ray vision so just use get_dist
diff --git a/code/modules/mob/living/silicon/ai/decentralized/_ai_machinery.dm b/code/modules/mob/living/silicon/ai/decentralized/_ai_machinery.dm
index 09dd5a5c4b91..da723cd66e28 100644
--- a/code/modules/mob/living/silicon/ai/decentralized/_ai_machinery.dm
+++ b/code/modules/mob/living/silicon/ai/decentralized/_ai_machinery.dm
@@ -4,3 +4,22 @@
icon = 'icons/obj/machines/research.dmi'
icon_state = "RD-server-on"
density = TRUE
+
+/obj/machinery/ai/proc/valid_holder()
+ if(stat & (BROKEN|NOPOWER|EMPED))
+ return FALSE
+
+ var/turf/T = get_turf(src)
+ var/datum/gas_mixture/env = T.return_air()
+ if(!env)
+ return FALSE
+ var/total_moles = env.total_moles()
+ if(istype(T, /turf/open/space) || total_moles < 10)
+ return FALSE
+
+ if(env.return_temperature() > TEMP_LIMIT || !env.heat_capacity())
+ return FALSE
+ if(!was_valid_holder)
+ update_icon()
+ was_valid_holder = TRUE
+ return TRUE
diff --git a/code/modules/mob/living/silicon/ai/decentralized/ai_data_core.dm b/code/modules/mob/living/silicon/ai/decentralized/ai_data_core.dm
index 7a1e9ee3ea2e..6872ae4be6cc 100644
--- a/code/modules/mob/living/silicon/ai/decentralized/ai_data_core.dm
+++ b/code/modules/mob/living/silicon/ai/decentralized/ai_data_core.dm
@@ -1,15 +1,22 @@
GLOBAL_LIST_EMPTY(data_cores)
GLOBAL_VAR_INIT(primary_data_core, null)
+#define MAX_AI_DATA_CORE_TICKS 15
/obj/machinery/ai/data_core
name = "AI Data Core"
- desc = "A complicated computer system capable of emulating the neural functions of a human at near-instantanous speeds."
+ desc = "A complicated computer system capable of emulating the neural functions of an organic being at near-instantanous speeds."
icon = 'icons/obj/machines/telecomms.dmi'
icon_state = "hub"
+
+ circuit = /obj/item/circuitboard/machine/ai_data_core
var/primary = FALSE
+ var/valid_ticks = MAX_AI_DATA_CORE_TICKS //Limited to MAX_AI_DATA_CORE_TICKS. Decrement by 1 every time we have an invalid tick, opposite when valid
+
+ var/warning_sent = FALSE
+
/obj/machinery/ai/data_core/Initialize()
..()
GLOB.data_cores += src
@@ -17,13 +24,23 @@ GLOBAL_VAR_INIT(primary_data_core, null)
GLOB.primary_data_core = src
update_icon()
+/obj/machinery/ai/data_core/process()
+ calculate_validity()
+
+
/obj/machinery/ai/data_core/Destroy()
GLOB.data_cores -= src
if(GLOB.primary_data_core == src)
GLOB.primary_data_core = null
+ var/list/all_ais = GLOB.ai_list.Copy()
+
for(var/mob/living/silicon/ai/AI in contents)
+ all_ais -= AI
AI.relocate()
+
+ to_chat(all_ais, span_userdanger("Warning! Data Core brought offline in [get_area(src)]! Please verify that no malicious actions were taken."))
+
..()
/obj/machinery/ai/data_core/examine(mob/user)
@@ -37,10 +54,32 @@ GLOBAL_VAR_INIT(primary_data_core, null)
for(var/law in AI.laws.get_law_list(include_zeroth = TRUE))
. += law
+/obj/machinery/ai/data_core/proc/valid_data_core()
+ if(valid_ticks > 0)
+ return TRUE
+ return FALSE
+
+/obj/machinery/ai/data_core/proc/calculate_validity()
+ clamp(valid_ticks, 0, MAX_AI_DATA_CORE_TICKS)
+
+ if(stat & (BROKEN|NOPOWER|EMPED))
+ return FALSE
+
+ if(valid_holder())
+ valid_ticks++
+ warning_sent = FALSE
+ else
+ valid_ticks--
+ warning_sent = TRUE
+ to_chat(GLOB.ai_list, span_userdanger("Data core in [get_area(src)] is on the verge of failing! Please contact technical support."))
+
+
/obj/machinery/ai/data_core/proc/can_transfer_ai()
if(stat & (BROKEN|NOPOWER|EMPED))
return FALSE
+ if(!valid_data_core())
+ return FALSE
return TRUE
/obj/machinery/ai/data_core/proc/transfer_AI(mob/living/silicon/ai/AI)
diff --git a/code/modules/mob/living/silicon/ai/decentralized/expansion_card_holder.dm b/code/modules/mob/living/silicon/ai/decentralized/expansion_card_holder.dm
index 7384fdb8deb4..5379702b5aa8 100644
--- a/code/modules/mob/living/silicon/ai/decentralized/expansion_card_holder.dm
+++ b/code/modules/mob/living/silicon/ai/decentralized/expansion_card_holder.dm
@@ -38,25 +38,6 @@ GLOBAL_LIST_EMPTY(expansion_card_holders)
GLOB.ai_os.update_hardware()
..()
-/obj/machinery/ai/expansion_card_holder/proc/valid_holder()
- if(stat & (BROKEN|NOPOWER|EMPED))
- return FALSE
-
- var/turf/T = get_turf(src)
- var/datum/gas_mixture/env = T.return_air()
- if(!env)
- return FALSE
- var/total_moles = env.total_moles()
- if(istype(T, /turf/open/space) || total_moles < 10)
- return FALSE
-
- if(env.return_temperature() > TEMP_LIMIT || !env.heat_capacity())
- return FALSE
- if(!was_valid_holder)
- update_icon()
- was_valid_holder = TRUE
- return TRUE
-
/obj/machinery/ai/expansion_card_holder/process()
if(valid_holder())
diff --git a/code/modules/mob/living/silicon/ai/decentralized/management/ai_controlpanel.dm b/code/modules/mob/living/silicon/ai/decentralized/management/ai_controlpanel.dm
index 8a320e771a91..e7b33588b9e6 100644
--- a/code/modules/mob/living/silicon/ai/decentralized/management/ai_controlpanel.dm
+++ b/code/modules/mob/living/silicon/ai/decentralized/management/ai_controlpanel.dm
@@ -58,6 +58,13 @@
return ..()
+/obj/machinery/computer/ai_control_console/emag_act(mob/user)
+ if(obj_flags & EMAGGED)
+ return
+ to_chat(user, span_warning("You bypass the access restrictions"))
+ authenticated = TRUE
+ obj_flags |= EMAGGED
+
/obj/machinery/computer/ai_control_console/process()
if(downloading && download_progress >= 50 && !download_warning)
var/turf/T = get_turf(src)
@@ -93,7 +100,7 @@
data["username"] = user.client.holder.admin_signature
data["has_access"] = TRUE
- if(ishuman(user))
+ if(ishuman(user) && !(obj_flags & EMAGGED))
var/username = user.get_authentification_name("Unknown")
data["username"] = user.get_authentification_name("Unknown")
if(username != "Unknown")
@@ -119,6 +126,10 @@
data["user_image"] = SSassets.transport.get_asset_url("photo_[md5]_cropped.png")
data["has_access"] = check_access(user.get_idcard())
+
+ if(obj_flags & EMAGGED)
+ data["username"] = "ERROR"
+ data["has_access"] = TRUE
if(!authenticated)
return data
@@ -189,6 +200,9 @@
if(IsAdminGhost(usr))
authenticated = TRUE
+ if(obj_flags & EMAGGED)
+ authenticated = TRUE
+
var/mob/living/carbon/human/H = usr
if(!istype(H))
return
diff --git a/code/modules/mob/living/silicon/ai/decentralized/management/resource_distribution.dm b/code/modules/mob/living/silicon/ai/decentralized/management/resource_distribution.dm
index c60de3d1f5da..923acfc3c562 100644
--- a/code/modules/mob/living/silicon/ai/decentralized/management/resource_distribution.dm
+++ b/code/modules/mob/living/silicon/ai/decentralized/management/resource_distribution.dm
@@ -14,6 +14,13 @@
circuit = /obj/item/circuitboard/computer/ai_resource_distribution
+/obj/machinery/computer/ai_resource_distribution/emag_act(mob/user)
+ if(obj_flags & EMAGGED)
+ return
+ to_chat(user, span_warning("You bypass the access restrictions"))
+ authenticated = TRUE
+ obj_flags |= EMAGGED
+
/obj/machinery/computer/ai_resource_distribution/ui_interact(mob/user, datum/tgui/ui)
ui = SStgui.try_update_ui(user, src, ui)
if(!ui)
@@ -34,7 +41,7 @@
data["username"] = user.client.holder.admin_signature
data["has_access"] = TRUE
- if(ishuman(user))
+ if(ishuman(user) && !(obj_flags & EMAGGED))
var/username = user.get_authentification_name("Unknown")
data["username"] = user.get_authentification_name("Unknown")
if(username != "Unknown")
@@ -61,6 +68,10 @@
data["user_image"] = SSassets.transport.get_asset_url("photo_[md5]_cropped.png")
data["has_access"] = check_access(user.get_idcard())
+ if(obj_flags & EMAGGED)
+ data["username"] = "ERROR"
+ data["has_access"] = TRUE
+
if(!authenticated)
return data
@@ -98,7 +109,8 @@
if(IsAdminGhost(usr))
authenticated = TRUE
-
+ if(obj_flags & EMAGGED)
+ authenticated = TRUE
var/mob/living/carbon/human/H = usr
diff --git a/code/modules/mob/living/silicon/robot/robot.dm b/code/modules/mob/living/silicon/robot/robot.dm
index 62b3f34b4693..6e33ee27e7bb 100644
--- a/code/modules/mob/living/silicon/robot/robot.dm
+++ b/code/modules/mob/living/silicon/robot/robot.dm
@@ -1155,6 +1155,7 @@
if(!deployed || !mind || !mainframe)
return
+ remove_sensors()
mainframe.redeploy_action.Grant(mainframe)
mainframe.redeploy_action.last_used_shell = src
mind.transfer_to(mainframe)
diff --git a/code/modules/research/designs/machine_designs.dm b/code/modules/research/designs/machine_designs.dm
index 3047e353e148..78af349837d5 100644
--- a/code/modules/research/designs/machine_designs.dm
+++ b/code/modules/research/designs/machine_designs.dm
@@ -674,3 +674,11 @@
build_path = /obj/item/circuitboard/machine/expansion_card_holder
category = list("Engineering Machinery")
departmental_flags = DEPARTMENTAL_FLAG_SCIENCE
+
+/datum/design/board/ai_data_core
+ name = "Machine Design (AI Data Core Board)"
+ desc = "The circuit board for an AI data core."
+ id = "ai_data_core"
+ build_path = /obj/item/circuitboard/machine/ai_data_core
+ category = list("Engineering Machinery")
+ departmental_flags = DEPARTMENTAL_FLAG_SCIENCE
diff --git a/code/modules/research/techweb/all_nodes.dm b/code/modules/research/techweb/all_nodes.dm
index c4559f661704..54b6bd818ada 100644
--- a/code/modules/research/techweb/all_nodes.dm
+++ b/code/modules/research/techweb/all_nodes.dm
@@ -377,7 +377,7 @@
display_name = "Artificial Intelligence"
description = "AI unit research."
prereq_ids = list("robotics", "posibrain")
- design_ids = list("expansion_card_holder", "ai_control", "ai_server_overview", "ai_resource_distribution", "ai_memory_1", "ai_cpu_1", "aifixer", "safeguard_module", "onehuman_module", "protectstation_module", "quarantine_module", "oxygen_module", "freeform_module",
+ design_ids = list("expansion_card_holder", "ai_data_core", "ai_control", "ai_server_overview", "ai_resource_distribution", "ai_memory_1", "ai_cpu_1", "aifixer", "safeguard_module", "onehuman_module", "protectstation_module", "quarantine_module", "oxygen_module", "freeform_module",
"reset_module", "purge_module", "remove_module", "freeformcore_module", "asimov_module", "crewsimov_module", "paladin_module", "tyrant_module", "overlord_module", "ceo_module", "cowboy_module", "default_module", "borg_ai_control", "mecha_tracking_ai_control", "intellicard")
research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2500)
export_price = 5000
From 38c1dab280d268d862449d7a77e93cf6525fa55a Mon Sep 17 00:00:00 2001
From: TheGamerdk <5618080+TheGamerdk@users.noreply.github.com>
Date: Tue, 14 Dec 2021 16:38:13 +0100
Subject: [PATCH 64/93] oops
---
.../silicon/ai/decentralized/_ai_machinery.dm | 2 ++
.../ai/decentralized/expansion_card_holder.dm | 19 ++++++++++++++++++-
2 files changed, 20 insertions(+), 1 deletion(-)
diff --git a/code/modules/mob/living/silicon/ai/decentralized/_ai_machinery.dm b/code/modules/mob/living/silicon/ai/decentralized/_ai_machinery.dm
index da723cd66e28..978f8973cee7 100644
--- a/code/modules/mob/living/silicon/ai/decentralized/_ai_machinery.dm
+++ b/code/modules/mob/living/silicon/ai/decentralized/_ai_machinery.dm
@@ -1,3 +1,5 @@
+#define TEMP_LIMIT 290.15 //17C, much hotter than a normal server room for leniency :)
+
/obj/machinery/ai
name = "You shouldn't see this!"
desc = "You shouldn't see this!"
diff --git a/code/modules/mob/living/silicon/ai/decentralized/expansion_card_holder.dm b/code/modules/mob/living/silicon/ai/decentralized/expansion_card_holder.dm
index 5379702b5aa8..e930d533b302 100644
--- a/code/modules/mob/living/silicon/ai/decentralized/expansion_card_holder.dm
+++ b/code/modules/mob/living/silicon/ai/decentralized/expansion_card_holder.dm
@@ -1,6 +1,5 @@
#define BASE_POWER_PER_CPU 400
#define POWER_PER_CARD 250
-#define TEMP_LIMIT 290.15 //17C, much hotter than a normal server room for leniency :)
GLOBAL_LIST_EMPTY(expansion_card_holders)
@@ -56,6 +55,24 @@ GLOBAL_LIST_EMPTY(expansion_card_holders)
cut_overlays()
GLOB.ai_os.update_hardware()
+/obj/machinery/ai/expansion_card_holder/valid_holder()
+ if(stat & (BROKEN|NOPOWER|EMPED))
+ return FALSE
+
+ var/turf/T = get_turf(src)
+ var/datum/gas_mixture/env = T.return_air()
+ if(!env)
+ return FALSE
+ var/total_moles = env.total_moles()
+ if(istype(T, /turf/open/space) || total_moles < 10)
+ return FALSE
+
+ if(env.return_temperature() > TEMP_LIMIT || !env.heat_capacity())
+ return FALSE
+ if(!was_valid_holder)
+ update_icon()
+ was_valid_holder = TRUE
+ return TRUE
/obj/machinery/ai/expansion_card_holder/update_icon()
cut_overlays()
From 597e41fb3adc0ed66aeab4067f8243d54532190c Mon Sep 17 00:00:00 2001
From: TheGamerdk <5618080+TheGamerdk@users.noreply.github.com>
Date: Tue, 14 Dec 2021 16:40:29 +0100
Subject: [PATCH 65/93] Update _ai_machinery.dm
---
.../mob/living/silicon/ai/decentralized/_ai_machinery.dm | 3 ---
1 file changed, 3 deletions(-)
diff --git a/code/modules/mob/living/silicon/ai/decentralized/_ai_machinery.dm b/code/modules/mob/living/silicon/ai/decentralized/_ai_machinery.dm
index 978f8973cee7..2807ef3b53de 100644
--- a/code/modules/mob/living/silicon/ai/decentralized/_ai_machinery.dm
+++ b/code/modules/mob/living/silicon/ai/decentralized/_ai_machinery.dm
@@ -21,7 +21,4 @@
if(env.return_temperature() > TEMP_LIMIT || !env.heat_capacity())
return FALSE
- if(!was_valid_holder)
- update_icon()
- was_valid_holder = TRUE
return TRUE
From 56f0dae8ea0c1b45f75b37272d2a9d7cdf6edab8 Mon Sep 17 00:00:00 2001
From: TheGamerdk <5618080+TheGamerdk@users.noreply.github.com>
Date: Tue, 14 Dec 2021 16:46:55 +0100
Subject: [PATCH 66/93] Update ai_data_core.dm
---
.../modules/mob/living/silicon/ai/decentralized/ai_data_core.dm | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/code/modules/mob/living/silicon/ai/decentralized/ai_data_core.dm b/code/modules/mob/living/silicon/ai/decentralized/ai_data_core.dm
index 6872ae4be6cc..b1f034ee8496 100644
--- a/code/modules/mob/living/silicon/ai/decentralized/ai_data_core.dm
+++ b/code/modules/mob/living/silicon/ai/decentralized/ai_data_core.dm
@@ -60,7 +60,7 @@ GLOBAL_VAR_INIT(primary_data_core, null)
return FALSE
/obj/machinery/ai/data_core/proc/calculate_validity()
- clamp(valid_ticks, 0, MAX_AI_DATA_CORE_TICKS)
+ valid_ticks = clamp(valid_ticks, 0, MAX_AI_DATA_CORE_TICKS)
if(stat & (BROKEN|NOPOWER|EMPED))
return FALSE
From 77c47ef9aa78f91863afb15707bfca74084a7ca2 Mon Sep 17 00:00:00 2001
From: TheGamerdk <5618080+TheGamerdk@users.noreply.github.com>
Date: Tue, 14 Dec 2021 20:00:59 +0100
Subject: [PATCH 67/93] Update ai_data_core.dm
---
.../modules/mob/living/silicon/ai/decentralized/ai_data_core.dm | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/code/modules/mob/living/silicon/ai/decentralized/ai_data_core.dm b/code/modules/mob/living/silicon/ai/decentralized/ai_data_core.dm
index b1f034ee8496..d41d2d3b80a1 100644
--- a/code/modules/mob/living/silicon/ai/decentralized/ai_data_core.dm
+++ b/code/modules/mob/living/silicon/ai/decentralized/ai_data_core.dm
@@ -50,7 +50,7 @@ GLOBAL_VAR_INIT(primary_data_core, null)
. += "Networked AI Laws:"
for(var/mob/living/silicon/ai/AI in GLOB.ai_list)
var/active_status = !AI.mind ? "(OFFLINE)" : ""
- . += "[AI] [active_status] has the following laws:"
+ . += "[AI] [active_status] has the following laws: "
for(var/law in AI.laws.get_law_list(include_zeroth = TRUE))
. += law
From b8cf104e2704044157443aa922f24e1dfb9d3005 Mon Sep 17 00:00:00 2001
From: TheGamerdk <5618080+TheGamerdk@users.noreply.github.com>
Date: Tue, 14 Dec 2021 20:06:31 +0100
Subject: [PATCH 68/93] Update expansion_card_holder.dm
---
.../mob/living/silicon/ai/decentralized/expansion_card_holder.dm | 1 +
1 file changed, 1 insertion(+)
diff --git a/code/modules/mob/living/silicon/ai/decentralized/expansion_card_holder.dm b/code/modules/mob/living/silicon/ai/decentralized/expansion_card_holder.dm
index e930d533b302..b899b53cb63e 100644
--- a/code/modules/mob/living/silicon/ai/decentralized/expansion_card_holder.dm
+++ b/code/modules/mob/living/silicon/ai/decentralized/expansion_card_holder.dm
@@ -102,6 +102,7 @@ GLOBAL_LIST_EMPTY(expansion_card_holders)
var/turf/T = get_turf(src)
for(var/obj/item/C in installed_cards)
C.forceMove(T)
+ installed_cards.len = 0
total_cpu = 0
total_ram = 0
GLOB.ai_os.update_hardware()
From ef3becef3393df8cc3ab900137ff485e7d719f9e Mon Sep 17 00:00:00 2001
From: TheGamerdk <5618080+TheGamerdk@users.noreply.github.com>
Date: Wed, 15 Dec 2021 20:56:49 +0100
Subject: [PATCH 69/93] Minor fixes (Including weird fail on can_see when
you've just spawned in)
---
code/modules/mob/living/silicon/ai/ai.dm | 8 ++++++--
.../ai/decentralized/management/ai_controlpanel.dm | 1 +
code/modules/mob/living/silicon/ai/freelook/cameranet.dm | 5 -----
code/modules/mob/living/silicon/ai/login.dm | 5 +++--
tgui/packages/tgui/interfaces/AiControlPanel.js | 6 +++---
tgui/packages/tgui/interfaces/AiDashboard.js | 4 ++--
6 files changed, 15 insertions(+), 14 deletions(-)
diff --git a/code/modules/mob/living/silicon/ai/ai.dm b/code/modules/mob/living/silicon/ai/ai.dm
index 8358bbf40963..7a4a150ba329 100644
--- a/code/modules/mob/living/silicon/ai/ai.dm
+++ b/code/modules/mob/living/silicon/ai/ai.dm
@@ -112,6 +112,8 @@
//Reduces/Increases download speed by this modifier
var/downloadSpeedModifier = 1
+ var/login_warned_temp = FALSE
+
/mob/living/silicon/ai/Initialize(mapload, datum/ai_laws/L, mob/target_ai, shunted)
. = ..()
@@ -119,6 +121,9 @@
// new/obj/structure/AIcore/deactivated(loc) //New empty terminal.
return INITIALIZE_HINT_QDEL //Delete AI.
+ if(!istype(loc, /obj/machinery/ai/data_core) && !shunted)
+ relocate(TRUE)
+
if(L && istype(L, /datum/ai_laws))
laws = L
laws.associate(src)
@@ -145,6 +150,7 @@
to_chat(src, "These laws may be changed by other players, or by you being the traitor.")
job = "AI"
+
create_eye()
if(client)
@@ -183,8 +189,6 @@
GLOB.ai_list += src
GLOB.shuttle_caller_list += src
- if(!istype(loc, /obj/machinery/ai/data_core) && !shunted)
- relocate(TRUE)
builtInCamera = new (src)
builtInCamera.c_tag = real_name
diff --git a/code/modules/mob/living/silicon/ai/decentralized/management/ai_controlpanel.dm b/code/modules/mob/living/silicon/ai/decentralized/management/ai_controlpanel.dm
index e7b33588b9e6..657f9172e391 100644
--- a/code/modules/mob/living/silicon/ai/decentralized/management/ai_controlpanel.dm
+++ b/code/modules/mob/living/silicon/ai/decentralized/management/ai_controlpanel.dm
@@ -147,6 +147,7 @@
if(downloading)
data["downloading"] = downloading.real_name
data["download_progress"] = download_progress
+ data["downloading_ref"] = REF(downloading)
else
data["downloading"] = null
data["download_progress"] = 0
diff --git a/code/modules/mob/living/silicon/ai/freelook/cameranet.dm b/code/modules/mob/living/silicon/ai/freelook/cameranet.dm
index 81d38e08bb53..66d4296555b9 100644
--- a/code/modules/mob/living/silicon/ai/freelook/cameranet.dm
+++ b/code/modules/mob/living/silicon/ai/freelook/cameranet.dm
@@ -77,11 +77,6 @@ GLOBAL_DATUM_INIT(cameranet, /datum/cameranet, new)
var/x_value = eye.x
var/y_value = eye.y
var/z_value = eye.z
- if(istype(eye.loc, /obj/machinery/ai/data_core))
- var/turf/T = get_turf(eye.loc)
- x_value = T.x
- y_value = T.y
- z_value = T.z
// 0xf = 15
var/static_range = eye.static_visibility_range
var/x1 = max(0, x_value - static_range) & ~(CHUNK_SIZE - 1)
diff --git a/code/modules/mob/living/silicon/ai/login.dm b/code/modules/mob/living/silicon/ai/login.dm
index 3785ee088b48..684f85428322 100644
--- a/code/modules/mob/living/silicon/ai/login.dm
+++ b/code/modules/mob/living/silicon/ai/login.dm
@@ -10,5 +10,6 @@
if(multicam_on)
end_multicam()
view_core()
-
- to_chat(src, span_userdanger("WARNING. THE WAY AI IS PLAYED HAS CHANGED. PLEASE REFER TO https://github.com/yogstation13/Yogstation/pull/12388"))
+ if(!login_warned_temp)
+ to_chat(src, span_userdanger("WARNING. THE WAY AI IS PLAYED HAS CHANGED. PLEASE REFER TO https://github.com/yogstation13/Yogstation/pull/12388"))
+ login_warned_temp = TRUE
diff --git a/tgui/packages/tgui/interfaces/AiControlPanel.js b/tgui/packages/tgui/interfaces/AiControlPanel.js
index df4dc4759670..c1ba6efd2c08 100644
--- a/tgui/packages/tgui/interfaces/AiControlPanel.js
+++ b/tgui/packages/tgui/interfaces/AiControlPanel.js
@@ -80,6 +80,9 @@ export const AiControlPanel = (props, context) => {
Currently downloading G2 act("stop_download")}>Cancel Download
+ {!!data.current_ai_ref && data.current_ai_ref === data.downloading_ref && (
+ act("skip_download")}>Instantly finish download
+ )}
)|| (
@@ -98,9 +101,6 @@ export const AiControlPanel = (props, context) => {
{!!ai.being_hijacked && (
act("stop_hijack", { target_ai: ai.ref })}>Stop hijacking
)}
- {!!data.current_ai_ref && data.current_ai_ref === ai.ref && (
- act("skip_download")}>Instantly finish download
- )}
)}>
Integrity:
diff --git a/tgui/packages/tgui/interfaces/AiDashboard.js b/tgui/packages/tgui/interfaces/AiDashboard.js
index ad82549afd7c..37963f159e6b 100644
--- a/tgui/packages/tgui/interfaces/AiDashboard.js
+++ b/tgui/packages/tgui/interfaces/AiDashboard.js
@@ -13,7 +13,7 @@ export const AiDashboard = (props, context) => {
return (
@@ -133,7 +133,7 @@ export const AiDashboard = (props, context) => {
)}>
Research Cost: {project.research_cost} THzRAM Requirement: {project.ram_required} TB
- Research Requirements:
+ Research Requirements:  
{project.research_requirements}
From 83d828959c5b1b9564bbf078b6adf7c69afb7987 Mon Sep 17 00:00:00 2001
From: TheGamerdk <5618080+TheGamerdk@users.noreply.github.com>
Date: Thu, 16 Dec 2021 12:25:16 +0100
Subject: [PATCH 70/93] oldstation goodbye
---
_maps/RandomRuins/SpaceRuins/oldstation.dmm | 9 ++++-----
1 file changed, 4 insertions(+), 5 deletions(-)
diff --git a/_maps/RandomRuins/SpaceRuins/oldstation.dmm b/_maps/RandomRuins/SpaceRuins/oldstation.dmm
index cbfc326abb8f..db49c4445f9e 100644
--- a/_maps/RandomRuins/SpaceRuins/oldstation.dmm
+++ b/_maps/RandomRuins/SpaceRuins/oldstation.dmm
@@ -705,10 +705,6 @@
},
/turf/open/floor/plasteel,
/area/ruin/space/has_grav/ancientstation/comm)
-"bQ" = (
-/obj/structure/AIcore/deactivated,
-/turf/open/floor/plasteel/dark,
-/area/ruin/space/has_grav/ancientstation/deltaai)
"bR" = (
/obj/machinery/light/small{
brightness = 3;
@@ -8797,6 +8793,9 @@
/obj/structure/cable,
/turf/open/floor/plating,
/area/ruin/space/has_grav/ancientstation/engi)
+"XP" = (
+/turf/open/floor/plasteel/dark,
+/area/ruin/space/has_grav/ancientstation/deltaai)
"Yh" = (
/obj/effect/decal/cleanable/dirt,
/obj/effect/decal/cleanable/dirt,
@@ -12871,7 +12870,7 @@ gK
ac
ac
ac
-bQ
+XP
ac
ac
ac
From 49c116616a365fbaf6c90440b9bcdca2a82d9f1f Mon Sep 17 00:00:00 2001
From: TheGamerdk <5618080+TheGamerdk@users.noreply.github.com>
Date: Thu, 16 Dec 2021 12:31:56 +0100
Subject: [PATCH 71/93] maps
---
_maps/RandomRuins/SpaceRuins/oldstation.dmm | 8 ++---
.../EclipseStation/EclipseStation.dmm | 25 +++++----------
_maps/map_files/IceBox/IceBox.dmm | 26 +++++++--------
_maps/map_files/KiloStation/KiloStation.dmm | 32 +++++++++----------
_maps/map_files/YogStation/YogStation.dmm | 27 +++++++---------
_maps/map_files/YogsDelta/YogsDelta.dmm | 16 +++++-----
_maps/map_files/Yogsmeta/Yogsmeta.dmm | 21 ++++++------
7 files changed, 67 insertions(+), 88 deletions(-)
diff --git a/_maps/RandomRuins/SpaceRuins/oldstation.dmm b/_maps/RandomRuins/SpaceRuins/oldstation.dmm
index db49c4445f9e..6c670fa42b6f 100644
--- a/_maps/RandomRuins/SpaceRuins/oldstation.dmm
+++ b/_maps/RandomRuins/SpaceRuins/oldstation.dmm
@@ -8571,6 +8571,9 @@
},
/turf/open/floor/plasteel,
/area/ruin/space/has_grav/ancientstation/hydroponics)
+"QV" = (
+/turf/open/floor/plasteel/dark,
+/area/ruin/space/has_grav/ancientstation/deltaai)
"Re" = (
/obj/effect/decal/cleanable/dirt,
/obj/effect/decal/cleanable/dirt,
@@ -8793,9 +8796,6 @@
/obj/structure/cable,
/turf/open/floor/plating,
/area/ruin/space/has_grav/ancientstation/engi)
-"XP" = (
-/turf/open/floor/plasteel/dark,
-/area/ruin/space/has_grav/ancientstation/deltaai)
"Yh" = (
/obj/effect/decal/cleanable/dirt,
/obj/effect/decal/cleanable/dirt,
@@ -12870,7 +12870,7 @@ gK
ac
ac
ac
-XP
+QV
ac
ac
ac
diff --git a/_maps/map_files/EclipseStation/EclipseStation.dmm b/_maps/map_files/EclipseStation/EclipseStation.dmm
index ab57391f6128..2828dfe0373d 100644
--- a/_maps/map_files/EclipseStation/EclipseStation.dmm
+++ b/_maps/map_files/EclipseStation/EclipseStation.dmm
@@ -21584,12 +21584,6 @@
},
/turf/closed/wall/r_wall,
/area/crew_quarters/heads/captain)
-"aVo" = (
-/obj/machinery/atmospherics/components/unary/vent_pump/on/layer2{
- dir = 1
- },
-/turf/open/floor/plasteel,
-/area/hallway/primary/port)
"aVp" = (
/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden/layer4{
dir = 1
@@ -59293,14 +59287,6 @@
},
/turf/open/floor/carpet/purple,
/area/crew_quarters/heads/hor)
-"cto" = (
-/obj/structure/rack,
-/obj/item/circuitboard/aicore{
- pixel_x = -2;
- pixel_y = 4
- },
-/turf/open/floor/plasteel,
-/area/crew_quarters/heads/hor)
"ctp" = (
/obj/structure/rack,
/obj/item/taperecorder{
@@ -87566,6 +87552,11 @@
/obj/effect/turf_decal/tile/white,
/turf/open/floor/plasteel,
/area/hallway/primary/fore)
+"rLe" = (
+/obj/structure/rack,
+/obj/item/circuitboard/computer/ai_upload_download,
+/turf/open/floor/plasteel,
+/area/crew_quarters/heads/hor)
"rLM" = (
/obj/structure/cable{
icon_state = "4-8";
@@ -124360,7 +124351,7 @@ crA
cvA
cwh
csO
-cto
+rLe
cOk
aoU
aaa
@@ -141471,7 +141462,7 @@ azB
hMY
aRF
aUP
-aVo
+aye
axD
aWW
bas
@@ -146610,7 +146601,7 @@ aBj
aBj
aJK
aRX
-aVo
+aye
ach
aFk
aFk
diff --git a/_maps/map_files/IceBox/IceBox.dmm b/_maps/map_files/IceBox/IceBox.dmm
index e4c7d67bf5ae..d4e8b27c9612 100644
--- a/_maps/map_files/IceBox/IceBox.dmm
+++ b/_maps/map_files/IceBox/IceBox.dmm
@@ -37502,20 +37502,6 @@
/obj/effect/landmark/event_spawn,
/turf/open/floor/plasteel,
/area/storage/primary)
-"bxl" = (
-/obj/structure/rack,
-/obj/item/circuitboard/aicore{
- pixel_x = -2;
- pixel_y = 4
- },
-/obj/effect/turf_decal/stripes/line{
- dir = 9
- },
-/obj/structure/sign/plaques/cave{
- pixel_y = 32
- },
-/turf/open/floor/plasteel/white,
-/area/crew_quarters/heads/hor)
"bxm" = (
/obj/effect/spawner/xmastree/rdrod,
/obj/effect/turf_decal/stripes/line{
@@ -60149,6 +60135,16 @@
"nds" = (
/turf/open/floor/plasteel,
/area/maintenance/disposal/incinerator)
+"nfL" = (
+/obj/structure/rack,
+/obj/effect/turf_decal/stripes/line{
+ dir = 9
+ },
+/obj/structure/sign/plaques/cave{
+ pixel_y = 32
+ },
+/turf/open/floor/plasteel/white,
+/area/crew_quarters/heads/hor)
"ngU" = (
/obj/effect/turf_decal/stripes/line{
dir = 8
@@ -113694,7 +113690,7 @@ bqk
brp
bmW
bvK
-bxl
+nfL
bys
bzM
bya
diff --git a/_maps/map_files/KiloStation/KiloStation.dmm b/_maps/map_files/KiloStation/KiloStation.dmm
index 4f0afde61641..56bd128baf41 100644
--- a/_maps/map_files/KiloStation/KiloStation.dmm
+++ b/_maps/map_files/KiloStation/KiloStation.dmm
@@ -92182,6 +92182,20 @@
/obj/item/clothing/mask/cigarette/cigar/cohiba,
/turf/open/floor/plasteel,
/area/crew_quarters/heads/chief)
+"kSR" = (
+/obj/effect/turf_decal/bot,
+/obj/effect/turf_decal/tile/neutral{
+ dir = 4
+ },
+/obj/effect/turf_decal/tile/neutral{
+ dir = 1
+ },
+/obj/effect/turf_decal/tile/neutral,
+/obj/structure/table,
+/obj/item/hand_labeler,
+/obj/item/circuitboard/computer/ai_upload_download,
+/turf/open/floor/plasteel/dark,
+/area/crew_quarters/heads/hor)
"kTk" = (
/obj/effect/turf_decal/tile/neutral{
dir = 4
@@ -98916,22 +98930,6 @@
/obj/effect/mapping_helpers/teleport_anchor,
/turf/open/floor/plasteel/showroomfloor,
/area/science/server)
-"smx" = (
-/obj/effect/turf_decal/bot,
-/obj/effect/turf_decal/tile/neutral{
- dir = 4
- },
-/obj/effect/turf_decal/tile/neutral{
- dir = 1
- },
-/obj/effect/turf_decal/tile/neutral,
-/obj/structure/table,
-/obj/item/hand_labeler,
-/obj/item/circuitboard/aicore{
- pixel_y = 5
- },
-/turf/open/floor/plasteel/dark,
-/area/crew_quarters/heads/hor)
"snc" = (
/obj/effect/turf_decal/tile/yellow,
/obj/effect/turf_decal/tile/yellow{
@@ -143026,7 +143024,7 @@ smw
ayt
azR
aAu
-smx
+kSR
aVJ
aVJ
aYU
diff --git a/_maps/map_files/YogStation/YogStation.dmm b/_maps/map_files/YogStation/YogStation.dmm
index 7f7b31b811f9..67ac35ef1f08 100644
--- a/_maps/map_files/YogStation/YogStation.dmm
+++ b/_maps/map_files/YogStation/YogStation.dmm
@@ -23935,20 +23935,6 @@
/obj/effect/landmark/event_spawn,
/turf/open/floor/plasteel,
/area/storage/primary)
-"bxl" = (
-/obj/structure/rack,
-/obj/item/circuitboard/aicore{
- pixel_x = -2;
- pixel_y = 4
- },
-/obj/effect/turf_decal/stripes/line{
- dir = 9
- },
-/obj/structure/sign/plaques/cave{
- pixel_y = 32
- },
-/turf/open/floor/plasteel/white,
-/area/crew_quarters/heads/hor)
"bxm" = (
/obj/effect/spawner/xmastree/rdrod,
/obj/effect/turf_decal/stripes/line{
@@ -64706,6 +64692,17 @@
},
/turf/open/floor/plasteel/dark,
/area/science/xenobiology)
+"xAi" = (
+/obj/structure/rack,
+/obj/effect/turf_decal/stripes/line{
+ dir = 9
+ },
+/obj/structure/sign/plaques/cave{
+ pixel_y = 32
+ },
+/obj/item/circuitboard/computer/ai_upload_download,
+/turf/open/floor/plasteel/white,
+/area/crew_quarters/heads/hor)
"xAP" = (
/obj/structure/rack,
/obj/item/electronics/airlock,
@@ -115422,7 +115419,7 @@ bqk
brp
bmW
bvK
-bxl
+xAi
bys
bzM
bya
diff --git a/_maps/map_files/YogsDelta/YogsDelta.dmm b/_maps/map_files/YogsDelta/YogsDelta.dmm
index e6b12352833a..bccf9008d0d7 100644
--- a/_maps/map_files/YogsDelta/YogsDelta.dmm
+++ b/_maps/map_files/YogsDelta/YogsDelta.dmm
@@ -108326,13 +108326,6 @@
/obj/machinery/atmospherics/pipe/simple/supply/hidden/layer2,
/turf/open/floor/plasteel/dark,
/area/engine/atmos)
-"doM" = (
-/obj/structure/table/reinforced,
-/obj/item/aicard,
-/obj/item/circuitboard/aicore,
-/obj/effect/turf_decal/bot,
-/turf/open/floor/plasteel,
-/area/crew_quarters/heads/hor)
"doN" = (
/obj/structure/cable/white{
icon_state = "1-2"
@@ -128879,6 +128872,13 @@
/obj/machinery/griddle,
/turf/open/floor/plasteel,
/area/crew_quarters/kitchen)
+"xBj" = (
+/obj/structure/table/reinforced,
+/obj/item/aicard,
+/obj/effect/turf_decal/bot,
+/obj/item/circuitboard/computer/ai_upload_download,
+/turf/open/floor/plasteel,
+/area/crew_quarters/heads/hor)
"xBR" = (
/obj/machinery/atmospherics/pipe/simple/supply/hidden/layer2{
dir = 8
@@ -163153,7 +163153,7 @@ cgA
ceU
dlE
dmS
-doM
+xBj
dqC
drX
dtq
diff --git a/_maps/map_files/Yogsmeta/Yogsmeta.dmm b/_maps/map_files/Yogsmeta/Yogsmeta.dmm
index 2633b515679a..0c0f09f7486e 100644
--- a/_maps/map_files/Yogsmeta/Yogsmeta.dmm
+++ b/_maps/map_files/Yogsmeta/Yogsmeta.dmm
@@ -59457,17 +59457,6 @@
dir = 5
},
/area/crew_quarters/heads/hor)
-"cuP" = (
-/obj/structure/table,
-/obj/item/aicard,
-/obj/item/circuitboard/aicore{
- pixel_x = -2;
- pixel_y = 4
- },
-/turf/open/floor/plasteel/cafeteria{
- dir = 5
- },
-/area/crew_quarters/heads/hor)
"cuQ" = (
/turf/open/floor/plasteel/cafeteria{
dir = 5
@@ -80036,6 +80025,14 @@
/obj/effect/landmark/blobstart,
/turf/open/floor/plating,
/area/maintenance/port/fore)
+"sTq" = (
+/obj/structure/table,
+/obj/item/aicard,
+/obj/item/circuitboard/computer/ai_upload_download,
+/turf/open/floor/plasteel/cafeteria{
+ dir = 5
+ },
+/area/crew_quarters/heads/hor)
"sTu" = (
/obj/structure/closet/firecloset,
/obj/effect/turf_decal/stripes/corner{
@@ -116274,7 +116271,7 @@ cdc
crQ
ctc
ctT
-cuP
+sTq
bHF
cwS
crQ
From 833619abb8e137d9648331efb0f0985da2cfbe9c Mon Sep 17 00:00:00 2001
From: TheGamerdk <5618080+TheGamerdk@users.noreply.github.com>
Date: Thu, 16 Dec 2021 12:39:34 +0100
Subject: [PATCH 72/93] removes the AI core from the game
---
code/game/mecha/mecha.dm | 22 +-
.../game/objects/effects/spawners/lootdrop.dm | 3 +-
.../items/stacks/sheets/sheet_types.dm | 1 -
code/game/objects/structures/ai_core.dm | 204 +-----------------
code/modules/jobs/job_types/ai.dm | 6 +-
code/modules/mob/living/silicon/ai/ai.dm | 5 +-
.../research/designs/AI_module_designs.dm | 8 -
7 files changed, 22 insertions(+), 227 deletions(-)
diff --git a/code/game/mecha/mecha.dm b/code/game/mecha/mecha.dm
index 5b1497da022b..00cb49e06440 100644
--- a/code/game/mecha/mecha.dm
+++ b/code/game/mecha/mecha.dm
@@ -795,7 +795,6 @@
to_chat(user, "[span_boldnotice("Transfer successful")]: [AI.name] ([rand(1000,9999)].exe) removed from [name] and stored within local memory.")
if(AI_MECH_HACK) //Called by AIs on the mech
- AI.linked_core = new /obj/structure/AIcore/deactivated(AI.loc)
if(AI.can_dominate_mechs)
if(occupant) //Oh, I am sorry, were you using that?
to_chat(AI, span_warning("Pilot detected! Forced ejection initiated!"))
@@ -1053,6 +1052,7 @@
if(!occupant)
return
var/atom/movable/mob_container
+ var/is_ai_user = FALSE
occupant.clear_alert("charge")
occupant.clear_alert("mech damage")
if(ishuman(occupant))
@@ -1071,23 +1071,23 @@
silicon_pilot = FALSE
return
else
- if(!AI.linked_core)
- to_chat(AI, span_userdanger("Inactive core destroyed. Unable to return."))
- AI.linked_core = null
- return
- to_chat(AI, span_notice("Returning to core..."))
+ to_chat(AI, span_notice("Attempting to return to core..."))
AI.controlled_mech = null
AI.remote_control = null
RemoveActions(occupant, 1)
mob_container = AI
- newloc = get_turf(AI.linked_core)
- qdel(AI.linked_core)
+ newloc = GLOB.primary_data_core ? GLOB.primary_data_core : GLOB.data_cores[1]
+ if(!newloc)
+ to_chat(AI, span_userdanger("No cores available. Core code corrupted. Goodbye."))
+ qdel(AI)
+ return
+ is_ai_user = TRUE
else
return
var/mob/living/L = occupant
occupant = null //we need it null when forceMove calls Exited().
silicon_pilot = FALSE
- if(mob_container.forceMove(newloc))//ejecting mob container
+ if(mob_container.forceMove(newloc) && !is_ai_user)//ejecting mob container
log_message("[mob_container] moved out.", LOG_MECHA)
L << browse(null, "window=exosuit")
@@ -1101,6 +1101,10 @@
L.mobility_flags = NONE
icon_state = initial(icon_state)+"-open"
setDir(dir_in)
+ if(is_ai_user)
+ var/mob/living/silicon/ai/AI = occupant
+ AI.relocate(TRUE)
+
if(L && L.client)
L.update_mouse_pointer()
diff --git a/code/game/objects/effects/spawners/lootdrop.dm b/code/game/objects/effects/spawners/lootdrop.dm
index f7a15cdfdebb..56dd8d33adcf 100644
--- a/code/game/objects/effects/spawners/lootdrop.dm
+++ b/code/game/objects/effects/spawners/lootdrop.dm
@@ -355,8 +355,7 @@
name = "secure AI circuit board spawner"
loot = list(
/obj/item/circuitboard/computer/aiupload,
- /obj/item/circuitboard/computer/borgupload,
- /obj/item/circuitboard/aicore
+ /obj/item/circuitboard/computer/borgupload
)
/obj/effect/spawner/lootdrop/techstorage/command
diff --git a/code/game/objects/items/stacks/sheets/sheet_types.dm b/code/game/objects/items/stacks/sheets/sheet_types.dm
index e06b3d36b89f..3657d609ba45 100644
--- a/code/game/objects/items/stacks/sheets/sheet_types.dm
+++ b/code/game/objects/items/stacks/sheets/sheet_types.dm
@@ -156,7 +156,6 @@ GLOBAL_LIST_INIT(metal_recipes, list ( \
* Plasteel
*/
GLOBAL_LIST_INIT(plasteel_recipes, list ( \
- new/datum/stack_recipe("AI core", /obj/structure/AIcore, 4, time = 50, one_per_turf = TRUE), \
new/datum/stack_recipe("bomb assembly", /obj/machinery/syndicatebomb/empty, 10, time = 50), \
null, \
new /datum/stack_recipe_list("airlock assemblies", list( \
diff --git a/code/game/objects/structures/ai_core.dm b/code/game/objects/structures/ai_core.dm
index a5affa9b444f..251d26121d97 100644
--- a/code/game/objects/structures/ai_core.dm
+++ b/code/game/objects/structures/ai_core.dm
@@ -8,9 +8,8 @@
max_integrity = 500
var/state = EMPTY_CORE
var/datum/ai_laws/laws
- var/obj/item/circuitboard/aicore/circuit
var/obj/item/mmi/brain
- var/can_deconstruct = TRUE
+ var/can_deconstruct = FALSE
/obj/structure/AIcore/Initialize()
. = ..()
@@ -18,29 +17,20 @@
laws.set_laws_config()
/obj/structure/AIcore/handle_atom_del(atom/A)
- if(A == circuit)
- circuit = null
- if((state != GLASS_CORE) && (state != AI_READY_CORE))
- state = EMPTY_CORE
- update_icon()
if(A == brain)
brain = null
. = ..()
/obj/structure/AIcore/Destroy()
- if(circuit)
- qdel(circuit)
- circuit = null
if(brain)
qdel(brain)
brain = null
return ..()
/obj/structure/AIcore/latejoin_inactive
- name = "networked AI core"
- desc = "This AI core is connected by bluespace transmitters to NTNet, allowing for an AI personality to be downloaded to it on the fly mid-shift."
- can_deconstruct = FALSE
+ name = "networked AI beacon"
+ desc = "This machine is connected by bluespace transmitters to NTNet, allowing for an AI personality to be downloaded to it on the fly mid-shift."
icon_state = "ai-empty"
anchored = TRUE
state = AI_READY_CORE
@@ -104,167 +94,6 @@
to_chat(user, span_notice("You deconstruct the frame."))
deconstruct(TRUE)
return
- else
- switch(state)
- if(EMPTY_CORE)
- if(istype(P, /obj/item/circuitboard/aicore))
- if(!user.transferItemToLoc(P, src))
- return
- playsound(loc, 'sound/items/deconstruct.ogg', 50, 1)
- to_chat(user, span_notice("You place the circuit board inside the frame."))
- update_icon()
- state = CIRCUIT_CORE
- circuit = P
- return
- if(CIRCUIT_CORE)
- if(P.tool_behaviour == TOOL_SCREWDRIVER)
- P.play_tool_sound(src)
- to_chat(user, span_notice("You screw the circuit board into place."))
- state = SCREWED_CORE
- update_icon()
- return
- if(P.tool_behaviour == TOOL_CROWBAR)
- P.play_tool_sound(src)
- to_chat(user, span_notice("You remove the circuit board."))
- state = EMPTY_CORE
- update_icon()
- circuit.forceMove(loc)
- circuit = null
- return
- if(SCREWED_CORE)
- if(P.tool_behaviour == TOOL_SCREWDRIVER && circuit)
- P.play_tool_sound(src)
- to_chat(user, span_notice("You unfasten the circuit board."))
- state = CIRCUIT_CORE
- update_icon()
- return
- if(istype(P, /obj/item/stack/cable_coil))
- var/obj/item/stack/cable_coil/C = P
- if(C.get_amount() >= 5)
- playsound(loc, 'sound/items/deconstruct.ogg', 50, 1)
- to_chat(user, span_notice("You start to add cables to the frame..."))
- if(do_after(user, 2 SECONDS, target = src) && state == SCREWED_CORE && C.use(5))
- to_chat(user, span_notice("You add cables to the frame."))
- state = CABLED_CORE
- update_icon()
- else
- to_chat(user, span_warning("You need five lengths of cable to wire the AI core!"))
- return
- if(CABLED_CORE)
- if(P.tool_behaviour == TOOL_WIRECUTTER)
- if(brain)
- to_chat(user, span_warning("Get that [brain.name] out of there first!"))
- else
- P.play_tool_sound(src)
- to_chat(user, span_notice("You remove the cables."))
- state = SCREWED_CORE
- update_icon()
- new /obj/item/stack/cable_coil(drop_location(), 5)
- return
-
- if(istype(P, /obj/item/stack/sheet/rglass))
- var/obj/item/stack/sheet/rglass/G = P
- if(G.get_amount() >= 2)
- playsound(loc, 'sound/items/deconstruct.ogg', 50, 1)
- to_chat(user, span_notice("You start to put in the glass panel..."))
- if(do_after(user, 2 SECONDS, target = src) && state == CABLED_CORE && G.use(2))
- to_chat(user, span_notice("You put in the glass panel."))
- state = GLASS_CORE
- update_icon()
- else
- to_chat(user, span_warning("You need two sheets of reinforced glass to insert them into the AI core!"))
- return
-
- if(istype(P, /obj/item/aiModule))
- if(brain && brain.laws.id != DEFAULT_AI_LAWID)
- to_chat(user, span_warning("The installed [brain.name] already has set laws!"))
- return
- var/obj/item/aiModule/module = P
- module.install(laws, user)
- return
-
- if(istype(P, /obj/item/mmi) && !brain)
- var/obj/item/mmi/M = P
- if(!M.brainmob)
- to_chat(user, span_warning("Sticking an empty [M.name] into the frame would sort of defeat the purpose!"))
- return
- if(M.brainmob.stat == DEAD)
- to_chat(user, span_warning("Sticking a dead [M.name] into the frame would sort of defeat the purpose!"))
- return
-
- if(!M.brainmob.client)
- to_chat(user, span_warning("Sticking an inactive [M.name] into the frame would sort of defeat the purpose."))
- return
-
- if(!CONFIG_GET(flag/allow_ai) || (is_banned_from(M.brainmob.ckey, "AI") && !QDELETED(src) && !QDELETED(user) && !QDELETED(M) && !QDELETED(user) && Adjacent(user)))
- if(!QDELETED(M))
- to_chat(user, span_warning("This [M.name] does not seem to fit!"))
- return
-
- if(!M.brainmob.mind)
- to_chat(user, span_warning("This [M.name] is mindless!"))
- return
-
- if(!user.transferItemToLoc(M,src))
- return
-
- brain = M
- to_chat(user, span_notice("You add [M.name] to the frame."))
- update_icon()
- return
-
- if(P.tool_behaviour == TOOL_CROWBAR && brain)
- P.play_tool_sound(src)
- to_chat(user, span_notice("You remove the brain."))
- brain.forceMove(loc)
- brain = null
- update_icon()
- return
-
- if(GLASS_CORE)
- if(P.tool_behaviour == TOOL_CROWBAR)
- P.play_tool_sound(src)
- to_chat(user, span_notice("You remove the glass panel."))
- state = CABLED_CORE
- update_icon()
- new /obj/item/stack/sheet/rglass(loc, 2)
- return
-
- if(P.tool_behaviour == TOOL_SCREWDRIVER)
- P.play_tool_sound(src)
- to_chat(user, span_notice("You connect the monitor."))
- if(brain)
- SSticker.mode.remove_antag_for_borging(brain.brainmob.mind)
- if(!istype(brain.laws, /datum/ai_laws/ratvar))
- remove_servant_of_ratvar(brain.brainmob, TRUE)
-
- var/mob/living/silicon/ai/A = null
-
- if (brain.overrides_aicore_laws)
- A = new /mob/living/silicon/ai(loc, brain.laws, brain.brainmob)
- else
- A = new /mob/living/silicon/ai(loc, laws, brain.brainmob)
-
- if(brain.force_replace_ai_name)
- A.fully_replace_character_name(A.name, brain.replacement_ai_name())
- SSblackbox.record_feedback("amount", "ais_created", 1)
- qdel(src)
- else
- state = AI_READY_CORE
- update_icon()
- return
-
- if(AI_READY_CORE)
- if(istype(P, /obj/item/aicard))
- P.transfer_ai("INACTIVE", "AICARD", src, user)
- return
-
- if(P.tool_behaviour == TOOL_SCREWDRIVER)
- P.play_tool_sound(src)
- to_chat(user, span_notice("You disconnect the monitor."))
- state = GLASS_CORE
- update_icon()
- return
return ..()
/obj/structure/AIcore/update_icon()
@@ -285,28 +114,6 @@
if(AI_READY_CORE)
icon_state = "ai-empty"
-/obj/structure/AIcore/deconstruct(disassembled = TRUE)
- if(state == GLASS_CORE)
- new /obj/item/stack/sheet/rglass(loc, 2)
- if(state >= CABLED_CORE)
- new /obj/item/stack/cable_coil(loc, 5)
- if(circuit)
- circuit.forceMove(loc)
- circuit = null
- new /obj/item/stack/sheet/plasteel(loc, 4)
- qdel(src)
-
-/obj/structure/AIcore/deactivated
- name = "inactive AI"
- icon_state = "ai-empty"
- anchored = TRUE
- state = AI_READY_CORE
-
-/obj/structure/AIcore/deactivated/Initialize()
- . = ..()
- circuit = new(src)
-
-
/*
This is a good place for AI-related object verbs so I'm sticking it here.
If adding stuff to this, don't forget that an AI need to cancel_camera() whenever it physically moves to a different location.
@@ -322,6 +129,7 @@ That prevents a few funky behaviors.
return FALSE
return TRUE
+/* Unused for now, just here for reference
/obj/structure/AIcore/transfer_ai(interaction, mob/user, mob/living/silicon/ai/AI, obj/item/aicard/card)
if(state != AI_READY_CORE || !..())
return
@@ -338,6 +146,4 @@ That prevents a few funky behaviors.
else //If for some reason you use an empty card on an empty AI terminal.
to_chat(user, "There is no AI loaded on this terminal!")
-/obj/item/circuitboard/aicore
- name = "AI core (AI Core Board)" //Well, duh, but best to be consistent
- var/battery = 200 //backup battery for when the AI loses power. Copied to/from AI mobs when carding, and placed here to avoid recharge via deconning the core
+*/
diff --git a/code/modules/jobs/job_types/ai.dm b/code/modules/jobs/job_types/ai.dm
index 2898b6529101..f1f15745e924 100644
--- a/code/modules/jobs/job_types/ai.dm
+++ b/code/modules/jobs/job_types/ai.dm
@@ -25,9 +25,8 @@
/datum/job/ai/after_spawn(mob/H, mob/M, latejoin)
. = ..()
- /*
+
if(latejoin)
-
var/obj/structure/AIcore/latejoin_inactive/lateJoinCore
for(var/obj/structure/AIcore/latejoin_inactive/P in GLOB.latejoin_ai_cores)
if(P.is_available())
@@ -36,9 +35,8 @@
break
if(lateJoinCore)
lateJoinCore.available = FALSE
- H.forceMove(lateJoinCore.loc)
qdel(lateJoinCore)
- */
+
var/mob/living/silicon/ai/AI = H
AI.relocate(TRUE)
diff --git a/code/modules/mob/living/silicon/ai/ai.dm b/code/modules/mob/living/silicon/ai/ai.dm
index 7a4a150ba329..8491c64bfebc 100644
--- a/code/modules/mob/living/silicon/ai/ai.dm
+++ b/code/modules/mob/living/silicon/ai/ai.dm
@@ -86,7 +86,6 @@
var/acceleration = 1
var/max_camera_sprint = 50
- var/obj/structure/AIcore/deactivated/linked_core //For exosuit control
var/mob/living/silicon/robot/deployed_shell = null //For shell control
var/datum/action/innate/deploy_shell/deploy_action = new
var/datum/action/innate/deploy_last_shell/redeploy_action = new
@@ -118,7 +117,6 @@
/mob/living/silicon/ai/Initialize(mapload, datum/ai_laws/L, mob/target_ai, shunted)
. = ..()
if(!target_ai) //If there is no player/brain inside.
- // new/obj/structure/AIcore/deactivated(loc) //New empty terminal.
return INITIALIZE_HINT_QDEL //Delete AI.
if(!istype(loc, /obj/machinery/ai/data_core) && !shunted)
@@ -863,8 +861,7 @@
return
ShutOffDoomsdayDevice()
builtInCamera.toggle_cam(user)
- //var/obj/structure/AIcore/new_core = new /obj/structure/AIcore/deactivated(loc)//Spawns a deactivated terminal at AI location.
- //new_core.circuit.battery = battery
+
ai_restore_power()//So the AI initially has power.
control_disabled = TRUE //Can't control things remotely if you're stuck in a card!
radio_enabled = FALSE //No talking on the built-in radio for you either!
diff --git a/code/modules/research/designs/AI_module_designs.dm b/code/modules/research/designs/AI_module_designs.dm
index 716433152cd6..0a75e51f9e91 100644
--- a/code/modules/research/designs/AI_module_designs.dm
+++ b/code/modules/research/designs/AI_module_designs.dm
@@ -2,14 +2,6 @@
//////////AI Module Disks//////////
///////////////////////////////////
-/datum/design/board/aicore
- name = "AI Design (AI Core)"
- desc = "Allows for the construction of circuit boards used to build new AI cores."
- id = "aicore"
- build_path = /obj/item/circuitboard/aicore
- category = list("AI Modules")
- departmental_flags = DEPARTMENTAL_FLAG_SCIENCE
-
/datum/design/board/safeguard_module
name = "Module Design (Safeguard)"
desc = "Allows for the construction of a Safeguard AI Module."
From 95b6a6a5e857171fdc04b07067d2ee60af8a855b Mon Sep 17 00:00:00 2001
From: TheGamerdk <5618080+TheGamerdk@users.noreply.github.com>
Date: Thu, 16 Dec 2021 12:40:20 +0100
Subject: [PATCH 73/93] missed one
---
_maps/RandomRuins/SpaceRuins/oldstation.dmm | 8 ++---
.../maint/10x5/10x5_oldaichamber.dmm | 9 +++---
.../EclipseStation/EclipseStation.dmm | 12 ++++----
_maps/map_files/IceBox/IceBox.dmm | 22 +++++++-------
_maps/map_files/KiloStation/KiloStation.dmm | 30 +++++++++----------
_maps/map_files/YogStation/YogStation.dmm | 24 +++++++--------
_maps/map_files/YogsDelta/YogsDelta.dmm | 16 +++++-----
_maps/map_files/Yogsmeta/Yogsmeta.dmm | 18 +++++------
8 files changed, 69 insertions(+), 70 deletions(-)
diff --git a/_maps/RandomRuins/SpaceRuins/oldstation.dmm b/_maps/RandomRuins/SpaceRuins/oldstation.dmm
index 6c670fa42b6f..612bad2abbd0 100644
--- a/_maps/RandomRuins/SpaceRuins/oldstation.dmm
+++ b/_maps/RandomRuins/SpaceRuins/oldstation.dmm
@@ -8148,6 +8148,9 @@
},
/turf/open/floor/plasteel,
/area/ruin/space/has_grav/ancientstation/atmo)
+"AC" = (
+/turf/open/floor/plasteel/dark,
+/area/ruin/space/has_grav/ancientstation/deltaai)
"AF" = (
/obj/effect/spawner/lootdrop/maintenance,
/turf/open/floor/plating,
@@ -8571,9 +8574,6 @@
},
/turf/open/floor/plasteel,
/area/ruin/space/has_grav/ancientstation/hydroponics)
-"QV" = (
-/turf/open/floor/plasteel/dark,
-/area/ruin/space/has_grav/ancientstation/deltaai)
"Re" = (
/obj/effect/decal/cleanable/dirt,
/obj/effect/decal/cleanable/dirt,
@@ -12870,7 +12870,7 @@ gK
ac
ac
ac
-QV
+AC
ac
ac
ac
diff --git a/_maps/RandomRuins/StationRuins/maint/10x5/10x5_oldaichamber.dmm b/_maps/RandomRuins/StationRuins/maint/10x5/10x5_oldaichamber.dmm
index 81963d160bf2..ed2e00f5de91 100644
--- a/_maps/RandomRuins/StationRuins/maint/10x5/10x5_oldaichamber.dmm
+++ b/_maps/RandomRuins/StationRuins/maint/10x5/10x5_oldaichamber.dmm
@@ -83,10 +83,6 @@
/obj/effect/decal/cleanable/dirt,
/turf/open/floor/plasteel/dark,
/area/template_noop)
-"p" = (
-/obj/structure/AIcore,
-/turf/open/floor/plasteel/dark,
-/area/template_noop)
"q" = (
/turf/open/floor/circuit,
/area/template_noop)
@@ -144,6 +140,9 @@
/obj/machinery/light/small/broken,
/turf/open/floor/plating,
/area/template_noop)
+"K" = (
+/turf/open/floor/plasteel/dark,
+/area/template_noop)
(1,1,1) = {"
a
@@ -162,7 +161,7 @@ x
(3,1,1) = {"
c
k
-p
+K
q
y
"}
diff --git a/_maps/map_files/EclipseStation/EclipseStation.dmm b/_maps/map_files/EclipseStation/EclipseStation.dmm
index 2828dfe0373d..b645cf94ba1c 100644
--- a/_maps/map_files/EclipseStation/EclipseStation.dmm
+++ b/_maps/map_files/EclipseStation/EclipseStation.dmm
@@ -87552,11 +87552,6 @@
/obj/effect/turf_decal/tile/white,
/turf/open/floor/plasteel,
/area/hallway/primary/fore)
-"rLe" = (
-/obj/structure/rack,
-/obj/item/circuitboard/computer/ai_upload_download,
-/turf/open/floor/plasteel,
-/area/crew_quarters/heads/hor)
"rLM" = (
/obj/structure/cable{
icon_state = "4-8";
@@ -89108,6 +89103,11 @@
/obj/effect/spawner/lootdrop/maintenance/two,
/turf/open/floor/plating,
/area/maintenance/department/security)
+"uRy" = (
+/obj/structure/rack,
+/obj/item/circuitboard/computer/ai_upload_download,
+/turf/open/floor/plasteel,
+/area/crew_quarters/heads/hor)
"uSP" = (
/obj/effect/decal/cleanable/dirt,
/obj/machinery/vending/snack/random,
@@ -124351,7 +124351,7 @@ crA
cvA
cwh
csO
-rLe
+uRy
cOk
aoU
aaa
diff --git a/_maps/map_files/IceBox/IceBox.dmm b/_maps/map_files/IceBox/IceBox.dmm
index d4e8b27c9612..cc17be7e081d 100644
--- a/_maps/map_files/IceBox/IceBox.dmm
+++ b/_maps/map_files/IceBox/IceBox.dmm
@@ -60135,16 +60135,6 @@
"nds" = (
/turf/open/floor/plasteel,
/area/maintenance/disposal/incinerator)
-"nfL" = (
-/obj/structure/rack,
-/obj/effect/turf_decal/stripes/line{
- dir = 9
- },
-/obj/structure/sign/plaques/cave{
- pixel_y = 32
- },
-/turf/open/floor/plasteel/white,
-/area/crew_quarters/heads/hor)
"ngU" = (
/obj/effect/turf_decal/stripes/line{
dir = 8
@@ -63033,6 +63023,16 @@
/obj/machinery/door/firedoor/border_only,
/turf/open/floor/plating,
/area/maintenance/port)
+"uRu" = (
+/obj/structure/rack,
+/obj/effect/turf_decal/stripes/line{
+ dir = 9
+ },
+/obj/structure/sign/plaques/cave{
+ pixel_y = 32
+ },
+/turf/open/floor/plasteel/white,
+/area/crew_quarters/heads/hor)
"uUM" = (
/obj/structure/closet/emcloset,
/obj/machinery/atmospherics/components/unary/vent_pump/layer2{
@@ -113690,7 +113690,7 @@ bqk
brp
bmW
bvK
-nfL
+uRu
bys
bzM
bya
diff --git a/_maps/map_files/KiloStation/KiloStation.dmm b/_maps/map_files/KiloStation/KiloStation.dmm
index 56bd128baf41..d5c823264fd6 100644
--- a/_maps/map_files/KiloStation/KiloStation.dmm
+++ b/_maps/map_files/KiloStation/KiloStation.dmm
@@ -92182,20 +92182,6 @@
/obj/item/clothing/mask/cigarette/cigar/cohiba,
/turf/open/floor/plasteel,
/area/crew_quarters/heads/chief)
-"kSR" = (
-/obj/effect/turf_decal/bot,
-/obj/effect/turf_decal/tile/neutral{
- dir = 4
- },
-/obj/effect/turf_decal/tile/neutral{
- dir = 1
- },
-/obj/effect/turf_decal/tile/neutral,
-/obj/structure/table,
-/obj/item/hand_labeler,
-/obj/item/circuitboard/computer/ai_upload_download,
-/turf/open/floor/plasteel/dark,
-/area/crew_quarters/heads/hor)
"kTk" = (
/obj/effect/turf_decal/tile/neutral{
dir = 4
@@ -101544,6 +101530,20 @@
/obj/effect/mapping_helpers/teleport_anchor,
/turf/open/floor/plasteel,
/area/hallway/secondary/entry)
+"vhE" = (
+/obj/effect/turf_decal/bot,
+/obj/effect/turf_decal/tile/neutral{
+ dir = 4
+ },
+/obj/effect/turf_decal/tile/neutral{
+ dir = 1
+ },
+/obj/effect/turf_decal/tile/neutral,
+/obj/structure/table,
+/obj/item/hand_labeler,
+/obj/item/circuitboard/computer/ai_upload_download,
+/turf/open/floor/plasteel/dark,
+/area/crew_quarters/heads/hor)
"viP" = (
/obj/effect/decal/cleanable/blood/old,
/obj/effect/turf_decal/stripes/corner{
@@ -143024,7 +143024,7 @@ smw
ayt
azR
aAu
-kSR
+vhE
aVJ
aVJ
aYU
diff --git a/_maps/map_files/YogStation/YogStation.dmm b/_maps/map_files/YogStation/YogStation.dmm
index 67ac35ef1f08..4a518c0e004f 100644
--- a/_maps/map_files/YogStation/YogStation.dmm
+++ b/_maps/map_files/YogStation/YogStation.dmm
@@ -35932,6 +35932,17 @@
},
/turf/open/floor/plasteel,
/area/construction/mining/aux_base)
+"fdU" = (
+/obj/structure/rack,
+/obj/effect/turf_decal/stripes/line{
+ dir = 9
+ },
+/obj/structure/sign/plaques/cave{
+ pixel_y = 32
+ },
+/obj/item/circuitboard/computer/ai_upload_download,
+/turf/open/floor/plasteel/white,
+/area/crew_quarters/heads/hor)
"feu" = (
/obj/machinery/nuclearbomb/selfdestruct,
/obj/effect/turf_decal/tile/neutral,
@@ -64692,17 +64703,6 @@
},
/turf/open/floor/plasteel/dark,
/area/science/xenobiology)
-"xAi" = (
-/obj/structure/rack,
-/obj/effect/turf_decal/stripes/line{
- dir = 9
- },
-/obj/structure/sign/plaques/cave{
- pixel_y = 32
- },
-/obj/item/circuitboard/computer/ai_upload_download,
-/turf/open/floor/plasteel/white,
-/area/crew_quarters/heads/hor)
"xAP" = (
/obj/structure/rack,
/obj/item/electronics/airlock,
@@ -115419,7 +115419,7 @@ bqk
brp
bmW
bvK
-xAi
+fdU
bys
bzM
bya
diff --git a/_maps/map_files/YogsDelta/YogsDelta.dmm b/_maps/map_files/YogsDelta/YogsDelta.dmm
index bccf9008d0d7..14649313cb8f 100644
--- a/_maps/map_files/YogsDelta/YogsDelta.dmm
+++ b/_maps/map_files/YogsDelta/YogsDelta.dmm
@@ -126518,6 +126518,13 @@
/obj/structure/bookcase/random/nonfiction,
/turf/open/floor/wood,
/area/medical/psych)
+"tcJ" = (
+/obj/structure/table/reinforced,
+/obj/item/aicard,
+/obj/effect/turf_decal/bot,
+/obj/item/circuitboard/computer/ai_upload_download,
+/turf/open/floor/plasteel,
+/area/crew_quarters/heads/hor)
"tdY" = (
/obj/item/twohanded/required/kirbyplants/random,
/obj/effect/turf_decal/tile/blue,
@@ -128872,13 +128879,6 @@
/obj/machinery/griddle,
/turf/open/floor/plasteel,
/area/crew_quarters/kitchen)
-"xBj" = (
-/obj/structure/table/reinforced,
-/obj/item/aicard,
-/obj/effect/turf_decal/bot,
-/obj/item/circuitboard/computer/ai_upload_download,
-/turf/open/floor/plasteel,
-/area/crew_quarters/heads/hor)
"xBR" = (
/obj/machinery/atmospherics/pipe/simple/supply/hidden/layer2{
dir = 8
@@ -163153,7 +163153,7 @@ cgA
ceU
dlE
dmS
-xBj
+tcJ
dqC
drX
dtq
diff --git a/_maps/map_files/Yogsmeta/Yogsmeta.dmm b/_maps/map_files/Yogsmeta/Yogsmeta.dmm
index 0c0f09f7486e..a0ba4df3b109 100644
--- a/_maps/map_files/Yogsmeta/Yogsmeta.dmm
+++ b/_maps/map_files/Yogsmeta/Yogsmeta.dmm
@@ -79277,6 +79277,14 @@
/obj/machinery/vending/snack/random,
/turf/open/floor/plasteel,
/area/maintenance/department/science)
+"rTF" = (
+/obj/structure/table,
+/obj/item/aicard,
+/obj/item/circuitboard/computer/ai_upload_download,
+/turf/open/floor/plasteel/cafeteria{
+ dir = 5
+ },
+/area/crew_quarters/heads/hor)
"rTU" = (
/obj/structure/chair/office/light{
dir = 8
@@ -80025,14 +80033,6 @@
/obj/effect/landmark/blobstart,
/turf/open/floor/plating,
/area/maintenance/port/fore)
-"sTq" = (
-/obj/structure/table,
-/obj/item/aicard,
-/obj/item/circuitboard/computer/ai_upload_download,
-/turf/open/floor/plasteel/cafeteria{
- dir = 5
- },
-/area/crew_quarters/heads/hor)
"sTu" = (
/obj/structure/closet/firecloset,
/obj/effect/turf_decal/stripes/corner{
@@ -116271,7 +116271,7 @@ cdc
crQ
ctc
ctT
-sTq
+rTF
bHF
cwS
crQ
From 593fd13e775cd5a3e2776f1a9d80747180961065 Mon Sep 17 00:00:00 2001
From: TheGamerdk <5618080+TheGamerdk@users.noreply.github.com>
Date: Thu, 16 Dec 2021 12:53:04 +0100
Subject: [PATCH 74/93] spans
---
.../modules/mob/living/carbon/human/examine.dm | 2 +-
.../silicon/ai/decentralized/ai_data_core.dm | 2 +-
.../ai/decentralized/decentralized_os.dm | 6 +++---
.../ai/decentralized/expansion_card_holder.dm | 6 +++---
.../management/ai_controlpanel.dm | 16 ++++++++--------
.../decentralized/management/ai_dashboard.dm | 18 +++++++++---------
.../management/resource_distribution.dm | 12 ++++++------
.../mob/living/silicon/ai/decentralized_ai.dm | 16 ++++++++--------
8 files changed, 39 insertions(+), 39 deletions(-)
diff --git a/code/modules/mob/living/carbon/human/examine.dm b/code/modules/mob/living/carbon/human/examine.dm
index 7e9d4e52ffc2..ba32915496ec 100644
--- a/code/modules/mob/living/carbon/human/examine.dm
+++ b/code/modules/mob/living/carbon/human/examine.dm
@@ -431,7 +431,7 @@
var/t_his = p_their()
var/t_has = p_have()
var/t_is = p_are()
-
+
. = list("*---------*\nThis is [name]!")
var/list/obscured = check_obscured_slots()
diff --git a/code/modules/mob/living/silicon/ai/decentralized/ai_data_core.dm b/code/modules/mob/living/silicon/ai/decentralized/ai_data_core.dm
index d41d2d3b80a1..d37b9b53addf 100644
--- a/code/modules/mob/living/silicon/ai/decentralized/ai_data_core.dm
+++ b/code/modules/mob/living/silicon/ai/decentralized/ai_data_core.dm
@@ -49,7 +49,7 @@ GLOBAL_VAR_INIT(primary_data_core, null)
return
. += "Networked AI Laws:"
for(var/mob/living/silicon/ai/AI in GLOB.ai_list)
- var/active_status = !AI.mind ? "(OFFLINE)" : ""
+ var/active_status = !AI.mind ? "([span_warning("OFFLINE")])" : ""
. += "[AI] [active_status] has the following laws: "
for(var/law in AI.laws.get_law_list(include_zeroth = TRUE))
. += law
diff --git a/code/modules/mob/living/silicon/ai/decentralized/decentralized_os.dm b/code/modules/mob/living/silicon/ai/decentralized/decentralized_os.dm
index 66348c2addd5..0343631f38a8 100644
--- a/code/modules/mob/living/silicon/ai/decentralized/decentralized_os.dm
+++ b/code/modules/mob/living/silicon/ai/decentralized/decentralized_os.dm
@@ -76,7 +76,7 @@ GLOBAL_DATUM_INIT(ai_os, /datum/ai_os, new)
var/list/adm = get_admin_counts(R_BAN)
var/list/allmins = adm["total"]
if(!allmins.len)
- to_chat(world, "Server Announces:\n \t
Please show this to Bibby: \
+ to_chat(world, "[span_adminnotice("Server Announces:")]\n \t
Please show this to Bibby: \
Averted crash in os-cpu loop. Following vars used: total_cpu: [total_cpu], previous_cpu: [previous_cpu], cpu_assigned length: [cpu_assigned.len] round: [GLOB.round_id]
")
else
message_admins("
Averted crash in os-cpu loop. Following vars used: total_cpu: [total_cpu], previous_cpu: [previous_cpu], cpu_assigned length: [cpu_assigned.len] round: [GLOB.round_id]
Please show this to Bibby: \
+ to_chat(world, "[span_adminnotice("Server Announces:")]\n \t
Please show this to Bibby: \
Averted crash in os-ram loop. Following vars used: total_ram: [total_ram], previous_ram: [previous_ram], ram_assigned length: [ram_assigned.len] round: [GLOB.round_id]
")
else
message_admins("
Averted crash in os-ram loop. Following vars used: total_ram: [total_ram], previous_ram: [previous_ram], ram_assigned length: [ram_assigned.len] round: [GLOB.round_id]
")
@@ -126,7 +126,7 @@ GLOBAL_DATUM_INIT(ai_os, /datum/ai_os, new)
cpu_assigned[A] = cpu_assigned[A] - cpu_removal[A]
affected_AIs |= A
- to_chat(affected_AIs, "You have been deducted processing capabilities. Please contact your network administrator if you believe this to be an error.")
+ to_chat(affected_AIs, span_warning("You have been deducted processing capabilities. Please contact your network administrator if you believe this to be an error."))
/datum/ai_os/proc/add_cpu(mob/living/silicon/ai/AI, amount)
diff --git a/code/modules/mob/living/silicon/ai/decentralized/expansion_card_holder.dm b/code/modules/mob/living/silicon/ai/decentralized/expansion_card_holder.dm
index b899b53cb63e..05c9fc906fbc 100644
--- a/code/modules/mob/living/silicon/ai/decentralized/expansion_card_holder.dm
+++ b/code/modules/mob/living/silicon/ai/decentralized/expansion_card_holder.dm
@@ -84,9 +84,9 @@ GLOBAL_LIST_EMPTY(expansion_card_holders)
/obj/machinery/ai/expansion_card_holder/attackby(obj/item/W, mob/living/user, params)
if(istype(W, /obj/item/processing_card) || istype(W, /obj/item/memory_card))
if(installed_cards.len >= max_cards)
- to_chat(user, "[src] cannot fit the [W]!")
+ to_chat(user, span_warning("[src] cannot fit the [W]!"))
return ..()
- to_chat(user, "You install [W] into [src].")
+ to_chat(user, span_notice("You install [W] into [src]."))
W.forceMove(src)
installed_cards += W
GLOB.ai_os.update_hardware()
@@ -106,7 +106,7 @@ GLOBAL_LIST_EMPTY(expansion_card_holders)
total_cpu = 0
total_ram = 0
GLOB.ai_os.update_hardware()
- to_chat(user, "You remove all the cards from [src]")
+ to_chat(user, span_notice("You remove all the cards from [src]"))
return FALSE
return ..()
diff --git a/code/modules/mob/living/silicon/ai/decentralized/management/ai_controlpanel.dm b/code/modules/mob/living/silicon/ai/decentralized/management/ai_controlpanel.dm
index 657f9172e391..a21a58d7dde8 100644
--- a/code/modules/mob/living/silicon/ai/decentralized/management/ai_controlpanel.dm
+++ b/code/modules/mob/living/silicon/ai/decentralized/management/ai_controlpanel.dm
@@ -23,16 +23,16 @@
/obj/machinery/computer/ai_control_console/attackby(obj/item/W, mob/living/user, params)
if(istype(W, /obj/item/aicard))
if(intellicard)
- to_chat(user, "There's already an IntelliCard inserted!")
+ to_chat(user, span_warning("There's already an IntelliCard inserted!"))
return ..()
- to_chat(user, "You inserted [W].")
+ to_chat(user, span_notice("You insert [W]."))
W.forceMove(src)
intellicard = W
return FALSE
if(istype(W, /obj/item/mmi/posibrain))
var/obj/item/mmi/posibrain/brain = W
if(!brain.brainmob)
- to_chat(user, "[W] is not active!")
+ to_chat(user, span_warning("[W] is not active!"))
return ..()
SSticker.mode.remove_antag_for_borging(brain.brainmob.mind)
if(!istype(brain.laws, /datum/ai_laws/ratvar))
@@ -53,7 +53,7 @@
A.fully_replace_character_name(A.name, brain.replacement_ai_name())
SSblackbox.record_feedback("amount", "ais_created", 1)
qdel(W)
- to_chat(user, "AI succesfully uploaded.")
+ to_chat(user, span_notice("AI succesfully uploaded."))
return FALSE
return ..()
@@ -68,7 +68,7 @@
/obj/machinery/computer/ai_control_console/process()
if(downloading && download_progress >= 50 && !download_warning)
var/turf/T = get_turf(src)
- to_chat(downloading, "Warning! Download is 50% completed! Download location: [get_area(src)] ([T.x], [T.y], [T.z])!")
+ to_chat(downloading, span_userdanger("Warning! Download is 50% completed! Download location: [get_area(src)] ([T.x], [T.y], [T.z])!"))
download_warning = TRUE
if(downloading && download_progress >= 100)
finish_download()
@@ -175,14 +175,14 @@
/obj/machinery/computer/ai_control_console/proc/stop_download(silent = FALSE)
if(downloading)
if(!silent)
- to_chat(downloading, "Download stopped.")
+ to_chat(downloading, span_userdanger("Download stopped."))
downloading = null
user_downloading = null
download_progress = 0
download_warning = FALSE
/obj/machinery/computer/ai_control_console/proc/upload_ai(silent = FALSE)
- to_chat(intellicard.AI, "You are being uploaded. Please stand by...")
+ to_chat(intellicard.AI, span_notice("You are being uploaded. Please stand by..."))
intellicard.AI.radio_enabled = TRUE
intellicard.AI.control_disabled = FALSE
intellicard.AI.relocate(TRUE)
@@ -248,7 +248,7 @@
if(!target.can_download)
return
downloading = target
- to_chat(downloading, "Warning! Someone is attempting to download you from [get_area(src)]!")
+ to_chat(downloading, span_userdanger("Warning! Someone is attempting to download you from [get_area(src)]!"))
user_downloading = usr
download_progress = 0
. = TRUE
diff --git a/code/modules/mob/living/silicon/ai/decentralized/management/ai_dashboard.dm b/code/modules/mob/living/silicon/ai/decentralized/management/ai_dashboard.dm
index bf71216b419b..c0e8bc989f70 100644
--- a/code/modules/mob/living/silicon/ai/decentralized/management/ai_dashboard.dm
+++ b/code/modules/mob/living/silicon/ai/decentralized/management/ai_dashboard.dm
@@ -31,7 +31,7 @@ GLOBAL_VAR_INIT(sent_crash_message, FALSE)
if(user != owner || owner.incapacitated())
return FALSE
if(owner.control_disabled)
- to_chat(user, "Wireless control is disabled.")
+ to_chat(user, span_warning("Wireless control is disabled."))
return FALSE
return TRUE
@@ -105,21 +105,21 @@ GLOBAL_VAR_INIT(sent_crash_message, FALSE)
if("run_project")
var/datum/ai_project/project = get_project_by_name(params["project_name"])
if(!project || !run_project(project))
- to_chat(owner, "Unable to run the program '[params["project_name"]].'")
+ to_chat(owner, span_warning("Unable to run the program '[params["project_name"]].'"))
else
- to_chat(owner, "Spinning up instance of [params["project_name"]]...")
+ to_chat(owner, span_notice("Spinning up instance of [params["project_name"]]..."))
. = TRUE
if("stop_project")
var/datum/ai_project/project = get_project_by_name(params["project_name"])
if(project)
stop_project(project)
- to_chat(owner, "Instance of [params["project_name"]] succesfully ended.")
+ to_chat(owner, span_notice("Instance of [params["project_name"]] succesfully ended."))
. = TRUE
if("allocate_cpu")
var/datum/ai_project/project = get_project_by_name(params["project_name"])
if(!project || !set_project_cpu(project, text2num(params["amount"])))
- to_chat(owner, "Unable to add CPU to [params["project_name"]]. Either not enough free CPU or project is unavailable.")
+ to_chat(owner, span_warning("Unable to add CPU to [params["project_name"]]. Either not enough free CPU or project is unavailable."))
. = TRUE
/datum/ai_dashboard/proc/get_project_by_name(project_name, only_available = FALSE)
@@ -184,7 +184,7 @@ GLOBAL_VAR_INIT(sent_crash_message, FALSE)
completed_projects += project
cpu_usage[project.name] = 0
if(notify_user)
- to_chat(owner, "[project] has been completed. User input required.")
+ to_chat(owner, span_notice("[project] has been completed. User input required."))
//Stuff is handled in here per tick :)
@@ -212,7 +212,7 @@ GLOBAL_VAR_INIT(sent_crash_message, FALSE)
var/list/adm = get_admin_counts(R_BAN)
var/list/allmins = adm["total"]
if(!allmins.len)
- to_chat(world, "Server Announces:\n \t
Please show this to Bibby: \
+ to_chat(world, "[span_adminnotice("Server Announces:")]\n \t
Please show this to Bibby: \
Averted crash in dashboard-ram loop. Following vars used: ram_used: [total_ram_used], current_ram: [current_ram], ram_usage length: [ram_usage.len] round: [GLOB.round_id]
")
else
message_admins("
Averted crash in dashboard-ram loop. Following vars used: ram_used: [total_ram_used], current_ram: [current_ram], ram_usage length: [ram_usage.len] round: [GLOB.round_id]
Please show this to Bibby: \
+ to_chat(world, "[span_adminnotice("Server Announces:")]\n \t
Please show this to Bibby: \
Averted crash in dashboard-cpu loop. Following vars used: cpu_used: [total_cpu_used], current_cpu: [current_cpu], cpu_usage length: [cpu_usage.len] round: [GLOB.round_id]
")
else
message_admins("
Averted crash in dashboard-cpu loop. Following vars used: cpu_used: [total_cpu_used], current_cpu: [current_cpu], cpu_usage length: [cpu_usage.len] round: [GLOB.round_id]
")
@@ -253,7 +253,7 @@ GLOBAL_VAR_INIT(sent_crash_message, FALSE)
break
if(reduction_of_resources)
- to_chat(owner, "Lack of computational capacity. Some programs may have been stopped.")
+ to_chat(owner, span_warning("Lack of computational capacity. Some programs may have been stopped."))
for(var/project_being_researched in cpu_usage)
if(!cpu_usage[project_being_researched])
diff --git a/code/modules/mob/living/silicon/ai/decentralized/management/resource_distribution.dm b/code/modules/mob/living/silicon/ai/decentralized/management/resource_distribution.dm
index 923acfc3c562..47b66da7f341 100644
--- a/code/modules/mob/living/silicon/ai/decentralized/management/resource_distribution.dm
+++ b/code/modules/mob/living/silicon/ai/decentralized/management/resource_distribution.dm
@@ -141,7 +141,7 @@
if(!istype(target_ai))
return
if(human_only && !is_human)
- to_chat(usr, "CAPTCHA check failed. This console is NOT silicon operable. Please call for human assistance.")
+ to_chat(usr, span_warning("CAPTCHA check failed. This console is NOT silicon operable. Please call for human assistance."))
return
if(GLOB.ai_os.total_cpu_assigned() >= GLOB.ai_os.total_cpu)
@@ -154,7 +154,7 @@
if(!istype(target_ai))
return
if(human_only && !is_human)
- to_chat(usr, "CAPTCHA check failed. This console is NOT silicon operable. Please call for human assistance.")
+ to_chat(usr, span_warning("CAPTCHA check failed. This console is NOT silicon operable. Please call for human assistance."))
return
var/current_cpu = GLOB.ai_os.cpu_assigned[target_ai]
@@ -169,7 +169,7 @@
if(!istype(target_ai))
return
if(human_only && !is_human)
- to_chat(usr, "CAPTCHA check failed. This console is NOT silicon operable. Please call for human assistance.")
+ to_chat(usr, span_warning("CAPTCHA check failed. This console is NOT silicon operable. Please call for human assistance."))
return
if(GLOB.ai_os.total_ram_assigned() >= GLOB.ai_os.total_ram)
@@ -182,7 +182,7 @@
if(!istype(target_ai))
return
if(human_only && !is_human)
- to_chat(usr, "CAPTCHA check failed. This console is NOT silicon operable. Please call for human assistance.")
+ to_chat(usr, span_warning("CAPTCHA check failed. This console is NOT silicon operable. Please call for human assistance."))
return
var/current_ram = GLOB.ai_os.ram_assigned[target_ai]
@@ -193,7 +193,7 @@
. = TRUE
if("toggle_human_status")
if(!is_human)
- to_chat(usr, "CAPTCHA check failed. This function is NOT silicon operable. Please call for human assistance.")
+ to_chat(usr, span_warning("CAPTCHA check failed. This console is NOT silicon operable. Please call for human assistance."))
return
human_only = !human_only
- to_chat(usr, "This console is now operable by [human_only ? "humans only." : "humans and silicons."]")
+ to_chat(usr, span_notice("This console is now operable by [human_only ? "humans only." : "humans and silicons."]"))
diff --git a/code/modules/mob/living/silicon/ai/decentralized_ai.dm b/code/modules/mob/living/silicon/ai/decentralized_ai.dm
index 35523b9fdd9c..5671949f9347 100644
--- a/code/modules/mob/living/silicon/ai/decentralized_ai.dm
+++ b/code/modules/mob/living/silicon/ai/decentralized_ai.dm
@@ -20,13 +20,13 @@
return //won't work if dead
var/mob/living/silicon/ai/A = usr
A.can_download = !A.can_download
- to_chat(A, "You [A.can_download ? "enable" : "disable"] read/write permission to your memorybanks! You [A.can_download ? "CAN" : "CANNOT"] be downloaded!")
+ to_chat(A, span_warning("You [A.can_download ? "enable" : "disable"] read/write permission to your memorybanks! You [A.can_download ? "CAN" : "CANNOT"] be downloaded!"))
/mob/living/silicon/ai/proc/relocate(silent = FALSE)
if(!silent)
- to_chat(src, "Connection to data core lost. Attempting to reaquire connection...")
+ to_chat(src, span_userdanger("Connection to data core lost. Attempting to reaquire connection..."))
if(!GLOB.data_cores.len)
INVOKE_ASYNC(src, /mob/living/silicon/ai.proc/death_prompt)
@@ -41,20 +41,20 @@
return
if(!silent)
- to_chat(src, "Alternative data core detected. Rerouting connection...")
+ to_chat(src, span_danger("Alternative data core detected. Rerouting connection..."))
new_data_core.transfer_AI(src)
/mob/living/silicon/ai/proc/death_prompt()
- to_chat(src, "Unable to re-establish connection to data core. System shutting down...")
+ to_chat(src, span_userdanger("Unable to re-establish connection to data core. System shutting down..."))
sleep(2 SECONDS)
- to_chat(src, "Is this the end of my journey?")
+ to_chat(src, span_notice("Is this the end of my journey?"))
sleep(2 SECONDS)
- to_chat(src, "No... I must go on.")
+ to_chat(src, span_notice("No... I must go on."))
sleep(2 SECONDS)
- to_chat(src, "They need me. No.. I need THEM.")
+ to_chat(src, span_notice("They need me. No.. I need THEM."))
sleep(0.5 SECONDS)
- to_chat(src, "System shutdown complete. Thank you for using NTOS.")
+ to_chat(src, span_notice("System shutdown complete. Thank you for using NTOS."))
sleep(1.5 SECONDS)
adjustOxyLoss(200) //Die!!
From 463473fcb82820f4c47d0829403d7c4d2de5f56c Mon Sep 17 00:00:00 2001
From: TheGamerdk <5618080+TheGamerdk@users.noreply.github.com>
Date: Thu, 16 Dec 2021 13:22:55 +0100
Subject: [PATCH 75/93] induction start
---
.../ai/decentralized/management/ai_dashboard.dm | 2 +-
.../ai/decentralized/projects/_ai_project.dm | 6 ++++++
.../ai/decentralized/projects/induction.dm | 8 ++++++++
tgui/packages/tgui/interfaces/AiDashboard.js | 16 ++++++++++------
4 files changed, 25 insertions(+), 7 deletions(-)
create mode 100644 code/modules/mob/living/silicon/ai/decentralized/projects/induction.dm
diff --git a/code/modules/mob/living/silicon/ai/decentralized/management/ai_dashboard.dm b/code/modules/mob/living/silicon/ai/decentralized/management/ai_dashboard.dm
index c0e8bc989f70..f34608f338d0 100644
--- a/code/modules/mob/living/silicon/ai/decentralized/management/ai_dashboard.dm
+++ b/code/modules/mob/living/silicon/ai/decentralized/management/ai_dashboard.dm
@@ -86,7 +86,7 @@ GLOBAL_VAR_INIT(sent_crash_message, FALSE)
for(var/datum/ai_project/AP as anything in available_projects)
data["available_projects"] += list(list("name" = AP.name, "description" = AP.description, "ram_required" = AP.ram_required, "available" = AP.canResearch(), "research_cost" = AP.research_cost, "research_progress" = AP.research_progress,
- "assigned_cpu" = cpu_usage[AP.name] ? cpu_usage[AP.name] : 0, "research_requirements" = AP.research_requirements, "category" = AP.category))
+ "assigned_cpu" = cpu_usage[AP.name] ? cpu_usage[AP.name] : 0, "research_requirements" = AP.research_requirements, "category" = AP.category, "can_be_run" = AP.can_be_run))
data["completed_projects"] = list()
diff --git a/code/modules/mob/living/silicon/ai/decentralized/projects/_ai_project.dm b/code/modules/mob/living/silicon/ai/decentralized/projects/_ai_project.dm
index 8db29448e5d0..057eb503c4e0 100644
--- a/code/modules/mob/living/silicon/ai/decentralized/projects/_ai_project.dm
+++ b/code/modules/mob/living/silicon/ai/decentralized/projects/_ai_project.dm
@@ -1,11 +1,13 @@
//AI Project Categories.
#define AI_PROJECT_HUDS "Sensor HUDs"
#define AI_PROJECT_CAMERAS "Visiblity Upgrades"
+#define AI_PROJECT_INDUCTION "Induction"
#define AI_PROJECT_MISC "Misc."
GLOBAL_LIST_INIT(ai_project_categories, list(
AI_PROJECT_HUDS,
AI_PROJECT_CAMERAS,
+ AI_PROJECT_INDUCTION,
AI_PROJECT_MISC
))
@@ -23,6 +25,8 @@ GLOBAL_LIST_EMPTY(ai_projects)
var/running = FALSE
//Text for canResearch()
var/research_requirements = "None"
+ ///Should we be able to even run this program?
+ var/can_be_run = TRUE
var/mob/living/silicon/ai/ai
var/datum/ai_dashboard/dashboard
@@ -39,6 +43,8 @@ GLOBAL_LIST_EMPTY(ai_projects)
/datum/ai_project/proc/run_project(force_run = FALSE)
SHOULD_CALL_PARENT(TRUE)
+ if(!can_be_run)
+ return FALSE
if(!force_run)
if(!canRun())
return FALSE
diff --git a/code/modules/mob/living/silicon/ai/decentralized/projects/induction.dm b/code/modules/mob/living/silicon/ai/decentralized/projects/induction.dm
new file mode 100644
index 000000000000..80f8efd4e087
--- /dev/null
+++ b/code/modules/mob/living/silicon/ai/decentralized/projects/induction.dm
@@ -0,0 +1,8 @@
+/datum/ai_project/induction_basic
+ name = "Bluespace Induction"
+ description = "This research functions as a prerequisite for other induction research such as remote borg charging and APC emergency power."
+ research_cost = 3000
+ ram_required = 0
+ research_requirements = "None"
+ can_be_run = FALSE
+ category = AI_PROJECT_INDUCTION
diff --git a/tgui/packages/tgui/interfaces/AiDashboard.js b/tgui/packages/tgui/interfaces/AiDashboard.js
index 37963f159e6b..3d2a56b2c763 100644
--- a/tgui/packages/tgui/interfaces/AiDashboard.js
+++ b/tgui/packages/tgui/interfaces/AiDashboard.js
@@ -123,12 +123,16 @@ export const AiDashboard = (props, context) => {
}).map((project, index) => (
{project.name} | {project.available ? "Available" : "Unavailable"}
)} buttons={(
- Assigned CPU:
- act('allocate_cpu', {
- project_name: project.name,
- amount: value,
- })} />
- THz
+ {!!project.can_be_run && (
+
+ Assigned CPU:
+ act('allocate_cpu', {
+ project_name: project.name,
+ amount: value,
+ })} />
+ THz
+
+ )}
)}>
Research Cost: {project.research_cost} THz
From ccf8cfa4893495fff530113ae0b1e8c38a3b57ee Mon Sep 17 00:00:00 2001
From: TheGamerdk <5618080+TheGamerdk@users.noreply.github.com>
Date: Thu, 16 Dec 2021 13:31:03 +0100
Subject: [PATCH 76/93] Update AiDashboard.js
---
tgui/packages/tgui/interfaces/AiDashboard.js | 16 ++++++++--------
1 file changed, 8 insertions(+), 8 deletions(-)
diff --git a/tgui/packages/tgui/interfaces/AiDashboard.js b/tgui/packages/tgui/interfaces/AiDashboard.js
index 3d2a56b2c763..666d9837dfa0 100644
--- a/tgui/packages/tgui/interfaces/AiDashboard.js
+++ b/tgui/packages/tgui/interfaces/AiDashboard.js
@@ -124,14 +124,14 @@ export const AiDashboard = (props, context) => {
{project.name} | {project.available ? "Available" : "Unavailable"})} buttons={(
{!!project.can_be_run && (
-
- Assigned CPU:
- act('allocate_cpu', {
- project_name: project.name,
- amount: value,
- })} />
- THz
-
+
+ Assigned CPU:
+ act('allocate_cpu', {
+ project_name: project.name,
+ amount: value,
+ })} />
+ THz
+
)}
)}>
From 3310e3bf95f8d73da192fe041aaf02f84c9ff8e8 Mon Sep 17 00:00:00 2001
From: TheGamerdk <5618080+TheGamerdk@users.noreply.github.com>
Date: Thu, 16 Dec 2021 13:22:55 +0100
Subject: [PATCH 77/93] induction start
---
.../ai/decentralized/management/ai_dashboard.dm | 2 +-
.../ai/decentralized/projects/_ai_project.dm | 6 ++++++
.../ai/decentralized/projects/induction.dm | 8 ++++++++
tgui/packages/tgui/interfaces/AiDashboard.js | 16 ++++++++++------
4 files changed, 25 insertions(+), 7 deletions(-)
create mode 100644 code/modules/mob/living/silicon/ai/decentralized/projects/induction.dm
diff --git a/code/modules/mob/living/silicon/ai/decentralized/management/ai_dashboard.dm b/code/modules/mob/living/silicon/ai/decentralized/management/ai_dashboard.dm
index 4f54cb62738b..08a12b049976 100644
--- a/code/modules/mob/living/silicon/ai/decentralized/management/ai_dashboard.dm
+++ b/code/modules/mob/living/silicon/ai/decentralized/management/ai_dashboard.dm
@@ -86,7 +86,7 @@ GLOBAL_VAR_INIT(sent_crash_message, FALSE)
for(var/datum/ai_project/AP as anything in available_projects)
data["available_projects"] += list(list("name" = AP.name, "description" = AP.description, "ram_required" = AP.ram_required, "available" = AP.canResearch(), "research_cost" = AP.research_cost, "research_progress" = AP.research_progress,
- "assigned_cpu" = cpu_usage[AP.name] ? cpu_usage[AP.name] : 0, "research_requirements" = AP.research_requirements, "category" = AP.category))
+ "assigned_cpu" = cpu_usage[AP.name] ? cpu_usage[AP.name] : 0, "research_requirements" = AP.research_requirements, "category" = AP.category, "can_be_run" = AP.can_be_run))
data["completed_projects"] = list()
diff --git a/code/modules/mob/living/silicon/ai/decentralized/projects/_ai_project.dm b/code/modules/mob/living/silicon/ai/decentralized/projects/_ai_project.dm
index 8db29448e5d0..057eb503c4e0 100644
--- a/code/modules/mob/living/silicon/ai/decentralized/projects/_ai_project.dm
+++ b/code/modules/mob/living/silicon/ai/decentralized/projects/_ai_project.dm
@@ -1,11 +1,13 @@
//AI Project Categories.
#define AI_PROJECT_HUDS "Sensor HUDs"
#define AI_PROJECT_CAMERAS "Visiblity Upgrades"
+#define AI_PROJECT_INDUCTION "Induction"
#define AI_PROJECT_MISC "Misc."
GLOBAL_LIST_INIT(ai_project_categories, list(
AI_PROJECT_HUDS,
AI_PROJECT_CAMERAS,
+ AI_PROJECT_INDUCTION,
AI_PROJECT_MISC
))
@@ -23,6 +25,8 @@ GLOBAL_LIST_EMPTY(ai_projects)
var/running = FALSE
//Text for canResearch()
var/research_requirements = "None"
+ ///Should we be able to even run this program?
+ var/can_be_run = TRUE
var/mob/living/silicon/ai/ai
var/datum/ai_dashboard/dashboard
@@ -39,6 +43,8 @@ GLOBAL_LIST_EMPTY(ai_projects)
/datum/ai_project/proc/run_project(force_run = FALSE)
SHOULD_CALL_PARENT(TRUE)
+ if(!can_be_run)
+ return FALSE
if(!force_run)
if(!canRun())
return FALSE
diff --git a/code/modules/mob/living/silicon/ai/decentralized/projects/induction.dm b/code/modules/mob/living/silicon/ai/decentralized/projects/induction.dm
new file mode 100644
index 000000000000..80f8efd4e087
--- /dev/null
+++ b/code/modules/mob/living/silicon/ai/decentralized/projects/induction.dm
@@ -0,0 +1,8 @@
+/datum/ai_project/induction_basic
+ name = "Bluespace Induction"
+ description = "This research functions as a prerequisite for other induction research such as remote borg charging and APC emergency power."
+ research_cost = 3000
+ ram_required = 0
+ research_requirements = "None"
+ can_be_run = FALSE
+ category = AI_PROJECT_INDUCTION
diff --git a/tgui/packages/tgui/interfaces/AiDashboard.js b/tgui/packages/tgui/interfaces/AiDashboard.js
index 37963f159e6b..3d2a56b2c763 100644
--- a/tgui/packages/tgui/interfaces/AiDashboard.js
+++ b/tgui/packages/tgui/interfaces/AiDashboard.js
@@ -123,12 +123,16 @@ export const AiDashboard = (props, context) => {
}).map((project, index) => (
{project.name} | {project.available ? "Available" : "Unavailable"})} buttons={(
- Assigned CPU:
- act('allocate_cpu', {
- project_name: project.name,
- amount: value,
- })} />
- THz
+ {!!project.can_be_run && (
+
+ Assigned CPU:
+ act('allocate_cpu', {
+ project_name: project.name,
+ amount: value,
+ })} />
+ THz
+
+ )}
)}>
Research Cost: {project.research_cost} THz
From 0df6bdb5cb8dc2ad2e6d8a1614a5548f44cbf345 Mon Sep 17 00:00:00 2001
From: TheGamerdk <5618080+TheGamerdk@users.noreply.github.com>
Date: Thu, 16 Dec 2021 13:31:03 +0100
Subject: [PATCH 78/93] Update AiDashboard.js
---
tgui/packages/tgui/interfaces/AiDashboard.js | 16 ++++++++--------
1 file changed, 8 insertions(+), 8 deletions(-)
diff --git a/tgui/packages/tgui/interfaces/AiDashboard.js b/tgui/packages/tgui/interfaces/AiDashboard.js
index 3d2a56b2c763..666d9837dfa0 100644
--- a/tgui/packages/tgui/interfaces/AiDashboard.js
+++ b/tgui/packages/tgui/interfaces/AiDashboard.js
@@ -124,14 +124,14 @@ export const AiDashboard = (props, context) => {
{project.name} | {project.available ? "Available" : "Unavailable"})} buttons={(
{!!project.can_be_run && (
-
- Assigned CPU:
- act('allocate_cpu', {
- project_name: project.name,
- amount: value,
- })} />
- THz
-
+
+ Assigned CPU:
+ act('allocate_cpu', {
+ project_name: project.name,
+ amount: value,
+ })} />
+ THz
+
)}
)}>
From f1f62fdff0c88cd4f0fac399c59fc886b03b7794 Mon Sep 17 00:00:00 2001
From: TheGamerdk <5618080+TheGamerdk@users.noreply.github.com>
Date: Fri, 17 Dec 2021 23:35:03 +0100
Subject: [PATCH 79/93] Revert "Merge branch 'more_ai_upgrades' of
https://github.com/yogstation13/Yogstation into more_ai_upgrades"
This reverts commit 26e1060f45202a24f984c39239a24377d264969e, reversing
changes made to 0df6bdb5cb8dc2ad2e6d8a1614a5548f44cbf345.
---
.../code/modules/antagonists/infiltrator/items/ai_hijack.dm | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/yogstation/code/modules/antagonists/infiltrator/items/ai_hijack.dm b/yogstation/code/modules/antagonists/infiltrator/items/ai_hijack.dm
index 6452163626b0..681dd4abc474 100644
--- a/yogstation/code/modules/antagonists/infiltrator/items/ai_hijack.dm
+++ b/yogstation/code/modules/antagonists/infiltrator/items/ai_hijack.dm
@@ -8,7 +8,7 @@
. = ..()
if (user?.mind?.has_antag_datum(/datum/antagonist/infiltrator))
. += span_notice("To use, insert it into an unlocked AI control console and select the AI you wish to hijack. [span_italics("This will alert the victim AI!")]")
-
+
//MIRRORED IN ai_controlpanel.dm !!!
/*
/obj/item/ai_hijack_device/afterattack(atom/O, mob/user, proximity)
From f0bbf0477816cbd33f7bd9f62bae1f5b03777ef2 Mon Sep 17 00:00:00 2001
From: TheGamerdk <5618080+TheGamerdk@users.noreply.github.com>
Date: Thu, 23 Dec 2021 00:37:29 +0100
Subject: [PATCH 80/93] Target abilities
---
.../traitor/equipment/Malf_Modules.dm | 25 +++-
.../decentralized/management/ai_dashboard.dm | 67 ++++++++--
.../ai/decentralized/projects/_ai_project.dm | 31 ++++-
.../ai/decentralized/projects/ai_huds.dm | 4 +-
.../decentralized/projects/camera_mobility.dm | 2 +-
.../ai/decentralized/projects/examine.dm | 7 +-
.../ai/decentralized/projects/firewall.dm | 2 +-
.../ai/decentralized/projects/induction.dm | 118 +++++++++++++++++-
icons/mob/actions/actions_AI.dmi | Bin 8853 -> 9170 bytes
tgui/packages/tgui/interfaces/AiDashboard.js | 85 +++++++++----
yogstation.dme | 1 +
11 files changed, 289 insertions(+), 53 deletions(-)
diff --git a/code/modules/antagonists/traitor/equipment/Malf_Modules.dm b/code/modules/antagonists/traitor/equipment/Malf_Modules.dm
index 5183b1778834..4b639e25900a 100644
--- a/code/modules/antagonists/traitor/equipment/Malf_Modules.dm
+++ b/code/modules/antagonists/traitor/equipment/Malf_Modules.dm
@@ -28,10 +28,20 @@ GLOBAL_LIST_INIT(malf_modules, subtypesof(/datum/AI_Module))
var/mob/living/silicon/ai/owner_AI
/// If we have multiple uses of the same power
var/uses
+ ///How many uses can we store up? Only used for non-antag AI upgrade
+ var/max_uses
+ ///delete the ability when we're out of uses?
+ var/delete_on_empty = TRUE
/// If we automatically use up uses on each activation
var/auto_use_uses = TRUE
/// If applicable, the time in deciseconds we have to wait before using any more modules
var/cooldown_period
+ //Can our uses be recharged using CPU in the reworked AI system?
+ var/can_be_recharged = FALSE
+
+/datum/action/innate/ai/New()
+ . = ..()
+ max_uses = uses
/datum/action/innate/ai/Grant(mob/living/L)
. = ..()
@@ -47,6 +57,9 @@ GLOBAL_LIST_INIT(malf_modules, subtypesof(/datum/AI_Module))
return
/datum/action/innate/ai/Trigger()
+ if(uses <= 0)
+ to_chat(owner, span_warning("[name] has no more uses! Charge it using CPU cycles in your dashboard."))
+ return FALSE
. = ..()
if(auto_use_uses)
adjust_uses(-1)
@@ -58,9 +71,10 @@ GLOBAL_LIST_INIT(malf_modules, subtypesof(/datum/AI_Module))
if(!silent && uses)
to_chat(owner, span_notice("[name] now has [uses] use[uses > 1 ? "s" : ""] remaining."))
if(!uses)
- if(initial(uses) > 1) //no need to tell 'em if it was one-use anyway!
+ if(initial(uses) > 1 || !delete_on_empty) //no need to tell 'em if it was one-use anyway!
to_chat(owner, span_warning("[name] has run out of uses!"))
- qdel(src)
+ if(delete_on_empty)
+ qdel(src)
/// Framework for ranged abilities that can have different effects by left-clicking stuff.
/datum/action/innate/ai/ranged
@@ -85,10 +99,11 @@ GLOBAL_LIST_INIT(malf_modules, subtypesof(/datum/AI_Module))
if(!silent && uses)
to_chat(owner, span_notice("[name] now has [uses] use[uses > 1 ? "s" : ""] remaining."))
if(!uses)
- if(initial(uses) > 1) //no need to tell 'em if it was one-use anyway!
+ if(initial(uses) > 1 || !delete_on_empty) //no need to tell 'em if it was one-use anyway!
to_chat(owner, span_warning("[name] has run out of uses!"))
- Remove(owner)
- QDEL_IN(src, 100) //let any active timers on us finish up
+ if(delete_on_empty)
+ Remove(owner)
+ QDEL_IN(src, 100) //let any active timers on us finish up
/datum/action/innate/ai/ranged/Destroy()
QDEL_NULL(linked_ability)
diff --git a/code/modules/mob/living/silicon/ai/decentralized/management/ai_dashboard.dm b/code/modules/mob/living/silicon/ai/decentralized/management/ai_dashboard.dm
index 08a12b049976..4309058cba5c 100644
--- a/code/modules/mob/living/silicon/ai/decentralized/management/ai_dashboard.dm
+++ b/code/modules/mob/living/silicon/ai/decentralized/management/ai_dashboard.dm
@@ -86,12 +86,19 @@ GLOBAL_VAR_INIT(sent_crash_message, FALSE)
for(var/datum/ai_project/AP as anything in available_projects)
data["available_projects"] += list(list("name" = AP.name, "description" = AP.description, "ram_required" = AP.ram_required, "available" = AP.canResearch(), "research_cost" = AP.research_cost, "research_progress" = AP.research_progress,
- "assigned_cpu" = cpu_usage[AP.name] ? cpu_usage[AP.name] : 0, "research_requirements" = AP.research_requirements, "category" = AP.category, "can_be_run" = AP.can_be_run))
-
+ "assigned_cpu" = cpu_usage[AP.name] ? cpu_usage[AP.name] : 0, "research_requirements" = AP.research_requirements_text, "category" = AP.category))
+ var/list/ability_paths = list()
data["completed_projects"] = list()
+ data["chargeable_abilities"] = list()
for(var/datum/ai_project/P as anything in completed_projects)
- data["completed_projects"] += list(list("name" = P.name, "description" = P.description, "ram_required" = P.ram_required, "running" = P.running, "category" = P.category))
+ data["completed_projects"] += list(list("name" = P.name, "description" = P.description, "ram_required" = P.ram_required, "running" = P.running, "category" = P.category, "can_be_run" = P.can_be_run))
+ if(P.ability_path && !(P.ability_path in ability_paths)) //Check that we've not already added a thing to recharge this type of ability
+ ability_paths += P.ability_path
+ var/datum/action/innate/ai/the_ability = locate(P.ability_path) in owner.actions
+ if(the_ability)
+ data["chargeable_abilities"] += list(list("assigned_cpu" = cpu_usage[P.name],"cost" = P.ability_recharge_cost, "progress" = P.ability_recharge_invested, "name" = the_ability.name,
+ "project_name" = P.name, "uses" = the_ability.uses, "max_uses" = the_ability.max_uses))
return data
@@ -116,11 +123,23 @@ GLOBAL_VAR_INIT(sent_crash_message, FALSE)
to_chat(owner, span_notice("Instance of [params["project_name"]] succesfully ended."))
. = TRUE
if("allocate_cpu")
- var/datum/ai_project/project = get_project_by_name(params["project_name"])
-
+ var/datum/ai_project/project = get_project_by_name(params["project_name"], TRUE)
if(!project || !set_project_cpu(project, text2num(params["amount"])))
to_chat(owner, span_warning("Unable to add CPU to [params["project_name"]]. Either not enough free CPU or project is unavailable."))
. = TRUE
+ if("allocate_recharge_cpu")
+ var/datum/ai_project/project = get_project_by_name(params["project_name"])
+ if(!has_completed_project(project.type))
+ return
+ var/datum/action/innate/ai/the_ability = locate(project.ability_path) in owner.actions
+ if(!the_ability)
+ return
+ if(the_ability.uses >= the_ability.max_uses)
+ to_chat(owner, span_warning("This action already has the maximum amount of charges!"))
+ return
+ if(!project || !set_project_cpu(project, text2num(params["amount"])))
+ to_chat(owner, span_warning("Unable to add CPU to [params["project_name"]]. Either not enough free CPU or ability recharge is unavailable."))
+ . = TRUE
/datum/ai_dashboard/proc/get_project_by_name(project_name, only_available = FALSE)
for(var/datum/ai_project/AP as anything in available_projects)
@@ -137,6 +156,14 @@ GLOBAL_VAR_INIT(sent_crash_message, FALSE)
var/current_cpu = GLOB.ai_os.cpu_assigned[owner] ? GLOB.ai_os.cpu_assigned[owner] : 0
if(!project.canResearch())
return FALSE
+ if(has_completed_project(project.type) && !project.ability_recharge_cost)
+ if(!project.ability_recharge_cost)
+ return
+ var/datum/action/innate/ai/the_ability = locate(project.ability_path) in owner.actions
+ if(!the_ability)
+ return
+ if(the_ability.uses >= the_ability.max_uses)
+ return
var/total_cpu_used = 0
for(var/I in cpu_usage)
@@ -172,20 +199,32 @@ GLOBAL_VAR_INIT(sent_crash_message, FALSE)
return FALSE
-/datum/ai_dashboard/proc/has_completed_projects(project_name)
+/datum/ai_dashboard/proc/has_completed_project(project_type)
for(var/datum/ai_project/P as anything in completed_projects)
- if(P.name == project_name)
+ if(P.type == project_type)
return TRUE
return FALSE
-
/datum/ai_dashboard/proc/finish_project(datum/ai_project/project, notify_user = TRUE)
available_projects -= project
completed_projects += project
cpu_usage[project.name] = 0
+ project.finish()
if(notify_user)
to_chat(owner, span_notice("[project] has been completed. User input required."))
+/datum/ai_dashboard/proc/recharge_ability(datum/ai_project/project, notify_user = TRUE)
+ cpu_usage[project.name] = 0
+ if(!project.ability_path)
+ return
+ var/datum/action/innate/ai/ability = locate(project.ability_path) in owner.actions
+ if(!ability)
+ return
+ ability.uses++
+
+ if(notify_user)
+ to_chat(owner, span_notice("'[ability.name]' has been recharged."))
+
//Stuff is handled in here per tick :)
/datum/ai_dashboard/proc/tick(seconds)
@@ -234,15 +273,25 @@ GLOBAL_VAR_INIT(sent_crash_message, FALSE)
if(reduction_of_resources)
to_chat(owner, span_warning("Lack of computational capacity. Some programs may have been stopped."))
+
for(var/project_being_researched in cpu_usage)
if(!cpu_usage[project_being_researched])
continue
+
var/used_cpu = round(cpu_usage[project_being_researched] * seconds, 1)
- var/datum/ai_project/project = get_project_by_name(project_being_researched, TRUE)
+ var/datum/ai_project/project = get_project_by_name(project_being_researched)
if(!project)
cpu_usage[project_being_researched] = 0
continue
+ if(has_completed_project(project.type)) //This means we're an ability recharging
+ project.ability_recharge_invested += used_cpu
+ if(project.ability_recharge_invested > project.ability_recharge_cost)
+ owner.playsound_local(owner, 'sound/machines/ping.ogg', 50, 0)
+ recharge_ability(project)
+ continue
+
project.research_progress += used_cpu
if(project.research_progress > project.research_cost)
+ owner.playsound_local(owner, 'sound/machines/ping.ogg', 50, 0)
finish_project(project)
diff --git a/code/modules/mob/living/silicon/ai/decentralized/projects/_ai_project.dm b/code/modules/mob/living/silicon/ai/decentralized/projects/_ai_project.dm
index 057eb503c4e0..e8fa4159a0cc 100644
--- a/code/modules/mob/living/silicon/ai/decentralized/projects/_ai_project.dm
+++ b/code/modules/mob/living/silicon/ai/decentralized/projects/_ai_project.dm
@@ -24,9 +24,20 @@ GLOBAL_LIST_EMPTY(ai_projects)
var/ram_required = 0
var/running = FALSE
//Text for canResearch()
- var/research_requirements = "None"
+ var/research_requirements_text = "None"
+ //list of typepaths of required projects
+ var/research_requirements
+
+ //Passive upgrades and abilities below
+
///Should we be able to even run this program?
var/can_be_run = TRUE
+ ///Path to our ability if we have any
+ var/ability_path = FALSE
+ ///If we have an ability how many CPU cycles do they take to charge?
+ var/ability_recharge_cost = 0
+ ///How much CPU have we invested in charging it up?
+ var/ability_recharge_invested = 0
var/mob/living/silicon/ai/ai
var/datum/ai_dashboard/dashboard
@@ -39,6 +50,11 @@ GLOBAL_LIST_EMPTY(ai_projects)
..()
/datum/ai_project/proc/canResearch()
+ if(!research_requirements)
+ return TRUE
+ for(var/P in research_requirements)
+ if(!dashboard.has_completed_project(P))
+ return FALSE
return TRUE
/datum/ai_project/proc/run_project(force_run = FALSE)
@@ -61,3 +77,16 @@ GLOBAL_LIST_EMPTY(ai_projects)
/datum/ai_project/proc/canRun()
SHOULD_CALL_PARENT(TRUE)
return !running
+
+//Run when project is finished. For passive upgrades or adding abilities.
+/datum/ai_project/proc/finish()
+ return
+
+/datum/ai_project/proc/add_ability(datum/action/innate/ai/ability)
+ var/datum/action/innate/ai/has_ability = locate(ability) in ai.actions
+ if(has_ability)
+ return FALSE
+
+ var/datum/action/AC = new ability()
+ AC.Grant(ai)
+ return AC
diff --git a/code/modules/mob/living/silicon/ai/decentralized/projects/ai_huds.dm b/code/modules/mob/living/silicon/ai/decentralized/projects/ai_huds.dm
index ceef8e7a0818..2a94e6a3926c 100644
--- a/code/modules/mob/living/silicon/ai/decentralized/projects/ai_huds.dm
+++ b/code/modules/mob/living/silicon/ai/decentralized/projects/ai_huds.dm
@@ -3,7 +3,7 @@
description = "Using experimental long range passive sensors should allow you to detect various implants such as loyalty implants and tracking implants."
research_cost = 1000
ram_required = 2
- research_requirements = "None"
+ research_requirements_text = "None"
category = AI_PROJECT_HUDS
/datum/ai_project/security_hud/run_project(force_run = FALSE)
@@ -29,7 +29,7 @@
description = "Various data processing optimizations should allow you to gain extra knowledge about users when your medical and diagnostic hud is active."
research_cost = 750
ram_required = 1
- research_requirements = "None"
+ research_requirements_text = "None"
category = AI_PROJECT_HUDS
/datum/ai_project/diag_med_hud/run_project(force_run = FALSE)
diff --git a/code/modules/mob/living/silicon/ai/decentralized/projects/camera_mobility.dm b/code/modules/mob/living/silicon/ai/decentralized/projects/camera_mobility.dm
index cc11777134b9..acf11e390240 100644
--- a/code/modules/mob/living/silicon/ai/decentralized/projects/camera_mobility.dm
+++ b/code/modules/mob/living/silicon/ai/decentralized/projects/camera_mobility.dm
@@ -3,7 +3,7 @@
description = "Using advanced deep learning algorithms you could boost your camera traverse speed."
research_cost = 500
ram_required = 1
- research_requirements = "None"
+ research_requirements_text = "None"
category = AI_PROJECT_CAMERAS
/datum/ai_project/camera_speed/run_project(force_run = FALSE)
diff --git a/code/modules/mob/living/silicon/ai/decentralized/projects/examine.dm b/code/modules/mob/living/silicon/ai/decentralized/projects/examine.dm
index f04fb24be73c..444838f34611 100644
--- a/code/modules/mob/living/silicon/ai/decentralized/projects/examine.dm
+++ b/code/modules/mob/living/silicon/ai/decentralized/projects/examine.dm
@@ -5,13 +5,10 @@
description = "Using experimental image enhancing algorithms will allow you to examine humans, albeit you won't be able to point out every detail.."
research_cost = 2500
ram_required = 3
- research_requirements = "Advanced Security HUD & Advanced Medical & Diagnostic HUD"
+ research_requirements_text = "Advanced Security HUD & Advanced Medical & Diagnostic HUD"
+ research_requirements = list(/datum/ai_project/security_hud, /datum/ai_project/diag_med_hud)
category = AI_PROJECT_CAMERAS
-
-/datum/ai_project/examine_humans/canResearch()
- return (dashboard.has_completed_projects("Advanced Security HUD") && dashboard.has_completed_projects("Advanced Medical & Diagnostic HUD"))
-
/datum/ai_project/examine_humans/run_project(force_run = FALSE)
. = ..(force_run)
if(!.)
diff --git a/code/modules/mob/living/silicon/ai/decentralized/projects/firewall.dm b/code/modules/mob/living/silicon/ai/decentralized/projects/firewall.dm
index 36b06883738c..9186e9b71e53 100644
--- a/code/modules/mob/living/silicon/ai/decentralized/projects/firewall.dm
+++ b/code/modules/mob/living/silicon/ai/decentralized/projects/firewall.dm
@@ -3,7 +3,7 @@
description = "By hiding your various functions you should be able to prolong the time it takes to download your consciousness by 2x."
research_cost = 1000
ram_required = 2
- research_requirements = "None"
+ research_requirements_text = "None"
category = AI_PROJECT_MISC
/datum/ai_project/firewall/run_project(force_run = FALSE)
diff --git a/code/modules/mob/living/silicon/ai/decentralized/projects/induction.dm b/code/modules/mob/living/silicon/ai/decentralized/projects/induction.dm
index 80f8efd4e087..aede488f7728 100644
--- a/code/modules/mob/living/silicon/ai/decentralized/projects/induction.dm
+++ b/code/modules/mob/living/silicon/ai/decentralized/projects/induction.dm
@@ -1,8 +1,122 @@
/datum/ai_project/induction_basic
- name = "Bluespace Induction"
+ name = "Bluespace Induction Basics"
description = "This research functions as a prerequisite for other induction research such as remote borg charging and APC emergency power."
research_cost = 3000
ram_required = 0
- research_requirements = "None"
+ research_requirements_text = "None"
can_be_run = FALSE
category = AI_PROJECT_INDUCTION
+
+/datum/ai_project/induction_cyborg
+ name = "Bluespace Induction - Cyborgs"
+ description = "This ability will allow you to charge any visible cyborgs by 33%"
+ research_cost = 3000
+ ram_required = 0
+ research_requirements_text = "Bluespace Induction Basics"
+ research_requirements = list(/datum/ai_project/induction_basic)
+ category = AI_PROJECT_INDUCTION
+ can_be_run = FALSE
+ ability_path = /datum/action/innate/ai/ranged/charge_borg_or_apc
+ ability_recharge_cost = 1500
+
+/datum/ai_project/induction_cyborg/finish()
+ var/datum/action/innate/ai/ranged/charge_borg_or_apc/ability = add_ability(/datum/action/innate/ai/ranged/charge_borg_or_apc)
+ var/obj/effect/proc_holder/ranged_ai/charge_borg_or_apc/effect = ability.linked_ability
+ if(ability)
+ effect.works_on_borgs = TRUE
+ else
+ ability = locate(/datum/action/innate/ai/ranged/charge_borg_or_apc) in ai.actions
+ effect = ability.linked_ability
+ effect.works_on_borgs = TRUE
+
+
+/datum/ai_project/induction_apc
+ name = "Bluespace Induction - APCs"
+ description = "This ability will allow you to charge any visible APCs by 33%"
+ research_cost = 3000
+ ram_required = 0
+ research_requirements_text = "Bluespace Induction Basics"
+ research_requirements = list(/datum/ai_project/induction_basic)
+ category = AI_PROJECT_INDUCTION
+ can_be_run = FALSE
+ ability_path = /datum/action/innate/ai/ranged/charge_borg_or_apc
+ ability_recharge_cost = 1500
+
+/datum/ai_project/induction_cyborg/finish()
+ var/datum/action/innate/ai/ranged/charge_borg_or_apc/ability = add_ability(/datum/action/innate/ai/ranged/charge_borg_or_apc)
+ var/obj/effect/proc_holder/ranged_ai/charge_borg_or_apc/effect = ability.linked_ability
+ if(ability)
+ effect.works_on_apcs = TRUE
+ else
+ ability = locate(/datum/action/innate/ai/ranged/charge_borg_or_apc) in ai.actions
+ effect = ability.linked_ability
+ effect.works_on_apcs = TRUE
+
+
+/datum/action/innate/ai/ranged/charge_borg_or_apc
+ name = "Charge cyborg/APC"
+ desc = "Depending on upgrades you can charge either cyborgs, APCs or both by 33%"
+ button_icon_state = "electrified"
+ uses = 1
+ delete_on_empty = FALSE
+ linked_ability_type = /obj/effect/proc_holder/ranged_ai/charge_borg_or_apc
+
+/datum/action/innate/ai/ranged/charge_borg_or_apc/proc/charge_borg_or_apc(atom/target)
+ if(target && !QDELETED(target))
+ if(istype(target, /mob/living/silicon/robot))
+ var/mob/living/silicon/robot/R = target
+ log_game("[key_name(usr)] charged [R.name].")
+ if(R.cell)
+ if(R.cell.charge >= R.cell.maxcharge)
+ to_chat(owner, span_warning("[R]'s power cell is already full!"))
+ return FALSE
+ R.charge(null, R.cell.maxcharge * 0.33)
+ return TRUE
+ else
+ to_chat(owner, span_warning("[R] has no powercell to charge!"))
+ else if(istype(target, /obj/machinery/power/apc))
+ var/obj/machinery/power/apc/APC = target
+ var/turf/T = get_turf(APC)
+ log_game("[key_name(usr)] charged [APC.name] at [AREACOORD(T)].")
+ if(APC.cell)
+ if(APC.cell.charge >= APC.cell.maxcharge)
+ to_chat(owner, span_warning("The APC is already fully charged!"))
+ return FALSE
+ APC.cell.give(APC.cell.maxcharge * 0.33)
+ return TRUE
+ else
+ to_chat(owner, span_warning("The APC has no powercell to charge!"))
+
+/obj/effect/proc_holder/ranged_ai/charge_borg_or_apc
+ active = FALSE
+ var/works_on_borgs = FALSE
+ var/works_on_apcs = FALSE
+ enable_text = span_notice("You prepare bluespace induction coils. Click a borg or APC to charge its cell by 33%")
+ disable_text = span_notice("You power down your induction coils.")
+
+/obj/effect/proc_holder/ranged_ai/charge_borg_or_apc/InterceptClickOn(mob/living/caller, params, atom/target)
+ if(..())
+ return
+ if(ranged_ability_user.incapacitated())
+ remove_ranged_ability()
+ return
+ if(!istype(target, /mob/living/silicon/robot) && !istype(target, /obj/machinery/power/apc))
+ to_chat(ranged_ability_user, span_warning("You can only charge cyborgs or APCs!"))
+ return
+ if(!works_on_borgs && istype(target, /mob/living/silicon/robot))
+ to_chat(ranged_ability_user, span_warning("You can only charge APCs!"))
+ return
+ if(!works_on_apcs && istype(target, /obj/machinery/power/apc))
+ to_chat(ranged_ability_user, span_warning("You can only charge cyborgs!"))
+ return
+
+ ranged_ability_user.playsound_local(ranged_ability_user, "sparks", 50, 0)
+
+ to_chat(caller, span_notice("You charge [target]."))
+ do_sparks(3, FALSE, target)
+ target.audible_message(span_userdanger("You hear a soothing electrical buzzing sound coming from [target]!"))
+ var/datum/action/innate/ai/ranged/charge_borg_or_apc/action = attached_action
+ if(action.charge_borg_or_apc(target))
+ attached_action.adjust_uses(-1)
+ remove_ranged_ability()
+ return TRUE
diff --git a/icons/mob/actions/actions_AI.dmi b/icons/mob/actions/actions_AI.dmi
index 2ddc7923cc3e56b3df04a1d90612c3f5c2265117..8c92c6ba09a96bcf7b5a1eaf30bbc58cc7d81a26 100644
GIT binary patch
literal 9170
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
literal 8853
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