diff --git a/code/datums/spell.dm b/code/datums/spell.dm index d8c7b26554c..b510434f467 100644 --- a/code/datums/spell.dm +++ b/code/datums/spell.dm @@ -5,6 +5,7 @@ var/panel = "Debug"//What panel the proc holder needs to go on. var/active = FALSE //Used by toggle based abilities. var/ranged_mousepointer + var/mob/living/ranged_ability_user var/list/spells = typesof(/obj/effect/proc_holder/spell) //needed for the badmin verb for now @@ -24,6 +25,7 @@ var/list/spells = typesof(/obj/effect/proc_holder/spell) //needed for the badmin to_chat(user, "[user.ranged_ability.name] has been replaced by [name].") user.ranged_ability.remove_ranged_ability(user) user.ranged_ability = src + ranged_ability_user = user user.client.click_intercept = user.ranged_ability add_mousepointer(user.client) active = TRUE @@ -43,6 +45,7 @@ var/list/spells = typesof(/obj/effect/proc_holder/spell) //needed for the badmin if(!user || !user.client || (user.ranged_ability && user.ranged_ability != src)) //To avoid removing the wrong ability return user.ranged_ability = null + ranged_ability_user = null user.client.click_intercept = null remove_mousepointer(user.client) active = FALSE diff --git a/code/game/gamemodes/malfunction/Malf_Modules.dm b/code/game/gamemodes/malfunction/Malf_Modules.dm index 9a40cb58881..eb54b52c225 100644 --- a/code/game/gamemodes/malfunction/Malf_Modules.dm +++ b/code/game/gamemodes/malfunction/Malf_Modules.dm @@ -77,13 +77,9 @@ var/disable_text = "Goodbye Cruel World!" //Context clues! var/datum/action/innate/ai/ranged/attached_action -/obj/effect/proc_holder/ranged_ai/Destroy() - QDEL_NULL(attached_action) - return ..() - /obj/effect/proc_holder/ranged_ai/proc/toggle(mob/user) if(active) - remove_ranged_ability(disable_text) + remove_ranged_ability(user, disable_text) else add_ranged_ability(user, enable_text) @@ -188,6 +184,7 @@ var/upgrade //If the module gives a passive upgrade, use this. Mutually exclusive with power_type. var/unlock_text = "Hello World!" //Text shown when an ability is unlocked var/unlock_sound //Sound played when an ability is unlocked + var/uses /datum/AI_Module/proc/upgrade(mob/living/silicon/AI/AI) //Apply upgrades! return @@ -349,7 +346,7 @@ for(var/obj/machinery/door/D in GLOB.airlocks) if(!is_station_level(D.z)) continue - INVOKE_ASYNC(D, /obj/machinery/door.proc/hostile_lockdown, src) + INVOKE_ASYNC(D, /obj/machinery/door.proc/hostile_lockdown, owner) addtimer(CALLBACK(D, /obj/machinery/door.proc/disable_lockdown), 900) post_status("alert", "lockdown") @@ -448,50 +445,60 @@ to_chat(owner, "All air alarm safeties on the station have been overriden. Air alarms may now use the Flood environmental mode.") owner.playsound_local(owner, 'sound/machines/terminal_off.ogg', 50, 0) + //Overload Machine: Allows the AI to overload a machine, detonating it after a delay. Two uses per purchase. /datum/AI_Module/small/overload_machine module_name = "Machine Overload" mod_pick_name = "overload" description = "Overheats an electrical machine, causing a small explosion and destroying it. Two uses per purchase." cost = 20 - power_type = /datum/action/innate/ai/overload_machine + power_type = /datum/action/innate/ai/ranged/overload_machine unlock_text = "You enable the ability for the station's APCs to direct intense energy into machinery." -/datum/action/innate/ai/overload_machine +/datum/action/innate/ai/ranged/overload_machine name = "Overload Machine" desc = "Overheats a machine, causing a small explosion after a short time." button_icon_state = "overload_machine" uses = 2 - auto_use_uses = FALSE + linked_ability_type = /obj/effect/proc_holder/ranged_ai/overload_machine -/datum/action/innate/ai/overload_machine/New() +/datum/action/innate/ai/ranged/overload_machine/New() ..() desc = "[desc] It has [uses] use\s remaining." button.desc = desc -/datum/action/innate/ai/overload_machine/Activate() - var/select = input("Choose a device to overload", "Overload Machine", null, null) as null|anything in GLOB.machines - if(!select) +/datum/action/innate/ai/ranged/overload_machine/proc/detonate_machine(obj/machinery/M) + if(M && !QDELETED(M)) + explosion(get_turf(M), 0,1,1,0) + if(M) //to check if the explosion killed it before we try to delete it + qdel(M) + +/obj/effect/proc_holder/ranged_ai/overload_machine + active = FALSE + ranged_mousepointer = 'icons/effects/overload_machine_target.dmi' + enable_text = "You tap into the station's powernet. Click on a machine to detonate it, or use the ability again to cancel." + disable_text = "You release your hold on the powernet." + +/obj/effect/proc_holder/ranged_ai/overload_machine/InterceptClickOn(mob/living/caller, params, obj/machinery/target) + if(..()) + return + if(ranged_ability_user.incapacitated()) + remove_ranged_ability() + return + if(!istype(target)) + to_chat(ranged_ability_user, "You can only overload machines!") return - var/obj/machinery/M = select - if(istype(M, /obj/machinery)) - if(uses > 0) - adjust_uses(-1) - if(src && uses) //Not sure if not having src here would cause a runtime, so it's here to be safe - desc = "[initial(desc)] It has [uses] use\s remaining." - UpdateButtonIcon() - M.audible_message("You hear a loud electrical buzzing sound!") - to_chat(owner, "Overloading machine circuitry...") - spawn(50) - if(M) - explosion(get_turf(M), 0,1,1,0) - qdel(M) - else - to_chat(owner, "Out of uses.") - else - to_chat(owner, "That's not a machine.") - return + ranged_ability_user.playsound_local(ranged_ability_user, "sparks", 50, 0) + attached_action.adjust_uses(-1) + if(attached_action && attached_action.uses) + attached_action.desc = "[initial(attached_action.desc)] It has [attached_action.uses] use\s remaining." + attached_action.UpdateButtonIcon() + target.audible_message("You hear a loud electrical buzzing sound coming from [target]!") + addtimer(CALLBACK(attached_action, /datum/action/innate/ai/ranged/overload_machine.proc/detonate_machine, target), 50) //kaboom! + remove_ranged_ability(ranged_ability_user, "Overloading machine circuitry...") + return TRUE + //Override Machine: Allows the AI to override a machine, animating it into an angry, living version of itself. /datum/AI_Module/small/override_machine @@ -499,46 +506,54 @@ mod_pick_name = "override" description = "Overrides a machine's programming, causing it to rise up and attack everyone except other machines. Four uses." cost = 30 - power_type = /datum/action/innate/ai/override_machine - unlock_text = "You procure a virus from the Space Dark Web and prepare to distribute it to the station's machines." + power_type = /datum/action/innate/ai/ranged/override_machine + unlock_text = "You procure a virus from the Space Dark Web and distribute it to the station's machines." -/datum/action/innate/ai/override_machine +/datum/action/innate/ai/ranged/override_machine name = "Override Machine" desc = "Animates a targeted machine, causing it to attack anyone nearby." button_icon_state = "override_machine" uses = 4 - auto_use_uses = FALSE + linked_ability_type = /obj/effect/proc_holder/ranged_ai/override_machine -/datum/action/innate/ai/override_machine/New() +/datum/action/innate/ai/ranged/override_machine/New() ..() desc = "[desc] It has [uses] use\s remaining." button.desc = desc -/datum/action/innate/ai/override_machine/Activate() - var/select = input("Choose a device to override", "Override Machine", null, null) as null|anything in GLOB.machines - if(!select) +/datum/action/innate/ai/ranged/override_machine/proc/animate_machine(obj/machinery/M) + if(M && !QDELETED(M)) + new/mob/living/simple_animal/hostile/mimic/copy/machine(get_turf(M), M, owner, 1) + +/obj/effect/proc_holder/ranged_ai/override_machine + active = FALSE + ranged_mousepointer = 'icons/effects/override_machine_target.dmi' + enable_text = "You tap into the station's powernet. Click on a machine to animate it, or use the ability again to cancel." + disable_text = "You release your hold on the powernet." + +/obj/effect/proc_holder/ranged_ai/override_machine/InterceptClickOn(mob/living/caller, params, obj/machinery/target) + if(..()) + return + if(ranged_ability_user.incapacitated()) + remove_ranged_ability() + return + if(!istype(target)) + to_chat(ranged_ability_user, "You can only animate machines!") + return + if(!target.can_be_overridden()) + to_chat(ranged_ability_user, "That machine can't be overridden!") return - var/obj/machinery/M = select - if(istype(M, /obj/machinery)) - if(!M.can_be_overridden()) - to_chat(owner, "Can't override this device.") - return - else if(uses > 0) - adjust_uses(-1) - if(src && uses) //Not sure if not having src here would cause a runtime, so it's here to be safe - desc = "[initial(desc)] It has [uses] use\s remaining." - UpdateButtonIcon() - M.audible_message("You hear a loud electrical buzzing sound!") - to_chat(owner, "Reprogramming machine behaviour...") - spawn(50) - if(M && !QDELETED(M)) - new /mob/living/simple_animal/hostile/mimic/copy/machine(get_turf(M), M, src, 1) - else - to_chat(owner, "Out of uses.") - else - to_chat(owner, "That's not a machine.") - return + ranged_ability_user.playsound_local(ranged_ability_user, 'sound/misc/interference.ogg', 50, 0) + attached_action.adjust_uses(-1) + if(attached_action && attached_action.uses) + attached_action.desc = "[initial(attached_action.desc)] It has [attached_action.uses] use\s remaining." + attached_action.UpdateButtonIcon() + target.audible_message("You hear a loud electrical buzzing sound coming from [target]!") + addtimer(CALLBACK(attached_action, /datum/action/innate/ai/ranged/override_machine.proc/animate_machine, target), 50) //kabeep! + remove_ranged_ability(ranged_ability_user, "Sending override signal...") + return TRUE + //Robotic Factory: Places a large machine that converts humans that go through it into cyborgs. Unlocking this ability removes shunting. /datum/AI_Module/large/place_cyborg_transformer diff --git a/icons/effects/overload_machine_target.dmi b/icons/effects/overload_machine_target.dmi new file mode 100644 index 00000000000..8bc67cdab6c Binary files /dev/null and b/icons/effects/overload_machine_target.dmi differ diff --git a/icons/effects/override_machine_target.dmi b/icons/effects/override_machine_target.dmi new file mode 100644 index 00000000000..77dbb4ba32b Binary files /dev/null and b/icons/effects/override_machine_target.dmi differ