diff --git a/code/game/machinery/computer/buildandrepair.dm b/code/game/machinery/computer/buildandrepair.dm
index 79bec6162f8..f06a943d473 100644
--- a/code/game/machinery/computer/buildandrepair.dm
+++ b/code/game/machinery/computer/buildandrepair.dm
@@ -163,6 +163,11 @@
build_path = /obj/machinery/computer/aiupload
origin_tech = "programming=4;engineering=4"
+/obj/item/circuitboard/aiupload_broken
+ board_name = "AI Upload"
+ desc = "The board is charred and smells of burnt plastic. It has been rendered useless."
+ icon_state = "command_broken"
+
/obj/item/circuitboard/borgupload
board_name = "Cyborg Upload"
icon_state = "command"
diff --git a/code/game/machinery/computer/law.dm b/code/game/machinery/computer/law.dm
index d8e06ad16e1..31c2a4fa3e4 100644
--- a/code/game/machinery/computer/law.dm
+++ b/code/game/machinery/computer/law.dm
@@ -1,3 +1,5 @@
+#define AIUPLOAD_EMAG_COOLDOWN 60 SECONDS
+
/obj/machinery/computer/aiupload
name = "\improper AI upload console"
desc = "Used to upload laws to the AI."
@@ -6,10 +8,24 @@
circuit = /obj/item/circuitboard/aiupload
var/mob/living/silicon/ai/current = null
var/opened = FALSE
-
light_color = LIGHT_COLOR_WHITE
light_range_on = 2
+ /// sets the cooldown time between uploads when emag'd
+ var/cooldown = 0
+ /// holds the value for when the inherent_laws are counted in countlaws()
+ var/found_laws = 0
+//For emagging the console
+/obj/machinery/computer/aiupload/emag_act(mob/user)
+ if(emagged)
+ return
+ emagged = TRUE
+ if(user)
+ user.visible_message("Sparks fly out of [src]!",
+ "You emag [src], scrambling the computer's law encoding system.")
+ playsound(loc, 'sound/effects/sparks4.ogg', 50, TRUE)
+ do_sparks(5, TRUE, src)
+ circuit = /obj/item/circuitboard/aiupload_broken
// What the fuck even is this
/obj/machinery/computer/aiupload/verb/AccessInternals()
@@ -27,20 +43,76 @@
return
-/obj/machinery/computer/aiupload/attackby(obj/item/O as obj, mob/user as mob, params)
- if(istype(O, /obj/item/aiModule))
- if(!current)//no AI selected
- to_chat(user, "No AI selected. Please chose a target before proceeding with upload.")
- return
- var/turf/T = get_turf(current)
- if(!atoms_share_level(T, src))
- to_chat(user, "Unable to establish a connection: You're too far away from the target silicon!")
- return
+/obj/machinery/computer/aiupload/attackby(obj/item/O, mob/user, params)
+ if(!istype(O, /obj/item/aiModule))
+ return ..()
+ if(!check_valid_selection(user))
+ return
+ if(!emagged) //non-emag law change
var/obj/item/aiModule/M = O
M.install(src)
return
- return ..()
+ apply_emag_laws(user)
+ return
+/// checks to ensure there is a selected AI, and that it is on the same Z level
+/obj/machinery/computer/aiupload/proc/check_valid_selection(mob/user)
+ if(!current)//no AI selected
+ to_chat(user, "No AI selected. Please choose a target before proceeding with upload.")
+ return FALSE
+ var/turf/T = get_turf(current)
+ if(!atoms_share_level(T, src))//off Z level
+ to_chat(user, "Unable to establish a connection: You're too far away from the target silicon!")
+ return FALSE
+ return TRUE
+
+/// applies ion-like laws into either the inherent law or true ion law positions due to an emag'd AI upload being used
+/obj/machinery/computer/aiupload/proc/apply_emag_laws(mob/user)
+ if(world.time < cooldown) //if the cooldown isnt over
+ to_chat(user, "The program seems to have frozen. It will need some time to process.")
+ return
+ do_sparks(5, TRUE, src)
+ found_laws = length(current.laws.inherent_laws)
+ if(!emag_ion_check()) //creates an ion-like inherent law if the ion_laws arnt modified or added
+ emag_inherent_law()
+
+/// checks to see if an ion law is added or modified
+/obj/machinery/computer/aiupload/proc/emag_ion_check()
+ var/datum/ai_law/inherent/new_law = new(generate_ion_law())
+ var/emag_law = new_law.law
+ if(!length(current.laws.ion_laws))
+ if(prob(80)) // 20% chance to generate an ion law if none exists
+ return FALSE
+ current.add_ion_law(generate_ion_law())
+ cooldown = world.time + AIUPLOAD_EMAG_COOLDOWN
+ return TRUE
+ if(prob(90)) //10% chance to overwrite a current ion
+ return FALSE
+ current.laws.ion_laws[1].law = emag_law
+ cooldown = world.time + AIUPLOAD_EMAG_COOLDOWN
+ log_and_message_admins("has given [current] the ion law: [current.laws.ion_laws[1].law].")
+ return TRUE
+
+/// modifies one of the AI's laws to read like an ion law
+/obj/machinery/computer/aiupload/proc/emag_inherent_law()
+ if(!found_laws)
+ return
+ var/datum/ai_law/inherent/new_law = new(generate_ion_law())
+ var/emag_law = new_law.law
+ var/lawposition = rand(1, found_laws)
+ current.laws.inherent_laws[lawposition].law = emag_law
+ log_and_message_admins("has given [current] the emag'd inherent law: [current.laws.inherent_laws[lawposition].law].")
+ current.show_laws()
+ alert_silicons()
+ cooldown = world.time + AIUPLOAD_EMAG_COOLDOWN
+
+/// pushes an alert to the AI and its borgs about the law changes
+/obj/machinery/computer/aiupload/proc/alert_silicons()
+ current.show_laws()
+ current.throw_alert("newlaw", /obj/screen/alert/newlaw)
+ for(var/mob/living/silicon/robot/borg in current.connected_robots)
+ borg.cmd_show_laws()
+ borg.throw_alert("newlaw", /obj/screen/alert/newlaw)
/obj/machinery/computer/aiupload/attack_hand(mob/user as mob)
if(src.stat & NOPOWER)
@@ -61,6 +133,8 @@
/obj/machinery/computer/aiupload/attack_ghost(user as mob)
return 1
+#undef AIUPLOAD_EMAG_COOLDOWN
+
// Why is this not a subtype
/obj/machinery/computer/borgupload
name = "cyborg upload console"
diff --git a/icons/obj/module.dmi b/icons/obj/module.dmi
index 0aea30a7b42..a1dad69342b 100644
Binary files a/icons/obj/module.dmi and b/icons/obj/module.dmi differ