Files
Bubberstation/code/modules/wiremod/shell/module.dm
SkyratBot 56e3a5e0db [MIRROR] MOD Complexity rebalance [MDB IGNORE] (#22226)
* MOD Complexity rebalance (#76077)

## About The Pull Request

Reduced the cost of a lot of MODules.

Pathfinder 2 -> 1
Tether 3 -> 1
Temperature Regulator 2 -> 1
DNA lock 2 -> 1
Health analyzer 2 -> 1
Sonar 2 -> 1
Microwave beam 2 -> 1
Drill 2 -> 1
All visors (including NV and thermals) 2 -> 1
Circuit Adapter 2 -> 1

The Mining MODsuit has had its complexity increased to 15 and now starts
with the eating apparatus module, with a total base complexity of 10/15
now.

The Prototype MODsuit's active slowdown has been decreased from 1.5 (!)
to 1.
## Why It's Good For The Game

> Reduced the cost of a lot of MODules.

There's lots of cute little MODules here, and they are all despite their
'small' cost far too expensive for them to ever be used. The small
little cost adds up, when you consider that two 2-complexity modules
cost FOUR, which is more than most good modules (that are 3), especially
when storage modules take up 3 complexity already. Think about it like
genetics, imagine if geladikinesis cost 40 instability. It'd be
pointless and just make it not used.

> Pathfinder 2 -> 1

Pathfinder is a little buggy, a bit janky, and still just a commodity,
so this might let captains keep it for themselves more often when
they're kitting out their MOD.

> Tether 3 -> 1

Tether costing 3 complexity is ABSURD. That's as much as the actual ion
jetpacks, and that's for something which you can replace completely with
a fire extinguisher, not even including the tiny 4 tiles tethering
range.

> Temperature Regulator 2 -> 1

This is vital for spacewalking, I really don't know why it's this
expensive. Hell it should be the norm, but whatevs.

> DNA lock 2 -> 1

Nobody's ever going to use this if it can just be EMPed and broken...
especially when it costs 2 complexity, which is the same cost as defibs,
surgical processor, holster, criminal capture..

> Health analyzer 2 -> 1

This is just a health analyzer. A small item that you're paying for the
privilege of being able to have it in your janksuit. It really shouldn't
cost 2 complexity, nobody ever takes this.

> Sonar 2 -> 1

I don't think there's much of a reason for sonar to be 2 complexity. You
might think it's nuts, but sonar really isn't that useful as it's a
windup with a screen-only range. Making it 1 might let it be seen ingame
at some point.

> Microwave beam 2 -> 1

Despite the cool name this just fries food. I don't think that should be
expensive!

> Drill 2 -> 1

The drill module is mostly redundant when by the time you get it,
chances are you have a plasma cutter already which is usually better, if
not as space-efficient. There's also the dumb issue with drilling into
gibtonite which instantly blows it up.

> All visors (including NV and thermals) 2 -> 1

Similarly to the health analyzer, chances are if you HAVE the module you
don't actually *need* it as you're already.. that job.

Additionally, and this is also part of the reason for the NV, thermal,
and even the health analyzer modules, is that traitors/nukies now have
to balance MOD economy alongside TC count, and I can't tell you just how
frustrating it is to buy something and be told I don't have enough
complexity to put it into the MODsuit. I already spent the damn TC!

> Circuit Adapter 2 -> 1

This thing seems pretty useless. All it can really do is open and close
your modsuit, which like, wow okay. No need for it to be expensive.

> The Mining MODsuit has had its complexity increased to 15 and now
starts with the eating apparatus module, with a total base complexity of
10/13 now.

The complexity increase is because for some reason the MODsuit is
already filled to the brim by default, which means that actually
interacting with robotics in any way is thoroughly disincentivized as
you'd need to take so many modules out to do so that it makes the
purchase and interaction pointless. Now you CAN go and ask robotics for
anything you need, though there isn't much a miner would want and value
enough to trek across the station, for now.

Also, it starts with the eating apparatus because it really looked like
it should! The flavor text even talks about miners, it's strange for
that to be there if miners won't use it. It'll also encourage it to
actually be bought more by allowing you to eat through it.

> The Prototype MODsuit's active slowdown has been decreased from 1.5
(!) to 1.

1.5 is a lot, A LOT, of slowdown. For such an incredibly rare mod, it
completely kills the damn thing, even for the charlie station crew! You
can't fight xenos with 1.5 slowdown! Having Kinesis isn't enough of a
reason to cripple it so thoroughly and pointlessly. It's 0.4 now, which
is a nice middleground between 'fast' suits like the medical and
security ones, and the 'slow' ones like civilian, engineering, science.
## Changelog
🆑
balance: Reduced the complexity cost of a lot of MODules.
balance: Pathfinder 2 -> 1
balance: Tether 3 -> 2
balance: Temperature Regulator 2 -> 1
balance: DNA lock 2 -> 1
balance: Health analyzer 2 -> 1
balance: Sonar 2 -> 1
balance: Microwave beam 2 -> 1
balance: Drill 2 -> 1
balance: All visors (including NV and thermals) 2 -> 1
balance: Circuit Adapter 2 -> 1
balance: The Mining MODsuit has had its complexity increased to 13 and
now starts with the eating apparatus module, with a total base
complexity of 10/13 now.
balance: The Prototype MODsuit's active slowdown has been decreased from
1.5 (!) to 1.
spellcheck: Fixed a type on the energy net module.
/🆑

* MOD Complexity rebalance

---------

Co-authored-by: carlarctg <53100513+carlarctg@users.noreply.github.com>
2023-07-08 17:32:07 -04:00

245 lines
9.8 KiB
Plaintext

/obj/item/mod/module/circuit
name = "MOD circuit adapter module"
desc = "A module shell that allows a circuit to be inserted into, and interface with, a MODsuit."
module_type = MODULE_USABLE
complexity = 1
idle_power_cost = DEFAULT_CHARGE_DRAIN * 0.5
incompatible_modules = list(/obj/item/mod/module/circuit)
cooldown_time = 0.5 SECONDS
/// A reference to the shell component, used to access the shell and its attached circuit
var/datum/component/shell/shell
/obj/item/mod/module/circuit/Initialize(mapload)
. = ..()
shell = AddComponent(/datum/component/shell, \
list(new /obj/item/circuit_component/mod_adapter_core()), \
capacity = SHELL_CAPACITY_LARGE, \
)
/obj/item/mod/module/circuit/proc/override_power_usage(datum/source, amount)
SIGNAL_HANDLER
if(drain_power(amount))
. = COMPONENT_OVERRIDE_POWER_USAGE
/obj/item/mod/module/circuit/on_install()
if(!shell?.attached_circuit)
return
RegisterSignal(shell?.attached_circuit, COMSIG_CIRCUIT_PRE_POWER_USAGE, PROC_REF(override_power_usage))
/obj/item/mod/module/circuit/on_uninstall(deleting = FALSE)
if(!shell?.attached_circuit)
return
UnregisterSignal(shell?.attached_circuit, COMSIG_CIRCUIT_PRE_POWER_USAGE)
/obj/item/mod/module/circuit/on_use()
. = ..()
if(!.)
return
if(!shell.attached_circuit)
return
var/list/action_components = shell.attached_circuit.get_all_contents_type(/obj/item/circuit_component/equipment_action/mod)
if(!action_components.len)
shell.attached_circuit.interact(mod.wearer)
return
var/list/repeat_name_counts = list("Access Circuit" = 1)
var/list/display_names = list()
var/list/radial_options = list()
for(var/obj/item/circuit_component/equipment_action/mod/action_component in action_components)
var/action_name = action_component.button_name.value
if(!repeat_name_counts[action_name])
repeat_name_counts[action_name] = 0
repeat_name_counts[action_name]++
if(repeat_name_counts[action_name] > 1)
action_name += " ([repeat_name_counts[action_name]])"
display_names[action_name] = REF(action_component)
var/option_icon_state = "bci_[replacetextEx(lowertext(action_component.icon_options.value), " ", "_")]"
radial_options += list("[action_name]" = image('icons/mob/actions/actions_items.dmi', option_icon_state))
radial_options += list("Access Circuit" = image(shell.attached_circuit))
var/selected_option = show_radial_menu(mod.wearer, src, radial_options, custom_check = FALSE, require_near = TRUE)
if(!selected_option)
return
if(!mod || !mod.wearer || !mod.active || mod.activating)
return
if(selected_option == "Access Circuit")
shell.attached_circuit?.interact(mod.wearer)
else
var/component_reference = display_names[selected_option]
var/obj/item/circuit_component/equipment_action/mod/selected_component = locate(component_reference) in shell.attached_circuit.contents
if(!istype(selected_component))
return
selected_component.signal.set_output(COMPONENT_SIGNAL)
/obj/item/circuit_component/mod_adapter_core
display_name = "MOD circuit adapter core"
desc = "Provides a reference to the MODsuit's occupant and allows the circuit to toggle the MODsuit."
/// The MODsuit module this circuit is associated with
var/obj/item/mod/module/attached_module
/// The name of the module to select
var/datum/port/input/option/module_to_select
/// The signal to toggle deployment of the modsuit
var/datum/port/input/toggle_deploy
/// The signal to toggle the suit
var/datum/port/input/toggle_suit
/// The signal to select a module
var/datum/port/input/select_module
/// A reference to the wearer of the MODsuit
var/datum/port/output/wearer
/// Whether or not the suit is deployed
var/datum/port/output/deployed
/// Whether or not the suit is activated
var/datum/port/output/activated
/// The name of the last selected module
var/datum/port/output/selected_module
/// A list of the names of all currently deployed parts
var/datum/port/output/deployed_parts
/// The signal that is triggered when a module is selected
var/datum/port/output/on_module_selected
/// The signal that is triggered when the suit is deployed by a signal
var/datum/port/output/on_deploy
/// The signal that is triggered when the suit has finished toggling itself after being activated by a signal
var/datum/port/output/on_toggle_finish
/obj/item/circuit_component/mod_adapter_core/populate_options()
module_to_select = add_option_port("Module to Select", list())
/obj/item/circuit_component/mod_adapter_core/populate_ports()
// Input Signals
toggle_deploy = add_input_port("Toggle Deployment", PORT_TYPE_SIGNAL)
toggle_suit = add_input_port("Toggle Suit", PORT_TYPE_SIGNAL)
select_module = add_input_port("Select Module", PORT_TYPE_SIGNAL)
// States
wearer = add_output_port("Wearer", PORT_TYPE_ATOM)
deployed = add_output_port("Deployed", PORT_TYPE_NUMBER)
activated = add_output_port("Activated", PORT_TYPE_NUMBER)
selected_module = add_output_port("Selected Module", PORT_TYPE_STRING)
deployed_parts = add_output_port("Deployed Parts", PORT_TYPE_LIST(PORT_TYPE_STRING))
// Output Signals
on_module_selected = add_output_port("On Module Selected", PORT_TYPE_SIGNAL)
on_deploy = add_output_port("On Deploy", PORT_TYPE_SIGNAL)
on_toggle_finish = add_output_port("Finished Toggling", PORT_TYPE_SIGNAL)
/obj/item/circuit_component/mod_adapter_core/register_shell(atom/movable/shell)
. = ..()
if(istype(shell, /obj/item/mod/module))
attached_module = shell
RegisterSignal(attached_module, COMSIG_MOVABLE_MOVED, PROC_REF(on_move))
/obj/item/circuit_component/mod_adapter_core/unregister_shell(atom/movable/shell)
if(attached_module)
UnregisterSignal(attached_module, COMSIG_MOVABLE_MOVED)
attached_module = null
return ..()
/obj/item/circuit_component/mod_adapter_core/input_received(datum/port/input/port)
if(!attached_module?.mod)
return
var/obj/item/mod/module/module
for(var/obj/item/mod/module/potential_module as anything in attached_module.mod.modules)
if(potential_module.name == module_to_select.value)
module = potential_module
if(COMPONENT_TRIGGERED_BY(toggle_suit, port))
INVOKE_ASYNC(attached_module.mod, TYPE_PROC_REF(/obj/item/mod/control, toggle_activate), attached_module.mod.wearer)
if(COMPONENT_TRIGGERED_BY(toggle_deploy, port))
INVOKE_ASYNC(attached_module.mod, TYPE_PROC_REF(/obj/item/mod/control, quick_deploy), attached_module.mod.wearer)
if(attached_module.mod.active && module && COMPONENT_TRIGGERED_BY(select_module, port))
INVOKE_ASYNC(module, TYPE_PROC_REF(/obj/item/mod/module, on_select))
/obj/item/circuit_component/mod_adapter_core/proc/on_move(atom/movable/source, atom/old_loc, dir, forced)
SIGNAL_HANDLER
if(istype(source.loc, /obj/item/mod/control))
var/obj/item/mod/control/mod = source.loc
RegisterSignal(mod, COMSIG_MOD_MODULE_SELECTED, PROC_REF(on_module_select))
RegisterSignal(mod, COMSIG_MOD_DEPLOYED, PROC_REF(on_mod_part_toggled))
RegisterSignal(mod, COMSIG_MOD_RETRACTED, PROC_REF(on_mod_part_toggled))
RegisterSignal(mod, COMSIG_MOD_TOGGLED, PROC_REF(on_mod_toggled))
RegisterSignal(mod, COMSIG_MOD_MODULE_ADDED, PROC_REF(on_module_changed))
RegisterSignal(mod, COMSIG_MOD_MODULE_REMOVED, PROC_REF(on_module_changed))
RegisterSignal(mod, COMSIG_ITEM_EQUIPPED, PROC_REF(equip_check))
wearer.set_output(mod.wearer)
var/modules_list = list()
for(var/obj/item/mod/module/module in mod.modules)
if(module.module_type != MODULE_PASSIVE)
modules_list += module.name
module_to_select.possible_options = modules_list
if (module_to_select.possible_options.len)
module_to_select.set_value(module_to_select.possible_options[1])
else if(istype(old_loc, /obj/item/mod/control))
UnregisterSignal(old_loc, list(COMSIG_MOD_MODULE_SELECTED, COMSIG_ITEM_EQUIPPED))
UnregisterSignal(old_loc, COMSIG_MOD_DEPLOYED)
UnregisterSignal(old_loc, COMSIG_MOD_RETRACTED)
UnregisterSignal(old_loc, COMSIG_MOD_TOGGLED)
UnregisterSignal(old_loc, COMSIG_MOD_MODULE_ADDED)
UnregisterSignal(old_loc, COMSIG_MOD_MODULE_REMOVED)
selected_module.set_output(null)
wearer.set_output(null)
deployed.set_output(FALSE)
activated.set_output(FALSE)
/obj/item/circuit_component/mod_adapter_core/proc/on_module_select(datum/source, obj/item/mod/module/module)
SIGNAL_HANDLER
selected_module.set_output(module.name)
on_module_selected.set_output(COMPONENT_SIGNAL)
/obj/item/circuit_component/mod_adapter_core/proc/on_module_changed()
SIGNAL_HANDLER
var/modules_list = list()
for(var/obj/item/mod/module/module in attached_module.mod.modules)
if(module.module_type != MODULE_PASSIVE)
modules_list += module.name
module_to_select.possible_options = modules_list
if (module_to_select.possible_options.len)
module_to_select.set_value(module_to_select.possible_options[1])
/obj/item/circuit_component/mod_adapter_core/proc/on_mod_part_toggled()
SIGNAL_HANDLER
var/string_list = list()
var/is_deployed = TRUE
for(var/obj/item/part as anything in attached_module.mod.mod_parts)
if(part.loc == attached_module.mod)
is_deployed = FALSE
else
var/part_name = "Undefined"
if(istype(part, /obj/item/clothing/head/mod))
part_name = "Helmet"
if(istype(part, /obj/item/clothing/suit/mod))
part_name = "Chestplate"
if(istype(part, /obj/item/clothing/gloves/mod))
part_name = "Gloves"
if(istype(part, /obj/item/clothing/shoes/mod))
part_name = "Boots"
string_list += part_name
deployed_parts.set_output(string_list)
deployed.set_output(is_deployed)
on_deploy.set_output(COMPONENT_SIGNAL)
/obj/item/circuit_component/mod_adapter_core/proc/on_mod_toggled()
SIGNAL_HANDLER
activated.set_output(attached_module.mod.active)
on_toggle_finish.set_output(COMPONENT_SIGNAL)
/obj/item/circuit_component/mod_adapter_core/proc/equip_check()
SIGNAL_HANDLER
if(!attached_module.mod?.wearer)
return
wearer.set_output(attached_module.mod.wearer)
/obj/item/circuit_component/equipment_action/mod
display_name = "MOD action"
desc = "Represents an action the user can take when wearing the MODsuit."
required_shells = list(/obj/item/mod/module/circuit)