diff --git a/code/_onclick/hud/screen_alarms.dm b/code/_onclick/hud/screen_alarms.dm
index 60a5019e287..8abda525839 100644
--- a/code/_onclick/hud/screen_alarms.dm
+++ b/code/_onclick/hud/screen_alarms.dm
@@ -82,6 +82,10 @@
client.screen -= alert
qdel(alert)
+/mob/proc/clear_all_alerts()
+ for(var/category in alerts)
+ clear_alert(category)
+
// PRIVATE = only edit, use, or override these if you're editing the system as a whole
@@ -97,6 +101,8 @@ var/global/list/screen_alarms_locs = list(
/datum/hud/proc/reorganize_alerts()
var/list/alerts = mymob.alerts
var/icon_pref
+ if(!alerts.len)
+ return FALSE
if(!hud_shown)
for(var/i = 1, i <= alerts.len, i++)
mymob.client.screen -= alerts[alerts[i]]
@@ -140,6 +146,8 @@ var/global/list/screen_alarms_locs = list(
#define SCREEN_ALARM_ROBOT_HACK "robot_hack"
#define SCREEN_ALARM_ROBOT_LOCK "robot_lock"
+#define SCREEN_ALARM_APC_HACKING "apc_hacking"
+
#define SCREEN_ALARM_NAMEPICK "namepick"
/obj/abstract/screen/alert
@@ -326,6 +334,20 @@ var/global/list/screen_alarms_locs = list(
desc = "This unit is on fire."
icon_state = "silicon_fire"
+/obj/abstract/screen/alert/robot/apc_hacking
+ icon_state = "hacking"
+ name = "Overriding APC"
+ desc = "You are currently overriding an APC's programming. Click this alert to jump to the APC."
+
+/obj/abstract/screen/alert/robot/apc_hacking/Click()
+ ..()
+ if(!isAI(usr))
+ return
+ var/mob/living/silicon/ai/A = usr
+ if(A.alerts[SCREEN_ALARM_APC_HACKING] == src)
+ if(A.eyeobj && A.malfhacking && A.malfhack)
+ A.eyeobj.forceMove(A.malfhack.loc)
+
/obj/abstract/screen/alert/robot/hacked
name = "Hacked"
desc = "Hazardous non-standard equipment detected. Please ensure any usage of this equipment is in line with this unit's laws, if any."
diff --git a/code/_onclick/hud/spell_screen_objects.dm b/code/_onclick/hud/spell_screen_objects.dm
index 939b09a1840..26c4bd2e223 100644
--- a/code/_onclick/hud/spell_screen_objects.dm
+++ b/code/_onclick/hud/spell_screen_objects.dm
@@ -177,7 +177,7 @@
/obj/abstract/screen/movable/spell_master/malf
name = "Malfunction Modules"
- icon_state = "grey_spell_ready"
+ icon_state = "malf_spell_ready"
open_state = "malf_open"
closed_state = "malf_closed"
diff --git a/code/datums/gamemode/factions/malf.dm b/code/datums/gamemode/factions/malf.dm
index ca3aff77d34..4b03228721f 100644
--- a/code/datums/gamemode/factions/malf.dm
+++ b/code/datums/gamemode/factions/malf.dm
@@ -76,7 +76,7 @@
to_chat(malfAI.antag.current, {"Congratulations! The station is now under your exclusive control.
You may decide to blow up the station. You have 60 seconds to choose.
You should now be able to use your Explode spell to interface with the nuclear fission device."})
- malfAI.antag.current.add_spell(new /spell/targeted/ai_win, "grey_spell_ready", /obj/abstract/screen/movable/spell_master/malf)
+ malfAI.antag.current.add_spell(new /spell/targeted/ai_win, "malf_spell_ready", /obj/abstract/screen/movable/spell_master/malf)
return
diff --git a/code/datums/gamemode/role/role.dm b/code/datums/gamemode/role/role.dm
index 23746f5eae8..a4a19202e73 100644
--- a/code/datums/gamemode/role/role.dm
+++ b/code/datums/gamemode/role/role.dm
@@ -579,8 +579,8 @@
if(istype(antag.current,/mob/living/silicon/ai))
var/mob/living/silicon/ai/malfAI = antag.current
- malfAI.add_spell(new /spell/aoe_turf/module_picker, "grey_spell_ready",/obj/abstract/screen/movable/spell_master/malf)
- malfAI.add_spell(new /spell/aoe_turf/takeover, "grey_spell_ready",/obj/abstract/screen/movable/spell_master/malf)
+ malfAI.add_spell(new /spell/aoe_turf/module_picker, "malf_spell_ready",/obj/abstract/screen/movable/spell_master/malf)
+ malfAI.add_spell(new /spell/aoe_turf/takeover, "malf_spell_ready",/obj/abstract/screen/movable/spell_master/malf)
malfAI.laws_sanity_check()
var/datum/ai_laws/laws = malfAI.laws
laws.malfunction()
diff --git a/code/game/gamemodes/malfunction/Malf_Modules.dm b/code/game/gamemodes/malfunction/Malf_Modules.dm
index a28ae561880..45a9ef59bbd 100644
--- a/code/game/gamemodes/malfunction/Malf_Modules.dm
+++ b/code/game/gamemodes/malfunction/Malf_Modules.dm
@@ -36,7 +36,7 @@ rcd light flash thingy on matter drain
if (istype(S,power_type))
S.charge_counter += uses
return
- user.add_spell(new power_type, "grey_spell_ready",/obj/abstract/screen/movable/spell_master/malf)
+ user.add_spell(new power_type, "malf_spell_ready",/obj/abstract/screen/movable/spell_master/malf)
// statistics collection - malf module purchases
if(user.mind && istype(user.mind.faction, /datum/faction/malf))
@@ -84,7 +84,7 @@ rcd light flash thingy on matter drain
charge_type = Sp_CHARGES
charge_max = 1
hud_state = "rcd_disable"
- override_base = "grey"
+ override_base = "malf"
/spell/aoe_turf/disable_rcd/cast(list/targets, mob/user)
for(var/obj/item/device/rcd/matter/engineering/rcd in rcd_list)
@@ -110,7 +110,7 @@ rcd light flash thingy on matter drain
charge_type = Sp_CHARGES
charge_max = 2
hud_state = "overload"
- override_base = "grey"
+ override_base = "malf"
/spell/targeted/overload_machine/is_valid_target(var/atom/target)
if (istype(target, /obj/machinery))
@@ -144,7 +144,7 @@ rcd light flash thingy on matter drain
range = GLOBALCAST
summon_type = list(/obj/machinery/autoborger/conveyor)
hud_state = "autoborger"
- override_base = "grey"
+ override_base = "malf"
/spell/aoe_turf/conjure/place_autoborger/New()
..()
@@ -217,7 +217,7 @@ rcd light flash thingy on matter drain
charge_type = Sp_CHARGES
charge_max = 3
hud_state = "blackout"
- override_base = "grey"
+ override_base = "malf"
/spell/aoe_turf/blackout/cast(var/list/targets, mob/user)
for(var/obj/machinery/power/apc/apc in power_machines)
@@ -241,7 +241,7 @@ rcd light flash thingy on matter drain
charge_type = Sp_CHARGES
charge_max = 3
hud_state = "fakemessage"
- override_base = "grey"
+ override_base = "malf"
/spell/aoe_turf/interhack/cast(var/list/targets,mob/user)
@@ -283,7 +283,7 @@ rcd light flash thingy on matter drain
range = GLOBALCAST
spell_flags = WAIT_FOR_CLICK
hud_state = "camera_reactivate"
- override_base = "grey"
+ override_base = "malf"
var/list/camera_images = list()
/spell/targeted/reactivate_camera/before_channel(mob/user)
@@ -343,7 +343,7 @@ rcd light flash thingy on matter drain
spell_flags = WAIT_FOR_CLICK
range = GLOBALCAST
hud_state = "camera_upgrade"
- override_base = "grey"
+ override_base = "malf"
/spell/targeted/upgrade_camera/is_valid_target(var/atom/target)
if(!istype(target, /obj/machinery/camera))
@@ -382,7 +382,7 @@ rcd light flash thingy on matter drain
var/datum/module_picker/MP
charge_max = 10
hud_state = "choose_module"
- override_base = "grey"
+ override_base = "malf"
/spell/aoe_turf/module_picker/New()
..()
@@ -456,7 +456,7 @@ rcd light flash thingy on matter drain
charge_type = Sp_CHARGES
charge_max = 1
hud_state = "systemtakeover"
- override_base = "grey"
+ override_base = "malf"
/spell/aoe_turf/takeover/before_target(mob/user)
var/datum/faction/malf/M = find_active_faction_by_member(user.mind.GetRole(MALF))
@@ -496,7 +496,7 @@ rcd light flash thingy on matter drain
max_targets = 1
hud_state = "radiation"
- override_base = "grey"
+ override_base = "malf"
/spell/targeted/ai_win/before_target(mob/user)
var/datum/faction/malf/M = find_active_faction_by_member(user.mind.GetRole(MALF))
diff --git a/code/modules/mob/living/silicon/ai/life.dm b/code/modules/mob/living/silicon/ai/life.dm
index 5fe8420edc5..dffc02399d0 100644
--- a/code/modules/mob/living/silicon/ai/life.dm
+++ b/code/modules/mob/living/silicon/ai/life.dm
@@ -152,10 +152,10 @@
/mob/living/silicon/ai/Life()
if(timestopped)
return 0 //under effects of time magick
-
if (stat == DEAD)
return
-
+ if(client)
+ handle_regular_hud_updates()
if(life_handle_health())
return
@@ -188,3 +188,9 @@
/mob/living/silicon/ai/update_canmove() //If the AI dies, mobs won't go through it anymore
return FALSE
+
+/mob/living/silicon/ai/handle_regular_hud_updates()
+ if(malfhacking)
+ throw_alert(SCREEN_ALARM_APC_HACKING, /obj/abstract/screen/alert/robot/apc_hacking)
+ else
+ clear_alert(SCREEN_ALARM_APC_HACKING)
diff --git a/code/modules/mob/living/silicon/ai/login.dm b/code/modules/mob/living/silicon/ai/login.dm
index 78a6d5aa3e3..a72b75a6672 100644
--- a/code/modules/mob/living/silicon/ai/login.dm
+++ b/code/modules/mob/living/silicon/ai/login.dm
@@ -1,6 +1,6 @@
/mob/living/silicon/ai/Login() //ThisIsDumb(TM) TODO: tidy this up ¬_¬ ~Carn
..()
-
+
to_chat(src, "You are playing the station's AI. The AI cannot move, but can interact with many objects while viewing them (through cameras).")
to_chat(src, "To look at other parts of the station, click on yourself to get a camera menu.")
to_chat(src, "While observing through a camera, you can use most (networked) devices which you can see, such as computers, APCs, intercoms, doors, etc.")
@@ -8,13 +8,15 @@
to_chat(src, {"Use say ":b to speak to your cyborgs through binary."})
show_laws()
if(ismalf(src))
- to_chat(src, "These laws may be changed by other players, or by you being the traitor.")
-
+ to_chat(src, "These laws may be changed by other players, but you are not required to follow any of them.")
var/datum/runeset/rune_set = global_runesets["blood_cult"]
for(var/obj/effect/rune/rune in rune_set.rune_list) //HOLY FUCK WHO THOUGHT LOOPING THROUGH THE WORLD WAS A GOOD IDEA
client.images += rune.blood_image
regenerate_icons()
+ clear_all_alerts() //fuck alerts
+ handle_regular_hud_updates()
+
if(stat != DEAD)
for(var/obj/machinery/ai_status_display/O in machines) //change status
O.mode = 1
diff --git a/code/modules/power/apc.dm b/code/modules/power/apc.dm
index ff3e8ff0079..6baf50baa6e 100644
--- a/code/modules/power/apc.dm
+++ b/code/modules/power/apc.dm
@@ -76,6 +76,7 @@
var/wiresexposed = 0
powernet = 0 // set so that APCs aren't found as powernet nodes //Hackish, Horrible, was like this before I changed it :(
var/malfhack = 0 //New var for my changes to AI malf. --NeoFite
+ var/mob/living/silicon/ai/hacking_ai = null //The AI that is currently attempting to hack this APC
var/mob/living/silicon/ai/malfai = null //See above --NeoFite
var/malflocked = 0 //used for malfs locking down APCs
// luminosity = 1
@@ -930,11 +931,14 @@
to_chat(malfai, "Beginning override of APC systems. This will take [time_required/10] seconds, and you cannot hack other APC's during the process.")
malfai.malfhack = src
malfai.malfhacking = 1
+ hacking_ai = malfai
+ malfai.handle_regular_hud_updates()
sleep(time_required)
if(src && malfai)
if (!src.aidisabled)
malfai.malfhack = null
malfai.malfhacking = 0
+ hacking_ai = null
locked = 1
if(M && STATION_Z == z)
M.apcs++
@@ -943,6 +947,7 @@
else
src.malfai = usr
to_chat(malfai, "Hack complete. The APC is now under your exclusive control. [STATION_Z == z?"You now have [M.apcs] under your control.":"As this APC is not located on the station, it is not contributing to your control of it."]")
+ malfai.handle_regular_hud_updates()
update_icon()
else if (href_list["occupyapc"])
@@ -1001,7 +1006,7 @@
if(malf.parent)
qdel(malf)
malf = null
- src.occupant.add_spell(new /spell/aoe_turf/corereturn, "grey_spell_ready",/obj/abstract/screen/movable/spell_master/malf)
+ src.occupant.add_spell(new /spell/aoe_turf/corereturn, "malf_spell_ready",/obj/abstract/screen/movable/spell_master/malf)
src.occupant.cancel_camera()
if (seclevel2num(get_security_level()) == SEC_LEVEL_DELTA)
for(var/obj/item/weapon/pinpointer/point in pinpointer_list)
@@ -1335,6 +1340,10 @@ obj/machinery/power/apc/proc/autoset(var/val, var/on)
var/area/this_area = get_area(src)
if(this_area.areaapc == src)
this_area.remove_apc(src)
+ if(hacking_ai) //APC got destroyed mid-hack
+ hacking_ai.malfhack = null
+ hacking_ai.malfhacking = 0
+ to_chat(hacking_ai, "The APC you were currently hacking was destroyed.")
if(malfai && operating)
var/datum/faction/malf/M = find_active_faction_by_type(/datum/faction/malf)
if (M && STATION_Z == z)
diff --git a/icons/mob/screen_alarms.dmi b/icons/mob/screen_alarms.dmi
index db51ff39d82..509fdedd747 100644
Binary files a/icons/mob/screen_alarms.dmi and b/icons/mob/screen_alarms.dmi differ
diff --git a/icons/mob/screen_spells.dmi b/icons/mob/screen_spells.dmi
index da7a24db1b1..556335d9d77 100644
Binary files a/icons/mob/screen_spells.dmi and b/icons/mob/screen_spells.dmi differ