From 954370b524d1212817e11f8153f091f618145a70 Mon Sep 17 00:00:00 2001 From: AltHit <52506929+AltHit@users.noreply.github.com> Date: Mon, 23 Sep 2024 13:22:14 +0300 Subject: [PATCH] Shield generator and Long range scanner refactor + Bioreactor fixes (#8514) * Bioreactor updates Now multistructures don't break until rebuild when screwed Bioreactor will now properly check for any breaches in the chamber and it will properly shut down if it spots any breaches Swapped placeholder power consumption for the real one Fixed bioreactor window opacity being inverted Cahors now has a slight anti-toxin effect as it should Bioreactor chamber ritual now updates breached status of bioreactor to restore it * Fix sensors/sheildgen and revert bioreactor fixes Fixed ability to extend shieldgen's and sensor's capacitors while they are unanchored * Everything. * Update food-Drinks.dm Changed effects of Cahors wine * Clearing up proc augments Suggested by SirRichardFrancis And yes, I tested affected procs. --- cev_eris.dme | 1 + code/__DEFINES/lrange_scanner.dm | 4 +- code/__HELPERS/turfs.dm | 9 + code/controllers/subsystems/staverbs.dm | 50 +++ code/datums/wires/lrange_scanner.dm | 6 +- code/datums/wires/shield_generator.dm | 6 +- code/game/gamemodes/events/space_weather.dm | 2 +- code/game/gamemodes/scores.dm | 2 +- code/game/machinery/machinery.dm | 7 + code/game/machinery/multistructure.dm | 6 +- .../circuitboards/machinery/lrange_scanner.dm | 23 +- .../circuitboards/machinery/shieldgen.dm | 21 +- .../bioreactor/bioreactor.dm | 8 +- .../bioreactor/platform.dm | 11 +- .../biomatter_manipulation/solidifier.dm | 1 + .../cruciform/rituals/machinery.dm | 7 +- code/modules/long_range_scanner/hull.dm | 7 +- .../long_range_scanner/long_range_scanner.dm | 392 +++++++----------- .../programs/engineering/shield_control.dm | 14 +- code/modules/nano/modules/nano_module.dm | 7 +- code/modules/overmap/ships/ship.dm | 22 +- code/modules/power/shipside_machinery.dm | 285 +++++++++++++ code/modules/reagents/reagents/food-Drinks.dm | 1 + code/modules/research/designs/circuits.dm | 29 +- code/modules/research/nodes/bluespace.dm | 10 +- code/modules/shield_generators/hull.dm | 7 +- code/modules/shield_generators/shield.dm | 14 +- .../shield_generators/shield_generator.dm | 324 +++++---------- maps/CEVEris/_CEV_Eris.dmm | 82 +++- 29 files changed, 805 insertions(+), 553 deletions(-) create mode 100644 code/modules/power/shipside_machinery.dm diff --git a/cev_eris.dme b/cev_eris.dme index f399f799d4b..2de7485a2b4 100644 --- a/cev_eris.dme +++ b/cev_eris.dme @@ -2382,6 +2382,7 @@ #include "code\modules\power\port_gen.dm" #include "code\modules\power\power.dm" #include "code\modules\power\powernet.dm" +#include "code\modules\power\shipside_machinery.dm" #include "code\modules\power\smes.dm" #include "code\modules\power\smes_construction.dm" #include "code\modules\power\solar.dm" diff --git a/code/__DEFINES/lrange_scanner.dm b/code/__DEFINES/lrange_scanner.dm index 46628c7be0e..6e726c4c3bf 100644 --- a/code/__DEFINES/lrange_scanner.dm +++ b/code/__DEFINES/lrange_scanner.dm @@ -1,5 +1,5 @@ -#define ENERGY_UPKEEP_SCANNER (35 KILOWATTS) // Base upkeep -#define ENERGY_PER_SCAN (100 MEGAWATTS) // Energy cost to launch a scan (yes it's in Watt and not in Joules...) +#define ENERGY_UPKEEP_SCANNER (350 KILOWATTS) // Base upkeep +#define ENERGY_PER_SCAN (500 MEGAWATTS) // Energy cost to launch a scan (yes it's in Watt and not in Joules...) #define SCANNER_OFF 0 // The shield is offline #define SCANNER_DISCHARGING 1 // The shield is shutting down and discharging. diff --git a/code/__HELPERS/turfs.dm b/code/__HELPERS/turfs.dm index 5a36b56168e..cc62a2c4cdb 100644 --- a/code/__HELPERS/turfs.dm +++ b/code/__HELPERS/turfs.dm @@ -28,6 +28,15 @@ return FALSE return TRUE +//A coppy of a proc above because sometimes you actually need to check if turf is clear no matter if it has wires or pipes +/proc/turf_clear_ignore_cables(turf/T) + if (T.density) + return FALSE + for(var/atom/A in T) + if(A.density) + return FALSE + return TRUE + /proc/clear_interior(var/turf/T) if (turf_clear(T)) if (!turf_is_external(T)) diff --git a/code/controllers/subsystems/staverbs.dm b/code/controllers/subsystems/staverbs.dm index b8c02ee28f5..eeb7f902b6f 100644 --- a/code/controllers/subsystems/staverbs.dm +++ b/code/controllers/subsystems/staverbs.dm @@ -180,3 +180,53 @@ SUBSYSTEM_DEF(statverbs) user.visible_message( SPAN_NOTICE("You stop repairing [target_name]."), ) + +/datum/statverb/connect_conduit //Connects or disconnects conduits of a shield generator or long range scanner + name = "Connect conduit" + required_stat = STAT_MEC + minimal_stat = STAT_LEVEL_ADEPT + +/datum/statverb/connect_conduit/action(mob/user, obj/machinery/power/conduit/conduit) + var/timer = 30 * (1 - user.stats.getStat(STAT_MEC) / 100) SECONDS + if(!conduit.base) //we try to connect it + var/turf/T = get_step(conduit, conduit.dir) + var/obj/machinery/power/shipside/target = locate(/obj/machinery/power/shipside/) in T + if(!target) + user.visible_message(self_message = SPAN_NOTICE("There is nothing to [conduit] to.")) + return FALSE + else + if(!target.tendrils_deployed && target.tendrils.len > 0) + if(!target.toggle_tendrils(TRUE)) //fail if conduits are not deployed and can not be deployed + return + if(target.tendrils.len < 1) //no conduits? + target.tendrils_deployed = TRUE + var/datum/repeating_sound/wrenchsound = new(30, timer, 0.15, conduit, 'sound/items/Ratchet.ogg', 80, 1) + user.visible_message(SPAN_NOTICE("[user] starts to connect various pipes and wires between [conduit] and [target]."), + "You start to connect various pipes and wires between [conduit] and [target].") + if(do_mob(user, conduit, timer)) + wrenchsound.stop() + qdel(wrenchsound) + conduit.connect(target) + user.visible_message(SPAN_NOTICE("[user] successfully connected [conduit] to the [target]!"), + "You successfully conneced [conduit] to the [target]!") + else + wrenchsound.stop() + qdel(wrenchsound) + user.visible_message(SPAN_NOTICE("[user] stopped connecting [conduit] and [target]."), + "You stopped connecting [conduit] and [target].") + else //disconnection + var/datum/repeating_sound/wrenchsound = new(30, timer, 0.15, conduit, 'sound/items/Ratchet.ogg', 80, 1) + user.visible_message(SPAN_NOTICE("[user] attempts to disconnect [conduit] from the [conduit.base]."), + "You attempt to disconnect [conduit] from the [conduit.base].") + if(do_mob(user, conduit, timer)) + wrenchsound.stop() + qdel(wrenchsound) + user.visible_message(SPAN_NOTICE("[user] successfully disconnected [conduit] from the [conduit.base]!"), + "You successfully disconneced [conduit] from the [conduit.base]!") + if(conduit.base.tendrils_deployed == TRUE) + conduit.disconnect() + else + wrenchsound.stop() + qdel(wrenchsound) + user.visible_message(SPAN_NOTICE("[user] stopped connecting [conduit] and [conduit.base]."), + "You stopped connecting [conduit] and [conduit.base].") \ No newline at end of file diff --git a/code/datums/wires/lrange_scanner.dm b/code/datums/wires/lrange_scanner.dm index 17703b29b0e..9775906569d 100644 --- a/code/datums/wires/lrange_scanner.dm +++ b/code/datums/wires/lrange_scanner.dm @@ -1,5 +1,5 @@ /datum/wires/long_range_scanner - holder_type = /obj/machinery/power/long_range_scanner/ + holder_type = /obj/machinery/power/shipside/long_range_scanner/ wire_count = 5 descriptions = list( new /datum/wire_description(SCANNER_WIRE_POWER, "Power"), @@ -14,13 +14,13 @@ var/const/SCANNER_WIRE_AICONTROL = 8 // Cut to disable AI control. Mend to rest var/const/SCANNER_WIRE_NOTHING = 16 // A blank wire that doesn't have any specific function /datum/wires/long_range_scanner/CanUse() - var/obj/machinery/power/long_range_scanner/S = holder + var/obj/machinery/power/shipside/long_range_scanner/S = holder if(S.panel_open) return 1 return 0 /datum/wires/long_range_scanner/UpdateCut(index, mended) - var/obj/machinery/power/long_range_scanner/S = holder + var/obj/machinery/power/shipside/long_range_scanner/S = holder switch(index) if(SCANNER_WIRE_POWER) S.input_cut = !mended diff --git a/code/datums/wires/shield_generator.dm b/code/datums/wires/shield_generator.dm index 8e4e5fd02bd..0c3dc57a86b 100644 --- a/code/datums/wires/shield_generator.dm +++ b/code/datums/wires/shield_generator.dm @@ -1,5 +1,5 @@ /datum/wires/shield_generator - holder_type = /obj/machinery/power/shield_generator/ + holder_type = /obj/machinery/power/shipside/shield_generator/ wire_count = 5 descriptions = list( new /datum/wire_description(SHIELDGEN_WIRE_POWER, "Main power"), @@ -13,13 +13,13 @@ var/const/SHIELDGEN_WIRE_AICONTROL = 8 // Cut to disable AI control. Mend to re var/const/SHIELDGEN_WIRE_NOTHING = 16 // A blank wire that doesn't have any specific function /datum/wires/shield_generator/CanUse() - var/obj/machinery/power/shield_generator/S = holder + var/obj/machinery/power/shipside/shield_generator/S = holder if(S.panel_open) return 1 return 0 /datum/wires/shield_generator/UpdateCut(index, mended) - var/obj/machinery/power/shield_generator/S = holder + var/obj/machinery/power/shipside/shield_generator/S = holder switch(index) if(SHIELDGEN_WIRE_POWER) S.input_cut = !mended diff --git a/code/game/gamemodes/events/space_weather.dm b/code/game/gamemodes/events/space_weather.dm index 2ecc9bbec1e..c86107ab124 100644 --- a/code/game/gamemodes/events/space_weather.dm +++ b/code/game/gamemodes/events/space_weather.dm @@ -149,7 +149,7 @@ SSevent.change_parallax(GLOB.random_parallax) /datum/event/harmonic_feedback/tick() //around two seconds - for(var/obj/machinery/power/shield_generator/G in GLOB.machines) + for(var/obj/machinery/power/shipside/shield_generator/G in GLOB.machines) if(G.running != SHIELD_OFF) G.take_shield_damage(250, SHIELD_DAMTYPE_SPECIAL, "UNKNOWN") // ALRIGHT LISTEN WEATHER CAN LAST AT MAXIMUM 450 TICKS, AVERAGE AT 375 SHIELD HITS // BY DEFAULT 1000 DAMAGE EQUALS 1 PERCENT, SO 0.25% * 375 = 93.75%, THIS WILL KNOCK SHIELDS OUT IF THEY'RE NOT AT FULL CAPACITY OR NOT CHARGING WELL diff --git a/code/game/gamemodes/scores.dm b/code/game/gamemodes/scores.dm index 80097318c85..438d7ae5371 100644 --- a/code/game/gamemodes/scores.dm +++ b/code/game/gamemodes/scores.dm @@ -180,7 +180,7 @@ GLOBAL_VAR_INIT(score_technomancer_faction_item_loss, 0) if(smes_count == 0) GLOB.all_smes_powered = FALSE - for(var/obj/machinery/power/shield_generator/S in GLOB.machines) + for(var/obj/machinery/power/shipside/shield_generator/S in GLOB.machines) if(!isStationLevel(S.z)) continue smes_count++ if(!S.running) continue diff --git a/code/game/machinery/machinery.dm b/code/game/machinery/machinery.dm index d4503530884..1d104e2ffd8 100644 --- a/code/game/machinery/machinery.dm +++ b/code/game/machinery/machinery.dm @@ -103,6 +103,9 @@ var/list/component_parts //list of all the parts used to build it, if made from certain kinds of frames. var/uid var/panel_open = 0 + //0 - panel closed + //1 - panel opened + //-1 - panel never should be opened (used for NT buildings) var/global/gl_uid = 1 var/interact_offline = 0 // Can the machine be interacted with while de-powered. var/obj/item/electronics/circuitboard/circuit @@ -304,6 +307,10 @@ //Tool qualities are stored in \code\__defines\tools_and_qualities.dm /obj/machinery/proc/default_deconstruction(obj/item/I, mob/user) + if(panel_open == -1) + to_chat(user, SPAN_NOTICE("There are no panels to open on \the [src].")) + return FALSE + var/qualities = list(QUALITY_SCREW_DRIVING) if(panel_open && circuit) diff --git a/code/game/machinery/multistructure.dm b/code/game/machinery/multistructure.dm index 0d6a182769f..dfe9b9eec28 100644 --- a/code/game/machinery/multistructure.dm +++ b/code/game/machinery/multistructure.dm @@ -112,14 +112,16 @@ /obj/machinery/multistructure/attackby(obj/item/I, mob/user) check_MS() if(default_deconstruction(I, user)) - if(MS) - MS.Destroy() return if(default_part_replacement(I, user)) return return +/obj/machinery/multistructure/on_deconstruction() //destroy multistructure if element is deconstructed with crowbar or in a simular way + if(MS) + MS.Destroy() + // This proc will check and attpemt to create MS // first it tries to find any element mentioned in MS structure and if finds any it will pass coords of where top-left element of a structure matrix should be to createMultistructure() diff --git a/code/game/objects/items/weapons/circuitboards/machinery/lrange_scanner.dm b/code/game/objects/items/weapons/circuitboards/machinery/lrange_scanner.dm index 1aad3f148f4..454d1ceb221 100644 --- a/code/game/objects/items/weapons/circuitboards/machinery/lrange_scanner.dm +++ b/code/game/objects/items/weapons/circuitboards/machinery/lrange_scanner.dm @@ -5,11 +5,24 @@ /obj/item/electronics/circuitboard/long_range_scanner name = T_BOARD("long range scanner") board_type = "machine" - build_path = /obj/machinery/power/long_range_scanner + build_path = /obj/machinery/power/shipside/long_range_scanner matter = list(MATERIAL_GLASS = 3, MATERIAL_GOLD = 3) - origin_tech = list(TECH_MAGNET = 3, TECH_POWER = 4) + origin_tech = list(TECH_BLUESPACE = 5, TECH_ENGINEERING = 4) req_components = list( - /obj/item/stock_parts/capacitor = 1, - /obj/item/stock_parts/micro_laser = 1, - /obj/item/stock_parts/smes_coil = 1, + /obj/item/stock_parts/scanning_module = 2, + /obj/item/bluespace_crystal = 1, + /obj/item/stock_parts/subspace/filter = 1, /obj/item/stock_parts/console_screen = 1) + + +/obj/item/electronics/circuitboard/scanner_conduit + name = T_BOARD("scanner conduit") + board_type = "machine" + build_path = /obj/machinery/power/conduit/scanner_conduit + matter = list(MATERIAL_GLASS = 3, MATERIAL_GOLD = 3) + origin_tech = list(TECH_BLUESPACE = 3, TECH_POWER = 4) + req_components = list( + /obj/item/stock_parts/subspace/crystal = 1, + /obj/item/stock_parts/subspace/amplifier = 1, + /obj/item/stock_parts/smes_coil = 1, + /obj/item/stock_parts/capacitor = 2) \ No newline at end of file diff --git a/code/game/objects/items/weapons/circuitboards/machinery/shieldgen.dm b/code/game/objects/items/weapons/circuitboards/machinery/shieldgen.dm index d780cda67c0..3677a7f54b7 100644 --- a/code/game/objects/items/weapons/circuitboards/machinery/shieldgen.dm +++ b/code/game/objects/items/weapons/circuitboards/machinery/shieldgen.dm @@ -5,15 +5,28 @@ /obj/item/electronics/circuitboard/shield_generator name = T_BOARD("hull shield generator") board_type = "machine" - build_path = /obj/machinery/power/shield_generator + build_path = /obj/machinery/power/shipside/shield_generator matter = list(MATERIAL_GLASS = 2, MATERIAL_GOLD = 1) - origin_tech = list(TECH_MAGNET = 3, TECH_POWER = 4) + origin_tech = list(TECH_ENGINEERING = 4, TECH_BLUESPACE = 4) req_components = list( - /obj/item/stock_parts/capacitor = 1, /obj/item/stock_parts/micro_laser = 1, - /obj/item/stock_parts/smes_coil = 1, + /obj/item/stock_parts/subspace/crystal = 1, //might be changed to the Catalyst in furure Techno updates + /obj/item/stock_parts/subspace/transmitter = 1, /obj/item/stock_parts/console_screen = 1) + +/obj/item/electronics/circuitboard/shield_conduit + name = T_BOARD("shield conduit") + board_type = "machine" + build_path = /obj/machinery/power/conduit/shield_conduit + matter = list(MATERIAL_GLASS = 2, MATERIAL_GOLD = 1) + origin_tech = list(TECH_MAGNET = 3, TECH_POWER = 4) + req_components = list( + /obj/item/stock_parts/capacitor = 4, + /obj/item/stock_parts/smes_coil = 1, + /obj/item/stack/cable_coil = 10) + + /obj/item/electronics/circuitboard/shield_diffuser name = T_BOARD("shield diffuser") board_type = "machine" diff --git a/code/modules/biomatter_manipulation/bioreactor/bioreactor.dm b/code/modules/biomatter_manipulation/bioreactor/bioreactor.dm index 47c0498e9d3..83007c82503 100644 --- a/code/modules/biomatter_manipulation/bioreactor/bioreactor.dm +++ b/code/modules/biomatter_manipulation/bioreactor/bioreactor.dm @@ -105,9 +105,10 @@ chamber_closed = !chamber_closed -/datum/multistructure/bioreactor/proc/pump_solution() - if(!chamber_closed || !is_operational()) - return +/datum/multistructure/bioreactor/proc/pump_solution(forced) + if(!forced) + if(!chamber_closed || !is_operational()) + return if(chamber_solution) solution.icon_state = "" flick("solution_pump_out", solution) @@ -128,6 +129,7 @@ icon_state = "biomassconsole1" anchored = TRUE density = TRUE + panel_open = -1 MS_type = /datum/multistructure/bioreactor var/datum/multistructure/bioreactor/MS_bioreactor diff --git a/code/modules/biomatter_manipulation/bioreactor/platform.dm b/code/modules/biomatter_manipulation/bioreactor/platform.dm index b5fac478ead..3e6f1a409e1 100644 --- a/code/modules/biomatter_manipulation/bioreactor/platform.dm +++ b/code/modules/biomatter_manipulation/bioreactor/platform.dm @@ -36,7 +36,7 @@ //if our target has hazard protection, apply damage based on the protection percentage. var/hazard_protection = victim.getarmor(null, ARMOR_BIO) var/damage = BIOREACTOR_DAMAGE_PER_TICK - (BIOREACTOR_DAMAGE_PER_TICK * (hazard_protection/100)) - victim.apply_damage(damage, BRUTE, used_weapon = "Biological") + victim.apply_damage(damage, BURN, used_weapon = "Biological") // Before ErisMed 4 damage type was CLONE until some CLOWN changed it to simply BRUTE for no reason. TODO: change to better damage type when possible victim.adjustOxyLoss(BIOREACTOR_DAMAGE_PER_TICK / 2) // Snowflake shit, but we need the mob to die within a reasonable time frame if(prob(10)) @@ -79,7 +79,7 @@ //if our machine is non operational, let's go idle powermode and pump out solution use_power(idle_power_usage) if(MS_bioreactor.chamber_solution) - MS_bioreactor.pump_solution() + MS_bioreactor.pump_solution(forced = 1) /obj/machinery/multistructure/bioreactor_part/platform/attackby(var/obj/item/I, var/mob/user) @@ -169,13 +169,12 @@ //Here we go through our windows and check it for breach. If somewhere glass will be missing, we return TRUE and turn our bioreactor var /obj/machinery/multistructure/bioreactor_part/platform/proc/is_breached() var/list/glass_dirs = get_opened_dirs() - for(var/obj/structure/window/reinforced/glass in loc) + for(var/obj/structure/window/reinforced/bioreactor/glass in loc) if(glass.dir in glass_dirs) glass_dirs -= glass.dir if(glass_dirs.len) MS_bioreactor.chamber_breached = TRUE return TRUE - MS_bioreactor.chamber_breached = FALSE return FALSE @@ -223,10 +222,10 @@ contamination_level += amount if(contamination_level >= max_contamination_lvl) contamination_level = max_contamination_lvl - opacity = FALSE + opacity = TRUE if(contamination_level <= 0) contamination_level = 0 - opacity = TRUE + opacity = FALSE update_icon() diff --git a/code/modules/biomatter_manipulation/solidifier.dm b/code/modules/biomatter_manipulation/solidifier.dm index c25dcf7ff60..439289802f8 100644 --- a/code/modules/biomatter_manipulation/solidifier.dm +++ b/code/modules/biomatter_manipulation/solidifier.dm @@ -17,6 +17,7 @@ idle_power_usage = 5 active_power_usage = 300 reagent_flags = TRANSPARENT + panel_open = -1 var/active = FALSE var/port_dir = SOUTH diff --git a/code/modules/core_implant/cruciform/rituals/machinery.dm b/code/modules/core_implant/cruciform/rituals/machinery.dm index db68a12d4a7..38eaea18338 100644 --- a/code/modules/core_implant/cruciform/rituals/machinery.dm +++ b/code/modules/core_implant/cruciform/rituals/machinery.dm @@ -219,10 +219,15 @@ /datum/ritual/cruciform/machines/bioreactor/chamber_doors name = "Bioreactor chamber's words" phrase = "Constituit quoque ianitores in portis domus Domini ut non ingrederetur eam inmundus in omni." - desc = "This ritual opens or closes the bioreactor chamber. You should stay nearby its screen." + desc = "This ritual opens, closes and checks if the bioreactor chamber is sealed properly. You should stay nearby its screen." /datum/ritual/cruciform/machines/bioreactor/chamber_doors/perform_command(datum/multistructure/bioreactor/bioreactor) + if(bioreactor.chamber_breached) + for(var/obj/machinery/multistructure/bioreactor_part/platform/platform in bioreactor.elements) + if(platform.is_breached()) + return FALSE + bioreactor.chamber_breached = FALSE if(bioreactor.chamber_solution) return FALSE bioreactor.toggle_platform_door() diff --git a/code/modules/long_range_scanner/hull.dm b/code/modules/long_range_scanner/hull.dm index c2ae02576ee..351ba6471c9 100644 --- a/code/modules/long_range_scanner/hull.dm +++ b/code/modules/long_range_scanner/hull.dm @@ -1,9 +1,10 @@ //The main hull long range scanner. -/obj/machinery/power/long_range_scanner/hull +/obj/machinery/power/shipside/long_range_scanner/hull name = "long range scanner core" //This subtype comes pre-deployed and partially charged -/obj/machinery/power/long_range_scanner/hull/installed/Initialize() +/obj/machinery/power/shipside/long_range_scanner/hull/installed/Initialize() . = ..() - anchored = toggle_tendrils(TRUE) + anchored = TRUE + spawn_tendrils() current_energy = max_energy * 0.30 diff --git a/code/modules/long_range_scanner/long_range_scanner.dm b/code/modules/long_range_scanner/long_range_scanner.dm index eb3e52609c8..3d6159045cb 100644 --- a/code/modules/long_range_scanner/long_range_scanner.dm +++ b/code/modules/long_range_scanner/long_range_scanner.dm @@ -5,13 +5,14 @@ #define PASSIVE_SCAN_PERIOD 3 SECONDS #define PULSE_PROGRESS_TIME 30 // in decisecond #define ACTIVE_SCAN_RANGE 10 -#define ACTIVE_SCAN_DURATION 30 SECONDS +#define ACTIVE_SCAN_DURATION 10 SECONDS var/list/ship_scanners = list() -/obj/machinery/power/long_range_scanner +/obj/machinery/power/shipside/long_range_scanner name = "long range scanner" desc = "An advanced long range scanner with heavy-duty capacitor, capable of scanning celestial anomalies at large distances." + description_info = "Can be moved by retracting the power conduits with the appropiate right-click verb" icon = 'icons/obj/machines/conduit_of_soul.dmi' icon_state = "core_inactive" density = TRUE @@ -19,78 +20,64 @@ var/list/ship_scanners = list() circuit = /obj/item/electronics/circuitboard/long_range_scanner - - - var/needs_update = FALSE //If true, will update in process - var/datum/wires/long_range_scanner/wires - var/list/event_log = list() // List of relevant events for this shield - var/max_log_entries = 200 // A safety to prevent players generating endless logs and maybe endangering server memory + list/event_log = list() // List of relevant events for this scanner + max_log_entries = 200 // A safety to prevent players generating endless logs and maybe endangering server memory - var/scanner_modes = 0 // Enabled scanner mode flags var/as_duration_multiplier = 1.0 // Active scan duration multiplier (improve internal components) var/as_energy_multiplier = 1.0 // Active scan energy cost multiplier (improve internal components) - var/max_energy = 0 // Maximal stored energy. In joules. Depends on the type of used SMES coil when constructing this scanner. - var/current_energy = 0 // Current stored energy. - var/running = SCANNER_OFF // Whether the scanner is enabled or not. - var/input_cap = 1 MEGAWATTS // Currently set input limit. Set to 0 to disable limits altogether. The shield will try to input this value per tick at most - var/upkeep_power_usage = 0 // Upkeep power usage last tick. - var/power_usage = 0 // Total power usage last tick. - var/overloaded = 0 // Whether the field has overloaded and shut down to regenerate. - var/offline_for = 0 // The scanner will be inoperable for this duration in ticks. - var/input_cut = 0 // Whether the input wire is cut. - var/mode_changes_locked = 0 // Whether the control wire is cut, locking out changes. - var/ai_control_disabled = 0 // Whether the AI control is disabled. - var/emergency_shutdown = FALSE // Whether the scanner is currently recovering from an emergency shutdown - var/list/default_modes = list() - var/generatingShield = FALSE //true when shield tiles are in process of being generated - - var/obj/effect/overmap/ship/linked_ship = null // To access position of Eris on the overmap - - var/list/tendrils = list() - var/list/tendril_dirs = list(NORTH, EAST, WEST) - var/tendrils_deployed = FALSE // Whether the dummy capacitors are currently extended - - -/obj/machinery/power/long_range_scanner/update_icon() - cut_overlays() + max_energy = 0 // Maximal stored energy. In joules. Depends on the type of used SMES coil when constructing this scanner. + var/input_maxcap = 0 // Maximal level of input by the scanner. Set by RefreshParts() + current_energy = 0 // Current stored energy. + running = SCANNER_OFF // Whether the scanner is enabled or not. + input_cap = 1 MEGAWATTS // Currently set input limit. Set to 0 to disable limits altogether. The scanner will try to input this value per tick at most + upkeep_power_usage = 0 // Upkeep power usage last tick. + power_usage = 0 // Total power usage last tick. + offline_for = 0 // The scanner will be inoperable for this duration in ticks. + input_cut = 0 // Whether the input wire is cut. + mode_changes_locked = 0 // Whether the control wire is cut, locking out changes. + ai_control_disabled = 0 // Whether the AI control is disabled. + emergency_shutdown = FALSE // Whether the scanner is currently recovering from an emergency shutdown + + obj/effect/overmap/ship/linked_ship = null // To access position of Eris on the overmap + + list/tendrils = list() + list/tendril_dirs = list() + tendrils_deployed = FALSE // Whether the capacitors are currently extended + + +/obj/machinery/power/shipside/long_range_scanner/update_icon() if(running) set_light(1, 1, "#82C2D8") - icon_state = "core_warmup" - spawn(20) + flick("core_warmup", src) + icon_state = "core_active" + spawn(6) set_light(2, 2, "#82C2D8") - icon_state = "core_active" else set_light(1, 1, "#82C2D8") - icon_state = "core_shutdown" - spawn(20) + flick("core_shutdown", src) + icon_state = "core_inactive" + spawn(5) set_light(0) - icon_state = "core_inactive" - for (var/obj/machinery/scanner_conduit/S in tendrils) + for (var/obj/machinery/power/conduit/scanner_conduit/S in tendrils) if (running) S.dim_light() - S.icon_state = "warmup" - S.update_icon() - spawn(20) + flick("warmup", S) + S.icon_state = "speen" + spawn(19) S.bright_light() - S.icon_state = "speen" - S.update_icon() - else S.dim_light() - S.icon_state = "shutdown" - S.update_icon() - spawn(20) + flick("shutdown", S) + S.icon_state = "inactive" + spawn(5) S.no_light() - S.icon_state = "inactive" - S.update_icon() -/obj/machinery/power/long_range_scanner/Initialize() +/obj/machinery/power/shipside/long_range_scanner/Initialize() . = ..() - connect_to_network() wires = new(src) ship_scanners += src var/obj/effect/overmap/ship/S = map_sectors["[z]"] @@ -100,8 +87,7 @@ var/list/ship_scanners = list() // Link to Eris object on the overmap linked_ship = (locate(/obj/effect/overmap/ship/eris) in GLOB.ships) -/obj/machinery/power/long_range_scanner/Destroy() - toggle_tendrils(FALSE) +/obj/machinery/power/shipside/long_range_scanner/Destroy() QDEL_NULL(wires) ship_scanners -= src var/obj/effect/overmap/ship/S = map_sectors["[z]"] @@ -110,28 +96,49 @@ var/list/ship_scanners = list() . = ..() -/obj/machinery/power/long_range_scanner/RefreshParts() +/obj/machinery/power/shipside/long_range_scanner/RefreshParts() max_energy = 0 - for(var/obj/item/stock_parts/smes_coil/S in component_parts) - max_energy += (S.ChargeCapacity / CELLRATE) - current_energy = between(0, current_energy, max_energy) - - // Better micro lasers increase the duration of the active scan mode - as_duration_multiplier = 1.0 + 0.5 * max_part_rating(/obj/item/stock_parts/micro_laser) - as_duration_multiplier = between(initial(as_duration_multiplier), as_duration_multiplier, 10.0) + input_maxcap = 0 + for(var/obj/machinery/power/conduit/scanner_conduit/SC in tendrils) + for(var/obj/item/stock_parts/smes_coil/S in SC.component_parts) + max_energy += (S.ChargeCapacity / CELLRATE) / 3 //Divide by 3 because three default conduits + input_maxcap += S.IOCapacity //Around 2.25 MEGAWATTS with default parts + current_energy = between(0, current_energy, max_energy) //Yes, same as the shieldgen. + input_cap = between(0, input_cap, input_maxcap) + + // Better scanners increase the duration of the active scan mode + var/scan_rating = 0 + as_duration_multiplier = max(1, 1.0 * tendrils.len) + for(var/obj/item/stock_parts/scanning_module/S in component_parts) + scan_rating += S.rating + as_duration_multiplier *= scan_rating / 2 + for(var/obj/item/bluespace_crystal/artificial/A in component_parts) + as_duration_multiplier /= 2 //Halves duration if you use cheep crystal. Miser pays twice! // Better capacitors diminish the energy consumption of the active scan mode - as_energy_multiplier = 1.0 - 0.1 * max_part_rating(/obj/item/stock_parts/capacitor) - as_energy_multiplier = between(0.0, as_energy_multiplier, initial(as_energy_multiplier)) - + as_energy_multiplier = 1.15 + for(var/obj/machinery/power/conduit/scanner_conduit/SC in tendrils) + as_energy_multiplier -= 0.05 * SC.rating // Shuts down the long range scanner -/obj/machinery/power/long_range_scanner/proc/shutdown_scanner() +/obj/machinery/power/shipside/long_range_scanner/shutdown_machine() running = SCANNER_OFF update_icon() +/obj/machinery/power/shipside/long_range_scanner/spawn_tendrils(dirs = list(NORTH, EAST, WEST)) + for (var/D in dirs) + var/turf/T = get_step(src, D) + var/obj/machinery/power/conduit/scanner_conduit/tendril = locate(T) + if(!tendril) + tendril = new(T) + tendril.connect(src) + tendril.face_atom(src) + tendril.anchored = TRUE + tendrils_deployed = TRUE + build_tendril_dirs() + update_icon() -/obj/machinery/power/long_range_scanner/Process() +/obj/machinery/power/shipside/long_range_scanner/Process() upkeep_power_usage = 0 power_usage = 0 @@ -145,77 +152,39 @@ var/list/ship_scanners = list() // We are shutting down, therefore our stored energy disperses faster than usual. else if(running == SCANNER_DISCHARGING) if (offline_for <= 0) - shutdown_scanner() //We've finished the winding down period and now turn off + shutdown_machine() //We've finished the winding down period and now turn off offline_for += 30 //Another minute before it can be turned back on again return - upkeep_power_usage = ENERGY_UPKEEP_SCANNER + if(running == SCANNER_RUNNING) + upkeep_power_usage = ENERGY_UPKEEP_SCANNER - if(powernet && !input_cut && (running == SCANNER_RUNNING || running == SCANNER_OFF)) + if(tendrils_deployed && !input_cut && (running == SCANNER_RUNNING || running == SCANNER_OFF)) var/energy_buffer = 0 - energy_buffer = draw_power(min(upkeep_power_usage, input_cap)) + for(var/obj/machinery/power/conduit/scanner_conduit/SC in tendrils) + energy_buffer += SC.draw_power(input_cap / tendrils.len) power_usage += round(energy_buffer) - - if(energy_buffer < upkeep_power_usage) - current_energy -= round(upkeep_power_usage - energy_buffer) // If we don't have enough energy from the grid, take it from the internal battery instead. - - // Now try to recharge our internal energy. - var/energy_to_demand - if(input_cap) - energy_to_demand = between(0, max_energy - current_energy, input_cap - upkeep_power_usage) - else - energy_to_demand = max(0, max_energy - current_energy) - energy_buffer = draw_power(energy_to_demand) - power_usage += energy_buffer - current_energy += round(energy_buffer) + current_energy += energy_buffer - upkeep_power_usage //if grid energy is lower than upkeep - negative number will be added else current_energy -= round(upkeep_power_usage) // We are shutting down, or we lack external power connection. Use energy from internal source instead. if(current_energy <= 0) energy_failure() - if (charge_level() > 5) - overloaded = 0 +/obj/machinery/power/shipside/long_range_scanner/proc/energy_failure() + offline_for += 150 + shutdown_machine() + emergency_shutdown = TRUE + if (current_energy < 0) + current_energy = 0 -/obj/machinery/power/long_range_scanner/attackby(obj/item/O as obj, mob/user as mob) - // Prevents dismantle-rebuild tactics to reset the emergency shutdown timer. - if(running) - to_chat(user, "Turn off \the [src] first!") - return - if(offline_for) - to_chat(user, "Wait until \the [src] cools down from emergency shutdown first!") - return - - if(default_deconstruction(O, user)) - return - if(default_part_replacement(O, user)) - return - - //TODO: Implement unwrenching in a proper centralised location. Having to copypaste this around sucks - if(QUALITY_BOLT_TURNING in O.tool_qualities) - wrench(user, O) - return - - if(istool(O)) - return src.attack_hand(user) - -/obj/machinery/power/long_range_scanner/proc/energy_failure() - if(running == SCANNER_DISCHARGING) - shutdown_scanner() - else - if (current_energy < 0) - current_energy = 0 - overloaded = 1 - - -/obj/machinery/power/long_range_scanner/nano_ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = NANOUI_FOCUS) +/obj/machinery/power/shipside/long_range_scanner/nano_ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = NANOUI_FOCUS) var/data[0] data["running"] = running data["logs"] = get_logs() - data["overloaded"] = overloaded data["max_energy"] = round(max_energy / 1000000, 0.1) data["current_energy"] = round(current_energy / 1000000, 0.1) data["input_cap_kw"] = round(input_cap / 1000) @@ -233,19 +202,19 @@ var/list/ship_scanners = list() ui.set_auto_update(1) -/obj/machinery/power/long_range_scanner/attack_hand(var/mob/user) +/obj/machinery/power/shipside/long_range_scanner/attack_hand(var/mob/user) nano_ui_interact(user) if(panel_open) wires.Interact(user) -/obj/machinery/power/long_range_scanner/CanUseTopic(var/mob/user) +/obj/machinery/power/shipside/long_range_scanner/CanUseTopic(var/mob/user) if(issilicon(user) && !Adjacent(user) && ai_control_disabled) return STATUS_UPDATE return ..() -/obj/machinery/power/long_range_scanner/Topic(href, href_list) +/obj/machinery/power/shipside/long_range_scanner/Topic(href, href_list) if(..()) return 1 if(!anchored) @@ -263,13 +232,17 @@ var/list/ship_scanners = list() log_event(EVENT_DISABLED, src) if(href_list["start_generator"]) + if(tendrils_deployed == FALSE) + visible_message(SPAN_DANGER("The [src] buzzes an insistent warning as it needs to have it's conduits deployed first to operate")) + playsound(src.loc, 'sound/machines/buzz-sigh.ogg', 100, 1, 5) + return running = SCANNER_RUNNING update_icon() log_event(EVENT_ENABLED, src) - offline_for = 3 //This is to prevent cases where you startup the shield and then turn it off again immediately while spamclicking + offline_for = 3 //This is to prevent cases where you startup the scanner and then turn it off again immediately while spamclicking . = 1 - // Instantly drops the shield, but causes a cooldown before it may be started again. Also carries a risk of EMP at high charge. + // Instantly drops the scanner, but causes a cooldown before it may be started again. Also carries a risk of EMP at high charge. if(href_list["emergency_shutdown"]) if(!running) return @@ -281,7 +254,7 @@ var/list/ship_scanners = list() var/temp_integrity = charge_level() offline_for += 300 //5 minutes, given that procs happen every 2 seconds - shutdown_scanner() + shutdown_machine() emergency_shutdown = TRUE log_event(EVENT_DISABLED, src) if(prob(temp_integrity - 50) * 1.75) @@ -293,28 +266,23 @@ var/list/ship_scanners = list() return 1 if(href_list["set_input_cap"]) - var/new_cap = round(input(usr, "Enter new input cap (in kW). Enter 0 or nothing to disable input cap.", "Generator Power Control", round(input_cap / 1000)) as num) + var/new_cap = round(input(usr, "Enter new input cap (in kW). Current maximal input cap is [input_maxcap / 1000] kW", "Scanner Power Control", round(input_cap / 1000)) as num) if(!new_cap) - input_cap = 0 return - input_cap = max(0, new_cap) * 1000 + input_cap = between(1, new_cap, input_maxcap / 1000) * 1000 log_event(EVENT_RECONFIGURED, src) . = 1 nano_ui_interact(usr) -/obj/machinery/power/long_range_scanner/proc/charge_level() +/obj/machinery/power/shipside/long_range_scanner/proc/charge_level() if(max_energy) return (current_energy / max_energy) * 100 return 0 -// Checks whether specific flags are enabled -/obj/machinery/power/long_range_scanner/proc/check_flag(var/flag) - return (scanner_modes & flag) - -/obj/machinery/power/long_range_scanner/proc/get_logs() +/obj/machinery/power/shipside/long_range_scanner/proc/get_logs() var/list/all_logs = list() for(var/i = event_log.len; i > 1; i--) all_logs.Add(list(list( @@ -322,30 +290,17 @@ var/list/ship_scanners = list() ))) return all_logs - -/obj/machinery/power/long_range_scanner/proc/wrench(var/user, var/obj/item/O) - if(O.use_tool(user, src, WORKTIME_FAST, QUALITY_BOLT_TURNING, FAILCHANCE_EASY, required_stat = STAT_MEC)) - playsound(src.loc, 'sound/items/Ratchet.ogg', 75, 1) - if(anchored) - to_chat(user, SPAN_NOTICE("You unsecure the [src] from the floor!")) - anchored = FALSE - else - if(istype(get_turf(src), /turf/space)) return //No wrenching these in space! - to_chat(user, SPAN_NOTICE("You secure the [src] to the floor!")) - anchored = TRUE - return - -//This proc keeps an internal log of shield impacts, activations, deactivations, and a vague log of config changes -/obj/machinery/power/long_range_scanner/proc/log_event(var/event_type, var/atom/origin_atom) +//This proc keeps an internal log of scanner activations, deactivations, and a vague log of config changes +/obj/machinery/power/shipside/long_range_scanner/log_event(var/event_type, var/atom/origin_atom) var/logstring = "[stationtime2text()]: " switch (event_type) if (EVENT_ENABLED to EVENT_RECONFIGURED) switch (event_type) if (EVENT_ENABLED) - logstring += "Shield powered up" + logstring += "Scanner powered up" if (EVENT_DISABLED) - logstring += "Shield powered down" + logstring += "Scanner powered down" if (EVENT_RECONFIGURED) logstring += "Configuration altered" else @@ -373,119 +328,54 @@ var/list/ship_scanners = list() if (event_log.len > max_log_entries) event_log.Cut(1,2) -/obj/machinery/scanner_conduit +/obj/machinery/power/shipside/long_range_scanner/proc/consume_energy_scan() + if(current_energy > round(ENERGY_PER_SCAN * as_energy_multiplier)) + current_energy -= round(ENERGY_PER_SCAN * as_energy_multiplier) + return TRUE + return FALSE + + +/obj/machinery/power/conduit/scanner_conduit name = "scanner conduit" icon = 'icons/obj/machines/conduit_of_soul.dmi' icon_state = "inactive" - desc = "A combined conduit and capacitor that transfers and stores massive amounts of energy." + desc = "A combined conduit and capacitor that transfers and stores massive amounts of energy while also increasing the efficiency of connected long range scanner." density = TRUE anchored = FALSE //Will be set true just after deploying - var/obj/machinery/power/long_range_scanner/scanner - -/obj/machinery/scanner_conduit/proc/connect(sca) - scanner = sca - -/obj/machinery/scanner_conduit/proc/no_light() + circuit = /obj/item/electronics/circuitboard/scanner_conduit + var/rating //average rating of all capacitors + +/obj/machinery/power/conduit/scanner_conduit/no_light() set_light(0) -/obj/machinery/scanner_conduit/proc/dim_light() +/obj/machinery/power/conduit/scanner_conduit/proc/dim_light() set_light(1, 1, "#82C2D8") -/obj/machinery/scanner_conduit/proc/bright_light() +/obj/machinery/power/conduit/scanner_conduit/bright_light() set_light(2, 2, "#82C2D8") -/obj/machinery/scanner_conduit/Destroy() - if(scanner) - scanner.toggle_tendrils(FALSE) - if(scanner.running != SCANNER_OFF && !scanner.emergency_shutdown) - scanner.offline_for += 300 - scanner.shutdown_scanner() - scanner.emergency_shutdown = TRUE - scanner.log_event(EVENT_DISABLED, scanner) +/obj/machinery/power/conduit/scanner_conduit/RefreshParts() + rating = 0 + for(var/obj/item/stock_parts/capacitor/C in component_parts) + rating += C.rating + rating /= 2 . = ..() -/obj/machinery/power/long_range_scanner/wrench(user, obj/item/I) - if(running != SCANNER_OFF) - to_chat(usr, SPAN_NOTICE("Scanner has to be toggled off first!")) - return - if(tendrils_deployed) - to_chat(usr, SPAN_NOTICE("Retract conduits first!")) - return - if(I.use_tool(user, src, WORKTIME_FAST, QUALITY_BOLT_TURNING, FAILCHANCE_EASY, required_stat = STAT_MEC)) - playsound(src.loc, 'sound/items/Ratchet.ogg', 75, 1) - if(anchored) - to_chat(user, SPAN_NOTICE("You unsecure the [src] from the floor!")) - toggle_tendrils(FALSE) - anchored = FALSE - else - if(istype(get_turf(src), /turf/space)) return //No wrenching these in space! - to_chat(user, SPAN_NOTICE("You secure the [src] to the floor!")) - anchored = TRUE - return - -/obj/machinery/power/long_range_scanner/verb/toggle_tendrils_verb() - set category = "Object" - set name = "Toggle conduits" - set src in view(1) - - if(running != SCANNER_OFF) - to_chat(usr, SPAN_NOTICE("Scanner has to be toggled off first!")) - return - toggle_tendrils() - -/obj/machinery/power/long_range_scanner/proc/toggle_tendrils(on = null) - var/target_state - if (!isnull(on)) - target_state = on - else - target_state = tendrils_deployed ? FALSE : TRUE //Otherwise we're toggling - - if (target_state == tendrils_deployed) - return - //If we're extending them - if (target_state == TRUE) - for (var/D in tendril_dirs) - var/turf/T = get_step(src, D) - var/obj/machinery/scanner_conduit/SC = locate(/obj/machinery/scanner_conduit) in T - if(SC) - continue - if (!turf_clear(T)) - visible_message(SPAN_DANGER("The [src] buzzes an insistent warning as it lacks the space to deploy")) - playsound(src.loc, "/sound/machines/buzz-two", 100, 1, 5) - tendrils_deployed = FALSE - update_icon() - return FALSE - - //Now deploy - for (var/D in tendril_dirs) - var/turf/T = get_step(src, D) - var/obj/machinery/scanner_conduit/SC = locate(/obj/machinery/scanner_conduit) in T - if(!SC) SC = new(T) - SC.connect(src) - tendrils.Add(SC) - SC.face_atom(src) - SC.anchored = TRUE - tendrils_deployed = TRUE - update_icon() - - to_chat(usr, SPAN_NOTICE("You deployed [src] conduits.")) - return TRUE - - else if (target_state == FALSE) - for (var/obj/machinery/scanner_conduit/SC in tendrils) - tendrils.Remove(SC) - qdel(SC) - tendrils_deployed = FALSE - update_icon() - - to_chat(usr, SPAN_NOTICE("You retracted [src] conduits.")) +/obj/machinery/power/conduit/scanner_conduit/disconnect() + if(!base) return FALSE - -/obj/machinery/power/long_range_scanner/proc/consume_energy_scan() - if(current_energy > round(ENERGY_PER_SCAN * as_energy_multiplier)) - current_energy -= round(ENERGY_PER_SCAN * as_energy_multiplier) - return TRUE - return FALSE + if(base.running != 0 && !base.emergency_shutdown) + base.offline_for += 300 + base.shutdown_machine() + base.emergency_shutdown = TRUE + base.log_event(EVENT_DISABLED, base) + base.tendrils.Remove(src) + base.build_tendril_dirs() + base.RefreshParts() + base.update_icon() + base = null + no_light() + disconnect_from_network() #undef EVENT_ENABLED #undef EVENT_DISABLED diff --git a/code/modules/modular_computers/file_system/programs/engineering/shield_control.dm b/code/modules/modular_computers/file_system/programs/engineering/shield_control.dm index 9d1019172b3..96e9dc644ca 100644 --- a/code/modules/modular_computers/file_system/programs/engineering/shield_control.dm +++ b/code/modules/modular_computers/file_system/programs/engineering/shield_control.dm @@ -23,7 +23,7 @@ /datum/nano_module/shield_control name = "Shield control" - var/obj/machinery/power/shield_generator/hull/gen = null + var/obj/machinery/power/shipside/shield_generator/hull/gen = null var/multigen = FALSE //Set true if multiple active hull shield generators are detected onstation var/genloc = ""//A string that describes the location of our connected shield generator @@ -35,11 +35,11 @@ /datum/nano_module/shield_control/proc/connect_to_generator() var/n = 0 gen = null - for (var/obj/machinery/power/shield_generator/hull/G in world) + for (var/obj/machinery/power/shipside/shield_generator/hull/G in world) //Check that the generator is on the same vessel as us. //This allows antag ships/stations to have their own shield generators and consoles if (is_matching_vessel(G, nano_host())) - if (G.anchored && G.tendrils_deployed) //Only look at those that are wrenched in and setup + if (G.anchored && G.tendrils_deployed && !G.ai_control_disabled) //Only look at those that are wrenched in and setup gen = G //It's a good enough candidate, we're connected! n++ @@ -121,6 +121,7 @@ //If the generator has been unwrenched we also lose connection playsound_host('sound/machines/buzz-two.ogg', 50) gen = null //Cut our connection, and we'll be unable to reconnect + genloc = "" //Clear the location too! return @@ -159,7 +160,7 @@ var/temp_integrity = gen.field_integrity() gen.offline_for += 300 //5 minutes, given that procs happen every 2 seconds - gen.shutdown_field() + gen.shutdown_machine() gen.emergency_shutdown = TRUE gen.log_event(EVENT_DISABLED, nano_host()) if(prob(temp_integrity - 50) * 1.75) @@ -180,11 +181,10 @@ . = 1 if(href_list["set_input_cap"]) - var/new_cap = round(input(usr, "Enter new input cap (in kW). Enter 0 or nothing to disable input cap.", "Generator Power Control", round(gen.input_cap / 1000)) as num) + var/new_cap = round(input(usr, "Enter new input cap (in kW). Current maximal input cap is [gen.input_maxcap / 1000] kW", "Generator Power Control", round(gen.input_cap / 1000)) as num) if(!new_cap) - gen.input_cap = 0 return - gen.input_cap = max(0, new_cap) * 1000 + gen.input_cap = between(1, new_cap, gen.input_maxcap / 1000) * 1000 gen.log_event(EVENT_RECONFIGURED, nano_host()) . = 1 diff --git a/code/modules/nano/modules/nano_module.dm b/code/modules/nano/modules/nano_module.dm index c856aa5a52d..da4f0ebcdde 100644 --- a/code/modules/nano/modules/nano_module.dm +++ b/code/modules/nano/modules/nano_module.dm @@ -174,8 +174,9 @@ //Allows computer programs to play sounds from the console /datum/nano_module/proc/playsound_host(soundin, vol as num, vary, extrarange as num, falloff, var/is_global, var/use_pressure = TRUE) - if (!host) - return + var/atom/nhost = nano_host() + if (!nhost) + return FALSE - var/turf/T = get_turf(host) + var/turf/T = get_turf(nhost) playsound(T, soundin, vol, vary, extrarange, falloff, is_global,use_pressure) diff --git a/code/modules/overmap/ships/ship.dm b/code/modules/overmap/ships/ship.dm index 0b0b146d636..9345016f8e4 100644 --- a/code/modules/overmap/ships/ship.dm +++ b/code/modules/overmap/ships/ship.dm @@ -14,7 +14,7 @@ var/obj/machinery/computer/helm/nav_control var/list/engines = list() // contains /datum/ship_engine - var/list/scanners = list() // contains /obj/machinery/power/long_range_scanner + var/list/scanners = list() // contains /obj/machinery/power/shipside/long_range_scanner var/engines_state = 1 //global on/off toggle for all engines var/thrust_limit = 1 //global thrust limit for all engines, 0..1 var/triggers_events = 1 @@ -57,7 +57,7 @@ E.linked = src //testing("Engines console at level [E.z] linked to overmap object '[name]'.") - for(var/obj/machinery/power/long_range_scanner/LRS in ship_scanners) + for(var/obj/machinery/power/shipside/long_range_scanner/LRS in ship_scanners) if (LRS.z in map_z) //testing("Scanner at level [LRS.z] linked to overmap object '[name]'.") scanners |= LRS @@ -87,7 +87,7 @@ E.linked = src //testing("Engines console at level [E.z] linked to overmap object '[name]'.") - for(var/obj/machinery/power/long_range_scanner/LRS in ship_scanners) + for(var/obj/machinery/power/shipside/long_range_scanner/LRS in ship_scanners) if (LRS.z in map_z) //testing("Scanner at level [LRS.z] linked to overmap object '[name]'.") scanners |= LRS @@ -251,14 +251,16 @@ if(pulsing) // Should not happen but better to check return - var/obj/machinery/power/long_range_scanner/enough_LRS = null - for(var/obj/machinery/power/long_range_scanner/LRS in scanners) // Among all ship's scanners get one with enough energy + var/obj/machinery/power/shipside/long_range_scanner/enough_LRS = null + for(var/obj/machinery/power/shipside/long_range_scanner/LRS in scanners) // Among all ship's scanners get one with enough energy if(LRS.running && (LRS.current_energy > round(ENERGY_PER_SCAN * LRS.as_energy_multiplier))) enough_LRS = LRS - if(enough_LRS) - enough_LRS.consume_energy_scan() + if(!enough_LRS) + nav_control.visible_message(SPAN_DANGER("The [src] buzzes an insistent warning as it fails to find any sensors with enough power to pulse")) + playsound(nav_control.loc, 'sound/machines/buzz-two.ogg', 100, 1, 5) + if(enough_LRS.consume_energy_scan()) pulsing = TRUE scan_range = ACTIVE_SCAN_RANGE spawn(ACTIVE_SCAN_DURATION * enough_LRS.as_duration_multiplier) @@ -269,7 +271,7 @@ /obj/effect/overmap/ship/proc/can_scan() - for(var/obj/machinery/power/long_range_scanner/LRS in scanners) + for(var/obj/machinery/power/shipside/long_range_scanner/LRS in scanners) . |= (LRS.running) /obj/effect/overmap/ship/proc/can_pulse() @@ -278,7 +280,7 @@ return FALSE // Check if one of the ship's scanners has enough energy to pulse - for(var/obj/machinery/power/long_range_scanner/LRS in scanners) + for(var/obj/machinery/power/shipside/long_range_scanner/LRS in scanners) . |= (LRS.running && (LRS.current_energy > round(ENERGY_PER_SCAN * LRS.as_energy_multiplier))) /obj/effect/overmap/ship/proc/can_scan_poi() @@ -286,7 +288,7 @@ if(!is_still()) // Ship must be immobile return FALSE - for(var/obj/machinery/power/long_range_scanner/LRS in scanners) + for(var/obj/machinery/power/shipside/long_range_scanner/LRS in scanners) . |= (LRS.running) /obj/effect/overmap/ship/proc/scan_poi() diff --git a/code/modules/power/shipside_machinery.dm b/code/modules/power/shipside_machinery.dm new file mode 100644 index 00000000000..5d4c7ba606e --- /dev/null +++ b/code/modules/power/shipside_machinery.dm @@ -0,0 +1,285 @@ +//File created to collect all of the shared code between shield generator, long range scanner and their conduits +//Maybe used for future uses too + +/obj/machinery/power/shipside + name = "heavy shipside machinery" + desc = "A heavy-duty unknown piece of machinery used for the basic functions of the ship." + description_info = "Shouldn't really appear anywhere, please notify admins" + icon = 'icons/obj/machines/shielding.dmi' + icon_state = "baygenerator0" + density = TRUE + anchored = FALSE + + circuit = null + + var/list/event_log = list() // List of relevant events for this machine + var/max_log_entries = 200 // A safety to prevent players generating endless logs and maybe endangering server memory + + var/max_energy = 0 // Maximal stored energy. In joules. Depends on the type of used SMES coil when constructing this machinery. + var/current_energy = 0 // Current stored energy. + var/running = null // Whether the machinery is enabled or not. + var/input_cap = 1 MEGAWATTS // Currently set input limit. Set to 0 to disable limits altogether. The machine will try to input this value per tick at most + var/upkeep_power_usage = 0 // Upkeep power usage last tick. + var/power_usage = 0 // Total power usage last tick. + var/overloaded = 0 // Whether the machinery has overloaded and shut down to regenerate. + var/offline_for = 0 // The machinery will be inoperable for this duration in ticks. + var/input_cut = 0 // Whether the input wire is cut. + var/mode_changes_locked = 0 // Whether the control wire is cut, locking out changes. + var/ai_control_disabled = 0 // Whether the AI control is disabled. + var/emergency_shutdown = FALSE // Whether the machinery is currently recovering from an emergency shutdown + + var/obj/effect/overmap/ship/linked_ship = null // To access position of Eris on the overmap + + var/list/tendrils = list() + var/list/tendril_dirs = list() + var/tendrils_deployed = FALSE // Whether the capacitors are currently extended + + +/obj/machinery/power/shipside/Destroy() + for(var/obj/machinery/power/conduit/C in tendrils) + C.disconnect() + . = ..() + +/obj/machinery/power/shipside/proc/shutdown_machine() + return + +/obj/machinery/power/shipside/proc/build_tendril_dirs() + tendril_dirs = list() + if(tendrils.len < 1) + return FALSE + for (var/obj/machinery/power/conduit/C in tendrils) + tendril_dirs.Add(turn(C.dir, 180)) + return TRUE + +/obj/machinery/power/shipside/proc/spawn_tendrils(dirs = list(NORTH, EAST, WEST)) + for (var/D in dirs) + var/turf/T = get_step(src, D) + var/obj/machinery/power/conduit/tendril = locate(T) + if(!tendril) + tendril = new(T) + tendril.connect(src) + tendril.face_atom(src) + tendril.anchored = TRUE + tendrils_deployed = TRUE + build_tendril_dirs() + update_icon() + +/obj/machinery/power/shipside/proc/log_event(event_type, atom/origin_atom) + return + +/obj/machinery/power/shipside/verb/toggle_tendrils_verb() + set category = "Object" + set name = "Toggle conduits" + set src in view(1) + + if(running != 0) + to_chat(usr, SPAN_NOTICE("[src] has to be toggled off first!")) + return + toggle_tendrils() + +/obj/machinery/power/shipside/proc/toggle_tendrils(forced_state) + var/target_state + if (isnull(forced_state)) + target_state = tendrils_deployed ? FALSE : TRUE + else + target_state = forced_state + + if (target_state == tendrils_deployed) + return + //If we're extending them + if (target_state == TRUE) + if(!anchored) + visible_message(SPAN_DANGER("The [src] buzzes an insistent warning as it needs to be properly anchored to deploy")) + playsound(src.loc, 'sound/machines/buzz-two.ogg', 100, 1, 5) + tendrils_deployed = FALSE + update_icon() + return FALSE + if(!build_tendril_dirs()) + visible_message(SPAN_DANGER("The [src] buzzes an insistent warning as it has no conduits to deploy")) + playsound(src.loc, 'sound/machines/buzz-two.ogg', 100, 1, 5) + return FALSE + for (var/D in tendril_dirs) + var/turf/T = get_step(src, D) + if (!turf_clear_ignore_cables(T)) + visible_message(SPAN_DANGER("The [src] buzzes an insistent warning as it lacks the space to deploy")) + playsound(src.loc, 'sound/machines/buzz-two.ogg', 100, 1, 5) + tendrils_deployed = FALSE + update_icon() + return FALSE + + //Now deploy + for (var/obj/machinery/power/conduit/C in tendrils) + var/turf/T = get_step(src, turn(C.dir, 180)) + C.forceMove(T) + C.connect(src) + C.anchored = TRUE + C.connect_to_network() + tendrils_deployed = TRUE + update_icon() + + to_chat(usr, SPAN_NOTICE("You deployed [src] conduits.")) + return TRUE + + else if (target_state == FALSE) + for (var/obj/machinery/power/conduit/C in tendrils) + C.disconnect_from_network() + C.forceMove(src) + tendrils_deployed = FALSE + update_icon() + + to_chat(usr, SPAN_NOTICE("You retracted [src] conduits.")) + return FALSE + +/obj/machinery/power/shipside/attackby(obj/item/O, mob/user) + // Prevents dismantle-rebuild tactics to reset the emergency shutdown timer. + if(running) + to_chat(user, "Turn off \the [src] first!") + return + if(offline_for) + to_chat(user, "Wait until \the [src] cools down from emergency shutdown first!") + return + + if(default_deconstruction(O, user)) + return + if(default_part_replacement(O, user)) + return + + //TODO: Implement unwrenching in a proper centralised location. Having to copypaste this around sucks + if(QUALITY_BOLT_TURNING in O.tool_qualities) + wrench(user, O) + return + + if(istool(O)) + return src.attack_hand(user) + +/obj/machinery/power/shipside/proc/wrench(user, obj/item/I) + if(running != 0) + to_chat(usr, SPAN_NOTICE("[src] has to be toggled off first!")) + return + if(tendrils_deployed) + to_chat(usr, SPAN_NOTICE("Retract conduits first!")) + return + if(I.use_tool(user, src, WORKTIME_FAST, QUALITY_BOLT_TURNING, FAILCHANCE_EASY, required_stat = STAT_MEC)) + playsound(src.loc, 'sound/items/Ratchet.ogg', 75, 1) + if(anchored) + to_chat(user, SPAN_NOTICE("You unsecure the [src] from the floor!")) + toggle_tendrils(FALSE) + anchored = FALSE + else + if(istype(get_turf(src), /turf/space)) return //No wrenching these in space! + to_chat(user, SPAN_NOTICE("You secure the [src] to the floor!")) + anchored = TRUE + return + + +/obj/machinery/power/conduit //Da parent of all the conduits, shouldn't really appear anywhere + name = "general conduit" + icon = 'icons/obj/machines/shielding.dmi' + icon_state = "shieldsparkles" + desc = "A combined conduit and capacitor that transfers and stores massive amounts of energy." + density = TRUE + anchored = FALSE //Will be set true just after deploying + circuit = null + var/obj/machinery/power/shipside/base + +/obj/machinery/power/conduit/Initialize() + . = ..() + add_statverb(/datum/statverb/connect_conduit) + +/obj/machinery/power/conduit/proc/connect(target) + if(base || !target) + return FALSE + base = target + base.tendrils.Add(src) + anchored = TRUE + connect_to_network() + base.RefreshParts() + base.build_tendril_dirs() + base.update_icon() + +/obj/machinery/power/conduit/proc/disconnect() + if(!base) + return FALSE + if(base.running != 0 && !base.emergency_shutdown) + base.offline_for += 300 + base.shutdown_machine() + base.emergency_shutdown = TRUE + base.log_event(0, base) + base.tendrils.Remove(src) + base.build_tendril_dirs() + base.RefreshParts() + base.update_icon() + base = null + no_light() + disconnect_from_network() + +/obj/machinery/power/conduit/proc/no_light() + set_light(0) + +/obj/machinery/power/conduit/proc/bright_light() + set_light(2, 2, "#ff0000") + +/obj/machinery/power/conduit/Destroy() + if(base) + disconnect() + . = ..() + +/obj/machinery/power/conduit/on_deconstruction() + disconnect() + . = ..() + +/obj/machinery/power/conduit/RefreshParts() + . = ..() + if(base) + base.RefreshParts() + +/obj/machinery/power/conduit/attackby(obj/item/O, mob/user) + // Prevents whatever unholy things can happen if you touch conduits mid-work. + if(base) + if(base.running) + to_chat(user, "Turn off \the [base] first!") + return + if(base.offline_for) + to_chat(user, "Wait until \the [base] cools down from emergency shutdown first!") + return + + if(default_deconstruction(O, user)) + return + if(default_part_replacement(O, user)) + if(base) + base.RefreshParts() + return + + //TODO: Implement unwrenching in a proper centralised location. Having to copypaste this around sucks + if(QUALITY_BOLT_TURNING in O.tool_qualities) + wrench(user, O) + return + + if(istool(O)) + return src.attack_hand(user) + +/obj/machinery/power/conduit/proc/wrench(user, obj/item/I) + if(base) + to_chat(usr, SPAN_NOTICE("Disconnect [src] from the [base] first!")) + return + if(I.use_tool(user, src, WORKTIME_FAST, QUALITY_BOLT_TURNING, FAILCHANCE_EASY, required_stat = STAT_MEC)) + playsound(src.loc, 'sound/items/Ratchet.ogg', 75, 1) + if(anchored) + to_chat(user, SPAN_NOTICE("You unsecure the [src] from the floor!")) + anchored = FALSE + else + if(istype(get_turf(src), /turf/space)) return //No wrenching these in space! + to_chat(user, SPAN_NOTICE("You secure the [src] to the floor!")) + anchored = TRUE + return + +/obj/machinery/power/conduit/verb/rotate() //copied from emitter.dm + set name = "Rotate" + set category = "Object" + set src in oview(1) + + if (src.anchored || usr.stat) + to_chat(usr, "It is fastened to the floor!") + return 0 + src.set_dir(turn(src.dir, 90)) + return 1 \ No newline at end of file diff --git a/code/modules/reagents/reagents/food-Drinks.dm b/code/modules/reagents/reagents/food-Drinks.dm index a573c22db5f..b108365cba4 100644 --- a/code/modules/reagents/reagents/food-Drinks.dm +++ b/code/modules/reagents/reagents/food-Drinks.dm @@ -1534,6 +1534,7 @@ ..() M.adjust_hallucination(-0.9 * effect_multiplier) M.add_chemical_effect(CE_TOXIN, -2.5 * effect_multiplier) + M.add_chemical_effect(CE_ANTITOX, 4) //two times as good as dylo // Cocktails /datum/reagent/alcohol/acid_spit diff --git a/code/modules/research/designs/circuits.dm b/code/modules/research/designs/circuits.dm index efd8a0c10b5..f5c38fe0f0e 100644 --- a/code/modules/research/designs/circuits.dm +++ b/code/modules/research/designs/circuits.dm @@ -385,16 +385,16 @@ category = CAT_MISC /datum/design/research/circuit/shield/hull - name = "hull" + name = "hull shield generator" + desc = "Allows for the construction of a shield conduit circuit board." build_path = /obj/item/electronics/circuitboard/shield_generator sort_string = "VAAAB" -/* -/datum/design/research/circuit/shield/capacitor - name = "capacitor" - desc = "Allows for the construction of a shield capacitor circuit board." - req_tech = list(TECH_MAGNET = 3, TECH_POWER = 4) - build_path = /obj/item/electronics/circuitboard/shield_cap - sort_string = "VAAAC"*/ + +/datum/design/research/circuit/shield/conduit + name = "shield conduit" + desc = "Allows for the construction of a shield conduit circuit board." + build_path = /obj/item/electronics/circuitboard/shield_conduit + sort_string = "VAAAC" // Long range scanner /datum/design/research/circuit/lrange_scanner @@ -404,19 +404,24 @@ /datum/design/research/circuit/lrange_scanner/hull name = "long range scanner" build_path = /obj/item/electronics/circuitboard/long_range_scanner - sort_string = "VAAAC" + sort_string = "VAAAD" + +/datum/design/research/circuit/lrange_scanner/conduit + name = "long range scanner conduit" + build_path = /obj/item/electronics/circuitboard/scanner_conduit + sort_string = "VAAAE" //BS /datum/design/research/circuit/telesci/console name = "TeleSci Console" build_path = /obj/item/electronics/circuitboard/telesci_console - sort_string = "VAAAD" + sort_string = "VAAAF" category = CAT_BLUE /datum/design/research/circuit/telesci/hub name = "TeleSci Pad" build_path = /obj/item/electronics/circuitboard/telesci_pad - sort_string = "VAAAE" + sort_string = "VAAAG" category = CAT_BLUE /datum/design/research/circuit/bssilk/console @@ -428,7 +433,7 @@ /datum/design/research/circuit/bssilk/hub name = "Bluespace Snare Hub" build_path = /obj/item/electronics/circuitboard/bssilk_hub - sort_string = "VAAAG" + sort_string = "VAAAH" category = CAT_BLUE /datum/design/research/circuit/teleporter/station diff --git a/code/modules/research/nodes/bluespace.dm b/code/modules/research/nodes/bluespace.dm index 2e7fda3b491..9581a32cf52 100644 --- a/code/modules/research/nodes/bluespace.dm +++ b/code/modules/research/nodes/bluespace.dm @@ -120,7 +120,8 @@ required_tech_levels = list() cost = 1500 - unlocks_designs = list(/datum/design/research/circuit/shield/hull) + unlocks_designs = list( /datum/design/research/circuit/shield/hull, + /datum/design/research/circuit/shield/conduit) /datum/technology/teleportation name = "Teleportation" @@ -135,8 +136,7 @@ required_tech_levels = list() cost = 1500 - unlocks_designs = list(/datum/design/research/circuit/teleconsole, - /datum/design/research/circuit/lrange_scanner/hull) + unlocks_designs = list( /datum/design/research/circuit/teleconsole) /datum/technology/adv_spatial_scan name = "Advanced Spatial Analyzing" @@ -157,7 +157,9 @@ /datum/design/research/circuit/bssilk/console, /datum/design/research/item/bs_snare, /datum/design/research/circuit/teleporter/station, - /datum/design/research/circuit/teleporter/hub + /datum/design/research/circuit/teleporter/hub, + /datum/design/research/circuit/lrange_scanner/hull, + /datum/design/research/circuit/lrange_scanner/conduit ) /datum/technology/bluespace_tools diff --git a/code/modules/shield_generators/hull.dm b/code/modules/shield_generators/hull.dm index 6c0669c83d8..0ee965d7570 100644 --- a/code/modules/shield_generators/hull.dm +++ b/code/modules/shield_generators/hull.dm @@ -1,11 +1,12 @@ //The main hull shield. Moving a few variables here to make it easier to branch off the parent for shortrange bubble shields and such -/obj/machinery/power/shield_generator/hull +/obj/machinery/power/shipside/shield_generator/hull name = "hull shield core" report_integrity = TRUE //This subtype comes pre-deployed and partially charged -/obj/machinery/power/shield_generator/hull/installed/Initialize() +/obj/machinery/power/shipside/shield_generator/hull/installed/Initialize() . = ..() - anchored = toggle_tendrils(TRUE) + anchored = TRUE + spawn_tendrils() current_energy = max_energy * 0.30 diff --git a/code/modules/shield_generators/shield.dm b/code/modules/shield_generators/shield.dm index a12141b9c68..8d0b58f1e94 100644 --- a/code/modules/shield_generators/shield.dm +++ b/code/modules/shield_generators/shield.dm @@ -27,7 +27,7 @@ layer = BELOW_OBJ_LAYER density = TRUE invisibility = 0 - var/obj/machinery/power/shield_generator/gen = null + var/obj/machinery/power/shipside/shield_generator/gen = null var/disabled_for = 0 var/diffused_for = 0 var/floorOnly = FALSE @@ -308,31 +308,31 @@ Like for example singulo act and whatever. // Shield collision checks below -/atom/movable/proc/can_pass_shield(var/obj/machinery/power/shield_generator/gen) +/atom/movable/proc/can_pass_shield(var/obj/machinery/power/shipside/shield_generator/gen) return 1 // Other mobs -/mob/living/can_pass_shield(var/obj/machinery/power/shield_generator/gen) +/mob/living/can_pass_shield(var/obj/machinery/power/shipside/shield_generator/gen) return !gen.check_flag(MODEFLAG_NONHUMANS) // Human mobs -/mob/living/carbon/human/can_pass_shield(var/obj/machinery/power/shield_generator/gen) +/mob/living/carbon/human/can_pass_shield(var/obj/machinery/power/shipside/shield_generator/gen) if(isSynthetic()) return !gen.check_flag(MODEFLAG_ANORGANIC) return !gen.check_flag(MODEFLAG_HUMANOIDS) // Silicon mobs -/mob/living/silicon/can_pass_shield(var/obj/machinery/power/shield_generator/gen) +/mob/living/silicon/can_pass_shield(var/obj/machinery/power/shipside/shield_generator/gen) return !gen.check_flag(MODEFLAG_ANORGANIC) // Generic objects. Also applies to bullets and meteors. -/obj/can_pass_shield(var/obj/machinery/power/shield_generator/gen) +/obj/can_pass_shield(var/obj/machinery/power/shipside/shield_generator/gen) return !gen.check_flag(MODEFLAG_HYPERKINETIC) // Beams -/obj/item/projectile/beam/can_pass_shield(var/obj/machinery/power/shield_generator/gen) +/obj/item/projectile/beam/can_pass_shield(var/obj/machinery/power/shipside/shield_generator/gen) return !gen.check_flag(MODEFLAG_PHOTONIC) diff --git a/code/modules/shield_generators/shield_generator.dm b/code/modules/shield_generators/shield_generator.dm index 509fe1acb90..fc0cb4d2235 100644 --- a/code/modules/shield_generators/shield_generator.dm +++ b/code/modules/shield_generators/shield_generator.dm @@ -6,7 +6,7 @@ #define EVENT_DISABLED 5 #define EVENT_RECONFIGURED 6 -/obj/machinery/power/shield_generator +/obj/machinery/power/shipside/shield_generator name = "advanced shield generator" desc = "A heavy-duty shield generator and capacitor, capable of generating energy shields at large distances." description_info = "Can be moved by retracting the power conduits with the appropiate right-click verb" @@ -22,36 +22,37 @@ var/datum/wires/shield_generator/wires var/list/field_segments = list() // List of all shield segments owned by this generator. var/list/damaged_segments = list() // List of shield segments that have failed and are currently regenerating. - var/list/event_log = list() // List of relevant events for this shield - var/max_log_entries = 200 // A safety to prevent players generating endless logs and maybe endangering server memory + list/event_log = list() // List of relevant events for this shield + max_log_entries = 200 // A safety to prevent players generating endless logs and maybe endangering server memory var/shield_modes = 0 // Enabled shield mode flags var/mitigation_em = 0 // Current EM mitigation var/mitigation_physical = 0 // Current Physical mitigation var/mitigation_heat = 0 // Current Burn mitigation var/mitigation_max = 0 // Maximal mitigation reachable with this generator. Set by RefreshParts() - var/max_energy = 0 // Maximal stored energy. In joules. Depends on the type of used SMES coil when constructing this generator. - var/current_energy = 0 // Current stored energy. + var/input_maxcap = 0 // Maximal level of input by the generator. Set by RefreshParts() + max_energy = 0 // Maximal stored energy. In joules. Depends on the type of used SMES coil when constructing this generator. + current_energy = 0 // Current stored energy. var/field_radius = 200 // Current field radius. //200 is default for hull shield - var/running = SHIELD_OFF // Whether the generator is enabled or not. - var/input_cap = 1 MEGAWATTS // Currently set input limit. Set to 0 to disable limits altogether. The shield will try to input this value per tick at most - var/upkeep_power_usage = 0 // Upkeep power usage last tick. + running = SHIELD_OFF // Whether the generator is enabled or not. + input_cap = 1 MEGAWATTS // Currently set input limit. Set to 0 to disable limits altogether. The shield will try to input this value per tick at most + upkeep_power_usage = 0 // Upkeep power usage last tick. var/upkeep_multiplier = 1 // Multiplier of upkeep values. var/upkeep_star_multiplier = 1 // Multiplier of upkeep values due to proximity with the star at the center of the overmap var/upkeep_star_multiplier_max = 4 // Maximum upkeep multiplier when the ship is right on top of the star var/upkeep_star_multiplier_safe = 50// Distance from star above which shields are no longer impacted (multiplier = 1) - var/power_usage = 0 // Total power usage last tick. - var/overloaded = 0 // Whether the field has overloaded and shut down to regenerate. - var/offline_for = 0 // The generator will be inoperable for this duration in ticks. - var/input_cut = 0 // Whether the input wire is cut. - var/mode_changes_locked = 0 // Whether the control wire is cut, locking out changes. - var/ai_control_disabled = 0 // Whether the AI control is disabled. + power_usage = 0 // Total power usage last tick. + overloaded = 0 // Whether the field has overloaded and shut down to regenerate. + offline_for = 0 // The generator will be inoperable for this duration in ticks. + input_cut = 0 // Whether the input wire is cut. + mode_changes_locked = 0 // Whether the control wire is cut, locking out changes. + ai_control_disabled = 0 // Whether the AI control is disabled. var/list/mode_list = null // A list of shield_mode datums. - var/emergency_shutdown = FALSE // Whether the generator is currently recovering from an emergency shutdown + emergency_shutdown = FALSE // Whether the generator is currently recovering from an emergency shutdown var/list/default_modes = list() var/generatingShield = FALSE //true when shield tiles are in process of being generated - var/obj/effect/overmap/ship/linked_ship = null // To access position of Eris on the overmap + obj/effect/overmap/ship/linked_ship = null // To access position of Eris on the overmap // The shield mode flags which should be enabled on this generator by default @@ -81,12 +82,12 @@ var/report_delay = 20 SECONDS //We will wait this amount of time after taking a hit before sending a report. var/report_scheduled = FALSE // - var/list/tendrils = list() - var/list/tendril_dirs = list(NORTH, EAST, WEST) - var/tendrils_deployed = FALSE // Whether the dummy capacitors are currently extended + list/tendrils = list() + list/tendril_dirs = list() + tendrils_deployed = FALSE // Whether the capacitors are currently extended -/obj/machinery/power/shield_generator/update_icon() +/obj/machinery/power/shipside/shield_generator/update_icon() overlays.Cut() if(running) icon_state = "generator1" @@ -99,7 +100,7 @@ var/I = image(icon,"capacitor_connected", dir = D) overlays += I - for (var/obj/machinery/shield_conduit/S in tendrils) + for (var/obj/machinery/power/conduit/shield_conduit/S in tendrils) if (running) S.icon_state = "conduit_1" S.bright_light() @@ -109,9 +110,8 @@ -/obj/machinery/power/shield_generator/Initialize() +/obj/machinery/power/shipside/shield_generator/Initialize() . = ..() - connect_to_network() wires = new(src) //Add all allowed modes to our mode list for users to select @@ -128,9 +128,8 @@ // Link to Eris object on the overmap linked_ship = (locate(/obj/effect/overmap/ship/eris) in GLOB.ships) -/obj/machinery/power/shield_generator/Destroy() - toggle_tendrils(FALSE) - shutdown_field() +/obj/machinery/power/shipside/shield_generator/Destroy() + shutdown_machine() field_segments = null damaged_segments = null mode_list = null @@ -138,22 +137,26 @@ . = ..() -/obj/machinery/power/shield_generator/RefreshParts() +/obj/machinery/power/shipside/shield_generator/RefreshParts() max_energy = 0 - for(var/obj/item/stock_parts/smes_coil/S in component_parts) - max_energy += (S.ChargeCapacity / CELLRATE) + input_maxcap = 0 + for(var/obj/machinery/power/conduit/shield_conduit/SC in tendrils) + for(var/obj/item/stock_parts/smes_coil/S in SC.component_parts) + max_energy += (S.ChargeCapacity / CELLRATE) / 3 //Divide by 3 because three default conduits + input_maxcap += S.IOCapacity //Around 2.25 MEGAWATTS with default parts current_energy = between(0, current_energy, max_energy) + input_cap = between(0, input_cap, input_maxcap) mitigation_max = MAX_MITIGATION_BASE - for(var/obj/item/stock_parts/capacitor/C in component_parts) - mitigation_max += MAX_MITIGATION_RESEARCH * C.rating + for(var/obj/item/stock_parts/micro_laser/L in component_parts) //Mitigation can theoretically reach 100% but only if One Star laser is used (0 energy per hit). + mitigation_max += MAX_MITIGATION_RESEARCH * L.rating //It could reach >100% (GAIN charge when hit) if tier 6 laser is used (currently not in game, admemes only) mitigation_em = between(0, mitigation_em, mitigation_max) mitigation_physical = between(0, mitigation_physical, mitigation_max) mitigation_heat = between(0, mitigation_heat, mitigation_max) // Shuts down the shield, removing all shield segments and unlocking generator settings. -/obj/machinery/power/shield_generator/proc/shutdown_field() +/obj/machinery/power/shipside/shield_generator/shutdown_machine() for(var/obj/effect/shield/S in field_segments) qdel(S) @@ -163,9 +166,21 @@ mitigation_heat = 0 update_icon() +/obj/machinery/power/shipside/shield_generator/spawn_tendrils(dirs = list(NORTH, EAST, WEST)) + for (var/D in dirs) + var/turf/T = get_step(src, D) + var/obj/machinery/power/conduit/shield_conduit/tendril = locate(T) + if(!tendril) + tendril = new(T) + tendril.connect(src) + tendril.face_atom(src) + tendril.anchored = TRUE + tendrils_deployed = TRUE + build_tendril_dirs() + update_icon() // Generates the field objects. Deletes existing field, if applicable. -/obj/machinery/power/shield_generator/proc/regenerate_field() +/obj/machinery/power/shipside/shield_generator/proc/regenerate_field() needs_update = FALSE if (generatingShield) return @@ -224,7 +239,7 @@ // Recalculates and updates the upkeep multiplier -/obj/machinery/power/shield_generator/proc/update_upkeep_multiplier() +/obj/machinery/power/shipside/shield_generator/proc/update_upkeep_multiplier() var/new_upkeep = 1 for(var/datum/shield_mode/SM in mode_list) if(check_flag(SM.mode_flag)) @@ -233,14 +248,14 @@ upkeep_multiplier = new_upkeep // Recalculates and updates the upkeep star multiplier -/obj/machinery/power/shield_generator/proc/update_upkeep_star_multiplier() +/obj/machinery/power/shipside/shield_generator/proc/update_upkeep_star_multiplier() var/distance = sqrt((linked_ship.x - GLOB.maps_data.overmap_size/2)**2 + (linked_ship.y - GLOB.maps_data.overmap_size/2)**2) // Distance from star if(distance>upkeep_star_multiplier_safe) // Above safe distance, no impact on shields upkeep_star_multiplier = 1 else // Otherwise shields are impacted depending on proximity to the star upkeep_star_multiplier = 1 + (upkeep_star_multiplier_max - 1) * ((upkeep_star_multiplier_safe - distance) / upkeep_star_multiplier_safe) -/obj/machinery/power/shield_generator/Process() +/obj/machinery/power/shipside/shield_generator/Process() upkeep_power_usage = 0 power_usage = 0 @@ -254,7 +269,7 @@ // We are shutting down, therefore our stored energy disperses faster than usual. else if(running == SHIELD_DISCHARGING) if (offline_for <= 0) - shutdown_field() //We've finished the winding down period and now turn off + shutdown_machine() //We've finished the winding down period and now turn off offline_for += 30 //Another minute before it can be turned back on again return @@ -266,23 +281,12 @@ upkeep_power_usage = round((field_segments.len - damaged_segments.len) * ENERGY_UPKEEP_PER_TILE * upkeep_multiplier * upkeep_star_multiplier) - if(powernet && !input_cut && (running == SHIELD_RUNNING || running == SHIELD_OFF)) + if(tendrils_deployed && !input_cut && (running == SHIELD_RUNNING || running == SHIELD_OFF)) var/energy_buffer = 0 - energy_buffer = draw_power(min(upkeep_power_usage, input_cap)) + for(var/obj/machinery/power/conduit/shield_conduit/SC in tendrils) + energy_buffer += SC.draw_power(input_cap / tendrils.len) power_usage += round(energy_buffer) - - if(energy_buffer < upkeep_power_usage) - current_energy -= round(upkeep_power_usage - energy_buffer) // If we don't have enough energy from the grid, take it from the internal battery instead. - - // Now try to recharge our internal energy. - var/energy_to_demand - if(input_cap) - energy_to_demand = between(0, max_energy - current_energy, input_cap - upkeep_power_usage) - else - energy_to_demand = max(0, max_energy - current_energy) - energy_buffer = draw_power(energy_to_demand) - power_usage += energy_buffer - current_energy += round(energy_buffer) + current_energy += energy_buffer - upkeep_power_usage //if grid energy is lower than upkeep - negative number will be added else current_energy -= round(upkeep_power_usage) // We are shutting down, or we lack external power connection. Use energy from internal source instead. @@ -299,32 +303,9 @@ regenerate_field() -/obj/machinery/power/shield_generator/attackby(obj/item/O as obj, mob/user as mob) - // Prevents dismantle-rebuild tactics to reset the emergency shutdown timer. - if(running) - to_chat(user, "Turn off \the [src] first!") - return - if(offline_for) - to_chat(user, "Wait until \the [src] cools down from emergency shutdown first!") - return - - if(default_deconstruction(O, user)) - return - if(default_part_replacement(O, user)) - return - - //TODO: Implement unwrenching in a proper centralised location. Having to copypaste this around sucks - if(QUALITY_BOLT_TURNING in O.tool_qualities) - wrench(user, O) - return - - if(istool(O)) - return src.attack_hand(user) - - -/obj/machinery/power/shield_generator/proc/energy_failure() +/obj/machinery/power/shipside/shield_generator/proc/energy_failure() if(running == SHIELD_DISCHARGING) - shutdown_field() + shutdown_machine() else if (current_energy < 0) current_energy = 0 @@ -333,7 +314,7 @@ S.fail(1) -/obj/machinery/power/shield_generator/nano_ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = NANOUI_FOCUS) +/obj/machinery/power/shipside/shield_generator/nano_ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = NANOUI_FOCUS) var/data[0] data["running"] = running @@ -366,7 +347,7 @@ //Sorts the mode list so that currently active ones are at the top -/obj/machinery/power/shield_generator/proc/sort_modes() +/obj/machinery/power/shipside/shield_generator/proc/sort_modes() var/list/temp = list() for (var/A in mode_list) var/datum/shield_mode/SM = A //This late casting is an optimisation trick @@ -385,18 +366,18 @@ mode_list.Add(temp) -/obj/machinery/power/shield_generator/attack_hand(var/mob/user) +/obj/machinery/power/shipside/shield_generator/attack_hand(var/mob/user) nano_ui_interact(user) if(panel_open) wires.Interact(user) -/obj/machinery/power/shield_generator/CanUseTopic(var/mob/user) +/obj/machinery/power/shipside/shield_generator/CanUseTopic(var/mob/user) if(issilicon(user) && !Adjacent(user) && ai_control_disabled) return STATUS_UPDATE return ..() -/obj/machinery/power/shield_generator/Topic(href, href_list) +/obj/machinery/power/shipside/shield_generator/Topic(href, href_list) if(..()) return 1 if(!anchored) @@ -414,6 +395,10 @@ log_event(EVENT_DISABLED, src) if(href_list["start_generator"]) + if(tendrils_deployed == FALSE) + visible_message(SPAN_DANGER("The [src] buzzes an insistent warning as it needs to have it's conduits deployed first to operate")) + playsound(src.loc, 'sound/machines/buzz-sigh.ogg', 100, 1, 5) + return running = SHIELD_RUNNING regenerate_field() log_event(EVENT_ENABLED, src) @@ -432,7 +417,7 @@ var/temp_integrity = field_integrity() offline_for += 300 //5 minutes, given that procs happen every 2 seconds - shutdown_field() + shutdown_machine() emergency_shutdown = TRUE log_event(EVENT_DISABLED, src) if(prob(temp_integrity - 50) * 1.75) @@ -453,11 +438,10 @@ . = 1 if(href_list["set_input_cap"]) - var/new_cap = round(input(usr, "Enter new input cap (in kW). Enter 0 or nothing to disable input cap.", "Generator Power Control", round(input_cap / 1000)) as num) + var/new_cap = round(input(usr, "Enter new input cap (in kW). Current maximal input cap is [input_maxcap / 1000] kW", "Generator Power Control", round(input_cap / 1000)) as num) if(!new_cap) - input_cap = 0 return - input_cap = max(0, new_cap) * 1000 + input_cap = between(1, new_cap, input_maxcap / 1000) * 1000 log_event(EVENT_RECONFIGURED, src) . = 1 @@ -469,14 +453,14 @@ nano_ui_interact(usr) -/obj/machinery/power/shield_generator/proc/field_integrity() +/obj/machinery/power/shipside/shield_generator/proc/field_integrity() if(max_energy) return (current_energy / max_energy) * 100 return 0 // Takes specific amount of damage -/obj/machinery/power/shield_generator/proc/take_shield_damage(var/damage, var/shield_damtype, var/atom/damager = null) +/obj/machinery/power/shipside/shield_generator/proc/take_shield_damage(damage, shield_damtype, atom/damager = null) var/energy_to_use = damage * ENERGY_PER_HP // Even if the shield isn't currently modulating, it can still use old modulation buildup to reduce damage @@ -536,11 +520,11 @@ // Checks whether specific flags are enabled -/obj/machinery/power/shield_generator/proc/check_flag(var/flag) +/obj/machinery/power/shipside/shield_generator/proc/check_flag(flag) return (shield_modes & flag) -/obj/machinery/power/shield_generator/proc/toggle_flag(var/flag) +/obj/machinery/power/shipside/shield_generator/proc/toggle_flag(flag) shield_modes ^= flag update_upkeep_multiplier() for(var/obj/effect/shield/S in field_segments) @@ -558,7 +542,7 @@ sort_modes() -/obj/machinery/power/shield_generator/proc/get_flag_descriptions() +/obj/machinery/power/shipside/shield_generator/proc/get_flag_descriptions() var/list/all_flags = list() for(var/datum/shield_mode/SM in mode_list) all_flags.Add(list(list( @@ -570,7 +554,7 @@ ))) return all_flags -/obj/machinery/power/shield_generator/proc/get_logs() +/obj/machinery/power/shipside/shield_generator/proc/get_logs() var/list/all_logs = list() for(var/i = event_log.len; i > 1; i--) all_logs.Add(list(list( @@ -578,7 +562,7 @@ ))) return all_logs -/obj/machinery/power/shield_generator/proc/fieldtype_square() +/obj/machinery/power/shipside/shield_generator/proc/fieldtype_square() var/list/out = list() var/list/base_turfs = get_base_turfs() @@ -603,7 +587,7 @@ CHECK_TICK return out -/obj/machinery/power/shield_generator/proc/fieldtype_hull() +/obj/machinery/power/shipside/shield_generator/proc/fieldtype_hull() var/list/turf/valid_turfs = list() var/list/base_turfs = get_base_turfs() @@ -621,7 +605,7 @@ return valid_turfs // Returns a list of turfs from which a field will propagate. If multi-Z mode is enabled, this will return a "column" of turfs above and below the generator. -/obj/machinery/power/shield_generator/proc/get_base_turfs() +/obj/machinery/power/shipside/shield_generator/proc/get_base_turfs() var/list/turfs = list() var/turf/T = get_turf(src) @@ -649,7 +633,7 @@ return turfs -/obj/machinery/power/shield_generator/proc/handle_reporting() +/obj/machinery/power/shipside/shield_generator/proc/handle_reporting() if (report_scheduled) return @@ -658,7 +642,7 @@ report_damage() //This proc sends reports for shield damage -/obj/machinery/power/shield_generator/proc/report_damage() +/obj/machinery/power/shipside/shield_generator/proc/report_damage() var/do_report = FALSE //We only report if this is true report_scheduled = FALSE //Reset this regardless of what we do here @@ -699,20 +683,9 @@ command_announcement.Announce(span(spanclass, "[prefix]Shield integrity at [round(field_integrity())]%"), "Shield Status Report", msg_sanitized = TRUE) -/obj/machinery/power/shield_generator/proc/wrench(var/user, var/obj/item/O) - if(O.use_tool(user, src, WORKTIME_FAST, QUALITY_BOLT_TURNING, FAILCHANCE_EASY, required_stat = STAT_MEC)) - playsound(src.loc, 'sound/items/Ratchet.ogg', 75, 1) - if(anchored) - to_chat(user, SPAN_NOTICE("You unsecure the [src] from the floor!")) - anchored = FALSE - else - if(istype(get_turf(src), /turf/space)) return //No wrenching these in space! - to_chat(user, SPAN_NOTICE("You secure the [src] to the floor!")) - anchored = TRUE - return //This proc keeps an internal log of shield impacts, activations, deactivations, and a vague log of config changes -/obj/machinery/power/shield_generator/proc/log_event(var/event_type, var/atom/origin_atom) +/obj/machinery/power/shipside/shield_generator/log_event(var/event_type, var/atom/origin_atom) var/logstring = "[stationtime2text()]: " switch (event_type) if(EVENT_DAMAGE_PHYSICAL to EVENT_DAMAGE_SPECIAL) @@ -771,125 +744,50 @@ if (event_log.len > max_log_entries) event_log.Cut(1,2) -/obj/machinery/shield_conduit +/obj/machinery/power/conduit/shield_conduit //Most of the stuff is moved to the shipside_machinery.dm name = "shield conduit" icon = 'icons/obj/machines/shielding.dmi' icon_state = "conduit_0" desc = "A combined conduit and capacitor that transfers and stores massive amounts of energy." density = TRUE anchored = FALSE //Will be set true just after deploying - var/obj/machinery/power/shield_generator/generator - -/obj/machinery/shield_conduit/proc/connect(gen) - generator = gen + circuit = /obj/item/electronics/circuitboard/shield_conduit + var/input_modifier = 0 //Modifier for the power use. Updated by RefreshParts() -/obj/machinery/shield_conduit/proc/no_light() +/obj/machinery/power/conduit/shield_conduit/no_light() set_light(0) -/obj/machinery/shield_conduit/proc/bright_light() +/obj/machinery/power/conduit/shield_conduit/bright_light() set_light(2, 2, "#8AD55D") -/obj/machinery/shield_conduit/Destroy() - if(generator) - generator.toggle_tendrils(FALSE) - if(generator.running != SHIELD_OFF && !generator.emergency_shutdown) - generator.offline_for += 300 - generator.shutdown_field() - generator.emergency_shutdown = TRUE - generator.log_event(EVENT_DISABLED, generator) +/obj/machinery/power/conduit/shield_conduit/RefreshParts() + input_modifier = 0 + for(var/obj/item/stock_parts/capacitor/C in component_parts) + input_modifier += C.rating / 4 . = ..() -/obj/machinery/power/shield_generator/wrench(user, obj/item/I) - if(running != SHIELD_OFF) - to_chat(usr, SPAN_NOTICE("Generator has to be toggled off first!")) - return - if(tendrils_deployed) - to_chat(usr, SPAN_NOTICE("Retract conduits first!")) - return - if(I.use_tool(user, src, WORKTIME_FAST, QUALITY_BOLT_TURNING, FAILCHANCE_EASY, required_stat = STAT_MEC)) - playsound(src.loc, 'sound/items/Ratchet.ogg', 75, 1) - if(anchored) - to_chat(user, SPAN_NOTICE("You unsecure the [src] from the floor!")) - toggle_tendrils(FALSE) - anchored = FALSE - else - if(istype(get_turf(src), /turf/space)) return //No wrenching these in space! - to_chat(user, SPAN_NOTICE("You secure the [src] to the floor!")) - anchored = TRUE - return - -/obj/machinery/power/shield_generator/verb/toggle_tendrils_verb() - set category = "Object" - set name = "Toggle conduits" - set src in view(1) - - if(running != SHIELD_OFF) - to_chat(usr, SPAN_NOTICE("Generator has to be toggled off first!")) - return - toggle_tendrils() - -/obj/machinery/power/shield_generator/proc/toggle_tendrils(on = null) - var/target_state - if (!isnull(on)) - target_state = on - else - target_state = tendrils_deployed ? FALSE : TRUE //Otherwise we're toggling - - if (target_state == tendrils_deployed) - return - //If we're extending them - if (target_state == TRUE) - for (var/D in tendril_dirs) - var/turf/T = get_step(src, D) - var/obj/machinery/shield_conduit/SC = locate(/obj/machinery/shield_conduit) in T - if(SC) - continue - if (!turf_clear(T)) - visible_message(SPAN_DANGER("The [src] buzzes an insistent warning as it lacks the space to deploy")) - playsound(src.loc, "/sound/machines/buzz-two", 100, 1, 5) - tendrils_deployed = FALSE - update_icon() - return FALSE - - //Now deploy - for (var/D in tendril_dirs) - var/turf/T = get_step(src, D) - var/obj/machinery/shield_conduit/SC = locate(/obj/machinery/shield_conduit) in T - if(!SC) SC = new(T) - SC.connect(src) - tendrils.Add(SC) - SC.face_atom(src) - SC.anchored = TRUE - tendrils_deployed = TRUE - update_icon() - - allowed_modes |= MODEFLAG_MULTIZ - allowed_modes |= MODEFLAG_HULL +/obj/machinery/power/conduit/shield_conduit/draw_power(amount) //manual fuckery with the powernet surely won't result in a disaster later on *clueless* + if(!powernet) + return 0 + var/draw = between(0, amount, surplus() * input_modifier) + powernet.load += draw / input_modifier + return draw - to_chat(usr, SPAN_NOTICE("You deployed [src] conduits.")) - return TRUE - - else if (target_state == FALSE) - for (var/obj/machinery/shield_conduit/SC in tendrils) - tendrils.Remove(SC) - qdel(SC) - tendrils_deployed = FALSE - update_icon() - - allowed_modes.Remove(MODEFLAG_MULTIZ) - allowed_modes.Remove(MODEFLAG_HULL) - to_chat(usr, SPAN_NOTICE("You retracted [src] conduits.")) +/obj/machinery/power/conduit/disconnect() + if(!base) return FALSE - - mode_list = list() - for(var/st in subtypesof(/datum/shield_mode/)) - var/datum/shield_mode/SM = new st() - if (locate(SM.mode_flag) in allowed_modes) - mode_list.Add(SM) - - //Enable all modes in the default modes list - for (var/DM in default_modes) - toggle_flag(DM) + if(base.running != 0 && !base.emergency_shutdown) + base.offline_for += 300 + base.shutdown_machine() + base.emergency_shutdown = TRUE + base.log_event(EVENT_DISABLED, base) + base.tendrils.Remove(src) + base.build_tendril_dirs() + base.RefreshParts() + base.update_icon() + base = null + no_light() + disconnect_from_network() #undef EVENT_DAMAGE_PHYSICAL #undef EVENT_DAMAGE_EM diff --git a/maps/CEVEris/_CEV_Eris.dmm b/maps/CEVEris/_CEV_Eris.dmm index 51ed06b2e9c..2680ffb8233 100644 --- a/maps/CEVEris/_CEV_Eris.dmm +++ b/maps/CEVEris/_CEV_Eris.dmm @@ -47729,10 +47729,16 @@ /area/eris/command/mbo) "cmk" = ( /obj/structure/table/rack, -/obj/item/electronics/circuitboard/communications, /obj/machinery/atmospherics/pipe/simple/hidden/scrubbers{ dir = 10 }, +/obj/item/electronics/circuitboard/shield_conduit{ + pixel_x = -2; + pixel_y = 2 + }, +/obj/item/electronics/circuitboard/communications{ + pixel_y = -2 + }, /obj/structure/cable/green{ d1 = 1; d2 = 2; @@ -79651,6 +79657,10 @@ /turf/wall/low/with_glass/smart, /area/eris/engineering/gravity_generator) "dPl" = ( +/obj/structure/cable/green{ + d2 = 8; + icon_state = "0-8" + }, /turf/floor/tiled/steel/gray_platform, /area/eris/engineering/shield_generator) "dPm" = ( @@ -79728,11 +79738,22 @@ /turf/floor/tiled/steel/gray_perforated, /area/eris/engineering/shield_generator) "dPx" = ( +/obj/machinery/power/shipside/shield_generator/hull/installed, +/obj/structure/cable/green{ + d1 = 2; + d2 = 8; + icon_state = "2-8" + }, +/obj/structure/cable/green{ + d1 = 2; + d2 = 4; + icon_state = "2-4" + }, /obj/structure/cable/green{ + d1 = 1; d2 = 2; - icon_state = "0-2" + icon_state = "1-2" }, -/obj/machinery/power/shield_generator/hull/installed, /turf/floor/tiled/steel/gray_platform, /area/eris/engineering/shield_generator) "dPy" = ( @@ -99727,11 +99748,22 @@ /turf/floor/reinforced/almost_airless, /area/eris/engineering/propulsion/left) "kaS" = ( +/obj/machinery/power/shipside/long_range_scanner/hull/installed, /obj/structure/cable/green{ + d1 = 2; + d2 = 8; + icon_state = "2-8" + }, +/obj/structure/cable/green{ + d1 = 2; + d2 = 4; + icon_state = "2-4" + }, +/obj/structure/cable/green{ + d1 = 1; d2 = 2; - icon_state = "0-2" + icon_state = "1-2" }, -/obj/machinery/power/long_range_scanner/hull/installed, /turf/floor/tiled/steel/gray_platform, /area/eris/engineering/long_range_scanner) "kaZ" = ( @@ -100029,6 +100061,13 @@ /obj/structure/kitchenspike, /turf/floor/tiled/white/brown_perforated, /area/eris/crew_quarters/kitchen_freezer) +"kFz" = ( +/obj/structure/cable/green{ + d2 = 8; + icon_state = "0-8" + }, +/turf/floor/tiled/steel/gray_platform, +/area/eris/engineering/long_range_scanner) "kFA" = ( /obj/machinery/door/firedoor, /turf/wall/low/with_glass/smart, @@ -101791,6 +101830,13 @@ /obj/machinery/atmospherics/pipe/simple/visible/yellow, /turf/floor/plating/under, /area/eris/maintenance/section4deck5port) +"orh" = ( +/obj/structure/cable/green{ + d2 = 2; + icon_state = "0-2" + }, +/turf/floor/tiled/steel/gray_platform, +/area/eris/engineering/shield_generator) "orM" = ( /obj/machinery/atmospherics/pipe/simple/hidden/scrubbers, /obj/structure/cable/green{ @@ -104704,6 +104750,10 @@ /area/eris/crew_quarters/kitchen_storage) "tCG" = ( /obj/machinery/camera/network/engineering, +/obj/structure/cable/green{ + d2 = 4; + icon_state = "0-4" + }, /turf/floor/tiled/steel/gray_platform, /area/eris/engineering/long_range_scanner) "tEu" = ( @@ -105426,6 +105476,13 @@ }, /turf/floor/tiled/steel/gray_perforated, /area/eris/engineering/long_range_scanner) +"uQK" = ( +/obj/structure/cable/green{ + d2 = 4; + icon_state = "0-4" + }, +/turf/floor/tiled/steel/gray_platform, +/area/eris/engineering/shield_generator) "uUD" = ( /obj/machinery/atmospherics/valve/open{ dir = 4; @@ -106853,6 +106910,13 @@ /obj/structure/disposalpipe/up, /turf/floor/plating/under, /area/eris/maintenance/section3deck4port) +"xDD" = ( +/obj/structure/cable/green{ + d2 = 2; + icon_state = "0-2" + }, +/turf/floor/tiled/steel/gray_platform, +/area/eris/engineering/long_range_scanner) "xDO" = ( /obj/item/device/radio/intercom{ dir = 4; @@ -292259,7 +292323,7 @@ dXi abF dKs dKs -dPl +uQK ezX dOT eQb @@ -292460,7 +292524,7 @@ dXi dXi abF dKs -dPl +orh dPx dPA dPG @@ -293677,7 +293741,7 @@ abF abF abF peB -xoq +xDD kaS sbX oAL @@ -293880,7 +293944,7 @@ abF abF peB peB -xoq +kFz uPp sBN oUD