From 2bf39c7ee976ea80b802cdab465dbb9befea074e Mon Sep 17 00:00:00 2001 From: Geeves Date: Sun, 9 Jun 2024 23:14:59 +0200 Subject: [PATCH] Exosuit Nuclear Power Cores (#18268) * Added power cores, a type of large battery cell that get used by exosuits. The nuclear and phoron variants are self-charging. * Combat mechs now start with nuclear power cores, allowing them to sustain themselves indefinitely, so long as they stay out of the action for a bit. * Removed basic power cells from the mechfab, replaced with the mech powercores. * Mech cell statuses now instantly update as soon as the cell charges or discharges. * Added a stack of 10 uranium to the machinist's workshop, which can print two nuclear power cores. --- aurorastation.dme | 1 + .../signals_atom/signals_power_cell.dm | 5 ++ .../objects/items/devices/suit_cooling.dm | 3 + .../game/objects/items/weapons/power_cells.dm | 72 +++++++++--------- code/game/objects/items/weapons/stunbaton.dm | 3 + code/game/objects/random/tech.dm | 4 +- code/modules/heavy_vehicle/components/body.dm | 8 +- .../heavy_vehicle/interface/_interface.dm | 29 +++---- .../heavy_vehicle/mech_construction.dm | 4 +- .../modules/heavy_vehicle/mech_interaction.dm | 13 +++- code/modules/heavy_vehicle/mecha.dm | 2 + .../modules/heavy_vehicle/premade/_premade.dm | 2 + code/modules/heavy_vehicle/premade/heavy.dm | 2 + code/modules/heavy_vehicle/premade/light.dm | 9 ++- .../modules/heavy_vehicle/premade/military.dm | 4 +- code/modules/heavy_vehicle/premade/pra.dm | 2 + code/modules/power/cell.dm | 25 ++++++ .../designs/protolathe/power_designs.dm | 21 ++++- html/changelogs/geeves-power_core_online.yml | 10 +++ icons/obj/machinery/cell_charger.dmi | Bin 3281 -> 3687 bytes maps/sccv_horizon/sccv_horizon-2_deck_2.dmm | 3 + maps/sccv_horizon/sccv_horizon-4_centcomm.dmm | 30 ++++---- 22 files changed, 178 insertions(+), 74 deletions(-) create mode 100644 code/__DEFINES/dcs/signals/signals_atom/signals_power_cell.dm create mode 100644 html/changelogs/geeves-power_core_online.yml diff --git a/aurorastation.dme b/aurorastation.dme index b21741bf95c..6ff8ac7aef5 100644 --- a/aurorastation.dme +++ b/aurorastation.dme @@ -159,6 +159,7 @@ #include "code\__DEFINES\dcs\signals\signals_atom\signals_atom_movable.dm" #include "code\__DEFINES\dcs\signals\signals_atom\signals_atom_movement.dm" #include "code\__DEFINES\dcs\signals\signals_atom\signals_atom_x_act.dm" +#include "code\__DEFINES\dcs\signals\signals_atom\signals_power_cell.dm" #include "code\__DEFINES\dcs\signals\signals_mob\signals_mob_living.dm" #include "code\__DEFINES\dcs\signals\signals_mob\signals_mob_main.dm" #include "code\__DEFINES\dcs\signals\signals_object\signals_object.dm" diff --git a/code/__DEFINES/dcs/signals/signals_atom/signals_power_cell.dm b/code/__DEFINES/dcs/signals/signals_atom/signals_power_cell.dm new file mode 100644 index 00000000000..7e950de28a3 --- /dev/null +++ b/code/__DEFINES/dcs/signals/signals_atom/signals_power_cell.dm @@ -0,0 +1,5 @@ +// Signals related to charge level of power cells +// Sent from cell.dm + +/// This is fired whenever a cell's charge changes. The data attached is the integer value of the cell's charge +#define COMSIG_CELL_CHARGE "cell_charge" diff --git a/code/game/objects/items/devices/suit_cooling.dm b/code/game/objects/items/devices/suit_cooling.dm index ffe8f6e59e7..4eae7ac51c6 100644 --- a/code/game/objects/items/devices/suit_cooling.dm +++ b/code/game/objects/items/devices/suit_cooling.dm @@ -166,6 +166,9 @@ if(cell) to_chat(user, SPAN_WARNING("There is \a [cell] already installed here.")) else + if(attacking_item.w_class != ITEMSIZE_NORMAL) + to_chat(user, SPAN_WARNING("\The [attacking_item] is too [attacking_item.w_class < ITEMSIZE_NORMAL ? "small" : "large"] to fit here.")) + return user.drop_from_inventory(attacking_item,src) cell = attacking_item to_chat(user, SPAN_NOTICE("You insert \the [cell].")) diff --git a/code/game/objects/items/weapons/power_cells.dm b/code/game/objects/items/weapons/power_cells.dm index 77cc9bfd6f0..f217954d9b7 100644 --- a/code/game/objects/items/weapons/power_cells.dm +++ b/code/game/objects/items/weapons/power_cells.dm @@ -17,6 +17,9 @@ matter = list(DEFAULT_WALL_MATERIAL = 700, MATERIAL_GLASS = 50) recyclable = TRUE + /// Percentage of maxcharge to recharge per minute, though it will trickle charge every process tick (every ~2 seconds), leave null for no self-recharge + var/self_charge_percentage + /// Smaller variant, used by energy guns and similar small devices /obj/item/cell/device name = "device power cell" @@ -82,13 +85,6 @@ maxcharge = 10000 matter = list(DEFAULT_WALL_MATERIAL = 700, MATERIAL_GLASS = 60) -/obj/item/cell/mecha - name = "exosuit-grade power cell" - origin_tech = list(TECH_POWER = 3) - icon_state = "hcell" - maxcharge = 15000 - matter = list(DEFAULT_WALL_MATERIAL = 700, MATERIAL_GLASS = 70) - /obj/item/cell/high/empty/Initialize() . = ..() charge = 0 @@ -151,42 +147,20 @@ icon_state = "yellow slime extract" maxcharge = 15000 matter = null - var/next_recharge -/obj/item/cell/slime/Initialize() - . = ..() - START_PROCESSING(SSprocessing, src) - -/obj/item/cell/slime/Destroy() - STOP_PROCESSING(SSprocessing, src) - return ..() - -/obj/item/cell/slime/process() - if(next_recharge < world.time) - charge = min(charge + (maxcharge / 10), maxcharge) - next_recharge = world.time + 1 MINUTE + // slime cores recharges 10% every one minute + self_charge_percentage = 10 /obj/item/cell/nuclear - name = "miniaturized nuclear power core" - desc = "A small self-charging thorium core that can store an immense amount of charge." + name = "miniaturized nuclear power cell" + desc = "A small self-charging cell with a thorium core that can store an immense amount of charge." origin_tech = list(TECH_POWER = 8, TECH_ILLEGAL = 4) icon_state = "icell" maxcharge = 50000 matter = null - var/next_recharge -/obj/item/cell/nuclear/Initialize() - . = ..() - START_PROCESSING(SSprocessing, src) - -/obj/item/cell/nuclear/Destroy() - STOP_PROCESSING(SSprocessing, src) - return ..() - -/obj/item/cell/nuclear/process() - if(next_recharge < world.time) - charge = min(charge + (maxcharge / 10), maxcharge) - next_recharge = world.time + 30 SECONDS + // nuclear cores recharges 20% every one minute + self_charge_percentage = 10 /obj/item/cell/device/emergency_light name = "miniature power cell" @@ -222,3 +196,31 @@ drop_sound = 'sound/items/drop/gascan.ogg' pickup_sound = 'sound/items/pickup/gascan.ogg' origin_tech = list(TECH_POWER = 4) + +/obj/item/cell/mecha + name = "power core" + origin_tech = list(TECH_POWER = 2) + icon_state = "core" + w_class = ITEMSIZE_LARGE + maxcharge = 20000 + matter = list(DEFAULT_WALL_MATERIAL = 20000, MATERIAL_GLASS = 10000) + +/obj/item/cell/mecha/nuclear + name = "nuclear power core" + origin_tech = list(TECH_POWER = 3, TECH_MATERIAL = 3) + icon_state = "nuclear_core" + maxcharge = 30000 + matter = list(DEFAULT_WALL_MATERIAL = 20000, MATERIAL_GLASS = 10000, MATERIAL_URANIUM = 10000) + + // nuclear mecha cores recharges 5% every one minute + self_charge_percentage = 5 + +/obj/item/cell/mecha/phoron + name = "phoron power core" + origin_tech = list(TECH_POWER = 5, TECH_MATERIAL = 5) + icon_state = "phoron_core" + maxcharge = 50000 + matter = list(DEFAULT_WALL_MATERIAL = 20000, MATERIAL_GLASS = 10000, MATERIAL_PHORON = 5000) + + // nuclear mecha cores recharges 10% every one minute + self_charge_percentage = 10 diff --git a/code/game/objects/items/weapons/stunbaton.dm b/code/game/objects/items/weapons/stunbaton.dm index 6174a4eafd5..c0edb1c5cf2 100644 --- a/code/game/objects/items/weapons/stunbaton.dm +++ b/code/game/objects/items/weapons/stunbaton.dm @@ -70,6 +70,9 @@ /obj/item/melee/baton/attackby(obj/item/attacking_item, mob/user) if(istype(attacking_item, /obj/item/cell)) + if(attacking_item.w_class != ITEMSIZE_NORMAL) + to_chat(user, SPAN_WARNING("\The [attacking_item] is too [attacking_item.w_class < ITEMSIZE_NORMAL ? "small" : "large"] to fit here.")) + return if(!bcell) user.drop_from_inventory(attacking_item, src) bcell = attacking_item diff --git a/code/game/objects/random/tech.dm b/code/game/objects/random/tech.dm index 2aa370bddf4..6db7875c047 100644 --- a/code/game/objects/random/tech.dm +++ b/code/game/objects/random/tech.dm @@ -30,10 +30,12 @@ icon = 'icons/obj/random.dmi' icon_state = "cell" problist = list( - /obj/item/cell/crap = 10, /obj/item/cell = 40, /obj/item/cell/high = 40, + /obj/item/cell/crap = 10, + /obj/item/cell/mecha = 10, /obj/item/cell/super = 9, + /obj/item/cell/mecha/nuclear = 5, /obj/item/cell/hyper = 1 ) diff --git a/code/modules/heavy_vehicle/components/body.dm b/code/modules/heavy_vehicle/components/body.dm index 445e1bb0613..2607a9fa751 100644 --- a/code/modules/heavy_vehicle/components/body.dm +++ b/code/modules/heavy_vehicle/components/body.dm @@ -17,7 +17,8 @@ var/mech_health = 600 var/obj/item/robot_parts/robot_component/diagnosis_unit/diagnostics - var/obj/item/cell/cell + var/obj/item/cell/mecha/cell + var/cell_type = /obj/item/cell/mecha var/obj/item/robot_parts/robot_component/armor/mech_armor var/obj/machinery/portable_atmospherics/canister/air_supply var/datum/gas_mixture/cockpit @@ -120,8 +121,9 @@ /obj/item/mech_component/chassis/prebuild() diagnostics = new(src) - cell = new /obj/item/cell/mecha(src) - cell.charge = cell.maxcharge + if(cell_type) + cell = new cell_type(src) + cell.charge = cell.maxcharge /obj/item/mech_component/chassis/attackby(obj/item/attacking_item, mob/user) if(istype(attacking_item, /obj/item/robot_parts/robot_component/diagnosis_unit)) diff --git a/code/modules/heavy_vehicle/interface/_interface.dm b/code/modules/heavy_vehicle/interface/_interface.dm index ee79b9b87c6..2e2fbc70a1f 100644 --- a/code/modules/heavy_vehicle/interface/_interface.dm +++ b/code/modules/heavy_vehicle/interface/_interface.dm @@ -65,19 +65,7 @@ var/obj/screen/mecha/hardpoint/H = hardpoint_hud_elements[hardpoint] if(H) H.update_system_info() handle_hud_icons_health() - var/obj/item/cell/C = get_cell() - if(istype(C)) - var/power_percentage = round((get_cell()?.charge / get_cell()?.maxcharge) * 100) - if(power_percentage >= 100) - hud_power?.maptext_x = 21 - else if(power_percentage < 10) - hud_power?.maptext_x = 25 - else if(power_percentage < 100) - hud_power?.maptext_x = 22 - hud_power.maptext = "[power_percentage]%" - else - hud_power?.maptext_x = 13 - hud_power?.maptext = "NO CELL" + handle_power_hud() refresh_hud() @@ -120,3 +108,18 @@ GLOB.mecha_damage_overlay_cache["[part]-[state]"] = I hud_health?.overlays |= GLOB.mecha_damage_overlay_cache["[part]-[state]"] + +/mob/living/heavy_vehicle/proc/handle_power_hud() + var/obj/item/cell/C = get_cell() + if(istype(C)) + var/power_percentage = round((get_cell()?.charge / get_cell()?.maxcharge) * 100) + if(power_percentage >= 100) + hud_power?.maptext_x = 21 + else if(power_percentage < 10) + hud_power?.maptext_x = 25 + else + hud_power?.maptext_x = 22 + hud_power?.maptext = "[power_percentage]%" + else + hud_power?.maptext_x = 13 + hud_power?.maptext = "NO CELL" diff --git a/code/modules/heavy_vehicle/mech_construction.dm b/code/modules/heavy_vehicle/mech_construction.dm index d8ff47b7862..82637fd3485 100644 --- a/code/modules/heavy_vehicle/mech_construction.dm +++ b/code/modules/heavy_vehicle/mech_construction.dm @@ -65,10 +65,12 @@ return var/obj/structure/heavy_vehicle_frame/frame = dest - if(istype(frame)) frame.body = body + if(body.cell) + UnregisterSignal(body.cell, COMSIG_CELL_CHARGE) + body.forceMove(dest) body = null diff --git a/code/modules/heavy_vehicle/mech_interaction.dm b/code/modules/heavy_vehicle/mech_interaction.dm index ac04c662f05..a11316007b5 100644 --- a/code/modules/heavy_vehicle/mech_interaction.dm +++ b/code/modules/heavy_vehicle/mech_interaction.dm @@ -445,9 +445,13 @@ visible_message(SPAN_NOTICE("\The [user] pries out \the [body.cell] using the \the [attacking_item].")) power = MECH_POWER_OFF hud_power_control.update_icon() + UnregisterSignal(body.cell, COMSIG_CELL_CHARGE) body.cell = null return else if(istype(attacking_item, /obj/item/cell)) + if(!istype(attacking_item, /obj/item/cell/mecha)) + to_chat(user, SPAN_WARNING("You can only use power cores in \the [src]!")) + return if(!maintenance_protocols) to_chat(user, SPAN_WARNING("The cell compartment remains locked while maintenance protocols are disabled.")) return @@ -458,9 +462,9 @@ if(user.unEquip(attacking_item)) attacking_item.forceMove(body) body.cell = attacking_item - to_chat(user, SPAN_NOTICE("You install \the [body.cell] into \the [src].")) + RegisterSignal(body.cell, COMSIG_CELL_CHARGE, PROC_REF(handle_cell_charge)) playsound(user.loc, 'sound/items/Screwdriver.ogg', 50, 1) - visible_message(SPAN_NOTICE("\The [user] installs \the [body.cell] into \the [src].")) + user.visible_message(SPAN_NOTICE("\The [user] installs \the [body.cell] into \the [src]."), SPAN_NOTICE("You install \the [body.cell] into \the [src].")) return else if(istype(attacking_item, /obj/item/device/robotanalyzer)) to_chat(user, SPAN_NOTICE("Diagnostic Report for \the [src]:")) @@ -730,3 +734,8 @@ say("Following [ID.registered_name].") break return + +/mob/living/heavy_vehicle/proc/handle_cell_charge(var/obj/item/cell/cell, var/new_charge) + SIGNAL_HANDLER + + handle_power_hud() diff --git a/code/modules/heavy_vehicle/mecha.dm b/code/modules/heavy_vehicle/mecha.dm index bef6fcf785e..e59b6fabde9 100644 --- a/code/modules/heavy_vehicle/mecha.dm +++ b/code/modules/heavy_vehicle/mecha.dm @@ -208,6 +208,8 @@ if(source_frame.body) source_frame.body.forceMove(src) body = source_frame.body + if(body.cell) + RegisterSignal(body.cell, COMSIG_CELL_CHARGE, PROC_REF(handle_cell_charge)) updatehealth() diff --git a/code/modules/heavy_vehicle/premade/_premade.dm b/code/modules/heavy_vehicle/premade/_premade.dm index 73078e35946..8e9e5991b4f 100644 --- a/code/modules/heavy_vehicle/premade/_premade.dm +++ b/code/modules/heavy_vehicle/premade/_premade.dm @@ -41,6 +41,8 @@ head.color = e_color if(!body && e_body) body = new e_body(src) + if(body.cell) + RegisterSignal(body.cell, COMSIG_CELL_CHARGE, PROC_REF(handle_cell_charge)) if(e_color) body.color = e_color if(!arms && e_arms) diff --git a/code/modules/heavy_vehicle/premade/heavy.dm b/code/modules/heavy_vehicle/premade/heavy.dm index 991c5313b50..85f92f5d8c1 100644 --- a/code/modules/heavy_vehicle/premade/heavy.dm +++ b/code/modules/heavy_vehicle/premade/heavy.dm @@ -59,6 +59,8 @@ has_hardpoints = list(HARDPOINT_BACK) power_use = 500 + cell_type = /obj/item/cell/mecha/nuclear + /obj/item/mech_component/chassis/heavy/prebuild() . = ..() mech_armor = new /obj/item/robot_parts/robot_component/armor/mech/combat(src) diff --git a/code/modules/heavy_vehicle/premade/light.dm b/code/modules/heavy_vehicle/premade/light.dm index 0b05cfa7279..121abaa9323 100644 --- a/code/modules/heavy_vehicle/premade/light.dm +++ b/code/modules/heavy_vehicle/premade/light.dm @@ -76,12 +76,16 @@ ) . = ..() +/obj/item/mech_component/chassis/light/nuclear + cell_type = /obj/item/cell/mecha/nuclear + /mob/living/heavy_vehicle/premade/light/legion name = "legion support exosuit" desc = "A light and agile exosuit painted in the colours of the Tau Ceti Foreign Legion." icon_state = "odysseus" e_color = COLOR_TCFL + e_body = /obj/item/mech_component/chassis/light/nuclear h_head = /obj/item/mecha_equipment/light h_back = /obj/item/mecha_equipment/sleeper @@ -96,6 +100,7 @@ icon_state = "odysseus" e_color = COLOR_IAC + e_body = /obj/item/mech_component/chassis/light/nuclear h_head = /obj/item/mecha_equipment/light h_back = /obj/item/mecha_equipment/sleeper @@ -109,6 +114,7 @@ desc = "A light and nimble exosuit, bearing the colour scheme of the Unathi Kataphracts." e_color = COLOR_CHESTNUT + e_body = /obj/item/mech_component/chassis/light/nuclear h_back = /obj/item/mecha_equipment/quick_enter h_l_hand = /obj/item/mecha_equipment/clamp @@ -120,8 +126,9 @@ desc = "A light and nimble recon exosuit, bearing the colour scheme of the Solarian Armed Forces." e_color = COLOR_DARK_GREEN_GRAY - e_arms = /obj/item/mech_component/manipulators/combat e_head = /obj/item/mech_component/sensors/combat + e_body = /obj/item/mech_component/chassis/light/nuclear + e_arms = /obj/item/mech_component/manipulators/combat e_legs = /obj/item/mech_component/propulsion/hover/light h_back = /obj/item/mecha_equipment/quick_enter diff --git a/code/modules/heavy_vehicle/premade/military.dm b/code/modules/heavy_vehicle/premade/military.dm index 81daf24db2c..4964d6f16c3 100644 --- a/code/modules/heavy_vehicle/premade/military.dm +++ b/code/modules/heavy_vehicle/premade/military.dm @@ -44,10 +44,10 @@ mech_health = 3500 power_use = 1500 + cell_type = /obj/item/cell/mecha/nuclear + /obj/item/mech_component/chassis/superheavy/prebuild() . = ..() - QDEL_NULL(cell) - cell = new /obj/item/cell/super(src) mech_armor = new /obj/item/robot_parts/robot_component/armor/mech/combat(src) /mob/living/heavy_vehicle/premade/superheavy diff --git a/code/modules/heavy_vehicle/premade/pra.dm b/code/modules/heavy_vehicle/premade/pra.dm index 95667d15ff5..ce004453762 100644 --- a/code/modules/heavy_vehicle/premade/pra.dm +++ b/code/modules/heavy_vehicle/premade/pra.dm @@ -94,6 +94,8 @@ max_damage = 150 power_use = 250 + cell_type = /obj/item/cell/mecha/nuclear + /obj/item/mech_component/chassis/pra_egg/armored/prebuild() . = ..() mech_armor = new /obj/item/robot_parts/robot_component/armor/mech/combat(src) diff --git a/code/modules/power/cell.dm b/code/modules/power/cell.dm index c369bd10df7..3f993b1b402 100644 --- a/code/modules/power/cell.dm +++ b/code/modules/power/cell.dm @@ -4,9 +4,30 @@ /obj/item/cell/Initialize() . = ..() + charge = maxcharge + + if(self_charge_percentage) + START_PROCESSING(SSprocessing, src) + update_icon() +/obj/item/cell/Destroy() + if(self_charge_percentage) + STOP_PROCESSING(SSprocessing, src) + return ..() + +/obj/item/cell/process(seconds_per_tick) + if(self_charge_percentage) + // we wanna recharge [self_charge_percentage% of the max charge] amount every 60 seconds + var/recharge_amount_per_minute = (maxcharge / 100) * self_charge_percentage + // since process fires every ~2 seconds, we wanna get the recharge amount per second + var/recharge_amount_per_second = recharge_amount_per_minute / 60 + // multiply the amount per second with how many seconds this tick took, then round it to prevent float errors + var/recharge_for_this_process = round(recharge_amount_per_second * (seconds_per_tick / 10)) // divides seconds_per_tick by 10 to turn deciseconds into seconds + // finally, charge the cell + give(recharge_for_this_process) + /obj/item/cell/Created() //Newly built cells spawn with no charge to prevent power exploits charge = 0 @@ -59,6 +80,7 @@ return 0 var/used = min(charge, amount) charge -= used + SEND_SIGNAL(src, COMSIG_CELL_CHARGE, charge) return used // Checks if the specified amount can be provided. If it can, it removes the amount @@ -78,6 +100,7 @@ var/amount_used = min(maxcharge-charge,amount) charge += amount_used + SEND_SIGNAL(src, COMSIG_CELL_CHARGE, charge) return amount_used @@ -180,6 +203,7 @@ charge -= maxcharge / severity if (charge < 0) charge = 0 + SEND_SIGNAL(src, COMSIG_CELL_CHARGE, charge) /** * Drains a percentage of the power from the battery @@ -196,6 +220,7 @@ charge -= maxcharge / divisor if (charge < 0) charge = 0 + SEND_SIGNAL(src, COMSIG_CELL_CHARGE, charge) /obj/item/cell/ex_act(severity) diff --git a/code/modules/research/designs/protolathe/power_designs.dm b/code/modules/research/designs/protolathe/power_designs.dm index 15e579f74e8..1c15e966bc2 100644 --- a/code/modules/research/designs/protolathe/power_designs.dm +++ b/code/modules/research/designs/protolathe/power_designs.dm @@ -1,5 +1,5 @@ /datum/design/item/powercell - build_type = PROTOLATHE | MECHFAB + build_type = PROTOLATHE category = "Misc" // For the mechfab p_category = "Power Cell Designs" @@ -48,3 +48,22 @@ req_tech = list(TECH_POWER = 2) materials = list(DEFAULT_WALL_MATERIAL = 150, MATERIAL_GLASS = 10) build_path = /obj/item/cell/device/high + +/datum/design/item/powercell/mecha + name = "Power Core" + build_type = MECHFAB + req_tech = list(TECH_POWER = 2) + materials = list(DEFAULT_WALL_MATERIAL = 20000, MATERIAL_GLASS = 10000) + build_path = /obj/item/cell/mecha + +/datum/design/item/powercell/mecha/nuclear + name = "Nuclear Power Core" + req_tech = list(TECH_POWER = 3, TECH_MATERIAL = 3) + materials = list(DEFAULT_WALL_MATERIAL = 20000, MATERIAL_GLASS = 10000, MATERIAL_URANIUM = 10000) + build_path = /obj/item/cell/mecha/nuclear + +/datum/design/item/powercell/mecha/phoron + name = "Phoron Power Core" + req_tech = list(TECH_POWER = 5, TECH_MATERIAL = 5) + materials = list(DEFAULT_WALL_MATERIAL = 20000, MATERIAL_GLASS = 10000, MATERIAL_PHORON = 5000) + build_path = /obj/item/cell/mecha/phoron diff --git a/html/changelogs/geeves-power_core_online.yml b/html/changelogs/geeves-power_core_online.yml new file mode 100644 index 00000000000..6688d499bb6 --- /dev/null +++ b/html/changelogs/geeves-power_core_online.yml @@ -0,0 +1,10 @@ +author: Geeves + +delete-after: True + +changes: + - rscadd: "Added power cores, a type of large battery cell that get used by exosuits. The nuclear and phoron variants are self-charging." + - balance: "Combat mechs now start with nuclear power cores, allowing them to sustain themselves indefinitely, so long as they stay out of the action for a bit." + - rscdel: "Removed basic power cells from the mechfab, replaced with the mech powercores." + - rscadd: "Mech cell statuses now instantly update as soon as the cell charges or discharges." + - rscadd: "Added a stack of 10 uranium to the machinist's workshop, which can print two nuclear power cores." \ No newline at end of file diff --git a/icons/obj/machinery/cell_charger.dmi b/icons/obj/machinery/cell_charger.dmi index fcc612b43920c2934f662622c6a14385abe56b71..f817928308993a1c160e45c20cdd24a7c4a4dd91 100644 GIT binary patch literal 3687 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 L<_1-l++zO)L@fH! literal 3281 zcmb_fXHb*d7X1iSI#L9bapeF$*#S0KjH!q<8%U zoB!NQ3@7LHDPP7D7=zh3gy`M5=Mn537~&n^4*(I!tXGxn59K+ZEbmFmDqLo`oaoHj zA>XXd37fcNWbCcj)JXd~>%@+t^Tfizk0U3!7{ZDZ#!5*Em!J7uNJqC4uM)|>sAQzV z)UTLPve)CWmu2|k!%E~dR;rH8tGia+Lhs%gm0iA8nZf085Rro{mifa$`Eu*XE8O0|_l% zdWth#NA@G)jzjM2Lg|zn?pVcp4-4o7rDJ5)e#9H-gm^rD!S$PT)#C&jV;xpc9r+;r z5xPh7uX3&A(ko+adyHS&t+x5!1w(0q81?EtD`k#rEwxDYv)Hbmg1i8S!61N7qV-+&JT1gwWM&W;h;Gq7Mi&x9KY<-Phx+&$;g z9F`ENCUZk@owp-eOaP>hcfA5DT^;ZZ+%B!%<7HlpzXBqU8{{ljU#cdr7&>LhF#$@b zR}TmLygsy9TLXYaipjtb>>@vfFoYcRLoYE4idd&>`D5N-C&LBO1vqo0RG1+Cs!A^6-PDbbFN~jxMJaQpsbD)?mux2EpD-)Y^T0Fs zR2^h<@lLc?y@-f#ndv@KfWvl9_aOGQi*gaD^yWuM8HchXrX16juI`v5#1bW&p&l;m zGE>O~kP;4h^2k`|+BMbsbLL*d3%CiY1S*|+X#kl`aYaHH0e3*V= z_CjxV(Q7T*kZ)xMj}F8@G1^lbU*cZ|BziRu4Q=)+rw7s3*5B2(a{(8E=s+}7|135H z8*svrKQh8s^XbzC_|)B*DM^zpxyD(RGO**8>@jTF)`{4VLD~%AY5QrqiPywPsvOye z0lC@CZ&ROJthM8_1N!PYT3)-}DhHGUqR$@kKFw6d>3a~;Yh2)?<$fCbT|*~Vde=!r z+Fz*Smy-EMqj9qS@BJTc*hKj5$b+nVWpg{iEiYI2mDS@#)9qxSea z;jx%^^UYNQJa%#J9Px3*6>(KKke>*LnG6($mNI!QD%ApqTZzSrqpXy4ZaO7QuKfK1|e+BFQUy zW_#S4OZ96-R1rUcF)v*_XzyB)cc4%C)|XE!l$i_$G#FVi zCu8*t^NwboYBmchYy{ngLLx6GN+Fi0MJtpJ-W*q4^tO>Wcdn&`yH*LlB?3N zEA9s6jWhx;FXYg!tP|SgQ;drSZxh%%;u8z^V8dn%YeZIa#-{ncjS#nzrII6}h$_is zi+UhZ4LqT&2dY^4?U}e;P(@-W zRoi_$59m1+L{JpIK6_Q6n?vx3rJnwiD5i7{Jbawe00EwPc8NUZN{^)%9drOrKmQ*9 zRx%S~=Ier0xZ7~J>^I4LVbOXCwr=yZPs*M_+(+;V{#dxvVuU~_PghynObg>I?hPMB zF<()N5^VItSn4jWd%sJS%ibb1(O=gTLEQpJZ_mQ+aR50*E7rA8OM33ZNbHwvm+*ql z~T&E@<4y@C>Xk7_7vdpeno*ES+*nNQjUHNMv7M1!;# z4PiVNnXA61CQ}D88veE;SzOEq(%zZFOp1TrM>&`reP1jA_b1-~Do$iscT_<8GsO<4 z(ppoLns(*m^&3s2Uwwa$ivTB4-wj4>$2L;T@cn4&m=wY?lU*oscl3jDa4ua{(j#I> zw!_h;I1#L6UTKdQpy%q2Y-#7R$Oeav8|>T-b<|1I_1)^ zU-WQeGMpZF@Ph#mB@v;4*pZCA*0jhPA^Lzmm~zBXi#E`#^>L=waPs9g^&`}d#}^i4 zD8Hq{$rL5;RPPxp=^ELzNFK|kGsUd53k`};(?Us$9*~owv5CPB}&Z3`dfA!1!tJ2<#ROr4(aag{Vk*olUms`2-SWg7RxXfZNN^OrnvoWa$65duM zxfCGYqfM~?c98n>Dd~;Bu%ofT$BB2psbS86K{T#?Dmdgb+J#5t`5IvX=xC{gO7Mak z=AajOLT~P!Y=|F$haDA0T$kJ^;?y8mL+0dKU;fvcam