From 6e01f2901fe5b74e2e1eeb2b6cf1db2015fe501f Mon Sep 17 00:00:00 2001 From: bloons3 Date: Wed, 30 Jun 2021 16:16:23 -0500 Subject: [PATCH] Enhances AI law and borg logging (#59684) Persistent logging for sometimes disputed actions The "impacted cyborgs" is useful for reconstructing which borgs were synced to an AI at what time, which sometimes may not be clear from logs --- code/datums/wires/robot.dm | 14 ++++++++++- code/game/machinery/camera/camera.dm | 2 +- code/game/machinery/computer/robot.dm | 5 +++- code/game/machinery/transformer.dm | 4 +-- code/game/objects/items/AI_modules.dm | 25 +++++++++++++++---- .../objects/items/robot/robot_upgrades.dm | 2 +- 6 files changed, 41 insertions(+), 11 deletions(-) diff --git a/code/datums/wires/robot.dm b/code/datums/wires/robot.dm index 20935e04731..d991a7a162f 100644 --- a/code/datums/wires/robot.dm +++ b/code/datums/wires/robot.dm @@ -42,6 +42,7 @@ R.notify_ai(DISCONNECT) if(new_ai && (new_ai != R.connected_ai)) R.set_connected_ai(new_ai) + log_combat(usr, R, "synced cyborg [R.connected_ai ? "from [ADMIN_LOOKUP(R.connected_ai)]": ""] to [ADMIN_LOOKUP(new_ai)]") if(R.shell) R.undeploy() //If this borg is an AI shell, disconnect the controlling AI and assign ti to a new AI R.notify_ai(AI_SHELL) @@ -49,15 +50,20 @@ R.notify_ai(TRUE) if(WIRE_CAMERA) // Pulse to disable the camera. if(!QDELETED(R.builtInCamera) && !R.scrambledcodes) - R.builtInCamera.toggle_cam(usr, 0) + R.builtInCamera.toggle_cam(usr, FALSE) R.visible_message(span_notice("[R]'s camera lens focuses loudly."), span_notice("Your camera lens focuses loudly.")) + log_combat(usr, R, "toggled cyborg camera to [R.builtInCamera.status ? "on" : "off"] via pulse") if(WIRE_LAWSYNC) // Forces a law update if possible. if(R.lawupdate) R.visible_message(span_notice("[R] gently chimes."), span_notice("LawSync protocol engaged.")) + log_combat(usr, R, "forcibly synced cyborg laws via pulse") + // TODO, log the laws they gained here R.lawsync() R.show_laws() if(WIRE_LOCKDOWN) R.SetLockdown(!R.lockcharge) // Toggle + log_combat(usr, R, "[!R.lockcharge ? "locked down" : "released"] via pulse") + if(WIRE_RESET_MODEL) if(R.has_model()) R.visible_message(span_notice("[R]'s model servos twitch."), span_notice("Your model display flickers.")) @@ -68,6 +74,7 @@ if(WIRE_AI) // Cut the AI wire to reset AI control. if(!mend) R.notify_ai(DISCONNECT) + log_combat(usr, R, "cut AI wire on cyborg[R.connected_ai ? " and disconnected from [ADMIN_LOOKUP(R.connected_ai)]": ""]") if(R.shell) R.undeploy() R.set_connected_ai(null) @@ -76,8 +83,10 @@ if(mend) if(!R.emagged) R.lawupdate = TRUE + log_combat(usr, R, "enabled lawsync via wire") else if(!R.deployed) //AI shells must always have the same laws as the AI R.lawupdate = FALSE + log_combat(usr, R, "disabled lawsync via wire") R.logevent("Lawsync Module fault [mend?"cleared":"detected"]") if (WIRE_CAMERA) // Disable the camera. if(!QDELETED(R.builtInCamera) && !R.scrambledcodes) @@ -85,12 +94,15 @@ R.builtInCamera.toggle_cam(usr, 0) R.visible_message(span_notice("[R]'s camera lens focuses loudly."), span_notice("Your camera lens focuses loudly.")) R.logevent("Camera Module fault [mend?"cleared":"detected"]") + log_combat(usr, R, "[mend ? "enabled" : "disabled"] cyborg camera via wire") if(WIRE_LOCKDOWN) // Simple lockdown. R.SetLockdown(!mend) R.logevent("Motor Controller fault [mend?"cleared":"detected"]") + log_combat(usr, R, "[!R.lockcharge ? "locked down" : "released"] via wire") if(WIRE_RESET_MODEL) if(R.has_model() && !mend) R.ResetModel() + log_combat(usr, R, "reset the cyborg module via wire") /datum/wires/robot/can_reveal_wires(mob/user) if(HAS_TRAIT(user, TRAIT_KNOW_CYBORG_WIRES)) diff --git a/code/game/machinery/camera/camera.dm b/code/game/machinery/camera/camera.dm index cfbad4b2c3d..afa02344f91 100644 --- a/code/game/machinery/camera/camera.dm +++ b/code/game/machinery/camera/camera.dm @@ -390,7 +390,7 @@ icon_state = "[xray_module][default_camera_icon][in_use_lights ? "_in_use" : ""]" return ..() -/obj/machinery/camera/proc/toggle_cam(mob/user, displaymessage = 1) +/obj/machinery/camera/proc/toggle_cam(mob/user, displaymessage = TRUE) status = !status if(can_use()) GLOB.cameranet.addCamera(src) diff --git a/code/game/machinery/computer/robot.dm b/code/game/machinery/computer/robot.dm index 6497aa64797..3c90c9d399b 100644 --- a/code/game/machinery/computer/robot.dm +++ b/code/game/machinery/computer/robot.dm @@ -83,7 +83,9 @@ if(can_control(usr, R) && !..()) var/turf/T = get_turf(R) message_admins(span_notice("[ADMIN_LOOKUPFLW(usr)] detonated [key_name_admin(R, R.client)] at [ADMIN_VERBOSEJMP(T)]!")) - log_game("[span_notice("[key_name(usr)] detonated [key_name(R)]!")]") + log_game("[key_name(usr)] detonated [key_name(R)]!") + log_combat(usr, R, "detonated cyborg") + if(R.connected_ai) to_chat(R.connected_ai, "

[span_alert("ALERT - Cyborg detonation detected: [R.name]")]
") R.self_destruct() @@ -95,6 +97,7 @@ if(can_control(usr, R) && !..()) message_admins(span_notice("[ADMIN_LOOKUPFLW(usr)] [!R.lockcharge ? "locked down" : "released"] [ADMIN_LOOKUPFLW(R)]!")) log_game("[key_name(usr)] [!R.lockcharge ? "locked down" : "released"] [key_name(R)]!") + log_combat(usr, R, "[!R.lockcharge ? "locked down" : "released"] cyborg") R.SetLockdown(!R.lockcharge) to_chat(R, !R.lockcharge ? span_notice("Your lockdown has been lifted!") : span_alert("You have been locked down!")) if(R.connected_ai) diff --git a/code/game/machinery/transformer.dm b/code/game/machinery/transformer.dm index 8d449ef1c98..05e6844f6a6 100644 --- a/code/game/machinery/transformer.dm +++ b/code/game/machinery/transformer.dm @@ -100,12 +100,12 @@ if(masterAI) R.set_connected_ai(masterAI) R.lawsync() - R.lawupdate = 1 + R.lawupdate = TRUE addtimer(CALLBACK(src, .proc/unlock_new_robot, R), 50) /obj/machinery/transformer/proc/unlock_new_robot(mob/living/silicon/robot/R) playsound(src.loc, 'sound/machines/ping.ogg', 50, FALSE) sleep(30) if(R) - R.SetLockdown(0) + R.SetLockdown(FALSE) R.notify_ai(NEW_BORG) diff --git a/code/game/objects/items/AI_modules.dm b/code/game/objects/items/AI_modules.dm index e1dcf921556..603f4653068 100644 --- a/code/game/objects/items/AI_modules.dm +++ b/code/game/objects/items/AI_modules.dm @@ -56,6 +56,7 @@ AI MODULES if(tot_laws > CONFIG_GET(number/silicon_max_law_amount) && !bypass_law_amt_check)//allows certain boards to avoid this check, eg: reset to_chat(user, span_alert("Not enough memory allocated to [law_datum.owner ? law_datum.owner : "the AI core"]'s law processor to handle this amount of laws.")) message_admins("[ADMIN_LOOKUPFLW(user)] tried to upload laws to [law_datum.owner ? ADMIN_LOOKUPFLW(law_datum.owner) : "an AI core"] that would exceed the law cap.") + log_game("[ADMIN_LOOKUP(user)] tried to upload laws to [law_datum.owner ? ADMIN_LOOKUP(law_datum.owner) : "an AI core"] that would exceed the law cap.") overflow = TRUE var/law2log = transmitInstructions(law_datum, user, overflow) //Freeforms return something extra we need to log @@ -68,9 +69,23 @@ AI MODULES var/time = time2text(world.realtime,"hh:mm:ss") var/ainame = law_datum.owner ? law_datum.owner.name : "empty AI core" var/aikey = law_datum.owner ? law_datum.owner.ckey : "null" - GLOB.lawchanges.Add("[time] : [user.name]([user.key]) used [src.name] on [ainame]([aikey]).[law2log ? " The law specified [law2log]" : ""]") - log_law("[user.key]/[user.name] used [src.name] on [aikey]/([ainame]) from [AREACOORD(user)].[law2log ? " The law specified [law2log]" : ""]") - message_admins("[ADMIN_LOOKUPFLW(user)] used [src.name] on [ADMIN_LOOKUPFLW(law_datum.owner)] from [AREACOORD(user)].[law2log ? " The law specified [law2log]" : ""]") + + //affected cyborgs are cyborgs linked to the AI with lawsync enabled + var/affected_cyborgs = list() + var/list/borg_txt = list() + var/list/borg_flw = list() + if(isAI(law_datum.owner)) + var/mob/living/silicon/ai/owner = law_datum.owner + for(var/mob/living/silicon/robot/owned_borg as anything in owner.connected_robots) + if(owned_borg.connected_ai && owned_borg.lawupdate) + affected_cyborgs += owned_borg + borg_flw += "[ADMIN_LOOKUPFLW(owned_borg)], " + borg_txt += "[ADMIN_LOOKUP(owned_borg)], " + + borg_txt = borg_txt.Join() + GLOB.lawchanges.Add("[time] : [user.name]([user.key]) used [src.name] on [ainame]([aikey]).[law2log ? " The law specified [law2log]" : ""], [length(affected_cyborgs) ? ", impacting synced borgs [borg_txt]" : ""]") + log_law("[user.key]/[user.name] used [src.name] on [aikey]/([ainame]) from [AREACOORD(user)].[law2log ? " The law specified [law2log]" : ""] , [length(affected_cyborgs) ? ", impacting synced borgs [borg_txt]" : ""]") + message_admins("[ADMIN_LOOKUPFLW(user)] used [src.name] on [ADMIN_LOOKUPFLW(law_datum.owner)] from [AREACOORD(user)].[law2log ? " The law specified [law2log]" : ""] , [length(affected_cyborgs) ? ", impacting synced borgs [borg_flw.Join()]" : ""]") if(law_datum.owner) deadchat_broadcast(" changed [span_name("[ainame]")]'s laws at [get_area_name(user, TRUE)].", span_name("[user]"), follow_target=user, message_type=DEADCHAT_LAWCHANGE) @@ -117,7 +132,7 @@ AI MODULES to_chat(law_datum.owner, "It would be in your best interest to play along with [sender.real_name] that:") for(var/failedlaw in laws) to_chat(law_datum.owner, "[failedlaw]") - return 1 + return TRUE for(var/templaw in laws) if(law_datum.owner) @@ -190,7 +205,7 @@ AI MODULES /obj/item/ai_module/zeroth/onehuman/install(datum/ai_laws/law_datum, mob/user) if(!targetName) to_chat(user, span_alert("No name detected on module, please enter one.")) - return 0 + return FALSE ..() /obj/item/ai_module/zeroth/onehuman/transmitInstructions(datum/ai_laws/law_datum, mob/sender, overflow) diff --git a/code/game/objects/items/robot/robot_upgrades.dm b/code/game/objects/items/robot/robot_upgrades.dm index 210651954f6..d422fb166a5 100644 --- a/code/game/objects/items/robot/robot_upgrades.dm +++ b/code/game/objects/items/robot/robot_upgrades.dm @@ -588,7 +588,7 @@ playsound(R, pick('sound/items/drill_use.ogg', 'sound/items/jaws_cut.ogg', 'sound/items/jaws_pry.ogg', 'sound/items/welder.ogg', 'sound/items/ratchet.ogg'), 80, TRUE, -1) sleep(12) if(!prev_lockcharge) - R.SetLockdown(0) + R.SetLockdown(FALSE) R.set_anchored(FALSE) R.notransform = FALSE R.resize = 2