diff --git a/aurorastation.dme b/aurorastation.dme index 101fb30d9ac..5c89d677e76 100644 --- a/aurorastation.dme +++ b/aurorastation.dme @@ -2636,10 +2636,10 @@ #include "code\modules\shareddream\dream_entry.dm" #include "code\modules\shieldgen\emergency_shield.dm" #include "code\modules\shieldgen\energy_field.dm" -#include "code\modules\shieldgen\sheldwallgen.dm" #include "code\modules\shieldgen\shield_capacitor.dm" #include "code\modules\shieldgen\shield_gen.dm" #include "code\modules\shieldgen\shield_gen_external.dm" +#include "code\modules\shieldgen\shieldwallgen.dm" #include "code\modules\shuttles\antagonist.dm" #include "code\modules\shuttles\departmental.dm" #include "code\modules\shuttles\escape_pods.dm" diff --git a/code/modules/power/singularity/singularity.dm b/code/modules/power/singularity/singularity.dm index a373108aacd..72d4eaab405 100644 --- a/code/modules/power/singularity/singularity.dm +++ b/code/modules/power/singularity/singularity.dm @@ -410,7 +410,7 @@ else if (locate(/obj/machinery/shieldwallgen) in T) var/obj/machinery/shieldwallgen/S = locate(/obj/machinery/shieldwallgen) in T - if (S && S.active) + if (S?.power_state) return 0 return 1 diff --git a/code/modules/shieldgen/sheldwallgen.dm b/code/modules/shieldgen/sheldwallgen.dm deleted file mode 100644 index 8ca6ae07467..00000000000 --- a/code/modules/shieldgen/sheldwallgen.dm +++ /dev/null @@ -1,325 +0,0 @@ -////FIELD GEN START //shameless copypasta from fieldgen, powersink, and grille -/obj/machinery/shieldwallgen - name = "Shield Generator" - desc = "A shield generator." - icon = 'icons/obj/stationobjs.dmi' - icon_state = "Shield_Gen" - anchored = 0 - density = 1 - req_access = list(access_engine_equip) - var/active = 0 - var/power = 0 - var/state = 0 - var/steps = 0 - var/last_check = 0 - var/check_delay = 10 - var/recalc = 0 - var/locked = 1 - var/destroyed = 0 - var/directwired = 1 -// var/maxshieldload = 200 - var/obj/structure/cable/attached // the attached cable - var/storedpower = 0 - flags = CONDUCT - //There have to be at least two posts, so these are effectively doubled - var/power_draw = 30000 //30 kW. 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/max_stored_power = 50000 //50 kW - use_power = 0 //Draws directly from power net. Does not use APC power. - -/obj/machinery/shieldwallgen/attack_hand(mob/user as mob) - if(state != 1) - to_chat(user, "The shield generator needs to be firmly secured to the floor first.") - return 1 - if(src.locked && !istype(user, /mob/living/silicon)) - to_chat(user, "The controls are locked!") - return 1 - if(power != 1) - to_chat(user, "The shield generator needs to be powered by wire underneath.") - return 1 - - if(src.active >= 1) - src.active = 0 - icon_state = "Shield_Gen" - - user.visible_message("[user] turned the shield generator off.", \ - "You turn off the shield generator.", \ - "You hear heavy droning fade out.") - for(var/dir in list(1,2,4,8)) src.cleanup(dir) - else - src.active = 1 - icon_state = "Shield_Gen +a" - user.visible_message("[user] turned the shield generator on.", \ - "You turn on the shield generator.", \ - "You hear heavy droning.") - src.add_fingerprint(user) - -/obj/machinery/shieldwallgen/proc/power() - if(!anchored) - power = 0 - return 0 - var/turf/T = src.loc - if (!istype(T)) - power = 0 - return 0 - - var/obj/structure/cable/C = T.get_cable_node() - var/datum/powernet/PN - if(C) PN = C.powernet // find the powernet of the connected cable - - if(!PN) - power = 0 - return 0 - - var/shieldload = between(500, max_stored_power - storedpower, power_draw) //what we try to draw - shieldload = PN.draw_power(shieldload) //what we actually get - storedpower += shieldload - - //If we're still in the red, then there must not be enough available power to cover our load. - if(storedpower <= 0) - power = 0 - return 0 - - power = 1 // IVE GOT THE POWER! - return 1 - -/obj/machinery/shieldwallgen/machinery_process() - power() - if(power) - storedpower -= 2500 //the generator post itself uses some power - - if(storedpower >= max_stored_power) - storedpower = max_stored_power - if(storedpower <= 0) - storedpower = 0 -// if(shieldload >= maxshieldload) //there was a loop caused by specifics of process(), so this was needed. -// shieldload = maxshieldload - - if(src.active == 1) - if(!src.state == 1) - src.active = 0 - return - addtimer(CALLBACK(src, .proc/setup_field, 1), 1) - addtimer(CALLBACK(src, .proc/setup_field, 2), 2) - addtimer(CALLBACK(src, .proc/setup_field, 3), 4) - addtimer(CALLBACK(src, .proc/setup_field, 4), 8) - src.active = 2 - if(src.active >= 1) - if(src.power == 0) - src.visible_message("The [src.name] shuts down due to lack of power!", \ - "You hear heavy droning fade out") - icon_state = "Shield_Gen" - src.active = 0 - for(var/dir in list(1,2,4,8)) - cleanup(dir) - -/obj/machinery/shieldwallgen/proc/setup_field(var/NSEW = 0) - var/turf/T = src.loc - var/turf/T2 = src.loc - var/obj/machinery/shieldwallgen/G - var/steps = 0 - var/oNSEW = 0 - - if(!NSEW)//Make sure its ran right - return - - if(NSEW == 1) - oNSEW = 2 - else if(NSEW == 2) - oNSEW = 1 - else if(NSEW == 4) - oNSEW = 8 - else if(NSEW == 8) - oNSEW = 4 - - for(var/dist = 0, dist <= 9, dist += 1) // checks out to 8 tiles away for another generator - T = get_step(T2, NSEW) - T2 = T - steps += 1 - if(locate(/obj/machinery/shieldwallgen) in T) - G = (locate(/obj/machinery/shieldwallgen) in T) - steps -= 1 - if(!G.active) - return - G.cleanup(oNSEW) - break - - if(isnull(G)) - return - - T2 = src.loc - - for(var/dist = 0, dist < steps, dist += 1) // creates each field tile - var/field_dir = get_dir(T2,get_step(T2, NSEW)) - T = get_step(T2, NSEW) - T2 = T - var/obj/shieldwall/CF = new/obj/shieldwall/(T, src, G) //(ref to this gen, ref to connected gen) - CF.set_dir(field_dir) - - -/obj/machinery/shieldwallgen/attackby(obj/item/W, mob/user) - if(W.iswrench()) - if(active) - to_chat(user, "Turn off the field generator first.") - return - - else if(state == 0) - state = 1 - playsound(src.loc, W.usesound, 75, 1) - to_chat(user, "You secure the external reinforcing bolts to the floor.") - src.anchored = 1 - return - - else if(state == 1) - state = 0 - playsound(src.loc, W.usesound, 75, 1) - to_chat(user, "You undo the external reinforcing bolts.") - src.anchored = 0 - return - - if(istype(W, /obj/item/card/id)||istype(W, /obj/item/device/pda)) - if (src.allowed(user)) - src.locked = !src.locked - to_chat(user, "Controls are now [src.locked ? "locked." : "unlocked."]") - else - to_chat(user, "Access denied.") - - else - src.add_fingerprint(user) - visible_message("The [src.name] has been hit with \the [W.name] by [user.name]!") - -/obj/machinery/shieldwallgen/proc/cleanup(var/NSEW) - var/obj/shieldwall/F - var/obj/machinery/shieldwallgen/G - var/turf/T = src.loc - var/turf/T2 = src.loc - - for(var/dist = 0, dist <= 9, dist += 1) // checks out to 8 tiles away for fields - T = get_step(T2, NSEW) - T2 = T - if(locate(/obj/shieldwall) in T) - F = (locate(/obj/shieldwall) in T) - qdel(F) - - if(locate(/obj/machinery/shieldwallgen) in T) - G = (locate(/obj/machinery/shieldwallgen) in T) - if(!G.active) - break - -/obj/machinery/shieldwallgen/Destroy() - src.cleanup(1) - src.cleanup(2) - src.cleanup(4) - src.cleanup(8) - return ..() - -/obj/machinery/shieldwallgen/bullet_act(var/obj/item/projectile/Proj) - storedpower -= 400 * Proj.get_structure_damage() - ..() - return - - -//////////////Containment Field START -/obj/shieldwall - name = "shield" - desc = "An energy shield." - icon = 'icons/effects/effects.dmi' - icon_state = "shieldwall" - anchored = 1 - density = 1 - unacidable = 1 - light_range = 3 - light_color = LIGHT_COLOR_BLUE - var/needs_power = 0 - var/active = 1 -// var/power = 10 - var/delay = 5 - var/last_active - var/mob/U - var/obj/machinery/shieldwallgen/gen_primary - var/obj/machinery/shieldwallgen/gen_secondary - var/power_usage = 2500 //how much power it takes to sustain the shield - var/generate_power_usage = 7500 //how much power it takes to start up the shield - -/obj/shieldwall/Initialize(mapload, var/obj/machinery/shieldwallgen/A, var/obj/machinery/shieldwallgen/B) - . = ..() - update_nearby_tiles() - gen_primary = A - gen_secondary = B - if(A && B && A.active && B.active) - needs_power = 1 - A.storedpower -= generate_power_usage/2 - B.storedpower -= generate_power_usage/2 - START_PROCESSING(SSprocessing, src) - else - qdel(src) //need at least two generator posts - -/obj/shieldwall/Destroy() - update_nearby_tiles() - STOP_PROCESSING(SSprocessing, src) - return ..() - -/obj/shieldwall/attack_hand(mob/user as mob) - return - -/obj/shieldwall/process() - if(needs_power) - if(!gen_primary || !gen_secondary) - qdel(src) - return - - if(!(gen_primary.active) || !(gen_secondary.active)) - qdel(src) - return - - gen_primary.storedpower -= power_usage/2 - gen_secondary.storedpower -= power_usage/2 - -/obj/shieldwall/bullet_act(var/obj/item/projectile/Proj) - if(needs_power) - var/obj/machinery/shieldwallgen/G - if(prob(50)) - G = gen_primary - else - G = gen_secondary - G.storedpower -= 400 * Proj.get_structure_damage() - ..() - return - - -/obj/shieldwall/ex_act(severity) - if(needs_power) - var/obj/machinery/shieldwallgen/G - switch(severity) - if(1.0) //big boom - if(prob(50)) - G = gen_primary - else - G = gen_secondary - G.storedpower -= 120000 - - if(2.0) //medium boom - if(prob(50)) - G = gen_primary - else - G = gen_secondary - G.storedpower -= 30000 - - if(3.0) //lil boom - if(prob(50)) - G = gen_primary - else - G = gen_secondary - G.storedpower -= 12000 - return - - -/obj/shieldwall/CanPass(atom/movable/mover, turf/target, height=0, air_group=0) - if(air_group || (height==0)) return 1 - - if(istype(mover) && mover.checkpass(PASSGLASS)) - return prob(20) - else - if (istype(mover, /obj/item/projectile)) - return prob(10) - else - return !src.density diff --git a/code/modules/shieldgen/shieldwallgen.dm b/code/modules/shieldgen/shieldwallgen.dm new file mode 100644 index 00000000000..37255968283 --- /dev/null +++ b/code/modules/shieldgen/shieldwallgen.dm @@ -0,0 +1,304 @@ +#define POWER_INACTIVE 0 +#define POWER_STARTING 1 +#define POWER_ACTIVE 2 + +/obj/machinery/shieldwallgen + name = "shield 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" + anchored = FALSE + density = TRUE + req_access = list(access_engine_equip) + + var/power_state = FALSE + var/is_powered = FALSE + var/wrenched = FALSE + var/steps = 0 + var/last_check = 0 + var/check_delay = 10 + var/locked = TRUE + var/storedpower = 0 + flags = CONDUCT + + //There have to be at least two posts, so these are effectively doubled + var/power_draw = 30000 //30 kW. 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/max_stored_power = 50000 //50 kW + use_power = FALSE //Draws directly from power net. Does not use APC power. + +/obj/machinery/shieldwallgen/update_icon() + if(power_state >= POWER_STARTING) + icon_state = "Shield_Gen +a" + else + icon_state = "Shield_Gen" + +/obj/machinery/shieldwallgen/attack_hand(mob/user) + if(!wrenched) + 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!")) + return TRUE + if(!is_powered) + to_chat(user, SPAN_WARNING("The shield generator needs to be powered by wire underneath.")) + return TRUE + + if(power_state >= POWER_STARTING) + power_state = POWER_INACTIVE + user.visible_message("[user] turns \the [src] off.", SPAN_NOTICE("You turn off \the [src]."), SPAN_NOTICE("You hear a heavy droning fade out.")) + alldir_cleanup() + else + power_state = POWER_STARTING + user.visible_message("[user] turns \the [src] on.", SPAN_NOTICE("You turn on \the [src]."), SPAN_NOTICE("You hear a heavy droning start up.")) + update_icon() + add_fingerprint(user) + +/obj/machinery/shieldwallgen/proc/power() + if(!anchored) + is_powered = FALSE + return FALSE + var/turf/T = loc + if(!istype(T)) + is_powered = FALSE + return FALSE + + var/obj/structure/cable/C = T.get_cable_node() + var/datum/powernet/PN + if(C) + PN = C.powernet // find the powernet of the connected cable + + if(!PN) + is_powered = FALSE + return FALSE + + var/shieldload = between(500, max_stored_power - storedpower, power_draw) //what we try to draw + shieldload = PN.draw_power(shieldload) //what we actually get + storedpower += shieldload + + //If we're still in the red, then there must not be enough available power to cover our load. + if(storedpower <= 0) + is_powered = FALSE + return FALSE + + is_powered = TRUE // IVE GOT THE POWER! + return TRUE + +/obj/machinery/shieldwallgen/machinery_process() + power() + if(is_powered) + storedpower -= 2500 + + storedpower = clamp(storedpower, 0, max_stored_power) + + if(power_state == POWER_STARTING) + if(!wrenched) + power_state = POWER_INACTIVE + return + addtimer(CALLBACK(src, .proc/setup_field, 1), 1) + addtimer(CALLBACK(src, .proc/setup_field, 2), 2) + addtimer(CALLBACK(src, .proc/setup_field, 3), 4) + addtimer(CALLBACK(src, .proc/setup_field, 4), 8) + power_state = POWER_ACTIVE + + if(power_state >= POWER_STARTING) + if(!is_powered) + visible_message(SPAN_WARNING("\The [src] shuts down due to a lack of power."), SPAN_NOTICE("You hear a heavy droning fade out.")) + power_state = POWER_INACTIVE + update_icon() + alldir_cleanup() + +/obj/machinery/shieldwallgen/proc/setup_field(var/NSEW) + var/turf/T = loc + var/turf/T2 = loc + var/obj/machinery/shieldwallgen/G + var/steps = 0 + var/oNSEW = 0 + + if(!NSEW)//Make sure its ran right + return + + oNSEW = reverse_direction(NSEW) + + for(var/dist = 0, dist <= 9, dist++) // checks out to 8 tiles away for another generator + T = get_step(T2, NSEW) + T2 = T + steps += 1 + if(locate(/obj/machinery/shieldwallgen) in T) + G = (locate(/obj/machinery/shieldwallgen) in T) + steps -= 1 + if(!G.power_state) + return + G.cleanup(oNSEW) + break + + if(isnull(G)) + return + + T2 = loc + + for(var/dist = 0, dist < steps, dist++) // creates each field tile + var/field_dir = get_dir(T2, get_step(T2, NSEW)) + T = get_step(T2, NSEW) + T2 = T + var/obj/shieldwall/CF = new /obj/shieldwall/(T, src, G) //(ref to this gen, ref to connected gen) + CF.set_dir(field_dir) + +/obj/machinery/shieldwallgen/attackby(obj/item/W, mob/user) + if(W.iswrench()) + if(power_state) + to_chat(user, SPAN_WARNING("You cannot unsecure \the [src] while it's active.")) + return + + wrenched = !wrenched + anchored = wrenched + playsound(loc, W.usesound, 75, TRUE) + 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(istype(W, /obj/item/card/id) || istype(W, /obj/item/device/pda)) + add_fingerprint(user) + if(allowed(user)) + locked = !locked + var/msg = "The controls are now [locked ? "locked" : "unlocked"]." + to_chat(user, SPAN_NOTICE(msg)) + else + to_chat(user, SPAN_WARNING("Access denied.")) + return + + return ..() + +/obj/machinery/shieldwallgen/proc/alldir_cleanup() + for(var/dir in list(NORTH, SOUTH, EAST, WEST)) + cleanup(dir) + +/obj/machinery/shieldwallgen/proc/cleanup(var/NSEW) + var/obj/shieldwall/F + var/obj/machinery/shieldwallgen/G + var/turf/T = loc + var/turf/T2 = loc + + for(var/dist = 0, dist <= 9, dist++) // checks out to 8 tiles away for fields + T = get_step(T2, NSEW) + T2 = T + if(locate(/obj/shieldwall) in T) + F = (locate(/obj/shieldwall) in T) + qdel(F) + + if(locate(/obj/machinery/shieldwallgen) in T) + G = (locate(/obj/machinery/shieldwallgen) in T) + if(!G.power_state) + break + +/obj/machinery/shieldwallgen/Destroy() + alldir_cleanup() + return ..() + +/obj/machinery/shieldwallgen/bullet_act(var/obj/item/projectile/Proj) + storedpower -= 400 * Proj.get_structure_damage() + if(power_state >= POWER_STARTING) + visible_message(SPAN_WARNING("\The [src]'s shielding sparks as \the [Proj] hits it!")) + return ..() + +/obj/shieldwall + name = "energy shield" + desc = "An energy shield." + icon = 'icons/effects/effects.dmi' + icon_state = "shieldwall" + anchored = TRUE + density = TRUE + unacidable = TRUE + light_range = 3 + light_color = LIGHT_COLOR_BLUE + var/needs_power = FALSE + var/power_state = POWER_STARTING + var/delay = 5 + var/last_active + var/mob/U + var/obj/machinery/shieldwallgen/gen_primary + var/obj/machinery/shieldwallgen/gen_secondary + var/power_usage = 2500 //how much power it takes to sustain the shield + var/generate_power_usage = 7500 //how much power it takes to start up the shield + +/obj/shieldwall/Initialize(mapload, var/obj/machinery/shieldwallgen/A, var/obj/machinery/shieldwallgen/B) + . = ..() + update_nearby_tiles() + gen_primary = A + gen_secondary = B + if(A?.power_state && B?.power_state) + needs_power = TRUE + A.storedpower -= generate_power_usage / 2 + B.storedpower -= generate_power_usage / 2 + START_PROCESSING(SSprocessing, src) + else + qdel(src) //need at least two generator posts + +/obj/shieldwall/Destroy() + update_nearby_tiles() + STOP_PROCESSING(SSprocessing, src) + return ..() + +/obj/shieldwall/attack_hand(mob/user) + to_chat(user, SPAN_WARNING("\The [src] pushes you back as you try to touch it.")) + +/obj/shieldwall/process() + if(needs_power) + if(!gen_primary || !gen_secondary) + qdel(src) + return + + if(!gen_primary.power_state || !gen_secondary.power_state) + qdel(src) + return + + gen_primary.storedpower -= power_usage / 2 + gen_secondary.storedpower -= power_usage / 2 + +/obj/shieldwall/bullet_act(var/obj/item/projectile/Proj) + if(needs_power) + var/obj/machinery/shieldwallgen/G + if(prob(50)) + G = gen_primary + else + G = gen_secondary + visible_message(SPAN_WARNING("\The [src] wobbles precariously as \the [Proj] impacts it!")) + G.storedpower -= 400 * Proj.get_structure_damage() + return ..() + +/obj/shieldwall/ex_act(severity) + if(needs_power) + var/obj/machinery/shieldwallgen/G + switch(severity) + if(1.0) //big boom + if(prob(50)) + G = gen_primary + else + G = gen_secondary + G.storedpower -= 120000 + + if(2.0) //medium boom + if(prob(50)) + G = gen_primary + else + G = gen_secondary + G.storedpower -= 30000 + + if(3.0) //lil boom + if(prob(50)) + G = gen_primary + else + G = gen_secondary + G.storedpower -= 12000 + +/obj/shieldwall/CanPass(atom/movable/mover, turf/target, height=0, air_group=0) + if(air_group || (height==0)) + return TRUE + if(istype(mover) && mover.checkpass(PASSGLASS)) + return prob(20) + else + if(istype(mover, /obj/item/projectile)) + return prob(10) + else + return !density \ No newline at end of file diff --git a/html/changelogs/geeves-shieldwall_responsiveness.yml b/html/changelogs/geeves-shieldwall_responsiveness.yml new file mode 100644 index 00000000000..a0542ad8af9 --- /dev/null +++ b/html/changelogs/geeves-shieldwall_responsiveness.yml @@ -0,0 +1,6 @@ +author: Geeves + +delete-after: True + +changes: + - rscadd: "Cleaned up some Shield Generator code, and added some text to generated shields being hit by projectiles, making it more clear that projectiles can dissipate those shields." \ No newline at end of file