From d7104ef0272cf033b914bd55e95e6abc44945207 Mon Sep 17 00:00:00 2001 From: Nerezza Date: Mon, 21 Nov 2016 19:33:30 -0600 Subject: [PATCH] Misc APC fixes & tweaks -Adds a Polaris version of APC rebooting -Changes the random APC-bluescreening event to be more sensible in what it does and how to repair it. Bluescreened APCs are permanently unlocked, and can be fixed by removing the power cell and applying a multitool. -EMP'd APCs now give Bay's timed (or manual) reboot nanoUI so that important places aren't shut off permanently if engineering can't get around to them. -Nins and twizs no longer **** up APCs when they drain power from the cell completely. Also, drained power comes from the powernet primarily, and only draws from the battery if the powernet doesn't give enough (random chance) or if the cable is cut. -Bluescreened APC sprite now switches to an open wire panel sprite if a screwdriver is applied. -Grid checks put a nanoUI notice on APCs. As it is now, you have to wait for the grid check to end or use the grid checker in engineering before you can manipulate APCs. -Grammar fixes -More grammar fixes -My god the grammar fixes -to_chat'd the user <The cover is locked and cannot be opened.") return @@ -571,6 +585,7 @@ if(do_after(user, 10)) if(has_electronics==0) has_electronics = 1 + reboot() to_chat(user,"You place the power control board inside the frame.") qdel(W) else if (istype(W, /obj/item/weapon/module/power_control) && opened && has_electronics==0 && ((stat & BROKEN))) @@ -584,7 +599,7 @@ user.visible_message("[user.name] begins cutting apart [src] with the [WT.name].", \ "You start welding the APC frame...", \ "You hear welding.") - playsound(src.loc, 'sound/items/Welder.ogg', 50, 1) + playsound(src.loc, 'sound/items/Welder.ogg', 25, 1) if(do_after(user, 50)) if(!src || !WT.remove_fuel(3, user)) return if (emagged || (stat & BROKEN) || opened==2) @@ -601,28 +616,35 @@ "You hear welding.") qdel(src) return - else if (istype(W, /obj/item/frame/apc) && opened && ((stat & BROKEN) || hacker || emagged)) - if(cell) - to_chat(user, "You need to remove the power cell first.") - return - user.visible_message("[user.name] begins replacing the damaged APC cover with a new one.",\ - "You begin to replace the damaged APC cover...") - if(do_after(user, 50)) - user.visible_message(\ - "[user.name] has replaced the damaged APC cover with a new one.",\ - "You replace the damaged APC cover with a new one.") - qdel(W) - emagged = 0 - stat &= ~BROKEN - // Malf AI, removes the APC from AI's hacked APCs list. - if(hacker && hacker.hacked_apcs && (src in hacker.hacked_apcs)) - hacker.hacked_apcs -= src - hacker = null - if (opened==2) - opened = 1 - update_icon() + else if (opened && ((stat & BROKEN) || hacker || emagged)) + if (istype(W, /obj/item/frame/apc) && (stat & BROKEN)) + if(cell) + to_chat(user, "You need to remove the power cell first.") + return + user.visible_message("[user.name] begins replacing the damaged APC cover with a new one.",\ + "You begin to replace the damaged APC cover...") + if(do_after(user, 50)) + user.visible_message("[user.name] has replaced the damaged APC cover with a new one.",\ + "You replace the damaged APC cover with a new one.") + qdel(W) + stat &= ~BROKEN + reboot() + if (opened==2) + opened = 1 + update_icon() + else if (istype(W, /obj/item/device/multitool) && (hacker || emagged)) + if(cell) + to_chat(user, "You need to remove the power cell first.") + return + user.visible_message("[user.name] connects their [W.name] to the APC and begins resetting it.",\ + "You begin resetting the APC...") + if(do_after(user, 50)) + user.visible_message("[user.name] resets the APC with a beep from their [W.name].",\ + "You finish resetting the APC.") + playsound(src.loc, 'sound/machines/chime.ogg', 25, 1) + reboot() else - if (((stat & BROKEN) || hacker) \ + if ((stat & BROKEN) \ && !opened \ && W.force >= 5 \ && W.w_class >= ITEMSIZE_NORMAL ) @@ -643,7 +665,7 @@ istype(W, /obj/item/weapon/wirecutters) || istype(W, /obj/item/device/assembly/signaler))) return src.attack_hand(user) //Placeholder until someone can do take_damage() for APCs or something. - to_chat(user,"The [W.name] doesn't look like it'd do much damage to [src.name] right now.") + to_chat(user,"The [src.name] looks too sturdy to bash open.") // attack with hand - remove cell (if cover open) or interact with the APC @@ -731,6 +753,7 @@ var/list/data = list( "locked" = locked, + "emagged" = emagged, "isOperating" = operating, "externalPower" = main_status, "powerCellStatus" = cell ? cell.percent() : null, @@ -738,6 +761,8 @@ "chargingStatus" = charging, "totalLoad" = round(lastused_total), "totalCharging" = round(lastused_charging), + "failTime" = failure_timer * 2, + "gridCheck" = grid_check, "coverLocked" = coverlocked, "siliconUser" = issilicon(user) || isobserver(user), //I add observer here so admins can have more control, even if it makes 'siliconUser' seem inaccurate. @@ -792,10 +817,10 @@ return "[area.name] : [equipment]/[lighting]/[environ] ([lastused_equip+lastused_light+lastused_environ]) : [cell? cell.percent() : "N/C"] ([charging])" /obj/machinery/power/apc/proc/update() - if(operating && !shorted && !grid_check) - area.power_light = (lighting > 1) - area.power_equip = (equipment > 1) - area.power_environ = (environ > 1) + if(operating && !shorted && !grid_check && !failure_timer) + area.power_light = (lighting >= POWERCHAN_ON) + area.power_equip = (equipment >= POWERCHAN_ON) + area.power_environ = (environ >= POWERCHAN_ON) // if (area.name == "AI Chamber") // spawn(10) // world << " [area.name] [area.power_equip]" @@ -872,6 +897,11 @@ if (href_list["lock"]) coverlocked = !coverlocked + else if (href_list["reboot"]) + failure_timer = 0 + update_icon() + update() + else if (href_list["breaker"]) toggle_breaker() @@ -907,9 +937,9 @@ if(istype(usr, /mob/living/silicon)) if(emagged || (stat & (BROKEN|MAINT))) to_chat(usr,"The APC does not respond to the command.") - else - locked = !locked - update_icon() + return + locked = !locked + update_icon() return 0 @@ -918,6 +948,8 @@ src.update() update_icon() +//This isn't used for now, so might as well disable it +/* /obj/machinery/power/apc/proc/ion_act() if(prob(3)) src.locked = 1 @@ -934,7 +966,7 @@ s.start() visible_message("The [src.name] suddenly lets out a blast of smoke and some sparks!", \ "You hear sizzling electronics.") - +*/ /obj/machinery/power/apc/surplus() if(terminal) @@ -970,6 +1002,12 @@ return if(!area.requires_power) return + if(failure_timer) + update() + queue_icon_update() + failure_timer-- + force_update = 1 + return lastused_light = area.usage(LIGHT) lastused_equip = area.usage(EQUIP) @@ -1069,7 +1107,8 @@ autoflag = 0 // update icon & area power if anything changed - if(last_lt != lighting || last_eq != equipment || last_en != environ) + if(last_lt != lighting || last_eq != equipment || last_en != environ || force_update) + force_update = 0 queue_icon_update() update() else if (last_ch != charging) @@ -1113,43 +1152,41 @@ // val 0=off, 1=off(auto) 2=on 3=on(auto) // on 0=off, 1=on, 2=autooff +// defines a state machine, returns the new state +obj/machinery/power/apc/proc/autoset(var/cur_state, var/on) + switch(cur_state) + if(POWERCHAN_OFF); //autoset will never turn on a channel set to off + if(POWERCHAN_OFF_AUTO) + if(on == 1) + return POWERCHAN_ON_AUTO + if(POWERCHAN_ON) + if(on == 0) + return POWERCHAN_OFF + if(POWERCHAN_ON_AUTO) + if(on == 0 || on == 2) + return POWERCHAN_OFF_AUTO -obj/machinery/power/apc/proc/autoset(var/val, var/on) - if(on==0) - if(val==2) // if on, return off - return 0 - else if(val==3) // if auto-on, return auto-off - return 1 - - else if(on==1) - if(val==1) // if auto-off, return auto-on - return 3 - - else if(on==2) - if(val==3) // if auto-on, return auto-off - return 1 - - return val + return cur_state //leave unchanged // damage and destruction acts /obj/machinery/power/apc/emp_act(severity) + // Fail for 8-12 minutes (divided by severity) + // Division by 2 is required, because machinery ticks are every two seconds. Without it we would fail for 16-24 minutes. if(is_critical) - severity += 2 - if(cell) - cell.emp_act(severity) + // Critical APCs are considered EMP shielded and will be offline only for about half minute. Prevents AIs being one-shot disabled by EMP strike. + // Critical APCs are also more resilient to cell corruption/power drain. + energy_fail(rand(240, 360) / severity / CRITICAL_APC_EMP_PROTECTION) + if(cell) + cell.emp_act(severity+2) + else + // Regular APCs fail for normal time. + energy_fail(rand(240, 360) / severity) + //Cells are partially shielded by the APC frame. + if(cell) + cell.emp_act(severity+1) - lighting = 0 - if(!is_critical) - equipment = 0 - environ = 0 - update() update_icon() - - spawn(600) - update_channels() - update() - update_icon() ..() /obj/machinery/power/apc/ex_act(severity) @@ -1219,6 +1256,33 @@ obj/machinery/power/apc/proc/autoset(var/val, var/on) update_icon() return 1 +/obj/machinery/power/apc/proc/reboot() + //reset various counters so that process() will start fresh + charging = initial(charging) + chargecount = initial(chargecount) + autoflag = initial(autoflag) + longtermpower = initial(longtermpower) + failure_timer = initial(failure_timer) + + //start with main breaker off, chargemode in the default state and all channels on auto upon reboot + operating = 0 + chargemode = initial(chargemode) + power_alarm.clearAlarm(loc, src) + + lighting = POWERCHAN_ON_AUTO + equipment = POWERCHAN_ON_AUTO + environ = POWERCHAN_ON_AUTO + + //If malf AI had this APC before, they don't now. + if(hacker && hacker.hacked_apcs && (src in hacker.hacked_apcs)) + hacker.hacked_apcs -= src + hacker = null + + emagged = initial(emagged) //Resets emagging, too. + + update_icon() + update() + /obj/machinery/power/apc/overload(var/obj/machinery/power/source) if(is_critical) return diff --git a/nano/templates/apc.tmpl b/nano/templates/apc.tmpl index 3cce2edd48e..b77b024c8f5 100644 --- a/nano/templates/apc.tmpl +++ b/nano/templates/apc.tmpl @@ -1,3 +1,24 @@ +{{if data.gridCheck}} +
+

SYSTEM FAILURE

+ Power surge detected, grid check in effect...
+
+{{else data.failTime}} +
+

SYSTEM FAILURE

+ I/O regulators malfunction detected! Waiting for system reboot...
+ Automatic reboot in {{:data.failTime}} seconds...
+ {{if !data.siliconUser}} + {{if data.locked}} + Swipe an ID card for manual reboot.


+ {{else}} + {{:helper.link('Reboot Now', 'refresh', {'reboot' : 1})}}


+ {{/if}} + {{else}} + {{:helper.link('Reboot Now', 'refresh', {'reboot' : 1})}}


+ {{/if}} +
+{{else}}
{{if data.siliconUser}}
@@ -8,7 +29,10 @@
{{else}} - {{if data.locked}} + {{if data.emagged}} +

Fault in ID authenticator

+ Please contact maintenance for service. + {{else data.locked}} Swipe an ID card to unlock this interface {{else}} Swipe an ID card to lock this interface @@ -178,4 +202,4 @@ {{/if}}
- \ No newline at end of file +{{/if}} \ No newline at end of file