diff --git a/code/game/atom/atom_examine.dm b/code/game/atom/atom_examine.dm index 2a19ebe33bd..d91c050b727 100644 --- a/code/game/atom/atom_examine.dm +++ b/code/game/atom/atom_examine.dm @@ -177,7 +177,11 @@ usr_client.Click(src, loc, null, mouseparams) return TRUE -/// Builds the text block variables for get_examine_text +/** + * Builds the text block variables for get_examine_text. + * Objects themselves are responsible for handling their own logic to build these hints. + * See mecha.dm for an example of a system that relays hints from contained items to a parent. + */ /atom/proc/update_desc_blocks(mob/user, distance, is_adjacent) var/list/mechanics_hints = mechanics_hints(user, distance, is_adjacent) var/list/assembly_hints = assembly_hints(user, distance, is_adjacent) diff --git a/code/modules/heavy_vehicle/equipment/_equipment.dm b/code/modules/heavy_vehicle/equipment/_equipment.dm index bd74ad98b3a..edee00efdef 100644 --- a/code/modules/heavy_vehicle/equipment/_equipment.dm +++ b/code/modules/heavy_vehicle/equipment/_equipment.dm @@ -16,6 +16,7 @@ var/active_power_use = 1 KILO WATTS var/require_adjacent = TRUE var/active = FALSE //For gear that has an active state (ie, floodlights) + var/list/module_hints = list() /obj/item/mecha_equipment/get_examine_text(mob/user, distance, is_adjacent, infix, suffix) . = ..() @@ -26,6 +27,17 @@ var/software = english_list(restricted_software, and_text = ", ") . += SPAN_NOTICE("Exosuit Software Requirement: [software]") +/obj/item/mecha_equipment/mechanics_hints(mob/user, distance, is_adjacent) + . += ..() + if (!length(module_hints)) + return + . += "When mounted on a mech, it gains the following mechanics:" + . += module_hints + +/// Called from the parent mech when a player requests the mech's mechanics hints. +/obj/item/mecha_equipment/proc/relayed_mechanics_hints(mob/user, distance, is_adjacent) + . += module_hints + /obj/item/mecha_equipment/attack(mob/living/target_mob, mob/living/user, target_zone) //Generally it's not desired to be able to attack with items return 0 diff --git a/code/modules/heavy_vehicle/equipment/combat.dm b/code/modules/heavy_vehicle/equipment/combat.dm index ba48870f6cb..a4a1ec56cab 100644 --- a/code/modules/heavy_vehicle/equipment/combat.dm +++ b/code/modules/heavy_vehicle/equipment/combat.dm @@ -6,6 +6,11 @@ icon_state = "mecha_taser" restricted_hardpoints = list(HARDPOINT_LEFT_HAND, HARDPOINT_RIGHT_HAND, HARDPOINT_LEFT_SHOULDER, HARDPOINT_RIGHT_SHOULDER) restricted_software = list(MECH_SOFTWARE_WEAPONS) + module_hints = list( + "Left Click: Fire a projectile in the target direction.", + "A mech can only fire within a 90 degree arc in the direction it is currently facing.", + "This weapon passively regenerates its ammunition using the mech's power supply.", + ) /obj/item/mecha_equipment/mounted_system/combat/CtrlClick(mob/user) if(owner && istype(holding, /obj/item/gun)) @@ -288,6 +293,12 @@ var/cooldown = 3.5 SECONDS // Time until we can recharge again after a blocked impact restricted_hardpoints = list(HARDPOINT_BACK) restricted_software = list(MECH_SOFTWARE_WEAPONS) + module_hints = list( + "Alt Click(Icon): Activates the shield drone.", + "When active, a large energy shield will appear in the mech's front facing arc.", + "The shield consumes a kilowatt of power each second while active.", + "It also consumes power to block incoming damage, and will shut down if it runs out.", + ) /obj/item/mecha_equipment/shield/installed(mob/living/heavy_vehicle/_owner) . = ..() @@ -367,6 +378,10 @@ /obj/item/mecha_equipment/shield/get_hardpoint_maptext() return "[(aura && aura.active) ? "ONLINE" : "OFFLINE"]: [round((charge / max_charge) * 100)]%" +/obj/item/mecha_equipment/shield/Destroy() + aura = null + return ..() + /obj/aura/mechshield icon = 'icons/mecha/shield.dmi' name = "mechshield" diff --git a/code/modules/heavy_vehicle/equipment/cult.dm b/code/modules/heavy_vehicle/equipment/cult.dm index 8542df6d587..8b6b6dc3068 100644 --- a/code/modules/heavy_vehicle/equipment/cult.dm +++ b/code/modules/heavy_vehicle/equipment/cult.dm @@ -25,3 +25,7 @@ if(!owner) return doomblade.attack(target_mob, user, user.zone_sel.selecting) + +/obj/item/mecha_equipment/doomblade/Destroy() + doomblade = null + return ..() diff --git a/code/modules/heavy_vehicle/equipment/engineering.dm b/code/modules/heavy_vehicle/equipment/engineering.dm index 366541d1ae6..c717ed1acd4 100644 --- a/code/modules/heavy_vehicle/equipment/engineering.dm +++ b/code/modules/heavy_vehicle/equipment/engineering.dm @@ -4,6 +4,11 @@ holding_type = /obj/item/rfd/construction/mounted/exosuit restricted_hardpoints = list(HARDPOINT_LEFT_HAND, HARDPOINT_RIGHT_HAND) restricted_software = list(MECH_SOFTWARE_ENGINEERING) + module_hints = list( + "Control Click(Self): Activate the RFD's mode selection radial menu.", + "Left Click(Target): Use the RFD on the target.", + "Matter used for the RFD is synthesized directly from the mech's power supply via a phoron-catalyzed mass fabricator.", + ) /obj/item/mecha_equipment/mounted_system/rfd/CtrlClick(mob/user) if(owner && istype(holding, /obj/item/rfd/construction/mounted/exosuit)) diff --git a/code/modules/heavy_vehicle/equipment/medical.dm b/code/modules/heavy_vehicle/equipment/medical.dm index 9f906dcc6a9..396d1499a2b 100644 --- a/code/modules/heavy_vehicle/equipment/medical.dm +++ b/code/modules/heavy_vehicle/equipment/medical.dm @@ -9,6 +9,12 @@ origin_tech = list(TECH_DATA = 2, TECH_BIO = 3) passive_power_use = 25 var/obj/machinery/sleeper/mounted/sleeper = null + module_hints = list( + "Left Click(Living Target): Load the target into the mech's onboard Medical Sleeper unit.", + "Alt Click(Icon): Activate the sleeper unit's control interface.", + "Mounted sleepers are capable of performing any task that a stationary sleeper can do.", + "This includes putting a patient into stasis, injecting medicines, and performing kidney dialysis.", + ) /obj/item/mecha_equipment/sleeper/Initialize() . = ..() @@ -132,7 +138,16 @@ var/mob/living/carbon/Target = null var/datum/beam/MyBeam = null + module_hints = list( + "Alt Click(Drone Icon): Activates the drone. When active, it will bob up and down rapidly as a visual indication.", + "When active, a crisis drone will constantly attempt to heal injured people within 3 tiles.", + "The drone is capable of healing most damage types, it will even alleviate a patient's pain. It cannot heal patients with less than 30 total damage.", + "It cannot heal the dead. It also cannot mend broken bones.", + ) + /obj/item/mecha_equipment/crisis_drone/Destroy() + Target = null + MyBeam = null STOP_PROCESSING(SSprocessing, src) . = ..() @@ -279,6 +294,10 @@ holding_type = /obj/item/device/healthanalyzer/mech restricted_hardpoints = list(HARDPOINT_LEFT_HAND, HARDPOINT_RIGHT_HAND) restricted_software = list(MECH_SOFTWARE_MEDICAL) + module_hints = list( + "Left Click(Target): Instantly perform a basic medical scan of the target.", + "Ctrl Click(Target): After remaining still for 7 seconds, print a full body scan of the target.", + ) /// Special health analyzer used by the exosuit health analyzer. /obj/item/device/healthanalyzer/mech diff --git a/code/modules/heavy_vehicle/equipment/mining.dm b/code/modules/heavy_vehicle/equipment/mining.dm index 736d1164fa3..46ad6e97bb9 100644 --- a/code/modules/heavy_vehicle/equipment/mining.dm +++ b/code/modules/heavy_vehicle/equipment/mining.dm @@ -9,6 +9,11 @@ var/obj/machinery/mining/drill/held_drill var/list/obj/machinery/mining/brace/held_braces var/charging = FALSE + module_hints = list( + "Left Click (Target Mining Drill or Brace): Load the target into the module's internal storage.", + "Alt Click (Icon): Deploy a held mining drill at the user's current location.", + "A drill mover can only hold one drill, and two braces at a time.", + ) /obj/item/mecha_equipment/drill_mover/afterattack(var/atom/target, var/mob/living/user, var/inrange, var/params) . = ..() @@ -85,6 +90,11 @@ held_braces -= brace . = ..() +/obj/item/mecha_equipment/drill_mover/Destroy() + QDEL_NULL(held_drill) + QDEL_NULL_LIST(held_braces) + return ..() + ABSTRACT_TYPE(/obj/item/mecha_equipment/mounted_system/mining) name = "mounted mining equipment" desc = DESC_PARENT @@ -97,6 +107,12 @@ ABSTRACT_TYPE(/obj/item/mecha_equipment/mounted_system/mining) desc = "A heavy-duty kinetic accelerator designed to be mounted on an exosuit." icon_state = "mecha_taser" // would be too difficult to get a proper sprite for this, would rather just get it in holding_type = /obj/item/gun/custom_ka/exosuit + module_hints = list( + "Left Click: Fire a kinetic blast in the target direction.", + "WARNING: This weapon produces a mining blast eight tiles in radius.", + "A mech can only fire within a 90 degree arc in the direction it is currently facing.", + "This weapon passively regenerates its ammunition using the mech's power supply.", + ) /obj/item/mecha_equipment/mounted_system/mining/kinetic_accelerator/get_hardpoint_status_value() if(!holding) @@ -137,7 +153,25 @@ ABSTRACT_TYPE(/obj/item/mecha_equipment/mounted_system/mining) /// How many chunks of ore can be moved at one time var/static/ore_limit = 50 + /// Radius of the summoner's pickup range. + var/pickup_range = 7 + + /// The linked warp extraction ore box. + var/obj/structure/ore_box/linked_box + + module_hints = list( + "Left Click (Target Ore Box): If the the target has a warp extraction beacon, link the summoner to it.", + "Alt Click (Icon): Teleport up to 50 ores within a radius of 7 tiles to the user.", + "If a warp ore box has been linked, it will teleport ores there.", + "Otherwise if the mech is also equipped with a mounted clamp that contains an ore box, ores will be teleported to said box.", + ) + /obj/item/mecha_equipment/ore_summoner/afterattack(var/atom/target, var/mob/living/user, var/inrange, var/params) + if(istype(target, /obj/structure/ore_box)) + var/obj/structure/ore_box/box = target + if (box.warp_core) + linked_box = target + to_chat(user, SPAN_NOTICE("You link \the [src] to \the [target]")) return FALSE /obj/item/mecha_equipment/ore_summoner/attack_self(var/mob/user) @@ -151,19 +185,22 @@ ABSTRACT_TYPE(/obj/item/mecha_equipment/mounted_system/mining) return var/obj/structure/ore_box/ore_box - for(var/hardpoint in owner.hardpoints) - var/obj/item/mecha_equipment/clamp/clamp = owner.hardpoints[hardpoint] - if(!istype(clamp)) - continue - var/obj/structure/ore_box/box = locate() in clamp - if(box) - ore_box = box - break + if(check_linked_box(user)) + ore_box = linked_box + else + for(var/hardpoint in owner.hardpoints) + var/obj/item/mecha_equipment/clamp/clamp = owner.hardpoints[hardpoint] + if(!istype(clamp)) + continue + var/obj/structure/ore_box/box = locate() in clamp + if(box) + ore_box = box + break var/turf/our_turf = get_turf(owner) var/limit = ore_limit - for(var/obj/item/ore/ore in range(7, owner)) + for(var/obj/item/ore/ore in range(pickup_range, owner)) if(limit <= 0) break if(ore_box) @@ -180,3 +217,18 @@ ABSTRACT_TYPE(/obj/item/mecha_equipment/mounted_system/mining) /obj/item/mecha_equipment/ore_summoner/get_hardpoint_maptext() return last_use + cooldown_time < world.time ? "Ready" : "Recharging" + +/obj/item/mecha_equipment/ore_summoner/proc/check_linked_box(var/mob/user) + if(!linked_box) + return FALSE + + if(!linked_box.warp_core) + to_chat(user, SPAN_WARNING("\The [linked_box] lost its warp beacon!")) + linked_box = null + return FALSE + + return TRUE + +/obj/item/mecha_equipment/ore_summoner/Destroy() + linked_box = null // Clear the reference to prevent hard deletes. + return ..() diff --git a/code/modules/heavy_vehicle/equipment/utility.dm b/code/modules/heavy_vehicle/equipment/utility.dm index 04700271283..02cf1bbfab4 100644 --- a/code/modules/heavy_vehicle/equipment/utility.dm +++ b/code/modules/heavy_vehicle/equipment/utility.dm @@ -9,6 +9,13 @@ var/list/obj/carrying = list() origin_tech = list(TECH_MATERIAL = 2, TECH_ENGINEERING = 2) var/list/afterattack_types = list(/obj/structure/closet, /obj/machinery/door/airlock) + module_hints = list( + "Attack(Harm): Swing the claw at a target to deal damage.", + "Attack(Non-Harm): Shove the target backwards,", + "Left Click(Door): Force open any door, even bolted and/or welded airlocks.", + "Left Click(Any other nonliving object): Pick up the object, storing it inside the clamp. Each clamp can hold up to 5 objects.", + "Alt Click(Clamp): Drop a selected held item.", + ) /obj/item/mecha_equipment/clamp/resolve_attackby(atom/A, mob/user, click_params) if(is_type_in_list(A, afterattack_types) && owner) @@ -172,6 +179,10 @@ /obj/item/weldingtool/get_hardpoint_maptext() return "[get_fuel()]/[max_fuel]" +/obj/item/mecha_equipment/clamp/Destroy() + QDEL_NULL_LIST(carrying) + return ..() + /obj/item/mecha_equipment/mounted_system/plasmacutter name = "mounted plasma cutter" desc = "An industrial plasma cutter mounted onto the chassis of the mech. " @@ -180,6 +191,11 @@ restricted_hardpoints = list(HARDPOINT_LEFT_HAND, HARDPOINT_RIGHT_HAND) restricted_software = list(MECH_SOFTWARE_UTILITY) origin_tech = list(TECH_MATERIAL = 4, TECH_PHORON = 4, TECH_ENGINEERING = 6, TECH_COMBAT = 3) + module_hints = list( + "Left Click(Target): Fire a plasma cutting beam in the target direction.", + "In addition to dealing damage, the plasma cutter can also mine through rocks at a time.", + "It also pierces through the target, striking an additional object behind the first one.", + ) /obj/item/gun/energy/plasmacutter/mounted/mech use_external_power = TRUE @@ -197,6 +213,9 @@ light_color = LIGHT_COLOR_TUNGSTEN light_wedge = LIGHT_WIDE origin_tech = list(TECH_MATERIAL = 1, TECH_ENGINEERING = 1) + module_hints = list( + "Alt Click(Icon): Light up a large area in front of the mech.", + ) /obj/item/mecha_equipment/light/attack_self(var/mob/user) . = ..() @@ -404,6 +423,12 @@ var/obj/item/material/drill_head/drill_head origin_tech = list(TECH_MATERIAL = 2, TECH_ENGINEERING = 2) + module_hints = list( + "Left Click(Target): Attack the target with a drill.", + "The drill is capable of destroying almost any structure, and can also destroy floors.", + "Using the drill consumes some of its durability. When it runs out, a new drill head will have to be placed in the module.", + ) + /obj/item/mecha_equipment/drill/Initialize() . = ..() drill_head = new /obj/item/material/drill_head(src, DEFAULT_WALL_MATERIAL)//You start with a basic steel head @@ -516,6 +541,10 @@ holding_type = /obj/item/gun/launcher/mech/flarelauncher restricted_hardpoints = list(HARDPOINT_LEFT_SHOULDER, HARDPOINT_RIGHT_SHOULDER) restricted_software = list(MECH_SOFTWARE_UTILITY) + module_hints = list( + "Left Click(Target): Fire an illuminating signal flare at the target location.", + "This weapon passively regenerates its ammunition using the mech's power supply.", + ) /obj/item/gun/launcher/mech/flarelauncher name = "mounted flare launcher" @@ -558,6 +587,10 @@ restricted_software = null origin_tech = list(TECH_MATERIAL = 2, TECH_ENGINEERING = 2) passive_power_use = 15 + module_hints = list( + "Left Click(Living Target): Load the target into the mech's onboard passenger compartment.", + "Alt Click(Icon): Eject the contents of the compartment.", + ) /obj/item/mecha_equipment/sleeper/passenger_compartment/uninstalled() . = ..() @@ -592,6 +625,10 @@ restricted_software = list(MECH_SOFTWARE_UTILITY) origin_tech = list(TECH_MATERIAL = 2, TECH_ENGINEERING = 2) var/obj/machinery/autolathe/mounted/lathe + module_hints = list( + "Left Click (Target Materials): Load materials into the autolathe.", + "Alt Click (Icon): Open the autolathe's UI.", + ) /obj/item/mecha_equipment/autolathe/get_hardpoint_maptext() if(lathe?.currently_printing) @@ -651,6 +688,11 @@ var/obj/item/powerdrill/mech/mounted_tool origin_tech = list(TECH_MATERIAL = 2, TECH_ENGINEERING = 2) + module_hints = list( + "Alt Click (Icon): Open a radial menu for selecting any desired tool.", + "Left Click (Target): Use the currently selected tool on the target.", + ) + /obj/item/mecha_equipment/toolset/Initialize() . = ..() mounted_tool = new/obj/item/powerdrill/mech(src) @@ -708,10 +750,14 @@ restricted_hardpoints = list(HARDPOINT_BACK) w_class = WEIGHT_CLASS_HUGE origin_tech = list(TECH_MATERIAL = 2, TECH_ENGINEERING = 3) + var/entry_speed_divisor = 6 + module_hints = list( + "Allows a user to enter the mech 6 times faster.", + ) /obj/item/mecha_equipment/quick_enter/installed() ..() - owner.entry_speed = 5 + owner.entry_speed /= entry_speed_divisor /obj/item/mecha_equipment/quick_enter/uninstalled() owner.entry_speed = initial(owner.entry_speed) @@ -735,6 +781,11 @@ var/obj/item/anomaly_core/AC var/image/anomaly_overlay + module_hints = list( + "Alt Click (Icon): Become incorporeal, gaining the ability to move through walls unimpeded.", + "This system consumes 88 kilowatts of power while active.", + ) + /obj/item/mecha_equipment/phazon/assembly_hints(mob/user, distance, is_adjacent) . += ..() if(!AC) @@ -803,3 +854,7 @@ holding_type = /obj/item/gun/launcher/mech/mountedgl/cl restricted_hardpoints = list(HARDPOINT_LEFT_SHOULDER, HARDPOINT_RIGHT_SHOULDER) restricted_software = list(MECH_SOFTWARE_UTILITY) + module_hints = list( + "Left Click(Target): Fire an cleaning grenade at the target location.", + "This weapon passively regenerates its ammunition using the mech's power supply.", + ) diff --git a/code/modules/heavy_vehicle/mecha.dm b/code/modules/heavy_vehicle/mecha.dm index 900c09d1754..35f8f6c9656 100644 --- a/code/modules/heavy_vehicle/mecha.dm +++ b/code/modules/heavy_vehicle/mecha.dm @@ -175,6 +175,23 @@ damage_string = SPAN_DANGER("destroyed") . += "Its [thing.name] [thing.gender == PLURAL ? "are" : "is"] [damage_string]." +/mob/living/heavy_vehicle/mechanics_hints(mob/user, distance, is_adjacent) + . += ..() + var/list/hardpoint_hints = list() + for(var/hardpoint in hardpoints) + var/obj/item/mecha_equipment/I = hardpoints[hardpoint] + if(!istype(I) || !length(I.module_hints)) + continue + hardpoint_hints += "- [hardpoint]: [SPAN_NOTICE("[I]")]" + hardpoint_hints += I.relayed_mechanics_hints(user, distance, is_adjacent) + + if(length(hardpoint_hints)) + . += "Its hardpoints have the following mechanics:" + . += hardpoint_hints + return + // Mech has no hardpoints, let's teach them how to fix that instead. + . += "modules can be attached to a mech by clicking on the mech with a module in hand." + /mob/living/heavy_vehicle/Topic(href,href_list[]) if (href_list["examine"]) var/mob/M = locate(href_list["examine"]) diff --git a/html/changelogs/Hellfirejag-exosuit-stuff.yml b/html/changelogs/Hellfirejag-exosuit-stuff.yml new file mode 100644 index 00000000000..3afbcb4993f --- /dev/null +++ b/html/changelogs/Hellfirejag-exosuit-stuff.yml @@ -0,0 +1,6 @@ +author: Hellfirejag +delete-after: True +changes: + - rscadd: "Added mechanics examine text for mech modules. Uniquely, examining a mech lets you see the mechanics of its equipped modules." + - rscadd: "Mech ore summoners can now be linked to warp extraction ore boxes." + - refactor: "Removed all lag-inducing hard deletes from mech code."