diff --git a/code/game/gamemodes/malfunction/Malf_Modules.dm b/code/game/gamemodes/malfunction/Malf_Modules.dm index 1b2e70664ce..beb5ba1840c 100644 --- a/code/game/gamemodes/malfunction/Malf_Modules.dm +++ b/code/game/gamemodes/malfunction/Malf_Modules.dm @@ -341,6 +341,7 @@ turret.health += 30 turret.eprojectile = /obj/item/projectile/beam/laser/ai_turret/heavylaser //Once you see it, you will know what it means to FEAR. turret.eshot_sound = 'sound/weapons/lasercannonfire.ogg' + AI.turrets_upgraded = TRUE //Hostile Station Lockdown: Locks, bolts, and electrifies every airlock on the station. After 90 seconds, the doors reset. /datum/AI_Module/lockdown @@ -626,6 +627,107 @@ to_chat(src, "[alert_msg]") return success +//Turret Assembly: Assemble an AI turret at the chosen location. One use per purchase +/datum/AI_Module/place_turret + module_name = "Deploy Turret" + mod_pick_name = "turretdeployer" + description = "Build a turret anywhere that lethally targets organic life in sight." + cost = 30 + power_type = /datum/action/innate/ai/place_turret + unlock_text = "You prepare an energy turret for deployment." + unlock_sound = 'sound/items/rped.ogg' + +/datum/action/innate/ai/place_turret + name = "Deploy Turret" + desc = "Build a turret anywhere that lethally targets organic life in sight." + button_icon_state = "deploy_turret" + uses = 1 + auto_use_uses = FALSE + var/image/turf_overlay + +/datum/action/innate/ai/place_turret/New() + ..() + turf_overlay = image('icons/turf/overlays.dmi') + +/datum/action/innate/ai/place_turret/Activate() + if(active) + to_chat(owner, "Your assemblers can only construct one turret at a time.") + return + if(!owner_AI.can_place_turret(src)) + return + active = TRUE + var/response = alert(owner, "Are you sure you want to place a turret here? Deployment will take a few seconds to complete, in which the turret will be vulnerable.", "Are you sure?", "No", "Yes") + if(!response || response == "No") + active = FALSE + return + if(!owner_AI.can_place_turret(src)) + active = FALSE + return + deploy_turret() + active = FALSE + +/datum/action/innate/ai/place_turret/proc/deploy_turret() + var/turf/T = get_turf(owner_AI.eyeobj) + + //Handles the turret construction and configuration + playsound(T, 'sound/items/rped.ogg', 100, TRUE) //Plays a sound both at the location of the construction to alert players and to the user as feedback + owner.playsound_local(owner, 'sound/items/rped.ogg', 50, FALSE, use_reverb = FALSE) + to_chat(owner, "You order your electronics to assemble a turret. This will take a few seconds.") + var/obj/effect/temp_visual/rcd_effect/spawning_effect = new(T) + QDEL_IN(spawning_effect, 5 SECONDS) + + //Deploys as lethal. Nonlethals can be enabled. + var/obj/machinery/porta_turret/turret = new /obj/machinery/porta_turret/ai_turret(T) + turret.disabled = TRUE + turret.lethal = TRUE + turret.raised = TRUE //While raised, it is vulnerable to damage + turret.targetting_is_configurable = FALSE + turret.check_synth = TRUE + turret.invisibility = 100 + + //If turrets are already upgraded, beef it up + if(owner_AI.turrets_upgraded) + turret.health += 30 + turret.eprojectile = /obj/item/projectile/beam/laser/ai_turret/heavylaser //Big gun + turret.eshot_sound = 'sound/weapons/lasercannonfire.ogg' + + if(do_after_once(owner, 5 SECONDS, target = T, allow_moving = TRUE)) //Once this is done, turret is armed and dangerous + turret.raised = initial(turret.raised) + turret.invisibility = initial(turret.invisibility) + turret.disabled = initial(turret.disabled) + new /obj/effect/temp_visual/rcd_effect/end(T) + playsound(T, 'sound/items/deconstruct.ogg', 100, TRUE) + to_chat(owner, "Turret deployed.") + adjust_uses(-1) + +/mob/living/silicon/ai/proc/can_place_turret(datum/action/innate/ai/place_turret/action) + if(!eyeobj || !isturf(eyeobj.loc) || incapacitated() || !action) + return + + var/turf/simulated/floor/deploylocation = get_turf(eyeobj) + + var/image/I = action.turf_overlay + I.loc = deploylocation + client.images += I + I.icon_state = "redOverlay" + var/datum/camerachunk/C = GLOB.cameranet.getCameraChunk(deploylocation.x, deploylocation.y, deploylocation.z) + + if(!istype(deploylocation)) + to_chat(src, "There isn't enough room! Make sure you are placing the machine in a clear area and on a floor.") + return FALSE + if(!C.visibleTurfs[deploylocation]) + to_chat(src, "You don't have camera vision of this location!") + addtimer(CALLBACK(src, PROC_REF(remove_transformer_image), client, I, deploylocation), 3 SECONDS) + return FALSE + if(is_blocked_turf(deploylocation)) + to_chat(src, "That area must be clear of objects!") + addtimer(CALLBACK(src, PROC_REF(remove_transformer_image), client, I, deploylocation), 3 SECONDS) + return FALSE + + I.icon_state = "greenOverlay" //greenOverlay and redOverlay for success and failure respectively + addtimer(CALLBACK(src, PROC_REF(remove_transformer_image), client, I, deploylocation), 3 SECONDS) + return TRUE + //Blackout: Overloads a random number of lights across the station. Three uses. /datum/AI_Module/blackout module_name = "Blackout" diff --git a/code/modules/mob/living/silicon/ai/ai_mob.dm b/code/modules/mob/living/silicon/ai/ai_mob.dm index 8d1dd45d5ae..1529339ddf0 100644 --- a/code/modules/mob/living/silicon/ai/ai_mob.dm +++ b/code/modules/mob/living/silicon/ai/ai_mob.dm @@ -77,6 +77,9 @@ GLOBAL_LIST_INIT(ai_verbs_default, list( var/obj/machinery/power/apc/malfhack = null var/explosive = 0 //does the AI explode when it dies? + ///Whether or not the AI has upgraded their turrets + var/turrets_upgraded = FALSE + /// List of modules the AI has purchased malf upgrades for. var/list/purchased_modules = list() diff --git a/icons/mob/actions/actions.dmi b/icons/mob/actions/actions.dmi index ae9e005bf80..fbb7887ae85 100644 Binary files a/icons/mob/actions/actions.dmi and b/icons/mob/actions/actions.dmi differ