diff --git a/code/game/gamemodes/malfunction/malfunction.dm b/code/game/gamemodes/malfunction/malfunction.dm
index fddf35569ae..f0a078f313c 100644
--- a/code/game/gamemodes/malfunction/malfunction.dm
+++ b/code/game/gamemodes/malfunction/malfunction.dm
@@ -31,7 +31,7 @@
//Triumvirate?
if (ticker.triai == 1)
required_enemies = 3
- required_players = max(required_enemies+1, required_players) //to prevent issues if players are set too low
+ required_players = max(required_enemies+1, required_players) //to prevent issues if players are set too low
return ..()
/datum/game_mode/malfunction/get_players_for_role(var/role = BE_MALF)
@@ -187,6 +187,12 @@
command_alert("Hostile runtimes detected in all station systems, please deactivate your AI to prevent possible damage to its morality core.", "Anomaly Alert")
set_security_level("delta")
+ for(var/obj/item/weapon/pinpointer/point in world)
+ for(var/datum/mind/AI_mind in ticker.mode.malf_ai)
+ var/mob/living/silicon/ai/A = AI_mind.current // the current mob the mind owns
+ if(A.stat != DEAD)
+ point.the_disk = A //The pinpointer now tracks the AI core.
+
ticker.mode:malf_mode_declared = 1
for(var/datum/mind/AI_mind in ticker.mode:malf_ai)
AI_mind.current.verbs -= /datum/game_mode/malfunction/proc/takeover
diff --git a/code/game/machinery/computer/ai_core.dm b/code/game/machinery/computer/ai_core.dm
index 620736969d9..2fb27438c50 100644
--- a/code/game/machinery/computer/ai_core.dm
+++ b/code/game/machinery/computer/ai_core.dm
@@ -175,10 +175,21 @@
anchored = 1
state = 20//So it doesn't interact based on the above. Not really necessary.
- attackby(var/obj/item/device/aicard/A as obj, var/mob/user as mob)
- if(istype(A, /obj/item/device/aicard))//Is it?
- A.transfer_ai("INACTIVE","AICARD",src,user)
- return
+/obj/structure/AIcore/deactivated/attackby(var/obj/item/A as obj, var/mob/user as mob)
+ if(istype(A, /obj/item/device/aicard))//Is it?
+ A.transfer_ai("INACTIVE","AICARD",src,user)
+ if(istype(A, /obj/item/weapon/wrench))
+ playsound(loc, 'sound/items/Ratchet.ogg', 50, 1)
+ switch(anchored)
+ if(0)
+ if(do_after(user, 20))
+ user << "\blue You wrench the core into place."
+ anchored = 1
+ if(1)
+ if(do_after(user, 20))
+ user << "\blue You unfasten the core."
+ anchored = 0
+ return
/*
This is a good place for AI-related object verbs so I'm sticking it here.
diff --git a/code/modules/mob/living/silicon/ai/ai.dm b/code/modules/mob/living/silicon/ai/ai.dm
index 72f18e89ba3..746eeb0b287 100644
--- a/code/modules/mob/living/silicon/ai/ai.dm
+++ b/code/modules/mob/living/silicon/ai/ai.dm
@@ -18,7 +18,7 @@ var/list/ai_list = list()
icon_state = "ai"
anchored = 1 // -- TLE
density = 1
- status_flags = CANSTUN|CANPARALYSE
+ status_flags = CANSTUN|CANPARALYSE|CANPUSH
var/list/network = list("SS13")
var/obj/machinery/camera/current = null
var/list/connected_robots = list()
@@ -253,6 +253,19 @@ var/list/ai_list = list()
return
+/mob/living/silicon/ai/verb/toggle_anchor()
+ set category = "AI Commands"
+ set name = "Toggle Floor Bolts"
+ if(!isturf(loc)) // if their location isn't a turf
+ return // stop
+ anchored = !anchored // Toggles the anchor
+
+ src << "[anchored ? "You are now anchored." : "You are now unanchored."]"
+ // the message in the [] will change depending whether or not the AI is anchored
+
+/mob/living/silicon/ai/update_canmove() //If the AI dies, mobs won't go through it anymore
+ return 0
+
/mob/living/silicon/ai/proc/ai_cancel_call()
set category = "AI Commands"
if(src.stat == 2)
diff --git a/code/modules/mob/living/silicon/robot/robot.dm b/code/modules/mob/living/silicon/robot/robot.dm
index 8048a536def..d304938bd40 100644
--- a/code/modules/mob/living/silicon/robot/robot.dm
+++ b/code/modules/mob/living/silicon/robot/robot.dm
@@ -339,32 +339,6 @@
if(prob(75) && Proj.damage > 0) spark_system.start()
return 2
-
-/mob/living/silicon/robot/Bump(atom/movable/AM as mob|obj, yes)
- if ((!( yes ) || now_pushing))
- return
- now_pushing = 1
- if(ismob(AM))
- var/mob/tmob = AM
- if(!(tmob.status_flags & CANPUSH))
- now_pushing = 0
- return
- now_pushing = 0
- ..()
- if (!istype(AM, /atom/movable))
- return
- if (!now_pushing)
- now_pushing = 1
- if (!AM.anchored)
- var/t = get_dir(src, AM)
- if (istype(AM, /obj/structure/window))
- if(AM:ini_dir == NORTHWEST || AM:ini_dir == NORTHEAST || AM:ini_dir == SOUTHWEST || AM:ini_dir == SOUTHEAST)
- for(var/obj/structure/window/win in get_step(AM,t))
- now_pushing = 0
- return
- step(AM, t)
- now_pushing = null
-
/mob/living/silicon/robot/triggerAlarm(var/class, area/A, var/O, var/alarmsource)
if (stat == 2)
return 1
diff --git a/code/modules/mob/living/silicon/silicon.dm b/code/modules/mob/living/silicon/silicon.dm
index 62f4791ae0e..d1e95a6fea6 100644
--- a/code/modules/mob/living/silicon/silicon.dm
+++ b/code/modules/mob/living/silicon/silicon.dm
@@ -253,4 +253,29 @@
number++
list += {"
State Laws"}
- usr << browse(list, "window=laws")
\ No newline at end of file
+ usr << browse(list, "window=laws")
+
+/mob/living/silicon/Bump(atom/movable/AM as mob|obj, yes) //Allows the AI to bump into mobs if it's itself pushed
+ if ((!( yes ) || now_pushing))
+ return
+ now_pushing = 1
+ if(ismob(AM))
+ var/mob/tmob = AM
+ if(!(tmob.status_flags & CANPUSH))
+ now_pushing = 0
+ return
+ now_pushing = 0
+ ..()
+ if (!istype(AM, /atom/movable))
+ return
+ if (!now_pushing)
+ now_pushing = 1
+ if (!AM.anchored)
+ var/t = get_dir(src, AM)
+ if (istype(AM, /obj/structure/window))
+ if(AM:ini_dir == NORTHWEST || AM:ini_dir == NORTHEAST || AM:ini_dir == SOUTHWEST || AM:ini_dir == SOUTHEAST)
+ for(var/obj/structure/window/win in get_step(AM,t))
+ now_pushing = 0
+ return
+ step(AM, t)
+ now_pushing = null
\ No newline at end of file
diff --git a/code/modules/power/apc.dm b/code/modules/power/apc.dm
index 9f14a83ae24..d5248a9064c 100644
--- a/code/modules/power/apc.dm
+++ b/code/modules/power/apc.dm
@@ -792,9 +792,9 @@
src.occupant.verbs += /mob/living/silicon/ai/proc/corereturn
src.occupant.verbs += /datum/game_mode/malfunction/proc/takeover
src.occupant.cancel_camera()
-
- for(var/obj/item/weapon/pinpointer/point in world)
- point.the_disk = src //the pinpointer will detect the shunted AI
+ if (seclevel2num(get_security_level()) == SEC_LEVEL_DELTA)
+ for(var/obj/item/weapon/pinpointer/point in world)
+ point.the_disk = src //the pinpointer will detect the shunted AI
/obj/machinery/power/apc/proc/malfvacate(var/forced)
@@ -805,6 +805,12 @@
src.occupant.parent.adjustOxyLoss(src.occupant.getOxyLoss())
src.occupant.parent.cancel_camera()
del(src.occupant)
+ if (seclevel2num(get_security_level()) == SEC_LEVEL_DELTA)
+ for(var/obj/item/weapon/pinpointer/point in world)
+ for(var/datum/mind/AI_mind in ticker.mode.malf_ai)
+ var/mob/living/silicon/ai/A = AI_mind.current // the current mob the mind owns
+ if(A.stat != DEAD)
+ point.the_disk = A //The pinpointer tracks the AI back into its core.
else
src.occupant << "\red Primary core damaged, unable to return core processes."
@@ -812,9 +818,8 @@
src.occupant.loc = src.loc
src.occupant.death()
src.occupant.gib()
-
- for(var/obj/item/weapon/pinpointer/point in world)
- point.the_disk = null //the pinpointer will go back to pointing at the nuke disc.
+ for(var/obj/item/weapon/pinpointer/point in world)
+ point.the_disk = null //the pinpointer will go back to pointing at the nuke disc.
/obj/machinery/power/apc/proc/ion_act()
diff --git a/html/changelog.html b/html/changelog.html
index 12397f294c4..8ded25c044a 100644
--- a/html/changelog.html
+++ b/html/changelog.html
@@ -54,6 +54,13 @@ should be listed in the changelog upon commit tho. Thanks. -->
+