mirror of
https://github.com/Aurorastation/Aurora.3.git
synced 2026-08-31 09:00:25 +01:00
Engineering spriting (detailing & port), portable shield balance, bugfixes (#21862)
EXTREMELY MINOR MISCELLANEOUS CHANGES TEEHEE 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." Bolted/welded down Emitter: <img width="130" height="101" alt="Screenshot 2026-02-13 123842" src="https://github.com/user-attachments/assets/8357b5ea-77e6-46f7-b4a0-724aaa141cef" /> Modified shieldwall sprites (with old ones for comparison) <img width="667" height="103" alt="Screenshot 2026-02-13 111422" src="https://github.com/user-attachments/assets/2b1e849e-f955-49cb-b094-0bef098a754f" /> Shields actually useful for damage control now (though they'll blow through APC charge if you go as crazy as this): <img width="804" height="891" alt="Screenshot 2026-02-13 124245" src="https://github.com/user-attachments/assets/39268b42-5abe-4a3b-ba8a-a18bdc63873e" /> ### Asset Licenses The following assets that **have not** been created by myself are included in this PR: | Path | Original Author | License | | --- | --- | --- | | icons/obj/atmos.dmi (all "sheater*") | [Wallemations, VinylSpiders (/tg/station #93800)](https://github.com/tgstation/tgstation/pull/93800) | CC-BY-SA | --------- Signed-off-by: Batrachophreno <Batrochophreno@gmail.com> Co-authored-by: SleepyGemmy <99297919+SleepyGemmy@users.noreply.github.com>
This commit is contained in:
co-authored by
SleepyGemmy
parent
adeaaaee4a
commit
0c342878e5
@@ -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 <b>[range]</b> 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 ? "<b>[user]</b> secures the external reinforcing bolts to the floor." : "<b>[user]</b> 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("<B>\[src] was hit by [hitting_atom].</B>"))
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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 <b>[range]</b> tiles away (maximum wall length of <b>[range - 1]</b>)."
|
||||
. += "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 ? "<b>[user]</b> secures the external reinforcing bolts to the floor." : "<b>[user]</b> 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 ? "<b>[user]</b> secures the external reinforcing bolts to the floor." : "<b>[user]</b> 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
|
||||
|
||||
Reference in New Issue
Block a user