From 5a3d6881eccf7b6a56d4529d74ccd49f9c149ddf Mon Sep 17 00:00:00 2001 From: necromanceranne <40847847+necromanceranne@users.noreply.github.com> Date: Mon, 2 Jun 2025 06:07:21 +1000 Subject: [PATCH] Completely strips silicon control options out of open cage mechs (except mech domination). Adds flags to handle granular control restrictions and beacon limitations. (#91118) ## About The Pull Request Open cabin mechs cannot be piloted by silicon pilots. MMI's, uploaded AI's, positronics or AI control beacons. The mechs can still be tracker beaconed. It can also be dominated via the malfunctioning AI power. Adds some flags to help flag which mechs can or cannot be beaconed, or which are silicon compatible. ## Why It's Good For The Game I'm not going to lie. I do feel a bit pressured on this change in particular. This is somewhat meant to be an intended feature. But I think the cats out of the bag on open cabin mechs and the ways to circumvent their downsides. And the more I think about it, the more I come to realize that I frankly haven't had many, if any, good interactions with a posibrain/MMI mech army. So making that more efficient is...a problem. Using a silicon-based pilot can help you evade the potential consequences of being a flesh and bone pilot inside of a steel mesh cabin and being shot repeatedly. So you may as well, in those instances, treat it as a sealed cabin mech. And these mechs are surprisingly pretty strong statistically. Especially the Paddy with its ability to equip actual lethal weaponry. They're cheap, can be mass produced, come out early, and durable. The only limitation is pilots, and if you're printing positronics and get ghosts for those positronics, you can usually just keep producing more. From a purely objective standpoint, there isn't much reason to not push out posi-paddys over any other mech. Rather than settle for a perfect answer, let's at least require some human pilots in these mechs so that their supposed downside is more of an Achilles heel. ## Changelog :cl: balance: Caged mechs cannot accept silicon pilots. AI uploaded pilots, AI control beacons, MMIs or positronics. Malfunctioning AIs can still dominate these mechs. code: Allows for a higher degree of granularity for what mechs can and cannot accept by including additoinal mecha flags to block beacon type installations, pilot uploads and so on. /:cl: --- code/__DEFINES/mecha.dm | 10 ++++++++-- code/_globalvars/bitfields.dm | 3 +++ code/modules/vehicles/mecha/_mecha.dm | 4 +--- code/modules/vehicles/mecha/combat/gygax.dm | 3 +-- code/modules/vehicles/mecha/combat/honker.dm | 4 ++-- code/modules/vehicles/mecha/combat/justice.dm | 2 +- code/modules/vehicles/mecha/combat/marauder.dm | 3 +-- code/modules/vehicles/mecha/combat/reticence.dm | 2 +- code/modules/vehicles/mecha/combat/savannah_ivanov.dm | 2 +- code/modules/vehicles/mecha/mecha_ai_interaction.dm | 3 +++ code/modules/vehicles/mecha/mecha_control_console.dm | 5 ++++- code/modules/vehicles/mecha/working/clarke.dm | 2 +- code/modules/vehicles/mecha/working/ripley.dm | 8 ++++---- 13 files changed, 31 insertions(+), 20 deletions(-) diff --git a/code/__DEFINES/mecha.dm b/code/__DEFINES/mecha.dm index 6a37321dbc5..7e7c4a000a7 100644 --- a/code/__DEFINES/mecha.dm +++ b/code/__DEFINES/mecha.dm @@ -17,10 +17,16 @@ #define CANNOT_INTERACT (1<<9) /// posibrains can drive this mecha #define MMI_COMPATIBLE (1<<10) +/// AI's can be placed inside this mech. This only prevents direct uploads. It does not prevent mech domination on the mech. +#define AI_COMPATIBLE (1<<11) /// Can click from any direction and perform stuff -#define OMNIDIRECTIONAL_ATTACKS (1<<11) +#define OMNIDIRECTIONAL_ATTACKS (1<<12) /// Prevents overpenetrating through the mecha and into the cockpit using an armour penetrating weapon -#define CANNOT_OVERPENETRATE (1<<12) +#define CANNOT_OVERPENETRATE (1<<13) +/// Can have a tracking beacon placed into the mech +#define BEACON_TRACKABLE (1<<14) +/// Can have an AI control beacon placed into the mech +#define BEACON_CONTROLLABLE (1<<15) #define MECHA_MELEE (1 << 0) #define MECHA_RANGED (1 << 1) diff --git a/code/_globalvars/bitfields.dm b/code/_globalvars/bitfields.dm index dfd97a6bce5..8c8929d8949 100644 --- a/code/_globalvars/bitfields.dm +++ b/code/_globalvars/bitfields.dm @@ -268,8 +268,11 @@ DEFINE_BITFIELD(mecha_flags, list( "QUIET_TURNS" = QUIET_TURNS, "CANNOT_INTERACT" = CANNOT_INTERACT, "MMI_COMPATIBLE" = MMI_COMPATIBLE, + "AI_COMPATIBLE" = AI_COMPATIBLE, "OMNIDIRECTIONAL_ATTACKS" = OMNIDIRECTIONAL_ATTACKS, "CANNOT_OVERPENETRATE" = CANNOT_OVERPENETRATE, + "BEACON_TRACKABLE" = BEACON_TRACKABLE, + "BEACON_CONTROLLABLE" = BEACON_CONTROLLABLE, )) DEFINE_BITFIELD(mob_biotypes, list( diff --git a/code/modules/vehicles/mecha/_mecha.dm b/code/modules/vehicles/mecha/_mecha.dm index 8c6b69498e7..c73c282d899 100644 --- a/code/modules/vehicles/mecha/_mecha.dm +++ b/code/modules/vehicles/mecha/_mecha.dm @@ -56,7 +56,7 @@ /// Keeps track of the mech's servo motor var/obj/item/stock_parts/servo/servo ///Contains flags for the mecha - var/mecha_flags = CAN_STRAFE | IS_ENCLOSED | HAS_LIGHTS | MMI_COMPATIBLE + var/mecha_flags = CAN_STRAFE | IS_ENCLOSED | HAS_LIGHTS | MMI_COMPATIBLE | BEACON_TRACKABLE | AI_COMPATIBLE | BEACON_CONTROLLABLE ///Spark effects are handled by this datum var/datum/effect_system/spark_spread/spark_system @@ -85,8 +85,6 @@ var/obj/machinery/camera/exosuit/chassis_camera ///Portable camera camerachunk update var/updating = FALSE - ///Determines whether or not you can install tracking beacons in the mech. - var/can_be_tracked = TRUE var/max_temperature = 25000 diff --git a/code/modules/vehicles/mecha/combat/gygax.dm b/code/modules/vehicles/mecha/combat/gygax.dm index 85a9362a642..974ec17818a 100644 --- a/code/modules/vehicles/mecha/combat/gygax.dm +++ b/code/modules/vehicles/mecha/combat/gygax.dm @@ -45,10 +45,9 @@ overclock_coeff = 2 overclock_temp_danger = 20 force = 30 - can_be_tracked = FALSE accesses = list(ACCESS_SYNDICATE) wreckage = /obj/structure/mecha_wreckage/gygax/dark - mecha_flags = ID_LOCK_ON | CAN_STRAFE | IS_ENCLOSED | HAS_LIGHTS | MMI_COMPATIBLE + mecha_flags = ID_LOCK_ON | CAN_STRAFE | IS_ENCLOSED | HAS_LIGHTS | MMI_COMPATIBLE | AI_COMPATIBLE max_equip_by_category = list( MECHA_L_ARM = 1, MECHA_R_ARM = 1, diff --git a/code/modules/vehicles/mecha/combat/honker.dm b/code/modules/vehicles/mecha/combat/honker.dm index 2a3da129ccd..f5ad579cda1 100644 --- a/code/modules/vehicles/mecha/combat/honker.dm +++ b/code/modules/vehicles/mecha/combat/honker.dm @@ -13,7 +13,7 @@ exit_delay = 40 accesses = list(ACCESS_MECH_SCIENCE, ACCESS_THEATRE) wreckage = /obj/structure/mecha_wreckage/honker - mecha_flags = CAN_STRAFE | IS_ENCLOSED | HAS_LIGHTS | MMI_COMPATIBLE + mecha_flags = CAN_STRAFE | IS_ENCLOSED | HAS_LIGHTS | MMI_COMPATIBLE | BEACON_TRACKABLE | AI_COMPATIBLE | BEACON_CONTROLLABLE mech_type = EXOSUIT_MODULE_HONK max_equip_by_category = list( MECHA_L_ARM = 1, @@ -51,7 +51,7 @@ max_temperature = 35000 accesses = list(ACCESS_SYNDICATE) wreckage = /obj/structure/mecha_wreckage/honker/dark - mecha_flags = ID_LOCK_ON | CAN_STRAFE | IS_ENCLOSED | HAS_LIGHTS | MMI_COMPATIBLE + mecha_flags = ID_LOCK_ON | CAN_STRAFE | IS_ENCLOSED | HAS_LIGHTS | MMI_COMPATIBLE | AI_COMPATIBLE max_equip_by_category = list( MECHA_L_ARM = 1, MECHA_R_ARM = 1, diff --git a/code/modules/vehicles/mecha/combat/justice.dm b/code/modules/vehicles/mecha/combat/justice.dm index a57efa1844e..f57a6254bb0 100644 --- a/code/modules/vehicles/mecha/combat/justice.dm +++ b/code/modules/vehicles/mecha/combat/justice.dm @@ -22,7 +22,7 @@ wreckage = /obj/structure/mecha_wreckage/justice mech_type = EXOSUIT_MODULE_JUSTICE resistance_flags = LAVA_PROOF | FIRE_PROOF | ACID_PROOF - mecha_flags = ID_LOCK_ON | QUIET_STEPS | QUIET_TURNS | CAN_STRAFE | HAS_LIGHTS | MMI_COMPATIBLE | IS_ENCLOSED + mecha_flags = ID_LOCK_ON | QUIET_STEPS | QUIET_TURNS | CAN_STRAFE | HAS_LIGHTS | MMI_COMPATIBLE | IS_ENCLOSED | AI_COMPATIBLE destroy_wall_sound = 'sound/vehicles/mecha/mech_blade_break_wall.ogg' brute_attack_sound = 'sound/vehicles/mecha/mech_blade_attack.ogg' attack_verbs = list("cut", "cuts", "cutting") diff --git a/code/modules/vehicles/mecha/combat/marauder.dm b/code/modules/vehicles/mecha/combat/marauder.dm index aeff67f2f5a..4d7aca910da 100644 --- a/code/modules/vehicles/mecha/combat/marauder.dm +++ b/code/modules/vehicles/mecha/combat/marauder.dm @@ -9,11 +9,10 @@ max_temperature = 60000 destruction_sleep_duration = 40 exit_delay = 40 - can_be_tracked = FALSE resistance_flags = LAVA_PROOF | FIRE_PROOF | ACID_PROOF accesses = list(ACCESS_CENT_SPECOPS) wreckage = /obj/structure/mecha_wreckage/marauder - mecha_flags = CAN_STRAFE | IS_ENCLOSED | HAS_LIGHTS | MMI_COMPATIBLE + mecha_flags = CAN_STRAFE | IS_ENCLOSED | HAS_LIGHTS | MMI_COMPATIBLE | AI_COMPATIBLE mech_type = EXOSUIT_MODULE_MARAUDER force = 45 max_equip_by_category = list( diff --git a/code/modules/vehicles/mecha/combat/reticence.dm b/code/modules/vehicles/mecha/combat/reticence.dm index 0860fbc407f..0925e2e77e9 100644 --- a/code/modules/vehicles/mecha/combat/reticence.dm +++ b/code/modules/vehicles/mecha/combat/reticence.dm @@ -12,7 +12,7 @@ exit_delay = 40 wreckage = /obj/structure/mecha_wreckage/reticence accesses = list(ACCESS_MECH_SCIENCE, ACCESS_THEATRE) - mecha_flags = CAN_STRAFE | IS_ENCLOSED | HAS_LIGHTS | QUIET_STEPS | QUIET_TURNS | MMI_COMPATIBLE + mecha_flags = CAN_STRAFE | IS_ENCLOSED | HAS_LIGHTS | QUIET_STEPS | QUIET_TURNS | MMI_COMPATIBLE | AI_COMPATIBLE mech_type = EXOSUIT_MODULE_RETICENCE max_equip_by_category = list( MECHA_L_ARM = 1, diff --git a/code/modules/vehicles/mecha/combat/savannah_ivanov.dm b/code/modules/vehicles/mecha/combat/savannah_ivanov.dm index 60dad9de64a..a5496c77a06 100644 --- a/code/modules/vehicles/mecha/combat/savannah_ivanov.dm +++ b/code/modules/vehicles/mecha/combat/savannah_ivanov.dm @@ -19,7 +19,7 @@ base_icon_state = "savannah_ivanov" icon_state = "savannah_ivanov_0_0" //does not include mmi compatibility - mecha_flags = CAN_STRAFE | IS_ENCLOSED | HAS_LIGHTS + mecha_flags = CAN_STRAFE | IS_ENCLOSED | HAS_LIGHTS | BEACON_TRACKABLE | BEACON_CONTROLLABLE mech_type = EXOSUIT_MODULE_SAVANNAH movedelay = 3 max_integrity = 450 //really tanky, like damn diff --git a/code/modules/vehicles/mecha/mecha_ai_interaction.dm b/code/modules/vehicles/mecha/mecha_ai_interaction.dm index e518c8eaddc..3d862e0edfb 100644 --- a/code/modules/vehicles/mecha/mecha_ai_interaction.dm +++ b/code/modules/vehicles/mecha/mecha_ai_interaction.dm @@ -93,6 +93,9 @@ if(!AI) to_chat(user, span_warning("There is no AI currently installed on this device.")) return + if(!(mecha_flags & AI_COMPATIBLE)) //If the mech isn't compatible with an AI transfer, early return. + to_chat(user, span_warning("An AI cannot be installed into [src].")) + return if(AI.deployed_shell) //Recall AI if shelled so it can be checked for a client AI.disconnect_shell() if(AI.stat || !AI.client) diff --git a/code/modules/vehicles/mecha/mecha_control_console.dm b/code/modules/vehicles/mecha/mecha_control_console.dm index 8c9e9eb58d3..42d4a460d03 100644 --- a/code/modules/vehicles/mecha/mecha_control_console.dm +++ b/code/modules/vehicles/mecha/mecha_control_console.dm @@ -85,6 +85,8 @@ var/recharging = FALSE /// The Mecha that this tracking beacon is attached to var/obj/vehicle/sealed/mecha/chassis + /// The type of flag this part checks before being able to be installed into the mech + var/flag_to_check = BEACON_TRACKABLE /** * Returns a html formatted string describing attached mech status @@ -122,7 +124,7 @@ return ..() /obj/item/mecha_parts/mecha_tracking/try_attach_part(mob/user, obj/vehicle/sealed/mecha/mecha_to_attach, attach_right = FALSE) - if(!mecha_to_attach.can_be_tracked) + if(!(mecha_to_attach.mecha_flags & flag_to_check)) return if(!..()) return @@ -151,3 +153,4 @@ name = "exosuit AI control beacon" desc = "A device used to transmit exosuit data. Also allows active AI units to take control of said exosuit." ai_beacon = TRUE + flag_to_check = BEACON_CONTROLLABLE diff --git a/code/modules/vehicles/mecha/working/clarke.dm b/code/modules/vehicles/mecha/working/clarke.dm index 07482cebf82..02f8f1ca843 100644 --- a/code/modules/vehicles/mecha/working/clarke.dm +++ b/code/modules/vehicles/mecha/working/clarke.dm @@ -29,7 +29,7 @@ wreckage = /obj/structure/mecha_wreckage/clarke mech_type = EXOSUIT_MODULE_CLARKE enter_delay = 40 - mecha_flags = IS_ENCLOSED | HAS_LIGHTS | MMI_COMPATIBLE | OMNIDIRECTIONAL_ATTACKS + mecha_flags = IS_ENCLOSED | HAS_LIGHTS | MMI_COMPATIBLE | OMNIDIRECTIONAL_ATTACKS | BEACON_TRACKABLE | AI_COMPATIBLE | BEACON_CONTROLLABLE accesses = list(ACCESS_MECH_ENGINE, ACCESS_MECH_SCIENCE, ACCESS_MECH_MINING) allow_diagonal_movement = FALSE pivot_step = TRUE diff --git a/code/modules/vehicles/mecha/working/ripley.dm b/code/modules/vehicles/mecha/working/ripley.dm index ee6d4ffcf08..d91abbd9e36 100644 --- a/code/modules/vehicles/mecha/working/ripley.dm +++ b/code/modules/vehicles/mecha/working/ripley.dm @@ -17,7 +17,7 @@ MECHA_POWER = 1, MECHA_ARMOR = 1, ) - mecha_flags = CAN_STRAFE | HAS_LIGHTS | MMI_COMPATIBLE + mecha_flags = CAN_STRAFE | HAS_LIGHTS | BEACON_TRACKABLE wreckage = /obj/structure/mecha_wreckage/ripley mech_type = EXOSUIT_MODULE_RIPLEY possible_int_damage = MECHA_INT_FIRE|MECHA_INT_CONTROL_LOST|MECHA_INT_SHORT_CIRCUIT @@ -75,7 +75,7 @@ movedelay = 4 max_temperature = 30000 max_integrity = 250 - mecha_flags = CAN_STRAFE | IS_ENCLOSED | HAS_LIGHTS | MMI_COMPATIBLE + mecha_flags = CAN_STRAFE | IS_ENCLOSED | HAS_LIGHTS | MMI_COMPATIBLE | BEACON_TRACKABLE | AI_COMPATIBLE | BEACON_CONTROLLABLE possible_int_damage = MECHA_INT_FIRE|MECHA_INT_TEMP_CONTROL|MECHA_CABIN_AIR_BREACH|MECHA_INT_CONTROL_LOST|MECHA_INT_SHORT_CIRCUIT armor_type = /datum/armor/mecha_ripley_mk2 wreckage = /obj/structure/mecha_wreckage/ripley/mk2 @@ -188,7 +188,7 @@ /obj/vehicle/sealed/mecha/ripley/paddy/preset accesses = list(ACCESS_SECURITY) - mecha_flags = CAN_STRAFE | HAS_LIGHTS | MMI_COMPATIBLE | ID_LOCK_ON + mecha_flags = CAN_STRAFE | HAS_LIGHTS | ID_LOCK_ON equip_by_category = list( MECHA_L_ARM = /obj/item/mecha_parts/mecha_equipment/weapon/energy/disabler, MECHA_R_ARM = /obj/item/mecha_parts/mecha_equipment/weapon/paddy_claw, @@ -208,7 +208,7 @@ lights_power = 7 wreckage = /obj/structure/mecha_wreckage/ripley/deathripley step_energy_drain = 0 - mecha_flags = CAN_STRAFE | IS_ENCLOSED | HAS_LIGHTS | MMI_COMPATIBLE + mecha_flags = CAN_STRAFE | IS_ENCLOSED | HAS_LIGHTS | MMI_COMPATIBLE | AI_COMPATIBLE enter_delay = 40 silicon_icon_state = null equip_by_category = list(