// // Rapid Fabrication Devices // // Defines #define MATERIALIZATION_FAIL_MESSAGE "You can't materialize two constructions of the same type." /** * # Rapid Fabrication Device * * A device used for rapid fabrication of things, built from a compressed matter cartridge */ ABSTRACT_TYPE(/obj/item/rfd) name = "\improper Rapid Fabrication Device" desc = "A device used for rapid fabrication. The matter decompression matrix is untuned, rendering it useless." icon = 'icons/obj/rfd.dmi' icon_state = "rfd" item_state = "rfd" item_icons = list( slot_l_hand_str = 'icons/mob/items/lefthand_tools.dmi', slot_r_hand_str = 'icons/mob/items/righthand_tools.dmi' ) opacity = FALSE density = FALSE anchored = FALSE obj_flags = OBJ_FLAG_CONDUCTABLE force = 11 throwforce = 10 throw_speed = 1 throw_range = 5 w_class = WEIGHT_CLASS_NORMAL origin_tech = list(TECH_ENGINEERING = 4, TECH_MATERIAL = 2) matter = list(DEFAULT_WALL_MATERIAL = 50000) drop_sound = 'sound/items/drop/gun.ogg' pickup_sound = 'sound/items/pickup/gun.ogg' /** * A K-V list of modes that the RFD will show as selectable in the radial menu * * Key is a string, the name of the mode * Value is an image, to be displayed inside the radial menu button */ var/list/radial_modes = list() /// Starts off full. var/stored_matter = 30 var/working = FALSE /// The mode the RFD is currently operating in var/mode = RFD_FLOORS_AND_WALL var/number_of_modes = 1 var/list/modes var/crafting = FALSE var/build_cost = 0 var/build_type var/build_atom var/build_delay var/last_fail = 0 /obj/item/rfd/feedback_hints(mob/user, distance, is_adjacent) . += ..() if(loc == user) . += "It currently holds [stored_matter]/30 matter units." /obj/item/rfd/Initialize() . = ..() return INITIALIZE_HINT_LATELOAD /obj/item/rfd/LateInitialize() . = ..() update_icon() /obj/item/rfd/attack(mob/living/target_mob, mob/living/user, target_zone) return FALSE /obj/item/rfd/proc/can_use(var/mob/user,var/turf/T) return (user.Adjacent(T) && user.get_active_hand() == src && !user.stat && !user.restrained()) /** * Changes RFD mode. */ /obj/item/rfd/attack_self(mob/user) // Change the mode if(++mode > number_of_modes) mode = RFD_FLOORS_AND_WALL to_chat(user, SPAN_NOTICE("The mode selection dial is now at [modes[mode]].")) playsound(get_turf(src), 'sound/weapons/laser_safetyon.ogg', 50, FALSE) /** * If attacked with a Compressed Matter Cartridge, refill the RFD by 10. */ /obj/item/rfd/attackby(obj/item/attacking_item, mob/user) if(istype(attacking_item, /obj/item/rfd_ammo)) if((stored_matter + 10) > 30) to_chat(user, SPAN_NOTICE("The RFD can't hold any more matter units.")) return user.drop_from_inventory(attacking_item, src) qdel(attacking_item) stored_matter += 10 playsound(src.loc, 'sound/weapons/laser_reload1.ogg', 50, FALSE) to_chat(user, SPAN_NOTICE("The RFD now holds [stored_matter]/30 matter units.")) update_icon() return TRUE // Turning it into a crossbow, as you do. if(attacking_item.tool_behaviour == TOOL_SCREWDRIVER) crafting = !crafting if(!crafting) to_chat(user, SPAN_NOTICE("You reassemble the RFD.")) else to_chat(user, SPAN_NOTICE("The RFD can now be modified.")) src.add_fingerprint(user) return TRUE if(crafting) // The thing we're gonna add, check what it is below var/obj/item/crossbow if(istype(attacking_item, /obj/item/crossbowframe)) var/obj/item/crossbowframe/F = attacking_item if(F.buildstate != 5) to_chat(user, SPAN_WARNING("You need to fully assemble the crossbow frame first!")) return TRUE crossbow = F else if(istype(attacking_item, /obj/item/gun/launcher/crossbow) && !istype(attacking_item, /obj/item/gun/launcher/crossbow/RFD)) var/obj/item/gun/launcher/crossbow/C = attacking_item if(C.bolt) to_chat(user, SPAN_WARNING("You need to remove \the [C.bolt] from \the [C] before you can attach it to \the [src].")) return TRUE if(C.cell) to_chat(user, SPAN_WARNING("You need to remove \the [C.cell] from \the [C] before you can attach it to \the [src].")) return TRUE crossbow = C if(crossbow) qdel(crossbow) // Can be found in "crossbow.dm". var/obj/item/gun/launcher/crossbow/RFD/CB = new(get_turf(user)) forceMove(CB) CB.stored_matter = src.stored_matter user.drop_from_inventory(src) qdel(src) user.put_in_hands(CB) return TRUE return ..() /obj/item/rfd/proc/useResource(var/amount, var/mob/user) if(stored_matter < amount) return FALSE stored_matter -= amount update_icon() return TRUE // For the fancy "ammo" counter. /** * Adds a fancy ammo counter. */ /obj/item/rfd/update_icon() CutOverlays() var/ratio = 0 /// 30 is the hardcoded max capacity of the RFD ratio = stored_matter / 30 ratio = max(round(ratio, 0.10) * 100, 10) AddOverlays("[icon_state]-[ratio]") /** * # RFD Compressed Matter Cartridge * * Highly compressed matter for the RFD, basically RFD ammos */ /obj/item/rfd_ammo name = "compressed matter cartridge" desc = "Highly compressed matter for the RFD." icon = 'icons/obj/ammo.dmi' icon_state = "rfd" item_state = "rfdammo" w_class = WEIGHT_CLASS_SMALL origin_tech = list(TECH_MATERIAL = 2) matter = list(DEFAULT_WALL_MATERIAL = 2000, MATERIAL_GLASS = 2000) recyclable = TRUE /*############## SUBTYPES ##############*/ // // RFD - Construction Class // /obj/item/rfd/construction name = "\improper Rapid Fabrication Device C-Class" desc = "A RFD, modified to construct walls and floors." var/can_rwall = FALSE var/disabled = FALSE /// A list of types that will be sent to the alter_atom proc if we click on them, rather than their turf. var/list/valid_atoms = list( /obj/machinery/door/airlock, /obj/structure/window_frame, /obj/structure/window/full ) /obj/item/rfd/construction/Initialize() . = ..() radial_modes = list( "Floor and Wall" = image(icon = 'icons/mob/screen/radial.dmi', icon_state = "wallfloor"), "Window and Window Frame" = image(icon = 'icons/mob/screen/radial.dmi', icon_state = "windowframe"), "Airlock" = image(icon = 'icons/mob/screen/radial.dmi', icon_state = "airlock"), "Deconstruct" = image(icon = 'icons/mob/screen/radial.dmi', icon_state = "delete") ) /obj/item/rfd/construction/attack_self(mob/user) var/current_mode = RADIAL_INPUT(user, radial_modes) switch(current_mode) if("Floor and Wall") mode = RFD_FLOORS_AND_WALL if("Window and Window Frame") mode = RFD_WINDOW_AND_FRAME if("Deconstruct") mode = RFD_DECONSTRUCT if("Airlock") mode = RFD_AIRLOCK else mode = RFD_DECONSTRUCT if(current_mode) to_chat(user, SPAN_NOTICE("You switch the selection dial to \"[current_mode]\".")) if(mode == 3) playsound(get_turf(src), 'sound/weapons/laser_safetyoff.ogg', 50, FALSE) else playsound(get_turf(src), 'sound/weapons/laser_safetyon.ogg', 50, FALSE) /obj/item/rfd/construction/afterattack(atom/A, mob/user, proximity) if(!proximity) return if((!isturf(A) && !isturf(A.loc)) || istype(A, /obj/structure/table)) return if(disabled && !isrobot(user)) return FALSE var/area/Area = get_area(A) if(Area.centcomm_area || istype(Area, /area/shuttle) || istype(Area, /turf/space/transit)) to_chat(user, SPAN_NOTICE("\The [src] can't be used here.")) return FALSE if(is_type_in_list(A, valid_atoms)) return alter_atom(A, user, (mode == RFD_DECONSTRUCT)) return alter_atom(get_turf(A), user, (mode == RFD_DECONSTRUCT)) /obj/item/rfd/construction/proc/alter_atom(var/atom/A, var/mob/user, var/deconstruct) if(working) return FALSE // The lower istypes will return false if T is null, which means we don't have to check whether it's an atom or a turf var/turf/T = isturf(A) ? A : null if(mode == RFD_FLOORS_AND_WALL) if(istype(T, /turf/space) || istype(T, T.baseturf)) build_cost = 1 build_type = "floor" build_atom = /turf/simulated/floor/airless else if(istype(T, /turf/simulated/open)) build_cost = 1 build_type = "floor" build_atom = /turf/simulated/floor/airless else if(istype(T, /turf/simulated/floor)) build_delay = 20 build_cost = 3 build_type = "wall" build_atom = /turf/simulated/wall else if(mode == RFD_WINDOW_AND_FRAME) if(istype(T, /turf/simulated/floor)) if(locate(/obj/structure/window_frame) in get_turf(A)) to_chat(user, SPAN_NOTICE(MATERIALIZATION_FAIL_MESSAGE)) return build_cost = 3 build_delay = 20 build_type = "window frame" build_atom = /obj/structure/window_frame else if(istype(A, /obj/structure/window_frame)) if(locate(/obj/structure/window/full/reinforced) in get_turf(A)) to_chat(user, SPAN_NOTICE(MATERIALIZATION_FAIL_MESSAGE)) return build_cost = 3 build_delay = 20 build_type = "window" build_atom = /obj/structure/window/full/reinforced else if(mode == RFD_AIRLOCK) if(istype(T, /turf/simulated/floor)) build_cost = 3 build_delay = 20 build_type = "airlock" build_atom = /obj/machinery/door/airlock else if(mode == RFD_DECONSTRUCT) // Airlocks if(istype(A, /obj/machinery/door/airlock)) build_cost = 10 build_delay = 50 build_type = "airlock" // Walls else if(istype(T, /turf/simulated/wall)) var/turf/simulated/wall/W = T build_cost = 5 build_delay = 50 build_type = (!can_rwall && W.reinf_material) ? null : "wall" build_atom = W.under_turf // Floors else if(istype(T, /turf/simulated/floor)) build_cost = 10 build_delay = 50 build_type = "floor" build_atom = T.baseturf // Window Frames if(istype(A, /obj/structure/window_frame)) if(locate(/obj/structure/window/full) in get_turf(A)) to_chat(user, SPAN_NOTICE("You can't deconstruct \the [A] if it has glass installed.")) return build_cost = 3 build_delay = 20 build_type = "window frame" // Full Windows else if(istype(A, /obj/structure/window/full)) build_cost = 5 build_delay = 50 build_type = "window" if(!build_type) working = FALSE return FALSE if(mode == RFD_DECONSTRUCT && istype(A, /obj/machinery/door) && !A.density) to_chat(user, SPAN_WARNING("\The [build_type] must be closed before you can deconstruct it.")) return FALSE if(stored_matter < build_cost) to_chat(user, SPAN_NOTICE("The \"Matter Units Low\" light on the device blinks yellow.")) flick("[icon_state]-empty", src) return FALSE playsound(get_turf(src), 'sound/items/rfd_start.ogg', 50, FALSE) working = TRUE user.visible_message(SPAN_NOTICE("[user] holds \the [src] towards \the [A]."), SPAN_NOTICE("You start [deconstruct ? "deconstructing" : "constructing"] \a [build_type]...")) var/obj/effect/constructing_effect/rfd_effect = new(get_turf(A), src.build_delay, src.mode) if((build_delay && !do_after(user, build_delay)) || (!useResource(build_cost, user))) working = FALSE rfd_effect.end_animation() return FALSE working = FALSE if(build_delay && !can_use(user, A)) return FALSE if(ispath(build_atom, /turf)) var/original_type = T.type T.ChangeTurf(build_atom) if(istype(T, /turf/simulated/wall)) var/turf/simulated/wall/W = T W.under_turf = original_type else if(ispath(build_atom, /obj)) new build_atom(get_turf(A)) else qdel(A) rfd_effect.end_animation() playsound(get_turf(src), 'sound/items/rfd_end.ogg', 50, FALSE) build_cost = null build_delay = null build_type = null /// So that it resets and any unintended functionality is avoided. build_atom = null return TRUE /obj/item/rfd/construction/borg can_rwall = TRUE /obj/item/rfd/construction/borg/useResource(var/amount, var/mob/user) if(isrobot(user)) var/mob/living/silicon/robot/R = user if(R.cell) var/cost = (amount * 30) if(R.cell.charge >= cost) R.cell.use(cost) return TRUE return FALSE /obj/item/rfd/construction/borg/infinite/useResource() return TRUE /obj/item/rfd/construction/borg/attackby() return /obj/item/rfd/construction/borg/can_use(var/mob/user,var/turf/T) return (user.Adjacent(T) && !user.stat) /obj/item/rfd/construction/mounted/useResource(var/amount, var/mob/user) /// So that a rig with default powercell can build ~2.5x the stuff a fully-loaded RFD-C can. var/cost = (amount * 130) if(istype(loc, /obj/item/rig_module)) var/obj/item/rig_module/module = loc if(module.holder && module.holder.cell) if(module.holder.cell.charge >= cost) module.holder.cell.use(cost) return TRUE else if(istype(user, /mob/living/heavy_vehicle)) var/obj/item/cell/c = user.get_cell() if(c && c.charge >= cost) c.use(cost) return TRUE return FALSE /obj/item/rfd/construction/mounted/attackby() return /obj/item/rfd/construction/mounted/can_use(var/mob/user,var/turf/T) return (user.Adjacent(T) && !user.stat && !user.restrained()) // // RFD - Service Class // /obj/item/rfd/service name = "\improper Rapid Fabrication Device S-Class" desc = "A RFD, modified to deploy service items." icon_state = "rfd-s" item_state = "rfd-s" /obj/item/rfd/service/Initialize() . = ..() radial_modes = list( "Cigarette" = image(icon = 'icons/obj/clothing/masks.dmi', icon_state = "cigoff"), "Drinking Glass" = image(icon = 'icons/obj/drinks.dmi', icon_state = "glass_empty"), "Paper" = image(icon = 'icons/obj/bureaucracy.dmi', icon_state = "paper"), "Pen" = image(icon = 'icons/obj/bureaucracy.dmi', icon_state = "pen"), "Dice Pack" = image(icon = 'icons/obj/dice.dmi', icon_state = "dicebag"), ) /obj/item/rfd/service/attack_self(mob/user) var/current_mode = RADIAL_INPUT(user, radial_modes) switch(current_mode) if("Cigarette") mode = 1 if("Drinking Glass") mode = 2 if("Paper") mode = 3 if("Pen") mode = 4 if("Dice Pack") mode = 5 if(current_mode) to_chat(user, SPAN_NOTICE("You switch the selection dial to \"[current_mode]\".")) playsound(src.loc, 'sound/effects/pop.ogg', 50, 0) /obj/item/rfd/service/resolve_attackby(atom/A, mob/user as mob, var/click_parameters) if(istype(user,/mob/living/silicon/robot)) var/mob/living/silicon/robot/R = user if(R.stat || !R.cell || R.cell.charge <= 0) return else if(stored_matter <= 0) if(last_fail <= world.time - 20) // Spam limiter. last_fail = world.time to_chat(user, SPAN_NOTICE("The \"Matter Units Low\" light on the device blinks yellow.")) playsound(get_turf(src), 'sound/items/rfd_empty.ogg', 50, FALSE) flick("[icon_state]-empty", src) return if(!istype(A, /obj/structure/table) && !istype(A, /turf/simulated/floor)) return playsound(src.loc, 'sound/items/rfd_dispense.ogg', 20, FALSE) sleep(2) var/used_energy = 0 var/obj/product switch(mode) if(1) product = new /obj/item/clothing/mask/smokable/cigarette() used_energy = 10 if(2) product = new /obj/item/reagent_containers/food/drinks/drinkingglass() used_energy = 50 if(3) product = new /obj/item/paper() used_energy = 10 if(4) product = new /obj/item/pen() used_energy = 50 if(5) product = new /obj/item/storage/pill_bottle/dice() used_energy = 200 to_chat(user, "Dispensing [product ? product : "product"]...") product.forceMove(get_turf(A)) playsound(src.loc, 'sound/machines/click.ogg' , 10, 1) if(istype(A, /obj/structure/table)) var/obj/structure/table/T = A T.auto_align(product, click_parameters) update_icon() if(isrobot(user)) var/mob/living/silicon/robot/R = user if(R.cell) R.cell.use(used_energy) else stored_matter-- to_chat(user, "The RSF now holds [stored_matter]/30 fabrication-units.") /*####################### RFD - Mining Class #######################*/ #define RFD_MINING_MODE_MINE_TRACK "Mine Track" #define RFD_MINING_MODE_MINE_CART "Mine Cart" #define RFD_MINING_MODE_MINE_CART_ENGINE "Mine Cart Engine" /obj/item/rfd/mining name = "\improper Rapid Fabrication Device M-Class" desc = "A RFD, modified to deploy mine tracks." icon_state = "rfd-m" item_state = "rfd-m" /obj/item/rfd/mining/feedback_hints(mob/user, distance, is_adjacent) . += ..() . += SPAN_WARNING("The printed mining units have to either be placed down in order, or linked manually after deployment.") /obj/item/rfd/mining/Initialize() . = ..() radial_modes = list( RFD_MINING_MODE_MINE_TRACK = image(/obj/structure/track), RFD_MINING_MODE_MINE_CART_ENGINE = image(/obj/vehicle/train/cargo/engine/mining), RFD_MINING_MODE_MINE_CART = image(/obj/vehicle/train/cargo/trolley/mining) ) /obj/item/rfd/mining/attack_self(mob/user) var/current_mode = RADIAL_INPUT(user, radial_modes) if(current_mode in radial_modes) mode = current_mode if(current_mode) to_chat(user, SPAN_NOTICE("You switch the selection dial to \"[current_mode]\".")) /obj/item/rfd/mining/afterattack(atom/target, mob/user, proximity_flag, click_parameters) if(!proximity_flag) return //Handle consumption of resources, either from the RFD matter cartridge or from a robot cell if(isrobot(user)) var/mob/living/silicon/robot/R = user if(R.stat || !R.cell || R.cell.charge <= 200) if(last_fail <= world.time - 20) //Spam limiter. last_fail = world.time to_chat(user, SPAN_WARNING("You are unable to produce enough charge to use \the [src]!")) playsound(get_turf(src), 'sound/items/rfd_empty.ogg', 50, FALSE) flick("[icon_state]-empty", src) return else if(stored_matter <= 0) if(last_fail <= world.time - 20) //Spam limiter. last_fail = world.time to_chat(user, SPAN_NOTICE("The \"Matter Units Low\" light on the device blinks yellow.")) playsound(get_turf(src), 'sound/items/rfd_empty.ogg', 50, FALSE) flick("[icon_state]-empty", src) return //Can only be used on floors if(!istype(target, /turf/simulated/floor) && !istype(target, /turf/unsimulated/floor)) return var/item_to_make = null switch(mode) if(RFD_MINING_MODE_MINE_TRACK) if(locate(/obj/structure/track) in target) to_chat(user, SPAN_WARNING("There is already a track on \the [target]!")) return item_to_make = /obj/structure/track if(RFD_MINING_MODE_MINE_CART_ENGINE) //Check that there's a track if(!(locate(/obj/structure/track) in target)) to_chat(user, SPAN_WARNING("There is no track on \the [target]!")) return //Check that there's no trolley or engine already if(locate(/obj/vehicle/train/cargo) in target) to_chat(user, SPAN_WARNING("There is already an engine or trolley on \the [target]!")) return item_to_make = /obj/vehicle/train/cargo/engine/mining if(RFD_MINING_MODE_MINE_CART) //Check that there's a track if(!(locate(/obj/structure/track) in target)) to_chat(user, SPAN_WARNING("There is no track on \the [target]!")) return //Check that there's no trolley or engine already if(locate(/obj/vehicle/train/cargo) in target) to_chat(user, SPAN_WARNING("There is already an engine or trolley on \the [target]!")) return item_to_make = /obj/vehicle/train/cargo/trolley/mining else to_chat(user, SPAN_WARNING("There's no valid mode selected for this RFD!")) return playsound(src.loc, 'sound/machines/click.ogg', 10, 1) new item_to_make(get_turf(target)) to_chat(user, SPAN_NOTICE("You deploy \a [mode] on \the [target].")) update_icon() //In case of success, consume the resources if(isrobot(user)) var/mob/living/silicon/robot/R = user if(R.cell) R.cell.use(200) else stored_matter-- to_chat(user, SPAN_NOTICE("The RFD now holds [stored_matter]/[initial(stored_matter)] fabrication-units.")) //As they start full, initial(stored_matter) also gives the maximum return TRUE #undef RFD_MINING_MODE_MINE_TRACK #undef RFD_MINING_MODE_MINE_CART #undef RFD_MINING_MODE_MINE_CART_ENGINE // Malf AI RFD Transformer /obj/item/rfd/transformer name = "\improper Rapid Fabrication Device T-Class" desc = "A device used for rapid fabrication, modified to deploy a transformer. It can only be used once and there can not be more than one made." stored_matter = 30 var/malftransformermade = 0 /obj/item/rfd/transformer/feedback_hints(mob/user, distance, is_adjacent) . += ..() if(loc == user) if(malftransformermade) . += "There is already a transformer machine made!" else . += "It is ready to deploy a transformer machine." /obj/item/rfd/transformer/attack_self(mob/user) return /obj/item/rfd/transformer/afterattack(atom/A, mob/user as mob, proximity) if(!proximity) return if(istype(user,/mob/living/silicon/robot)) var/mob/living/silicon/robot/R = user if(R.stat || !R.cell || R.cell.charge <= 0) return if(!istype(A, /turf/simulated/floor)) return if(malftransformermade) if(last_fail <= world.time - 20) //Spam limiter. last_fail = world.time to_chat(user, "There is already a transformer machine made!") playsound(get_turf(src), 'sound/items/rfd_empty.ogg', 50, FALSE) flick("[icon_state]-empty", src) return playsound(src.loc, 'sound/machines/click.ogg', 10, 1) var/used_energy = 100 to_chat(user, "Fabricating machine...") playsound(get_turf(src), 'sound/items/rfd_start.ogg', 50, FALSE) if(do_after(user, 30 SECONDS, src, DO_UNIQUE)) var/obj/product = new /obj/machinery/transformer malftransformermade = 1 product.forceMove(get_turf(A)) stored_matter = 0 update_icon() playsound(get_turf(src), 'sound/items/rfd_end.ogg', 50, FALSE) if(isrobot(user)) var/mob/living/silicon/robot/R = user if(R.cell) R.cell.use(used_energy) return TRUE // // RFD - Piping Class // #define STANDARD_PIPE "Standard Pipes" #define SUPPLY_PIPE "Supply Pipes" #define SCRUBBER_PIPE "Scrubber Pipes" #define FUEL_PIPE "Fuel Pipes" #define AUX_PIPE "Auxiliary Pipes" #define DEVICES "Devices" /obj/item/rfd/piping name = "\improper Rapid Fabrication Device P-Class" desc = "A heavily modified RFD, modified to construct pipes and piping accessories." icon_state = "rfd-p" item_state = "rfd-p" modes = list(STANDARD_PIPE, SUPPLY_PIPE, SCRUBBER_PIPE, FUEL_PIPE, AUX_PIPE, DEVICES) var/selected_mode = STANDARD_PIPE /// Used in the examine proc to see what you're putting down at a glance var/pipe_examine = "Pipe" /// Default is standard pipe, used for the new pipe creation var/selected_pipe = 0 /// This RFD only uses 1 unit of power per pipe, but can be modified if need be in future. build_cost = 1 build_delay = 10 // The numbers below refer to the numberized designator for each pipe, which is used in obj/item/pipe's new // Take a look at code\game\machinery\pipe\construction.dm line 69 for more information. - Geeves var/list/standard_pipes = list( "Pipe" = PIPE_SIMPLE_STRAIGHT, "Bent Pipe" = PIPE_SIMPLE_BENT, "Manifold" = PIPE_MANIFOLD, "Manual Valve" = PIPE_MVALVE, "4-Way Manifold" = PIPE_MANIFOLD4W, "Manual T-Valve" = PIPE_MTVALVE, "Upward Pipe" = PIPE_UP, "Downward Pipe" = PIPE_DOWN ) var/list/supply_pipes = list( "Pipe" = PIPE_SUPPLY_STRAIGHT, "Bent Pipe" = PIPE_SUPPLY_BENT, "Manifold" = PIPE_SUPPLY_MANIFOLD, "4-Way Manifold" = PIPE_SUPPLY_MANIFOLD4W, "Upward Pipe" = PIPE_SUPPLY_UP, "Downward Pipe" = PIPE_SUPPLY_DOWN ) var/list/scrubber_pipes = list( "Pipe" = PIPE_SCRUBBERS_STRAIGHT, "Bent Pipe" = PIPE_SCRUBBERS_BENT, "Manifold" = PIPE_SCRUBBERS_MANIFOLD, "4-Way Manifold" = PIPE_SCRUBBERS_MANIFOLD4W, "Upward Pipe" = PIPE_SCRUBBERS_UP, "Downward Pipe" = PIPE_SCRUBBERS_DOWN ) var/list/fuel_pipes = list( "Pipe" = PIPE_FUEL_STRAIGHT, "Bent Pipe" = PIPE_FUEL_BENT, "Manifold" = PIPE_FUEL_MANIFOLD, "4-Way Manifold" = PIPE_FUEL_MANIFOLD4W, "Upward Pipe" = PIPE_FUEL_UP, "Downward Pipe" = PIPE_FUEL_DOWN ) var/list/aux_pipes = list( "Pipe" = PIPE_AUX_STRAIGHT, "Bent Pipe" = PIPE_AUX_BENT, "Manifold" = PIPE_AUX_MANIFOLD, "4-Way Manifold" = PIPE_AUX_MANIFOLD4W, "Upward Pipe" = PIPE_AUX_UP, "Downward Pipe" = PIPE_AUX_DOWN ) var/list/devices = list( "Universal Pipe Adapter" = PIPE_UNIVERSAL, "Connector" = PIPE_CONNECTOR, "Unary Vent" = PIPE_UVENT, "Auxiliary Unary Vent" = PIPE_AUX_UVENT, "Scrubber" = PIPE_SCRUBBER, "Gas Pump" = PIPE_PUMP, "Fuel Gas Pump" = PIPE_PUMP_FUEL, "Pressure Regulator" = PIPE_PASSIVE_GATE, "High Power Gas Pump" = PIPE_VOLUME_PUMP, "Gas Filter" = PIPE_GAS_FILTER_M, "Omni Gas Filter" = PIPE_OMNI_FILTER, "Omni Gas Mixer" = PIPE_OMNI_MIXER, "Gas Meter" = "gasmeter" ) /obj/item/rfd/piping/mechanics_hints(mob/user, distance, is_adjacent) . += ..() . += "Use in-hand to change pipe selection." . += "ALT-click to change pipe category." /obj/item/rfd/piping/feedback_hints(mob/user, distance, is_adjacent) . += ..() . += "Selected pipe category: [selected_mode]." . += "Selected pipe: [pipe_examine]." /obj/item/rfd/piping/afterattack(atom/A, mob/user, proximity) if(!proximity || !isturf(A)) return if(istype(get_area(A), /area/shuttle) || istype(get_area(A), /turf/space)) to_chat(user, SPAN_WARNING("You can't materialize a pipe here!")) return FALSE var/turf/target_turf = get_turf(A) if(!is_station_level(target_turf.z)) to_chat(user, SPAN_WARNING("You can't materialize a pipe on this level!")) return FALSE return do_pipe(target_turf, user) /obj/item/rfd/piping/proc/do_pipe(var/turf/target_turf, var/mob/user) if(working) return FALSE if(stored_matter < build_cost) to_chat(user, SPAN_NOTICE("The \"Matter Units Low\" light on the device blinks yellow.")) playsound(get_turf(src), 'sound/items/rfd_empty.ogg', 50, FALSE) flick("[icon_state]-empty", src) return FALSE playsound(get_turf(src), 'sound/items/rfd_start.ogg', 50, FALSE) working = TRUE user.visible_message(SPAN_NOTICE("[user] holds \the [src] towards \the [target_turf]."), SPAN_NOTICE("You start laying down a pipe...")) if((build_delay && !do_after(user, build_delay)) || (!useResource(build_cost, user))) playsound(get_turf(src), 'sound/items/rfd_interrupt.ogg', 50, FALSE) working = FALSE return FALSE if(build_delay && !can_use(user, target_turf)) return FALSE // Special case for meters- technically it's not a pipe, we can't create a new /obj/item/pipe. Duh. if(selected_pipe == "gasmeter") new /obj/item/pipe_meter(target_turf) else // Special case handling for bent pipes. They require a non-cardinal direction var/pipe_dir = NORTH if(selected_pipe in list(PIPE_SIMPLE_BENT, PIPE_SUPPLY_BENT, PIPE_SCRUBBERS_BENT, PIPE_FUEL_BENT, PIPE_AUX_BENT)) pipe_dir = NORTHEAST new /obj/item/pipe(target_turf, selected_pipe, pipe_dir) playsound(get_turf(src), 'sound/items/rfd_end.ogg', 50, FALSE) working = FALSE return TRUE /obj/item/rfd/piping/attack_self(mob/user) playsound(get_turf(src), 'sound/weapons/laser_safetyon.ogg', 50, FALSE) var/list/pipe_selection = list() switch(selected_mode) if(STANDARD_PIPE) pipe_selection = standard_pipes if(SUPPLY_PIPE) pipe_selection = supply_pipes if(SCRUBBER_PIPE) pipe_selection = scrubber_pipes if(FUEL_PIPE) pipe_selection = fuel_pipes if(AUX_PIPE) pipe_selection = aux_pipes if(DEVICES) pipe_selection = devices pipe_examine = tgui_input_list(user, "Choose the pipe you want to deploy.", "Pipe Selection", pipe_selection, selected_pipe) selected_pipe = pipe_selection[pipe_examine] /obj/item/rfd/piping/AltClick(mob/user) selected_mode = tgui_input_list(user, "Choose the category you want to change to.", "Pipe Categories", modes, selected_mode) switch(selected_mode) if(STANDARD_PIPE) pipe_examine = "Pipe" selected_pipe = PIPE_SIMPLE_STRAIGHT if(SUPPLY_PIPE) pipe_examine = "Pipe" selected_pipe = PIPE_SUPPLY_STRAIGHT if(SCRUBBER_PIPE) pipe_examine = "Pipe" selected_pipe = PIPE_SCRUBBERS_STRAIGHT if(FUEL_PIPE) pipe_examine = "Pipe" selected_pipe = PIPE_FUEL_STRAIGHT if(AUX_PIPE) pipe_examine = "Pipe" selected_pipe = PIPE_AUX_STRAIGHT if(DEVICES) pipe_examine = "Universal Pipe Adapter" selected_pipe = PIPE_UNIVERSAL /obj/item/rfd/piping/borg/useResource(var/amount, var/mob/user) if(isrobot(user)) var/mob/living/silicon/robot/R = user if(R.cell) var/cost = amount * 30 if(R.cell.charge >= cost) R.cell.use(cost) return TRUE return FALSE /obj/item/rfd/piping/borg/attackby() return #undef STANDARD_PIPE #undef SUPPLY_PIPE #undef SCRUBBER_PIPE #undef FUEL_PIPE #undef AUX_PIPE #undef DEVICES #undef MATERIALIZATION_FAIL_MESSAGE