Powerator Cleanup/QOL (#3625)

## About The Pull Request

Gives powerator code some TLC
- Move it all out of `modular_skyrat`, put the icon file in a proper
place
- Powerator penalties are now faction based instead of global, this
means that the station, persistence, and tarkon all running powerators
won't interfere with each other
- Changed the power draw input to take a number in kilowatts, because
nobody is ever setting it to less than one kilowatt
- Fixed the number set having seemingly no correlation with the amount
of power drawn from the grid, this is because it needed to be converted
between "energy" and "power" (watts and joules), now you just enter the
number of kilowatts and thats how much is going to be drawn from the
grid and everyone's happy
- Changed the examine text to only add a line if there's a problem (not
wrenched down, no wire, etc.) so there isn't 4 additional lines giving
you no relevant information
- Added context tooltips for tool interactions
- Refactor away the "powerator penalties" subsystem

## Why It's Good For The Game

Nice code no silly subsystems good bug fixes yes yes

## Proof Of Testing

This is like a whole thing but I swear I tested it all

## Changelog
🆑
add: added screentips for the powerator
qol: powerator input now takes kilowatts instead of watts
fix: powerator no longer draws weird amounts of power that aren't the
number you typed in
fix: powerator penalties are now faction-based (station, persistence,
tarkon), no more diminishing gains on station because tarkon is also
running a powerator
/🆑
This commit is contained in:
Roxy
2025-04-24 23:13:23 -04:00
committed by GitHub
parent dbe314ec48
commit e71bdf8a43
6 changed files with 231 additions and 229 deletions
-1
View File
@@ -192,7 +192,6 @@
#define INIT_ORDER_PATH -50
#define INIT_ORDER_MATURITY_GUARD -60 //SKYRAT EDIT ADDITION
#define INIT_ORDER_DECAY -61 //SKYRAT EDIT ADDITION
#define INIT_ORDER_POWERATOR_PENALITY -62 // SKYRAT EDIT ADDITION
#define INIT_ORDER_EXPLOSIONS -69
#define INIT_ORDER_STATPANELS -97
#define INIT_ORDER_BAN_CACHE -98
@@ -1,196 +0,0 @@
/obj/item/circuitboard/machine/powerator
name = "Powerator"
desc = "The powerator is a machine that allows stations to sell their power to other stations that require additional sources."
greyscale_colors = CIRCUIT_COLOR_GENERIC
build_path = /obj/machinery/powerator
req_components = list(
/obj/item/stack/sheet/glass = 1,
/obj/item/stack/ore/bluespace_crystal/refined = 1,
/obj/item/stack/cable_coil = 5,
/datum/stock_part/matter_bin = 2,
/datum/stock_part/micro_laser = 2,
/datum/stock_part/servo = 2,
)
needs_anchored = TRUE
/datum/supply_pack/misc/powerator
name = "Powerator"
desc = "We know the feeling of losing power and Central sending power, it is our time to do the same."
cost = CARGO_CRATE_VALUE * 50 // 10,000
contains = list(/obj/item/circuitboard/machine/powerator)
crate_name = "Powerator Circuitboard Crate"
crate_type = /obj/structure/closet/crate
/datum/design/board/powerator
name = "Machine Design (Powerator)"
desc = "Allows for the construction of circuit boards used to build a powerator."
id = "powerator"
build_path = /obj/item/circuitboard/machine/powerator
category = list(
RND_CATEGORY_MACHINE + RND_SUBCATEGORY_MACHINE_ENGINEERING
)
departmental_flags = DEPARTMENT_BITFLAG_SCIENCE | DEPARTMENT_BITFLAG_CARGO | DEPARTMENT_BITFLAG_ENGINEERING
/datum/techweb_node/powerator
id = TECHWEB_NODE_POWERATOR
display_name = "Powerator"
description = "We've been saved by it in the past, we should send some power ourselves!"
research_costs = list(TECHWEB_POINT_TYPE_GENERIC = TECHWEB_TIER_3_POINTS)
hidden = TRUE
experimental = TRUE
prereq_ids = list(TECHWEB_NODE_PARTS_ADV)
design_ids = list(
"powerator",
)
/obj/machinery/powerator
name = "powerator"
desc = "Beyond the ridiculous name, it is the standard for transporting and selling energy to power networks that require additional sources!"
icon = 'modular_skyrat/modules/power/icons/machines.dmi'
icon_state = "powerator"
density = TRUE
circuit = /obj/item/circuitboard/machine/powerator
idle_power_usage = 100
/// the current amount of power that we are trying to process
var/current_power = 10 KILO WATTS
/// the max amount of power that can be sent per process, from 100 KW (t1) to 10000 KW (t4)
var/max_power = 100 KILO WATTS
/// how much the current_power is divided by to determine the profit
var/divide_ratio = 0.00001
/// the attached cable to the machine
var/obj/structure/cable/attached_cable
/// how many credits this machine has actually made so far
var/credits_made = 0
/// the account credits will be sent towards
var/credits_account = ""
/obj/machinery/powerator/Initialize(mapload)
. = ..()
SSpowerator_penality.sum_powerators()
SSpowerator_penality.calculate_penality()
START_PROCESSING(SSobj, src)
/obj/machinery/powerator/Destroy()
STOP_PROCESSING(SSobj, src)
SSpowerator_penality.remove_deled_powerators(src)
SSpowerator_penality.calculate_penality()
attached_cable = null
return ..()
/obj/machinery/powerator/examine(mob/user)
. = ..()
. += "<br>"
if(panel_open)
. += span_warning("The maintainence panel is currently open, preventing [src] from working!")
else
. += span_notice("The maintainence panel is closed.")
if(!anchored)
. += span_warning("The anchors are not bolted to the floor, preventing [src] from working!")
else
. += span_notice("The anchors are bolted to the floor.")
if(machine_stat & (NOPOWER | BROKEN))
. += span_warning("There is either damage or no power being supplied, preventing [src] from working!")
else
. += span_notice("There is no damage and power is being supplied.")
if(!attached_cable)
. += span_warning("There is no power cable underneath, preventing [src] from working!")
else
. += span_notice("There is a power cable underneath.")
. += span_notice("Current Power: [display_power(current_power)]/[display_power(max_power)]")
. += span_notice("This machine has made [credits_made] credits from selling power so far.")
if(length(SSpowerator_penality.powerator_list) > 1)
. += span_notice("Multiple powerators detected, total efficiency reduced by [(SSpowerator_penality.diminishing_gains_multiplier)*100]%")
/obj/machinery/powerator/RefreshParts()
. = ..()
var/efficiency = -2 //set to -2 so that tier 1 parts do nothing
max_power = 100 KILO WATTS
for(var/datum/stock_part/micro_laser/laser_part in component_parts)
efficiency += laser_part.tier
max_power += (efficiency * 1650 KILO WATTS)
efficiency = -2
divide_ratio = 0.00001
for(var/datum/stock_part/servo/servo_part in component_parts)
efficiency += servo_part.tier
divide_ratio += (efficiency * 0.000005)
/obj/machinery/powerator/update_overlays()
. = ..()
cut_overlays()
if(panel_open)
add_overlay("panel_open")
else
add_overlay("panel_close")
if(machine_stat & (NOPOWER | BROKEN) || !anchored || panel_open)
add_overlay("error")
return
if(!attached_cable)
add_overlay("cable")
return
if(!attached_cable.avail(current_power))
add_overlay("power")
return
add_overlay("work")
/obj/machinery/powerator/process()
update_appearance() //lets just update this
var/turf/src_turf = get_turf(src)
attached_cable = locate() in src_turf
if(machine_stat & (NOPOWER | BROKEN) || !anchored || panel_open || !attached_cable) //no power, broken, unanchored, maint panel open, or no cable? lets reset
return
if(!attached_cable)
return
if(current_power <= 0)
current_power = 0 //this is just for the fringe case, wouldn't want it to somehow produce power for money! unless...
return
if(!attached_cable.avail(current_power))
if(!attached_cable.newavail())
return
current_power = attached_cable.newavail()
attached_cable.add_delayedload(current_power)
var/money_ratio = round(current_power * divide_ratio) * SSpowerator_penality.diminishing_gains_multiplier
var/datum/bank_account/synced_bank_account = SSeconomy.get_dep_account(credits_account == "" ? ACCOUNT_CAR : credits_account)
synced_bank_account.adjust_money(money_ratio)
credits_made += money_ratio
update_appearance() //lets just update this
/obj/machinery/powerator/attack_hand(mob/living/user, list/modifiers)
. = ..()
current_power = tgui_input_number(user, "How much power (in Watts) would you like to draw? Max: [display_power(max_power)]", "Power Draw", current_power, max_power, 0)
if(isnull(current_power))
current_power = 10 KILO WATTS
return
/obj/machinery/powerator/screwdriver_act(mob/living/user, obj/item/tool)
tool.play_tool_sound(src)
panel_open = !panel_open
update_appearance()
return ITEM_INTERACT_SUCCESS
/obj/machinery/powerator/crowbar_act(mob/user, obj/item/tool)
if(default_deconstruction_crowbar(tool))
return ITEM_INTERACT_SUCCESS
/obj/machinery/powerator/wrench_act(mob/living/user, obj/item/tool)
. = ..()
default_unfasten_wrench(user, tool)
return ITEM_INTERACT_SUCCESS
@@ -1,28 +0,0 @@
SUBSYSTEM_DEF(powerator_penality)
name = "Powerator Penalities"
flags = SS_NO_FIRE
init_order = INIT_ORDER_POWERATOR_PENALITY
/// How many powerators we have build on server
var/list/powerator_list = list()
/// Current penality for powerator cash gain
var/diminishing_gains_multiplier = 1
/datum/controller/subsystem/powerator_penality/Initialize()
return SS_INIT_SUCCESS
/datum/controller/subsystem/powerator_penality/proc/sum_powerators()
for(var/obj/machinery/powerator/poweratorc as anything in SSmachines.get_machines_by_type_and_subtypes(/obj/machinery/powerator))
powerator_list |= poweratorc
/datum/controller/subsystem/powerator_penality/proc/remove_deled_powerators(src)
powerator_list -= src
return
/datum/controller/subsystem/powerator_penality/proc/calculate_penality()
if(length(powerator_list) > 0)
diminishing_gains_multiplier = min(1, 2 ** log(4, length(powerator_list)) / length(powerator_list))
return diminishing_gains_multiplier
else
diminishing_gains_multiplier = initial(diminishing_gains_multiplier)
+231 -2
View File
@@ -1,3 +1,227 @@
#define POWERATOR_FACTION_STATION "station"
#define POWERATOR_FACTION_INTERDYNE "interdyne"
#define POWERATOR_FACTION_TARKON "tarkon"
/obj/item/circuitboard/machine/powerator
name = "Powerator"
desc = "The powerator is a machine that allows stations to sell their power to other stations that require additional sources."
greyscale_colors = CIRCUIT_COLOR_GENERIC
build_path = /obj/machinery/powerator
req_components = list(
/obj/item/stack/sheet/glass = 1,
/obj/item/stack/ore/bluespace_crystal/refined = 1,
/obj/item/stack/cable_coil = 5,
/datum/stock_part/matter_bin = 2,
/datum/stock_part/micro_laser = 2,
/datum/stock_part/servo = 2,
)
needs_anchored = TRUE
/datum/supply_pack/misc/powerator
name = "Powerator"
desc = "We know the feeling of losing power and Central sending power, it is our time to do the same."
cost = CARGO_CRATE_VALUE * 50 // 10,000
contains = list(/obj/item/circuitboard/machine/powerator)
crate_name = "Powerator Circuitboard Crate"
crate_type = /obj/structure/closet/crate
/datum/design/board/powerator
name = "Machine Design (Powerator)"
desc = "Allows for the construction of circuit boards used to build a powerator."
id = "powerator"
build_path = /obj/item/circuitboard/machine/powerator
category = list(
RND_CATEGORY_MACHINE + RND_SUBCATEGORY_MACHINE_ENGINEERING
)
departmental_flags = DEPARTMENT_BITFLAG_SCIENCE | DEPARTMENT_BITFLAG_CARGO | DEPARTMENT_BITFLAG_ENGINEERING
/datum/techweb_node/powerator
id = TECHWEB_NODE_POWERATOR
display_name = "Powerator"
description = "We've been saved by it in the past, we should send some power ourselves!"
research_costs = list(TECHWEB_POINT_TYPE_GENERIC = TECHWEB_TIER_3_POINTS)
hidden = TRUE
experimental = TRUE
prereq_ids = list(TECHWEB_NODE_PARTS_ADV)
design_ids = list(
"powerator",
)
/obj/machinery/powerator
name = "powerator"
desc = "Beyond the ridiculous name, it is the standard for transporting and selling energy to power networks that require additional sources!"
icon = 'modular_zubbers/icons/obj/machines/powerator.dmi'
icon_state = "powerator"
density = TRUE
circuit = /obj/item/circuitboard/machine/powerator
idle_power_usage = 100
/// Assoc list of factions -> powerators
var/static/list/powerator_list = list()
/// Assoc list of factions -> powerator penalties
var/static/list/powerator_penalty_multiplier_list = list()
/// the current amount of power that we are trying to process
var/current_power = 10 KILO WATTS
/// the max amount of power that can be sent per process, from 100 KW (t1) to 10000 KW (t4)
var/max_power = 100 KILO WATTS
/// how much the current_power is divided by to determine the profit
var/divide_ratio = 0.00001
/// the attached cable to the machine
var/obj/structure/cable/attached_cable
/// how many credits this machine has actually made so far
var/credits_made = 0
/// which faction the powerator belongs to
var/powerator_faction = POWERATOR_FACTION_STATION
/// the account credits will be sent towards
var/credits_account = ACCOUNT_CAR
/obj/machinery/powerator/Initialize(mapload)
. = ..()
LAZYADD(powerator_list[powerator_faction], src)
update_penalty()
register_context()
/obj/machinery/powerator/Destroy()
LAZYREMOVE(powerator_list[powerator_faction], src)
update_penalty()
attached_cable = null
. = ..()
/obj/machinery/powerator/add_context(atom/source, list/context, obj/item/held_item, mob/user)
. = ..()
if(!held_item)
context[SCREENTIP_CONTEXT_LMB] = "Adjust power draw"
return CONTEXTUAL_SCREENTIP_SET
switch(held_item.tool_behaviour)
if(TOOL_WRENCH)
context[SCREENTIP_CONTEXT_LMB] = "[anchored ? "Unanchor" : "Anchor"]"
return CONTEXTUAL_SCREENTIP_SET
if(TOOL_SCREWDRIVER)
context[SCREENTIP_CONTEXT_LMB] = "[panel_open ? "Close" : "Open"] panel"
return CONTEXTUAL_SCREENTIP_SET
if(TOOL_CROWBAR)
if(panel_open)
context[SCREENTIP_CONTEXT_LMB] = "Dismantle machine"
return CONTEXTUAL_SCREENTIP_SET
/obj/machinery/powerator/examine(mob/user)
. = ..()
if(panel_open)
. += span_warning("The maintainence panel is currently open, preventing [src] from working!")
if(!anchored)
. += span_warning("The anchors are not bolted to the floor, preventing [src] from working!")
if(machine_stat & (NOPOWER | BROKEN))
. += span_warning("There is either damage or no power being supplied, preventing [src] from working!")
if(!attached_cable)
. += span_warning("There is no power cable underneath, preventing [src] from working!")
. += span_notice("Current Power: [display_power(current_power)]/[display_power(max_power)]")
. += span_notice("This machine has made [credits_made] credits from selling power so far.")
if(length(powerator_list[powerator_faction]) > 1)
. += span_notice("Multiple powerators detected, total efficiency reduced by [(powerator_penalty_multiplier_list[powerator_faction])*100]%")
/obj/machinery/powerator/RefreshParts()
. = ..()
var/efficiency = -2 //set to -2 so that tier 1 parts do nothing
max_power = 100 KILO WATTS
for(var/datum/stock_part/micro_laser/laser_part in component_parts)
efficiency += laser_part.tier
max_power += (efficiency * 1650 KILO WATTS)
efficiency = -2
divide_ratio = 0.00001
for(var/datum/stock_part/servo/servo_part in component_parts)
efficiency += servo_part.tier
divide_ratio += (efficiency * 0.000005)
/obj/machinery/powerator/update_overlays()
. = ..()
cut_overlays()
if(panel_open)
add_overlay("panel_open")
else
add_overlay("panel_close")
if(machine_stat & (NOPOWER | BROKEN) || !anchored || panel_open)
add_overlay("error")
return
if(!attached_cable)
add_overlay("cable")
return
if(!attached_cable.avail(current_power))
add_overlay("power")
return
add_overlay("work")
/obj/machinery/powerator/process()
update_appearance() //lets just update this
var/turf/src_turf = get_turf(src)
attached_cable = locate() in src_turf
if(machine_stat & (NOPOWER | BROKEN) || !anchored || panel_open || !attached_cable) //no power, broken, unanchored, maint panel open, or no cable? lets reset
return
if(!attached_cable)
return
if(current_power <= 0)
current_power = 0 //this is just for the fringe case, wouldn't want it to somehow produce power for money! unless...
return
if(!attached_cable.avail(current_power))
if(!attached_cable.newavail())
return
current_power = attached_cable.newavail()
attached_cable.add_delayedload(current_power)
var/money_ratio = round(current_power * divide_ratio) * powerator_penalty_multiplier_list[powerator_faction]
var/datum/bank_account/synced_bank_account = SSeconomy.get_dep_account(credits_account)
synced_bank_account.adjust_money(money_ratio)
credits_made += money_ratio
update_appearance() //lets just update this
/obj/machinery/powerator/attack_hand(mob/living/user, list/modifiers)
. = ..()
var/new_power = tgui_input_number(user, "How much power (in kilowatts) would you like to draw? Max: [display_power(max_power)]", "Power Draw", energy_to_power(current_power) / (1 KILO WATTS), energy_to_power(max_power) / (1 KILO WATTS), 1)
if(!isnum(new_power))
return TRUE
current_power = power_to_energy(new_power) KILO WATTS
return TRUE
/obj/machinery/powerator/screwdriver_act(mob/living/user, obj/item/tool)
tool.play_tool_sound(src)
panel_open = !panel_open
update_appearance()
return ITEM_INTERACT_SUCCESS
/obj/machinery/powerator/crowbar_act(mob/user, obj/item/tool)
if(default_deconstruction_crowbar(tool))
return ITEM_INTERACT_SUCCESS
/obj/machinery/powerator/wrench_act(mob/living/user, obj/item/tool)
. = ..()
default_unfasten_wrench(user, tool)
return ITEM_INTERACT_SUCCESS
/// Update the penalty multiplier for this powerator's faction
/obj/machinery/powerator/proc/update_penalty()
if(length(powerator_list[powerator_faction]) > 0)
powerator_penalty_multiplier_list[powerator_faction] = min(1, 2 ** log(4, length(powerator_list[powerator_faction])) / length(powerator_list[powerator_faction]))
else
powerator_penalty_multiplier_list[powerator_faction] = 1
// Ghost role versions
/obj/item/circuitboard/machine/powerator/interdyne
name = "Interdyne Powerator"
greyscale_colors = CIRCUIT_COLOR_SUPPLY
@@ -8,9 +232,10 @@
desc = "Beyond the ridiculous name, it is the standard for transporting and selling energy to power networks that require additional sources! It appears to be an earlier variant before environmental regulation reduced its efficiency."
circuit = /obj/item/circuitboard/machine/powerator/interdyne
/// the account credits will be sent towards
powerator_faction = POWERATOR_FACTION_INTERDYNE
credits_account = ACCOUNT_INT
/obj/item/circuitboard/machine/powerator/tarkon
name = "Tarkon Powerator"
greyscale_colors = CIRCUIT_COLOR_SUPPLY
@@ -21,5 +246,9 @@
desc = "Beyond the ridiculous name, it is the standard for transporting and selling energy to power networks that require additional sources! It appears to be an earlier variant before environmental regulation reduced its efficiency."
circuit = /obj/item/circuitboard/machine/powerator/tarkon
/// the account credits will be sent towards
powerator_faction = POWERATOR_FACTION_TARKON
credits_account = ACCOUNT_TAR
#undef POWERATOR_FACTION_STATION
#undef POWERATOR_FACTION_INTERDYNE
#undef POWERATOR_FACTION_TARKON

Before

Width:  |  Height:  |  Size: 519 B

After

Width:  |  Height:  |  Size: 519 B

-2
View File
@@ -8499,8 +8499,6 @@
#include "modular_skyrat\modules\pollution\code\turf_open.dm"
#include "modular_skyrat\modules\poly_commands\parrot.dm"
#include "modular_skyrat\modules\positronic_alert_console\code\positronic_alert_console.dm"
#include "modular_skyrat\modules\power\code\powerator.dm"
#include "modular_skyrat\modules\power\code\powerator_subsystem.dm"
#include "modular_skyrat\modules\power\code\teg.dm"
#include "modular_skyrat\modules\primitive_catgirls\code\clothing.dm"
#include "modular_skyrat\modules\primitive_catgirls\code\clothing_vendor.dm"