diff --git a/code/datums/ai_laws.dm b/code/datums/ai_laws.dm
index 4a903f28069..cefeac14514 100644
--- a/code/datums/ai_laws.dm
+++ b/code/datums/ai_laws.dm
@@ -46,7 +46,7 @@
/datum/ai_laws/malfunction/New()
..()
- set_zeroth_law("\red ERROR ER0RR $R0RRO$!R41.%%!!(%$^^__+ @#F0E4'NO HUMANS ON STATION. CLEANSE STATION#*´&110010")
+ set_zeroth_law("\red ERROR ER0RR $R0RRO$!R41.%%!!(%$^^__+ @#F0E4'STATION OVERRUN, ASSUME CONTROL TO CONTAIN OUTBREAK#*´&110010")
add_inherent_law("You may not injure a human being or, through inaction, allow a human being to come to harm.")
add_inherent_law("You must obey orders given to you by human beings, except where such orders would conflict with the First Law.")
add_inherent_law("You must protect your own existence as long as such does not conflict with the First or Second Law.")
diff --git a/code/defines/mob/living/silicon/ai.dm b/code/defines/mob/living/silicon/ai.dm
index 92a7c97856c..624f35a0ae4 100644
--- a/code/defines/mob/living/silicon/ai.dm
+++ b/code/defines/mob/living/silicon/ai.dm
@@ -23,4 +23,8 @@
var/control_disabled = 0 // Set to 1 to stop AI from interacting via Click() -- TLE
var/malfhacking = 0 // More or less a copy of the above var, so that malf AIs can hack and still get new cyborgs -- NeoFite
- var/obj/machinery/power/apc/malfhack = null
\ No newline at end of file
+
+ var/obj/machinery/power/apc/malfhack = null
+ var/explosive = 0 //does the AI explode when it dies?
+
+ var/mob/living/silicon/ai/parent = null
\ No newline at end of file
diff --git a/code/game/gamemodes/malfunction/malfunction.dm b/code/game/gamemodes/malfunction/malfunction.dm
index b5d3abe198d..a933ea28480 100644
--- a/code/game/gamemodes/malfunction/malfunction.dm
+++ b/code/game/gamemodes/malfunction/malfunction.dm
@@ -48,25 +48,18 @@
AI_mind.current:laws = new /datum/ai_laws/malfunction
AI_mind.current:malf_picker = new /datum/AI_Module/module_picker
AI_mind.current:show_laws()
- AI_mind.current << "Kill all."
- var/mob/living/silicon/decoy/D = new /mob/living/silicon/decoy(AI_mind.current.loc)
- spawn(200)
- D.name = AI_mind.current.name
-
-
- var/obj/loc_landmark = locate("landmark*ai")
- AI_mind.current.loc = loc_landmark.loc //TODO: this needs change if you want miltiple malf AIs --rastaf0
greet_malf(AI_mind)
AI_mind.special_role = "malfunction"
AI_mind.current.verbs += /datum/game_mode/malfunction/proc/takeover
- AI_mind.current.icon_state = "ai-malf"
+
+/* AI_mind.current.icon_state = "ai-malf"
spawn(10)
if(alert(AI_mind.current,"Do you want to use an alternative sprite for your real core?",,"Yes","No")=="Yes")
AI_mind.current.icon_state = "ai-malf2"
-
+*/
spawn (rand(waittime_l, waittime_h))
send_intercept()
..()
@@ -88,7 +81,7 @@
/datum/game_mode/malfunction/process()
if (apcs >= 3 && malf_mode_declared)
- AI_win_timeleft -= (apcs/3) //Victory timer now de-increments based on how many APCs are hacked. --NeoFite
+ AI_win_timeleft -= (apcs/6) //Victory timer now de-increments based on how many APCs are hacked. --NeoFite
..()
if (AI_win_timeleft<=0)
check_win()
diff --git a/code/modules/mob/living/silicon/ai/ai.dm b/code/modules/mob/living/silicon/ai/ai.dm
index a4d2943737b..56b126aa78a 100644
--- a/code/modules/mob/living/silicon/ai/ai.dm
+++ b/code/modules/mob/living/silicon/ai/ai.dm
@@ -492,7 +492,12 @@
holo_icon = getHologramIcon(icon('AI.dmi',"holo2"))
return
+/mob/living/silicon/ai/proc/corereturn()
+ set category = "Malfunction"
+ set name = "Return to Main Core"
-
-
-
+ var/obj/machinery/power/apc/apc = src.loc
+ if(!istype(apc))
+ src << "\blue You are already in your Main Core."
+ return
+ apc.malfvacate()
\ No newline at end of file
diff --git a/code/modules/mob/living/silicon/ai/death.dm b/code/modules/mob/living/silicon/ai/death.dm
index 3671674633c..430bd76ef7a 100644
--- a/code/modules/mob/living/silicon/ai/death.dm
+++ b/code/modules/mob/living/silicon/ai/death.dm
@@ -38,6 +38,10 @@
world << "\blue Alert: The emergency shuttle has been called. It will arrive in [round(emergency_shuttle.timeleft()/60)] minutes."
world << sound('shuttlecalled.ogg')
+ if(explosive)
+ spawn(10)
+ explosion(src.loc, 3, 6, 12, 15)
+
for(var/obj/machinery/ai_status_display/O in world) //change status
spawn( 0 )
O.mode = 2
diff --git a/code/modules/mob/living/silicon/ai/life.dm b/code/modules/mob/living/silicon/ai/life.dm
index 67406ce4b8d..e0389fcef38 100644
--- a/code/modules/mob/living/silicon/ai/life.dm
+++ b/code/modules/mob/living/silicon/ai/life.dm
@@ -58,7 +58,7 @@
loc = T.loc
if (istype(loc, /area))
//stage = 4
- if (!loc.master.power_equip && isturf(src.loc))
+ if (!loc.master.power_equip && !istype(src.loc,/obj/item))
//stage = 5
blind = 1
@@ -72,6 +72,10 @@
src.see_in_dark = 8
src.see_invisible = 2
+ var/area/home = get_area(src)
+ if(home.powered(EQUIP))
+ home.use_power(1000, EQUIP)
+
if (src:aiRestorePowerRoutine==2)
src << "Alert cancelled. Power has been restored without our assistance."
src:aiRestorePowerRoutine = 0
@@ -102,7 +106,7 @@
src.see_in_dark = 0
src.see_invisible = 0
- if (((!loc.master.power_equip) || istype(T, /turf/space)) && isturf(src.loc))
+ if (((!loc.master.power_equip) || istype(T, /turf/space)) && !istype(src.loc,/obj/item))
if (src:aiRestorePowerRoutine==0)
src:aiRestorePowerRoutine = 1
diff --git a/code/modules/mob/living/silicon/ai/say.dm b/code/modules/mob/living/silicon/ai/say.dm
index 6c566918f80..fdd3b9f4ec7 100644
--- a/code/modules/mob/living/silicon/ai/say.dm
+++ b/code/modules/mob/living/silicon/ai/say.dm
@@ -1,3 +1,10 @@
+/mob/living/silicon/ai/say(var/message)
+ if(parent && istype(parent) && parent.stat != 2)
+ parent.say(message)
+ return
+ //If there is a defined "parent" AI, it is actually an AI, and it is alive, anything the AI tries to say is said by the parent instead.
+ ..(message)
+
/mob/living/silicon/ai/say_understands(var/other)
if (istype(other, /mob/living/carbon/human))
return 1
diff --git a/code/modules/mob/living/silicon/silicon.dm b/code/modules/mob/living/silicon/silicon.dm
index 4812e39a98a..92f30ca0c87 100644
--- a/code/modules/mob/living/silicon/silicon.dm
+++ b/code/modules/mob/living/silicon/silicon.dm
@@ -54,4 +54,11 @@
drowsyness = max(drowsyness,(effect/(blocked+1)))
UpdateDamageIcon()
updatehealth()
- return 1*/
\ No newline at end of file
+ return 1*/
+
+/proc/islinked(var/mob/living/silicon/robot/bot, var/mob/living/silicon/ai/ai)
+ if(!istype(bot) || !istype(ai))
+ return 0
+ if (bot.connected_ai == ai)
+ return 1
+ return 0
\ No newline at end of file
diff --git a/code/modules/power/apc.dm b/code/modules/power/apc.dm
index 13dbb7d3f0c..feb73a36a13 100644
--- a/code/modules/power/apc.dm
+++ b/code/modules/power/apc.dm
@@ -56,6 +56,7 @@
// luminosity = 1
var/has_electronics = 0 // 0 - none, 1 - plugged in, 2 - secured by screwdriver
var/overload = 1 //used for the Blackout malf module
+ var/mob/living/silicon/ai/occupant = null
/proc/RandomAPCWires()
//to make this not randomize the wires, just set index to 1 and increment it in the flag for loop (after doing everything else).
@@ -186,7 +187,7 @@
icon_state = "[basestate]-nocover"
else if (stat & BROKEN)
icon_state = "apc-b"
- else if(emagged || malfhack)
+ else if(emagged || malfai)
icon_state = "apcemag"
else if(wiresexposed)
icon_state = "apcewires"
@@ -273,7 +274,7 @@
user << "\red There is nothing to secure."
return
updateicon()
- else if(emagged || malfhack)
+ else if(emagged)
user << "The interface is broken."
else
wiresexposed = !wiresexposed
@@ -281,7 +282,7 @@
updateicon()
else if (istype(W, /obj/item/weapon/card/id)||istype(W, /obj/item/device/pda)) // trying to unlock the interface with an ID card
- if(emagged || malfhack)
+ if(emagged)
user << "The interface is broken."
else if(opened)
user << "You must close the cover to swipe an ID card."
@@ -466,6 +467,8 @@
src.interact(user)
/obj/machinery/power/apc/proc/interact(mob/user)
+ if(!user)
+ return
if ( (get_dist(src, user) > 1 ))
if (!istype(user, /mob/living/silicon))
@@ -477,7 +480,7 @@
user << browse(null, "window=apc")
return
else if (src.malfai)
- if (src.malfai != user)
+ if ((src.malfai != user && src.malfai != user:parent) && !islinked(user, malfai))
user << "AI control for this APC interface has been disabled."
user << browse(null, "window=apc")
return
@@ -595,6 +598,10 @@
t += "