diff --git a/code/game/gamemodes/malfunction/Malf_Modules.dm b/code/game/gamemodes/malfunction/Malf_Modules.dm index c1a907f9191..fd2004d39c7 100644 --- a/code/game/gamemodes/malfunction/Malf_Modules.dm +++ b/code/game/gamemodes/malfunction/Malf_Modules.dm @@ -592,7 +592,8 @@ active = FALSE return var/turf/T = get_turf(owner_AI.eyeobj) - new /obj/machinery/transformer/conveyor(T) + var/obj/machinery/transformer/TR = new(T) + TR.owner_AI = owner_AI playsound(T, 'sound/effects/phasein.ogg', 100, 1) owner_AI.can_shunt = FALSE to_chat(owner, "You are no longer able to shunt your core to APCs.") diff --git a/code/game/machinery/transformer.dm b/code/game/machinery/transformer.dm index cc9fc3e4666..e08ad3a3da3 100644 --- a/code/game/machinery/transformer.dm +++ b/code/game/machinery/transformer.dm @@ -6,17 +6,43 @@ layer = MOB_LAYER+1 // Overhead anchored = 1 density = 1 - var/transform_dead = 0 - var/transform_standing = 0 - var/cooldown_duration = 600 // 1 minute - var/cooldown = 0 - var/robot_cell_charge = 5000 + /// TRUE if the factory can transform dead mobs. + var/transform_dead = TRUE + /// TRUE if the mob can be standing and still be transformed. + var/transform_standing = TRUE + /// Cooldown between each transformation, in deciseconds. + var/cooldown_duration = 600 + /// If the factory is currently on cooldown from its last transformation. + var/is_on_cooldown = FALSE + /// The type of cell that newly created borgs get. + var/robot_cell_type = /obj/item/stock_parts/cell/high/plus + /// The direction that mobs must moving in to get transformed. var/acceptdir = EAST + /// The AI who placed this factory. + var/mob/living/silicon/ai/owner_AI /obj/machinery/transformer/New() - // On us - ..() - new /obj/machinery/conveyor/auto(loc, WEST) + . = ..() + initialize_belts() + +/// Used to create all of the belts the transformer will be using. All belts should be pushing `WEST`. +/obj/machinery/transformer/proc/initialize_belts() + var/turf/T = get_turf(src) + if(!T) + return + + // Belt under the factory. + new /obj/machinery/conveyor/auto(T, WEST) + + // Get the turf 1 tile to the EAST. + var/turf/east = locate(T.x + 1, T.y, T.z) + if(istype(east, /turf/simulated/floor)) + new /obj/machinery/conveyor/auto(east, WEST) + + // Get the turf 1 tile to the WEST. + var/turf/west = locate(T.x - 1, T.y, T.z) + if(istype(west, /turf/simulated/floor)) + new /obj/machinery/conveyor/auto(west, WEST) /obj/machinery/transformer/power_change() ..() @@ -24,7 +50,7 @@ /obj/machinery/transformer/update_icon() ..() - if(stat & (BROKEN|NOPOWER) || cooldown == 1) + if(is_on_cooldown || stat & (BROKEN|NOPOWER)) icon_state = "separator-AO0" else icon_state = initial(icon_state) @@ -35,120 +61,70 @@ C.setDir(newdir) acceptdir = turn(newdir, 180) -/obj/machinery/transformer/Bumped(var/atom/movable/AM) +/// Resets `is_on_cooldown` to `FALSE` and updates our icon. Used in a callback after the transformer does a transformation. +/obj/machinery/transformer/proc/reset_cooldown() + is_on_cooldown = FALSE + update_icon() - if(cooldown == 1) +/obj/machinery/transformer/Bumped(atom/movable/AM) + // They have to be human to be transformed. + if(is_on_cooldown || !ishuman(AM)) return - // Crossed didn't like people lying down. - if(ishuman(AM)) - // Only humans can enter from the west side, while lying down. - var/move_dir = get_dir(loc, AM.loc) - var/mob/living/carbon/human/H = AM - if((transform_standing || H.lying) && move_dir == acceptdir)// || move_dir == WEST) - AM.loc = src.loc - do_transform(AM) + var/mob/living/carbon/human/H = AM + var/move_dir = get_dir(loc, H.loc) -/obj/machinery/transformer/proc/do_transform(var/mob/living/carbon/human/H) - if(stat & (BROKEN|NOPOWER)) - return - if(cooldown == 1) + if((transform_standing || H.lying) && move_dir == acceptdir) + H.forceMove(loc) + do_transform(H) + +/// Transforms a human mob into a cyborg, connects them to the malf AI which placed the factory. +/obj/machinery/transformer/proc/do_transform(mob/living/carbon/human/H) + if(is_on_cooldown || stat & (BROKEN|NOPOWER)) return if(!transform_dead && H.stat == DEAD) - playsound(src.loc, 'sound/machines/buzz-sigh.ogg', 50, 0) + playsound(loc, 'sound/machines/buzz-sigh.ogg', 50, 0) return - playsound(src.loc, 'sound/items/welder.ogg', 50, 1) - H.emote("scream") // It is painful - H.adjustBruteLoss(max(0, 80 - H.getBruteLoss())) // Hurt the human, don't try to kill them though. - - // Sleep for a couple of ticks to allow the human to see the pain - sleep(5) - + playsound(loc, 'sound/items/welder.ogg', 50, 1) use_power(5000) // Use a lot of power. - var/mob/living/silicon/robot/R = H.Robotize(1) // Delete the items or they'll all pile up in a single tile and lag - R.cell.maxcharge = robot_cell_charge - R.cell.charge = robot_cell_charge + H.emote("scream") // It is painful + if(owner_AI) + H.Robotize(robot_cell_type, FALSE, owner_AI) + else + H.Robotize(robot_cell_type) - // So he can't jump out the gate right away. - R.lockcharge = !R.lockcharge - spawn(50) - playsound(src.loc, 'sound/machines/ping.ogg', 50, 0) - sleep(30) - if(R) - R.lockcharge = !R.lockcharge - R.notify_ai(1) + addtimer(CALLBACK(null, .proc/playsound, loc, 'sound/machines/ping.ogg', 50, 0), 2 SECONDS) // Activate the cooldown - cooldown = 1 + is_on_cooldown = TRUE update_icon() - spawn(cooldown_duration) - cooldown = 0 - update_icon() - -/obj/machinery/transformer/conveyor/New() - ..() - var/turf/T = loc - if(T) - // Spawn Conveyour Belts - - //East - var/turf/east = locate(T.x + 1, T.y, T.z) - if(istype(east, /turf/simulated/floor)) - new /obj/machinery/conveyor/auto(east, WEST) - - // West - var/turf/west = locate(T.x - 1, T.y, T.z) - if(istype(west, /turf/simulated/floor)) - new /obj/machinery/conveyor/auto(west, WEST) - + addtimer(CALLBACK(src, .proc/reset_cooldown), cooldown_duration) /obj/machinery/transformer/mime name = "Mimetech Greyscaler" desc = "Turns anything placed inside black and white." - -/obj/machinery/transformer/mime/conveyor/New() - ..() - var/turf/T = loc - if(T) - // Spawn Conveyour Belts - - //East - var/turf/east = locate(T.x + 1, T.y, T.z) - if(istype(east, /turf/simulated/floor)) - new /obj/machinery/conveyor/auto(east, WEST) - - // West - var/turf/west = locate(T.x - 1, T.y, T.z) - if(istype(west, /turf/simulated/floor)) - new /obj/machinery/conveyor/auto(west, WEST) - -/obj/machinery/transformer/mime/Bumped(var/atom/movable/AM) - - if(cooldown == 1) +/obj/machinery/transformer/mime/Bumped(atom/movable/AM) + if(is_on_cooldown) return // Crossed didn't like people lying down. - if(isatom(AM)) - AM.loc = src.loc + if(istype(AM)) + AM.forceMove(loc) do_transform_mime(AM) else to_chat(AM, "Only items can be greyscaled.") return -/obj/machinery/transformer/proc/do_transform_mime(var/obj/item/I) - if(stat & (BROKEN|NOPOWER)) - return - if(cooldown == 1) +/obj/machinery/transformer/proc/do_transform_mime(obj/item/I) + if(is_on_cooldown || stat & (BROKEN|NOPOWER)) return - playsound(src.loc, 'sound/items/welder.ogg', 50, 1) - // Sleep for a couple of ticks to allow the human to see the pain - sleep(5) + playsound(loc, 'sound/items/welder.ogg', 50, 1) use_power(5000) // Use a lot of power. var/icon/newicon = new(I.icon, I.icon_state) @@ -156,42 +132,27 @@ I.icon = newicon // Activate the cooldown - cooldown = 1 + is_on_cooldown = TRUE update_icon() - spawn(cooldown_duration) - cooldown = 0 - update_icon() + addtimer(CALLBACK(src, .proc/reset_cooldown), cooldown_duration) /obj/machinery/transformer/xray name = "Automatic X-Ray 5000" desc = "A large metalic machine with an entrance and an exit. A sign on the side reads, 'backpack go in, backpack come out', 'human go in, irradiated human come out'." + acceptdir = WEST -/obj/machinery/transformer/xray/Initialize(mapload) - . = ..() - // On us - new /obj/machinery/conveyor/auto(loc, EAST) - -/obj/machinery/transformer/xray/conveyor/New() - ..() - var/turf/T = loc +/obj/machinery/transformer/xray/initialize_belts() + var/turf/T = get_turf(src) if(T) - // Spawn Conveyour Belts + // This handles the belt under the transformer and 1 tile to the left and right. + . = ..() - //East - var/turf/east = locate(T.x + 1, T.y, T.z) - if(istype(east, /turf/simulated/floor)) - new /obj/machinery/conveyor/auto(east, EAST) - //East2 + // Get the turf 2 tiles to the EAST. var/turf/east2 = locate(T.x + 2, T.y, T.z) if(istype(east2, /turf/simulated/floor)) new /obj/machinery/conveyor/auto(east2, EAST) - // West - var/turf/west = locate(T.x - 1, T.y, T.z) - if(istype(west, /turf/simulated/floor)) - new /obj/machinery/conveyor/auto(west, EAST) - - // West2 + // Get the turf 2 tiles to the WEST. var/turf/west2 = locate(T.x - 2, T.y, T.z) if(istype(west2, /turf/simulated/floor)) new /obj/machinery/conveyor/auto(west2, EAST) @@ -207,30 +168,30 @@ else icon_state = initial(icon_state) -/obj/machinery/transformer/xray/Bumped(var/atom/movable/AM) - - if(cooldown == 1) +/obj/machinery/transformer/xray/Bumped(atom/movable/AM) + if(is_on_cooldown) return // Crossed didn't like people lying down. if(ishuman(AM)) // Only humans can enter from the west side, while lying down. - var/move_dir = get_dir(loc, AM.loc) var/mob/living/carbon/human/H = AM - if(H.lying && move_dir == WEST)// || move_dir == WEST) - AM.loc = src.loc - irradiate(AM) + var/move_dir = get_dir(loc, H.loc) - else if(isatom(AM)) - AM.loc = src.loc + if(H.lying && move_dir == acceptdir) + H.forceMove(loc) + irradiate(H) + + else if(istype(AM)) + AM.forceMove(loc) scan(AM) -/obj/machinery/transformer/xray/proc/irradiate(var/mob/living/carbon/human/H) +/obj/machinery/transformer/xray/proc/irradiate(mob/living/carbon/human/H) if(stat & (BROKEN|NOPOWER)) return flick("separator-AO0",src) - playsound(src.loc, 'sound/effects/alert.ogg', 50, 0) + playsound(loc, 'sound/effects/alert.ogg', 50, 0) sleep(5) H.apply_effect((rand(150,200)),IRRADIATE,0) if(prob(5)) @@ -242,15 +203,15 @@ domutcheck(H,null,1) -/obj/machinery/transformer/xray/proc/scan(var/obj/item/I) +/obj/machinery/transformer/xray/proc/scan(obj/item/I) if(scan_rec(I)) - playsound(src.loc, 'sound/effects/alert.ogg', 50, 0) + playsound(loc, 'sound/effects/alert.ogg', 50, 0) flick("separator-AO0",src) else - playsound(src.loc, 'sound/machines/ping.ogg', 50, 0) + playsound(loc, 'sound/machines/ping.ogg', 50, 0) sleep(30) -/obj/machinery/transformer/xray/proc/scan_rec(var/obj/item/I) +/obj/machinery/transformer/xray/proc/scan_rec(obj/item/I) if(istype(I, /obj/item/gun)) return TRUE if(istype(I, /obj/item/transfer_valve)) diff --git a/code/modules/mob/living/silicon/robot/robot.dm b/code/modules/mob/living/silicon/robot/robot.dm index 2eb1e4669ab..7f154d32a68 100644 --- a/code/modules/mob/living/silicon/robot/robot.dm +++ b/code/modules/mob/living/silicon/robot/robot.dm @@ -108,7 +108,7 @@ GLOBAL_LIST_INIT(robot_verbs_default, list( /mob/living/silicon/robot/get_cell() return cell -/mob/living/silicon/robot/New(loc,var/syndie = 0,var/unfinished = 0, var/alien = 0) +/mob/living/silicon/robot/New(loc, syndie = FALSE, unfinished = FALSE, alien = FALSE, connect_to_AI = TRUE) spark_system = new /datum/effect_system/spark_spread() spark_system.set_up(5, 0, src) spark_system.attach(src) @@ -130,7 +130,7 @@ GLOBAL_LIST_INIT(robot_verbs_default, list( radio = new /obj/item/radio/borg(src) common_radio = radio - init() + init(alien, connect_to_AI) if(!scrambledcodes && !camera) camera = new /obj/machinery/camera(src) @@ -168,16 +168,16 @@ GLOBAL_LIST_INIT(robot_verbs_default, list( scanner = new(src) scanner.Grant(src) -/mob/living/silicon/robot/proc/init(var/alien=0) +/mob/living/silicon/robot/proc/init(alien = FALSE, connect_to_AI = TRUE) aiCamera = new/obj/item/camera/siliconcam/robot_camera(src) make_laws() additional_law_channels["Binary"] = ":b " var/new_ai = select_active_ai_with_fewest_borgs() - if(new_ai) - lawupdate = 1 + if(new_ai && connect_to_AI) + lawupdate = TRUE connect_to_ai(new_ai) else - lawupdate = 0 + lawupdate = FALSE playsound(loc, 'sound/voice/liveagain.ogg', 75, 1) diff --git a/code/modules/mob/transform_procs.dm b/code/modules/mob/transform_procs.dm index 2ee4a9d2a9c..914f961e5a6 100644 --- a/code/modules/mob/transform_procs.dm +++ b/code/modules/mob/transform_procs.dm @@ -44,26 +44,37 @@ -//human -> robot -/mob/living/carbon/human/proc/Robotize() +/** + For transforming humans into robots (cyborgs). + + Arguments: + * cell_type: A type path of the cell the new borg should receive. + * connect_to_default_AI: TRUE if you want /robot/New() to handle connecting the borg to the AI with the least borgs. + * AI: A reference to the AI we want to connect to. +*/ +/mob/living/carbon/human/proc/Robotize(cell_type = null, connect_to_default_AI = TRUE, mob/living/silicon/ai/AI = null) if(notransform) return for(var/obj/item/W in src) unEquip(W) - regenerate_icons() + notransform = 1 canmove = 0 icon = null invisibility = 101 - for(var/t in bodyparts) - qdel(t) - for(var/i in internal_organs) - qdel(i) - var/mob/living/silicon/robot/O = new /mob/living/silicon/robot( loc ) + // Creating a new borg here will connect them to a default AI and notify that AI, if `connect_to_default_AI` is TRUE. + var/mob/living/silicon/robot/O = new /mob/living/silicon/robot(loc, connect_to_AI = connect_to_default_AI) - // cyborgs produced by Robotize get an automatic power cell - O.cell = new /obj/item/stock_parts/cell/high(O) + // If `AI` is passed in, we want to connect to that AI specifically. + if(AI) + O.lawupdate = TRUE + O.connect_to_ai(AI) + + if(!cell_type) + O.cell = new /obj/item/stock_parts/cell/high(O) + else + O.cell = new cell_type(O) O.gender = gender O.invisibility = 0 @@ -77,9 +88,8 @@ else O.key = key - O.loc = loc + O.forceMove(loc) O.job = "Cyborg" - O.notify_ai(1) if(O.mind && O.mind.assigned_role == "Cyborg") if(O.mind.role_alt_title == "Android")