From f9eaaea115e6a8fa7cc7277a9b6096ed446ae9ee Mon Sep 17 00:00:00 2001 From: Gandalf Date: Wed, 16 Jun 2021 22:24:47 +0100 Subject: [PATCH] Armadyne Munitions Workbench (#6318) * BOOYAH BABY * 0 * Update ammo_workbench.dm * a * a * Update modular_skyrat/modules/ammo_workbench/code/ammo_workbench.dm Co-authored-by: Matthew J. <12817816+ZephyrTFA@users.noreply.github.com> * AA * a * Update ammo_workbench.dm * AAAAAA * 0 * 0 * maps * Update ammo_workbench.dm * Update pirate_enclave.dmm * Update ammo_workbench.dm * Revert "Update ammo_workbench.dm" This reverts commit 319c97654436af308263863716d2570f6cdf6f59. * Update M45A5.dmi * a * Update ammo_workbench.dm * NOW WORKS WITH ALL AMMOBOXES * aAAAAAAAAAAAAA * AAAAAA * AAAAAAAA * turbomode * a * Update ammo_workbench.dm * Update _basemap.dm * Update modular_projectiles.dm Co-authored-by: Matthew J. <12817816+ZephyrTFA@users.noreply.github.com> --- .../Deltastation/DeltaStation2_skyrat.dmm | 2 +- .../IceBoxStation/IceBoxStation_skyrat.dmm | 4 +- .../KiloStation/KiloStation_skyrat.dmm | 2 +- .../MetaStation/MetaStation_skyrat.dmm | 2 +- _maps/map_files/NSSJourney/NSSJourney.dmm | 4 +- .../WaterKiloStation/WaterKiloStation.dmm | 2 +- .../tramstation/tramstation_skyrat.dmm | 2 +- .../tramstation/tramstation_skyrat_old.dmm | 2 +- _maps/shuttles/pirate_enclave.dmm | 17 +- .../ammunition/ballistic/revolver.dm | 1 + .../ammunition/ballistic/shotgun.dm | 2 + .../research/machinery/circuit_imprinter.dm | 3 +- code/modules/research/techweb/all_nodes.dm | 2 + .../ammo_workbench/code/ammo_workbench.dm | 535 ++++++++++++++++++ .../ammo_workbench/code/design_disks.dm | 18 + .../ammo_workbench/icons/ammo_workbench.dmi | Bin 0 -> 2149 bytes .../code/modules/jobs/job_types/blueshield.dm | 2 +- .../projectiles/guns/ballistic/ballistic.dm | 35 +- .../blueshield/icons/obj/guns/M45A5.dmi | Bin 1006 -> 755 bytes .../projectile/bullets/modular_projectiles.dm | 7 +- .../modules/sec_haul/code/guns/bullets.dm | 4 +- .../code/junior_officer/pepperball_gun.dm | 1 + tgstation.dme | 2 + .../packages/tgui/interfaces/AmmoWorkbench.js | 276 +++++++++ 24 files changed, 874 insertions(+), 51 deletions(-) create mode 100644 modular_skyrat/modules/ammo_workbench/code/ammo_workbench.dm create mode 100644 modular_skyrat/modules/ammo_workbench/code/design_disks.dm create mode 100644 modular_skyrat/modules/ammo_workbench/icons/ammo_workbench.dmi create mode 100644 tgui/packages/tgui/interfaces/AmmoWorkbench.js diff --git a/_maps/map_files/Deltastation/DeltaStation2_skyrat.dmm b/_maps/map_files/Deltastation/DeltaStation2_skyrat.dmm index f7d4b54737b..17d8535f23b 100644 --- a/_maps/map_files/Deltastation/DeltaStation2_skyrat.dmm +++ b/_maps/map_files/Deltastation/DeltaStation2_skyrat.dmm @@ -109464,7 +109464,7 @@ /obj/effect/turf_decal/tile/red{ dir = 8 }, -/obj/machinery/vending/security_ammo, +/obj/machinery/ammo_workbench, /turf/open/floor/iron/dark, /area/security/brig) "uIv" = ( diff --git a/_maps/map_files/IceBoxStation/IceBoxStation_skyrat.dmm b/_maps/map_files/IceBoxStation/IceBoxStation_skyrat.dmm index ca0713a6fd5..b13c46633c2 100644 --- a/_maps/map_files/IceBoxStation/IceBoxStation_skyrat.dmm +++ b/_maps/map_files/IceBoxStation/IceBoxStation_skyrat.dmm @@ -44913,7 +44913,7 @@ /obj/structure/window/reinforced{ dir = 4 }, -/obj/machinery/vending/security_ammo, +/obj/machinery/ammo_workbench, /turf/open/floor/iron/dark, /area/security/office) "qcl" = ( @@ -55454,7 +55454,7 @@ /turf/open/floor/iron, /area/hallway/primary/central) "vGa" = ( -/obj/machinery/vending/security_ammo, +/obj/machinery/ammo_workbench, /turf/open/floor/iron/dark, /area/security/office) "vGb" = ( diff --git a/_maps/map_files/KiloStation/KiloStation_skyrat.dmm b/_maps/map_files/KiloStation/KiloStation_skyrat.dmm index 735dcf99e18..f17b5989a09 100644 --- a/_maps/map_files/KiloStation/KiloStation_skyrat.dmm +++ b/_maps/map_files/KiloStation/KiloStation_skyrat.dmm @@ -77093,7 +77093,7 @@ /obj/effect/turf_decal/siding/red/corner{ dir = 4 }, -/obj/machinery/vending/security_ammo, +/obj/machinery/ammo_workbench, /turf/open/floor/iron/dark, /area/security/brig) "fLz" = ( diff --git a/_maps/map_files/MetaStation/MetaStation_skyrat.dmm b/_maps/map_files/MetaStation/MetaStation_skyrat.dmm index b6a2461dc0f..13fb243c445 100644 --- a/_maps/map_files/MetaStation/MetaStation_skyrat.dmm +++ b/_maps/map_files/MetaStation/MetaStation_skyrat.dmm @@ -28815,7 +28815,7 @@ dir = 4 }, /obj/structure/cable, -/obj/machinery/vending/security_ammo, +/obj/machinery/ammo_workbench, /turf/open/floor/iron/dark, /area/security/range) "dBN" = ( diff --git a/_maps/map_files/NSSJourney/NSSJourney.dmm b/_maps/map_files/NSSJourney/NSSJourney.dmm index f68f3431709..94202e6d63f 100644 --- a/_maps/map_files/NSSJourney/NSSJourney.dmm +++ b/_maps/map_files/NSSJourney/NSSJourney.dmm @@ -45051,7 +45051,7 @@ /obj/structure/window/reinforced{ dir = 4 }, -/obj/machinery/vending/security_ammo, +/obj/machinery/ammo_workbench, /turf/open/floor/iron/dark, /area/security/office) "kVn" = ( @@ -49916,7 +49916,7 @@ /turf/open/floor/iron/white, /area/science/explab) "pJj" = ( -/obj/machinery/vending/security_ammo, +/obj/machinery/ammo_workbench, /turf/open/floor/iron/dark, /area/security/office) "pKi" = ( diff --git a/_maps/map_files/WaterKiloStation/WaterKiloStation.dmm b/_maps/map_files/WaterKiloStation/WaterKiloStation.dmm index 4b6fd9c1abb..d13b686af54 100644 --- a/_maps/map_files/WaterKiloStation/WaterKiloStation.dmm +++ b/_maps/map_files/WaterKiloStation/WaterKiloStation.dmm @@ -31031,7 +31031,7 @@ /obj/effect/turf_decal/siding/red/corner{ dir = 4 }, -/obj/machinery/vending/security_ammo, +/obj/machinery/ammo_workbench, /turf/open/floor/iron/dark, /area/security/brig) "bFM" = ( diff --git a/_maps/map_files/tramstation/tramstation_skyrat.dmm b/_maps/map_files/tramstation/tramstation_skyrat.dmm index 2f1d9e29619..079d793a025 100644 --- a/_maps/map_files/tramstation/tramstation_skyrat.dmm +++ b/_maps/map_files/tramstation/tramstation_skyrat.dmm @@ -71451,7 +71451,7 @@ }, /area/service/chapel) "xnt" = ( -/obj/machinery/vending/security_ammo, +/obj/machinery/ammo_workbench, /obj/effect/turf_decal/bot, /turf/open/floor/iron/showroomfloor, /area/security/office) diff --git a/_maps/map_files/tramstation/tramstation_skyrat_old.dmm b/_maps/map_files/tramstation/tramstation_skyrat_old.dmm index 381c93183f6..7b9f228b85e 100644 --- a/_maps/map_files/tramstation/tramstation_skyrat_old.dmm +++ b/_maps/map_files/tramstation/tramstation_skyrat_old.dmm @@ -57496,7 +57496,7 @@ /turf/open/floor/plating/airless, /area/mine/explored) "rmF" = ( -/obj/machinery/vending/security_ammo, +/obj/machinery/ammo_workbench, /obj/effect/turf_decal/bot, /turf/open/floor/iron/showroomfloor, /area/security/office) diff --git a/_maps/shuttles/pirate_enclave.dmm b/_maps/shuttles/pirate_enclave.dmm index 2c2adbbe659..61db40fdd35 100644 --- a/_maps/shuttles/pirate_enclave.dmm +++ b/_maps/shuttles/pirate_enclave.dmm @@ -285,9 +285,10 @@ "kR" = ( /obj/structure/table/wood, /obj/effect/turf_decal/siding/wood, -/obj/item/storage/box/donkpockets/donkpocketpizza{ - pixel_y = 6 +/obj/item/storage/backpack/duffelbag/syndie/x4{ + pixel_y = 8 }, +/obj/item/storage/box/donkpockets/donkpocketteriyaki, /turf/open/floor/wood, /area/shuttle/syndicate/slaver) "kZ" = ( @@ -1295,16 +1296,8 @@ /turf/open/floor/carpet/red, /area/shuttle/syndicate/slaver) "ZD" = ( -/obj/structure/table/reinforced, -/obj/item/storage/backpack/duffelbag/syndie/x4{ - pixel_y = 8 - }, -/obj/item/grenade/smokebomb{ - pixel_x = -5 - }, -/obj/item/grenade/smokebomb{ - pixel_x = 5 - }, +/obj/machinery/ammo_workbench/unlocked, +/obj/item/stack/sheet/iron/five, /turf/open/floor/iron/dark, /area/shuttle/syndicate/slaver) diff --git a/code/modules/projectiles/ammunition/ballistic/revolver.dm b/code/modules/projectiles/ammunition/ballistic/revolver.dm index 8784bdeece3..307a114ab70 100644 --- a/code/modules/projectiles/ammunition/ballistic/revolver.dm +++ b/code/modules/projectiles/ammunition/ballistic/revolver.dm @@ -41,6 +41,7 @@ name = ".38 Rubber bullet casing" desc = "A .38 rubber bullet casing, manufactured to exceedingly bouncy standards." projectile_type = /obj/projectile/bullet/c38/match/bouncy + harmful = FALSE //SKYRAT EDIT ADDITION /obj/item/ammo_casing/c38/dumdum name = ".38 DumDum bullet casing" diff --git a/code/modules/projectiles/ammunition/ballistic/shotgun.dm b/code/modules/projectiles/ammunition/ballistic/shotgun.dm index 5e21c533c28..e4e91bcfe3a 100644 --- a/code/modules/projectiles/ammunition/ballistic/shotgun.dm +++ b/code/modules/projectiles/ammunition/ballistic/shotgun.dm @@ -27,6 +27,7 @@ icon_state = "bshell" custom_materials = list(/datum/material/iron=250) projectile_type = /obj/projectile/bullet/shotgun_beanbag + harmful = FALSE //SKYRAT EDIT ADDITION /obj/item/ammo_casing/shotgun/incendiary name = "incendiary slug" @@ -85,6 +86,7 @@ pellets = 6 variance = 25 custom_materials = list(/datum/material/iron=4000) + harmful = FALSE //SKYRAT EDIT ADDITION /obj/item/ammo_casing/shotgun/incapacitate name = "custom incapacitating shot" diff --git a/code/modules/research/machinery/circuit_imprinter.dm b/code/modules/research/machinery/circuit_imprinter.dm index fabe05ac597..8f032a146ac 100644 --- a/code/modules/research/machinery/circuit_imprinter.dm +++ b/code/modules/research/machinery/circuit_imprinter.dm @@ -15,7 +15,8 @@ "Research Machinery", "Misc. Machinery", "Computer Parts", - "Circuitry" + "Circuitry", + "Weapons Machinery" //SKYRAT EDIT CHANGE ) production_animation = "circuit_imprinter_ani" allowed_buildtypes = IMPRINTER diff --git a/code/modules/research/techweb/all_nodes.dm b/code/modules/research/techweb/all_nodes.dm index 3edc6a51313..6d6b99afb2c 100644 --- a/code/modules/research/techweb/all_nodes.dm +++ b/code/modules/research/techweb/all_nodes.dm @@ -1308,6 +1308,7 @@ prereq_ids = list("adv_engi", "weaponry") design_ids = list( "pin_loyalty", + "ammo_workbench", //SKYRAT EDIT ADDITION ) research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 10000) required_experiments = list(/datum/experiment/explosion/medium) @@ -1392,6 +1393,7 @@ "c38_hotshot", "c38_iceblox", "techshotshell", + "ammoworkbench_disk_lethal", //SKYRAT EDIT ADDITION ) research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2500) diff --git a/modular_skyrat/modules/ammo_workbench/code/ammo_workbench.dm b/modular_skyrat/modules/ammo_workbench/code/ammo_workbench.dm new file mode 100644 index 00000000000..8f3a92f2654 --- /dev/null +++ b/modular_skyrat/modules/ammo_workbench/code/ammo_workbench.dm @@ -0,0 +1,535 @@ +/obj/machinery/ammo_workbench + name = "Ammunitions Workbench" + desc = "A machine, somewhat akin to a lathe, made specifically for manufacturing ammunition. It has a slot for magazines." + icon = 'modular_skyrat/modules/ammo_workbench/icons/ammo_workbench.dmi' + icon_state = "ammobench" + density = TRUE + use_power = IDLE_POWER_USE + circuit = /obj/item/circuitboard/machine/ammo_workbench + var/busy = FALSE + var/hacked = FALSE + var/disabled = FALSE + var/shocked = FALSE + var/hack_wire + var/disable_wire + var/error_message = "" + var/error_type = "" + var/disk_error = "" + var/disk_error_type = "" + var/shock_wire + var/timer_id + var/turbo_boost = FALSE + var/obj/item/ammo_box/loaded_magazine = null + var/obj/item/disk/ammo_workbench/loaded_datadisk = null + /// A list of all currently allowed ammo types. + var/list/allowed_ammo_types = list() + var/list/allowed_harmful = FALSE + var/list/loaded_datadisks = list() + var/time_per_round = 20 + var/creation_efficiency = 1.6 + +/obj/machinery/ammo_workbench/unlocked + allowed_harmful = TRUE + +/obj/item/circuitboard/machine/ammo_workbench + name = "Ammunition Workbench (Machine Board)" + icon_state = "circuit_map" + build_path = /obj/machinery/ammo_workbench + req_components = list( + /obj/item/stock_parts/manipulator = 2, + /obj/item/stock_parts/matter_bin = 2, + /obj/item/stock_parts/micro_laser = 2 + ) + +/obj/machinery/ammo_workbench/Initialize() + AddComponent(/datum/component/material_container, SSmaterials.materials_by_category[MAT_CATEGORY_ITEM_MATERIAL], 0, MATCONTAINER_EXAMINE, allowed_items = /obj/item/stack, _after_insert = CALLBACK(src, .proc/AfterMaterialInsert)) + . = ..() + wires = new /datum/wires/ammo_workbench(src) + +/obj/machinery/ammo_workbench/ui_interact(mob/user, datum/tgui/ui) + ui = SStgui.try_update_ui(user, src, ui) + if(!ui) + ui = new(user, src, "AmmoWorkbench") + ui.open() + + if(shocked) + shock(user, 80) + +/obj/machinery/ammo_workbench/ui_data(mob/user) + var/list/data = list() + + data["loaded_datadisks"] = list() + data["datadisk_loaded"] = FALSE + data["datadisk_name"] = null + data["datadisk_desc"] = null + + data["disk_error"] = disk_error + data["disk_error_type"] = disk_error_type + + if(loaded_datadisk) + data["datadisk_loaded"] = TRUE + data["datadisk_name"] = initial(loaded_datadisk.name) + data["datadisk_desc"] = initial(loaded_datadisk.desc) + + for(var/type in loaded_datadisks) + var/obj/item/disk/ammo_workbench/disk = type + data["loaded_datadisks"] += list(list("loaded_disk_name" = initial(disk.name), "loaded_disk_desc" = initial(disk.desc))) + + data["mag_loaded"] = FALSE + data["error"] = null + data["error_type"] = null + data["system_busy"] = busy + + data["efficiency"] = creation_efficiency + data["time"] = time_per_round / 10 + data["hacked"] = allowed_harmful + data["turboBoost"] = turbo_boost + + data["materials"] = list() + var/datum/component/material_container/mat_container = GetComponent(/datum/component/material_container) + if (mat_container) + for(var/mat in mat_container.materials) + var/datum/material/M = mat + var/amount = mat_container.materials[M] + var/sheet_amount = amount / MINERAL_MATERIAL_AMOUNT + var/ref = REF(M) + data["materials"] += list(list("name" = M.name, "id" = ref, "amount" = sheet_amount)) + + if(error_message) + data["error"] = error_message + data["error_type"] = error_type + else if(busy) + data["error"] = "SYSTEM IS BUSY" + data["error_type"] = "" + + if(!loaded_magazine) + data["error"] = "NO MAGAZINE IS INSERTED" + data["error_type"] = "" + return data + else + data["mag_loaded"] = TRUE + + data["available_rounds"] = list() + var/obj/item/ammo_casing/ammo_type = loaded_magazine.ammo_type + + var/list/round_types = typesof(ammo_type) + for(var/casing as anything in round_types) + var/obj/item/ammo_casing/our_casing = casing + if(initial(our_casing.harmful) && !allowed_harmful) + continue + data["available_rounds"] += list(list( + "name" = initial(our_casing.name), + "typepath" = our_casing + )) + + data["mag_name"] = loaded_magazine.name + data["caliber"] = initial(ammo_type.caliber) + data["current_rounds"] = loaded_magazine.stored_ammo.len + data["max_rounds"] = loaded_magazine.max_ammo + + return data + +/obj/machinery/ammo_workbench/ui_act(action, params) + . = ..() + if(.) + return + switch(action) + if("EjectMag") + ejectItem() + . = TRUE + + if("FillMagazine") + var/type_to_pass = text2path(params["selected_type"]) + fill_magazine_start(type_to_pass) + . = TRUE + + if("Release") + + var/datum/component/material_container/mat_container = GetComponent(/datum/component/material_container) + + if(!mat_container) + return + var/datum/material/mat = locate(params["id"]) + + var/amount = mat_container.materials[mat] + if(!amount) + return + + var/stored_amount = CEILING(amount / MINERAL_MATERIAL_AMOUNT, 0.1) + + if(!stored_amount) + return + + var/desired = 0 + if (params["sheets"]) + desired = text2num(params["sheets"]) + + var/sheets_to_remove = round(min(desired,50,stored_amount)) + + mat_container.retrieve_sheets(sheets_to_remove, mat, loc) + . = TRUE + + if("ReadDisk") + loadDisk() + + if("EjectDisk") + ejectDisk() + + if("turboBoost") + toggleTurboBoost() + +/obj/machinery/ammo_workbench/proc/toggleTurboBoost() + turbo_boost = !turbo_boost + + if(turbo_boost) + time_per_round = 1 + creation_efficiency = 3 + else + RefreshParts() + +/obj/machinery/ammo_workbench/proc/ejectItem() + if(loaded_magazine) + loaded_magazine.forceMove(drop_location()) + loaded_magazine = null + busy = FALSE + error_message = "" + error_type = "" + if(timer_id) + deltimer(timer_id) + timer_id = null + update_appearance() + +/obj/machinery/ammo_workbench/proc/fill_magazine_start(casing_type) + if(machine_stat & (NOPOWER|BROKEN)) + busy = FALSE + if(timer_id) + deltimer(timer_id) + timer_id = null + return + + if(error_message) + error_message = "" + error_type = "" + + var/list/allowed_types = typecacheof(loaded_magazine.ammo_type) + + if(!(casing_type in allowed_types)) + error_message = "AMMUNITION MISSMATCH" + error_type = "bad" + return + + var/obj/item/ammo_casing/our_casing = casing_type + + if(initial(our_casing.harmful) && !allowed_harmful) + error_message = "SYSTEM CORRUPTION DETECTED" + error_type = "bad" + return + + if(!loaded_magazine) + error_message = "NO MAGAZINE INSERTED" + error_type = "" + return + + if(loaded_magazine.stored_ammo.len >= loaded_magazine.max_ammo) + error_message = "MAGAZINE IS FULL" + error_type = "good" + return + + if(busy) + return + + busy = TRUE + + timer_id = addtimer(CALLBACK(src, .proc/fill_round, casing_type), time_per_round, TIMER_STOPPABLE) + +/obj/machinery/ammo_workbench/proc/fill_round(casing_type) + if(machine_stat & (NOPOWER|BROKEN)) + busy = FALSE + if(timer_id) + deltimer(timer_id) + timer_id = null + return + + if(!loaded_magazine) + return + + var/datum/component/material_container/materials = GetComponent(/datum/component/material_container) + + var/obj/item/ammo_casing/new_casing = new casing_type + + var/list/required_materials = new_casing.get_material_composition() + + if(!materials.has_materials(required_materials)) + error_message = "INSUFFICIENT MATERIALS" + error_type = "bad" + ammo_fill_finish(FALSE) + qdel(new_casing) + return + + if(istype(new_casing, loaded_magazine.ammo_type)) + if(!loaded_magazine.give_round(new_casing)) + error_message = "AMMUNITION MISSMATCH" + error_type = "bad" + ammo_fill_finish(FALSE) + qdel(new_casing) + return + materials.use_materials(required_materials) + loaded_magazine.update_appearance() + flick("ammobench_process", src) + use_power(3000) + playsound(loc, 'sound/machines/piston_raise.ogg', 60, 1) + else + qdel(new_casing) + ammo_fill_finish(FALSE) + return + + if(loaded_magazine.stored_ammo.len >= loaded_magazine.max_ammo) + ammo_fill_finish() + error_message = "MAGAZINE IS FULL" + error_type = "good" + return + + updateDialog() + + timer_id = addtimer(CALLBACK(src, .proc/fill_round, casing_type), time_per_round, TIMER_STOPPABLE) + +/obj/machinery/ammo_workbench/proc/ammo_fill_finish(successfully = TRUE) + updateDialog() + if(successfully) + playsound(loc, 'sound/machines/ping.ogg', 40, TRUE) + else + playsound(loc, 'sound/machines/buzz-sigh.ogg', 40, TRUE) + update_appearance() + busy = FALSE + if(timer_id) + deltimer(timer_id) + timer_id = null + +/obj/machinery/ammo_workbench/proc/loadDisk() + disk_error = "" + disk_error_type = "" + if(!loaded_datadisk) + return FALSE + if(loaded_datadisk.type in loaded_datadisks) + disk_error = "ERROR: DISK BLUEPRINT ALREADY IN SYSTEM MEMEORY" + return FALSE + + if(istype(loaded_datadisk, /obj/item/disk/ammo_workbench/lethal)) + allowed_harmful = TRUE + loaded_datadisks += loaded_datadisk.type + disk_error = "DISK LOADED SUCCESSFULLY" + disk_error_type = "good" + return TRUE + + loaded_datadisks += loaded_datadisk.type + +/obj/machinery/ammo_workbench/proc/ejectDisk() + if(loaded_datadisk) + loaded_datadisk.forceMove(drop_location()) + loaded_datadisk = null + disk_error = "" + disk_error_type = "" + +/datum/design/board/ammo_workbench + name = "Machine Design (Ammunitions Workbench)" + desc = "A machine, somewhat akin to a lathe, made specifically for manufacturing ammunition. It has a slot for magazines." + id = "ammo_workbench" + build_path = /obj/item/circuitboard/machine/ammo_workbench + category = list("Weapons Machinery") + departmental_flags = DEPARTMENTAL_FLAG_SECURITY + + +//MISC MACHINE PROCS + +/obj/machinery/ammo_workbench/RefreshParts() + var/time_efficiency = 20 + for(var/obj/item/stock_parts/micro_laser/new_laser in component_parts) + time_efficiency -= new_laser.rating * 2 + time_per_round = clamp(time_efficiency, 1, 20) + + var/efficiency = 1.8 + for(var/obj/item/stock_parts/manipulator/new_manipulator in component_parts) + efficiency -= new_manipulator.rating * 0.2 + creation_efficiency = max(1,efficiency) // creation_efficiency goes 1.6 -> 1.4 -> 1.2 -> 1 per level of manipulator efficiency + + var/mat_capacity = 0 + for(var/obj/item/stock_parts/matter_bin/new_matter_bin in component_parts) + mat_capacity += new_matter_bin.rating * 75000 + var/datum/component/material_container/materials = GetComponent(/datum/component/material_container) + materials.max_amount = mat_capacity + +/obj/machinery/ammo_workbench/update_overlays() + . = ..() + if(loaded_magazine) + . += "ammobench_loaded" + +/obj/machinery/ammo_workbench/proc/AfterMaterialInsert(obj/item/item_inserted, id_inserted, amount_inserted) + if(istype(item_inserted, /obj/item/stack/ore/bluespace_crystal)) + use_power(MINERAL_MATERIAL_AMOUNT / 10) + else if(item_inserted.has_material_type(/datum/material/glass)) + flick("autolathe_r", src)//plays glass insertion animation by default otherwise + else + flick("autolathe_o", src)//plays metal insertion animation + + use_power(min(1000, amount_inserted / 100)) + updateUsrDialog() + +/obj/machinery/ammo_workbench/Destroy() + QDEL_NULL(wires) + if(timer_id) + deltimer(timer_id) + timer_id = null + if(loaded_magazine) + loaded_magazine.forceMove(loc) + loaded_magazine = null + . = ..() + return ..() + +/obj/machinery/ammo_workbench/proc/shock(mob/user, prb) + if(machine_stat & (BROKEN|NOPOWER)) // unpowered, no shock + return FALSE + if(!prob(prb)) + return FALSE + do_sparks(5, TRUE, src) + if (electrocute_mob(user, get_area(src), src, 0.7, TRUE)) + return TRUE + else + return FALSE + +/obj/machinery/ammo_workbench/attackby(obj/item/O, mob/user, params) + if (default_deconstruction_screwdriver(user, "[initial(icon_state)]_t", initial(icon_state), O)) + return + if(default_deconstruction_crowbar(O)) + return + if(panel_open && is_wire_tool(O)) + wires.interact(user) + return TRUE + if(is_refillable() && O.is_drainable()) + return FALSE //inserting reagents into the machine + if(Insert_Item(O, user)) + return TRUE + else + return ..() + + +/obj/machinery/ammo_workbench/proc/Insert_Item(obj/item/O, mob/living/user) + if(user.combat_mode) + return FALSE + if(!is_insertion_ready(user)) + return FALSE + if(istype(O, /obj/item/ammo_box)) + if(!user.transferItemToLoc(O, src)) + return FALSE + if(loaded_magazine) + to_chat(user, "You swap quickly swap [O] for [loaded_magazine].") + loaded_magazine.forceMove(drop_location()) + user.put_in_hands(loaded_magazine) + loaded_magazine = null + busy = FALSE + error_message = "" + error_type = "" + if(timer_id) + deltimer(timer_id) + timer_id = null + loaded_magazine = O + to_chat(user, "You insert [O] to into [src]'s reciprocal.") + flick("h_lathe_load", src) + update_appearance() + playsound(loc, 'sound/weapons/autoguninsert.ogg', 35, 1) + return TRUE + if(istype(O, /obj/item/disk/ammo_workbench)) + if(!user.transferItemToLoc(O, src)) + return FALSE + loaded_datadisk = O + to_chat(user, "You insert [O] to into [src]'s floppydisk port.") + flick("h_lathe_load", src) + update_appearance() + playsound(loc, 'sound/machines/terminal_insert_disc.ogg', 35, 1) + return TRUE + return FALSE + +/obj/machinery/ammo_workbench/proc/is_insertion_ready(mob/user, obj/item/O) + if(panel_open) + to_chat(user, "You can't load [src] while it's opened!") + return FALSE + if(disabled) + to_chat(user, "The insertion belts of [src] won't engage!") + return FALSE + if(machine_stat & BROKEN) + to_chat(user, "[src] is broken.") + return FALSE + if(machine_stat & NOPOWER) + to_chat(user, "[src] has no power.") + return FALSE + if(istype(O, /obj/item/disk/ammo_workbench) && loaded_datadisk) + to_chat(user, "[src] already has a disk inserted.") + return FALSE + return TRUE + +/obj/machinery/ammo_workbench/proc/reset(wire) + switch(wire) + if(WIRE_HACK) + if(!wires.is_cut(wire)) + adjust_hacked(FALSE) + if(WIRE_SHOCK) + if(!wires.is_cut(wire)) + shocked = FALSE + if(WIRE_DISABLE) + if(!wires.is_cut(wire)) + disabled = FALSE + +/obj/machinery/ammo_workbench/proc/adjust_hacked(state) + hacked = state + + +// WIRE DATUM +/datum/wires/ammo_workbench + holder_type = /obj/machinery/ammo_workbench + proper_name = "Ammunitions Workbench" + +/datum/wires/ammo_workbench/New(atom/holder) + wires = list( + WIRE_HACK, WIRE_DISABLE, + WIRE_SHOCK, WIRE_ZAP + ) + add_duds(6) + ..() + +/datum/wires/ammo_workbench/interactable(mob/user) + if(!..()) + return FALSE + var/obj/machinery/ammo_workbench/A = holder + if(A.panel_open) + return TRUE + +/datum/wires/ammo_workbench/get_status() + var/obj/machinery/ammo_workbench/A = holder + var/list/status = list() + status += "The red light is [A.disabled ? "on" : "off"]." + status += "The blue light is [A.hacked ? "on" : "off"]." + return status + +/datum/wires/ammo_workbench/on_pulse(wire) + var/obj/machinery/ammo_workbench/A = holder + switch(wire) + if(WIRE_HACK) + A.adjust_hacked(!A.hacked) + addtimer(CALLBACK(A, /obj/machinery/ammo_workbench.proc/reset, wire), 60) + if(WIRE_SHOCK) + A.shocked = !A.shocked + addtimer(CALLBACK(A, /obj/machinery/ammo_workbench.proc/reset, wire), 60) + if(WIRE_DISABLE) + A.disabled = !A.disabled + addtimer(CALLBACK(A, /obj/machinery/ammo_workbench.proc/reset, wire), 60) + +/datum/wires/ammo_workbench/on_cut(wire, mend) + var/obj/machinery/ammo_workbench/A = holder + switch(wire) + if(WIRE_HACK) + A.adjust_hacked(!mend) + if(WIRE_HACK) + A.shocked = !mend + if(WIRE_DISABLE) + A.disabled = !mend + if(WIRE_ZAP) + A.shock(usr, 50) diff --git a/modular_skyrat/modules/ammo_workbench/code/design_disks.dm b/modular_skyrat/modules/ammo_workbench/code/design_disks.dm new file mode 100644 index 00000000000..e6796ec271b --- /dev/null +++ b/modular_skyrat/modules/ammo_workbench/code/design_disks.dm @@ -0,0 +1,18 @@ +/obj/item/disk/ammo_workbench + name = "Armadyne Munitions Blueprint Datadisk" + desc = "You shouldn't be seeing this!" + var/list/loaded_ammo_types + +/obj/item/disk/ammo_workbench/lethal + name = "Lethal Munitions Datadisk" + desc = "An Armadyne datadisk filled with lethal casing design blueprints for the Ammunitions Workbench." + icon_state = "datadisk0" + +/datum/design/disk/ammo_workbench_lethal + name = "Ammo Workbench: Lethal Munitions Datadisk" + id = "ammoworkbench_disk_lethal" + build_type = PROTOLATHE + materials = list(/datum/material/iron = 1000) + build_path = /obj/item/disk/ammo_workbench/lethal + category = list("intial", "Security", "Ammo") + departmental_flags = DEPARTMENTAL_FLAG_SECURITY diff --git a/modular_skyrat/modules/ammo_workbench/icons/ammo_workbench.dmi b/modular_skyrat/modules/ammo_workbench/icons/ammo_workbench.dmi new file mode 100644 index 0000000000000000000000000000000000000000..05eacaa2df2a563355b33764c410d1770cab91d7 GIT binary patch literal 2149 zcmV-r2%7haP)V=-0C=30j=u_nFc`$=d{1%cTEzYVrz|B>9P|}RYQ8oBV@eWQ`t}_ht3!u_ zJGkF*CC=@o8=(4*UL2DPGbBz`P2%lLwvad;NLY3co0pKX&J2k{dmnB*kG3FTTuhMI zlekCidGWu^>lCzM^9S&ZVdRw7iH3yXNq-IP3n#|gU8 z000MsNklZ%h+s9LK*k#W~i%iB&Ab3_GG@%thRknZ` z8;LR7UMySUoB2j(Omx0*iaL@(n8am>dqF0hx~YIbqDT;|>;-f%(92@F4U@4K-JPYq z()<5h?|D9nIeK^8=lRj6ch9wbzPbW|02uT#i*y4RWN{mHpwo3NQ%d*UzO~F{l-Dkh zu3xL)unqtK@9x}|bRUlM;K0GJrkvObNY}5$&n^L!V`vB9IFFHsOF2l_uf=cZCE)85 z^)qgN>&paY$q?b2hBwm=5}U@gBA0FdMJA|o?XTgy#^bp0g# z)5ZYjFSM#|Ks1T2GlPSJ0DzVsFY7wK*^sWEgg=m*o@MbuLNZoUbPx5)T+^G!Gw*r?eT z*8#jH~#BBZ>xiN(X_zhklD&x6t>r>UODxbp2ZVy|=otWND!$zdLrr`1m-| z(q^k_fQZs-d?+-Mbe}{|_RZEsC@xafEJf(4|7PnV0Q&0J>c82#2!+oV;nAZ>P5!tu zz_Mj8D3(Xl*LNG8o$dHJF!MmBgfE342s7@}P=AKl2Sr-y@56cs2Gy_D--q?^Li^ue z>Hry;nb=ib1po;D^>Jzy0`qoZgj1)DJ*W8>BOUoo~&oz{vX5Jo%*kZU9NI$!ZuI9meNd zkIHWQ^57RJD0t2=mr;%gQ!LMU?QR z343!1U#hJt3m{!TDZlKefm!o%WtSqJr##dCiG)HUn5;O2e$SP-WhgX)n!N`U-2#$E zPyN~Z4`ayJAuT5>4q?dGflz1!$4)4#-%7vg?*o*TZIE3*HaZNB<8bfdDlA^t9=Dtr z@S~~GCGDH4B&+}Wkyntj@-nU;S%c!5U!-Nvj!JxU>hZpI@w)F5w0hpiSd;sQW`2fsM z$ZxxR0On7jd;q<3)8$a=H^Z&eZw#uK#t<|q9A3&U&4j7jYpwu7jw%Q--w$d->*5kKL zJ^=GOEFVD49Cfqu36!?M%zOkTZ7@5ZL2N@nW>%SL`2cF?$eWQ*pr#FGgw%H;dfcaTI0P{N~A0XA{$J6dNJRcy{=Eu|Sw?#ex^HZJ=!2Fcw128|!2Vj0e ze%s~)Fh7O)0L)KuJ^=Hxd;kUk44oK~idg)@vmK7<0N*!XO?of=diiSGgj3oD$K(S5 zGta&I?rgKvMkoH)^;&UMJ^%o8_w>cBD_ULvAksdw{iz0<8%Q~h$_HSm$5HtJ-<@ri zU0<+g3(5h&WPd8+n0$cpqx-P=wa8ne)yu~)v|<*1s`aAg(j-26Zv~3o6)5Ll#JTiz z;EkQ8wk4Ht%ow2g!+of^G>Mu^lh{}}g}knRabf=`03bLN1OUtl+`xukyGb_Fb~q*< zfa9{z^3JnZ%UwfLqYG`q%Ru8boP2dQ{CWPQep+!%KEUAMAc8|d9Nj;K^`BhaTxu6%%Ktj-6B zMGyo-{IubSe1K@Q`f0_qe1KTCAHOdbILJS-o8a#%h9 zWbdR^E@9tJ&LrSR#-j&<*PgKlD1WKM zrAb-A)z1YSi~ul|VP_W)Yxw{G0jx;+z+z}VKee>HRWrum1{J7HQujQfp;Q0k%CMXIvuPS8wuK71wNi^GrknNG zH^2xLL)b-YK{nhlOvUgMigm;6brAcDRl_WyQh9a5slC}7PA|^XaKUmNv48j!u?&+I zgnfRiD#2D3XuGZwq!(YW9ndBh7p+uh5G!>Su~26cpPU?nqh(osQ}~wWR`1Fz%lQv* zzx&MGVxF=r{1TI8doCHQ9eL`eEGv>#M3(J`2QWOmVoTlXEZYx~0P%92k!5Kju>t%S zG|#d&F`Qb^dZBg7ZDv`6&08Cm;-xH`LL5Ra@h(Rk!oQpJdBpG5{dsX!am_Y$p^U-N z7al|F!o?~$dc$LAU4;3$qQ46J7lhF)H={UeSO5S307*qo IM6N<$f~y)aJ^%m! delta 943 zcmV;g15o_)1?~qWiBL{Q4GJ0x0000DNk~Le0001>0001h2m=5B0K2`CDF6TfW056K ze}tS)#nf`%wms_GgTX{T&}B~_lEQ+**d)W`d;kCd0d!JMQvg8b*k%9#0MvR^Sad{X zb7OL8aCB*JZU6vyoSl=w4uUWcM9=gq8aPW(!J8KYF&yLNe~gGXD(>XNOj-)nNH>}7hV+g(F-c#?2}^w9 zab^3-uZdS%ro~f#rb^A4Ka-UKw;)=AIbQ_-Nmw%iYq>Uj0A?4)%P`(Wt9k%f3M$EK z6bQme1}Ib-05f(*wGPGGp{j&Mp+a}=hOCNW-@Bp)yvm~3dATTZzNfEbK(iv9f8X*B z^%EjM(#Hi%00076NklcpL{JTH^_J@N9KY zg`nazzMfc>dR3(W05xbD9sQryn(eHHZrj)j?q3_Wvle<{{qJ;BmtK*Za(x?*}}>-^CdxFKvvOJF|fFbZf13 zFEm8hPXGz6E~n9VSu)Fju_JbYv+jazYI`rK;Z*aR{9a7cNZ)84imihzpnd%C>iwoeMi*J z5v9Mr-aGo*IpXv_qTqmIM9~2$qVRwK0Fck{XGE%}hT*T{<|bv<^3?6%ISfKQb$hsT z9PW}AtmHY-!?<7_Pkcake+oo<;s=O;xgL&SrgugG?>!H4kKiNml=gW07=~x!U%3H3 z^Df99H1m4=fG?icpT5IgHw0vQQ-PH#v1)l!ft4(=YI#$El@@DxK_yZpQ7zA_BT_v8 z007b{-urRaWqK?0e%y6=9{Ryt?~FbfqntU7^Z|0kUV14eFwOjln z$gSTVc>#;pZ^iq;N*?;bJP-X~wx`e!7VrQ707$2FpSMCkDBD9nnCprESRy_k%9%_L z0dqYZ!AuVUqaO2Xa^?HMvg?-b2djO5u(ZeAF#5qf5B*@ar_c`;@W8q81_g-D=Hpy2 RCIA2c07*qoM6N<$0fL8|xvu~K diff --git a/modular_skyrat/modules/modular_weapons/code/modules/projectiles/projectile/bullets/modular_projectiles.dm b/modular_skyrat/modules/modular_weapons/code/modules/projectiles/projectile/bullets/modular_projectiles.dm index af4f1198fa5..9c223313841 100644 --- a/modular_skyrat/modules/modular_weapons/code/modules/projectiles/projectile/bullets/modular_projectiles.dm +++ b/modular_skyrat/modules/modular_weapons/code/modules/projectiles/projectile/bullets/modular_projectiles.dm @@ -21,6 +21,7 @@ desc = "A .32 rubber bullet casing." caliber = "c32acp" projectile_type = /obj/projectile/bullet/c32/rubber + harmful = FALSE /obj/projectile/bullet/c32/rubber name = ".32 rubber bullet" @@ -61,6 +62,7 @@ desc = "A 10mm Magnum bullet casing. This fires a non-lethal projectile to cause compliance by pain and bruising. Don't aim for the head." caliber = CALIBER_10MM projectile_type = /obj/projectile/bullet/c10mm/rubber + harmful = FALSE /obj/projectile/bullet/c10mm/rubber name = "10mm Magnum rubber ball" @@ -117,6 +119,7 @@ name = "4.6x30mm rubber bullet casing" desc = "A 4.6x30mm rubber bullet casing." projectile_type = /obj/projectile/bullet/c46x30mm_rubber + harmful = FALSE ///// HK 4.6x30mm ///// //////////////////////// @@ -127,6 +130,7 @@ desc = "A 5.56mm rubber bullet casing." caliber = CALIBER_A556 projectile_type = /obj/projectile/bullet/a556/rubber + harmful = FALSE /obj/projectile/bullet/a556/rubber name = "5.56mm rubber bullet" @@ -162,6 +166,7 @@ icon_state = "762-casing" caliber = CALIBER_A762 projectile_type = /obj/projectile/bullet/a762/rubber + harmful = FALSE /obj/projectile/bullet/a762/rubber name = "7.62mm rubber bullet" @@ -173,7 +178,7 @@ ricochet_decay_damage = 0.7 shrapnel_type = null sharpness = NONE - embedding = null + embedding = null ////// 7.62 ////// //////////////////////// diff --git a/modular_skyrat/modules/sec_haul/code/guns/bullets.dm b/modular_skyrat/modules/sec_haul/code/guns/bullets.dm index 3da7bf170f2..72d32e87431 100644 --- a/modular_skyrat/modules/sec_haul/code/guns/bullets.dm +++ b/modular_skyrat/modules/sec_haul/code/guns/bullets.dm @@ -344,7 +344,7 @@ icon_state = "sr-casing" caliber = CALIBER_473MM projectile_type = /obj/projectile/bullet/advanced/b473/rubber - harmful = TRUE + harmful = FALSE /obj/projectile/bullet/advanced/b473/rubber name = "4.73x33mm rubber bullet" @@ -366,7 +366,7 @@ icon_state = "si-casing" caliber = CALIBER_473MM projectile_type = /obj/projectile/bullet/advanced/b473/ihdf - harmful = TRUE + harmful = FALSE /obj/projectile/bullet/advanced/b473/ihdf name = "4.73x33mm ihdf bullet" diff --git a/modular_skyrat/modules/sec_haul/code/junior_officer/pepperball_gun.dm b/modular_skyrat/modules/sec_haul/code/junior_officer/pepperball_gun.dm index 21a7c50f2c1..7272687f6ba 100644 --- a/modular_skyrat/modules/sec_haul/code/junior_officer/pepperball_gun.dm +++ b/modular_skyrat/modules/sec_haul/code/junior_officer/pepperball_gun.dm @@ -32,6 +32,7 @@ desc = "A pepperball casing." caliber = CALIBER_PEPPERBALL projectile_type = /obj/projectile/bullet/pepperball + harmful = FALSE /obj/projectile/bullet/pepperball name = "pepperball orb" diff --git a/tgstation.dme b/tgstation.dme index 849676f7dc3..85698487fd8 100644 --- a/tgstation.dme +++ b/tgstation.dme @@ -3824,6 +3824,8 @@ #include "modular_skyrat\modules\ambitions\code\ambition_templates.dm" #include "modular_skyrat\modules\ambitions\code\antag_datums.dm" #include "modular_skyrat\modules\ambitions\code\mind.dm" +#include "modular_skyrat\modules\ammo_workbench\code\ammo_workbench.dm" +#include "modular_skyrat\modules\ammo_workbench\code\design_disks.dm" #include "modular_skyrat\modules\antagonists\code\gamemodes.dm" #include "modular_skyrat\modules\antagonists\code\gang_things.dm" #include "modular_skyrat\modules\antagonists\eldritch_cult\knowledge\ash_lore_skyrat.dm" diff --git a/tgui/packages/tgui/interfaces/AmmoWorkbench.js b/tgui/packages/tgui/interfaces/AmmoWorkbench.js new file mode 100644 index 00000000000..370a827f593 --- /dev/null +++ b/tgui/packages/tgui/interfaces/AmmoWorkbench.js @@ -0,0 +1,276 @@ +import { toTitleCase } from 'common/string'; +import { useBackend, useSharedState, useLocalState } from '../backend'; +import { Box, Button, NumberInput, NoticeBox, ProgressBar, Section, Flex, Stack, RoundGauge, Tabs, Table } from '../components'; +import { Window } from '../layouts'; + +export const AmmoWorkbench = (props, context) => { + const [tab, setTab] = useSharedState(context, 'tab', 1); + return ( + + + + setTab(1)}> + Ammunitions + + setTab(2)}> + Materials + + setTab(3)}> + Datadisks + + + {tab === 1 && ( + + )} + {tab === 2 && ( + + )} + {tab === 3 && ( + + )} + + + ); +}; + +export const AmmunitionsTab = (props, context) => { + const { act, data } = useBackend(context); + const { + mag_loaded, + system_busy, + hacked, + error, + error_type, + mag_name, + turboBoost, + current_rounds, + max_rounds, + efficiency, + time, + available_rounds = [], + } = data; + return ( + <> + {!!error && ( + + {error} + + )} +
+ + Current Efficiency: null} + /> + + + Time Per Round: {time} seconds + + act('turboBoost')}> + Turbo Boost + +
+
+ {!!mag_loaded && ( + + + + )} +
+
+ {!!mag_loaded && ( + + {available_rounds.map(available_round => ( + + +
+ {!!hacked &&( + + !WARNING! - ARMADYNE SAFETY PROTOCOLS ARE NOT ENGAGED! + MISUSE IS NOT COVERED UNDER WARRANTY. + SOME MUNITION TYPES MAY CONSTITUTE A WAR CRIME IN YOUR AREA. + PLEASE CONTACT AN ARMADYNE ADMINISTRATOR IMMEDIATELY. + + )} + + ); +}; + +export const MaterialsTab = (props, context) => { + const { act, data } = useBackend(context); + const { + materials = [], + } = data; + return ( +
+ + {materials.map(material => ( + act('Release', { + id: material.id, + sheets: amount, + })} /> + ))} +
+
+ ); +}; + +export const DatadiskTab = (props, context) => { + const { act, data } = useBackend(context); + const { + loaded_datadisks = [], + datadisk_loaded, + datadisk_name, + datadisk_desc, + disk_error, + disk_error_type, + } = data; + return ( + <> + {!!disk_error && ( + + {disk_error} + + )} +
+
+
+ + {loaded_datadisks.map(loaded_datadisk => ( + + {loaded_datadisk.loaded_disk_name} + + Description: {loaded_datadisk.loaded_disk_desc} + + + ))} +
+
+ + ); +}; + +const MaterialRow = (props, context) => { + const { material, onRelease } = props; + + const [ + amount, + setAmount, + ] = useLocalState(context, "amount" + material.name, 1); + + const amountAvailable = Math.floor(material.amount); + return ( + + + {toTitleCase(material.name).replace('Alloy', '')} + + + + {material.value && material.value + ' cr'} + + + + + {amountAvailable} sheets + + + + setAmount(value)} /> +