diff --git a/code/ZAS/Atom.dm b/code/ZAS/Atom.dm index d1138035768..c6eff62e0a3 100644 --- a/code/ZAS/Atom.dm +++ b/code/ZAS/Atom.dm @@ -1,3 +1,4 @@ +/// Pre-check proc for passing things over the turf. Passes more advanced checks for AMs to turf/enter(...), otherwise handles ZAS. /turf/CanPass(atom/movable/mover, turf/target, height=1.5,air_group=0) if(!target) return FALSE @@ -10,31 +11,34 @@ else // Now, doing more detailed checks for air movement and air group formation if(target.blocks_air||blocks_air) - return 0 + return FALSE for(var/obj/obstacle in src) if(!obstacle.CanPass(mover, target, height, air_group)) - return 0 + return FALSE if(target != src) for(var/obj/obstacle in target) if(!obstacle.CanPass(mover, src, height, air_group)) - return 0 + return FALSE - return 1 + return TRUE -//Convenience function for atoms to update turfs they occupy +/// Convenience function for atoms to update turfs they occupy /atom/movable/proc/update_nearby_tiles(need_rebuild) for(var/turf/simulated/turf in locs) SSair.mark_for_update(turf) return 1 -//Basically another way of calling CanPass(null, other, 0, 0) and CanPass(null, other, 1.5, 1). -//Returns: -// 0 - Not blocked -// AIR_BLOCKED - Blocked -// ZONE_BLOCKED - Not blocked, but zone boundaries will not cross. -// BLOCKED - Blocked, zone boundaries will not cross even if opened. +/** + * Basically another way of calling CanPass(null, other, 0, 0) and CanPass(null, other, 1.5, 1). + * + * Returns: + * - 0 - Not blocked + * - AIR_BLOCKED - Blocked + * - ZONE_BLOCKED - Not blocked, but zone boundaries will not cross. + * - BLOCKED - Blocked, zone boundaries will not cross even if opened. + */ /atom/proc/c_airblock(turf/other) #ifdef ZASDBG ASSERT(isturf(other)) diff --git a/code/controllers/subsystems/falling.dm b/code/controllers/subsystems/falling.dm index 36a11201a9e..f82430d693f 100644 --- a/code/controllers/subsystems/falling.dm +++ b/code/controllers/subsystems/falling.dm @@ -4,6 +4,19 @@ if (MC_TICK_CHECK) return; \ continue; +/** + * Notes for potential future development. + * + * Falling subsystem currently treats 'falling' as a event that happens instantly in the presence of gravity, which (presently) is a binary true/false condition. + * To handle more strengths of gravity beyond 0g and 1g, falling logic will need to be able to handle things falling 'slowly'. The easiest way to implement this + * will probably be to provide handling for an component/element (if pending fall in low-g, give an AM an additional highlight or examine-able info), and also + * provide in-game feedback in some way to the player- ideally through a UI grav condition button like /tg/'s, that indicates how long it'll take before you drift + * down a Z-level. + * + * This would also give us more granular control over levels of sub-1 gravity. Instead of 'no grav, low grav, standard grav', we could have 0.0 -> 1.0 grav just be + * the the delay factor on the falling subsystem's fire() logic, and the thresholds over which that a z-level fall happens gently (or not gently). + */ + SUBSYSTEM_DEF(falling) name = "Falling" flags = SS_NO_INIT diff --git a/code/game/machinery/spaceheater.dm b/code/game/machinery/spaceheater.dm index 41985bec25e..6b533791857 100644 --- a/code/game/machinery/spaceheater.dm +++ b/code/game/machinery/spaceheater.dm @@ -8,16 +8,22 @@ use_power = POWER_USE_OFF clicksound = SFX_SWITCH var/on = FALSE - /// Currently heating or cooling the environment, if on. + /// Currently heating or cooling the environment, if on, and by how much (in terms of heat transfer). var/active = 0 - /// Force it to at least somewhat obey thermodynamics. + /// This value gets overwritten on activation. heating_power scales with cell maxcharge (to a point). var/heating_power = 40 KILO WATTS var/current_temperature + /// Current target temperature for the unit. var/set_temperature = T0C + 20 + /// Maximum allowed target temperature. var/set_temperature_max = T0C + 40 + /// Minimum allowed target temperature. var/set_temperature_min = T0C var/datum/gas_mixture/env + /// The cell we spawn with. var/obj/item/cell/apc/cell + /// Is our cell high-powered? (>= 50 kW, so 'super' or better). + var/high_power_cell = FALSE /obj/machinery/space_heater/feedback_hints(mob/user, distance, is_adjacent) . += ..() @@ -41,20 +47,25 @@ /obj/machinery/space_heater/update_icon() ClearOverlays() - if(!on) - icon_state = "sheater-off" - set_light(0) - else if(active > 0) - icon_state = "sheater-heat" - set_light(0.7, 1, COLOR_SEDONA) - else if(active < 0) - icon_state = "sheater-cool" - set_light(0.7, 1, COLOR_DEEP_SKY_BLUE) - else - icon_state = "sheater-standby" - set_light(0) if(panel_open) AddOverlays("sheater-open") + if(!on) + icon_state = "sheater-off" + set_light_on(FALSE) + else if(active > 0) + icon_state = "sheater-heat" + AddOverlays(emissive_appearance(icon, "sheater-heat-emissive", src, alpha = src.alpha)) + set_light_range_power_color(0.7, 1, COLOR_SEDONA) + set_light_on(TRUE) + else if(active < 0) + icon_state = "sheater-cool" + AddOverlays(emissive_appearance(icon, "sheater-cool-emissive", src, alpha = src.alpha)) + set_light_range_power_color(0.7, 1, COLOR_DEEP_SKY_BLUE) + set_light_on(TRUE) + else + icon_state = "sheater-standby" + AddOverlays(emissive_appearance(icon, "sheater-standby-emissive", src, alpha = src.alpha)) + set_light_on(FALSE) /obj/machinery/space_heater/powered() if(cell && cell.charge) @@ -74,23 +85,22 @@ if(istype(attacking_item, /obj/item/cell)) if(panel_open) if(cell) - to_chat(user, "There is already a power cell inside.") + to_chat(user, "There is already \a [cell] inside.") else // insert cell user.drop_from_inventory(attacking_item,src) cell = attacking_item attacking_item.add_fingerprint(user) - visible_message(SPAN_NOTICE("[user] inserts a power cell into [src]."), - SPAN_NOTICE("You insert the power cell into [src].")) + SPAN_NOTICE("You insert \the [cell] into [src].")) power_change() else - to_chat(user, SPAN_NOTICE("The hatch must be open to insert a power cell.")) + balloon_alert("hatch still closed!") return TRUE else if(attacking_item.tool_behaviour == TOOL_SCREWDRIVER) panel_open = !panel_open - user.visible_message(SPAN_NOTICE("[user] [panel_open ? "opens" : "closes"] the hatch on the [src]."), - SPAN_NOTICE("You [panel_open ? "open" : "close"] the hatch on the [src].")) + attacking_item.play_tool_sound(get_turf(src), 50) + balloon_alert_to_viewers("[panel_open ? "opened" : "closed"]") update_icon() return TRUE return ..() @@ -99,15 +109,20 @@ src.add_fingerprint(user) if(panel_open) if(cell) - user.visible_message(SPAN_NOTICE("\The [user] removes \the [cell] from \the [src]."), + user.visible_message(SPAN_NOTICE("\The [user] removes a power cell from \the [src]."), SPAN_NOTICE("You remove \the [cell] from \the [src].")) cell.update_icon() user.put_in_hands(cell) cell.add_fingerprint(user) cell = null power_change() + /// If a cell's power rating is above a certain threshold (>= super), expand temperature minmax range by 10 in both directions. + if(cell.maxcharge >= 50000) + high_power_cell = TRUE + else + high_power_cell = FALSE else - to_chat(user,"There's no cell to remove!") + to_chat(user, SPAN_WARNING("There's no cell to remove!")) else ui_interact(user) @@ -115,7 +130,7 @@ /obj/machinery/space_heater/ui_interact(mob/user, datum/tgui/ui) ui = SStgui.try_update_ui(user, src, ui) if(!ui) - ui = new(user, src, "SpaceHeater", src.name, 700, 300) + ui = new(user, src, "SpaceHeater", src.name, 415, 280) ui.open() /obj/machinery/space_heater/ui_data(mob/user) @@ -123,16 +138,19 @@ current_temperature = round(env.temperature - T0C, 0.1) - data["power_cell_inserted"] = cell + var/bonus_temp_range = 0 + if(high_power_cell) + bonus_temp_range = 10 + + data["power_cell_inserted"] = cell != null data["power_cell_charge"] = cell?.percent() data["is_on"] = on data["is_active"] = active data["panel_open"] = panel_open - data["heating_power"] = heating_power data["current_temperature"] = current_temperature data["set_temperature"] = set_temperature - T0C - data["set_temperature_max"] = set_temperature_max - T0C - data["set_temperature_min"] = set_temperature_min - T0C + data["set_temperature_max"] = set_temperature_max - T0C + bonus_temp_range + data["set_temperature_min"] = set_temperature_min - T0C - bonus_temp_range return data @@ -140,18 +158,22 @@ . = ..() if (.) return - switch(action) if("powerToggle") + balloon_alert_to_viewers("turned [on ? "on" : "off"]") on = !on - active = FALSE + active = 0 power_change() - usr.visible_message(SPAN_NOTICE("[usr] toggles the power on \the [src]."), - SPAN_NOTICE("You toggle the power on \the [src].")) update_icon() + heating_power = clamp(0 WATTS, (cell?.maxcharge), 500 KILO WATTS) + playsound(src, clicksound, clickvol) . = TRUE if ("tempSet") - set_temperature = between(set_temperature_min, text2num(params["set_temperature"]) + T0C, set_temperature_max) + var/bonus_temp_range = 0 + if(high_power_cell) + bonus_temp_range = 10 + set_temperature = clamp(set_temperature_min - bonus_temp_range, text2num(params["set_temperature"]) + T0C, set_temperature_max + bonus_temp_range) + playsound(src, 'sound/machines/terminal/terminal_select.ogg', 10, TRUE) . = TRUE // TGUI functions end @@ -160,7 +182,7 @@ if(cell && cell.charge) env = loc.return_air() if(env && abs(env.temperature - set_temperature) <= 0.1) - active = FALSE + active = 0 else var/transfer_moles = 0.25 * env.total_moles var/datum/gas_mixture/removed = env.remove(transfer_moles) @@ -168,27 +190,29 @@ var/heat_transfer = removed.get_thermal_energy_change(set_temperature) var/power_draw if(heat_transfer > 0) // Heating. - heat_transfer = min(heat_transfer , heating_power) // Limit by the power rating of the heater. + // Limit by the power rating of the cell (messy but workable, while we still don't have joules) + heat_transfer = min(heat_transfer, heating_power) removed.add_thermal_energy(heat_transfer) - power_draw = heat_transfer + power_draw = heat_transfer * 1.2 // Lets at least pretend we respect entropy. else // Cooling. heat_transfer = abs(heat_transfer) // Assume the heat is being pumped into the hull which is fixed at 20 C. var/cop = removed.temperature/T20C // Co-efficient of performance from thermodynamics -> power used = heat_transfer/cop. - heat_transfer = min(heat_transfer, cop * heating_power) // Limit heat transfer by available power. + // Limit by the power rating of the cell (messy but workable, while we still don't have joules) + heat_transfer = min(heat_transfer, cop * heating_power) heat_transfer = removed.add_thermal_energy(-heat_transfer) // Get the actual heat transfer. - power_draw = abs(heat_transfer)/cop + power_draw = (abs(heat_transfer)/cop) * 1.2 // Lets at least pretend we respect entropy. cell.use(power_draw * CELLRATE) active = heat_transfer env.merge(removed) else on = FALSE - active = FALSE + active = 0 power_change() update_icon() diff --git a/code/game/objects/auras/personal_shield.dm b/code/game/objects/auras/personal_shield.dm index e2de1d277a2..01f03e06763 100644 --- a/code/game/objects/auras/personal_shield.dm +++ b/code/game/objects/auras/personal_shield.dm @@ -1,7 +1,7 @@ /obj/aura/personal_shield name = "personal shield" icon = 'icons/effects/effects.dmi' - icon_state = "shield" + icon_state = "personal_shield" /obj/aura/personal_shield/handle_bullet_act(datum/source, obj/projectile/projectile) user.visible_message(SPAN_WARNING("\The [user]'s [src.name] flashes before \the [projectile] can hit them!")) diff --git a/code/game/objects/items/weapons/policetape.dm b/code/game/objects/items/weapons/policetape.dm index a05ce566de1..fa9206beb81 100644 --- a/code/game/objects/items/weapons/policetape.dm +++ b/code/game/objects/items/weapons/policetape.dm @@ -98,12 +98,12 @@ GLOBAL_LIST_INIT(tape_roll_applications, list()) /obj/item/tape/engineering/mechanics_hints(mob/user, distance, is_adjacent) . += ..() - . += "You can use a multitool on this tape to allow emergency shield generators to deploy shields on this tile." + . += "You can use a multitool on this tape to allow emergency shield projectors to deploy shields on this tile." /obj/item/tape/engineering/feedback_hints(mob/user, distance, is_adjacent) . += ..() if(shield_marker) - . += "This strip of tape has been modified to serve as a marker for emergency shield generators to lock onto." + . += "This strip of tape has been modified to serve as a marker for emergency shield projectors to lock onto." /obj/item/tape/engineering/attackby(obj/item/attacking_item, mob/user) if(attacking_item.tool_behaviour == TOOL_MULTITOOL) diff --git a/code/game/objects/items/weapons/power_cells.dm b/code/game/objects/items/weapons/power_cells.dm index 05edb3623c8..82f99bd51c5 100644 --- a/code/game/objects/items/weapons/power_cells.dm +++ b/code/game/objects/items/weapons/power_cells.dm @@ -52,10 +52,17 @@ /obj/item/cell/crap name = "old power cell" desc = "A cheap, old power cell. It's probably been in use for quite some time now." + icon_state = "ocell" origin_tech = list(TECH_POWER = 0) - maxcharge = 1500 + maxcharge = 900 matter = list(DEFAULT_WALL_MATERIAL = 700, MATERIAL_GLASS = 40) +/obj/item/cell/crap/Initialize() + . = ..() + // 5% chance to make the cell rigged. + if(prob(5)) + rigged = TRUE + /obj/item/cell/crap/empty/Initialize() . = ..() charge = 0 @@ -79,14 +86,16 @@ /obj/item/cell/apc name = "heavy-duty power cell" + desc = "A rechargeable electrochemical power cell. This variant is rated for use in APCs and other high-draw electronics in industrial environments. Environments like, say, a space ship." origin_tech = list(TECH_POWER = 1) + icon_state = "hcell" maxcharge = 15000 matter = list(DEFAULT_WALL_MATERIAL = 700, MATERIAL_GLASS = 50) /obj/item/cell/high name = "high-capacity power cell" origin_tech = list(TECH_POWER = 2) - icon_state = "hcell" + icon_state = "h+cell" maxcharge = 30000 matter = list(DEFAULT_WALL_MATERIAL = 700, MATERIAL_GLASS = 60) diff --git a/code/modules/cargo/items/security.dm b/code/modules/cargo/items/security.dm index c90b6c1fc6d..a44c04195e4 100644 --- a/code/modules/cargo/items/security.dm +++ b/code/modules/cargo/items/security.dm @@ -114,9 +114,9 @@ /singleton/cargo_item/shieldgenerator category = "security" - name = "Shield Generator" + name = "Shield Wall Generator" supplier = "nanotrasen" - description = "A shield generator." + description = "A shield wall generator." price = 550 items = list( /obj/machinery/shieldwallgen diff --git a/code/modules/modular_computers/file_system/programs/engineering/powermonitor.dm b/code/modules/modular_computers/file_system/programs/engineering/powermonitor.dm index d3d29be9326..c4b6e60bc4a 100644 --- a/code/modules/modular_computers/file_system/programs/engineering/powermonitor.dm +++ b/code/modules/modular_computers/file_system/programs/engineering/powermonitor.dm @@ -60,7 +60,7 @@ if(!T) // Safety check return for(var/obj/machinery/power/sensor/S in SSmachinery.all_sensors) - if(AreConnectedZLevels(S.z, computer.z) || (S.long_range)) + if(AreConnectedZLevels(S.z, T.z) || (S.long_range)) if(S.name_tag == "#UNKN#") // Default name. Shouldn't happen! warning("Powernet sensor with unset ID Tag! [S.x]X [S.y]Y [S.z]Z") else diff --git a/code/modules/multiz/turfs/open_space.dm b/code/modules/multiz/turfs/open_space.dm index 77e75242fd2..ce890b38270 100644 --- a/code/modules/multiz/turfs/open_space.dm +++ b/code/modules/multiz/turfs/open_space.dm @@ -22,8 +22,10 @@ var/tmp/list/climbers -// An override of turf/Enter() to make it so that magboots allow you to stop -// falling off the damned rock. +/** + * An override of turf/Enter() to make it so that magboots allow you to stop + * falling off the damned rock. + */ /turf/simulated/open/Enter(mob/living/carbon/human/mover, atom/oldloc) if (istype(mover) && isturf(oldloc)) if (mover.Check_Shoegrip(FALSE) && mover.can_fall(below, src)) @@ -74,10 +76,11 @@ return catwalk return src - -// Add a falling atom by default. Even if it's not an atom that can actually fall. -// SSfalling will check this on its own and remove if necessary. This is saner, as it -// centralizes control to SSfalling. +/** + * Add a falling atom by default. Even if it's not an atom that can actually fall. + * SSfalling will check this on its own and remove if necessary. This is saner, as it + * centralizes control to SSfalling. + */ /turf/simulated/open/Entered(atom/movable/mover) ..() if (is_hole) diff --git a/code/modules/power/apc.dm b/code/modules/power/apc.dm index 5452f01f999..3d1ad99d42a 100644 --- a/code/modules/power/apc.dm +++ b/code/modules/power/apc.dm @@ -763,20 +763,21 @@ ABSTRACT_TYPE(/obj/machinery/power/apc) else if (istype(attacking_item, /obj/item/debugger)) if(emagged || hacker || infected) to_chat(user, SPAN_WARNING("There is a software error with the device. Attempting to fix...")) - if(attacking_item.use_tool(src, user, 50, volume = 50)) + if(attacking_item.use_tool(src, user, 1 SECONDS, volume = 50)) to_chat(user, SPAN_NOTICE("Problem diagnosed, searching for solution...")) - if(attacking_item.use_tool(src, user, 150, volume = 50)) + if(attacking_item.use_tool(src, user, 3 SECONDS, volume = 50)) to_chat(user, SPAN_NOTICE("Solution found. Applying fixes...")) - if(attacking_item.use_tool(src, user, 300, volume = 50)) + if(attacking_item.use_tool(src, user, 8 SECONDS, volume = 50)) if(prob(15)) to_chat(user, SPAN_WARNING("Error while applying fixes. Please try again.")) return to_chat(user, SPAN_NOTICE("Applied default software. Restarting APC...")) - if(attacking_item.use_tool(src, user, 50, volume = 50)) + if(attacking_item.use_tool(src, user, 3 SECONDS, volume = 50)) to_chat(user, SPAN_NOTICE("APC Reset. Fixes applied.")) if(hacker) hacker.hacked_apcs -= src hacker = null + ClearOverlays() // Manually clear overlays first. update_icon() if(emagged) emagged = FALSE diff --git a/code/modules/power/fusion/core/core_field.dm b/code/modules/power/fusion/core/core_field.dm index af6e65c8672..af0917f2421 100644 --- a/code/modules/power/fusion/core/core_field.dm +++ b/code/modules/power/fusion/core/core_field.dm @@ -3,7 +3,7 @@ #define FUSION_REACTANT_CAP 10000 #define FUSION_WARNING_DELAY 20 #define FUSION_BLACKBODY_MULTIPLIER 350 -#define FUSION_INTEGRITY_RATE_LIMIT 0.11 +#define FUSION_INTEGRITY_RATE_LIMIT 0.07 #define FUSION_TICK_MAX_TEMP_CHANGE 0.3 /obj/effect/fusion_em_field @@ -63,7 +63,9 @@ /obj/structure/cable, /obj/machinery/atmospherics, /obj/machinery/air_sensor, - /obj/machinery/camera + /obj/machinery/camera, + /obj/item/tape, + /obj/machinery/shield ) var/light_min_range = 2 @@ -104,8 +106,8 @@ var/pause_rupture = FALSE var/power_log_base = 1.35 - var/power_multiplier = 3.5 - var/power_power = 2.9 + var/power_multiplier = 3.7 + var/power_power = 3.05 /obj/effect/fusion_em_field/proc/UpdateVisuals() //Take the particle system and edit it @@ -214,7 +216,10 @@ field_strength_power_multiplier = max((owned_core.field_strength ** 1.2) / 100, 1) // Dump power to our powernet. - power_output = ((log(power_log_base, plasma_temperature) * power_multiplier) ** power_power) * field_strength_power_multiplier + if(plasma_temperature > 0) + power_output = ((log(power_log_base, plasma_temperature) * power_multiplier) ** power_power) * field_strength_power_multiplier + else + power_output = 0 output_archive_5 = output_archive_4 output_archive_4 = output_archive_3 output_archive_3 = output_archive_2 @@ -436,6 +441,10 @@ change_size(calc_size) /obj/effect/fusion_em_field/proc/AddEnergy(a_energy, a_plasma_temperature) + // If there are no reactants, there's nothing to heat. Ignore. + if(!length(reactants)) + return + // Boost gyro effects at low temperatures for faster startup if(plasma_temperature <= 5000) a_energy = a_energy * 32 diff --git a/code/modules/power/singularity/containment_field.dm b/code/modules/power/singularity/containment_field.dm index 6de56a0a3a2..fe3ec6e10f2 100644 --- a/code/modules/power/singularity/containment_field.dm +++ b/code/modules/power/singularity/containment_field.dm @@ -1,7 +1,7 @@ /obj/machinery/containment_field name = "containment field" desc = "An energy field." - icon = 'icons/obj/machinery/field_generator.dmi' + icon = 'icons/effects/effects.dmi' icon_state = "contain_f" anchored = 1 density = 0 diff --git a/code/modules/power/singularity/emitter.dm b/code/modules/power/singularity/emitter.dm index 43b1fe679ba..1c869ff8e54 100644 --- a/code/modules/power/singularity/emitter.dm +++ b/code/modules/power/singularity/emitter.dm @@ -95,6 +95,13 @@ if(active && powernet && POWER_AVAIL(src)) AddOverlays(emissive_appearance(icon, "[icon_state]_lights")) AddOverlays("[icon_state]_lights") + if(anchored) + AddOverlays("+bolts") + if(state == 2) + AddOverlays("+welding") + var/image/lights_image = image(icon, null, "+lights") + lights_image.plane = ABOVE_LIGHTING_PLANE + AddOverlays(lights_image) /obj/machinery/power/emitter/attack_hand(mob/user) add_fingerprint(user) diff --git a/code/modules/power/singularity/field_generator.dm b/code/modules/power/singularity/field_generator.dm index 889faf7a666..82053f69c5d 100644 --- a/code/modules/power/singularity/field_generator.dm +++ b/code/modules/power/singularity/field_generator.dm @@ -13,7 +13,7 @@ field_generator power level display /obj/machinery/field_generator name = "field generator" desc = "A large thermal battery that projects a high amount of energy when powered." - icon = 'icons/obj/machinery/field_generator.dmi' + icon = 'icons/obj/machinery/shielding.dmi' icon_state = "field_gen" anchored = 0 density = 1 diff --git a/code/modules/shieldgen/emergency_shield.dm b/code/modules/shieldgen/emergency_shield.dm index 9c2aa63c376..a14100842c8 100644 --- a/code/modules/shieldgen/emergency_shield.dm +++ b/code/modules/shieldgen/emergency_shield.dm @@ -1,3 +1,255 @@ +/obj/machinery/shieldgen + name = "emergency shield projector" + desc = "Used to seal minor hull breaches." + icon = 'icons/obj/machinery/shielding.dmi' + icon_state = "shieldoff" + density = TRUE + opacity = TRUE + anchored = FALSE + req_access = list(ACCESS_ENGINE) + var/health = 100 + var/active = FALSE + /// Malfunction causes parts of the shield to slowly dissipate + var/malfunction = FALSE + var/list/deployed_shields = list() + var/list/regenerating = list() + /// Range at which it can project shields. + var/range = 4 + panel_open = FALSE + var/locked = FALSE + /// Periodically recheck if we need to rebuild a shield. + var/check_delay = 60 + use_power = POWER_USE_OFF + idle_power_usage = 250 + +/obj/machinery/shieldgen/mechanics_hints(mob/user, distance, is_adjacent) + . += ..() + . += "This machine's primary function is to project energy shields calibrated for atmospheric containment; these shields keep the air in and the vacuum out." + . += "If activated while within [range] tiles of a 'space' turf, an 'open space' turf, or an otherwise 'airless' turf, it will automatically project shields there, making it extremely useful for containing hull breaches." + . += "It will also project energy shields onto any engineering tape within range that has been toggled as a 'shield marker' using a multitool." + . += "ALT-click the [src] to lock or unlock it (if you have the appropriate ID access)." + +/obj/machinery/shieldgen/Destroy() + collapse_shields() + return ..() + +/obj/machinery/shieldgen/proc/shields_up() + if(active) return FALSE //If it's already turned on, how did this get called? + + src.active = TRUE + update_icon() + + create_shields() + + var/shield_power_usage + for(var/obj/machinery/shield/shield_tile in deployed_shields) + shield_power_usage += shield_tile.shield_idle_power + + change_power_consumption(shield_power_usage, POWER_USE_IDLE) + update_use_power(POWER_USE_IDLE) + +/obj/machinery/shieldgen/proc/shields_down() + if(!active) return FALSE //If it's already off, how did this get called? + + src.active = FALSE + update_icon() + + collapse_shields() + + update_use_power(POWER_USE_OFF) + +/obj/machinery/shieldgen/proc/create_shields() + for(var/T in RANGE_TURFS(range, src)) + var/turf/target_tile = T + if(locate(/obj/machinery/shield) in target_tile) + continue + var/obj/item/tape/engineering/E = locate() in target_tile + if(E?.shield_marker) + deploy_shield(target_tile) + else if(istype(target_tile,/turf/space) || istype(target_tile,/turf/simulated/open) || istype(target_tile,/turf/simulated/floor/exoplanet/asteroid/ash) || istype(target_tile,/turf/simulated/floor/airless)) + if(malfunction && prob(33) || !malfunction) + deploy_shield(target_tile) + +/obj/machinery/shieldgen/proc/deploy_shield(var/turf/T) + var/obj/machinery/shield/shield_tile = new /obj/machinery/shield(T) + deployed_shields += shield_tile + use_power_oneoff(shield_tile.shield_generate_power) + +/obj/machinery/shieldgen/proc/collapse_shields() + for(var/obj/machinery/shield/shield_tile in deployed_shields) + deployed_shields -= shield_tile + if(!QDELETED(shield_tile)) + qdel(shield_tile) + change_power_consumption(250, POWER_USE_IDLE) + update_use_power(POWER_USE_IDLE) + +/obj/machinery/shieldgen/power_change() + ..() + if(!active) return + if(stat & NOPOWER) + collapse_shields() + else + create_shields() + update_icon() + +/obj/machinery/shieldgen/process() + if(stat & NOPOWER) + if(active) + visible_message(SPAN_WARNING("\The [src] shuts down due to a lack of power."), SPAN_NOTICE("You hear a heavy droning fade out.")) + active = FALSE + collapse_shields() + return + + if(malfunction) + if(deployed_shields.len && prob(5)) + qdel(pick(deployed_shields)) + else + if (check_delay <= 0) + create_shields() + + var/new_power_usage = 0 + for(var/obj/machinery/shield/shield_tile in deployed_shields) + new_power_usage += shield_tile.shield_idle_power + + if (new_power_usage != idle_power_usage) + change_power_consumption(new_power_usage, POWER_USE_IDLE) + use_power_oneoff(0) + + check_delay = 30 + else + check_delay-- + +/obj/machinery/shieldgen/proc/checkhp() + if(health <= 30) + src.malfunction = TRUE + if(health <= 0) + spawn(0) + explosion(get_turf(src.loc), 0, 0, 1, 0, 0, 0) + qdel(src) + update_icon() + return + +/obj/machinery/shieldgen/ex_act(severity) + switch(severity) + if(1.0) + src.health -= 75 + src.checkhp() + if(2.0) + src.health -= 30 + if (prob(15)) + src.malfunction = 1 + src.checkhp() + if(3.0) + src.health -= 10 + src.checkhp() + return + +/obj/machinery/shieldgen/emp_act(severity) + . = ..() + + switch(severity) + if(EMP_HEAVY) + src.health /= 2 //cut health in half + malfunction = TRUE + locked = pick(0,1) + if(EMP_LIGHT) + if(prob(50)) + src.health *= 0.3 //chop off a third of the health + malfunction = TRUE + checkhp() + +/obj/machinery/shieldgen/attack_hand(mob/user) + if(locked) + to_chat(user, SPAN_WARNING("The machine is locked!")) + return + if(panel_open) + to_chat(user, SPAN_WARNING("The panel must be closed before operating this machine.")) + return + + if (src.active) + user.visible_message(SPAN_NOTICE("[icon2html(src, viewers(get_turf(src)))] [user] deactivates the shield generator."), \ + SPAN_NOTICE("[icon2html(src, viewers(get_turf(src)))] You deactivate the shield generator."), \ + "You hear heavy droning fade out.") + src.shields_down() + else + if(anchored) + user.visible_message(SPAN_NOTICE("[icon2html(src, viewers(get_turf(src)))] [user] activate the shield generator."), \ + SPAN_NOTICE("[icon2html(src, viewers(get_turf(src)))] You activate the shield generator."), \ + "You hear heavy droning.") + src.shields_up() + else + to_chat(user, SPAN_WARNING("The device must first be secured to the floor.")) + return + +/obj/machinery/shieldgen/emag_act(var/remaining_charges, var/mob/user) + if(!malfunction) + malfunction = TRUE + update_icon() + return TRUE + +/obj/machinery/shieldgen/attackby(obj/item/attacking_item, mob/user) + if(attacking_item.tool_behaviour == TOOL_SCREWDRIVER) + update_icon() + attacking_item.play_tool_sound(get_turf(src), 50) + if(panel_open) + to_chat(user, SPAN_NOTICE("You close the panel.")) + panel_open = FALSE + else + to_chat(user, SPAN_NOTICE("You open the panel and expose the wiring.")) + panel_open = TRUE + + else if(attacking_item.tool_behaviour == TOOL_CABLECOIL && malfunction && panel_open) + var/obj/item/stack/cable_coil/coil = attacking_item + to_chat(user, SPAN_NOTICE("You begin to replace the wires.")) + //if(do_after(user, min(60, round( ((maxhealth/health)*10)+(malfunction*10) ))) //Take longer to repair heavier damage + if(attacking_item.use_tool(src, user, 30, volume = 50)) + if (coil.use(1)) + health = initial(health) + malfunction = FALSE + to_chat(user, SPAN_NOTICE("You repair the [src]!")) + update_icon() + + else if(attacking_item.tool_behaviour == TOOL_WRENCH) + if(locked) + playsound(src, 'sound/machines/terminal/terminal_error.ogg', 25, FALSE) + balloon_alert(user, "locked!") + return + if(attacking_item.use_tool(src, user, 1 SECONDS, volume = 50)) + anchored = !anchored + add_fingerprint(user) + var/others_msg = anchored ? "[user] secures the external reinforcing bolts to the floor." : "[user] unsecures the external reinforcing bolts." + var/self_msg = anchored ? "You secure the external reinforcing bolts to the floor." : "You unsecure the external reinforcing bolts." + user.visible_message(others_msg, SPAN_NOTICE(self_msg), SPAN_NOTICE("You hear a ratcheting noise.")) + update_icon() + return + + else + ..() + +/obj/machinery/shieldgen/AltClick(mob/user) + if(Adjacent(user)) + add_fingerprint(user) + if(allowed(user)) + locked = !locked + if(locked) + playsound(src, 'sound/machines/terminal/terminal_button03.ogg', 35, FALSE) + else + playsound(src, 'sound/machines/terminal/terminal_button01.ogg', 35, FALSE) + balloon_alert(user, locked ? "locked" : "unlocked") + else + to_chat(user, SPAN_WARNING("Access denied.")) + playsound(src, 'sound/machines/terminal/terminal_error.ogg', 25, FALSE) + balloon_alert(user, "access denied!") + +/obj/machinery/shieldgen/update_icon() + ClearOverlays() + if(anchored) + AddOverlays("+bolts") + if(active && !(stat & NOPOWER)) + src.icon_state = malfunction ? "shieldonbr":"shieldon" + else + src.icon_state = malfunction ? "shieldoffbr":"shieldoff" + /obj/machinery/shield name = "emergency energy shield" desc = "An energy shield used to contain hull breaches." @@ -8,9 +260,12 @@ anchored = TRUE unacidable = TRUE atmos_canpass = CANPASS_NEVER - var/health = 75 //The shield can only take so much beating (prevents perma-prisons) - var/shield_generate_power = 2500 //how much power we use when regenerating - var/shield_idle_power = 500 //how much power we use when just being sustained. + /// The shield can only take so much beating (prevents perma-prisons) + var/health = 75 + /// How much power we use when first creating the shield + var/shield_generate_power = 75 KILO WATTS + /// How much power we use when just being sustained. + var/shield_idle_power = 30 KILO WATTS /obj/machinery/shield/malfai name = "emergency forcefield" @@ -90,8 +345,12 @@ health -= hitting_projectile.get_structure_damage() check_failure() - opacity = 1 - spawn(20) if(src) opacity = FALSE + opacity = TRUE + addtimer(CALLBACK(src, PROC_REF(update_opacity), FALSE), 2 SECONDS) + +/obj/machinery/shield/proc/update_opacity(var/new_opacity) + if(src) + opacity = new_opacity /obj/machinery/shield/ex_act(severity) switch(severity) @@ -117,7 +376,6 @@ if(prob(50)) qdel(src) - /obj/machinery/shield/hitby(atom/movable/hitting_atom, skipcatch, hitpush, blocked, datum/thrownthing/throwingdatum) //Let everyone know we've been hit! visible_message(SPAN_NOTICE("\[src] was hit by [hitting_atom].")) @@ -139,247 +397,7 @@ //The shield becomes dense to absorb the blow.. purely asthetic. opacity = TRUE - spawn(20) if(src) opacity = FALSE + addtimer(CALLBACK(src, PROC_REF(update_opacity), FALSE), 2 SECONDS) ..() return - -/obj/machinery/shieldgen - name = "emergency shield projector" - desc = "Used to seal minor hull breaches." - icon = 'icons/obj/machinery/shielding.dmi' - icon_state = "shieldoff" - density = TRUE - opacity = FALSE - anchored = FALSE - req_access = list(ACCESS_ENGINE) - var/health = 100 - var/active = FALSE - // Malfunction causes parts of the shield to slowly dissapate - var/malfunction = FALSE - var/list/deployed_shields = list() - var/list/regenerating = list() - panel_open = FALSE - var/locked = FALSE - var/check_delay = 60 //periodically recheck if we need to rebuild a shield - use_power = POWER_USE_OFF - idle_power_usage = 0 - -/obj/machinery/shieldgen/mechanics_hints(mob/user, distance, is_adjacent) - . += ..() - . += "ALT-click the [src] to lock or unlock it (if you have the appropriate ID access)." - -/obj/machinery/shieldgen/Destroy() - collapse_shields() - return ..() - -/obj/machinery/shieldgen/proc/shields_up() - if(active) return FALSE //If it's already turned on, how did this get called? - - src.active = 1 - update_icon() - - create_shields() - - var/shield_power_usage - for(var/obj/machinery/shield/shield_tile in deployed_shields) - shield_power_usage += shield_tile.shield_idle_power - - change_power_consumption(shield_power_usage, POWER_USE_IDLE) - update_use_power(POWER_USE_IDLE) - -/obj/machinery/shieldgen/proc/shields_down() - if(!active) return FALSE //If it's already off, how did this get called? - - src.active = FALSE - update_icon() - - collapse_shields() - - update_use_power(POWER_USE_OFF) - -/obj/machinery/shieldgen/proc/create_shields() - for(var/T in RANGE_TURFS(2, src)) - var/turf/target_tile = T - if(locate(/obj/machinery/shield) in target_tile) - continue - var/obj/item/tape/engineering/E = locate() in target_tile - if(E?.shield_marker) - deploy_shield(target_tile) - else if(istype(target_tile,/turf/space) || istype(target_tile,/turf/simulated/open) || istype(target_tile,/turf/simulated/floor/exoplanet/asteroid/ash) || istype(target_tile,/turf/simulated/floor/airless)) - if(malfunction && prob(33) || !malfunction) - deploy_shield(target_tile) - -/obj/machinery/shieldgen/proc/deploy_shield(var/turf/T) - var/obj/machinery/shield/S = new /obj/machinery/shield(T) - deployed_shields += S - use_power_oneoff(S.shield_generate_power) - -/obj/machinery/shieldgen/proc/collapse_shields() - for(var/obj/machinery/shield/shield_tile in deployed_shields) - qdel(shield_tile) - -/obj/machinery/shieldgen/power_change() - ..() - if(!active) return - if (stat & NOPOWER) - collapse_shields() - else - create_shields() - update_icon() - -/obj/machinery/shieldgen/process() - if (!active || (stat & NOPOWER)) - return - - if(malfunction) - if(deployed_shields.len && prob(5)) - qdel(pick(deployed_shields)) - else - if (check_delay <= 0) - create_shields() - - var/new_power_usage = 0 - for(var/obj/machinery/shield/shield_tile in deployed_shields) - new_power_usage += shield_tile.shield_idle_power - - if (new_power_usage != idle_power_usage) - change_power_consumption(new_power_usage, POWER_USE_IDLE) - use_power_oneoff(0) - - check_delay = 60 - else - check_delay-- - -/obj/machinery/shieldgen/proc/checkhp() - if(health <= 30) - src.malfunction = 1 - if(health <= 0) - spawn(0) - explosion(get_turf(src.loc), 0, 0, 1, 0, 0, 0) - qdel(src) - update_icon() - return - -/obj/machinery/shieldgen/ex_act(severity) - switch(severity) - if(1.0) - src.health -= 75 - src.checkhp() - if(2.0) - src.health -= 30 - if (prob(15)) - src.malfunction = 1 - src.checkhp() - if(3.0) - src.health -= 10 - src.checkhp() - return - -/obj/machinery/shieldgen/emp_act(severity) - . = ..() - - switch(severity) - if(EMP_HEAVY) - src.health /= 2 //cut health in half - malfunction = TRUE - locked = pick(0,1) - if(EMP_LIGHT) - if(prob(50)) - src.health *= 0.3 //chop off a third of the health - malfunction = TRUE - checkhp() - -/obj/machinery/shieldgen/attack_hand(mob/user) - if(locked) - to_chat(user, SPAN_WARNING("The machine is locked!")) - return - if(panel_open) - to_chat(user, SPAN_WARNING("The panel must be closed before operating this machine.")) - return - - if (src.active) - user.visible_message(SPAN_NOTICE("[icon2html(src, viewers(get_turf(src)))] [user] deactivates the shield generator."), \ - SPAN_NOTICE("[icon2html(src, viewers(get_turf(src)))] You deactivate the shield generator."), \ - "You hear heavy droning fade out.") - src.shields_down() - else - if(anchored) - user.visible_message(SPAN_NOTICE("[icon2html(src, viewers(get_turf(src)))] [user] activate the shield generator."), \ - SPAN_NOTICE("[icon2html(src, viewers(get_turf(src)))] You activate the shield generator."), \ - "You hear heavy droning.") - src.shields_up() - else - to_chat(user, SPAN_WARNING("The device must first be secured to the floor.")) - return - -/obj/machinery/shieldgen/emag_act(var/remaining_charges, var/mob/user) - if(!malfunction) - malfunction = TRUE - update_icon() - return 1 - -/obj/machinery/shieldgen/attackby(obj/item/attacking_item, mob/user) - if(attacking_item.tool_behaviour == TOOL_SCREWDRIVER) - attacking_item.play_tool_sound(get_turf(src), 50) - if(panel_open) - to_chat(user, SPAN_NOTICE("You close the panel.")) - panel_open = FALSE - else - to_chat(user, SPAN_NOTICE("You open the panel and expose the wiring.")) - panel_open = TRUE - - else if(attacking_item.tool_behaviour == TOOL_CABLECOIL && malfunction && panel_open) - var/obj/item/stack/cable_coil/coil = attacking_item - to_chat(user, SPAN_NOTICE("You begin to replace the wires.")) - //if(do_after(user, min(60, round( ((maxhealth/health)*10)+(malfunction*10) ))) //Take longer to repair heavier damage - if(attacking_item.use_tool(src, user, 30, volume = 50)) - if (coil.use(1)) - health = initial(health) - malfunction = FALSE - to_chat(user, SPAN_NOTICE("You repair the [src]!")) - update_icon() - - else if(attacking_item.tool_behaviour == TOOL_WRENCH) - if(locked) - to_chat(user, "The bolts are covered, unlocking this would retract the covers.") - return - if(anchored) - attacking_item.play_tool_sound(get_turf(src), 100) - to_chat(user, SPAN_NOTICE("You unsecure the [src] from the floor!")) - if(active) - to_chat(user, SPAN_NOTICE("The [src] shuts off!")) - src.shields_down() - anchored = FALSE - else - if(istype(get_turf(src), /turf/space)) return //No wrenching these in space! - attacking_item.play_tool_sound(get_turf(src), 100) - to_chat(user, SPAN_NOTICE("You secure the [src] to the floor!")) - anchored = TRUE - - else - ..() - -/obj/machinery/shieldgen/AltClick(mob/user) - if(Adjacent(user)) - add_fingerprint(user) - if(allowed(user)) - locked = !locked - if(locked) - playsound(src, 'sound/machines/terminal/terminal_button03.ogg', 35, FALSE) - else - playsound(src, 'sound/machines/terminal/terminal_button01.ogg', 35, FALSE) - balloon_alert(user, locked ? "locked" : "unlocked") - else - to_chat(user, SPAN_WARNING("Access denied.")) - playsound(src, 'sound/machines/terminal/terminal_error.ogg', 25, FALSE) - balloon_alert(user, "access denied!") - return - - -/obj/machinery/shieldgen/update_icon() - if(active && !(stat & NOPOWER)) - src.icon_state = malfunction ? "shieldonbr":"shieldon" - else - src.icon_state = malfunction ? "shieldoffbr":"shieldoff" - return diff --git a/code/modules/shieldgen/energy_field.dm b/code/modules/shieldgen/energy_field.dm index 797121d07ff..3c9de1eefaf 100644 --- a/code/modules/shieldgen/energy_field.dm +++ b/code/modules/shieldgen/energy_field.dm @@ -4,7 +4,7 @@ /obj/effect/energy_field name = "energy shield" desc = "A strong field of energy, capable of blocking anything as long as it's active." - icon = 'icons/obj/machinery/shielding.dmi' + icon = 'icons/effects/effects.dmi' icon_state = "shield_normal" alpha = 0 mouse_opacity = MOUSE_OPACITY_TRANSPARENT diff --git a/code/modules/shieldgen/shield_capacitor.dm b/code/modules/shieldgen/shield_capacitor.dm index 0fd4a0c647d..a62a7cbf190 100644 --- a/code/modules/shieldgen/shield_capacitor.dm +++ b/code/modules/shieldgen/shield_capacitor.dm @@ -14,11 +14,11 @@ var/stored_charge = 0 var/last_stored_charge = 0 var/time_since_fail = 100 - var/max_charge = 8e6 //8 MJ - var/max_charge_rate = 400000 //400 kW + var/max_charge = 2e8 //200 MJ + var/max_charge_rate = 9000000 //9 MW var/locked = FALSE - var/charge_rate = 100000 //100 kW + var/charge_rate = 100000 //100 kW var/obj/machinery/shield_gen/owned_gen /obj/machinery/shield_capacitor/Initialize() @@ -138,5 +138,6 @@ else ..() +/// Horizon-specific non-variant, for now. /obj/machinery/shield_capacitor/multiz - max_charge_rate = 1250000 + diff --git a/code/modules/shieldgen/shieldwallgen.dm b/code/modules/shieldgen/shieldwallgen.dm index 54b6944a9a4..9f46f7f5a80 100644 --- a/code/modules/shieldgen/shieldwallgen.dm +++ b/code/modules/shieldgen/shieldwallgen.dm @@ -3,17 +3,17 @@ #define POWER_ACTIVE 2 /obj/machinery/shieldwallgen - name = "shield generator" + name = "shield wall generator" desc = "A portable shield generator, capable of casting a shield to another powered generator in range." - icon = 'icons/obj/stationobjs.dmi' - icon_state = "Shield_Gen" + icon = 'icons/obj/machinery/shielding.dmi' + icon_state = "shieldwalloff" anchored = FALSE density = TRUE req_access = list(ACCESS_ENGINE_EQUIP) - + /// Range at which it can pair with another shield wall generator (must be this many spaces BETWEEN THEM at maximum) + var/range = 9 var/power_state = FALSE var/is_powered = FALSE - var/wrenched = FALSE var/locked = TRUE var/storedpower = 0 obj_flags = OBJ_FLAG_CONDUCTABLE @@ -21,36 +21,40 @@ //There have to be at least two posts, so these are effectively doubled ///How much power is drawn from powernet. Increase this to allow the generator to sustain longer shields, at the cost of more power draw. - var/power_draw = 30 KILO WATTS - var/max_stored_power = 50 KILO WATTS + var/power_draw = 200 KILO WATTS + var/max_stored_power = 1000 KILO WATTS /// Draws directly from power net. Does not use APC power. use_power = POWER_USE_OFF /obj/machinery/shieldwallgen/mechanics_hints(mob/user, distance, is_adjacent) . += ..() + . += "A shield wall generator can pair with another from up to [range] tiles away (maximum wall length of [range - 1])." . += "ALT-click the [src] to lock or unlock it (if you have the appropriate ID access)." /obj/machinery/shieldwallgen/active power_state = POWER_STARTING is_powered = TRUE - wrenched = TRUE anchored = TRUE locked = FALSE - icon_state = "Shield_Gen +a" + icon_state = "shieldwallon" storedpower = 9000000 /obj/machinery/shieldwallgen/update_icon() + ClearOverlays() if(power_state >= POWER_STARTING) - icon_state = "Shield_Gen +a" + icon_state = "shieldwallon" else - icon_state = "Shield_Gen" + icon_state = "shieldwalloff" + if(anchored) + AddOverlays("+bolts") /obj/machinery/shieldwallgen/attack_hand(mob/user) - if(!wrenched) + if(!anchored) to_chat(user, SPAN_WARNING("The shield generator needs to be firmly secured to the floor first.")) return TRUE if(locked && !issilicon(user)) - to_chat(user, SPAN_WARNING("The controls are locked!")) + playsound(src, 'sound/machines/terminal/terminal_error.ogg', 25, FALSE) + balloon_alert(user, "locked!") return TRUE if(!is_powered) to_chat(user, SPAN_WARNING("The shield generator needs to be powered by wire underneath.")) @@ -105,7 +109,7 @@ storedpower = clamp(storedpower, 0, max_stored_power) if(power_state == POWER_STARTING) - if(!wrenched) + if(!anchored) power_state = POWER_INACTIVE return addtimer(CALLBACK(src, PROC_REF(setup_field), 1), 1) @@ -133,7 +137,7 @@ oNSEW = REVERSE_DIR(NSEW) - for(var/dist = 0, dist <= 9, dist++) // checks out to 8 tiles away for another generator + for(var/dist = 0, dist <= range, dist++) // checks out to 8 tiles away for another generator T = get_step(T2, NSEW) T2 = T steps += 1 @@ -162,15 +166,14 @@ if(power_state) to_chat(user, SPAN_WARNING("You cannot unsecure \the [src] while it's active.")) return - - wrenched = !wrenched - anchored = wrenched - attacking_item.play_tool_sound(get_turf(src), 75) - add_fingerprint(user) - var/others_msg = wrenched ? "[user] secures the external reinforcing bolts to the floor." : "[user] unsecures the external reinforcing bolts." - var/self_msg = wrenched ? "You secure the external reinforcing bolts to the floor." : "You unsecure the external reinforcing bolts." - user.visible_message(others_msg, SPAN_NOTICE(self_msg), SPAN_NOTICE("You hear a ratcheting noise.")) - return + if(attacking_item.use_tool(src, user, 1 SECONDS, volume = 50)) + anchored = !anchored + add_fingerprint(user) + var/others_msg = anchored ? "[user] secures the external reinforcing bolts to the floor." : "[user] unsecures the external reinforcing bolts." + var/self_msg = anchored ? "You secure the external reinforcing bolts to the floor." : "You unsecure the external reinforcing bolts." + user.visible_message(others_msg, SPAN_NOTICE(self_msg), SPAN_NOTICE("You hear a ratcheting noise.")) + update_icon() + return return ..() /obj/machinery/shieldwallgen/AltClick(mob/user) @@ -184,7 +187,6 @@ playsound(src, 'sound/machines/terminal/terminal_button01.ogg', 35, FALSE) balloon_alert(user, locked ? "locked" : "unlocked") else - to_chat(user, SPAN_WARNING("Access denied.")) playsound(src, 'sound/machines/terminal/terminal_error.ogg', 25, FALSE) balloon_alert(user, "access denied!") return diff --git a/html/changelogs/Bat-EngiStuff.yml b/html/changelogs/Bat-EngiStuff.yml new file mode 100644 index 00000000000..0a5e426879c --- /dev/null +++ b/html/changelogs/Bat-EngiStuff.yml @@ -0,0 +1,79 @@ +################################ +# Example Changelog File +# +# Note: This file, and files beginning with ".", and files that don't end in ".yml" will not be read. If you change this file, you will look really dumb. +# +# Your changelog will be merged with a master changelog. (New stuff added only, and only on the date entry for the day it was merged.) +# When it is, any changes listed below will disappear. +# +# Valid Prefixes: +# bugfix +# - (fixes bugs) +# wip +# - (work in progress) +# qol +# - (quality of life) +# soundadd +# - (adds a sound) +# sounddel +# - (removes a sound) +# rscadd +# - (adds a feature) +# rscdel +# - (removes a feature) +# imageadd +# - (adds an image or sprite) +# imagedel +# - (removes an image or sprite) +# spellcheck +# - (fixes spelling or grammar) +# experiment +# - (experimental change) +# balance +# - (balance changes) +# code_imp +# - (misc internal code change) +# refactor +# - (refactors code) +# config +# - (makes a change to the config files) +# admin +# - (makes changes to administrator tools) +# server +# - (miscellaneous changes to server) +################################# + +# Your name. +author: Batrachophrenoboocosmomachia + +# Optional: Remove this file after generating master changelog. Useful for PR changelogs that won't get used again. +delete-after: True + +# Any changes you've made. See valid prefix list above. +# INDENT WITH TWO SPACES. NOT TABS. SPACES. +# SCREW THIS UP AND IT WON'T WORK. +# Also, this gets changed to [] after reading. Just remove the brackets when you add new shit. +# Please surround your changes in double quotes ("). It works without them, but if you use certain characters it screws up compiling. The quotes will not show up in the changelog. +changes: + - imageadd: "Adds +bolted, +welded, +lights overlays to several large machines for easier visual identification of whether or not clicking on that emitter will kill you or not, etc." + - imageadd: "Modifies the base of the Shield Wall Generator sprite to better match that of the Emergency Shield Projector (and so they can use the same overlays mentioned above)." + - imageadd: "Tweaks the Emitter's directional sprites slightly so that the base doesn't seem to change shape quite so drastically when rotated." + - imageadd: "Ports very pretty space heater sprites made by Wallemations and vinylspiders from /tg/." + - imageadd: "Adds unique sprites for Old and Heavy-Duty power cells." + - balance: "Increases power draw and range of Emergency Shield Projectors." + - balance: "Increases power draw of Shield Wall Generators." + - balance: "Greatly reduces time for debugger to fix APCs corrupted by electrical storms." + - balance: "Increases multi-z shield capacitor reserve charge and maximum throughput, so that high-strength shields can actually be run (at high power draw)." + - balance: "Tweaks the INDRA power output formula to scale better with increasing temperature." + - balance: "Slight adjustments to space heater efficiency formula with a friendly handwave to entropy." + - balance: "Old power cells have a 5% chance to be defective and have slightly lower maxcharge than standard cells." + - qol: "Adds extended examine hints to engineering objects." + - qol: "Extends list of object types which INDRA core field will interact peacefully with." + - qol: "Improved space heater UX (chat msgs changed to balloon alerts, audible feedback, etc.)" + - code_imp: "Updates many code comments to use DMdocs." + - code_imp: "Consolidates various shield generation machine sprites in scattered across multiple files into a single shield generator machines sprite file." + - bugfix: "Fixes Emergency Shield Projector hard del issue." + - bugfix: "Emergency Shield Projector now shuts down as intended if the area's APC gets completely drained." + - bugfix: "Firing the gyrotron into the INDRA while no reactants are present will no longer generate heat." + - bugfix: "Fixes INDRA runtime." + - bugfix: "Fixes Power Monitoring app not displaying grid sensors when run from a modular computer held in-hand." diff --git a/icons/effects/effects.dmi b/icons/effects/effects.dmi index 1fbd4ec1026..1f224ccd19d 100644 Binary files a/icons/effects/effects.dmi and b/icons/effects/effects.dmi differ diff --git a/icons/obj/atmos.dmi b/icons/obj/atmos.dmi index 2c32bb0d990..a74e7c3d33f 100644 Binary files a/icons/obj/atmos.dmi and b/icons/obj/atmos.dmi differ diff --git a/icons/obj/emitter.dmi b/icons/obj/emitter.dmi index 05238c94b31..70bc948d4e8 100644 Binary files a/icons/obj/emitter.dmi and b/icons/obj/emitter.dmi differ diff --git a/icons/obj/machinery/cell_charger.dmi b/icons/obj/machinery/cell_charger.dmi index e8f6da95631..e1658e98b22 100644 Binary files a/icons/obj/machinery/cell_charger.dmi and b/icons/obj/machinery/cell_charger.dmi differ diff --git a/icons/obj/machinery/field_generator.dmi b/icons/obj/machinery/field_generator.dmi deleted file mode 100644 index 3fd5ae9a4a8..00000000000 Binary files a/icons/obj/machinery/field_generator.dmi and /dev/null differ diff --git a/icons/obj/machinery/shielding.dmi b/icons/obj/machinery/shielding.dmi index b359af7d56a..79925e22c75 100644 Binary files a/icons/obj/machinery/shielding.dmi and b/icons/obj/machinery/shielding.dmi differ diff --git a/icons/obj/stationobjs.dmi b/icons/obj/stationobjs.dmi index 84845eb5356..63711bdf024 100644 Binary files a/icons/obj/stationobjs.dmi and b/icons/obj/stationobjs.dmi differ diff --git a/tgui/packages/tgui/interfaces/SpaceHeater.tsx b/tgui/packages/tgui/interfaces/SpaceHeater.tsx index 6570f59d514..628a07c04b2 100644 --- a/tgui/packages/tgui/interfaces/SpaceHeater.tsx +++ b/tgui/packages/tgui/interfaces/SpaceHeater.tsx @@ -17,7 +17,6 @@ export type SpaceHeaterData = { power_cell_inserted: BooleanLike; power_cell_charge: number; panel_open: BooleanLike; - heating_power: number; current_temperature: number; set_temperature: number; set_temperature_max: number; @@ -28,13 +27,14 @@ export const SpaceHeater = (props, context) => { const { act, data } = useBackend(context); return ( - +
act('powerToggle')}