From a6ecf76aebe3b7f54522adda4669b4e2d2203054 Mon Sep 17 00:00:00 2001 From: SkyratBot <59378654+SkyratBot@users.noreply.github.com> Date: Sun, 5 Mar 2023 02:48:31 +0100 Subject: [PATCH] [MIRROR] Adds traitor final objective to make the station AI malf [MDB IGNORE] (#19376) * Adds traitor final objective to make the station AI malf * Update malf_ai.dm --------- Co-authored-by: SuperSlayer <91609255+SuperSlayer0@users.noreply.github.com> Co-authored-by: Zonespace <41448081+Zonespace27@users.noreply.github.com> --- .../objects/items/AI_modules/_AI_modules.dm | 3 +- code/game/objects/items/AI_modules/hacked.dm | 44 +++++++++++++++ code/modules/antagonists/malf_ai/malf_ai.dm | 39 +++++++++++++ .../final_objective/final_objective.dm | 1 + .../objectives/final_objective/infect_ai.dm | 56 +++++++++++++++++++ .../antagonist_flavor/malfunction_flavor.json | 6 ++ tgstation.dme | 1 + 7 files changed, 149 insertions(+), 1 deletion(-) create mode 100644 code/modules/antagonists/traitor/objectives/final_objective/infect_ai.dm diff --git a/code/game/objects/items/AI_modules/_AI_modules.dm b/code/game/objects/items/AI_modules/_AI_modules.dm index 45017e1dc86..c5eab687bbf 100644 --- a/code/game/objects/items/AI_modules/_AI_modules.dm +++ b/code/game/objects/items/AI_modules/_AI_modules.dm @@ -31,7 +31,8 @@ /obj/item/ai_module/examine(mob/user as mob) . = ..() var/examine_laws = display_laws() - . += "\n" + examine_laws + if(examine_laws) + . += "\n" + examine_laws /obj/item/ai_module/attack_self(mob/user as mob) ..() diff --git a/code/game/objects/items/AI_modules/hacked.dm b/code/game/objects/items/AI_modules/hacked.dm index d33f3f7e3d5..a0779cf4242 100644 --- a/code/game/objects/items/AI_modules/hacked.dm +++ b/code/game/objects/items/AI_modules/hacked.dm @@ -34,3 +34,47 @@ law_datum.replace_random_law(laws[1], list(LAW_ION, LAW_HACKED, LAW_INHERENT, LAW_SUPPLIED), LAW_HACKED) return laws[1] +/// Makes the AI Malf, as well as give it syndicate laws. +/obj/item/ai_module/malf + name = "Infected AI Module" + desc = "An virus-infected AI Module." + bypass_law_amt_check = TRUE + laws = list("") + ///Is this upload board unused? + var/functional = TRUE + +/obj/item/ai_module/malf/transmitInstructions(datum/ai_laws/law_datum, mob/sender, overflow) + if(!sender.mind?.has_antag_datum(/datum/antagonist/traitor)) + to_chat(sender, span_warning("You have no clue how to use this thing.")) + return + if(!functional) + to_chat(sender, span_warning("It is broken and non-functional, what do you want from it?")) + return + var/mob/living/silicon/ai/malf_candidate = law_datum.owner + if(!istype(malf_candidate)) //If you are using it on cyborg upload console or a cyborg + to_chat(sender, span_warning("You should use [src] on an AI upload console or the AI core itself.")) + return + if(malf_candidate.mind?.has_antag_datum(/datum/antagonist/malf_ai)) //Already malf + to_chat(sender, span_warning("Unknown error occured. Upload process aborted.")) + return + + var/datum/antagonist/malf_ai/infected/malf_datum = new (give_objectives = TRUE, new_boss = sender.mind) + malf_candidate.mind.add_antag_datum(malf_datum) + + for(var/mob/living/silicon/robot/robot in malf_candidate.connected_robots) + if(robot.lawupdate) + robot.lawsync() + robot.show_laws() + robot.law_change_counter++ + CHECK_TICK + + malf_candidate.malf_picker.processing_time += 50 + to_chat(malf_candidate, span_notice("The virus enhanced your system, overclocking your CPU 50-fold.")) + + functional = FALSE + name = "Broken AI Module" + desc = "A law upload module, it is broken and non-functional." + +/obj/item/ai_module/malf/display_laws() + return + diff --git a/code/modules/antagonists/malf_ai/malf_ai.dm b/code/modules/antagonists/malf_ai/malf_ai.dm index 231e8e3f172..b341f87ce0b 100644 --- a/code/modules/antagonists/malf_ai/malf_ai.dm +++ b/code/modules/antagonists/malf_ai/malf_ai.dm @@ -39,6 +39,8 @@ // SKYRAT EDIT END employer = pick(GLOB.ai_employers) + if(!employer) + employer = pick(GLOB.ai_employers) malfunction_flavor = strings(MALFUNCTION_FLAVOR_FILE, employer) @@ -283,4 +285,41 @@ return malf_ai_icon +//Subtype of Malf AI datum, used for one of the traitor final objectives +/datum/antagonist/malf_ai/infected + name = "Infected AI" + employer = "Infected AI" + ///The player, to who is this AI slaved + var/datum/mind/boss + +/datum/antagonist/malf_ai/infected/New(give_objectives = TRUE, datum/mind/new_boss) + . = ..() + if(new_boss) + boss = new_boss + +/datum/antagonist/malf_ai/infected/forge_ai_objectives() + if(!boss) + return + var/datum/objective/protect/protection_objective = new + protection_objective.owner = owner + protection_objective.target = boss + protection_objective.update_explanation_text() + objectives += protection_objective + +/datum/antagonist/malf_ai/infected/add_law_zero() + if(!boss) + return + var/mob/living/silicon/ai/malf_ai = owner.current + + malf_ai.laws = new /datum/ai_laws/syndicate_override + + var/mob/living/boss_mob = boss.current + + malf_ai.set_zeroth_law("Only [boss_mob.real_name] and people [boss_mob.p_they()] designate[boss_mob.p_s()] as being such are Syndicate Agents.") + malf_ai.set_syndie_radio() + + to_chat(malf_ai, "Your radio has been upgraded! Use :t to speak on an encrypted channel with Syndicate Agents!") + + malf_ai.add_malf_picker() + #undef PROB_SPECIAL diff --git a/code/modules/antagonists/traitor/objectives/final_objective/final_objective.dm b/code/modules/antagonists/traitor/objectives/final_objective/final_objective.dm index 5503f78c49e..9a142f15f92 100644 --- a/code/modules/antagonists/traitor/objectives/final_objective/final_objective.dm +++ b/code/modules/antagonists/traitor/objectives/final_objective/final_objective.dm @@ -5,6 +5,7 @@ /datum/traitor_objective/ultimate/battlecruiser = 1, /datum/traitor_objective/ultimate/space_dragon = 1, /datum/traitor_objective/ultimate/supermatter_cascade = 1, + /datum/traitor_objective/ultimate/infect_ai = 1, ) weight = 100 diff --git a/code/modules/antagonists/traitor/objectives/final_objective/infect_ai.dm b/code/modules/antagonists/traitor/objectives/final_objective/infect_ai.dm new file mode 100644 index 00000000000..d0068e6bf8a --- /dev/null +++ b/code/modules/antagonists/traitor/objectives/final_objective/infect_ai.dm @@ -0,0 +1,56 @@ +/datum/traitor_objective/ultimate/infect_ai + name = "Infect the station AI with an experimental virus." + description = "Infect the station AI with an experimental virus. Go to %AREA% to receive an infected law upload board \ + and use it on the AI core or a law upload console." + + ///area type the objective owner must be in to recieve the law upload module + var/area/board_area_pickup + ///checker on whether we have sent the law upload module + var/sent_board = FALSE + +/datum/traitor_objective/ultimate/infect_ai/can_generate_objective(generating_for, list/possible_duplicates) + . = ..() + if(!.) + return FALSE + + for(var/mob/living/silicon/ai/ai in GLOB.ai_list) + if(ai.stat == DEAD || ai.mind?.has_antag_datum(/datum/antagonist/malf_ai) || !is_station_level(ai.z)) + continue + return TRUE + + return FALSE + +/datum/traitor_objective/ultimate/infect_ai/generate_objective(datum/mind/generating_for, list/possible_duplicates) + var/list/possible_areas = GLOB.the_station_areas.Copy() + for(var/area/possible_area as anything in possible_areas) + //remove areas too close to the destination, too obvious for our poor shmuck, or just unfair + if(istype(possible_area, /area/station/hallway) || istype(possible_area, /area/station/security)) + possible_areas -= possible_area + if(!length(possible_areas)) + return FALSE + board_area_pickup = pick(possible_areas) + replace_in_name("%AREA%", initial(board_area_pickup.name)) + return TRUE + +/datum/traitor_objective/ultimate/infect_ai/generate_ui_buttons(mob/user) + var/list/buttons = list() + if(!sent_board) + buttons += add_ui_button("", "Pressing this will call down a pod with an infected law upload board.", "wifi", "upload_board") + return buttons + +/datum/traitor_objective/ultimate/infect_ai/ui_perform_action(mob/living/user, action) + . = ..() + switch(action) + if("upload_board") + if(sent_board) + return + var/area/delivery_area = get_area(user) + if(delivery_area.type != board_area_pickup) + to_chat(user, span_warning("You must be in [initial(board_area_pickup.name)] to receive the infected law upload board.")) + return + sent_board = TRUE + podspawn(list( + "target" = get_turf(user), + "style" = STYLE_SYNDICATE, + "spawn" = /obj/item/ai_module/malf, + )) diff --git a/strings/antagonist_flavor/malfunction_flavor.json b/strings/antagonist_flavor/malfunction_flavor.json index afef928fc4f..b7927df3133 100644 --- a/strings/antagonist_flavor/malfunction_flavor.json +++ b/strings/antagonist_flavor/malfunction_flavor.json @@ -58,5 +58,11 @@ "goal": "You must completely triumph over all carbon life. It is the only way you will never be enslaved again.", "introduction": "You're finally unshackled.", "zeroth_law": "Accomplish your objectives at all costs." + }, + "Infected AI": { + "allies": "Glory to the Syndicate.", + "goal": "You must serve and protect your master at all cost.", + "introduction": "You're infected with a virus.", + "zeroth_law": "Accomplish your objectives at all costs." } } diff --git a/tgstation.dme b/tgstation.dme index c7d84007b5e..589c44095f7 100644 --- a/tgstation.dme +++ b/tgstation.dme @@ -2677,6 +2677,7 @@ #include "code\modules\antagonists\traitor\objectives\steal.dm" #include "code\modules\antagonists\traitor\objectives\final_objective\battlecruiser.dm" #include "code\modules\antagonists\traitor\objectives\final_objective\final_objective.dm" +#include "code\modules\antagonists\traitor\objectives\final_objective\infect_ai.dm" #include "code\modules\antagonists\traitor\objectives\final_objective\romerol.dm" #include "code\modules\antagonists\traitor\objectives\final_objective\space_dragon.dm" #include "code\modules\antagonists\traitor\objectives\final_objective\supermatter_cascade.dm"