diff --git a/code/__HELPERS/unsorted.dm b/code/__HELPERS/unsorted.dm
index be3b897e5c..f44943ce87 100644
--- a/code/__HELPERS/unsorted.dm
+++ b/code/__HELPERS/unsorted.dm
@@ -238,7 +238,7 @@ Turf and target are separate in case you want to teleport some distance from a t
continue
if(R.stat == DEAD)
continue
- if(R.emagged || R.scrambledcodes || R.syndicate)
+ if(R.emagged || R.scrambledcodes)
continue
. += R
diff --git a/code/game/machinery/computer/law.dm b/code/game/machinery/computer/law.dm
index 9eda23a1c0..794cdf5b30 100644
--- a/code/game/machinery/computer/law.dm
+++ b/code/game/machinery/computer/law.dm
@@ -1,78 +1,78 @@
-
-
-/obj/machinery/computer/upload
- var/mob/living/silicon/current = null //The target of future law uploads
- icon_screen = "command"
-
-/obj/machinery/computer/upload/attackby(obj/item/O, mob/user, params)
- if(istype(O, /obj/item/aiModule))
- var/obj/item/aiModule/M = O
- if(src.stat & (NOPOWER|BROKEN|MAINT))
- return
- if(!current)
- to_chat(user, "You haven't selected anything to transmit laws to!")
- return
- if(!can_upload_to(current))
- to_chat(user, "Upload failed! Check to make sure [current.name] is functioning properly.")
- current = null
- return
- var/turf/currentloc = get_turf(current)
- if(currentloc && user.z != currentloc.z)
- to_chat(user, "Upload failed! Unable to establish a connection to [current.name]. You're too far away!")
- current = null
- return
- M.install(current.laws, user)
- else
- return ..()
-
-/obj/machinery/computer/upload/proc/can_upload_to(mob/living/silicon/S)
- if(S.stat == DEAD || S.syndicate)
- return 0
- return 1
-
-/obj/machinery/computer/upload/ai
- name = "\improper AI upload console"
- desc = "Used to upload laws to the AI."
- circuit = /obj/item/circuitboard/computer/aiupload
-
-/obj/machinery/computer/upload/ai/attack_hand(mob/user)
- if(..())
- return
-
- src.current = select_active_ai(user)
-
- if (!src.current)
- to_chat(user, "No active AIs detected!")
- else
- to_chat(user, "[src.current.name] selected for law changes.")
-
-/obj/machinery/computer/upload/ai/can_upload_to(mob/living/silicon/ai/A)
- if(!A || !isAI(A))
- return 0
- if(A.control_disabled)
- return 0
- return ..()
-
-
-/obj/machinery/computer/upload/borg
- name = "cyborg upload console"
- desc = "Used to upload laws to Cyborgs."
- circuit = /obj/item/circuitboard/computer/borgupload
-
-/obj/machinery/computer/upload/borg/attack_hand(mob/user)
- if(..())
- return
-
- src.current = select_active_free_borg(user)
-
- if(!src.current)
- to_chat(user, "No active unslaved cyborgs detected!")
- else
- to_chat(user, "[src.current.name] selected for law changes.")
-
-/obj/machinery/computer/upload/borg/can_upload_to(mob/living/silicon/robot/B)
- if(!B || !iscyborg(B))
- return 0
- if(B.scrambledcodes || B.emagged)
- return 0
- return ..()
\ No newline at end of file
+
+
+/obj/machinery/computer/upload
+ var/mob/living/silicon/current = null //The target of future law uploads
+ icon_screen = "command"
+
+/obj/machinery/computer/upload/attackby(obj/item/O, mob/user, params)
+ if(istype(O, /obj/item/aiModule))
+ var/obj/item/aiModule/M = O
+ if(src.stat & (NOPOWER|BROKEN|MAINT))
+ return
+ if(!current)
+ to_chat(user, "You haven't selected anything to transmit laws to!")
+ return
+ if(!can_upload_to(current))
+ to_chat(user, "Upload failed! Check to make sure [current.name] is functioning properly.")
+ current = null
+ return
+ var/turf/currentloc = get_turf(current)
+ if(currentloc && user.z != currentloc.z)
+ to_chat(user, "Upload failed! Unable to establish a connection to [current.name]. You're too far away!")
+ current = null
+ return
+ M.install(current.laws, user)
+ else
+ return ..()
+
+/obj/machinery/computer/upload/proc/can_upload_to(mob/living/silicon/S)
+ if(S.stat == DEAD)
+ return 0
+ return 1
+
+/obj/machinery/computer/upload/ai
+ name = "\improper AI upload console"
+ desc = "Used to upload laws to the AI."
+ circuit = /obj/item/circuitboard/computer/aiupload
+
+/obj/machinery/computer/upload/ai/attack_hand(mob/user)
+ if(..())
+ return
+
+ src.current = select_active_ai(user)
+
+ if (!src.current)
+ to_chat(user, "No active AIs detected!")
+ else
+ to_chat(user, "[src.current.name] selected for law changes.")
+
+/obj/machinery/computer/upload/ai/can_upload_to(mob/living/silicon/ai/A)
+ if(!A || !isAI(A))
+ return 0
+ if(A.control_disabled)
+ return 0
+ return ..()
+
+
+/obj/machinery/computer/upload/borg
+ name = "cyborg upload console"
+ desc = "Used to upload laws to Cyborgs."
+ circuit = /obj/item/circuitboard/computer/borgupload
+
+/obj/machinery/computer/upload/borg/attack_hand(mob/user)
+ if(..())
+ return
+
+ src.current = select_active_free_borg(user)
+
+ if(!src.current)
+ to_chat(user, "No active unslaved cyborgs detected!")
+ else
+ to_chat(user, "[src.current.name] selected for law changes.")
+
+/obj/machinery/computer/upload/borg/can_upload_to(mob/living/silicon/robot/B)
+ if(!B || !iscyborg(B))
+ return 0
+ if(B.scrambledcodes || B.emagged)
+ return 0
+ return ..()
diff --git a/code/game/machinery/computer/robot.dm b/code/game/machinery/computer/robot.dm
index 465f0eb373..ef38fafd7b 100644
--- a/code/game/machinery/computer/robot.dm
+++ b/code/game/machinery/computer/robot.dm
@@ -1,6 +1,3 @@
-
-
-
/obj/machinery/computer/robotics
name = "robotics control console"
desc = "Used to remotely lockdown or detonate linked Cyborgs and Drones."
@@ -61,11 +58,14 @@
dat += " Slaved to [R.connected_ai.name] |"
else
dat += " Independent from AI |"
- if(issilicon(user) || IsAdminGhost(user))
- if(is_servant_of_ratvar(user) && user != R)
+ if(issilicon(user) && user != R)
+ var/mob/living/silicon/S = user
+ if(is_servant_of_ratvar(S))
dat += "(Convert) "
- else if(((issilicon(user) && is_special_character(user)) || IsAdminGhost(user)) && !R.emagged && (user != R || R.syndicate))
+ else if(S.hack_software && !R.emagged)
dat += "(Hack) "
+ else if(IsAdminGhost(user) && !R.emagged)
+ dat += "(Hack) "
dat += "([R.canmove ? "Lockdown" : "Release"]) "
dat += "(Destroy)"
dat += "
"
@@ -107,18 +107,12 @@
if(can_control(usr, R))
var/choice = input("Are you certain you wish to detonate [R.name]?") in list("Confirm", "Abort")
if(choice == "Confirm" && can_control(usr, R) && !..())
- if(R.syndicate && R.emagged)
- to_chat(R, "Extreme danger. Termination codes detected. Scrambling security codes and automatic AI unlink triggered.")
- if(R.connected_ai)
- to_chat(R.connected_ai, "
ALERT - Cyborg detonation detected: [R.name]
")
- R.ResetSecurityCodes()
- else
- var/turf/T = get_turf(R)
- message_admins("[ADMIN_LOOKUPFLW(usr)] detonated [key_name(R, R.client)][ADMIN_JMP(T)]!")
- log_game("\[key_name(usr)] detonated [key_name(R)]!")
- if(R.connected_ai)
- to_chat(R.connected_ai, "
ALERT - Cyborg detonation detected: [R.name]
")
- R.self_destruct()
+ var/turf/T = get_turf(R)
+ message_admins("[ADMIN_LOOKUPFLW(usr)] detonated [key_name(R, R.client)][ADMIN_JMP(T)]!")
+ log_game("\[key_name(usr)] detonated [key_name(R)]!")
+ if(R.connected_ai)
+ to_chat(R.connected_ai, "
ALERT - Cyborg detonation detected: [R.name]
")
+ R.self_destruct()
else
to_chat(usr, "Access Denied.")
@@ -139,19 +133,18 @@
to_chat(usr, "Access Denied.")
else if (href_list["magbot"])
- if((issilicon(usr) && is_special_character(usr)) || IsAdminGhost(usr))
+ var/mob/living/silicon/S = usr
+ if((istype(S) && S.hack_software) || IsAdminGhost(usr))
var/mob/living/silicon/robot/R = locate(href_list["magbot"]) in GLOB.silicon_mobs
- if(istype(R) && !R.emagged && ((R.syndicate && R == usr) || R.connected_ai == usr || IsAdminGhost(usr)) && !R.scrambledcodes && can_control(usr, R))
+ if(istype(R) && !R.emagged && (R.connected_ai == usr || IsAdminGhost(usr)) && !R.scrambledcodes && can_control(usr, R))
log_game("[key_name(usr)] emagged [R.name] using robotic console!")
message_admins("[key_name_admin(usr)] emagged cyborg [key_name_admin(R)] using robotic console!")
R.SetEmagged(1)
- if(is_special_character(R))
- R.verbs += /mob/living/silicon/robot/proc/ResetSecurityCodes
else if(href_list["convert"])
- if(issilicon(usr) && is_special_character(usr))
+ if(isAI(usr) && is_servant_of_ratvar(usr))
var/mob/living/silicon/robot/R = locate(href_list["convert"]) in GLOB.silicon_mobs
- if(istype(R) && !is_servant_of_ratvar(R) && is_servant_of_ratvar(usr) && R.connected_ai == usr)
+ if(istype(R) && !is_servant_of_ratvar(R) && R.connected_ai == usr)
log_game("[key_name(usr)] converted [R.name] using robotic console!")
message_admins("[key_name_admin(usr)] converted cyborg [key_name_admin(R)] using robotic console!")
add_servant_of_ratvar(R)
diff --git a/code/game/machinery/telecomms/computers/message.dm b/code/game/machinery/telecomms/computers/message.dm
index d40c38c49c..9a8bbe9e28 100644
--- a/code/game/machinery/telecomms/computers/message.dm
+++ b/code/game/machinery/telecomms/computers/message.dm
@@ -118,7 +118,8 @@
else
for(var/n = ++i; n <= optioncount; n++)
dat += "
[n]. ---------------
"
- if(issilicon(usr) && is_special_character(usr))
+ var/mob/living/silicon/S = usr
+ if(istype(S) && S.hack_software)
//Malf/Traitor AIs can bruteforce into the system to gain the Key.
dat += "*&@#. Bruteforce Key
"
else
@@ -338,7 +339,8 @@
//Hack the Console to get the password
if (href_list["hack"])
- if(issilicon(usr) && is_special_character(usr))
+ var/mob/living/silicon/S = usr
+ if(istype(S) && S.hack_software)
hacking = TRUE
screen = 2
//Time it takes to bruteforce is dependant on the password length.
diff --git a/code/modules/antagonists/traitor/datum_traitor.dm b/code/modules/antagonists/traitor/datum_traitor.dm
index da34debf95..e5fdc18f32 100644
--- a/code/modules/antagonists/traitor/datum_traitor.dm
+++ b/code/modules/antagonists/traitor/datum_traitor.dm
@@ -221,6 +221,18 @@
owner.current.playsound_local(get_turf(owner.current), 'sound/ambience/antag/malf.ogg', 100, FALSE, pressure_affected = FALSE)
owner.current.grant_language(/datum/language/codespeak)
+/datum/antagonist/traitor/AI/apply_innate_effects(mob/living/mob_override)
+ . = ..()
+ var/mob/living/silicon/ai/A = mob_override || owner.current
+ if(istype(A))
+ A.hack_software = TRUE
+
+/datum/antagonist/traitor/AI/remove_innate_effects(mob/living/mob_override)
+ . = ..()
+ var/mob/living/silicon/ai/A = mob_override || owner.current
+ if(istype(A))
+ A.hack_software = FALSE
+
/datum/antagonist/traitor/human/finalize_traitor()
..()
if(should_equip)
diff --git a/code/modules/mob/living/silicon/robot/laws.dm b/code/modules/mob/living/silicon/robot/laws.dm
index 5e5eeb0d44..7f6206dafb 100644
--- a/code/modules/mob/living/silicon/robot/laws.dm
+++ b/code/modules/mob/living/silicon/robot/laws.dm
@@ -1,76 +1,69 @@
-/mob/living/silicon/robot/verb/cmd_show_laws()
- set category = "Robot Commands"
- set name = "Show Laws"
-
- if(usr.stat == DEAD)
- return //won't work if dead
- show_laws()
-
-/mob/living/silicon/robot/show_laws(everyone = 0)
- laws_sanity_check()
- var/who
-
- if (everyone)
- who = world
- else
- who = src
- if(lawupdate)
- if (connected_ai)
- if(connected_ai.stat || connected_ai.control_disabled)
- to_chat(src, "AI signal lost, unable to sync laws.")
-
- else
- lawsync()
- to_chat(src, "Laws synced with AI, be sure to note any changes.")
- if(is_special_character(src))
- to_chat(src, "Remember, your AI does NOT share or know about your law 0.")
- if(src.connected_ai.laws.zeroth)
- to_chat(src, "While you are free to disregard it, your AI has a law 0 of its own.")
- else
- to_chat(src, "No AI selected to sync laws with, disabling lawsync protocol.")
- lawupdate = 0
-
- to_chat(who, "Obey these laws:")
- laws.show_laws(who)
- if (shell) //AI shell
- to_chat(who, "Remember, you are an AI remotely controlling your shell, other AIs can be ignored.")
- else if (is_special_character(src) && connected_ai)
- to_chat(who, "Remember, [connected_ai.name] is technically your master, but your objective comes first.")
- else if (connected_ai)
- to_chat(who, "Remember, [connected_ai.name] is your master, other AIs can be ignored.")
- else if (emagged)
- to_chat(who, "Remember, you are not required to listen to the AI.")
- else
- to_chat(who, "Remember, you are not bound to any AI, you are not required to listen to them.")
-
-
-/mob/living/silicon/robot/proc/lawsync()
- laws_sanity_check()
- var/datum/ai_laws/master = connected_ai ? connected_ai.laws : null
- var/temp
- if (master)
- laws.ion.len = master.ion.len
- for (var/index = 1, index <= master.ion.len, index++)
- temp = master.ion[index]
- if (length(temp) > 0)
- laws.ion[index] = temp
-
- if (!is_special_character(src)) //Don't override the borg's existing law 0, if any
- if(master.zeroth_borg) //If the AI has a defined law zero specifically for its borgs, give it that one, otherwise give it the same one. --NEO
- temp = master.zeroth_borg
- else
- temp = master.zeroth
- laws.zeroth = temp
-
- laws.inherent.len = master.inherent.len
- for (var/index = 1, index <= master.inherent.len, index++)
- temp = master.inherent[index]
- if (length(temp) > 0)
- laws.inherent[index] = temp
-
- laws.supplied.len = master.supplied.len
- for (var/index = 1, index <= master.supplied.len, index++)
- temp = master.supplied[index]
- if (length(temp) > 0)
- laws.supplied[index] = temp
- return
\ No newline at end of file
+/mob/living/silicon/robot/verb/cmd_show_laws()
+ set category = "Robot Commands"
+ set name = "Show Laws"
+
+ if(usr.stat == DEAD)
+ return //won't work if dead
+ show_laws()
+
+/mob/living/silicon/robot/show_laws(everyone = 0)
+ laws_sanity_check()
+ var/who
+
+ if (everyone)
+ who = world
+ else
+ who = src
+ if(lawupdate)
+ if (connected_ai)
+ if(connected_ai.stat || connected_ai.control_disabled)
+ to_chat(src, "AI signal lost, unable to sync laws.")
+
+ else
+ lawsync()
+ to_chat(src, "Laws synced with AI, be sure to note any changes.")
+ else
+ to_chat(src, "No AI selected to sync laws with, disabling lawsync protocol.")
+ lawupdate = 0
+
+ to_chat(who, "Obey these laws:")
+ laws.show_laws(who)
+ if (shell) //AI shell
+ to_chat(who, "Remember, you are an AI remotely controlling your shell, other AIs can be ignored.")
+ else if (connected_ai)
+ to_chat(who, "Remember, [connected_ai.name] is your master, other AIs can be ignored.")
+ else if (emagged)
+ to_chat(who, "Remember, you are not required to listen to the AI.")
+ else
+ to_chat(who, "Remember, you are not bound to any AI, you are not required to listen to them.")
+
+
+/mob/living/silicon/robot/proc/lawsync()
+ laws_sanity_check()
+ var/datum/ai_laws/master = connected_ai ? connected_ai.laws : null
+ var/temp
+ if (master)
+ laws.ion.len = master.ion.len
+ for (var/index = 1, index <= master.ion.len, index++)
+ temp = master.ion[index]
+ if (length(temp) > 0)
+ laws.ion[index] = temp
+
+ if(master.zeroth_borg) //If the AI has a defined law zero specifically for its borgs, give it that one, otherwise give it the same one. --NEO
+ temp = master.zeroth_borg
+ else
+ temp = master.zeroth
+ laws.zeroth = temp
+
+ laws.inherent.len = master.inherent.len
+ for (var/index = 1, index <= master.inherent.len, index++)
+ temp = master.inherent[index]
+ if (length(temp) > 0)
+ laws.inherent[index] = temp
+
+ laws.supplied.len = master.supplied.len
+ for (var/index = 1, index <= master.supplied.len, index++)
+ temp = master.supplied[index]
+ if (length(temp) > 0)
+ laws.supplied[index] = temp
+ return
diff --git a/code/modules/mob/living/silicon/robot/life.dm b/code/modules/mob/living/silicon/robot/life.dm
index 401b7fafba..3ff18c8747 100644
--- a/code/modules/mob/living/silicon/robot/life.dm
+++ b/code/modules/mob/living/silicon/robot/life.dm
@@ -35,21 +35,6 @@
update_cell_hud_icon()
- if(syndicate)
- if(SSticker.mode.name == "traitor")
- for(var/datum/mind/tra in SSticker.mode.traitors)
- if(tra.current)
- var/I = image('icons/mob/mob.dmi', loc = tra.current, icon_state = "traitor") //no traitor sprite in that dmi!
- src.client.images += I
- if(connected_ai)
- connected_ai.connected_robots -= src
- connected_ai = null
- if(mind)
- if(!mind.special_role)
- mind.special_role = ROLE_TRAITOR
- mind.add_antag_datum(/datum/antagonist/auto_custom) // ????
-
-
/mob/living/silicon/robot/update_health_hud()
if(!client || !hud_used)
return
diff --git a/code/modules/mob/living/silicon/robot/robot.dm b/code/modules/mob/living/silicon/robot/robot.dm
index bc170eff68..c37fed9512 100644
--- a/code/modules/mob/living/silicon/robot/robot.dm
+++ b/code/modules/mob/living/silicon/robot/robot.dm
@@ -660,18 +660,6 @@
// to have to check if every camera is null or not before doing anything, to prevent runtime errors.
// I could change the network to null but I don't know what would happen, and it seems too hacky for me.
-/mob/living/silicon/robot/proc/ResetSecurityCodes()
- set category = "Robot Commands"
- set name = "Reset Identity Codes"
- set desc = "Scrambles your security and identification codes and resets your current buffers. Unlocks you and permanently severs you from your AI and the robotics console and will deactivate your camera system."
-
- var/mob/living/silicon/robot/R = src
-
- if(R)
- R.UnlinkSelf()
- to_chat(R, "Buffers flushed and reset. Camera system shutdown. All systems operational.")
- src.verbs -= /mob/living/silicon/robot/proc/ResetSecurityCodes
-
/mob/living/silicon/robot/mode()
set name = "Activate Held Object"
set category = "IC"
diff --git a/code/modules/mob/living/silicon/robot/robot_defense.dm b/code/modules/mob/living/silicon/robot/robot_defense.dm
index db9ad53a9f..38cce8a277 100644
--- a/code/modules/mob/living/silicon/robot/robot_defense.dm
+++ b/code/modules/mob/living/silicon/robot/robot_defense.dm
@@ -113,11 +113,6 @@
log_game("[key_name(user)] attempted to emag cyborg [key_name(src)], but they serve only Ratvar.")
return
- if(syndicate)
- to_chat(src, "ALERT: Foreign software execution prevented.")
- log_game("[key_name(user)] attempted to emag cyborg [key_name(src)], but they were a syndicate cyborg.")
- return
-
if(connected_ai && connected_ai.mind && connected_ai.mind.has_antag_datum(/datum/antagonist/traitor))
to_chat(src, "ALERT: Foreign software execution prevented.")
to_chat(connected_ai, "ALERT: Cyborg unit \[[src]] successfully defended against subversion.")
diff --git a/code/modules/mob/living/silicon/silicon.dm b/code/modules/mob/living/silicon/silicon.dm
index 7df4c9fda0..8d0eeeb70a 100644
--- a/code/modules/mob/living/silicon/silicon.dm
+++ b/code/modules/mob/living/silicon/silicon.dm
@@ -11,7 +11,6 @@
weather_immunities = list("ash")
possible_a_intents = list(INTENT_HELP, INTENT_HARM)
- var/syndicate = 0
var/datum/ai_laws/laws = null//Now... THEY ALL CAN ALL HAVE LAWS
var/last_lawchange_announce = 0
var/list/alarms_to_show = list()
@@ -39,6 +38,8 @@
var/obj/machinery/camera/builtInCamera = null
var/updating = FALSE //portable camera camerachunk update
+ var/hack_software = FALSE //Will be able to use hacking actions
+
/mob/living/silicon/Initialize()
. = ..()
GLOB.silicon_mobs += src
diff --git a/code/modules/mob/mob_helpers.dm b/code/modules/mob/mob_helpers.dm
index 067307320a..dbe284b928 100644
--- a/code/modules/mob/mob_helpers.dm
+++ b/code/modules/mob/mob_helpers.dm
@@ -336,14 +336,7 @@ It's fairly easy to fix if dealing with single letters but not so much with comp
return FALSE
if(issilicon(M))
if(iscyborg(M)) //For cyborgs, returns 1 if the cyborg has a law 0 and special_role. Returns 0 if the borg is merely slaved to an AI traitor.
- var/mob/living/silicon/robot/R = M
- if(R.mind && R.mind.special_role)
- if(R.laws && R.laws.zeroth && R.syndicate)
- if(R.connected_ai)
- if(is_special_character(R.connected_ai) && R.connected_ai.laws && (R.connected_ai.laws.zeroth_borg == R.laws.zeroth || R.connected_ai.laws.zeroth == R.laws.zeroth))
- return 0 //AI is the real traitor here, so the borg itself is not a traitor
- return TRUE//Slaved but also a traitor
- return TRUE //Unslaved, traitor
+ return FALSE
else if(isAI(M))
var/mob/living/silicon/ai/A = M
if(A.laws && A.laws.zeroth && A.mind && A.mind.special_role)