#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(W.GetID()) 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