From 7a30d5fdc487b85966ca06d4218756eef85e695c Mon Sep 17 00:00:00 2001 From: Iajret Creature <122297233+Steals-The-PRs@users.noreply.github.com> Date: Tue, 6 Feb 2024 14:32:41 +0300 Subject: [PATCH] [MIRROR] Exosuit-mounted RCD now works like the handheld version (#1792) * Exosuit-mounted RCD now works like the handheld version (#81162) --------- Co-authored-by: NovaBot <154629622+NovaBot13@users.noreply.github.com> Co-authored-by: SapphicOverload <93578146+SapphicOverload@users.noreply.github.com> --- code/__DEFINES/construction/rcd.dm | 3 + code/__DEFINES/mecha.dm | 1 + code/game/objects/items/rcd/RCD.dm | 61 +++++++- code/game/objects/items/rcd/RHD.dm | 5 +- code/game/turfs/open/floor/plating.dm | 1 - .../mecha/equipment/tools/work_tools.dm | 143 +++++++----------- code/modules/vehicles/mecha/mecha_defense.dm | 10 ++ .../tgui/interfaces/Mecha/ModulesPane.tsx | 49 ++++++ 8 files changed, 176 insertions(+), 97 deletions(-) diff --git a/code/__DEFINES/construction/rcd.dm b/code/__DEFINES/construction/rcd.dm index e8c9ae55f32..95c5ab80053 100644 --- a/code/__DEFINES/construction/rcd.dm +++ b/code/__DEFINES/construction/rcd.dm @@ -19,6 +19,9 @@ /// Time taken for an rcd hologram to disappear #define RCD_HOLOGRAM_FADE_TIME (15 SECONDS) +/// Delay before another rcd scan can be performed in the UI +#define RCD_DESTRUCTIVE_SCAN_COOLDOWN (RCD_HOLOGRAM_FADE_TIME + 1 SECONDS) + //All available upgrades /// Upgrade for building machines #define RCD_UPGRADE_FRAMES (1 << 0) diff --git a/code/__DEFINES/mecha.dm b/code/__DEFINES/mecha.dm index 8fd3ff4888c..33c8ca373a7 100644 --- a/code/__DEFINES/mecha.dm +++ b/code/__DEFINES/mecha.dm @@ -48,6 +48,7 @@ #define MECHA_SNOWFLAKE_ID_GENERATOR "generator_snowflake" #define MECHA_SNOWFLAKE_ID_ORE_SCANNER "orescanner_snowflake" #define MECHA_SNOWFLAKE_ID_CLAW "lawclaw_snowflake" +#define MECHA_SNOWFLAKE_ID_RCD "rcd_snowflake" #define MECHA_AMMO_INCENDIARY "Incendiary bullet" #define MECHA_AMMO_BUCKSHOT "Buckshot shell" diff --git a/code/game/objects/items/rcd/RCD.dm b/code/game/objects/items/rcd/RCD.dm index ab97026a6a1..7e14ca91b3f 100644 --- a/code/game/objects/items/rcd/RCD.dm +++ b/code/game/objects/items/rcd/RCD.dm @@ -1,9 +1,6 @@ /// Multiplier applied on construction & deconstruction time when building multiple structures #define FREQUENT_USE_DEBUFF_MULTIPLIER 3 -/// Delay before another rcd scan can be performed in the UI -#define RCD_DESTRUCTIVE_SCAN_COOLDOWN (RCD_HOLOGRAM_FADE_TIME + 1 SECONDS) - //RAPID CONSTRUCTION DEVICE /obj/item/construction/rcd @@ -33,8 +30,8 @@ /// The path of the structure the rcd is currently creating var/atom/movable/rcd_design_path - /// owner of this rcd. It can either be an construction console or an player - var/owner + /// Owner of this rcd. It can either be a construction console, player, or mech. + var/atom/owner /// used by arcd, can this rcd work from a range var/ranged = FALSE /// delay multiplier for all construction types @@ -243,8 +240,9 @@ return FALSE var/beam if(ranged) - beam = user.Beam(target, icon_state = "rped_upgrade", time = delay) - if(!do_after(user, delay, target = target)) + var/atom/beam_source = owner ? owner : user + beam = beam_source.Beam(target, icon_state = "rped_upgrade", time = delay) + if(delay && !do_after(user, delay, target = target)) // no need for do_after with no delay qdel(rcd_effect) if(!isnull(beam)) qdel(beam) @@ -510,8 +508,55 @@ has_ammobar = FALSE upgrade = RCD_ALL_UPGRADES & ~RCD_UPGRADE_SILO_LINK +/obj/item/construction/rcd/exosuit + name = "mounted RCD" + desc = "An exosuit-mounted Rapid Construction Device." + max_matter = INFINITY // mass-energy equivalence go brrrrrr + canRturf = TRUE + ranged = TRUE + has_ammobar = FALSE + resistance_flags = FIRE_PROOF | INDESTRUCTIBLE // should NOT be destroyed unless the equipment is destroyed + item_flags = NO_MAT_REDEMPTION | NOBLUDGEON | DROPDEL // already qdeleted in the equipment's Destroy() but you can never be too sure + delay_mod = 0.5 + ///How much charge is used up for each matter unit. + var/mass_to_energy = 16 + +/obj/item/construction/rcd/exosuit/ui_status(mob/user) + if(ismecha(owner)) + return owner.ui_status(user) + return UI_CLOSE + +/obj/item/construction/rcd/exosuit/get_matter(mob/user) + if(silo_link) + return ..() + if(!ismecha(owner)) + return 0 + var/obj/vehicle/sealed/mecha/gundam = owner + return round(gundam.get_charge() / mass_to_energy) + +/obj/item/construction/rcd/exosuit/useResource(amount, mob/user) + if(silo_link) + return ..() + if(!ismecha(owner)) + return 0 + var/obj/vehicle/sealed/mecha/gundam = owner + if(!gundam.use_power(amount * mass_to_energy)) + gundam.balloon_alert(user, "insufficient charge!") + return FALSE + return TRUE + +/obj/item/construction/rcd/exosuit/checkResource(amount, mob/user) + if(silo_link) + return ..() + if(!ismecha(owner)) + return 0 + var/obj/vehicle/sealed/mecha/gundam = owner + if(!gundam.has_charge(amount * mass_to_energy)) + gundam.balloon_alert(user, "insufficient charge!") + return FALSE + return TRUE + #undef FREQUENT_USE_DEBUFF_MULTIPLIER -#undef RCD_DESTRUCTIVE_SCAN_COOLDOWN /obj/item/rcd_ammo name = "RCD matter cartridge" diff --git a/code/game/objects/items/rcd/RHD.dm b/code/game/objects/items/rcd/RHD.dm index 8abf1f2e3f2..9151c85ed03 100644 --- a/code/game/objects/items/rcd/RHD.dm +++ b/code/game/objects/items/rcd/RHD.dm @@ -95,16 +95,17 @@ /obj/item/construction/proc/install_upgrade(obj/item/rcd_upgrade/design_disk, mob/user) if(design_disk.upgrade & upgrade) balloon_alert(user, "already installed!") - return + return FALSE if(design_disk.upgrade & banned_upgrades) balloon_alert(user, "cannot install upgrade!") - return + return FALSE upgrade |= design_disk.upgrade if((design_disk.upgrade & RCD_UPGRADE_SILO_LINK) && !silo_mats) silo_mats = AddComponent(/datum/component/remote_materials, FALSE, FALSE) playsound(loc, 'sound/machines/click.ogg', 50, TRUE) qdel(design_disk) update_static_data_for_all_viewers() + return TRUE /// Inserts matter into the RCD allowing it to build /obj/item/construction/proc/insert_matter(obj/item, mob/user) diff --git a/code/game/turfs/open/floor/plating.dm b/code/game/turfs/open/floor/plating.dm index 3e58d647023..8634883762f 100644 --- a/code/game/turfs/open/floor/plating.dm +++ b/code/game/turfs/open/floor/plating.dm @@ -314,7 +314,6 @@ icon = 'icons/hud/radial.dmi' icon_state = "wallfloor" - #undef PLATE_INTACT #undef PLATE_BOLTS_LOOSENED #undef PLATE_CUT diff --git a/code/modules/vehicles/mecha/equipment/tools/work_tools.dm b/code/modules/vehicles/mecha/equipment/tools/work_tools.dm index 5907ee98903..1960303baab 100644 --- a/code/modules/vehicles/mecha/equipment/tools/work_tools.dm +++ b/code/modules/vehicles/mecha/equipment/tools/work_tools.dm @@ -217,117 +217,88 @@ attempt_refill(usr) return TRUE -#define MODE_DECONSTRUCT 0 -#define MODE_WALL 1 -#define MODE_AIRLOCK 2 - /obj/item/mecha_parts/mecha_equipment/rcd name = "mounted RCD" desc = "An exosuit-mounted Rapid Construction Device." icon_state = "mecha_rcd" - equip_cooldown = 10 - energy_drain = 250 + equip_cooldown = 0 // internal RCD already handles it + energy_drain = 0 // internal RCD handles power consumption based on matter use range = MECHA_MELEE|MECHA_RANGED item_flags = NO_MAT_REDEMPTION - ///determines what we'll so when clicking on a turf - var/mode = MODE_DECONSTRUCT + ///Maximum range the RCD can construct at. + var/rcd_range = 3 + ///Whether or not to deconstruct instead. + var/deconstruct_active = FALSE + ///The type of internal RCD this equipment uses. + var/rcd_type = /obj/item/construction/rcd/exosuit + ///The internal RCD item used by this equipment. + var/obj/item/construction/rcd/internal_rcd /obj/item/mecha_parts/mecha_equipment/rcd/Initialize(mapload) . = ..() + internal_rcd = new rcd_type(src) GLOB.rcd_list += src /obj/item/mecha_parts/mecha_equipment/rcd/Destroy() GLOB.rcd_list -= src + qdel(internal_rcd) return ..() /obj/item/mecha_parts/mecha_equipment/rcd/get_snowflake_data() return list( - "snowflake_id" = MECHA_SNOWFLAKE_ID_MODE, - "mode" = get_mode_name(), - "mode_label" = "RCD control", + "snowflake_id" = MECHA_SNOWFLAKE_ID_RCD, + "scan_ready" = COOLDOWN_FINISHED(internal_rcd, destructive_scan_cooldown), + "deconstructing" = deconstruct_active, + "mode" = internal_rcd.design_title, ) -/// fetches the mode name to display in the UI -/obj/item/mecha_parts/mecha_equipment/rcd/proc/get_mode_name() - switch(mode) - if(MODE_DECONSTRUCT) - return "Deconstruct" - if(MODE_WALL) - return "Build wall" - if(MODE_AIRLOCK) - return "Build Airlock" - else - return "Someone didnt set this" +/// Set the RCD's owner when attaching and detaching it +/obj/item/mecha_parts/mecha_equipment/rcd/attach(obj/vehicle/sealed/mecha/new_mecha, attach_right) + internal_rcd.owner = new_mecha + return ..() + +/obj/item/mecha_parts/mecha_equipment/rcd/detach(atom/moveto) + internal_rcd.owner = null + return ..() /obj/item/mecha_parts/mecha_equipment/rcd/handle_ui_act(action, list/params) - if(action == "change_mode") - mode++ - if(mode > MODE_AIRLOCK) - mode = MODE_DECONSTRUCT - switch(mode) - if(MODE_DECONSTRUCT) - to_chat(chassis.occupants, "[icon2html(src, chassis.occupants)][span_notice("Switched RCD to Deconstruct.")]") - energy_drain = initial(energy_drain) - if(MODE_WALL) - to_chat(chassis.occupants, "[icon2html(src, chassis.occupants)][span_notice("Switched RCD to Construct Walls and Flooring.")]") - energy_drain = 2*initial(energy_drain) - if(MODE_AIRLOCK) - to_chat(chassis.occupants, "[icon2html(src, chassis.occupants)][span_notice("Switched RCD to Construct Airlock.")]") - energy_drain = 2*initial(energy_drain) - return TRUE + switch(action) + if("rcd_scan") + if(!COOLDOWN_FINISHED(internal_rcd, destructive_scan_cooldown)) + return FALSE + rcd_scan(internal_rcd) + COOLDOWN_START(internal_rcd, destructive_scan_cooldown, RCD_DESTRUCTIVE_SCAN_COOLDOWN) + return TRUE + if("toggle_deconstruct") + deconstruct_active = !deconstruct_active + return TRUE + if("change_mode") + for(var/mob/driver as anything in chassis.return_drivers()) + internal_rcd.ui_interact(driver) + return TRUE /obj/item/mecha_parts/mecha_equipment/rcd/action(mob/source, atom/target, list/modifiers) - if(!isturf(target) && !istype(target, /obj/machinery/door/airlock)) - target = get_turf(target) - if(!action_checks(target) || !(target in view(3, chassis)) || istype(target, /turf/open/space/transit)) + if(!action_checks(target)) return - playsound(chassis, 'sound/machines/click.ogg', 50, TRUE) - - switch(mode) - if(MODE_DECONSTRUCT) - to_chat(source, "[icon2html(src, source)][span_notice("Deconstructing [target]...")]") - if(iswallturf(target)) - var/turf/closed/wall/wall_turf = target - if(!do_after_cooldown(wall_turf, source)) - return - wall_turf.ScrapeAway() - else if(isfloorturf(target)) - var/turf/open/floor/floor_turf = target - if(!do_after_cooldown(floor_turf, source)) - return - floor_turf.ScrapeAway(flags = CHANGETURF_INHERIT_AIR) - else if (istype(target, /obj/machinery/door/airlock)) - if(!do_after_cooldown(target, source)) - return - qdel(target) - if(MODE_WALL) - if(isfloorturf(target)) - var/turf/open/floor/floor_turf = target - to_chat(source, "[icon2html(src, source)][span_notice("Building Wall...")]") - if(!do_after_cooldown(floor_turf, source)) - return - floor_turf.place_on_top(/turf/closed/wall) - else if(isopenturf(target)) - var/turf/open/open_turf = target - to_chat(source, "[icon2html(src, source)][span_notice("Building Floor...")]") - if(!do_after_cooldown(open_turf, source)) - return - open_turf.place_on_top(/turf/open/floor/plating, flags = CHANGETURF_INHERIT_AIR) - if(MODE_AIRLOCK) - if(isfloorturf(target)) - to_chat(source, "[icon2html(src, source)][span_notice("Building Airlock...")]") - if(!do_after_cooldown(target, source)) - return - var/obj/machinery/door/airlock/airlock_door = new /obj/machinery/door/airlock(target) - airlock_door.autoclose = TRUE - playsound(target, 'sound/effects/sparks2.ogg', 50, TRUE) - chassis.spark_system.start() - playsound(target, 'sound/items/deconstruct.ogg', 50, TRUE) - return ..() + if(get_dist(chassis, target) > rcd_range) + balloon_alert(source, "out of range!") + return + if(!internal_rcd) // if it somehow went missing + internal_rcd = new rcd_type(src) + stack_trace("Exosuit-mounted RCD had no internal RCD!") + ..() // do this now because the do_after can take a while + var/construction_mode = internal_rcd.mode + if(deconstruct_active) // deconstruct isn't in the RCD menu so switch it to deconstruct mode and set it back when it's done + internal_rcd.mode = RCD_DECONSTRUCT + internal_rcd.rcd_create(target, source) + internal_rcd.mode = construction_mode + return TRUE -#undef MODE_DECONSTRUCT -#undef MODE_WALL -#undef MODE_AIRLOCK +/obj/item/mecha_parts/mecha_equipment/rcd/attackby(obj/item/attacking_item, mob/user, params) + if(istype(attacking_item, /obj/item/rcd_upgrade)) + internal_rcd.install_upgrade(attacking_item, user) + return + return ..() //Dunno where else to put this so shrug /obj/item/mecha_parts/mecha_equipment/ripleyupgrade diff --git a/code/modules/vehicles/mecha/mecha_defense.dm b/code/modules/vehicles/mecha/mecha_defense.dm index 015e4782199..c1207c2677f 100644 --- a/code/modules/vehicles/mecha/mecha_defense.dm +++ b/code/modules/vehicles/mecha/mecha_defense.dm @@ -225,6 +225,10 @@ ammo_resupply(weapon, user) return + if(istype(weapon, /obj/item/rcd_upgrade)) + upgrade_rcd(weapon, user) + return + if(weapon.GetID()) if(!allowed(user)) if(mecha_flags & ID_LOCK_ON) @@ -510,3 +514,9 @@ else balloon_alert(user, "can't use this ammo!") return FALSE + +///Upgrades any attached RCD equipment. +/obj/vehicle/sealed/mecha/proc/upgrade_rcd(obj/item/rcd_upgrade/rcd_upgrade, mob/user) + for(var/obj/item/mecha_parts/mecha_equipment/rcd/rcd_equip in flat_equipment) + if(rcd_equip.internal_rcd.install_upgrade(rcd_upgrade, user)) + return diff --git a/tgui/packages/tgui/interfaces/Mecha/ModulesPane.tsx b/tgui/packages/tgui/interfaces/Mecha/ModulesPane.tsx index 5cd22f11d16..99b0fd4b7a7 100644 --- a/tgui/packages/tgui/interfaces/Mecha/ModulesPane.tsx +++ b/tgui/packages/tgui/interfaces/Mecha/ModulesPane.tsx @@ -310,6 +310,7 @@ const MECHA_SNOWFLAKE_ID_WEAPON_BALLISTIC = 'ballistic_weapon_snowflake'; const MECHA_SNOWFLAKE_ID_GENERATOR = 'generator_snowflake'; const MECHA_SNOWFLAKE_ID_ORE_SCANNER = 'orescanner_snowflake'; const MECHA_SNOWFLAKE_ID_CLAW = 'lawclaw_snowflake'; +const MECHA_SNOWFLAKE_ID_RCD = 'rcd_snowflake'; export const ModuleDetailsExtra = (props: { module: MechModule }) => { const module = props.module; @@ -332,6 +333,8 @@ export const ModuleDetailsExtra = (props: { module: MechModule }) => { return ; case MECHA_SNOWFLAKE_ID_CLAW: return ; + case MECHA_SNOWFLAKE_ID_RCD: + return ; default: return null; } @@ -978,3 +981,49 @@ const SnowflakeLawClaw = (props) => { /> ); }; + +const SnowflakeRCD = (props) => { + const { act, data } = useBackend(); + const { ref } = props.module; + const { scan_ready, deconstructing, mode } = props.module.snowflake; + return ( + <> + +