From 5408b91737574a05ce85a252d2b4d0a424a5a15c Mon Sep 17 00:00:00 2001 From: Gw0sty <83688318+Gw0sty@users.noreply.github.com> Date: Sun, 4 May 2025 11:52:39 -0500 Subject: [PATCH 1/6] AI apc upgrade --- code/__DEFINES/is_helpers.dm | 2 + code/game/objects/items/robot/ai_upgrades.dm | 51 +++++++++++++++++ code/modules/antagonists/malf_ai/malf_ai.dm | 4 +- .../malf_ai/malf_ai_module_picker.dm | 6 +- .../antagonists/malf_ai/malf_ai_modules.dm | 56 +++++++++---------- code/modules/mob/living/silicon/ai/ai.dm | 6 +- .../silicon/ai/ai_actions/remote_power.dm | 42 ++++++++++++++ .../research/designs/electronics_designs.dm | 12 ++++ code/modules/research/techweb/robo_nodes.dm | 1 + .../antagonists/malf_ai/infected_ipc.dm | 2 +- tgstation.dme | 1 + 11 files changed, 146 insertions(+), 37 deletions(-) create mode 100644 code/modules/mob/living/silicon/ai/ai_actions/remote_power.dm diff --git a/code/__DEFINES/is_helpers.dm b/code/__DEFINES/is_helpers.dm index 17dcc0f16495..92e07bce0be8 100644 --- a/code/__DEFINES/is_helpers.dm +++ b/code/__DEFINES/is_helpers.dm @@ -270,6 +270,8 @@ GLOBAL_LIST_INIT(cat_typecache, typecacheof(list( #define is_reagent_container(O) (istype(O, /obj/item/reagent_containers)) +#define isapc(A) (istype(A, /obj/machinery/power/apc)) + //MONKESTATION EDIT: used to block cargo teleporters from escaping with syndicate blackbox #define issyndicateblackbox(O) (istype(O, /obj/item/syndicate_blackbox)) diff --git a/code/game/objects/items/robot/ai_upgrades.dm b/code/game/objects/items/robot/ai_upgrades.dm index 6873b838ebde..d3346ec48c45 100644 --- a/code/game/objects/items/robot/ai_upgrades.dm +++ b/code/game/objects/items/robot/ai_upgrades.dm @@ -1,5 +1,45 @@ ///AI Upgrades +/obj/item/aiupgrade + name = "ai upgrade disk" + desc = "You really shouldn't be seeing this" + icon = 'icons/obj/module.dmi' + icon_state = "datadisk3" + ///The upgrade that will be applied to the AI when installed + var/datum/ai_module/to_gift = /datum/ai_module +/obj/item/aiupgrade/pre_attack(atom/target, mob/living/user, proximity) + if(!proximity) + return ..() + if(!isAI(target)) + return ..() + var/mob/living/silicon/ai/AI = target + var/datum/action/innate/ai/action = locate(to_gift.power_type) in AI.actions + var/datum/ai_module/gifted_ability = new to_gift + if(!to_gift.upgrade) + if(!action) + var/ability = to_gift.power_type + var/datum/action/gifted_action = new ability + gifted_action.Grant(AI) + else if(gifted_ability.one_purchase) + to_chat(user, "[AI] already has \a [src] installed!") + return + else + action.uses += initial(action.uses) + action.desc = "[initial(action.desc)] It has [action.uses] use\s remaining." + action.build_all_button_icons() + else + if(!action) + gifted_ability.upgrade(AI) + if(gifted_ability.unlock_text) + to_chat(AI, gifted_ability.unlock_text) + if(gifted_ability.unlock_sound) + AI.playsound_local(AI, gifted_ability.unlock_sound, 50, 0) + update_static_data(AI) + to_chat(user, span_notice("You install [src], upgrading [AI].")) + to_chat(AI, span_userdanger("[user] has upgraded you with [src]!")) + user.log_message("has upgraded [key_name(AI)] with a [src].", LOG_GAME) + qdel(src) + return TRUE //Malf Picker /obj/item/malf_upgrade @@ -52,3 +92,14 @@ message_admins("[ADMIN_LOOKUPFLW(user)] has upgraded [ADMIN_LOOKUPFLW(AI)] with a [src].") qdel(src) return TRUE + +//Lipreading +/obj/item/aiupgrade/surveillance_upgrade + name = "surveillance software upgrade" + desc = "An illegal software package that will allow an artificial intelligence to 'hear' from its cameras via lip reading and hidden microphones." + to_gift = /datum/ai_module/upgrade/eavesdrop + +/obj/item/aiupgrade/power_transfer + name = "power transfer upgrade" + desc = "A legal upgrade that allows an artificial intelligence to directly provide power to APCs from a distance" + to_gift = /datum/ai_module/power_apc diff --git a/code/modules/antagonists/malf_ai/malf_ai.dm b/code/modules/antagonists/malf_ai/malf_ai.dm index c892143f4f1c..f94f7d7064a4 100644 --- a/code/modules/antagonists/malf_ai/malf_ai.dm +++ b/code/modules/antagonists/malf_ai/malf_ai.dm @@ -189,7 +189,7 @@ "name" = category, "items" = (category == malf_ai.malf_picker.selected_cat ? list() : null)) for(var/module in malf_ai.malf_picker.possible_modules[category]) - var/datum/ai_module/mod = malf_ai.malf_picker.possible_modules[category][module] + var/datum/ai_module/malf/mod = malf_ai.malf_picker.possible_modules[category][module] // monkestation start: add icons var/list/item_data = list( "name" = mod.name, @@ -221,7 +221,7 @@ for(var/category in malf_ai.malf_picker.possible_modules) buyable_items += malf_ai.malf_picker.possible_modules[category] for(var/key in buyable_items) - var/datum/ai_module/valid_mod = buyable_items[key] + var/datum/ai_module/malf/valid_mod = buyable_items[key] if(valid_mod.name == item_name) malf_ai.malf_picker.purchase_module(malf_ai, valid_mod) return TRUE diff --git a/code/modules/antagonists/malf_ai/malf_ai_module_picker.dm b/code/modules/antagonists/malf_ai/malf_ai_module_picker.dm index 0ac27c14c97b..af7edaf4e5a1 100644 --- a/code/modules/antagonists/malf_ai/malf_ai_module_picker.dm +++ b/code/modules/antagonists/malf_ai/malf_ai_module_picker.dm @@ -16,7 +16,7 @@ var/list/filtered_modules = list() for(var/path in GLOB.malf_modules) - var/datum/ai_module/AM = new path + var/datum/ai_module/malf/AM = new path if((AM.power_type == /datum/action/innate/ai) && !AM.upgrade) continue if(!filtered_modules[AM.category]) @@ -52,7 +52,7 @@ "name" = category, "items" = (category == selected_cat ? list() : null)) for(var/module in possible_modules[category]) - var/datum/ai_module/AM = possible_modules[category][module] + var/datum/ai_module/malf/AM = possible_modules[category][module] cat["items"] += list(list( "name" = AM.name, "cost" = AM.cost, @@ -75,7 +75,7 @@ for(var/category in possible_modules) buyable_items += possible_modules[category] for(var/key in buyable_items) - var/datum/ai_module/AM = buyable_items[key] + var/datum/ai_module/malf/AM = buyable_items[key] if(AM.name == item_name) purchase_module(usr, AM) return TRUE diff --git a/code/modules/antagonists/malf_ai/malf_ai_modules.dm b/code/modules/antagonists/malf_ai/malf_ai_modules.dm index 67d14c6dca14..aa3bc298bb07 100644 --- a/code/modules/antagonists/malf_ai/malf_ai_modules.dm +++ b/code/modules/antagonists/malf_ai/malf_ai_modules.dm @@ -49,7 +49,7 @@ GLOBAL_LIST_INIT(blacklisted_malf_machines, typecacheof(list( /obj/machinery/portable_atmospherics/canister, ))) -GLOBAL_LIST_INIT(malf_modules, subtypesof(/datum/ai_module)) +GLOBAL_LIST_INIT(malf_modules, subtypesof(/datum/ai_module/malf)) /// The malf AI action subtype. All malf actions are subtypes of this. /datum/action/innate/ai @@ -138,15 +138,15 @@ GLOBAL_LIST_INIT(malf_modules, subtypesof(/datum/ai_module)) category = "Destructive Modules" /// Modules with stealthy and utility uses -/datum/ai_module/utility +/datum/ai_module/malf/utility category = "Utility Modules" /// Modules that are improving AI abilities and assets -/datum/ai_module/upgrade +/datum/ai_module/malf/upgrade category = "Upgrade Modules" /// Doomsday Device: Starts the self-destruct timer. It can only be stopped by killing the AI completely. -/datum/ai_module/destructive/nuke_station +/datum/ai_module/malf/destructive/nuke_station name = "Doomsday Device" description = "Activate a weapon that will disintegrate all organic life on the station after a 450 second delay. \ Can only be used while on the station, will fail if your core is moved off station or destroyed. \ @@ -369,7 +369,7 @@ GLOBAL_LIST_INIT(malf_modules, subtypesof(/datum/ai_module)) return TRUE /// Hostile Station Lockdown: Locks, bolts, and electrifies every airlock on the station. After 90 seconds, the doors reset. -/datum/ai_module/destructive/lockdown +/datum/ai_module/malf/destructive/lockdown name = "Hostile Station Lockdown" description = "Overload the airlock, blast door and fire control networks, locking them down. \ Caution! This command also electrifies all airlocks. The networks will automatically reset after 90 seconds, briefly \ @@ -421,7 +421,7 @@ GLOBAL_LIST_INIT(malf_modules, subtypesof(/datum/ai_module)) CHECK_TICK /// Override Machine: Allows the AI to override a machine, animating it into an angry, living version of itself. -/datum/ai_module/destructive/override_machine +/datum/ai_module/malf/destructive/override_machine name = "Machine Override" description = "Overrides a machine's programming, causing it to rise up and attack everyone except other machines. Four uses per purchase." cost = 30 @@ -473,7 +473,7 @@ GLOBAL_LIST_INIT(malf_modules, subtypesof(/datum/ai_module)) new /mob/living/basic/mimic/copy/machine(get_turf(to_animate), to_animate, user, TRUE) /// Destroy RCDs: Detonates all non-cyborg RCDs on the station. -/datum/ai_module/destructive/destroy_rcd +/datum/ai_module/malf/destructive/destroy_rcd name = "Destroy RCDs" description = "Send a specialised pulse to detonate all hand-held and exosuit Rapid Construction Devices on the station." cost = 25 @@ -498,7 +498,7 @@ GLOBAL_LIST_INIT(malf_modules, subtypesof(/datum/ai_module)) owner.playsound_local(owner, 'sound/machines/twobeep.ogg', 50, 0) /// Overload Machine: Allows the AI to overload a machine, detonating it after a delay. Two uses per purchase. -/datum/ai_module/destructive/overload_machine +/datum/ai_module/malf/destructive/overload_machine name = "Machine Overload" description = "Overheats an electrical machine, causing a small explosion and destroying it. Two uses per purchase." cost = 20 @@ -554,7 +554,7 @@ GLOBAL_LIST_INIT(malf_modules, subtypesof(/datum/ai_module)) return TRUE /// Blackout: Overloads a random number of lights across the station. Three uses. -/datum/ai_module/destructive/blackout +/datum/ai_module/malf/destructive/blackout name = "Blackout" description = "Attempts to overload the lighting circuits on the station, destroying some bulbs. Three uses per purchase." cost = 15 @@ -588,7 +588,7 @@ GLOBAL_LIST_INIT(malf_modules, subtypesof(/datum/ai_module)) build_all_button_icons() /// HIGH IMPACT HONKING -/datum/ai_module/destructive/megahonk +/datum/ai_module/malf/destructive/megahonk name = "Percussive Intercomm Interference" description = "Emit a debilitatingly percussive auditory blast through the station intercoms. Does not overpower hearing protection. Two uses per purchase." cost = 20 @@ -627,7 +627,7 @@ GLOBAL_LIST_INIT(malf_modules, subtypesof(/datum/ai_module)) to_chat(victim, span_clown("HOOOOONK!")) /// Robotic Factory: Places a large machine that converts humans that go through it into cyborgs. Unlocking this ability removes shunting. -/datum/ai_module/utility/place_cyborg_transformer +/datum/ai_module/malf/utility/place_cyborg_transformer name = "Robotic Factory (Removes Shunting)" description = "Build a machine anywhere, using expensive nanomachines, that can convert a living human into a loyal either cyborg or IPC slave when placed inside." // monkestation edit PR #5133 cost = 100 @@ -702,7 +702,7 @@ GLOBAL_LIST_INIT(malf_modules, subtypesof(/datum/ai_module)) return success /// Air Alarm Safety Override: Unlocks the ability to enable flooding on all air alarms. -/datum/ai_module/utility/break_air_alarms +/datum/ai_module/malf/utility/break_air_alarms name = "Air Alarm Safety Override" description = "Gives you the ability to disable safeties on all air alarms. This will allow you to use the environmental mode Flood, \ which disables scrubbers as well as pressure checks on vents. Anyone can check the air alarm's interface and may be tipped off by their nonfunctionality." @@ -727,7 +727,7 @@ GLOBAL_LIST_INIT(malf_modules, subtypesof(/datum/ai_module)) owner.playsound_local(owner, 'sound/machines/terminal_off.ogg', 50, 0) /// Thermal Sensor Override: Unlocks the ability to disable all fire alarms from doing their job. -/datum/ai_module/utility/break_fire_alarms +/datum/ai_module/malf/utility/break_fire_alarms name = "Thermal Sensor Override" description = "Gives you the ability to override the thermal sensors on all fire alarms. \ This will remove their ability to scan for fire and thus their ability to alert." @@ -758,7 +758,7 @@ GLOBAL_LIST_INIT(malf_modules, subtypesof(/datum/ai_module)) owner.playsound_local(owner, 'sound/machines/terminal_off.ogg', 50, 0) /// Disable Emergency Lights -/datum/ai_module/utility/emergency_lights +/datum/ai_module/malf/utility/emergency_lights name = "Disable Emergency Lights" description = "Cuts emergency lights across the entire station. If power is lost to light fixtures, \ they will not attempt to fall back on emergency power reserves." @@ -784,7 +784,7 @@ GLOBAL_LIST_INIT(malf_modules, subtypesof(/datum/ai_module)) owner.playsound_local(owner, 'sound/effects/light_flicker.ogg', 50, FALSE) /// Reactivate Camera Network: Reactivates up to 30 cameras across the station. -/datum/ai_module/utility/reactivate_cameras +/datum/ai_module/malf/utility/reactivate_cameras name = "Reactivate Camera Network" description = "Runs a network-wide diagnostic on the camera network, resetting focus and re-routing power to failed cameras. \ Can be used to repair up to 30 cameras." @@ -825,7 +825,7 @@ GLOBAL_LIST_INIT(malf_modules, subtypesof(/datum/ai_module)) build_all_button_icons() /// Upgrade Camera Network: EMP-proofs all cameras, in addition to giving them X-ray vision. -/datum/ai_module/upgrade/upgrade_cameras +/datum/ai_module/malf/upgrade/upgrade_cameras name = "Upgrade Camera Network" description = "Install broad-spectrum scanning and electrical redundancy firmware to the camera network, enabling EMP-proofing and light-amplified X-ray vision. Upgrade is done immediately upon purchase." //I <3 pointless technobabble //This used to have motion sensing as well, but testing quickly revealed that giving it to the whole cameranet is PURE HORROR. @@ -834,7 +834,7 @@ GLOBAL_LIST_INIT(malf_modules, subtypesof(/datum/ai_module)) unlock_text = span_notice("OTA firmware distribution complete! Cameras upgraded: CAMSUPGRADED. Light amplification system online.") unlock_sound = 'sound/items/rped.ogg' -/datum/ai_module/upgrade/upgrade_cameras/upgrade(mob/living/silicon/ai/AI) +/datum/ai_module/malf/upgrade/upgrade_cameras/upgrade(mob/living/silicon/ai/AI) // Sets up nightvision RegisterSignal(AI, COMSIG_MOB_UPDATE_SIGHT, PROC_REF(on_update_sight)) AI.update_sight() @@ -861,13 +861,13 @@ GLOBAL_LIST_INIT(malf_modules, subtypesof(/datum/ai_module)) upgraded_cameras++ unlock_text = replacetext(unlock_text, "CAMSUPGRADED", "[upgraded_cameras]") //This works, since unlock text is called after upgrade() -/datum/ai_module/upgrade/upgrade_cameras/proc/on_update_sight(mob/source) +/datum/ai_module/malf/upgrade/upgrade_cameras/proc/on_update_sight(mob/source) SIGNAL_HANDLER // Dim blue, pretty source.lighting_color_cutoffs = blend_cutoff_colors(source.lighting_color_cutoffs, list(5, 25, 35)) /// AI Turret Upgrade: Increases the health and damage of all turrets. -/datum/ai_module/upgrade/upgrade_turrets +/datum/ai_module/malf/malf/upgrade/upgrade_turrets name = "AI Turret Upgrade" description = "Improves the power and health of all AI turrets. This effect is permanent. Upgrade is done immediately upon purchase." cost = 30 @@ -875,7 +875,7 @@ GLOBAL_LIST_INIT(malf_modules, subtypesof(/datum/ai_module)) unlock_text = span_notice("You establish a power diversion to your turrets, upgrading their health and damage.") unlock_sound = 'sound/items/rped.ogg' -/datum/ai_module/upgrade/upgrade_turrets/upgrade(mob/living/silicon/ai/AI) +/datum/ai_module/malf/upgrade/upgrade_turrets/upgrade(mob/living/silicon/ai/AI) for(var/obj/machinery/porta_turret/ai/turret in GLOB.machines) turret.AddElement(/datum/element/empprotection, EMP_PROTECT_SELF | EMP_PROTECT_WIRES | EMP_PROTECT_CONTENTS) turret.max_integrity = 200 @@ -884,7 +884,7 @@ GLOBAL_LIST_INIT(malf_modules, subtypesof(/datum/ai_module)) turret.lethal_projectile_sound = 'sound/weapons/lasercannonfire.ogg' /// Enhanced Surveillance: Enables AI to hear conversations going on near its active vision. -/datum/ai_module/upgrade/eavesdrop +/datum/ai_module/malf/upgrade/eavesdrop name = "Enhanced Surveillance" description = "Via a combination of hidden microphones and lip reading software, \ you are able to use your cameras to listen in on conversations. Upgrade is done immediately upon purchase." @@ -893,12 +893,12 @@ GLOBAL_LIST_INIT(malf_modules, subtypesof(/datum/ai_module)) unlock_text = span_notice("OTA firmware distribution complete! Cameras upgraded: Enhanced surveillance package online.") unlock_sound = 'sound/items/rped.ogg' -/datum/ai_module/upgrade/eavesdrop/upgrade(mob/living/silicon/ai/AI) +/datum/ai_module/umalf/pgrade/eavesdrop/upgrade(mob/living/silicon/ai/AI) if(AI.eyeobj) AI.eyeobj.relay_speech = TRUE /// Unlock Mech Domination: Unlocks the ability to dominate mechs. Big shocker, right? -/datum/ai_module/upgrade/mecha_domination +/datum/ai_module/malf/upgrade/mecha_domination name = "Unlock Mech Domination" description = "Allows you to hack into a mech's onboard computer, shunting all processes into it and ejecting any occupants. \ Once uploaded to the mech, it is impossible to leave. Do not allow the mech to leave the station's vicinity or allow it to be destroyed. \ @@ -909,10 +909,10 @@ GLOBAL_LIST_INIT(malf_modules, subtypesof(/datum/ai_module)) Loss of signal will result in total system lockout.") unlock_sound = 'sound/mecha/nominal.ogg' -/datum/ai_module/upgrade/mecha_domination/upgrade(mob/living/silicon/ai/AI) +/datum/ai_module/malf/upgrade/mecha_domination/upgrade(mob/living/silicon/ai/AI) AI.can_dominate_mechs = TRUE //Yep. This is all it does. Honk! -/datum/ai_module/upgrade/voice_changer +/datum/ai_module/malf/upgrade/voice_changer name = "Voice Changer" description = "Allows you to change the AI's voice. Upgrade is active immediately upon purchase." cost = 40 @@ -1033,7 +1033,7 @@ GLOBAL_LIST_INIT(malf_modules, subtypesof(/datum/ai_module)) if("name") say_name = params["name"] -/datum/ai_module/utility/emag +/datum/ai_module/malf/utility/emag name = "Targetted Safeties Override" description = "Allows you to disable the safeties of any machinery on the station, provided you can access it." cost = 20 @@ -1127,7 +1127,7 @@ GLOBAL_LIST_INIT(malf_modules, subtypesof(/datum/ai_module)) return TRUE -/datum/ai_module/utility/core_tilt +/datum/ai_module/malf/utility/core_tilt name = "Rolling Servos" description = "Allows you to slowly roll around, crushing anything in your way with your bulk." cost = 10 @@ -1226,7 +1226,7 @@ GLOBAL_LIST_INIT(malf_modules, subtypesof(/datum/ai_module)) stack_trace("non-standard dir entered to get_rotation_from_dir. (got: [dir])") return 0 -/datum/ai_module/utility/remote_vendor_tilt +/datum/ai_module/malf/utility/remote_vendor_tilt name = "Remote vendor tilting" description = "Lets you remotely tip vendors over in any direction." cost = 15 diff --git a/code/modules/mob/living/silicon/ai/ai.dm b/code/modules/mob/living/silicon/ai/ai.dm index bda3ed47ff80..14ec45ef1ef5 100644 --- a/code/modules/mob/living/silicon/ai/ai.dm +++ b/code/modules/mob/living/silicon/ai/ai.dm @@ -49,7 +49,7 @@ //MALFUNCTION var/datum/module_picker/malf_picker - var/list/datum/ai_module/current_modules = list() + var/list/datum/ai_module/malf/current_modules = list() var/can_dominate_mechs = FALSE var/shunted = FALSE //1 if the AI is currently shunted. Used to differentiate between shunted and ghosted/braindead var/obj/machinery/ai_voicechanger/ai_voicechanger = null // reference to machine that holds the voicechanger @@ -253,7 +253,7 @@ /// Removes all malfunction-related abilities from the AI /mob/living/silicon/ai/proc/remove_malf_abilities() QDEL_NULL(modules_action) - for(var/datum/ai_module/AM in current_modules) + for(var/datum/ai_module/malf/AM in current_modules) for(var/datum/action/A in actions) if(istype(A, initial(AM.power_type))) qdel(A) @@ -1060,7 +1060,7 @@ malf_picker.processing_time += 10 var/area/apcarea = apc.area - var/datum/ai_module/destructive/nuke_station/doom_n_boom = locate(/datum/ai_module/destructive/nuke_station) in malf_picker.possible_modules["Destructive Modules"] + var/datum/ai_module/malf/destructive/nuke_station/doom_n_boom = locate(/datum/ai_module/malf/destructive/nuke_station) in malf_picker.possible_modules["Destructive Modules"] if(doom_n_boom && (is_type_in_list (apcarea, doom_n_boom.discount_areas)) && !(is_type_in_list (apcarea, doom_n_boom.hacked_command_areas))) doom_n_boom.hacked_command_areas += apcarea doom_n_boom.cost = max(50, 130 - (length(doom_n_boom.hacked_command_areas) * 20)) diff --git a/code/modules/mob/living/silicon/ai/ai_actions/remote_power.dm b/code/modules/mob/living/silicon/ai/ai_actions/remote_power.dm new file mode 100644 index 000000000000..1a32d8bb3d18 --- /dev/null +++ b/code/modules/mob/living/silicon/ai/ai_actions/remote_power.dm @@ -0,0 +1,42 @@ +/datum/ai_module/malf/power_apc + name = "Remote Power" + description = "remotely powers an APC from a distance" + one_purchase = TRUE + power_type = /datum/action/innate/ai/ranged/power_apc + unlock_text = span_notice("Remote APC power systems online.") + +/datum/action/innate/ai/ranged/power_apc + name = "Remotely Power APC" + desc = "Use to remotely power an APC." + button_icon = 'monkestation/code/modules/aesthetics/icons/apc.dmi' + button_icon_state = "apcewires" + ranged_mousepointer = 'icons/effects/mouse_pointers/supplypod_target.dmi' + enable_text = span_notice("You prepare to power any APC you see.") + disable_text = span_notice("You stop focusing on powering APCs.") + +/datum/action/innate/ai/ranged/power_apc/do_ability(mob/living/clicker, atom/clicked_on) + + if (!isAI(clicker)) + return FALSE + var/mob/living/silicon/ai/ai_clicker = clicker + +/* if(clicker.incapacitated) + unset_ranged_ability(clicker) + return FALSE +*/ + + if(!isapc(clicked_on)) + clicked_on.balloon_alert(ai_clicker, "not an APC!") + return FALSE + + if(ai_clicker.battery - 50 <= 0) + to_chat(ai_clicker, span_warning("You do not have the battery to charge an APC!")) + return FALSE + + var/obj/machinery/power/apc/apc = clicked_on + var/obj/item/stock_parts/cell/cell = apc.get_cell() + cell.give(1000) + ai_clicker.battery -= 50 + + + diff --git a/code/modules/research/designs/electronics_designs.dm b/code/modules/research/designs/electronics_designs.dm index d55e1a188bd7..6a717e1e0505 100644 --- a/code/modules/research/designs/electronics_designs.dm +++ b/code/modules/research/designs/electronics_designs.dm @@ -39,6 +39,18 @@ ) departmental_flags = DEPARTMENT_BITFLAG_SCIENCE +/datum/design/ai_power_transfer + name = "AI Power Transfer Update" + desc = "An upgrade package that lets an AI charge an APC from a distance" + id = "ai_power_upgrade" + build_type = PROTOLATHE | AWAY_LATHE + materials = list(/datum/material/iron =SHEET_MATERIAL_AMOUNT * 2.5, /datum/material/glass =SHEET_MATERIAL_AMOUNT * 2.5) + build_path = /obj/item/aiupgrade/power_transfer + category = list( + RND_CATEGORY_AI + RND_SUBCATEGORY_AI_UPGRADES + ) + departmental_flags = DEPARTMENT_BITFLAG_SCIENCE + //////////////////////////////////////// //////////Disk Construction Disks/////// //////////////////////////////////////// diff --git a/code/modules/research/techweb/robo_nodes.dm b/code/modules/research/techweb/robo_nodes.dm index 5f74311d5d38..7bc21e8d1950 100644 --- a/code/modules/research/techweb/robo_nodes.dm +++ b/code/modules/research/techweb/robo_nodes.dm @@ -90,6 +90,7 @@ description = "State of the art lawsets to be used for AI research." prereq_ids = list("ai_basic") design_ids = list( + "ai_power_upgrade", "asimovpp_module", "paladin_devotion_module", "dungeon_master_module", diff --git a/monkestation/code/modules/antagonists/malf_ai/infected_ipc.dm b/monkestation/code/modules/antagonists/malf_ai/infected_ipc.dm index d769b89a9495..c97e754cc2fe 100644 --- a/monkestation/code/modules/antagonists/malf_ai/infected_ipc.dm +++ b/monkestation/code/modules/antagonists/malf_ai/infected_ipc.dm @@ -142,7 +142,7 @@ owner.mind.remove_antag_datum(/datum/antagonist/infected_ipc) //AI MODULE -/datum/ai_module/utility/override_directive +/datum/ai_module/malf/utility/override_directive name = "Positronic Chassis Hacking" description = "Instill a directive upon a single IPC to follow your whims and protect you, \ Requires target to be incapacitated and non-mindshielded to use. \ diff --git a/tgstation.dme b/tgstation.dme index 5fe839cd757c..cd40b71fd6b6 100644 --- a/tgstation.dme +++ b/tgstation.dme @@ -4882,6 +4882,7 @@ #include "code\modules\mob\living\silicon\ai\multicam.dm" #include "code\modules\mob\living\silicon\ai\robot_control.dm" #include "code\modules\mob\living\silicon\ai\vox_sounds.dm" +#include "code\modules\mob\living\silicon\ai\ai_actions\remote_power.dm" #include "code\modules\mob\living\silicon\ai\freelook\cameranet.dm" #include "code\modules\mob\living\silicon\ai\freelook\chunk.dm" #include "code\modules\mob\living\silicon\ai\freelook\eye.dm" From a09ffd9ebc1e1e195f91f7b3975a880cc34c0d02 Mon Sep 17 00:00:00 2001 From: Gw0sty <83688318+Gw0sty@users.noreply.github.com> Date: Sun, 4 May 2025 12:06:59 -0500 Subject: [PATCH 2/6] touchups --- code/game/objects/items/robot/ai_upgrades.dm | 2 +- code/modules/mob/living/silicon/ai/ai_actions/remote_power.dm | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/code/game/objects/items/robot/ai_upgrades.dm b/code/game/objects/items/robot/ai_upgrades.dm index d3346ec48c45..5281e5d1dad0 100644 --- a/code/game/objects/items/robot/ai_upgrades.dm +++ b/code/game/objects/items/robot/ai_upgrades.dm @@ -97,7 +97,7 @@ /obj/item/aiupgrade/surveillance_upgrade name = "surveillance software upgrade" desc = "An illegal software package that will allow an artificial intelligence to 'hear' from its cameras via lip reading and hidden microphones." - to_gift = /datum/ai_module/upgrade/eavesdrop + to_gift = /datum/ai_module/malf/upgrade/eavesdrop /obj/item/aiupgrade/power_transfer name = "power transfer upgrade" diff --git a/code/modules/mob/living/silicon/ai/ai_actions/remote_power.dm b/code/modules/mob/living/silicon/ai/ai_actions/remote_power.dm index 1a32d8bb3d18..44c5ab9c6227 100644 --- a/code/modules/mob/living/silicon/ai/ai_actions/remote_power.dm +++ b/code/modules/mob/living/silicon/ai/ai_actions/remote_power.dm @@ -1,4 +1,4 @@ -/datum/ai_module/malf/power_apc +/datum/ai_module/power_apc name = "Remote Power" description = "remotely powers an APC from a distance" one_purchase = TRUE From fa43b1d788bc9485d6ff7037a9a3992a6e83bf77 Mon Sep 17 00:00:00 2001 From: Gw0sty <83688318+Gw0sty@users.noreply.github.com> Date: Mon, 5 May 2025 06:49:01 -0500 Subject: [PATCH 3/6] we do be draftin --- code/modules/antagonists/malf_ai/malf_ai_modules.dm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/modules/antagonists/malf_ai/malf_ai_modules.dm b/code/modules/antagonists/malf_ai/malf_ai_modules.dm index aa3bc298bb07..2385a5baeea6 100644 --- a/code/modules/antagonists/malf_ai/malf_ai_modules.dm +++ b/code/modules/antagonists/malf_ai/malf_ai_modules.dm @@ -893,7 +893,7 @@ GLOBAL_LIST_INIT(malf_modules, subtypesof(/datum/ai_module/malf)) unlock_text = span_notice("OTA firmware distribution complete! Cameras upgraded: Enhanced surveillance package online.") unlock_sound = 'sound/items/rped.ogg' -/datum/ai_module/umalf/pgrade/eavesdrop/upgrade(mob/living/silicon/ai/AI) +/datum/ai_module/malf/upgrade/eavesdrop/upgrade(mob/living/silicon/ai/AI) if(AI.eyeobj) AI.eyeobj.relay_speech = TRUE From 73429d637c065b58708f20735ddee0ccf0975808 Mon Sep 17 00:00:00 2001 From: Gw0sty <83688318+Gw0sty@users.noreply.github.com> Date: Tue, 6 May 2025 09:31:40 -0500 Subject: [PATCH 4/6] Incapaciated check --- code/modules/mob/living/silicon/ai/ai_actions/remote_power.dm | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/code/modules/mob/living/silicon/ai/ai_actions/remote_power.dm b/code/modules/mob/living/silicon/ai/ai_actions/remote_power.dm index 44c5ab9c6227..1122c9ff9eb0 100644 --- a/code/modules/mob/living/silicon/ai/ai_actions/remote_power.dm +++ b/code/modules/mob/living/silicon/ai/ai_actions/remote_power.dm @@ -20,10 +20,9 @@ return FALSE var/mob/living/silicon/ai/ai_clicker = clicker -/* if(clicker.incapacitated) + if(clicker.incapacitated()) unset_ranged_ability(clicker) return FALSE -*/ if(!isapc(clicked_on)) clicked_on.balloon_alert(ai_clicker, "not an APC!") From faa53ee1bf44f5a37778431c189449ba91c143ab Mon Sep 17 00:00:00 2001 From: Ghosti <83688318+notghosti@users.noreply.github.com> Date: Tue, 20 May 2025 13:48:37 -0500 Subject: [PATCH 5/6] Update code/game/objects/items/robot/ai_upgrades.dm Co-authored-by: Lucy --- code/game/objects/items/robot/ai_upgrades.dm | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/code/game/objects/items/robot/ai_upgrades.dm b/code/game/objects/items/robot/ai_upgrades.dm index 5281e5d1dad0..4ad162f437cc 100644 --- a/code/game/objects/items/robot/ai_upgrades.dm +++ b/code/game/objects/items/robot/ai_upgrades.dm @@ -8,9 +8,7 @@ var/datum/ai_module/to_gift = /datum/ai_module /obj/item/aiupgrade/pre_attack(atom/target, mob/living/user, proximity) - if(!proximity) - return ..() - if(!isAI(target)) + if(!proximity || !isAI(target)) return ..() var/mob/living/silicon/ai/AI = target var/datum/action/innate/ai/action = locate(to_gift.power_type) in AI.actions From 26c43874139625e2b26013970b9ce7668ed4e7b6 Mon Sep 17 00:00:00 2001 From: Ghosti <83688318+notghosti@users.noreply.github.com> Date: Tue, 20 May 2025 13:49:44 -0500 Subject: [PATCH 6/6] Apply suggestions from code review Co-authored-by: Lucy --- code/game/objects/items/robot/ai_upgrades.dm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/game/objects/items/robot/ai_upgrades.dm b/code/game/objects/items/robot/ai_upgrades.dm index 4ad162f437cc..b740d372e83c 100644 --- a/code/game/objects/items/robot/ai_upgrades.dm +++ b/code/game/objects/items/robot/ai_upgrades.dm @@ -31,7 +31,7 @@ if(gifted_ability.unlock_text) to_chat(AI, gifted_ability.unlock_text) if(gifted_ability.unlock_sound) - AI.playsound_local(AI, gifted_ability.unlock_sound, 50, 0) + AI.playsound_local(AI, gifted_ability.unlock_sound, vol = 50, vary = TRUE) update_static_data(AI) to_chat(user, span_notice("You install [src], upgrading [AI].")) to_chat(AI, span_userdanger("[user] has upgraded you with [src]!"))