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 (
+ <>
+
+
+
+
+
+
+ >
+ );
+};