diff --git a/_maps/configs/independent_kilo.json b/_maps/configs/independent_kilo.json index 0890ba4a9cef..9ff4ccfbf191 100644 --- a/_maps/configs/independent_kilo.json +++ b/_maps/configs/independent_kilo.json @@ -31,7 +31,7 @@ }, "Deckhand": { "outfit": "/datum/outfit/job/independent/assistant", - "slots": 2 + "slots": 1 } }, "enabled": true diff --git a/_maps/configs/independent_mudskipper.json b/_maps/configs/independent_mudskipper.json index 8db7b5668e03..469230d752a3 100644 --- a/_maps/configs/independent_mudskipper.json +++ b/_maps/configs/independent_mudskipper.json @@ -15,7 +15,7 @@ "SPACE" ], "map_path": "_maps/shuttles/independent/independent_mudskipper.dmm", - "limit": 1, + "limit": 2, "starting_funds": 1500, "job_slots": { "Salvage Leader": { diff --git a/_maps/configs/inteq_vaquero.json b/_maps/configs/inteq_vaquero.json index 232562369a3d..2b0bed8bfe98 100644 --- a/_maps/configs/inteq_vaquero.json +++ b/_maps/configs/inteq_vaquero.json @@ -39,7 +39,7 @@ }, "Recruit": { "outfit": "/datum/outfit/job/inteq/assistant", - "slots": 2 + "slots": 1 } }, "enabled": true diff --git a/_maps/shuttles/independent/independent_junker.dmm b/_maps/shuttles/independent/independent_junker.dmm index 7819d04ec1c2..0ae98ef37fe2 100644 --- a/_maps/shuttles/independent/independent_junker.dmm +++ b/_maps/shuttles/independent/independent_junker.dmm @@ -2284,7 +2284,6 @@ /turf/closed/wall/r_wall, /area/ship/maintenance/port) "Ro" = ( -/obj/machinery/pipedispenser/disposal, /obj/item/reagent_containers/food/drinks/mug/tea{ pixel_y = 8; pixel_x = -7 @@ -2305,6 +2304,7 @@ /obj/machinery/atmospherics/components/unary/vent_pump/on/layer2{ dir = 1 }, +/obj/machinery/pipedispenser, /turf/open/floor/plating, /area/ship/maintenance/central) "RQ" = ( diff --git a/_maps/shuttles/inteq/inteq_colossus.dmm b/_maps/shuttles/inteq/inteq_colossus.dmm index 482d6999b28c..74ac142692c6 100644 --- a/_maps/shuttles/inteq/inteq_colossus.dmm +++ b/_maps/shuttles/inteq/inteq_colossus.dmm @@ -653,9 +653,9 @@ /turf/open/floor/plasteel/telecomms_floor, /area/ship/bridge) "gH" = ( -/obj/machinery/porta_turret/ship/ballistic{ - dir = 6; - id = "colossus_grid" +/obj/machinery/porta_turret/ship/inteq{ + id = "colossus_grid"; + dir = 4 }, /turf/closed/wall/mineral/plastitanium/nodiagonal, /area/ship/crew) @@ -1138,9 +1138,9 @@ /turf/open/floor/plasteel/patterned/grid, /area/ship/hallway/fore) "mb" = ( -/obj/machinery/porta_turret/ship/ballistic{ - dir = 5; - id = "colossus_grid" +/obj/machinery/porta_turret/ship/inteq/light{ + id = "colossus_grid"; + dir = 5 }, /turf/closed/wall/mineral/plastitanium/nodiagonal, /area/ship/hallway/port) @@ -1734,9 +1734,9 @@ /turf/open/floor/plasteel/dark, /area/ship/crew/office) "sT" = ( -/obj/machinery/porta_turret/ship/ballistic{ - dir = 5; - id = "colossus_grid" +/obj/machinery/porta_turret/ship/inteq/light{ + id = "colossus_grid"; + dir = 5 }, /turf/closed/wall/mineral/plastitanium, /area/ship/crew) @@ -2068,9 +2068,9 @@ /turf/closed/wall/mineral/plastitanium/nodiagonal, /area/ship/cargo) "vJ" = ( -/obj/machinery/porta_turret/ship/ballistic{ - dir = 5; - id = "colossus_grid" +/obj/machinery/porta_turret/ship/inteq{ + id = "colossus_grid"; + dir = 5 }, /turf/closed/wall/mineral/plastitanium, /area/ship/maintenance/port) @@ -2442,9 +2442,9 @@ /turf/open/floor/plating, /area/ship/maintenance/port) "Bi" = ( -/obj/machinery/porta_turret/ship/ballistic{ - dir = 9; - id = "colossus_grid" +/obj/machinery/porta_turret/ship/inteq{ + id = "colossus_grid"; + dir = 9 }, /turf/closed/wall/mineral/plastitanium/nodiagonal, /area/ship/crew/office) @@ -3320,8 +3320,9 @@ /turf/closed/wall/mineral/plastitanium/nodiagonal, /area/ship/security/armory) "Ll" = ( -/obj/machinery/porta_turret/ship/ballistic{ - dir = 5 +/obj/machinery/porta_turret/ship/inteq{ + id = "colossus_grid"; + dir = 4 }, /turf/closed/wall/mineral/plastitanium/nodiagonal, /area/ship/bridge) @@ -3557,7 +3558,8 @@ /turf/open/floor/plasteel/patterned, /area/ship/cargo) "Oa" = ( -/obj/machinery/porta_turret/ship/ballistic{ +/obj/machinery/porta_turret/ship/inteq/light{ + id = "colossus_grid"; dir = 6 }, /turf/closed/wall/mineral/plastitanium, @@ -3630,9 +3632,9 @@ /turf/open/floor/engine/hull/reinforced, /area/ship/maintenance/starboard) "OI" = ( -/obj/machinery/porta_turret/ship/ballistic{ - dir = 6; - id = "colossus_grid" +/obj/machinery/porta_turret/ship/inteq{ + id = "colossus_grid"; + dir = 6 }, /turf/closed/wall/mineral/plastitanium, /area/ship/maintenance/starboard) @@ -3790,9 +3792,9 @@ /turf/open/floor/plating, /area/ship/maintenance/starboard) "Qw" = ( -/obj/machinery/porta_turret/ship/ballistic{ - dir = 10; - id = "colossus_grid" +/obj/machinery/porta_turret/ship/inteq{ + id = "colossus_grid"; + dir = 10 }, /turf/closed/wall/mineral/plastitanium/nodiagonal, /area/ship/security/armory) @@ -3944,9 +3946,9 @@ /turf/open/floor/plasteel/patterned/cargo_one, /area/ship/cargo) "RZ" = ( -/obj/machinery/porta_turret/ship/ballistic{ - dir = 6; - id = "colossus_grid" +/obj/machinery/porta_turret/ship/inteq/light{ + id = "talos_grid"; + dir = 6 }, /turf/closed/wall/mineral/plastitanium, /area/ship/security) diff --git a/_maps/shuttles/inteq/inteq_talos.dmm b/_maps/shuttles/inteq/inteq_talos.dmm index 6b05aa78caaa..2ab9a9405507 100644 --- a/_maps/shuttles/inteq/inteq_talos.dmm +++ b/_maps/shuttles/inteq/inteq_talos.dmm @@ -103,7 +103,7 @@ /turf/open/floor/circuit/telecomms/mainframe, /area/ship/engineering/communications) "aC" = ( -/obj/machinery/porta_turret/ship/weak{ +/obj/machinery/porta_turret/ship/inteq{ dir = 5; id = "talos_grid" }, @@ -849,7 +849,7 @@ /turf/open/floor/plating/airless, /area/ship/storage/port) "fs" = ( -/obj/machinery/porta_turret/ship/weak{ +/obj/machinery/porta_turret/ship/inteq{ dir = 5; id = "talos_grid" }, @@ -2689,14 +2689,14 @@ /turf/open/floor/plasteel/tech/grid, /area/ship/crew/cryo) "qt" = ( -/obj/machinery/porta_turret/ship/weak{ +/obj/machinery/porta_turret/ship/inteq{ dir = 6; id = "talos_grid" }, /turf/closed/wall/mineral/plastitanium, /area/ship/maintenance/starboard) "qz" = ( -/obj/machinery/porta_turret/ship/weak{ +/obj/machinery/porta_turret/ship/inteq{ dir = 5; id = "talos_grid" }, @@ -4556,9 +4556,9 @@ /turf/open/floor/plasteel/grimy, /area/ship/crew) "Cr" = ( -/obj/machinery/porta_turret/ship/weak{ - dir = 9; - id = "talos_grid" +/obj/machinery/porta_turret/ship/inteq/light{ + id = "talos_grid"; + dir = 9 }, /turf/closed/wall/mineral/plastitanium, /area/ship/engineering/communications) @@ -4821,7 +4821,7 @@ autolinkers = list("hub","processor4","bus"); network = "irmg_commnet" }, -/turf/open/floor/circuit/telecomms/mainframe, +/turf/closed/wall/mineral/plastitanium, /area/ship/engineering/communications) "Ep" = ( /obj/item/trash/can, @@ -4853,9 +4853,9 @@ /turf/open/floor/plasteel/telecomms_floor, /area/ship/engineering/communications) "ED" = ( -/obj/machinery/porta_turret/ship/weak{ - dir = 10; - id = "talos_grid" +/obj/machinery/porta_turret/ship/inteq/light{ + id = "talos_grid"; + dir = 10 }, /turf/closed/wall/mineral/plastitanium, /area/ship/storage) @@ -6624,7 +6624,7 @@ /turf/open/floor/plasteel/telecomms_floor, /area/ship/engineering/communications) "Rf" = ( -/obj/machinery/porta_turret/ship/weak{ +/obj/machinery/porta_turret/ship/inteq{ dir = 6; id = "talos_grid" }, @@ -7491,7 +7491,7 @@ /turf/open/floor/plating, /area/ship/engineering/engine) "WN" = ( -/obj/machinery/porta_turret/ship/weak{ +/obj/machinery/porta_turret/ship/inteq{ dir = 6; id = "talos_grid" }, diff --git a/_maps/shuttles/inteq/inteq_vaquero.dmm b/_maps/shuttles/inteq/inteq_vaquero.dmm index 336bf5792208..92e024ba7bf6 100644 --- a/_maps/shuttles/inteq/inteq_vaquero.dmm +++ b/_maps/shuttles/inteq/inteq_vaquero.dmm @@ -1933,7 +1933,7 @@ /turf/open/floor/plasteel/dark, /area/ship/security) "DT" = ( -/obj/machinery/porta_turret/ship/weak{ +/obj/machinery/porta_turret/ship/inteq{ dir = 6; id = "vaquero_grid" }, @@ -2027,7 +2027,7 @@ /turf/open/floor/plasteel/dark, /area/ship/crew/office) "Fm" = ( -/obj/machinery/porta_turret/ship/weak{ +/obj/machinery/porta_turret/ship/inteq{ dir = 5; id = "vaquero_grid" }, @@ -2523,7 +2523,7 @@ /turf/open/floor/plasteel/patterned/grid, /area/ship/hallway/central) "NO" = ( -/obj/machinery/porta_turret/ship/weak{ +/obj/machinery/porta_turret/ship/inteq{ dir = 6; id = "vaquero_grid" }, @@ -2957,7 +2957,7 @@ port_direction = 8; preferred_direction = 4 }, -/obj/machinery/porta_turret/ship/weak{ +/obj/machinery/porta_turret/ship/inteq{ dir = 5; id = "vaquero_grid" }, diff --git a/_maps/shuttles/nanotrasen/nanotrasen_delta.dmm b/_maps/shuttles/nanotrasen/nanotrasen_delta.dmm index 00967afb927e..351e8e2df037 100644 --- a/_maps/shuttles/nanotrasen/nanotrasen_delta.dmm +++ b/_maps/shuttles/nanotrasen/nanotrasen_delta.dmm @@ -1371,9 +1371,9 @@ /turf/open/floor/plasteel/tech/techmaint, /area/ship/engineering) "jH" = ( -/obj/machinery/porta_turret/ship/weak{ - dir = 9; - id = "delta_grid" +/obj/machinery/porta_turret/ship/nt/light{ + id = "delta_grid"; + dir = 9 }, /turf/closed/wall/mineral/titanium, /area/ship/bridge) @@ -2891,9 +2891,9 @@ /turf/open/floor/plasteel/white, /area/ship/science/robotics) "WG" = ( -/obj/machinery/porta_turret/ship/weak{ - dir = 4; - id = "delta_grid" +/obj/machinery/porta_turret/ship/nt/light{ + id = "delta_grid"; + dir = 4 }, /turf/closed/wall/mineral/titanium, /area/ship/bridge) @@ -3018,9 +3018,9 @@ /turf/open/floor/plasteel/white, /area/ship/science/robotics) "YZ" = ( -/obj/machinery/porta_turret/ship/weak{ - dir = 10; - id = "delta_grid" +/obj/machinery/porta_turret/ship/nt/light{ + id = "delta_grid"; + dir = 10 }, /turf/closed/wall/mineral/titanium, /area/ship/bridge) diff --git a/_maps/shuttles/nanotrasen/nanotrasen_meta.dmm b/_maps/shuttles/nanotrasen/nanotrasen_meta.dmm index eaf4abc2b9b3..95b61c204b54 100644 --- a/_maps/shuttles/nanotrasen/nanotrasen_meta.dmm +++ b/_maps/shuttles/nanotrasen/nanotrasen_meta.dmm @@ -1680,9 +1680,10 @@ /turf/open/floor/plating, /area/ship/cargo) "jo" = ( -/obj/machinery/porta_turret/ship/weak{ - dir = 4; - id = "meta_grid" +/obj/machinery/porta_turret/ship/nt/light{ + id = "meta_grid"; + pixel_y = 0; + dir = 4 }, /turf/closed/wall/mineral/titanium, /area/ship/crew) @@ -2206,9 +2207,10 @@ /turf/open/floor/plasteel/dark, /area/ship/cargo) "uT" = ( -/obj/machinery/porta_turret/ship/weak{ - dir = 4; - id = "meta_grid" +/obj/machinery/porta_turret/ship/nt/light{ + id = "meta_grid"; + pixel_y = 0; + dir = 4 }, /turf/closed/wall/mineral/titanium, /area/ship/crew/canteen/kitchen) @@ -2399,9 +2401,10 @@ /turf/open/floor/plasteel, /area/ship/crew/canteen/kitchen) "yF" = ( -/obj/machinery/porta_turret/ship/weak{ - dir = 1; - id = "meta_grid" +/obj/machinery/porta_turret/ship/nt/light{ + id = "meta_grid"; + pixel_y = 0; + dir = 5 }, /turf/closed/wall/mineral/titanium, /area/ship/engineering) @@ -3079,9 +3082,10 @@ /turf/open/floor/plating, /area/ship/engineering) "Lo" = ( -/obj/machinery/porta_turret/ship/weak{ - dir = 2; - id = "meta_grid" +/obj/machinery/porta_turret/ship/nt/light{ + id = "meta_grid"; + pixel_y = 0; + dir = 6 }, /turf/closed/wall/mineral/titanium, /area/ship/engineering) @@ -3480,16 +3484,18 @@ /turf/open/floor/plasteel/dark, /area/ship/cargo) "TR" = ( -/obj/machinery/porta_turret/ship/weak{ - dir = 2; - id = "meta_grid" +/obj/machinery/porta_turret/ship/nt/light{ + id = "meta_grid"; + pixel_y = 0; + dir = 10 }, /turf/closed/wall/mineral/titanium, /area/ship/crew/canteen) "TV" = ( -/obj/machinery/porta_turret/ship/weak{ - dir = 1; - id = "meta_grid" +/obj/machinery/porta_turret/ship/nt/light{ + id = "meta_grid"; + pixel_y = 0; + dir = 9 }, /turf/closed/wall/mineral/titanium, /area/ship/crew) diff --git a/_maps/shuttles/subshuttles/inteq_anvil.dmm b/_maps/shuttles/subshuttles/inteq_anvil.dmm index 002ddfe6d0d3..61d7946fb794 100644 --- a/_maps/shuttles/subshuttles/inteq_anvil.dmm +++ b/_maps/shuttles/subshuttles/inteq_anvil.dmm @@ -191,14 +191,6 @@ "w" = ( /turf/template_noop, /area/template_noop) -"x" = ( -/obj/machinery/porta_turret/ship/weak{ - faction = list("playerInteq","turret"); - dir = 9; - id = "anvil_grid" - }, -/turf/closed/wall/mineral/plastitanium/nodiagonal, -/area/ship/bridge) "y" = ( /obj/machinery/power/terminal, /obj/structure/cable{ @@ -387,9 +379,8 @@ /turf/open/floor/plasteel/dark, /area/ship/bridge) "T" = ( -/obj/machinery/porta_turret/ship/weak{ - faction = list("playerInteq","turret"); - dir = 10; +/obj/machinery/porta_turret/ship/inteq/light{ + dir = 8; id = "anvil_grid" }, /turf/closed/wall/mineral/plastitanium/nodiagonal, @@ -436,7 +427,7 @@ (1,1,1) = {" w -x +T X u Q diff --git a/check_regex.yaml b/check_regex.yaml index eadd642f0676..41174bd9aa22 100644 --- a/check_regex.yaml +++ b/check_regex.yaml @@ -31,14 +31,14 @@ standards: - exactly: [4, "/mob text paths", '"/mob'] - exactly: [42, "/obj text paths", '"/obj'] - exactly: [0, "/turf text paths", '"/turf'] - - exactly: [117, "text2path uses", "text2path"] + - exactly: [115, "text2path uses", "text2path"] - exactly: [18, "world<< uses", 'world[ \t]*<<'] - exactly: [0, "world.log<< uses", 'world.log[ \t]*<<'] - exactly: [ - 266, + 262, "non-bitwise << uses", '(?You cut apart \the [src].", "You cut apart \the [src].") + deconstruct() + return TRUE /obj/structure/frame/machine name = "machine frame" diff --git a/code/game/machinery/deployable.dm b/code/game/machinery/deployable.dm index 41760633726e..3dedf5887d0c 100644 --- a/code/game/machinery/deployable.dm +++ b/code/game/machinery/deployable.dm @@ -79,6 +79,14 @@ return return ..() +/obj/structure/barricade/wooden/deconstruct_act(mob/living/user, obj/item/I) + . = ..() + if(!I.tool_start_check(user, amount=0)) + return FALSE + if (I.use_tool(src, user, 2 SECONDS, volume=0)) + to_chat(user, "You cut apart [src].") + deconstruct() + return TRUE /obj/structure/barricade/wooden/crude name = "crude plank barricade" diff --git a/code/game/machinery/doors/airlock.dm b/code/game/machinery/doors/airlock.dm index 4c27a08e64a7..3412321b380b 100644 --- a/code/game/machinery/doors/airlock.dm +++ b/code/game/machinery/doors/airlock.dm @@ -1243,6 +1243,21 @@ return INVOKE_ASYNC(src, (density ? PROC_REF(open) : PROC_REF(close)), 2) +/obj/machinery/door/airlock/deconstruct_act(mob/living/user, obj/item/I) + . = ..() + if(!I.tool_start_check(user, amount=0)) + return FALSE + var/decon_time = 5 SECONDS + if(welded) + decon_time += 5 SECONDS + if(locked) + decon_time += 5 SECONDS + if(seal) + decon_time += 15 SECONDS + if (I.use_tool(src, user, decon_time, volume=100)) + to_chat(user, "You cut open the [src].") + deconstruct(FALSE, user) + return TRUE /obj/machinery/door/airlock/open(forced=0) if(operating || welded || locked || seal || !wires) diff --git a/code/game/machinery/pipe/pipe_dispenser.dm b/code/game/machinery/pipe/pipe_dispenser.dm index 0772e483a536..f21b7a59e035 100644 --- a/code/game/machinery/pipe/pipe_dispenser.dm +++ b/code/game/machinery/pipe/pipe_dispenser.dm @@ -1,65 +1,120 @@ +#define ATMOS_CATEGORY 0 +#define DISPOSALS_CATEGORY 1 +#define TRANSIT_CATEGORY 2 + + /obj/machinery/pipedispenser name = "pipe dispenser" icon = 'icons/obj/stationobjs.dmi' icon_state = "pipe_d" desc = "Dispenses countless types of pipes. Very useful if you need pipes." + layer = GATEWAY_UNDERLAY_LAYER //so it renders underneath dispensed disposals density = TRUE circuit = /obj/item/circuitboard/machine/pipedispenser interaction_flags_machine = INTERACT_MACHINE_ALLOW_SILICON | INTERACT_MACHINE_OPEN_SILICON | INTERACT_MACHINE_OFFLINE - var/wait = 0 + var/delay = 0 + var/busy = FALSE + var/p_dir = NORTH + var/p_flipped = FALSE + var/category = ATMOS_CATEGORY var/piping_layer = PIPING_LAYER_DEFAULT + var/ducting_layer = DUCT_LAYER_DEFAULT + var/datum/pipe_info/recipe + var/paint_color = "grey" + var/static/datum/pipe_info/first_atmos + var/static/datum/pipe_info/first_disposal + var/static/datum/pipe_info/first_transit + +/obj/machinery/pipedispenser/Initialize() + . = ..() + if(!first_atmos) + first_atmos = GLOB.atmos_pipe_recipes[GLOB.atmos_pipe_recipes[1]][1] + if(!first_disposal) + first_disposal = GLOB.disposal_pipe_recipes[GLOB.disposal_pipe_recipes[1]][1] + if(!first_transit) + first_transit = GLOB.transit_tube_recipes[GLOB.transit_tube_recipes[1]][1] + + recipe = first_atmos + +/obj/machinery/pipedispenser/ui_assets(mob/user) + return list( + get_asset_datum(/datum/asset/spritesheet/pipes), + ) /obj/machinery/pipedispenser/attack_paw(mob/user) return attack_hand(user) -/obj/machinery/pipedispenser/ui_interact(mob/user) +/obj/machinery/pipedispenser/ui_interact(mob/user, datum/tgui/ui) + ui = SStgui.try_update_ui(user, src, ui) + if(!ui) + ui = new(user, src, "PipeDispenser", name) + ui.open() + +/obj/machinery/pipedispenser/ui_data(mob/user) + var/list/data = list( + "category" = category, + "piping_layer" = piping_layer, + "ducting_layer" = ducting_layer, + "preview_rows" = recipe.get_preview(p_dir), + "categories" = list(), + "selected_color" = paint_color, + "paint_colors" = GLOB.pipe_paint_colors + ) + + var/list/recipes + switch(category) + if(ATMOS_CATEGORY) + recipes = GLOB.atmos_pipe_recipes + if(DISPOSALS_CATEGORY) + recipes = GLOB.disposal_pipe_recipes + if(TRANSIT_CATEGORY) + recipes = GLOB.transit_tube_recipes + for(var/c in recipes) + var/list/cat = recipes[c] + var/list/r = list() + for(var/i in 1 to cat.len) + var/datum/pipe_info/info = cat[i] + r += list(list("pipe_name" = info.name, "pipe_index" = i, "selected" = (info == recipe), "all_layers" = info.all_layers)) + data["categories"] += list(list("cat_name" = c, "recipes" = r)) + + return data + +/obj/machinery/pipedispenser/ui_act(action, params) . = ..() - var/dat = "PIPING LAYER: --[piping_layer]++
" - - var/recipes = GLOB.atmos_pipe_recipes - - for(var/category in recipes) - var/list/cat_recipes = recipes[category] - dat += "[category]:" - - user << browse("[src][dat]", "window=pipedispenser") - onclose(user, "pipedispenser") - return - -/obj/machinery/pipedispenser/Topic(href, href_list) - if(..()) - return 1 - var/mob/living/L = usr - if(!anchored || (istype(L) && !(L.mobility_flags & MOBILITY_UI)) || usr.stat != CONSCIOUS || HAS_TRAIT(usr, TRAIT_HANDS_BLOCKED) || !in_range(loc, usr)) - usr << browse(null, "window=pipedispenser") - return 1 - usr.set_machine(src) - add_fingerprint(usr) - if(href_list["makepipe"]) - if(wait < world.time) - var/p_type = text2path(href_list["makepipe"]) - if (!verify_recipe(GLOB.atmos_pipe_recipes, p_type)) - return - var/p_dir = text2num(href_list["dir"]) - var/obj/item/pipe/P = new (loc, p_type, p_dir) - P.setPipingLayer(piping_layer) - P.add_fingerprint(usr) - wait = world.time + 10 - if(href_list["makemeter"]) - if(wait < world.time) - new /obj/item/pipe_meter(loc) - wait = world.time + 15 - if(href_list["layer_up"]) - piping_layer = clamp(++piping_layer, PIPING_LAYER_MIN, PIPING_LAYER_MAX) - if(href_list["layer_down"]) - piping_layer = clamp(--piping_layer, PIPING_LAYER_MIN, PIPING_LAYER_MAX) - return + if(.) + return + + if(!usr.canUseTopic(src, BE_CLOSE)) + return + switch(action) + if("color") + paint_color = params["paint_color"] + if("category") + category = text2num(params["category"]) + switch(category) + if(DISPOSALS_CATEGORY) + recipe = first_disposal + if(ATMOS_CATEGORY) + recipe = first_atmos + if(TRANSIT_CATEGORY) + recipe = first_transit + p_dir = NORTH + if("print") + make_pipe() + if("piping_layer") + piping_layer = text2num(params["piping_layer"]) + if("ducting_layer") + ducting_layer = text2num(params["ducting_layer"]) + if("pipe_type") + var/static/list/recipes + if(!recipes) + recipes = GLOB.disposal_pipe_recipes + GLOB.atmos_pipe_recipes + GLOB.transit_tube_recipes + recipe = recipes[params["category"]][text2num(params["pipe_type"])] + p_dir = NORTH + if("setdir") + p_dir = text2dir(params["dir"]) + p_flipped = text2num(params["flipped"]) + return TRUE /obj/machinery/pipedispenser/attackby(obj/item/W, mob/user, params) add_fingerprint(user) @@ -70,15 +125,6 @@ else return ..() -/obj/machinery/pipedispenser/proc/verify_recipe(recipes, path) - for(var/category in recipes) - var/list/cat_recipes = recipes[category] - for(var/i in cat_recipes) - var/datum/pipe_info/info = i - if (path == info.id) - return TRUE - return FALSE - /obj/machinery/pipedispenser/wrench_act(mob/living/user, obj/item/I) ..() if(default_unfasten_wrench(user, I, 40)) @@ -96,129 +142,77 @@ default_deconstruction_crowbar(I) return TRUE -/obj/machinery/pipedispenser/disposal - name = "disposal pipe dispenser" - icon = 'icons/obj/stationobjs.dmi' - icon_state = "pipe_d" - desc = "Dispenses pipes that will ultimately be used to move trash around." - density = TRUE - - //Allow you to drag-drop disposal pipes and transit tubes into it -/obj/machinery/pipedispenser/disposal/MouseDrop_T(obj/structure/pipe, mob/usr) - if(!usr.incapacitated()) +/obj/machinery/pipedispenser/MouseDrop_T(obj/structure/pipe, mob/usr) + if(usr.incapacitated()) return - if (!istype(pipe, /obj/structure/disposalconstruct) && !istype(pipe, /obj/structure/c_transit_tube) && !istype(pipe, /obj/structure/c_transit_tube_pod)) + if(!istype(pipe, /obj/structure/disposalconstruct) && !istype(pipe, /obj/structure/c_transit_tube) && !istype(pipe, /obj/structure/c_transit_tube_pod)) return - if (get_dist(usr, src) > 1 || get_dist(src,pipe) > 1) + if(get_dist(usr, src) > 1 || get_dist(src,pipe) > 1) return - if (pipe.anchored) + if(pipe.anchored) return qdel(pipe) -/obj/machinery/pipedispenser/disposal/interact(mob/user) - - var/dat = "" - var/recipes = GLOB.disposal_pipe_recipes - - for(var/category in recipes) - var/list/cat_recipes = recipes[category] - dat += "[category]:" - - user << browse("[src][dat]", "window=pipedispenser") - return - - -/obj/machinery/pipedispenser/disposal/Topic(href, href_list) - if(..()) - return 1 - usr.set_machine(src) - add_fingerprint(usr) - if(href_list["dmake"]) - if(wait < world.time) - var/p_type = text2path(href_list["dmake"]) - if (!verify_recipe(GLOB.disposal_pipe_recipes, p_type)) - return - var/obj/structure/disposalconstruct/C = new (loc, p_type) - - if(!C.can_place()) - to_chat(usr, "There's not enough room to build that here!") - qdel(C) - return - if(href_list["dir"]) - C.setDir(text2num(href_list["dir"])) - C.add_fingerprint(usr) - C.update_appearance() - wait = world.time + 15 - return - -//transit tube dispenser -//inherit disposal for the dragging proc -/obj/machinery/pipedispenser/disposal/transit_tube - name = "transit tube dispenser" - icon = 'icons/obj/stationobjs.dmi' - icon_state = "pipe_d" - density = TRUE - desc = "Dispenses pipes that will move beings around." - -/obj/machinery/pipedispenser/disposal/transit_tube/interact(mob/user) - - var/dat = {"Transit Tubes:
-Straight Tube
-Straight Tube with Crossing
-Curved Tube
-Diagonal Tube
-Diagonal Tube with Crossing
-Junction
-Station Equipment:
-Through Tube Station
-Terminus Tube Station
-Transit Tube Pod
-"} - - user << browse("[src][dat]", "window=pipedispenser") - return - - -/obj/machinery/pipedispenser/disposal/transit_tube/Topic(href, href_list) - if(..()) - return 1 - usr.set_machine(src) - add_fingerprint(usr) - if(wait < world.time) - if(href_list["tube"]) - var/tube_type = text2num(href_list["tube"]) - var/obj/structure/C - switch(tube_type) - if(TRANSIT_TUBE_STRAIGHT) - C = new /obj/structure/c_transit_tube(loc) - if(TRANSIT_TUBE_STRAIGHT_CROSSING) - C = new /obj/structure/c_transit_tube/crossing(loc) - if(TRANSIT_TUBE_CURVED) - C = new /obj/structure/c_transit_tube/curved(loc) - if(TRANSIT_TUBE_DIAGONAL) - C = new /obj/structure/c_transit_tube/diagonal(loc) - if(TRANSIT_TUBE_DIAGONAL_CROSSING) - C = new /obj/structure/c_transit_tube/diagonal/crossing(loc) - if(TRANSIT_TUBE_JUNCTION) - C = new /obj/structure/c_transit_tube/junction(loc) - if(TRANSIT_TUBE_STATION) - C = new /obj/structure/c_transit_tube/station(loc) - if(TRANSIT_TUBE_TERMINUS) - C = new /obj/structure/c_transit_tube/station/reverse(loc) - if(TRANSIT_TUBE_POD) - C = new /obj/structure/c_transit_tube_pod(loc) - if(C) - C.add_fingerprint(usr) - wait = world.time + 15 - return +/obj/machinery/pipedispenser/proc/make_pipe(mob/user) + if(busy) + src.visible_message(span_warning("[src] is busy.")) + return + var/queued_p_type = recipe.id + var/queued_p_dir = p_dir + var/queued_p_flipped = p_flipped + switch(category) + if(ATMOS_CATEGORY) + if(recipe.type == /datum/pipe_info/meter) + new /obj/item/pipe_meter(loc) + on_make_pipe() + else + if(recipe.all_layers == FALSE && (piping_layer == 1 || piping_layer == 5)) + src.visible_message(span_warning("[src] can't print this object on the layer...")) + return + var/obj/machinery/atmospherics/path = queued_p_type + var/pipe_item_type = initial(path.construction_type) || /obj/item/pipe + var/obj/item/pipe/P = new pipe_item_type(loc, queued_p_type, queued_p_dir) + on_make_pipe() + + if(queued_p_flipped && istype(P, /obj/item/pipe/trinary/flippable)) + var/obj/item/pipe/trinary/flippable/F = P + F.flipped = queued_p_flipped + + P.update() + P.setPipingLayer(piping_layer) + if(ispath(path, /obj/machinery/atmospherics/pipe) && !findtext("[queued_p_type]", "layer_manifold")) + P.add_atom_colour(GLOB.pipe_paint_colors[paint_color], FIXED_COLOUR_PRIORITY) + + if(DISPOSALS_CATEGORY) //Making disposals pipes + new /obj/structure/disposalconstruct(loc, queued_p_type, queued_p_dir, queued_p_flipped) + on_make_pipe() + return + + if(TRANSIT_CATEGORY) //Making transit tubes + if(istype(queued_p_type, /obj/structure/c_transit_tube_pod)) + new /obj/structure/c_transit_tube_pod(loc) + on_make_pipe() + else + var/obj/structure/c_transit_tube/tube = new queued_p_type(loc) + on_make_pipe() + tube.setDir(queued_p_dir) + + if(queued_p_flipped) + tube.setDir(turn(queued_p_dir, 45)) + tube.simple_rotate_flip() + +/obj/machinery/pipedispenser/proc/on_make_pipe() + busy = TRUE + delay = addtimer(CALLBACK(src, PROC_REF(reset_busy)), 5) + +/obj/machinery/pipedispenser/proc/reset_busy() + busy = FALSE + +#undef ATMOS_CATEGORY +#undef DISPOSALS_CATEGORY +#undef TRANSIT_CATEGORY diff --git a/code/game/machinery/porta_turret/portable_turret.dm b/code/game/machinery/porta_turret/portable_turret.dm index 3e50954df0c7..5c592c7409dd 100644 --- a/code/game/machinery/porta_turret/portable_turret.dm +++ b/code/game/machinery/porta_turret/portable_turret.dm @@ -77,8 +77,6 @@ DEFINE_BITFIELD(turret_flags, list( var/has_cover = TRUE /// The cover that is covering this turret var/obj/machinery/porta_turret_cover/cover = null - /// World.time the turret last fired - var/last_fired = 0 /// Ticks until next shot (1.5 ?) var/shot_delay = 15 /// Turret flags about who is turret allowed to shoot @@ -101,6 +99,8 @@ DEFINE_BITFIELD(turret_flags, list( var/datum/action/turret_toggle/toggle_action /// Mob that is remotely controlling the turret var/mob/remote_controller + //our cooldowns + COOLDOWN_DECLARE(fire_cooldown) /// For connecting to additional turrets var/id = "" @@ -599,9 +599,9 @@ DEFINE_BITFIELD(turret_flags, list( return if(!(obj_flags & EMAGGED)) //if it hasn't been emagged, cooldown before shooting again - if(last_fired + shot_delay > world.time) + if(!COOLDOWN_FINISHED(src, fire_cooldown)) return - last_fired = world.time + COOLDOWN_START(src, fire_cooldown, shot_delay) var/turf/T = get_turf(src) var/turf/U = get_turf(target) @@ -842,6 +842,44 @@ DEFINE_BITFIELD(turret_flags, list( stun_projectile_sound = 'sound/weapons/gun/smg/shot.ogg' desc = "A ballistic machine gun auto-turret." +//high rof, range, faster projectile speed +/* 'Nanotrasen' turrets */ + +/obj/machinery/porta_turret/ship/nt + name = "Sharplite Defense Turret" + desc = "A cheap and effective turret designed by Sharplite and purchased and installed on most Nanotrasen Vessels." + faction = list(FACTION_PLAYER_NANOTRASEN, "turret") + icon_state = "standard_lethal" + base_icon_state = "standard" + stun_projectile = /obj/projectile/beam/disabler/sharplite + lethal_projectile = /obj/projectile/beam/laser/sharplite + lethal_projectile_sound = 'sound/weapons/gun/laser/nt-fire.ogg' + stun_projectile_sound = 'sound/weapons/taser2.ogg' + shot_delay = 10 + scan_range = 10 + +/obj/machinery/porta_turret/ship/nt/light + name = "Sharplite LDS" + desc = "A cheap and effective 'defensive system' designed by Sharplite for installation on Nanotrasen vessels." + stun_projectile = /obj/projectile/beam/disabler/weak/sharplite + lethal_projectile = /obj/projectile/beam/laser/light/sharplite + lethal_projectile_sound = 'sound/weapons/gun/laser/nt-fire.ogg' + stun_projectile_sound = 'sound/weapons/taser2.ogg' + + +/obj/machinery/porta_turret/ship/nt/heavy + name = "Sharplite Defense Cannon" + desc = "A heavy laser mounting designed by Sharplite for usage on Nanotrasen vessels." + lethal_projectile = /obj/projectile/beam/laser/heavylaser/sharplite + lethal_projectile_sound = 'sound/weapons/lasercannonfire.ogg' + +/obj/machinery/porta_turret/ship/nt/pulse + name = "Sharplite Pulse Cannon" + desc = "A pulse cannon mounting designed by Sharplite. Not sold to any purchasers and exclusively used on Nanotrasen Vessels." + lethal_projectile = /obj/projectile/beam/pulse/sharplite_turret + lethal_projectile_sound = 'sound/weapons/gun/laser/heavy_laser.ogg' + + /* Syndicate Turrets */ @@ -866,6 +904,40 @@ DEFINE_BITFIELD(turret_flags, list( lethal_projectile = /obj/projectile/beam/laser/heavylaser lethal_projectile_sound = 'sound/weapons/lasercannonfire.ogg' +/* Inteq Turrets */ + +/obj/machinery/porta_turret/ship/inteq + name = "Vanguard Turret" + desc = "A turret designed by IRMG engineers for defending ships from hostile flora, fauna, and people (and Elzousa, which count as flora and people)." + stun_projectile = /obj/projectile/bullet/a762_40/rubber + stun_projectile_sound = 'sound/weapons/gun/rifle/skm.ogg' + lethal_projectile = /obj/projectile/bullet/a762_40 + lethal_projectile_sound = 'sound/weapons/gun/rifle/skm.ogg' + scan_range = 8 + shot_delay = 20 + faction = list(FACTION_PLAYER_INTEQ, "turret") + +/obj/machinery/porta_turret/ship/inteq/light + name = "Close-In Vanguard Turret" + desc = "A light turret designed by IRMG engineers for the the task of defending from close-in encounters. Low power, high speed." + stun_projectile = /obj/projectile/bullet/c10mm/rubber + stun_projectile_sound = 'sound/weapons/gun/smg/vector_fire.ogg' + lethal_projectile = /obj/projectile/bullet/c10mm + lethal_projectile_sound = 'sound/weapons/gun/smg/vector_fire.ogg' + subsystem_type = /datum/controller/subsystem/processing/fastprocess //turns out if you have a shot delay below what SSmachines fires at you need to use a different subsystem + scan_range = 4 + shot_delay = 5 + +/obj/machinery/porta_turret/ship/inteq/heavy + name = "Vanguard Overwatch Turret" + desc = "A turret designed by IRMG engineers to provide long range defensive fire on their installations. Has a habit of leaving big holes." + stun_projectile = /obj/projectile/bullet/a308/rubber + stun_projectile_sound = 'sound/weapons/gun/rifle/f4.ogg' + lethal_projectile = /obj/projectile/bullet/a308 + lethal_projectile_sound = 'sound/weapons/gun/rifle/f4.ogg' + scan_range = 12 + shot_delay = 20 + /* Solcon Turrets */ /obj/machinery/porta_turret/ship/solgov diff --git a/code/game/mecha/equipment/tools/work_tools.dm b/code/game/mecha/equipment/tools/work_tools.dm index 44c8c6626dae..aa5dbf38c27f 100644 --- a/code/game/mecha/equipment/tools/work_tools.dm +++ b/code/game/mecha/equipment/tools/work_tools.dm @@ -491,6 +491,86 @@ return 1 //WS Edit End - Readded from Smartwire Revert +/obj/item/mecha_parts/mecha_equipment/salvage_saw + name = "109-C Salvage Saw" + desc = "Equipment for cutting open walls and airlocks." + icon_state = "mecha_saw" + equip_cooldown = 5 + energy_drain = 10 + force = 15 + var/dam_force = 30 + harmful = TRUE + tool_behaviour = TOOL_DECONSTRUCT + toolspeed = 0.5 + var/datum/effect_system/spark_spread/spark_system + +/obj/item/mecha_parts/mecha_equipment/salvage_saw/can_attach(obj/mecha/M as obj) + if(..()) + if(istype(M, /obj/mecha/working) || istype(M, /obj/mecha/combat)) + return 1 + return 0 + +/obj/item/mecha_parts/mecha_equipment/salvage_saw/attach() + ..() + toolspeed = 0.5 + return + +/obj/item/mecha_parts/mecha_equipment/salvage_saw/detach() + ..() + toolspeed = 10 //yeah sure, use a mech tool without a mech. see how far that gets you + return ..() + +/obj/item/mecha_parts/mecha_equipment/salvage_saw/action(atom/target) + if(!action_checks(target)) + return + if(isliving(target)) + if(chassis.occupant.a_intent == INTENT_HARM) + var/mob/living/M = target + saw_mob(M, chassis.occupant) + return + else + target.add_overlay(GLOB.cutting_effect) + if(target.deconstruct_act(chassis.occupant, src)) + do_sparks(2, TRUE, src) + chassis.stopped-- + target.cut_overlay(GLOB.cutting_effect) + if(!chassis.stopped) + occupant_message("[src] finishes cutting, allowing movement again.") + +/obj/item/mecha_parts/mecha_equipment/salvage_saw/tool_start_check(user, amount) + if(!chassis.stopped) + occupant_message("[src] begins cutting, locking in place!") + chassis.stopped++ + return TRUE + +/obj/item/mecha_parts/mecha_equipment/salvage_saw/proc/saw_mob(mob/living/target, mob/user) + target.visible_message("[chassis] is sawing [target] with [src]!", \ + "[chassis] is sawing you with [src]!") + if(!do_after_cooldown(target)) + return + log_combat(user, target, "sawed", "[name]", "(INTENT: [uppertext(user.a_intent)]) (DAMTYPE: [uppertext(damtype)])") + if(target.stat == DEAD && target.getBruteLoss() >= 400) + log_combat(user, target, "gibbed", name) + target.gib() + else + var/obj/item/bodypart/target_part = target.get_bodypart(ran_zone(BODY_ZONE_CHEST)) + target.apply_damage(15, BRUTE, BODY_ZONE_CHEST, target.run_armor_check(target_part, "melee")) + + //blood splatters + var/splatter_dir = get_dir(chassis, target) + if(isalien(target)) + new /obj/effect/temp_visual/dir_setting/bloodsplatter/xenosplatter(target.drop_location(), splatter_dir) + else + var/splatter_color = null + if(iscarbon(target)) + var/mob/living/carbon/carbon_target = target + splatter_color = carbon_target.dna.blood_type.color + new /obj/effect/temp_visual/dir_setting/bloodsplatter(target.drop_location(), splatter_dir, splatter_color) + + //organs go everywhere + if(target_part && prob(10)) + target_part.dismember(BRUTE) + //Dunno where else to put this so shrug /obj/item/mecha_parts/mecha_equipment/conversion_kit name = "Exosuit Conversion Kit" diff --git a/code/game/mecha/mecha.dm b/code/game/mecha/mecha.dm index db59620b39fd..eba4801ba56d 100644 --- a/code/game/mecha/mecha.dm +++ b/code/game/mecha/mecha.dm @@ -15,6 +15,7 @@ light_on = FALSE var/ruin_mecha = FALSE //if the mecha starts on a ruin, don't automatically give it a tracking beacon to prevent metagaming. var/can_move = 0 //time of next allowed movement + var/stopped = FALSE var/mob/living/carbon/occupant = null var/step_in = 10 //make a step in step_in/10 sec. var/dir_in = 2//What direction will the mech face when entered/powered on? Defaults to South. @@ -596,6 +597,8 @@ /obj/mecha/proc/domove(direction) if(can_move >= world.time) return 0 + if(stopped) + return 0 if(!Process_Spacemove(direction)) return 0 if(!has_charge(step_energy_drain)) diff --git a/code/game/objects/items.dm b/code/game/objects/items.dm index a1302008cf89..154f6bde143a 100644 --- a/code/game/objects/items.dm +++ b/code/game/objects/items.dm @@ -2,6 +2,10 @@ GLOBAL_DATUM_INIT(fire_overlay, /mutable_appearance, mutable_appearance('icons/e GLOBAL_DATUM_INIT(welding_sparks, /mutable_appearance, mutable_appearance('icons/effects/welding_effect.dmi', "welding_sparks", GASFIRE_LAYER, ABOVE_LIGHTING_PLANE)) +GLOBAL_DATUM_INIT(cutting_effect, /mutable_appearance, mutable_appearance('icons/effects/cutting_effect.dmi', "cutting_effect", GASFIRE_LAYER, ABOVE_LIGHTING_PLANE)) + +GLOBAL_DATUM_INIT(advanced_cutting_effect, /mutable_appearance, mutable_appearance('icons/effects/cutting_effect.dmi', "advanced_cutting_effect", GASFIRE_LAYER, ABOVE_LIGHTING_PLANE)) + GLOBAL_DATUM_INIT(cleaning_bubbles, /mutable_appearance, mutable_appearance('icons/effects/effects.dmi', "bubbles", ABOVE_MOB_LAYER, GAME_PLANE)) GLOBAL_VAR_INIT(rpg_loot_items, FALSE) diff --git a/code/game/objects/items/gear_packs.dm b/code/game/objects/items/gear_packs.dm new file mode 100644 index 000000000000..65db4ffa28c9 --- /dev/null +++ b/code/game/objects/items/gear_packs.dm @@ -0,0 +1,285 @@ +/obj/item/gear_pack + name = "gear pack" + desc = "A large backpack that usually holds things" + icon = 'icons/obj/hydroponics/equipment.dmi' + icon_state = "waterbackpack" + item_state = "waterbackpack" + lefthand_file = 'icons/mob/inhands/equipment/backpack_lefthand.dmi' + righthand_file = 'icons/mob/inhands/equipment/backpack_righthand.dmi' + w_class = WEIGHT_CLASS_HUGE + slot_flags = ITEM_SLOT_BACK + item_flags = SLOWS_WHILE_IN_HAND + max_integrity = 300 + slowdown = 1 + drag_slowdown = 1 + actions_types = list(/datum/action/item_action/toggle_gear_handle) + max_integrity = 200 + armor = list("melee" = 0, "bullet" = 0, "laser" = 0, "energy" = 0, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 100, "acid" = 30) + resistance_flags = FIRE_PROOF + var/on = FALSE + var/obj/item/stock_parts/cell/cell + var/preload_cell_type = /obj/item/stock_parts/cell/high + var/powered = FALSE + var/activate_sound = "sparks" + var/obj/item/gear_handle/gear_handle_type = /obj/item/gear_handle + var/obj/item/gear_handle/gear_handle + +/obj/item/gear_pack/get_cell() + return cell + +/obj/item/gear_pack/Initialize() + . = ..() + drag_slowdown = slowdown + gear_handle = new gear_handle_type(src) + cell = new preload_cell_type(src) + update_power() + return + +/obj/item/gear_pack/examine(mob/user) + . = ..() + . += "It is [ on ? "currently" : "not"] active." + if(cell) + . += "A small readout reports [PERCENT(cell.charge / cell.maxcharge)]% charge." + +/obj/item/gear_pack/fire_act(exposed_temperature, exposed_volume) + . = ..() + if(gear_handle?.loc == src) + gear_handle.fire_act(exposed_temperature, exposed_volume) + +/obj/item/gear_pack/extinguish() + . = ..() + if(gear_handle?.loc == src) + gear_handle.extinguish() + +/obj/item/gear_pack/proc/update_power() + if(!QDELETED(cell)) + if(QDELETED(gear_handle) || cell.charge < gear_handle.usecost) + powered = FALSE + else + powered = TRUE + else + powered = FALSE + update_icon() + +/obj/item/gear_pack/update_overlays() + . = ..() + + if(powered) + . += "[initial(icon_state)]-powered" + if(!QDELETED(cell)) + var/ratio = cell.charge / cell.maxcharge + ratio = CEILING(ratio*4, 1) * 25 + . += "[initial(icon_state)]-charge[ratio]" + if(!cell) + . += "[initial(icon_state)]-nocell" + if(!on) + . += "[initial(icon_state)]-attachment" + +/obj/item/gear_pack/CheckParts(list/parts_list) + ..() + cell = locate(/obj/item/stock_parts/cell) in contents + update_power() + +/obj/item/gear_pack/ui_action_click() + toggle_gear_handle() + +//ATTACK HAND IGNORING PARENT RETURN VALUE +/obj/item/gear_pack/attack_hand(mob/user) + if(loc == user) + if(slot_flags == ITEM_SLOT_BACK) + if(user.get_item_by_slot(ITEM_SLOT_BACK) == src) + ui_action_click() + else + to_chat(user, "Put the [src] on your back first!") + + else if(slot_flags == ITEM_SLOT_BELT) + if(user.get_item_by_slot(ITEM_SLOT_BELT) == src) + ui_action_click() + else + to_chat(user, "Strap the [src]'s belt on first!") + return + return ..() + +/obj/item/gear_pack/MouseDrop(obj/over_object) + . = ..() + if(ismob(loc)) + var/mob/M = loc + if(!M.incapacitated() && istype(over_object, /atom/movable/screen/inventory/hand)) + var/atom/movable/screen/inventory/hand/H = over_object + M.putItemFromInventoryInHandIfPossible(src, H.held_index) + +/obj/item/gear_pack/attackby(obj/item/W, mob/user, params) + if(W == gear_handle) + toggle_gear_handle() + else if(istype(W, /obj/item/stock_parts/cell)) + var/obj/item/stock_parts/cell/C = W + if(cell) + to_chat(user, "[src] already has a cell!") + else + if(C.maxcharge < gear_handle.usecost) + to_chat(user, "[src] requires a higher capacity cell.") + return + if(!user.transferItemToLoc(W, src)) + return + cell = W + to_chat(user, "You install a cell in [src].") + update_power() + + else if(W.tool_behaviour == TOOL_SCREWDRIVER) + if(cell) + cell.update_icon() + cell.forceMove(get_turf(src)) + cell = null + to_chat(user, "You remove the cell from [src].") + update_power() + else + return ..() + +/obj/item/gear_pack/emp_act(severity) + . = ..() + if(cell && !(. & EMP_PROTECT_CONTENTS)) + deductcharge(1000 / severity) + if(. & EMP_PROTECT_SELF) + return + update_power() + +/obj/item/gear_pack/proc/toggle_gear_handle() + set name = "Toggle gear_handle" + set category = "Object" + on = !on + + var/mob/living/carbon/user = usr + if(on) + //Detach the gear_handle into the user's hands + playsound(src, 'sound/items/handling/multitool_pickup.ogg', 100) + if(!usr.put_in_hands(gear_handle)) + on = FALSE + to_chat(user, "You need a free hand to hold the [gear_handle]!") + update_power() + return + else + //Remove from their hands and back onto the gear pack + remove_gear_handle(user) + + update_power() + for(var/X in actions) + var/datum/action/A = X + A.UpdateButtonIcon() + + +/obj/item/gear_pack/equipped(mob/user, slot) + ..() + if((slot_flags == ITEM_SLOT_BACK && slot != ITEM_SLOT_BACK) || (slot_flags == ITEM_SLOT_BELT && slot != ITEM_SLOT_BELT)) + remove_gear_handle(user) + update_power() + +/obj/item/gear_pack/item_action_slot_check(slot, mob/user) + if(slot == user.getBackSlot()) + return 1 + +/obj/item/gear_pack/proc/remove_gear_handle(mob/user) + if(ismob(gear_handle.loc)) + var/mob/M = gear_handle.loc + M.dropItemToGround(gear_handle, TRUE) + return + +/obj/item/gear_pack/Destroy() + if(on) + var/M = get(gear_handle, /mob) + remove_gear_handle(M) + QDEL_NULL(gear_handle) + QDEL_NULL(cell) + return ..() + +/obj/item/gear_pack/proc/deductcharge(chrgdeductamt) + if(cell) + if(cell.charge < (gear_handle.usecost+chrgdeductamt)) + powered = FALSE + update_power() + if(cell.use(chrgdeductamt)) + update_power() + return TRUE + else + return FALSE + +/obj/item/gear_handle + + name = "gear handle" + desc = "handles the gear." + icon = 'icons/obj/hydroponics/equipment.dmi' + icon_state = "mister" + item_state = "mister" + lefthand_file = 'icons/mob/inhands/equipment/mister_lefthand.dmi' + righthand_file = 'icons/mob/inhands/equipment/mister_righthand.dmi' + + force = 0 + throwforce = 6 + w_class = WEIGHT_CLASS_BULKY + resistance_flags = INDESTRUCTIBLE + base_icon_state = "mister" + + var/req_pack = TRUE + var/usecost = 1000 + var/obj/item/gear_pack/pack + +/obj/item/gear_handle/Initialize() + . = ..() + ADD_TRAIT(src, TRAIT_NO_STORAGE_INSERT, GENERIC_ITEM_TRAIT) + if (!loc || !istype(loc, /obj/item/gear_pack)) + return INITIALIZE_HINT_QDEL + if(!req_pack) + return + pack = loc + update_icon() + +/obj/item/gear_handle/Destroy() + pack = null + return ..() + +/obj/item/gear_handle/equipped(mob/user, slot) + . = ..() + if(!req_pack) + return + RegisterSignal(user, COMSIG_MOVABLE_MOVED, PROC_REF(check_range)) + +/obj/item/gear_handle/Moved() + . = ..() + check_range() + + +/obj/item/gear_handle/fire_act(exposed_temperature, exposed_volume) + . = ..() + if((req_pack && pack) && loc != pack) + pack.fire_act(exposed_temperature, exposed_volume) + +/obj/item/gear_handle/proc/check_range() + SIGNAL_HANDLER + + if(!req_pack ||!pack) + return + if(!in_range(src,pack)) + var/mob/living/L = loc + if(istype(L)) + to_chat(L, "[pack]'s [src] overextends and comes out of your hands!") + else + visible_message("[src] snaps back into [pack].") + snap_back() + +/obj/item/gear_handle/dropped(mob/user) + . = ..() + if(!req_pack) + return ..() + if(user) + UnregisterSignal(user, COMSIG_MOVABLE_MOVED) + if(user != loc) + to_chat(user, "[src] snap back into the main unit.") + snap_back() + return + +/obj/item/gear_handle/proc/snap_back() + if(!pack) + return + playsound() + pack.on = FALSE + forceMove(pack) + pack.update_power() diff --git a/code/game/objects/structures/beds_chairs/bed.dm b/code/game/objects/structures/beds_chairs/bed.dm index ec7132a67cdd..533f58bdf2ac 100644 --- a/code/game/objects/structures/beds_chairs/bed.dm +++ b/code/game/objects/structures/beds_chairs/bed.dm @@ -71,7 +71,7 @@ return attack_hand(user) /obj/structure/bed/attackby(obj/item/W, mob/user, params) - if(W.tool_behaviour == TOOL_WRENCH && !(flags_1&NODECONSTRUCT_1)) + if((W.tool_behaviour == TOOL_WRENCH || W.tool_behaviour == TOOL_DECONSTRUCT) && !(flags_1&NODECONSTRUCT_1)) W.play_tool_sound(src) deconstruct(TRUE) else diff --git a/code/game/objects/structures/beds_chairs/chair.dm b/code/game/objects/structures/beds_chairs/chair.dm index 045bf39ae9b6..40e0d9388515 100644 --- a/code/game/objects/structures/beds_chairs/chair.dm +++ b/code/game/objects/structures/beds_chairs/chair.dm @@ -60,7 +60,7 @@ qdel(src) /obj/structure/chair/attackby(obj/item/W, mob/user, params) - if(W.tool_behaviour == TOOL_WRENCH && !(flags_1&NODECONSTRUCT_1)) + if((W.tool_behaviour == TOOL_WRENCH || W.tool_behaviour == TOOL_DECONSTRUCT) && !(flags_1&NODECONSTRUCT_1)) W.play_tool_sound(src) deconstruct() else if(istype(W, /obj/item/assembly/shock_kit)) diff --git a/code/game/objects/structures/catwalk.dm b/code/game/objects/structures/catwalk.dm index 20986f9e6c27..2202e84d70e4 100644 --- a/code/game/objects/structures/catwalk.dm +++ b/code/game/objects/structures/catwalk.dm @@ -57,7 +57,7 @@ . += "The supporting rods look like they could be welded." /obj/structure/catwalk/attackby(obj/item/C, mob/user, params) - if(C.tool_behaviour == TOOL_WELDER && !(resistance_flags & INDESTRUCTIBLE)) + if((C.tool_behaviour == TOOL_WELDER || C.tool_behaviour == TOOL_DECONSTRUCT) && !(resistance_flags & INDESTRUCTIBLE)) to_chat(user, "You slice off [src]") deconstruct() return diff --git a/code/game/objects/structures/crates_lockers/closets.dm b/code/game/objects/structures/crates_lockers/closets.dm index 7731bf48d2ff..cd1c880eae74 100644 --- a/code/game/objects/structures/crates_lockers/closets.dm +++ b/code/game/objects/structures/crates_lockers/closets.dm @@ -255,10 +255,24 @@ if(user in src) return if(src.tool_interact(W,user)) - return 1 // No afterattack + return TRUE // No afterattack else return ..() +/obj/structure/closet/proc/try_deconstruct(obj/item/W, mob/user) + if(W.tool_behaviour == cutting_tool || W.tool_behaviour == TOOL_DECONSTRUCT) + if(!W.tool_start_check(user, amount = 0)) + return + to_chat(user, span_notice("You begin cutting \the [src] apart...")) + if(W.use_tool(src, user, 40, volume = 50)) + if(!opened) + return + user.visible_message(span_notice("[user] slices apart \the [src]."), + span_notice("You cut \the [src] apart with \the [W]."), + span_hear("You hear welding.")) + deconstruct(TRUE) + return TRUE + /obj/structure/closet/proc/tool_interact(obj/item/W, mob/user)//returns TRUE if attackBy call shouldnt be continued (because tool was used/closet was of wrong type), FALSE if otherwise . = TRUE if(opened) @@ -300,6 +314,13 @@ user.visible_message("[user] [anchored ? "anchored" : "unanchored"] \the [src] [anchored ? "to" : "from"] the ground.", \ "You [anchored ? "anchored" : "unanchored"] \the [src] [anchored ? "to" : "from"] the ground.", \ "You hear a ratchet.") + + else if(W.tool_behaviour == TOOL_DECONSTRUCT && locked) + user.visible_message("[user] is cutting \the [src] open !", "You begin to cut \the [src] open.") + if (W.use_tool(src, user, 10 SECONDS, volume=0)) + bust_open() + user.visible_message("[user] busted \the [src] open !", "You finish cutting \the [src] open.") + else if(user.a_intent != INTENT_HARM) var/item_is_id = W.GetID() if(!item_is_id) diff --git a/code/game/objects/structures/crates_lockers/closets/cardboardbox.dm b/code/game/objects/structures/crates_lockers/closets/cardboardbox.dm index 7135b3d199a2..b0674a2d2b60 100644 --- a/code/game/objects/structures/crates_lockers/closets/cardboardbox.dm +++ b/code/game/objects/structures/crates_lockers/closets/cardboardbox.dm @@ -20,6 +20,13 @@ var/move_delay = FALSE var/egged = 0 +/obj/structure/closet/cardboard/try_deconstruct(obj/item/W, mob/user) + if(W.tool_behaviour == cutting_tool) + user.visible_message(span_notice("[user] cut apart \the [src]."), \ + span_notice("You cut \the [src] apart with \the [W].")) + deconstruct(TRUE) + return TRUE + /obj/structure/closet/cardboard/relaymove(mob/living/user, direction) if(opened || move_delay || user.incapacitated() || !isturf(loc) || !has_gravity(loc)) return diff --git a/code/game/objects/structures/door_assembly.dm b/code/game/objects/structures/door_assembly.dm index 4246075e49f6..43052f1f0dbb 100644 --- a/code/game/objects/structures/door_assembly.dm +++ b/code/game/objects/structures/door_assembly.dm @@ -333,6 +333,14 @@ new mineral_path(T, 2) qdel(src) +/obj/structure/door_assembly/deconstruct_act(mob/living/user, obj/item/I) + . = ..() + if(!I.tool_start_check(user, amount=0)) + return FALSE + if (I.use_tool(src, user, 3 SECONDS, volume=100)) + to_chat(user, "You slice [src] apart.") + deconstruct(FALSE) + return TRUE /obj/structure/door_assembly/rcd_vals(mob/user, obj/item/construction/rcd/the_rcd) if(the_rcd.mode == RCD_DECONSTRUCT) diff --git a/code/game/objects/structures/false_walls.dm b/code/game/objects/structures/false_walls.dm index d5a8c3e496c1..48bf8817e1e7 100644 --- a/code/game/objects/structures/false_walls.dm +++ b/code/game/objects/structures/false_walls.dm @@ -107,9 +107,6 @@ else if(W.tool_behaviour == TOOL_WELDER) if(W.use_tool(src, user, 0, volume=50)) dismantle(user, TRUE) - else if(istype(W, /obj/item/pickaxe/drill/jackhammer)) - W.play_tool_sound(src) - dismantle(user, TRUE) else return ..() diff --git a/code/game/objects/structures/girders.dm b/code/game/objects/structures/girders.dm index 362de185e9ba..df0d3cf1f43c 100644 --- a/code/game/objects/structures/girders.dm +++ b/code/game/objects/structures/girders.dm @@ -36,26 +36,7 @@ playsound(src, 'sound/machines/clockcult/integration_cog_install.ogg', 50, TRUE) add_fingerprint(user) - if(istype(W, /obj/item/gun/energy/plasmacutter)) - to_chat(user, "You start slicing apart the girder...") - if(W.use_tool(src, user, 10, volume=100)) - to_chat(user, "You slice apart the girder.") - var/obj/item/stack/sheet/metal/M = new (loc, 2) - M.add_fingerprint(user) - qdel(src) - - return - - else if(istype(W, /obj/item/pickaxe/drill/jackhammer)) - to_chat(user, "You smash through the girder!") - new /obj/item/stack/sheet/metal(get_turf(src)) - W.play_tool_sound(src) - qdel(src) - - return - - - else if(istype(W, /obj/item/stack)) + if(istype(W, /obj/item/stack)) if(iswallturf(loc)) to_chat(user, "There is already a wall present!") return @@ -231,6 +212,15 @@ else return ..() +/obj/structure/girder/deconstruct_act(mob/living/user, obj/item/I) + . = ..() + if(!I.tool_start_check(user, amount=0)) + return FALSE + if(I.use_tool(src, user, 3 SECONDS, volume=0)) + to_chat(user, "You cut apart \the [src].", "You cut apart \the [src].") + deconstruct() + return TRUE + // Screwdriver behavior for girders /obj/structure/girder/screwdriver_act(mob/user, obj/item/tool) if(..()) @@ -373,13 +363,6 @@ transfer_fingerprints_to(R) qdel(src) - else if(istype(W, /obj/item/pickaxe/drill/jackhammer)) - to_chat(user, "Your jackhammer smashes through the girder!") - var/obj/item/stack/sheet/mineral/hidden/hellstone/R = new(drop_location(), 2) - transfer_fingerprints_to(R) - W.play_tool_sound(src) - qdel(src) - else if(istype(W, /obj/item/stack/sheet/mineral/hidden/hellstone)) var/obj/item/stack/sheet/mineral/hidden/hellstone/R = W if(R.get_amount() < 1) @@ -447,13 +430,6 @@ transfer_fingerprints_to(B) qdel(src) - else if(istype(W, /obj/item/pickaxe/drill/jackhammer)) - to_chat(user, "Your jackhammer smashes through the girder!") - var/obj/item/stack/tile/bronze/B = new(drop_location(), 2) - transfer_fingerprints_to(B) - W.play_tool_sound(src) - qdel(src) - else if(istype(W, /obj/item/stack/tile/bronze)) var/obj/item/stack/tile/bronze/B = W if(B.get_amount() < 2) diff --git a/code/game/objects/structures/grille.dm b/code/game/objects/structures/grille.dm index 5bca53e84dd6..b1897ee661d4 100644 --- a/code/game/objects/structures/grille.dm +++ b/code/game/objects/structures/grille.dm @@ -227,6 +227,15 @@ qdel(src) ..() +/obj/structure/grille/deconstruct_act(mob/living/user, obj/item/I) + . = ..() + if(!I.tool_start_check(user, amount=0)) + return FALSE + if (I.use_tool(src, user, 1 SECONDS, volume=100)) + to_chat(user, "You slice [src] apart.") + deconstruct(FALSE) + return TRUE + /obj/structure/grille/obj_break() if(!broken && !(flags_1 & NODECONSTRUCT_1)) new broken_type(src.loc) diff --git a/code/game/objects/structures/lattice.dm b/code/game/objects/structures/lattice.dm index 30999b58a620..9aaefb8c014e 100644 --- a/code/game/objects/structures/lattice.dm +++ b/code/game/objects/structures/lattice.dm @@ -40,6 +40,15 @@ var/turf/T = get_turf(src) return T.attackby(C, user) //hand this off to the turf instead (for building plating, catwalks, etc) +/obj/structure/lattice/deconstruct_act(mob/living/user, obj/item/I) + . = ..() + if(!I.tool_start_check(user, amount=0)) + return FALSE + if(I.use_tool(src, user, 1 SECONDS, volume=0)) + to_chat(user, "You cut apart \the [src].", "You cut apart \the [src].") + deconstruct() + return TRUE + /obj/structure/lattice/deconstruct(disassembled = TRUE) if(!(flags_1 & NODECONSTRUCT_1)) new build_material(get_turf(src), number_of_mats) diff --git a/code/game/objects/structures/railings.dm b/code/game/objects/structures/railings.dm index 95c24145399f..d8f5c543a168 100644 --- a/code/game/objects/structures/railings.dm +++ b/code/game/objects/structures/railings.dm @@ -65,6 +65,15 @@ deconstruct() return TRUE +/obj/structure/railing/deconstruct_act(mob/living/user, obj/item/I) + . = ..() + if(!I.tool_start_check(user, amount=0)) + return FALSE + if (I.use_tool(src, user, 3 SECONDS, volume=0)) + to_chat(user, "You cut apart the railing.") + deconstruct() + return TRUE + /obj/structure/railing/deconstruct(disassembled) . = ..() if(!loc) //quick check if it's qdeleted already. diff --git a/code/game/objects/structures/safe.dm b/code/game/objects/structures/safe.dm index 5f3e2914bc47..44a9f7f94717 100644 --- a/code/game/objects/structures/safe.dm +++ b/code/game/objects/structures/safe.dm @@ -75,6 +75,13 @@ FLOOR SAFES if(istype(I, /obj/item/clothing/neck/stethoscope)) attack_hand(user) return + + else if(I.tool_behaviour == TOOL_DECONSTRUCT) + user.visible_message("[user] begin to cut through the lock of \the [src].","You start cutting trough the lock of [src].") + if(I.use_tool(src, user, 60 SECONDS)) + broken = TRUE + user.visible_message("[user] successfully cuts trough the lock of \the [src].","You successfully cut trough the lock of [src].") + else to_chat(user, "You can't put [I] into the safe while it is closed!") return diff --git a/code/game/objects/structures/salvaging.dm b/code/game/objects/structures/salvaging.dm index dbd75dac488f..f4aad715db19 100644 --- a/code/game/objects/structures/salvaging.dm +++ b/code/game/objects/structures/salvaging.dm @@ -34,6 +34,16 @@ qdel(src) return TRUE +/obj/structure/salvageable/deconstruct_act(mob/living/user, obj/item/tool) + . = ..() + user.visible_message("[user] starts slicing [src].", \ + "You start salvaging anything useful from [src]...") + if(tool.use_tool(src, user, 6 SECONDS)) + user.visible_message("[user] dismantles [src].", \ + "You salvage [src].") + dismantle(user) + qdel(src) + return TRUE //Types themself, use them, but not the parent object diff --git a/code/game/objects/structures/tables_racks.dm b/code/game/objects/structures/tables_racks.dm index a7404ef68a6c..d5b1710b6296 100644 --- a/code/game/objects/structures/tables_racks.dm +++ b/code/game/objects/structures/tables_racks.dm @@ -162,7 +162,7 @@ /obj/structure/table/attackby(obj/item/I, mob/user, params) var/list/modifiers = params2list(params) if(!(flags_1 & NODECONSTRUCT_1) && user.a_intent != INTENT_HELP) - if(I.tool_behaviour == TOOL_SCREWDRIVER && deconstruction_ready) + if((I.tool_behaviour == TOOL_SCREWDRIVER) && deconstruction_ready) to_chat(user, "You start disassembling [src]...") if(I.use_tool(src, user, 20, volume=50)) deconstruct(TRUE) @@ -227,6 +227,15 @@ else return ..() +/obj/structure/table/deconstruct_act(mob/living/user, obj/item/I) + . = ..() + if(!I.tool_start_check(user, amount=0)) + return FALSE + if (I.use_tool(src, user, 1 SECONDS, volume=0)) + to_chat(user, span_warning("You cut [src] into sheets.")) + deconstruct(wrench_disassembly = TRUE) + return TRUE + /obj/structure/table/proc/AfterPutItemOnTable(obj/item/I, mob/living/user) return diff --git a/code/game/objects/structures/window.dm b/code/game/objects/structures/window.dm index 5420cc06b490..5064883c5de9 100644 --- a/code/game/objects/structures/window.dm +++ b/code/game/objects/structures/window.dm @@ -27,6 +27,7 @@ var/real_explosion_block //ignore this, just use explosion_block var/breaksound = "shatter" var/hitsound = 'sound/effects/Glasshit.ogg' + var/decon_time = 5 SECONDS flags_ricochet = RICOCHET_HARD ricochet_chance_mod = 0.4 @@ -289,6 +290,15 @@ qdel(src) update_nearby_icons() +/obj/structure/window/deconstruct_act(mob/living/user, obj/item/I) + . = ..() + if(!I.tool_start_check(user, amount=0)) + return FALSE + if (I.use_tool(src, user, decon_time, volume=100)) + to_chat(user, span_warning("You shatter [src] with the [I].")) + deconstruct(FALSE) + return TRUE + /obj/structure/window/proc/spawnDebris(location) . = list() . += new /obj/item/shard(location) @@ -399,6 +409,7 @@ glass_type = /obj/item/stack/sheet/rglass rad_insulation = RAD_HEAVY_INSULATION ricochet_chance_mod = 0.8 + decon_time = 20 SECONDS //this is shitcode but all of construction is shitcode and needs a refactor, it works for now //If you find this like 4 years later and construction still hasn't been refactored, I'm so sorry for this @@ -408,7 +419,7 @@ switch(state) if(RWINDOW_SECURE) - if(I.tool_behaviour == TOOL_WELDER && user.a_intent == INTENT_HARM) + if((I.tool_behaviour == TOOL_WELDER) && user.a_intent == INTENT_HARM) user.visible_message("[user] holds \the [I] to the security screws on \the [src]...", "You begin heating the security screws on \the [src]...") if(I.use_tool(src, user, 150, volume = 100)) @@ -531,6 +542,7 @@ damage_deflection = 11 //WS Edit - Weakens R-Windows explosion_block = 2 glass_type = /obj/item/stack/sheet/plasmarglass + decon_time = 25 SECONDS //entirely copypasted code //take this out when construction is made a component or otherwise modularized in some way @@ -746,6 +758,7 @@ glass_type = /obj/item/stack/sheet/plastitaniumglass glass_amount = 2 rad_insulation = RAD_HEAVY_INSULATION + decon_time = 30 SECONDS /obj/structure/window/plasma/reinforced/plastitanium/unanchored anchored = FALSE diff --git a/code/game/turfs/closed/_closed.dm b/code/game/turfs/closed/_closed.dm index 766d7e0e5a24..ea0c0d4ed4b1 100644 --- a/code/game/turfs/closed/_closed.dm +++ b/code/game/turfs/closed/_closed.dm @@ -269,6 +269,21 @@ return FALSE +/turf/closed/deconstruct_act(mob/living/user, obj/item/I) + var/act_duration = breakdown_duration + if(!I.tool_start_check(user, amount=0)) + return FALSE + to_chat(user, "You begin slicing through the outer plating...") + while(I.use_tool(src, user, act_duration, volume=100)) + if(iswallturf(src)) + to_chat(user, "You slice through some of the outer plating...") + if(!alter_integrity(-(I.wall_decon_damage),user,FALSE,TRUE)) + return TRUE + else + break + + return FALSE + /turf/closed/mech_melee_attack(obj/mecha/M) M.do_attack_animation(src) switch(M.damtype) diff --git a/code/modules/cargo/packs/tools.dm b/code/modules/cargo/packs/tools.dm index e4081a448e0b..36bfefc02796 100644 --- a/code/modules/cargo/packs/tools.dm +++ b/code/modules/cargo/packs/tools.dm @@ -111,6 +111,13 @@ crate_name = "tank transfer valve crate" crate_type = /obj/structure/closet/crate/secure/science +/datum/supply_pack/tools/anglegrinder + name = "Angle Grinder" + desc = "Contains one angle grinder pack, a tool used for quick structure deconstruction and salvaging" + cost = 2000 + contains = list(/obj/item/gear_pack/anglegrinder) + crate_name = "Angle Grinder" + /* Liquid tanks */ diff --git a/code/modules/mining/abandoned_crates.dm b/code/modules/mining/abandoned_crates.dm index caf01866a019..406259246db1 100644 --- a/code/modules/mining/abandoned_crates.dm +++ b/code/modules/mining/abandoned_crates.dm @@ -124,6 +124,10 @@ qdel(src) ..() +// No busting open (used to disallow angle grinder cheesing +/obj/structure/closet/crate/secure/loot/bust_open() + boom() + /obj/structure/closet/crate/secure/loot/proc/spawn_loot() var/loot = rand(1,100) //100 different crates with varying chances of spawning switch(loot) diff --git a/code/modules/mining/equipment/angle_grinder.dm b/code/modules/mining/equipment/angle_grinder.dm new file mode 100644 index 000000000000..290cf0d153d7 --- /dev/null +++ b/code/modules/mining/equipment/angle_grinder.dm @@ -0,0 +1,144 @@ +/obj/item/gear_pack/anglegrinder + name = "grinder pack" + desc = "Supplies the high voltage needed to run the attached grinder." + icon = 'icons/obj/item/gear_packs.dmi' + item_state = "anglegrinderpack" + icon_state = "anglegrinderpack" + lefthand_file = 'icons/mob/inhands/equipment/backpack_lefthand.dmi' + righthand_file = 'icons/mob/inhands/equipment/backpack_righthand.dmi' + gear_handle_type = /obj/item/gear_handle/anglegrinder + +/obj/item/gear_handle/anglegrinder + name = "angle grinder" + desc = "A powerful salvage tool used to cut apart walls and airlocks. A hazard sticker recommends ear and eye protection." + icon = 'icons/obj/item/gear_packs.dmi' + icon_state = "anglegrinder" + item_state = "anglegrinder" + lefthand_file = 'icons/mob/inhands/equipment/gear_handle_lefthand.dmi' + righthand_file = 'icons/mob/inhands/equipment/gear_handle_righthand.dmi' + flags_1 = CONDUCT_1 + force = 13 + armour_penetration = 5 + w_class = WEIGHT_CLASS_BULKY + item_flags = ABSTRACT + attack_verb = list("lacerated", "ripped", "sliced", "sawed", "cut", "chopped", "diced") + hitsound = 'sound/weapons/anglegrinder.ogg' + usesound = 'sound/weapons/anglegrinder.ogg' + tool_behaviour = null // is set to TOOL_DECONSTRUCT once wielded + toolspeed = 1 + wall_decon_damage = 200 + usecost = 5 + pack = /obj/item/gear_pack/anglegrinder + var/startsound = 'sound/weapons/chainsawhit.ogg' + var/adv = FALSE + var/wielded = FALSE // track wielded status on item + var/two_hand_force = 24 + +/obj/item/gear_handle/anglegrinder/tool_start_check(mob/living/user, amount) + if(!pack) + to_chat(user, "how do you not have a pack for this. what.") + return FALSE + if(!pack.cell) + to_chat(user, "You need a cell to start!") + return FALSE + var/obj/item/stock_parts/cell/cell = pack.get_cell() + if(cell.charge < usecost) + to_chat(user, "You need more charge to complete this task!") + return FALSE + return TRUE + +/obj/item/gear_handle/anglegrinder/tool_use_check(mob/living/user, amount) + if(!pack.cell) + return FALSE + if(pack.deductcharge(usecost)) + return TRUE + else + to_chat(user, "You need more charge to complete this task!") + return FALSE + +/obj/item/gear_handle/anglegrinder/use(used) + return TRUE + +/obj/item/gear_handle/anglegrinder/Initialize() + . = ..() + RegisterSignal(src, COMSIG_TWOHANDED_WIELD, PROC_REF(on_wield)) + RegisterSignal(src, COMSIG_TWOHANDED_UNWIELD, PROC_REF(on_unwield)) + +/obj/item/gear_handle/anglegrinder/ComponentInitialize() + . = ..() + AddComponent(/datum/component/butchering, 30, 100, 0, startsound, TRUE) + AddComponent(/datum/component/two_handed, force_unwielded=force, force_wielded=two_hand_force, wieldsound=startsound) + AddElement(/datum/element/tool_bang, 2) + +/// triggered on wield of two handed item +/obj/item/gear_handle/anglegrinder/proc/on_wield(obj/item/source, mob/user) + SIGNAL_HANDLER + + tool_behaviour = TOOL_DECONSTRUCT + wielded = TRUE + sharpness = IS_SHARP + icon_state = "[initial(item_state)]-wield" + item_state = "[initial(item_state)]-wield" + +/// triggered on unwield of two handed item +/obj/item/gear_handle/anglegrinder/proc/on_unwield(obj/item/source, mob/user) + SIGNAL_HANDLER + + tool_behaviour = null + wielded = FALSE + sharpness = initial(sharpness) + icon_state = initial(icon_state) + item_state = initial(item_state) + +/obj/item/gear_handle/anglegrinder/get_dismemberment_chance() + if(wielded) + . = ..() + +/obj/item/gear_handle/anglegrinder/use_tool(atom/target, mob/living/user, delay, amount=1, volume=0, datum/callback/extra_checks) + if(adv) + target.add_overlay(GLOB.advanced_cutting_effect) + . = ..() + target.cut_overlay(GLOB.advanced_cutting_effect) + else + target.add_overlay(GLOB.cutting_effect) + . = ..() + target.cut_overlay(GLOB.cutting_effect) + +/obj/item/gear_pack/anglegrinder/energy + name = "energy supply pack" + desc = "a highly inefficient GEC-E-014 Supply Pack, used to generate and contain an energy field." + item_state = "energyanglegrinderpack" + icon_state = "energyanglegrinderpack" + gear_handle_type = /obj/item/gear_handle/anglegrinder/energy + +/obj/item/gear_handle/anglegrinder/energy + name = "energy saw" + desc = "An early prototype for handheld energy weapons, designed by a joint GEC-Cybersun lab to create an energy field for combat use." + icon_state = "energyanglegrinder" + item_state = "energyanglegrinder" + force = 5 + two_hand_force = 28 + armour_penetration = 16 + w_class = WEIGHT_CLASS_BULKY + item_flags = ABSTRACT + attack_verb = list("lacerated", "ripped", "burned", "sliced", "cauterized", "seared", "diced") + hitsound = 'sound/weapons/blade1.ogg' + usesound = 'sound/weapons/blade1.ogg' + startsound = 'sound/weapons/saberon.ogg' + toolspeed = 0.7 + usecost = 10 + pack = /obj/item/gear_pack/anglegrinder/energy + light_system = MOVABLE_LIGHT + light_range = 3 + light_color = LIGHT_COLOR_ELECTRIC_GREEN + light_on = FALSE + adv = TRUE + +/obj/item/gear_handle/anglegrinder/energy/on_wield(obj/item/source, mob/user) + . = ..() + set_light_on(TRUE) + +/obj/item/gear_handle/anglegrinder/energy/on_unwield(obj/item/source, mob/user) + . = ..() + set_light_on(FALSE) + diff --git a/code/modules/overmap/missions/acquire_mission.dm b/code/modules/overmap/missions/acquire_mission.dm index 8a3424c8eb11..ea55beb00120 100644 --- a/code/modules/overmap/missions/acquire_mission.dm +++ b/code/modules/overmap/missions/acquire_mission.dm @@ -180,14 +180,6 @@ Acquire: Anomaly weight = 2 objective_type = /mob/living/simple_animal/hostile/asteroid/ice_whelp -/datum/mission/acquire/creature/ice_demon - name = "Capture an ice demon" - desc = "I require a live ice demon for research purposes. Trap one within the given \ - Lifeform Containment Unit and return it to me and you will be paid handsomely." - value = 1500 - weight = 2 - objective_type = /mob/living/simple_animal/hostile/asteroid/ice_demon - /datum/mission/acquire/creature/migo name = "Capture a live mi-go" desc = "I require a live mi-go for research purposes. Trap one within the given \ diff --git a/code/modules/projectiles/ammunition/energy/plasma.dm b/code/modules/projectiles/ammunition/energy/plasma.dm index 00de4a90ffee..d593086157fd 100644 --- a/code/modules/projectiles/ammunition/energy/plasma.dm +++ b/code/modules/projectiles/ammunition/energy/plasma.dm @@ -2,10 +2,9 @@ projectile_type = /obj/projectile/plasma select_name = "plasma burst" fire_sound = 'sound/weapons/plasma_cutter.ogg' - delay = 15 - e_cost = 25 + delay = 30 + e_cost = 100 /obj/item/ammo_casing/energy/plasma/adv projectile_type = /obj/projectile/plasma/adv - delay = 10 - e_cost = 10 + delay = 20 diff --git a/code/modules/projectiles/guns/energy/special.dm b/code/modules/projectiles/guns/energy/special.dm index c63c8358e2de..067a4bbc5d97 100644 --- a/code/modules/projectiles/guns/energy/special.dm +++ b/code/modules/projectiles/guns/energy/special.dm @@ -122,11 +122,12 @@ heat = 3800 usesound = list('sound/items/welder.ogg', 'sound/items/welder2.ogg') - tool_behaviour = TOOL_WELDER + tool_behaviour = TOOL_DECONSTRUCT wall_decon_damage = 200 - toolspeed = 0.7 //plasmacutters can be used as welders, and are faster than standard welders + toolspeed = 0.9 //plasmacutters can be used like angle grinders, and are a bit faster internal_cell = TRUE //so you don't cheese through the need for plasma - WS EDIT - var/charge_weld = 25 //amount of charge used up to start action (multiplied by amount) and per progress_flash_divisor ticks of welding + var/charge_cut = 100 //amount of charge used up to start action (multiplied by amount) and per progress_flash_divisor ticks of cutting + var/adv = FALSE /obj/item/gun/energy/plasmacutter/ComponentInitialize() . = ..() @@ -155,16 +156,16 @@ else ..() -// Can we weld? Plasma cutter does not use charge continuously. +// Can we cut? Plasma cutter does not use charge continuously. // Amount cannot be defaulted to 1: most of the code specifies 0 in the call. /obj/item/gun/energy/plasmacutter/tool_use_check(mob/living/user, amount) if(QDELETED(cell)) to_chat(user, "[src] does not have a cell, and cannot be used!") return FALSE - // Amount cannot be used if drain is made continuous, e.g. amount = 5, charge_weld = 25 + // Amount cannot be used if drain is made continuous, e.g. amount = 5, charge_cut = 25 // Then it'll drain 125 at first and 25 periodically, but fail if charge dips below 125 even though it still can finish action - // Alternately it'll need to drain amount*charge_weld every period, which is either obscene or makes it free for other uses - if(amount ? cell.charge < charge_weld * amount : cell.charge < charge_weld) + // Alternately it'll need to drain amount*charge_cut every period, which is either obscene or makes it free for other uses + if(amount ? cell.charge < charge_cut * amount : cell.charge < charge_cut) to_chat(user, "You need more charge to complete this task!") return FALSE @@ -186,13 +187,19 @@ return TRUE /obj/item/gun/energy/plasmacutter/use(amount) - return (!QDELETED(cell) && cell.use(amount ? amount * charge_weld : charge_weld)) + return (!QDELETED(cell) && cell.use(amount ? amount * charge_cut : charge_cut)) /obj/item/gun/energy/plasmacutter/use_tool(atom/target, mob/living/user, delay, amount=1, volume=0, datum/callback/extra_checks) if(amount) - target.add_overlay(GLOB.welding_sparks) + if(adv) + target.add_overlay(GLOB.advanced_cutting_effect) + else + target.add_overlay(GLOB.cutting_effect) . = ..() - target.cut_overlay(GLOB.welding_sparks) + if(adv) + target.cut_overlay(GLOB.advanced_cutting_effect) + else + target.cut_overlay(GLOB.cutting_effect) else . = ..(amount=1) @@ -201,11 +208,9 @@ icon_state = "adv_plasmacutter" item_state = "adv_plasmacutter" force = 15 + wall_decon_damage = 300 ammo_type = list(/obj/item/ammo_casing/energy/plasma/adv) - wall_decon_damage = 200 - toolspeed = 0.4 - /obj/item/gun/energy/wormhole_projector name = "bluespace wormhole projector" desc = "A projector that emits high density quantum-coupled bluespace beams." //WS Edit - Any anomaly core for phazons diff --git a/code/modules/projectiles/guns/manufacturer/clip_lanchester/ballistics.dm b/code/modules/projectiles/guns/manufacturer/clip_lanchester/ballistics.dm index f32a2f11a508..a244b188863a 100644 --- a/code/modules/projectiles/guns/manufacturer/clip_lanchester/ballistics.dm +++ b/code/modules/projectiles/guns/manufacturer/clip_lanchester/ballistics.dm @@ -223,7 +223,6 @@ EMPTY_GUN_HELPER(automatic/smg/cm5) righthand_file = 'icons/obj/guns/manufacturer/clip_lanchester/righthand.dmi' mob_overlay_icon = 'icons/obj/guns/manufacturer/clip_lanchester/onmob.dmi' - fire_sound = 'sound/weapons/gun/rifle/shot.ogg' icon_state = "f4" item_state = "f4" show_magazine_on_sprite = TRUE diff --git a/code/modules/projectiles/projectile/beams.dm b/code/modules/projectiles/projectile/beams.dm index c46a4c6cb2f9..b95c3dd37ddb 100644 --- a/code/modules/projectiles/projectile/beams.dm +++ b/code/modules/projectiles/projectile/beams.dm @@ -37,6 +37,15 @@ muzzle_type = /obj/effect/projectile/muzzle/laser impact_type = /obj/effect/projectile/impact/laser +/obj/projectile/beam/laser/sharplite + speed = 0.4 + +/obj/projectile/beam/laser/light + damage = 15 + +/obj/projectile/beam/laser/light/sharplite + speed = 0.4 + /obj/projectile/beam/laser/eoehoma damage = 25 armour_penetration = -10 @@ -54,6 +63,9 @@ muzzle_type = /obj/effect/projectile/muzzle/heavy_laser impact_type = /obj/effect/projectile/impact/heavy_laser +/obj/projectile/beam/laser/heavylaser/sharplite + speed = 0.4 + /obj/projectile/beam/laser/on_hit(atom/target, blocked = FALSE) . = ..() if(iscarbon(target)) @@ -119,9 +131,15 @@ muzzle_type = /obj/effect/projectile/muzzle/disabler impact_type = /obj/effect/projectile/impact/disabler +/obj/projectile/beam/disabler/sharplite + speed = 0.4 + /obj/projectile/beam/disabler/weak damage = 15 +/obj/projectile/beam/disabler/weak/sharplite + speed = 0.4 + /obj/projectile/beam/disabler/weak/negative_ap armour_penetration = -30 range = 9 @@ -148,6 +166,11 @@ return targets_turf.IgniteTurf(rand(8,22), "blue") +/obj/projectile/beam/pulse/sharplite_turret + wall_damage_flags = null + wall_damage_override = 0 + speed = 0.4 + /obj/projectile/beam/pulse/shotgun damage = 40 diff --git a/code/modules/projectiles/projectile/bullets/rifle.dm b/code/modules/projectiles/projectile/bullets/rifle.dm index 690f02d6b5c5..1d5d48c9b826 100644 --- a/code/modules/projectiles/projectile/bullets/rifle.dm +++ b/code/modules/projectiles/projectile/bullets/rifle.dm @@ -49,6 +49,13 @@ damage = 30 armour_penetration = 20 +/obj/projectile/bullet/a762_40/rubber //"rubber" + name = "7.62x40mm CLIP Rubber" + damage = 15 + stamina = 40 + armour_penetration = 20 + + //.308 WIN (M514 & GAL DMRs) /obj/projectile/bullet/a308 @@ -57,6 +64,13 @@ damage = 30 armour_penetration = 40 +/obj/projectile/bullet/a308/rubber //"rubber" + name = ".308 Rubber" + speed = 0.3 + damage = 25 + stamina = 50 + armour_penetration = 40 + // 8x58mm caseless (SG-669) /obj/projectile/bullet/a858 diff --git a/code/modules/projectiles/projectile/special/plasma.dm b/code/modules/projectiles/projectile/special/plasma.dm index d957ad924572..68071bd2c557 100644 --- a/code/modules/projectiles/projectile/special/plasma.dm +++ b/code/modules/projectiles/projectile/special/plasma.dm @@ -1,10 +1,10 @@ /obj/projectile/plasma name = "plasma blast" icon_state = "plasmacutter" - damage_type = BRUTE - damage = 5 + damage_type = BURN + damage = 15 range = 4 - dismemberment = 20 + dismemberment = 10 /// chance that the plasmablast ruins the ore var/slag_chance = 33 impact_effect_type = /obj/effect/temp_visual/impact_effect/purple_laser diff --git a/code/modules/surgery/organic_steps.dm b/code/modules/surgery/organic_steps.dm index 8959a7f99715..39fb1d71b258 100644 --- a/code/modules/surgery/organic_steps.dm +++ b/code/modules/surgery/organic_steps.dm @@ -152,13 +152,17 @@ implements = list( TOOL_SAW = 100, /obj/item/melee/axe/fire = 50, + /obj/item/gear_handle/anglegrinder = 50, /obj/item/melee/arm_blade = 40, /obj/item/hatchet = 40, /obj/item/melee/knife/butcher = 33, + /obj/item/gun/energy/plasmacutter = 30, /obj/item = 10) //10% success (sort of) with any sharp item with a force>=10 time = 5.4 SECONDS preop_sound = list( /obj/item/circular_saw = 'sound/surgery/saw.ogg', + /obj/item/gear_handle/anglegrinder = 'sound/surgery/saw.ogg', + /obj/item/gun/energy/plasmacutter = 'sound/weapons/plasma_cutter.ogg', /obj/item/melee/arm_blade = 'sound/surgery/scalpel1.ogg', /obj/item/melee/axe/fire = 'sound/surgery/scalpel1.ogg', /obj/item/hatchet = 'sound/surgery/scalpel1.ogg', diff --git a/html/changelogs/AutoChangeLog-pr-3146.yml b/html/changelogs/AutoChangeLog-pr-3146.yml new file mode 100644 index 000000000000..2b6397e66448 --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-3146.yml @@ -0,0 +1,5 @@ +author: Thera-Pissed +changes: + - {rscadd: angle grinders for salvage} + - {rscadd: reworks plasma cutters for salvage} +delete-after: true diff --git a/html/changelogs/AutoChangeLog-pr-3382.yml b/html/changelogs/AutoChangeLog-pr-3382.yml deleted file mode 100644 index eedebb40d990..000000000000 --- a/html/changelogs/AutoChangeLog-pr-3382.yml +++ /dev/null @@ -1,7 +0,0 @@ -author: Gristlebee, Rye-Rice, INFRARED_BARON -changes: - - {rscadd: Inteq Gygax and mech charges} - - {rscadd: Paladin shield backlash} - - {bugfix: Durand shield blocking all projectiles} - - {imageadd: Inteq Gygax sprites} -delete-after: true diff --git a/html/changelogs/AutoChangeLog-pr-3406.yml b/html/changelogs/AutoChangeLog-pr-3406.yml new file mode 100644 index 000000000000..16dcd1234872 --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-3406.yml @@ -0,0 +1,6 @@ +author: Bjarl +changes: + - {rscadd: IRMG engineers have rolled new turrets out into the frontier. Please + report back on their effectiveness. Unless you have been shot. Then you should + be dead.} +delete-after: true diff --git a/html/changelogs/AutoChangeLog-pr-3421.yml b/html/changelogs/AutoChangeLog-pr-3421.yml new file mode 100644 index 000000000000..7e32d923d25c --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-3421.yml @@ -0,0 +1,4 @@ +author: SomeguyManperson +changes: + - {rscdel: missions will no longer request capturing ice demons} +delete-after: true diff --git a/html/changelogs/AutoChangeLog-pr-3436.yml b/html/changelogs/AutoChangeLog-pr-3436.yml new file mode 100644 index 000000000000..6020a91bbc22 --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-3436.yml @@ -0,0 +1,5 @@ +author: Apogee-dev +changes: + - {balance: increased mudskipper limit to 2} + - {balance: cut a deckhand slot from kilo} +delete-after: true diff --git a/html/changelogs/AutoChangeLog-pr-3438.yml b/html/changelogs/AutoChangeLog-pr-3438.yml new file mode 100644 index 000000000000..f446f6f0d204 --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-3438.yml @@ -0,0 +1,4 @@ +author: Apogee-dev +changes: + - {balance: removed one recruit slot from the vaquero} +delete-after: true diff --git a/html/changelogs/AutoChangeLog-pr-3442.yml b/html/changelogs/AutoChangeLog-pr-3442.yml deleted file mode 100644 index 93368cdd5e5a..000000000000 --- a/html/changelogs/AutoChangeLog-pr-3442.yml +++ /dev/null @@ -1,4 +0,0 @@ -author: zimon9 -changes: - - {bugfix: fixed the waste and scrubber gas reclamation filters on the colossus} -delete-after: true diff --git a/html/changelogs/AutoChangeLog-pr-3451.yml b/html/changelogs/AutoChangeLog-pr-3451.yml new file mode 100644 index 000000000000..a09e9e0324b7 --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-3451.yml @@ -0,0 +1,5 @@ +author: Bjarl +changes: + - {rscadd: 'Sharplite has produced a line of turrets for Nanotrasen, which is now + mounting them on relevant vessels.'} +delete-after: true diff --git a/html/changelogs/AutoChangeLog-pr-3452.yml b/html/changelogs/AutoChangeLog-pr-3452.yml deleted file mode 100644 index 227901e38429..000000000000 --- a/html/changelogs/AutoChangeLog-pr-3452.yml +++ /dev/null @@ -1,6 +0,0 @@ -author: Jedi-Toothpaste -changes: - - {rscadd: Added extra intercoms in high traffic areas on the Valor Class} - - {rscadd: Added Firelocks underneath the Cargo-Bay Doors on the Valor Class} - - {rscadd: 'Air Alarms, Scrubbers and Vents to every applicable room'} -delete-after: true diff --git a/html/changelogs/AutoChangeLog-pr-3466.yml b/html/changelogs/AutoChangeLog-pr-3466.yml deleted file mode 100644 index d35081929039..000000000000 --- a/html/changelogs/AutoChangeLog-pr-3466.yml +++ /dev/null @@ -1,4 +0,0 @@ -author: generalthrax -changes: - - {balance: Replace red insuls with yellow insuls in syndicate toolboxes} -delete-after: true diff --git a/html/changelogs/AutoChangeLog-pr-3468.yml b/html/changelogs/AutoChangeLog-pr-3468.yml deleted file mode 100644 index a0130e2f3b75..000000000000 --- a/html/changelogs/AutoChangeLog-pr-3468.yml +++ /dev/null @@ -1,7 +0,0 @@ -author: Bjarl -changes: - - {rscadd: A cargo ship happened to lose an entire crate of Hammer Rocket Launchers - while travelling through the system. We have reason to believe they're probably - on sale now.} - - {rscdel: you can no longer purchase PML-9s on the black market.} -delete-after: true diff --git a/html/changelogs/AutoChangeLog-pr-3473.yml b/html/changelogs/AutoChangeLog-pr-3473.yml deleted file mode 100644 index 6ef0f09fd71e..000000000000 --- a/html/changelogs/AutoChangeLog-pr-3473.yml +++ /dev/null @@ -1,4 +0,0 @@ -author: PositiveEntropy -changes: - - {imageadd: Waste Planet Turfs Now Look Much More Refined!} -delete-after: true diff --git a/html/changelogs/AutoChangeLog-pr-3476.yml b/html/changelogs/AutoChangeLog-pr-3476.yml deleted file mode 100644 index 51594996de27..000000000000 --- a/html/changelogs/AutoChangeLog-pr-3476.yml +++ /dev/null @@ -1,4 +0,0 @@ -author: MemeSnorfer -changes: - - {rscadd: 'Three new Elzuose horn types. Cervid, Prong, and Brow'} -delete-after: true diff --git a/html/changelogs/archive/2024-10.yml b/html/changelogs/archive/2024-10.yml index 7dff4c0f36d5..2055dcb1e4c0 100644 --- a/html/changelogs/archive/2024-10.yml +++ b/html/changelogs/archive/2024-10.yml @@ -24,3 +24,28 @@ 2024-10-03: Bjarl: - bugfix: defibs now work again. +2024-10-05: + Bjarl: + - rscadd: A cargo ship happened to lose an entire crate of Hammer Rocket Launchers + while travelling through the system. We have reason to believe they're probably + on sale now. + - rscdel: you can no longer purchase PML-9s on the black market. + Gristlebee, Rye-Rice, INFRARED_BARON: + - rscadd: Inteq Gygax and mech charges + - rscadd: Paladin shield backlash + - bugfix: Durand shield blocking all projectiles + - imageadd: Inteq Gygax sprites + Jedi-Toothpaste: + - rscadd: Added extra intercoms in high traffic areas on the Valor Class + - rscadd: Added Firelocks underneath the Cargo-Bay Doors on the Valor Class + - rscadd: Air Alarms, Scrubbers and Vents to every applicable room + MemeSnorfer: + - rscadd: Three new Elzuose horn types. Cervid, Prong, and Brow + PositiveEntropy: + - imageadd: Waste Planet Turfs Now Look Much More Refined! + Thera-Pissed: + - rscadd: pipe dispenser UI is now similar to rapid pipe dispenser UI. + generalthrax: + - balance: Replace red insuls with yellow insuls in syndicate toolboxes + zimon9: + - bugfix: fixed the waste and scrubber gas reclamation filters on the colossus diff --git a/icons/effects/cutting_effect.dmi b/icons/effects/cutting_effect.dmi new file mode 100644 index 000000000000..e8b4abeec5d0 Binary files /dev/null and b/icons/effects/cutting_effect.dmi differ diff --git a/icons/mecha/mecha_equipment.dmi b/icons/mecha/mecha_equipment.dmi index 5e08a834a892..76549c15a3e0 100644 Binary files a/icons/mecha/mecha_equipment.dmi and b/icons/mecha/mecha_equipment.dmi differ diff --git a/icons/mob/clothing/back.dmi b/icons/mob/clothing/back.dmi index 5508bc67523c..fc00f899ed93 100644 Binary files a/icons/mob/clothing/back.dmi and b/icons/mob/clothing/back.dmi differ diff --git a/icons/mob/inhands/equipment/gear_handle_lefthand.dmi b/icons/mob/inhands/equipment/gear_handle_lefthand.dmi new file mode 100644 index 000000000000..169f91ce6eba Binary files /dev/null and b/icons/mob/inhands/equipment/gear_handle_lefthand.dmi differ diff --git a/icons/mob/inhands/equipment/gear_handle_righthand.dmi b/icons/mob/inhands/equipment/gear_handle_righthand.dmi new file mode 100644 index 000000000000..172f18e6095a Binary files /dev/null and b/icons/mob/inhands/equipment/gear_handle_righthand.dmi differ diff --git a/icons/obj/item/gear_packs.dmi b/icons/obj/item/gear_packs.dmi new file mode 100644 index 000000000000..76fb94bd4ff3 Binary files /dev/null and b/icons/obj/item/gear_packs.dmi differ diff --git a/icons/obj/mining.dmi b/icons/obj/mining.dmi index 337e3bf6d8da..efffc5cebb4a 100644 Binary files a/icons/obj/mining.dmi and b/icons/obj/mining.dmi differ diff --git a/shiptest.dme b/shiptest.dme index 7fdfccc47234..3c585e4a5bda 100644 --- a/shiptest.dme +++ b/shiptest.dme @@ -680,6 +680,7 @@ #include "code\datums\elements\selfknockback.dm" #include "code\datums\elements\snail_crawl.dm" #include "code\datums\elements\squish.dm" +#include "code\datums\elements\tool_bang.dm" #include "code\datums\elements\tool_flash.dm" #include "code\datums\elements\turf_transparency.dm" #include "code\datums\elements\undertile.dm" @@ -1187,6 +1188,7 @@ #include "code\game\objects\items\etherealdiscoball.dm" #include "code\game\objects\items\extinguisher.dm" #include "code\game\objects\items\flamethrower.dm" +#include "code\game\objects\items\gear_packs.dm" #include "code\game\objects\items\gift.dm" #include "code\game\objects\items\granters.dm" #include "code\game\objects\items\handcuffs.dm" @@ -2432,6 +2434,7 @@ #include "code\modules\mining\ores_coins.dm" #include "code\modules\mining\satchel_ore_boxdm.dm" #include "code\modules\mining\shelters.dm" +#include "code\modules\mining\equipment\angle_grinder.dm" #include "code\modules\mining\equipment\explorer_gear.dm" #include "code\modules\mining\equipment\kinetic_crusher.dm" #include "code\modules\mining\equipment\lazarus_injector.dm" diff --git a/sound/weapons/anglegrinder.ogg b/sound/weapons/anglegrinder.ogg new file mode 100644 index 000000000000..c0bc5b593a18 Binary files /dev/null and b/sound/weapons/anglegrinder.ogg differ diff --git a/tgui/packages/tgui-dev-server/package.json b/tgui/packages/tgui-dev-server/package.json index a026558a47a1..1a0f4c972244 100644 --- a/tgui/packages/tgui-dev-server/package.json +++ b/tgui/packages/tgui-dev-server/package.json @@ -4,7 +4,7 @@ "version": "4.3.1", "type": "module", "dependencies": { - "axios": "^1.6.0", + "axios": "^1.7.4", "glob": "^7.1.7", "source-map": "^0.7.3", "stacktrace-parser": "^0.1.10", diff --git a/tgui/packages/tgui/interfaces/PipeDispenser.js b/tgui/packages/tgui/interfaces/PipeDispenser.js new file mode 100644 index 000000000000..61798b67306a --- /dev/null +++ b/tgui/packages/tgui/interfaces/PipeDispenser.js @@ -0,0 +1,193 @@ +import { classes } from 'common/react'; +import { useBackend, useLocalState } from '../backend'; +import { + Box, + Button, + ColorBox, + Flex, + LabeledList, + Section, + Tabs, +} from '../components'; +import { Window } from '../layouts'; + +const ROOT_CATEGORIES = ['Atmospherics', 'Disposals', 'Transit Tubes']; + +const ICON_BY_CATEGORY_NAME = { + 'Atmospherics': 'wrench', + 'Disposals': 'trash-alt', + 'Transit Tubes': 'bus', + 'Pipes': 'grip-lines', + 'Disposal Pipes': 'grip-lines', + 'Devices': 'microchip', + 'Heat Exchange': 'thermometer-half', + 'Station Equipment': 'microchip', +}; + +const PAINT_COLORS = { + grey: '#bbbbbb', + amethyst: '#a365ff', + blue: '#4466ff', + brown: '#b26438', + cyan: '#48eae8', + dark: '#808080', + green: '#1edd00', + orange: '#ffa030', + purple: '#b535ea', + red: '#ff3333', + violet: '#6e00f6', + yellow: '#ffce26', +}; + +export const PipeDispenser = (props, context) => { + const { act, data } = useBackend(context); + const { + category: rootCategoryIndex, + categories = [], + selected_color, + piping_layer, + mode, + } = data; + const previews = data.preview_rows.flatMap((row) => row.previews); + const [categoryName, setCategoryName] = useLocalState( + context, + 'categoryName' + ); + const shownCategory = + categories.find((category) => category.cat_name === categoryName) || + categories[0]; + return ( + + +
+ + + {ROOT_CATEGORIES.map((categoryName, i) => ( +
+ + +
+ {rootCategoryIndex === 0 && ( + + {[1, 2, 3, 4, 5].map((layer) => ( + + act('piping_layer', { + piping_layer: layer, + }) + } + /> + ))} + + )} + + {previews.map((preview) => ( + + ))} + +
+
+ +
+ + {categories.map((category, i) => ( + setCategoryName(category.cat_name)} + > + {category.cat_name} + + ))} + + {shownCategory?.recipes.map((recipe) => ( + + act('pipe_type', { + pipe_type: recipe.pipe_index, + category: shownCategory.cat_name, + }) + } + /> + ))} +
+
+
+
+
+ ); +}; diff --git a/tgui/yarn.lock b/tgui/yarn.lock index bdf58e167804..6bb17b2fc675 100644 --- a/tgui/yarn.lock +++ b/tgui/yarn.lock @@ -2951,14 +2951,14 @@ __metadata: languageName: node linkType: hard -"axios@npm:^1.6.0": - version: 1.6.1 - resolution: "axios@npm:1.6.1" +"axios@npm:^1.7.4": + version: 1.7.5 + resolution: "axios@npm:1.7.5" dependencies: - follow-redirects: ^1.15.0 + follow-redirects: ^1.15.6 form-data: ^4.0.0 proxy-from-env: ^1.1.0 - checksum: 573f03f59b7487d54551b16f5e155d1d130ad4864ed32d1da93d522b78a57123b34e3bde37f822a65ee297e79f1db840f9ad6514addff50d3cbf5caeed39e8dc + checksum: 2859fe01437cf133eee35571abc1d4b5224bb13e530e66cb3581ca226e170541dd5eef9f46abb41592cee0a2f54930c9e4978354e0cf1064748fc20d9a05e9d5 languageName: node linkType: hard @@ -4814,13 +4814,13 @@ __metadata: languageName: node linkType: hard -"follow-redirects@npm:^1.15.0": - version: 1.15.4 - resolution: "follow-redirects@npm:1.15.4" +"follow-redirects@npm:^1.15.6": + version: 1.15.6 + resolution: "follow-redirects@npm:1.15.6" peerDependenciesMeta: debug: optional: true - checksum: e178d1deff8b23d5d24ec3f7a94cde6e47d74d0dc649c35fc9857041267c12ec5d44650a0c5597ef83056ada9ea6ca0c30e7c4f97dbf07d035086be9e6a5b7b6 + checksum: a62c378dfc8c00f60b9c80cab158ba54e99ba0239a5dd7c81245e5a5b39d10f0c35e249c3379eae719ff0285fff88c365dd446fab19dee771f1d76252df1bbf5 languageName: node linkType: hard @@ -8940,7 +8940,7 @@ resolve@^2.0.0-next.3: version: 0.0.0-use.local resolution: "tgui-dev-server@workspace:packages/tgui-dev-server" dependencies: - axios: ^1.6.0 + axios: ^1.7.4 glob: ^7.1.7 source-map: ^0.7.3 stacktrace-parser: ^0.1.10