Powernet rework

This commit is contained in:
Markolie
2015-07-31 23:59:41 +02:00
parent 267a95c327
commit 51035f931e
57 changed files with 1711 additions and 1431 deletions
+1 -1
View File
@@ -1139,7 +1139,7 @@ But you can call procs that are of type /mob/living/carbon/human/proc/ for that
for(var/obj/machinery/power/smes/SMES in world)
if(SMES.anchored)
SMES.chargemode = 1
SMES.input_attempt = 1
/client/proc/cmd_debug_mob_lists()
set category = "Debug"
+1 -1
View File
@@ -18,7 +18,7 @@
var/delay = 0
var/datum/radio_frequency/radio_connection
var/airlock_wire = null
New()
..()
if(!radio_controller)
+186 -190
View File
@@ -54,7 +54,7 @@
var/areastring = null
var/obj/item/weapon/stock_parts/cell/cell
var/start_charge = 90 // initial cell charge %
var/cell_type = 2500 // 0=no cell, 1=regular, 2=high-cap (x5) <- old, now it's just 0=no cell, otherwise dictate cellcapacity by changing this value. 1 used to be 1000, 2 was 2500
var/cell_type = 2500
var/opened = 0 //0=closed, 1=opened, 2=cover removed
var/shorted = 0
var/lighting = 3
@@ -84,12 +84,13 @@
var/has_electronics = 0 // 0 - none, 1 - plugged in, 2 - secured by screwdriver
var/overload = 1 //used for the Blackout malf module
var/beenhit = 0 // used for counting how many times it has been hit, used for Aliens at the moment
var/mob/living/silicon/ai/occupant = null
var/mob/living/silicon/ai/occupier = null
var/longtermpower = 10
var/update_state = -1
var/update_overlay = -1
var/global/status_overlays = 0
var/updating_icon = 0
var/standard_max_charge
var/datum/wires/apc/wires = null
//var/debug = 0
var/global/list/status_overlays_lock
@@ -99,14 +100,21 @@
var/global/list/status_overlays_environ
var/indestructible = 0 // If set, prevents aliens from destroying it
/obj/machinery/power/apc/updateDialog()
if (stat & (BROKEN|MAINT))
return
..()
/obj/machinery/power/apc/connect_to_network()
//Override because the APC does not directly connect to the network; it goes through a terminal.
//The terminal is what the power computer looks for anyway.
if(!terminal)
make_terminal()
if(terminal)
terminal.connect_to_network()
/obj/machinery/power/apc/New(turf/loc, var/ndir, var/building=0)
..()
wires = new(src)
var/tmp/obj/item/weapon/stock_parts/cell/tmp_cell = new
standard_max_charge = tmp_cell.maxcharge
qdel(tmp_cell)
// offset 24 pixels in direction of dir
// this allows the APC to be embedded in a wall, yet still inside an area
if (building)
@@ -128,8 +136,24 @@
src.update_icon()
spawn(5)
src.update()
/obj/machinery/power/apc/Destroy()
if(malfai && operating)
if (ticker.mode.config_tag == "malfunction")
if (src.z == 1) //if (is_type_in_list(get_area(src), the_station_areas))
ticker.mode:apcs--
area.power_light = 0
area.power_equip = 0
area.power_environ = 0
area.power_change()
if(occupier)
malfvacate(1)
qdel(wires)
if(cell)
qdel(cell) // qdel
if(terminal)
disconnect_terminal()
..()
/obj/machinery/power/apc/proc/make_terminal()
// create a terminal object at the same position as original turf loc
@@ -269,7 +293,7 @@
if(update & 2)
if(overlays.len)
overlays = 0
overlays.len = 0
if(!(stat & (BROKEN|MAINT)) && update_state & UPSTATE_ALLGOOD)
overlays += status_overlays_lock[locked+1]
@@ -342,10 +366,11 @@
return 0
if(last_update_state != update_state)
results += 1
if(last_update_overlay != update_overlay && update_overlay != 0)
if(last_update_overlay != update_overlay)
results += 2
return results
// Used in process so it doesn't update the icon too much
/obj/machinery/power/apc/proc/queue_icon_update()
if(!updating_icon)
@@ -372,29 +397,30 @@
if (istype(W, /obj/item/weapon/crowbar) && opened)
if (has_electronics==1)
if (terminal)
user << "\red Disconnect wires first."
user << "<span class='warning'>Disconnect wires first.</span>"
return
playsound(src.loc, 'sound/items/Crowbar.ogg', 50, 1)
user << "You are trying to remove the power control board..." //lpeters - fixed grammar issues
if(do_after(user, 50))
has_electronics = 0
if ((stat & BROKEN) || malfhack)
user.visible_message(\
"\red [user.name] has broken the power control board inside [src.name]!",\
"You broke the charred power control board and remove the remains.",
"You hear a crack!")
//ticker.mode:apcs-- //XSI said no and I agreed. -rastaf0
else
user.visible_message(\
"\red [user.name] has removed the power control board from [src.name]!",\
"You remove the power control board.")
new /obj/item/weapon/module/power_control(loc)
if (has_electronics==1)
has_electronics = 0
if ((stat & BROKEN) || malfhack)
user.visible_message(\
"<span class='warning'>[user.name] has broken the power control board inside [src.name]!</span>",\
"<span class='notice'>You broke the charred power control board and remove the remains.</span>",
"You hear a crack!")
//ticker.mode:apcs-- //XSI said no and I agreed. -rastaf0
else
user.visible_message(\
"<span class='warning'>[user.name] has removed the power control board from [src.name]!</span>",\
"<span class='notice'>You remove the power control board.</span>")
new /obj/item/weapon/module/power_control(loc)
else if (opened!=2) //cover isn't removed
opened = 0
update_icon()
else if (istype(W, /obj/item/weapon/crowbar) && !((stat & BROKEN) || malfhack) )
if(coverlocked && !(stat & MAINT))
user << "\red The cover is locked and cannot be opened."
user << "<span class='warning'>The cover is locked and cannot be opened.</span>"
return
else
opened = 1
@@ -405,20 +431,20 @@
return
else
if (stat & MAINT)
user << "\red There is no connector for your power cell."
user << "<span class='warning'>There is no connector for your power cell.</span>"
return
user.drop_item()
W.loc = src
cell = W
user.visible_message(\
"\red [user.name] has inserted the power cell to [src.name]!",\
"<span class='warning'>[user.name] has inserted the power cell to [src.name]!</span>",\
"You insert the power cell.")
chargecount = 0
update_icon()
else if (istype(W, /obj/item/weapon/screwdriver)) // haxing
if(opened)
if (cell)
user << "\red Close the APC first." //Less hints more mystery!
user << "<span class='warning'>Close the APC first.</span>" //Less hints more mystery!
return
else
if (has_electronics==1 && terminal)
@@ -432,7 +458,7 @@
playsound(src.loc, 'sound/items/Screwdriver.ogg', 50, 1)
user << "You unfasten the electronics."
else /* has_electronics==0 */
user << "\red There is nothing to secure."
user << "<span class='warning'>There is nothing to secure.</span>"
return
update_icon()
else if(emagged)
@@ -457,87 +483,90 @@
user << "You [ locked ? "lock" : "unlock"] the APC interface."
update_icon()
else
user << "\red Access denied."
user << "<span class='warning'>Access denied.</span>"
else if (istype(W, /obj/item/stack/cable_coil) && !terminal && opened && has_electronics!=2)
if (src.loc:intact)
user << "\red You must remove the floor plating in front of the APC first."
user << "<span class='warning'>You must remove the floor plating in front of the APC first.</span>"
return
var/obj/item/stack/cable_coil/C = W
if(C.amount < 10)
user << "\red You need more wires."
user << "<span class='warning'>You need more wires.</span>"
return
user << "You start adding cables to the APC frame..."
playsound(src.loc, 'sound/items/Deconstruct.ogg', 50, 1)
if(do_after(user, 20) && C.amount >= 10)
var/turf/T = get_turf(src)
var/obj/structure/cable/N = T.get_cable_node()
if (prob(50) && electrocute_mob(usr, N, N))
var/datum/effect/effect/system/spark_spread/s = new /datum/effect/effect/system/spark_spread
s.set_up(5, 1, src)
s.start()
return
C.use(10)
user.visible_message(\
"\red [user.name] has added cables to the APC frame!",\
"You add cables to the APC frame.")
make_terminal()
terminal.connect_to_network()
if(do_after(user, 20))
if (C.amount >= 10 && !terminal && opened && has_electronics != 2)
var/turf/T = get_turf(src)
var/obj/structure/cable/N = T.get_cable_node()
if (prob(50) && electrocute_mob(usr, N, N))
var/datum/effect/effect/system/spark_spread/s = new /datum/effect/effect/system/spark_spread
s.set_up(5, 1, src)
s.start()
return
C.use(10)
user.visible_message(\
"<span class='warning'>[user.name] has added cables to the APC frame!</span>",\
"You add cables to the APC frame.")
make_terminal()
terminal.connect_to_network()
else if (istype(W, /obj/item/weapon/wirecutters) && terminal && opened && has_electronics!=2)
if (src.loc:intact)
user << "\red You must remove the floor plating in front of the APC first."
user << "<span class='warning'>You must remove the floor plating in front of the APC first.</span>"
return
user << "You begin to cut the cables..."
playsound(src.loc, 'sound/items/Deconstruct.ogg', 50, 1)
if(do_after(user, 50))
if (prob(50) && electrocute_mob(usr, terminal.powernet, terminal))
var/datum/effect/effect/system/spark_spread/s = new /datum/effect/effect/system/spark_spread
s.set_up(5, 1, src)
s.start()
return
new /obj/item/stack/cable_coil(loc,10)
user.visible_message(\
"\red [user.name] cut the cables and dismantled the power terminal.",\
"You cut the cables and dismantle the power terminal.")
qdel(terminal)
if(terminal && opened && has_electronics!=2)
if (prob(50) && electrocute_mob(usr, terminal.powernet, terminal))
var/datum/effect/effect/system/spark_spread/s = new /datum/effect/effect/system/spark_spread
s.set_up(5, 1, src)
s.start()
return
new /obj/item/stack/cable_coil(loc,10)
user << "<span class='notice'>You cut the cables and dismantle the power terminal.</span>"
qdel(terminal) // qdel
else if (istype(W, /obj/item/weapon/module/power_control) && opened && has_electronics==0 && !((stat & BROKEN) || malfhack))
user << "You trying to insert the power control board into the frame..."
playsound(src.loc, 'sound/items/Deconstruct.ogg', 50, 1)
if(do_after(user, 10))
has_electronics = 1
user << "You place the power control board inside the frame."
qdel(W)
if(has_electronics==0)
has_electronics = 1
user << "<span class='notice'>You place the power control board inside the frame.</span>"
qdel(W) // qdel
else if (istype(W, /obj/item/weapon/module/power_control) && opened && has_electronics==0 && ((stat & BROKEN) || malfhack))
user << "\red You cannot put the board inside, the frame is damaged."
user << "<span class='warning'>You cannot put the board inside, the frame is damaged.</span>"
return
else if (istype(W, /obj/item/weapon/weldingtool) && opened && has_electronics==0 && !terminal)
var/obj/item/weapon/weldingtool/WT = W
if (WT.get_fuel() < 3)
user << "\blue You need more welding fuel to complete this task."
user << "<span class='warning'>You need more welding fuel to complete this task.</span>"
return
user << "You start welding the APC frame..."
user.visible_message("<span class='warning'>[user.name] welds [src].</span>", \
"You start welding the APC frame...", \
"You hear welding.")
playsound(src.loc, 'sound/items/Welder.ogg', 50, 1)
if(do_after(user, 50))
if(!src || !WT.remove_fuel(3, user)) return
if (emagged || malfhack || (stat & BROKEN) || opened==2)
new /obj/item/stack/sheet/metal(loc)
user.visible_message(\
"\red [src] has been cut apart by [user.name] with the weldingtool.",\
"You disassembled the broken APC frame.",\
"\red You hear welding.")
"<span class='warning'>[src] has been cut apart by [user.name] with the weldingtool.</span>",\
"<span class='notice'>You disassembled the broken APC frame.</span>",\
"You hear welding.")
else
new /obj/item/mounted/frame/apc_frame(loc)
user.visible_message(\
"\red [src] has been cut from the wall by [user.name] with the weldingtool.",\
"You cut the APC frame from the wall.",\
"\red You hear welding.")
qdel(src)
"<span class='warning'>[src] has been cut from the wall by [user.name] with the weldingtool.</span>",\
"<span class='notice'>You cut the APC frame from the wall.</span>",\
"You hear welding.")
qdel(src) // qdel
return
else if (istype(W, /obj/item/mounted/frame/apc_frame) && opened && emagged)
emagged = 0
if (opened==2)
opened = 1
user.visible_message(\
"\red [user.name] has replaced the damaged APC frontal panel with a new one.",\
"<span class='warning'>[user.name] has replaced the damaged APC frontal panel with a new one.</span>",\
"You replace the damaged APC frontal panel with a new one.")
qdel(W)
update_icon()
@@ -548,7 +577,7 @@
user << "You begin to replace the damaged APC frame..."
if(do_after(user, 50))
user.visible_message(\
"\red [user.name] has replaced the damaged APC frame with new one.",\
"<span class='notice'>[user.name] has replaced the damaged APC frame with new one.</span>",\
"You replace the damaged APC frame with new one.")
qdel(W)
stat &= ~BROKEN
@@ -566,8 +595,8 @@
) \
&& prob(20) )
opened = 2
user.visible_message("\red The APC cover was knocked down with the [W.name] by [user.name]!", \
"\red You knock down the APC cover with your [W.name]!", \
user.visible_message("<span class='danger'>The APC cover was knocked down with the [W.name] by [user.name]!</span>", \
"<span class='danger'>You knock down the APC cover with your [W.name]!</span>", \
"You hear bang")
update_icon()
else
@@ -578,8 +607,8 @@
istype(W, /obj/item/weapon/wirecutters) || istype(W, /obj/item/device/assembly/signaler)))
return src.attack_hand(user)
user.do_attack_animation(src)
user.visible_message("\red The [src.name] has been hit with the [W.name] by [user.name]!", \
"\red You hit the [src.name] with your [W.name]!", \
user.visible_message("<span class='warning'>The [src.name] has been hit with the [W.name] by [user.name]!</span>", \
"<span class='warning'>You hit the [src.name] with your [W.name]!</span>", \
"You hear bang")
/obj/machinery/power/apc/emag_act(user as mob)
@@ -612,7 +641,7 @@
var/datum/effect/effect/system/spark_spread/s = new /datum/effect/effect/system/spark_spread
s.set_up(3, 1, src)
s.start()
H << "\red The APC power currents surge eratically, damaging your chassis!"
H << "<span class='warning'>The APC power currents surge eratically, damaging your chassis!</span>"
H.adjustFireLoss(10,0)
else if(src.cell && src.cell.charge > 0)
if(H.nutrition < 450)
@@ -624,13 +653,13 @@
H.nutrition += src.cell.charge/10
src.cell.charge = 0
user << "\blue You slot your fingers into the APC interface and siphon off some of the stored charge for your own use."
user << "<span class='notice'>You slot your fingers into the APC interface and siphon off some of the stored charge for your own use.</span>"
if(src.cell.charge < 0) src.cell.charge = 0
if(H.nutrition > 500) H.nutrition = 500
src.charging = 1
else
user << "\blue You are already fully charged."
user << "<span class='notice'>You are already fully charged.</span>"
else
user << "There is no charge to draw from that APC."
return
@@ -645,7 +674,7 @@
cell.updateicon()
src.cell = null
user.visible_message("\red [user.name] removes the power cell from [src.name]!", "You remove the power cell.")
user.visible_message("<span class='warning'>[user.name] removes the power cell from [src.name]!", "You remove the power cell.</span>")
//user << "You remove the power cell."
charging = 0
src.update_icon()
@@ -664,7 +693,7 @@
return
user.changeNext_move(CLICK_CD_MELEE)
user.do_attack_animation(src)
user.visible_message("\red [user.name] slashes at the [src.name]!", "\blue You slash at the [src.name]!")
user.visible_message("<span class='warning'>[user.name] slashes at the [src.name]!", "<span class='notice'>You slash at the [src.name]!</span></span>")
playsound(src.loc, 'sound/weapons/slash.ogg', 100, 1)
var/allcut = wires.IsAllCut()
@@ -672,12 +701,12 @@
if(beenhit >= pick(3, 4) && wiresexposed != 1)
wiresexposed = 1
src.update_icon()
src.visible_message("\red The [src.name]'s cover flies open, exposing the wires!")
src.visible_message("<span class='warning'>The [src.name]'s cover flies open, exposing the wires!</span>")
else if(wiresexposed == 1 && allcut == 0)
wires.CutAll()
src.update_icon()
src.visible_message("\red The [src.name]'s wires are shredded!")
src.visible_message("<span class='warning'>The [src.name]'s wires are shredded!</span>")
else
beenhit += 1
return
@@ -700,7 +729,7 @@
/obj/machinery/power/apc/proc/get_malf_status(mob/user)
if (ticker && ticker.mode && (user.mind in ticker.mode.malf_ai) && istype(user, /mob/living/silicon/ai))
if (src.malfai == (user:parent ? user:parent : user))
if (src.occupant == user)
if (src.occupier == user)
return 3 // 3 = User is shunted in this APC
else if (istype(user.loc, /obj/machinery/power/apc))
return 4 // 4 = User is shunted in another APC
@@ -801,7 +830,7 @@
/obj/machinery/power/apc/proc/can_use(mob/user as mob, var/loud = 0) //used by attack_hand() and Topic()
if (user.stat && !isobserver(user))
user << "\red You must be conscious to use this [src]!"
user << "<span class='warning'>You must be conscious to use this [src]!</span>"
return 0
if(stat & (NOPOWER|BROKEN))
return 0
@@ -811,13 +840,13 @@
return 0
if ( ! (istype(user, /mob/living/carbon/human) || \
istype(user, /mob/living/silicon)))
user << "\red You don't have the dexterity to use this [src]!"
user << "<span class='warning'>You don't have the dexterity to use this [src]!</span>"
return 0
if(user.restrained())
user << "\red You must have free hands to use this [src]"
user << "<span class='warning'>You must have free hands to use this [src]</span>"
return 0
if(user.lying)
user << "\red You must stand to use this [src]!"
user << "<span class='warning'>You must stand to use this [src]!</span>"
return 0
autoflag = 5
if (istype(user, /mob/living/silicon))
@@ -832,7 +861,7 @@
) \
)
if(!loud)
user << "\red \The [src] has AI control disabled!"
user << "<span class='danger'>\The [src] has AI control disabled!</span>"
user << browse(null, "window=apc")
user.unset_machine()
return 0
@@ -844,10 +873,10 @@
if (istype(H))
if(H.getBrainLoss() >= 60)
for(var/mob/M in viewers(src, null))
M << "\red [H] stares cluelessly at [src] and drools."
M << "<span class='danger'>[H] stares cluelessly at [src] and drools.</span>"
return 0
else if(prob(H.getBrainLoss()))
user << "\red You momentarily forget how to use [src]."
user << "<span class='danger'>You momentarily forget how to use [src].</span>"
return 0
return 1
@@ -989,34 +1018,34 @@
return
if(!(src.z in config.station_levels))
return
src.occupant = new /mob/living/silicon/ai(src,malf.laws,null,1)
src.occupant.adjustOxyLoss(malf.getOxyLoss())
if(!findtext(src.occupant.name,"APC Copy"))
src.occupant.name = "[malf.name] APC Copy"
src.occupier = new /mob/living/silicon/ai(src,malf.laws,null,1)
src.occupier.adjustOxyLoss(malf.getOxyLoss())
if(!findtext(src.occupier.name,"APC Copy"))
src.occupier.name = "[malf.name] APC Copy"
if(malf.parent)
src.occupant.parent = malf.parent
src.occupier.parent = malf.parent
else
src.occupant.parent = malf
malf.mind.transfer_to(src.occupant)
src.occupant.eyeobj.name = "[src.occupant.name] (AI Eye)"
src.occupier.parent = malf
malf.mind.transfer_to(src.occupier)
src.occupier.eyeobj.name = "[src.occupier.name] (AI Eye)"
if(malf.parent)
qdel(malf)
src.occupant.verbs += /mob/living/silicon/ai/proc/corereturn
src.occupant.verbs += /datum/game_mode/malfunction/proc/takeover
src.occupant.cancel_camera()
src.occupier.verbs += /mob/living/silicon/ai/proc/corereturn
src.occupier.verbs += /datum/game_mode/malfunction/proc/takeover
src.occupier.cancel_camera()
if (seclevel2num(get_security_level()) == SEC_LEVEL_DELTA)
for(var/obj/item/weapon/pinpointer/point in world)
point.the_disk = src //the pinpointer will detect the shunted AI
/obj/machinery/power/apc/proc/malfvacate(var/forced)
if(!src.occupant)
if(!src.occupier)
return
if(src.occupant.parent && src.occupant.parent.stat != 2)
src.occupant.mind.transfer_to(src.occupant.parent)
src.occupant.parent.adjustOxyLoss(src.occupant.getOxyLoss())
src.occupant.parent.cancel_camera()
qdel(src.occupant)
if(src.occupier.parent && src.occupier.parent.stat != 2)
src.occupier.mind.transfer_to(src.occupier.parent)
src.occupier.parent.adjustOxyLoss(src.occupier.getOxyLoss())
src.occupier.parent.cancel_camera()
del(src.occupier) // qdel
if (seclevel2num(get_security_level()) == SEC_LEVEL_DELTA)
for(var/obj/item/weapon/pinpointer/point in world)
for(var/datum/mind/AI_mind in ticker.mode.malf_ai)
@@ -1025,11 +1054,11 @@
point.the_disk = A //The pinpointer tracks the AI back into its core.
else
src.occupant << "\red Primary core damaged, unable to return core processes."
src.occupier << "<span class='danger'>Primary core damaged, unable to return core processes.</span>"
if(forced)
src.occupant.loc = src.loc
src.occupant.death()
src.occupant.gib()
src.occupier.loc = src.loc
src.occupier.death()
src.occupier.gib()
for(var/obj/item/weapon/pinpointer/point in world)
point.the_disk = null //the pinpointer will go back to pointing at the nuke disc.
@@ -1040,7 +1069,7 @@
if(prob(3))
src.locked = 1
if (src.cell.charge > 0)
// world << "\red blew APC in [src.loc.loc]"
// world << "<span class='warning'>blew APC in [src.loc.loc]</span>"
src.cell.charge = 0
cell.corrupt()
src.malfhack = 1
@@ -1053,7 +1082,7 @@
s.set_up(3, 1, src)
s.start()
for(var/mob/M in viewers(src))
M.show_message("\red The [src.name] suddenly lets out a blast of smoke and some sparks!", 3, "\red You hear sizzling electronics.", 2)
M.show_message("<span class='danger'>The [src.name] suddenly lets out a blast of smoke and some sparks!", 3, "<span class='danger'>You hear sizzling electronics.</span>", 2)
/obj/machinery/power/apc/surplus()
@@ -1062,9 +1091,14 @@
else
return 0
/obj/machinery/power/apc/add_load(var/amount)
//Returns 1 if the APC should attempt to charge
/obj/machinery/power/apc/proc/attempt_charging()
return (chargemode && charging == 1 && operating)
/obj/machinery/power/apc/draw_power(var/amount)
if(terminal && terminal.powernet)
terminal.powernet.load += amount
return terminal.powernet.draw_power(amount)
return 0
/obj/machinery/power/apc/avail()
if(terminal)
@@ -1082,8 +1116,7 @@
lastused_light = area.usage(LIGHT)
lastused_equip = area.usage(EQUIP)
lastused_environ = area.usage(ENVIRON)
if(area.powerupdate)
area.clear_usage()
area.clear_usage()
lastused_total = lastused_light + lastused_equip + lastused_environ
@@ -1102,33 +1135,24 @@
else
main_status = 2
//if(debug)
//world << "Status: [main_status] - Excess: [excess] - Last Equip: [lastused_equip] - Last Light: [lastused_light]"
if(debug)
log_debug("Status: [main_status] - Excess: [excess] - Last Equip: [lastused_equip] - Last Light: [lastused_light] - Longterm: [longtermpower]")
if(cell && !shorted)
var/cell_charge = cell.charge
var/cell_maxcharge = cell.maxcharge
// draw power from cell as before to power the area
var/cellused = min(cell_charge, CELLRATE * lastused_total) // clamp deduction to a max, amount left in cell
var/cellused = min(cell.charge, CELLRATE * lastused_total) // clamp deduction to a max, amount left in cell
cell.use(cellused)
if(excess > lastused_total) // if power excess recharge the cell
// by the same amount just used
cell.give(cellused)
add_load(cellused/CELLRATE) // add the load used to recharge the cell
// by the same amount just used
var/draw = draw_power(cellused/CELLRATE) // draw the power needed to charge this cell
cell.give(draw * CELLRATE)
else // no excess, and not enough per-apc
if( (cell_charge/CELLRATE + excess) >= lastused_total) // can we draw enough from cell+grid to cover last usage?
cell_charge = min(cell_maxcharge, cell_charge + CELLRATE * excess) //recharge with what we can
add_load(excess) // so draw what we can from the grid
if( (cell.charge/CELLRATE + excess) >= lastused_total) // can we draw enough from cell+grid to cover last usage?
var/draw = draw_power(excess)
cell.charge = min(cell.maxcharge, cell.charge + CELLRATE * draw) //recharge with what we can
charging = 0
else if (autoflag != 0) // not enough power available to run the last tick!
else // not enough power available to run the last tick!
charging = 0
chargecount = 0
// This turns everything off in the case that there is still a charge left on the battery, just not enough to run the room.
@@ -1138,7 +1162,7 @@
autoflag = 0
// set channels depending on how much charge we have left
// Set channels depending on how much charge we have left
// Allow the APC to operate as normal if the cell can charge
if(charging && longtermpower < 10)
@@ -1146,31 +1170,30 @@
else if(longtermpower > -10)
longtermpower -= 2
if(cell_charge >= 1250 || longtermpower > 0) // Put most likely at the top so we don't check it last, effeciency 101
if(cell.charge >= 1250 || longtermpower > 0) // Put most likely at the top so we don't check it last, effeciency 101
if(autoflag != 3)
equipment = autoset(equipment, 1)
lighting = autoset(lighting, 1)
environ = autoset(environ, 1)
autoflag = 3
area.poweralert(1, src)
if(cell_charge >= 4000)
if(cell.charge >= 4000)
area.poweralert(1, src)
else if(cell_charge < 1250 && cell_charge > 750 && longtermpower < 0) // <30%, turn off equipment
else if(cell.charge < 1250 && cell.charge > 750 && longtermpower < 0) // <30%, turn off equipment
if(autoflag != 2)
equipment = autoset(equipment, 2)
lighting = autoset(lighting, 1)
environ = autoset(environ, 1)
area.poweralert(0, src)
autoflag = 2
else if(cell_charge < 750 && cell_charge > 10 && longtermpower < 0) // <15%, turn off lighting & equipment
if(autoflag != 1)
else if(cell.charge < 750 && cell.charge > 10) // <15%, turn off lighting & equipment
if((autoflag > 1 && longtermpower < 0) || (autoflag > 1 && longtermpower >= 0))
equipment = autoset(equipment, 2)
lighting = autoset(lighting, 2)
environ = autoset(environ, 1)
area.poweralert(0, src)
autoflag = 1
else if(cell_charge <= 0) // zero charge, turn all off
else if(cell.charge <= 0) // zero charge, turn all off
if(autoflag != 0)
equipment = autoset(equipment, 0)
lighting = autoset(lighting, 0)
@@ -1180,32 +1203,31 @@
// now trickle-charge the cell
if(chargemode && charging == 1 && operating)
if(src.attempt_charging())
if(excess > 0) // check to make sure we have enough to charge
// Max charge is capped to % per second constant
var/ch = min(excess*CELLRATE, cell.maxcharge*CHARGELEVEL)
add_load(ch/CELLRATE) // Removes the power we're taking from the grid
cell.give(ch) // actually recharge the cell
ch = draw_power(ch/CELLRATE) // Removes the power we're taking from the grid
cell.give(ch*CELLRATE) // actually recharge the cell
else
charging = 0 // stop charging
chargecount = 0
// show cell as fully charged if so
if(cell.charge >= cell.maxcharge)
cell.charge = cell.maxcharge
charging = 2
if(chargemode)
if(!charging)
if(excess > cell_maxcharge*CHARGELEVEL)
if(excess > cell.maxcharge*CHARGELEVEL)
chargecount++
else
chargecount = 0
charging = 0
if(chargecount == 10)
if(chargecount >= 10)
chargecount = 0
charging = 1
@@ -1224,18 +1246,15 @@
area.poweralert(0, src)
autoflag = 0
// update icon & area power if anything changed
if(last_lt != lighting || last_eq != equipment || last_en != environ)
queue_icon_update()
update()
else if (last_ch != charging)
queue_icon_update()
// val 0=off, 1=off(auto) 2=on 3=on(auto)
// on 0=off, 1=on, 2=autooff
obj/machinery/power/apc/proc/autoset(var/val, var/on)
/obj/machinery/power/apc/proc/autoset(var/val, var/on)
if(on==0)
if(val==2) // if on, return off
return 0
@@ -1251,14 +1270,14 @@ obj/machinery/power/apc/proc/autoset(var/val, var/on)
return 1
return val
// damage and destruction acts
/obj/machinery/power/apc/emp_act(severity)
if(cell)
cell.emp_act(severity)
if(occupant)
occupant.emp_act(severity)
if(occupier)
occupier.emp_act(severity)
lighting = 0
equipment = 0
environ = 0
@@ -1293,6 +1312,12 @@ obj/machinery/power/apc/proc/autoset(var/val, var/on)
set_broken()
if (cell && prob(5))
cell.blob_act()
/obj/machinery/power/apc/disconnect_terminal()
if(terminal)
terminal.master = null
terminal = null
/obj/machinery/power/apc/proc/set_broken()
if(malfai && operating)
@@ -1301,7 +1326,7 @@ obj/machinery/power/apc/proc/autoset(var/val, var/on)
ticker.mode:apcs--
stat |= BROKEN
operating = 0
if(occupant)
if(occupier)
malfvacate(1)
update_icon()
update()
@@ -1320,35 +1345,6 @@ obj/machinery/power/apc/proc/autoset(var/val, var/on)
L.broken()
sleep(1)
/obj/machinery/power/apc/Destroy()
if(malfai && operating)
if (ticker.mode.config_tag == "malfunction")
if ((src.z in config.station_levels)) //if (is_type_in_list(get_area(src), the_station_areas))
ticker.mode:apcs--
area.power_light = 0
area.power_equip = 0
area.power_environ = 0
area.power_change()
if(occupant)
malfvacate(1)
qdel(wires)
if(cell)
qdel(cell)
return ..()
/obj/machinery/power/apc/proc/shock(mob/user, prb)
if(!prob(prb))
return 0
var/datum/effect/effect/system/spark_spread/s = new /datum/effect/effect/system/spark_spread
s.set_up(5, 1, src)
s.start()
if(isalien(user))
return 0
if (electrocute_mob(user, src, src))
return 1
else
return 0
/obj/machinery/power/apc/proc/setsubsystem(val)
if(cell && cell.charge > 0)
return (val==1) ? 0 : val
File diff suppressed because it is too large Load Diff
+176 -301
View File
@@ -1,26 +1,37 @@
//////////////////////////////
// POWER MACHINERY BASE CLASS
//////////////////////////////
/////////////////////////////
// Definitions
/////////////////////////////
/obj/machinery/power
name = null
icon = 'icons/obj/power.dmi'
anchored = 1.0
var/datum/powernet/powernet = null
var/directwired = 1 // by default, power machines are connected by a cable in a neighbouring turf
// if set to 0, requires a 0-X cable on this turf
use_power = 0
idle_power_usage = 0
active_power_usage = 0
/obj/machinery/power/Destroy()
/obj/machinery/power/Del()
disconnect_from_network()
return ..()
..()
///////////////////////////////
// General procedures
//////////////////////////////
// common helper procs for all power machines
/obj/machinery/power/proc/add_avail(var/amount)
if(powernet)
powernet.newavail += amount
/obj/machinery/power/proc/add_load(var/amount)
/obj/machinery/power/proc/draw_power(var/amount)
if(powernet)
powernet.load += amount
return powernet.draw_power(amount)
return 0
/obj/machinery/power/proc/surplus()
if(powernet)
@@ -34,17 +45,16 @@
else
return 0
/obj/machinery/power/proc/disconnect_terminal() // machines without a terminal will just return, no harm no fowl.
return
// returns true if the area has power on given channel (or doesn't require power).
// defaults to power_channel
/obj/machinery/proc/powered(var/chan = -1)
/obj/machinery/proc/powered(var/chan = -1) // defaults to power_channel
if(!src.loc)
return 0
if(!use_power)
return 1
var/area/A = src.loc.loc // make sure it's in an area
if(!A || !isarea(A))
return 0 // if not, then not powered
@@ -71,94 +81,63 @@
stat |= NOPOWER
return
// connect the machine to a powernet if a node cable is present on the turf
/obj/machinery/power/proc/connect_to_network()
var/turf/T = src.loc
if(!T || !istype(T))
return 0
// the powernet datum
// each contiguous network of cables & nodes
// rebuild all power networks from scratch
/hook/startup/proc/buildPowernets()
return makepowernets()
/proc/makepowernets()
for(var/datum/powernet/PN in powernets)
qdel(PN)
powernets.Cut()
for(var/obj/structure/cable/PC in cable_list)
if(!PC.powernet)
PC.powernet = new()
powernets += PC.powernet
// if(Debug) world.log << "Starting mpn at [PC.x],[PC.y] ([PC.d1]/[PC.d2])"
powernet_nextlink(PC,PC.powernet)
// if(Debug) world.log << "[powernets.len] powernets found"
for(var/obj/structure/cable/C in cable_list)
if(!C.powernet) continue
C.powernet.cables += C
for(var/obj/machinery/power/M in machines)
if(!M.powernet) continue // APCs have powernet=0 so they don't count as network nodes directly
M.powernet.nodes[M] = M
var/obj/structure/cable/C = T.get_cable_node() //check if we have a node cable on the machine turf, the first found is picked
if(!C || !C.powernet)
return 0
C.powernet.add_machine(src)
return 1
// remove and disconnect the machine from its current powernet
/obj/machinery/power/proc/disconnect_from_network()
if(!powernet)
return 0
powernet.remove_machine(src)
return 1
// returns a list of all power-related objects (nodes, cable, junctions) in turf,
// excluding source, that match the direction d
// if unmarked==1, only return those with no powernet
/proc/power_list(var/turf/T, var/source, var/d, var/unmarked=0)
. = list()
var/fdir = (!d)? 0 : turn(d, 180) // the opposite direction to d (or 0 if d==0)
// world.log << "d=[d] fdir=[fdir]"
for(var/AM in T)
if(AM == source) continue //we don't want to return source
// attach a wire to a power machine - leads from the turf you are standing on
//almost never called, overwritten by all power machines but terminal and generator
/obj/machinery/power/attackby(obj/item/weapon/W, mob/user)
if(istype(AM,/obj/machinery/power))
var/obj/machinery/power/P = AM
if(P.powernet == 0) continue // exclude APCs which have powernet=0
if(istype(W, /obj/item/stack/cable_coil))
if(!unmarked || !P.powernet) //if unmarked=1 we only return things with no powernet
if(P.directwired || (d == 0))
. += P
var/obj/item/stack/cable_coil/coil = W
else if(istype(AM,/obj/structure/cable))
var/obj/structure/cable/C = AM
var/turf/T = user.loc
if(!unmarked || !C.powernet)
if(C.d1 == fdir || C.d2 == fdir)
. += C
else if(C.d1 == turn(C.d2, 180))
. += C
return .
if(T.intact || !istype(T, /turf/simulated/floor))
return
if(get_dist(src, user) > 1)
return
/obj/structure/cable/proc/get_connections()
. = list() // this will be a list of all connected power objects
var/turf/T = loc
if(d1) T = get_step(src, d1)
if(T) . += power_list(T, src, d1, 1)
T = get_step(src, d2)
if(T) . += power_list(T, src, d2, 1)
return .
coil.turf_place(T, user)
return
else
..()
return
///////////////////////////////////////////
// Powernet handling helpers
//////////////////////////////////////////
//returns all the cables WITHOUT a powernet in neighbors turfs,
//pointing towards the turf the machine is located at
/obj/machinery/power/proc/get_connections()
. = list()
if(!directwired)
return get_indirect_connections()
var/cdir
var/turf/T
for(var/card in cardinal)
var/turf/T = get_step(loc,card)
T = get_step(loc,card)
cdir = get_dir(T,loc)
for(var/obj/structure/cable/C in T)
@@ -167,193 +146,132 @@
. += C
return .
//returns all the cables in neighbors turfs,
//pointing towards the turf the machine is located at
/obj/machinery/power/proc/get_marked_connections()
. = list()
var/cdir
var/turf/T
for(var/card in cardinal)
T = get_step(loc,card)
cdir = get_dir(T,loc)
for(var/obj/structure/cable/C in T)
if(C.d1 == cdir || C.d2 == cdir)
. += C
return .
//returns all the NODES (O-X) cables WITHOUT a powernet in the turf the machine is located at
/obj/machinery/power/proc/get_indirect_connections()
. = list()
for(var/obj/structure/cable/C in loc)
if(C.powernet) continue
if(C.d1 == 0)
if(C.d1 == 0) // the cable is a node cable
. += C
return .
///////////////////////////////////////////
// GLOBAL PROCS for powernets handling
//////////////////////////////////////////
/proc/powernet_nextlink(var/obj/O, var/datum/powernet/PN)
var/list/P
while(1)
if( istype(O,/obj/structure/cable) )
var/obj/structure/cable/C = O
C.powernet = PN
P = C.get_connections()
// returns a list of all power-related objects (nodes, cable, junctions) in turf,
// excluding source, that match the direction d
// if unmarked==1, only return those with no powernet
/proc/power_list(var/turf/T, var/source, var/d, var/unmarked=0, var/cable_only = 0)
. = list()
var/fdir = (!d)? 0 : turn(d, 180) // the opposite direction to d (or 0 if d==0)
///// Z-Level Stuff
var/Zdir
if(d==11)
Zdir = 11
else if (d==12)
Zdir = 12
else
Zdir = 999
///// Z-Level Stuff
for(var/AM in T)
if(AM == source) continue //we don't want to return source
else if(O.anchored && istype(O,/obj/machinery/power))
var/obj/machinery/power/M = O
M.powernet = PN
P = M.get_connections()
if(!cable_only && istype(AM,/obj/machinery/power))
var/obj/machinery/power/P = AM
if(P.powernet == 0) continue // exclude APCs which have powernet=0
if(!unmarked || !P.powernet) //if unmarked=1 we only return things with no powernet
if(d == 0)
. += P
else if(istype(AM,/obj/structure/cable))
var/obj/structure/cable/C = AM
if(!unmarked || !C.powernet)
///// Z-Level Stuff
if(C.d1 == fdir || C.d2 == fdir || C.d1 == Zdir || C.d2 == Zdir)
///// Z-Level Stuff
. += C
else if(C.d1 == d || C.d2 == d)
. += C
return .
/hook/startup/proc/buildPowernets()
return makepowernets()
// rebuild all power networks from scratch - only called at world creation or by the admin verb
/proc/makepowernets()
for(var/datum/powernet/PN in powernets)
del(PN)
powernets.Cut()
for(var/obj/structure/cable/PC in cable_list)
if(!PC.powernet)
var/datum/powernet/NewPN = new()
NewPN.add_cable(PC)
propagate_network(PC,PC.powernet)
return 1
//remove the old powernet and replace it with a new one throughout the network.
/proc/propagate_network(var/obj/O, var/datum/powernet/PN)
//world.log << "propagating new network"
var/list/worklist = list()
var/list/found_machines = list()
var/index = 1
var/obj/P = null
worklist+=O //start propagating from the passed object
while(index<=worklist.len) //until we've exhausted all power objects
P = worklist[index] //get the next power object found
index++
if( istype(P,/obj/structure/cable))
var/obj/structure/cable/C = P
if(C.powernet != PN) //add it to the powernet, if it isn't already there
PN.add_cable(C)
worklist |= C.get_connections() //get adjacents power objects, with or without a powernet
else if(P.anchored && istype(P,/obj/machinery/power))
var/obj/machinery/power/M = P
found_machines |= M //we wait until the powernet is fully propagates to connect the machines
else
return
continue
if(P.len == 0) return
O = P[1]
for(var/L = 2 to P.len)
powernet_nextlink(P[L], PN)
//now that the powernet is set, connect found machines to it
for(var/obj/machinery/power/PM in found_machines)
if(!PM.connect_to_network()) //couldn't find a node on its turf...
PM.disconnect_from_network() //... so disconnect if already on a powernet
// cut a powernet at this cable object
/datum/powernet/proc/cut_cable(var/obj/structure/cable/C)
var/turf/T1 = C.loc
if(!T1) return
var/node = 0
if(C.d1 == 0)
node = 1
var/turf/T2
if(C.d2) T2 = get_step(T1, C.d2)
if(C.d1) T1 = get_step(T1, C.d1)
var/list/P1 = power_list(T1, C, C.d1) // what joins on to cut cable in dir1
var/list/P2 = power_list(T2, C, C.d2) // what joins on to cut cable in dir2
// if(Debug)
// for(var/obj/O in P1)
// world.log << "P1: [O] at [O.x] [O.y] : [istype(O, /obj/structure/cable) ? "[O:d1]/[O:d2]" : null] "
// for(var/obj/O in P2)
// world.log << "P2: [O] at [O.x] [O.y] : [istype(O, /obj/structure/cable) ? "[O:d1]/[O:d2]" : null] "
if(P1.len == 0 || P2.len == 0)//if nothing in either list, then the cable was an endpoint no need to rebuild the powernet,
cables -= C //just remove cut cable from the list
// if(Debug) world.log << "Was end of cable"
//Merge two powernets, the bigger (in cable length term) absorbing the other
/proc/merge_powernets(var/datum/powernet/net1, var/datum/powernet/net2)
if(!net1 || !net2) //if one of the powernet doesn't exist, return
return
//null the powernet reference of all cables & nodes in this powernet
var/i=1
while(i<=cables.len)
var/obj/structure/cable/Cable = cables[i]
if(Cable)
Cable.powernet = null
if(Cable == C)
cables.Cut(i,i+1)
continue
i++
i=1
while(i<=nodes.len)
var/obj/machinery/power/Node = nodes[i]
if(Node)
Node.powernet = null
i++
// remove the cut cable from the network
// C.netnum = -1
C.loc = null
powernet_nextlink(P1[1], src) // propagate network from 1st side of cable, using current netnum //TODO?
// now test to see if propagation reached to the other side
// if so, then there's a loop in the network
var/notlooped = 0
for(var/O in P2)
if( istype(O, /obj/machinery/power) )
var/obj/machinery/power/Machine = O
if(Machine.powernet != src)
notlooped = 1
break
else if( istype(O, /obj/structure/cable) )
var/obj/structure/cable/Cable = O
if(Cable.powernet != src)
notlooped = 1
break
if(notlooped)
// not looped, so make a new powernet
var/datum/powernet/PN = new()
powernets += PN
// if(Debug) world.log << "Was not looped: spliting PN#[number] ([cables.len];[nodes.len])"
i=1
while(i<=cables.len)
var/obj/structure/cable/Cable = cables[i]
if(Cable && !Cable.powernet) // non-connected cables will have powernet=null, since they weren't reached by propagation
Cable.powernet = PN
cables.Cut(i,i+1) // remove from old network & add to new one
PN.cables += Cable
continue
i++
i=1
while(i<=nodes.len)
var/obj/machinery/power/Node = nodes[i]
if(Node && !Node.powernet)
Node.powernet = PN
nodes.Cut(i,i+1)
PN.nodes[Node] = Node
continue
i++
// Disconnect machines connected to nodes
if(node)
for(var/obj/machinery/power/P in T1)
if(P.powernet && !P.powernet.nodes[src])
P.disconnect_from_network()
// if(Debug)
// world.log << "Old PN#[number] : ([cables.len];[nodes.len])"
// world.log << "New PN#[PN.number] : ([PN.cables.len];[PN.nodes.len])"
//
// else
// if(Debug)
// world.log << "Was looped."
// //there is a loop, so nothing to be done
// return
/datum/powernet/proc/reset()
//see if there's a surplus of power remaining in the powernet and stores unused power in the SMES
netexcess = avail - load
if(netexcess > 100 && nodes && nodes.len) // if there was excess power last cycle
for(var/obj/machinery/power/smes/S in nodes) // find the SMESes in the network
S.restore() // and restore some of the power that was used
//updates the viewed load (as seen on power computers)
viewload = 0.8*viewload + 0.2*load
viewload = round(viewload)
//reset the powernet
load = 0
avail = newavail
newavail = 0
/datum/powernet/proc/get_electrocute_damage()
switch(avail)
if (5000000 to INFINITY)
return min(rand(200,300),rand(200,300))
if (4000000 to 5000000)
return min(rand(80,180),rand(80,180))
if (1000000 to 4000000)
return min(rand(50,160),rand(50,160))
if (200000 to 1000000)
return min(rand(25,80),rand(25,80))
if (100000 to 200000)//Ave powernet
return min(rand(20,60),rand(20,60))
if (50000 to 100000)
return min(rand(15,40),rand(15,40))
if (1000 to 50000)
return min(rand(10,20),rand(10,20))
else
return 0
//The powernet that calls this proc will consume the other powernet - Rockdtben
//TODO: rewrite so the larger net absorbs the smaller net
/proc/merge_powernets(var/datum/powernet/net1, var/datum/powernet/net2)
if(!net1 || !net2) return
if(net1 == net2) return
if(net1 == net2) //don't merge same powernets
return
//We assume net1 is larger. If net2 is in fact larger we are just going to make them switch places to reduce on code.
if(net1.cables.len < net2.cables.len) //net2 is larger than net1. Let's switch them around
@@ -361,57 +279,18 @@
net1 = net2
net2 = temp
for(var/i=1,i<=net2.nodes.len,i++) //merge net2 into net1
var/obj/machinery/power/Node = net2.nodes[i]
if(Node)
Node.powernet = net1
net1.nodes[Node] = Node
//merge net2 into net1
for(var/obj/structure/cable/Cable in net2.cables) //merge cables
net1.add_cable(Cable)
if(!net2) return net1
for(var/i=1,i<=net2.cables.len,i++)
var/obj/structure/cable/Cable = net2.cables[i]
if(Cable)
Cable.powernet = net1
net1.cables += Cable
for(var/obj/machinery/power/Node in net2.nodes) //merge power machines
if(!Node.connect_to_network())
Node.disconnect_from_network() //if somehow we can't connect the machine to the new powernet, disconnect it from the old nonetheless
qdel(net2)
return net1
/obj/machinery/power/proc/connect_to_network()
var/turf/T = src.loc
var/obj/structure/cable/C = T.get_cable_node()
if(!C || !C.powernet) return 0
// makepowernets() //TODO: find fast way //EWWWW what are you doing!?
powernet = C.powernet
powernet.nodes[src] = src
return 1
/obj/machinery/power/proc/disconnect_from_network()
if(!powernet)
//world << " no powernet"
return 0
powernet.nodes -= src
powernet = null
//world << "powernet null"
return 1
/turf/proc/get_cable_node()
if(!istype(src, /turf/simulated/floor))
return null
for(var/obj/structure/cable/C in src)
if(C.d1 == 0)
return C
return null
/area/proc/get_apc()
// This was a simple locate() in src, but an unresolved BYOND bug causes trying to locate() in an
// area to take an inconceivably long time, especially for large areas.
// See: http://www.byond.com/forum/?post=1860571
var/obj/machinery/power/apc/FINDME
for(FINDME in src)
return FINDME
//Determines how strong could be shock, deals damage to mob, uses power.
//M is a mob who touched wire/whatever
//power_source is a source of electricity, can be powercell, area, apc, cable, powernet or null
@@ -419,9 +298,6 @@
//No animations will be performed by this proc.
/proc/electrocute_mob(mob/living/carbon/M as mob, var/power_source, var/obj/source, var/siemens_coeff = 1.0)
if(istype(M.loc,/obj/mecha)) return 0 //feckin mechs are dumb
//This is for performance optimization only.
//DO NOT modify siemens_coeff here. That is checked in human/electrocute_act()
if(istype(M,/mob/living/carbon/human))
var/mob/living/carbon/human/H = M
if(H.gloves)
@@ -475,8 +351,7 @@
source_area.use_power(drained_energy/CELLRATE)
else if (istype(power_source,/datum/powernet))
var/drained_power = drained_energy/CELLRATE //convert from "joules" to "watts"
PN.load+=drained_power
drained_power = PN.draw_power(drained_power)
else if (istype(power_source, /obj/item/weapon/stock_parts/cell))
cell.use(drained_energy)
return drained_energy
+158
View File
@@ -0,0 +1,158 @@
/datum/powernet
var/list/cables = list() // all cables & junctions
var/list/nodes = list() // all connected machines
var/load = 0 // the current load on the powernet, increased by each machine at processing
var/newavail = 0 // what available power was gathered last tick, then becomes...
var/avail = 0 //...the current available power in the powernet
var/viewload = 0 // the load as it appears on the power console (gradually updated)
var/number = 0 // Unused //TODEL
var/perapc = 0 // per-apc avilability
var/perapc_excess = 0
var/netexcess = 0 // excess power on the powernet (typically avail-load)
var/problem = 0 // If either of these is set to 1 there is some sort of issue at the powernet.
/datum/powernet/New()
powernets += src
..()
/datum/powernet/Destroy()
powernets -= src
..()
//Returns the amount of excess power (before refunding to SMESs) from last tick.
//This is for machines that might adjust their power consumption using this data.
/datum/powernet/proc/last_surplus()
return max(avail - load, 0)
/datum/powernet/proc/draw_power(var/amount)
var/draw = between(0, amount, avail - load)
load += draw
return draw
/datum/powernet/proc/is_empty()
return !cables.len && !nodes.len
//remove a cable from the current powernet
//if the powernet is then empty, delete it
//Warning : this proc DON'T check if the cable exists
/datum/powernet/proc/remove_cable(var/obj/structure/cable/C)
cables -= C
C.powernet = null
if(is_empty())//the powernet is now empty...
del(src)///... delete it - qdel
//add a cable to the current powernet
//Warning : this proc DON'T check if the cable exists
/datum/powernet/proc/add_cable(var/obj/structure/cable/C)
if(C.powernet)// if C already has a powernet...
if(C.powernet == src)
return
else
C.powernet.remove_cable(C) //..remove it
C.powernet = src
cables +=C
//remove a power machine from the current powernet
//if the powernet is then empty, delete it
//Warning : this proc DON'T check if the machine exists
/datum/powernet/proc/remove_machine(var/obj/machinery/power/M)
nodes -=M
M.powernet = null
if(is_empty())//the powernet is now empty...
del(src)///... delete it - qdel
//add a power machine to the current powernet
//Warning : this proc DON'T check if the machine exists
/datum/powernet/proc/add_machine(var/obj/machinery/power/M)
if(M.powernet)// if M already has a powernet...
if(M.powernet == src)
return
else
M.disconnect_from_network()//..remove it
M.powernet = src
nodes[M] = M
// Triggers warning for certain amount of ticks
/datum/powernet/proc/trigger_warning(var/duration_ticks = 20)
problem = max(duration_ticks, problem)
//handles the power changes in the powernet
//called every ticks by the powernet controller
/datum/powernet/proc/reset()
var/numapc = 0
if(problem > 0)
problem = max(problem - 1, 0)
if(nodes && nodes.len) // Added to fix a bad list bug -- TLE
for(var/obj/machinery/power/terminal/term in nodes)
if( istype( term.master, /obj/machinery/power/apc ) )
numapc++
netexcess = avail - load
if(numapc)
//very simple load balancing. If there was a net excess this tick then it must have been that some APCs used less than perapc, since perapc*numapc = avail
//Therefore we can raise the amount of power rationed out to APCs on the assumption that those APCs that used less than perapc will continue to do so.
//If that assumption fails, then some APCs will miss out on power next tick, however it will be rebalanced for the tick after.
if (netexcess >= 0)
perapc_excess += min(netexcess/numapc, (avail - perapc) - perapc_excess)
else
perapc_excess = 0
perapc = avail/numapc + perapc_excess
if(netexcess > 100 && nodes && nodes.len) // if there was excess power last cycle
for(var/obj/machinery/power/smes/S in nodes) // find the SMESes in the network
S.restore() // and restore some of the power that was used
//updates the viewed load (as seen on power computers)
viewload = round(load)
//reset the powernet
load = 0
avail = newavail
newavail = 0
/datum/powernet/proc/get_electrocute_damage()
switch(avail)
if (1000000 to INFINITY)
return min(rand(50,160),rand(50,160))
if (200000 to 1000000)
return min(rand(25,80),rand(25,80))
if (100000 to 200000)//Ave powernet
return min(rand(20,60),rand(20,60))
if (50000 to 100000)
return min(rand(15,40),rand(15,40))
if (1000 to 50000)
return min(rand(10,20),rand(10,20))
else
return 0
////////////////////////////////////////////////
// Misc.
///////////////////////////////////////////////
// return a knot cable (O-X) if one is present in the turf
// null if there's none
/turf/proc/get_cable_node()
if(!istype(src, /turf/simulated/floor))
return null
for(var/obj/structure/cable/C in src)
if(C.d1 == 0)
return C
return null
/area/proc/get_apc()
// This was a simple locate() in src, but an unresolved BYOND bug causes trying to locate() in an
// area to take an inconceivably long time, especially for large areas.
// See: http://www.byond.com/forum/?post=1860571
var/obj/machinery/power/apc/FINDME
for(FINDME in src)
return FINDME
@@ -8,7 +8,6 @@ var/global/list/rad_collectors = list()
icon_state = "ca"
anchored = 0
density = 1
directwired = 1
req_access = list(access_engine_equip)
// use_power = 0
var/obj/item/weapon/tank/plasma/P = null
@@ -46,57 +46,23 @@
return 1
return 0
/obj/machinery/containment_field/proc/shock(mob/living/user as mob)
/obj/machinery/containment_field/shock(mob/living/user as mob)
if(hasShocked)
return 0
if(!FG1 || !FG2)
qdel(src)
return 0
if(iscarbon(user))
var/datum/effect/effect/system/spark_spread/s = new /datum/effect/effect/system/spark_spread
s.set_up(5, 1, user.loc)
s.start()
if(isliving(user))
hasShocked = 1
var/shock_damage = min(rand(30,40),rand(30,40))
user.burn_skin(shock_damage)
user.updatehealth()
user.visible_message("\red [user.name] was shocked by the [src.name]!", \
"\red <B>You feel a powerful shock course through your body sending you flying!</B>", \
"\red You hear a heavy electrical crack")
user.electrocute_act(shock_damage, src)
var/stun = min(shock_damage, 15)
user.Stun(stun)
user.Weaken(10)
user.updatehealth()
var/atom/target = get_edge_target_turf(user, get_dir(src, get_step_away(user, src)))
user.throw_at(target, 200, 4)
sleep(20)
hasShocked = 0
return
else if(issilicon(user))
var/datum/effect/effect/system/spark_spread/s = new /datum/effect/effect/system/spark_spread
s.set_up(5, 1, user.loc)
s.start()
hasShocked = 1
var/shock_damage = rand(15,30)
user.take_overall_damage(0,shock_damage)
user.visible_message("\red [user.name] was shocked by the [src.name]!", \
"\red <B>Energy pulse detected, system damaged!</B>", \
"\red You hear an electrical crack")
if(prob(20))
user.Stun(2)
sleep(20)
hasShocked = 0
return
return
/obj/machinery/containment_field/proc/set_master(var/master1,var/master2)
+4 -10
View File
@@ -48,7 +48,6 @@
..()
if(state == 2 && anchored)
connect_to_network()
src.directwired = 1
if(frequency)
set_frequency(frequency)
/obj/machinery/power/emitter/multitool_menu(var/mob/user,var/obj/item/device/multitool/P)
@@ -145,8 +144,8 @@
return
if(((src.last_shot + src.fire_delay) <= world.time) && (src.active == 1))
if(!active_power_usage || avail(active_power_usage))
add_load(active_power_usage)
var/actual_load = draw_power(active_power_usage)
if(actual_load >= active_power_usage) //does the laser have enough power to shoot?
if(!powered)
powered = 1
update_icon()
@@ -238,7 +237,6 @@
state = 2
user << "You weld the [src] to the floor."
connect_to_network()
src.directwired = 1
else
user << "\red You need more welding fuel to complete this task."
if(2)
@@ -252,7 +250,6 @@
state = 1
user << "You cut the [src] free from the floor."
disconnect_from_network()
src.directwired = 0
else
user << "\red You need more welding fuel to complete this task."
return
@@ -275,11 +272,8 @@
..()
return
/obj/machinery/power/emitter/emag_act(user as mob)
/obj/machinery/power/emitter/emag_act(var/mob/living/user as mob)
if(!emagged)
if(!ishuman(user))
return
var/mob/living/carbon/human/H = user
locked = 0
emagged = 1
H.visible_message("[H.name] emags the [src.name].","\red You short out the lock.")
user.visible_message("[user.name] emags the [src.name].","\red You short out the lock.")
+171 -159
View File
@@ -13,22 +13,32 @@
icon_state = "smes"
density = 1
anchored = 1
use_power = 0
var/output = 50000
var/lastout = 0
var/loaddemand = 0
var/capacity = 5e6
var/charge = 0
var/charging = 0
var/chargemode = 0
var/chargecount = 0
var/chargelevel = 50000
var/input_level_max = 200000 // cap on input_level
var/output_level_max = 200000 // cap on output_level
var/online = 1
var/capacity = 5e6 // maximum charge
var/charge = 1e6 // actual charge
var/input_attempt = 0 // 1 = attempting to charge, 0 = not attempting to charge
var/inputting = 0 // 1 = actually inputting, 0 = not inputting
var/input_level = 50000 // amount of power the SMES attempts to charge by
var/input_level_max = 200000 // cap on input_level
var/input_available = 0 // amount of charge available from input last tick
var/output_attempt = 1 // 1 = attempting to output, 0 = not attempting to output
var/outputting = 1 // 1 = actually outputting, 0 = not outputting
var/output_level = 50000 // amount of power the SMES attempts to output
var/output_level_max = 200000 // cap on output_level
var/output_used = 0 // amount of power actually outputted. may be less than output_level if the powernet returns excess power
//Holders for powerout event.
var/last_output_attempt = 0
var/last_input_attempt = 0
var/last_charge = 0
var/open_hatch = 0
var/name_tag = null
var/building_terminal = 0 //Suggestions about how to avoid clickspam building several terminals accepted!
var/obj/machinery/power/terminal/terminal = null
var/list/overlay_images
/obj/machinery/power/smes/New()
..()
@@ -42,6 +52,7 @@
component_parts += new /obj/item/weapon/stock_parts/capacitor(null)
component_parts += new /obj/item/stack/cable_coil(null, 5)
RefreshParts()
spawn(5)
if(!powernet)
connect_to_network()
@@ -59,9 +70,22 @@
terminal.master = src
if(!terminal.powernet)
terminal.connect_to_network()
updateicon()
update_icon()
return
/obj/machinery/power/smes/upgraded/New()
..()
component_parts = list()
component_parts += new /obj/item/weapon/circuitboard/smes(null)
component_parts += new /obj/item/weapon/stock_parts/cell/high(null)
component_parts += new /obj/item/weapon/stock_parts/cell/high(null)
component_parts += new /obj/item/weapon/stock_parts/cell/high(null)
component_parts += new /obj/item/weapon/stock_parts/cell/high(null)
component_parts += new /obj/item/weapon/stock_parts/cell/high(null)
component_parts += new /obj/item/weapon/stock_parts/capacitor(null)
component_parts += new /obj/item/stack/cable_coil(null, 5)
RefreshParts()
/obj/machinery/power/smes/RefreshParts()
var/IO = 0
var/C = 0
@@ -73,41 +97,25 @@
C += PC.maxcharge
capacity = C / (15000) * 1e6
/obj/machinery/power/smes/proc/updateicon()
/obj/machinery/power/smes/update_icon()
overlays.Cut()
if(stat & BROKEN) return
if(isnull(src.overlay_images))
src.overlay_images = new
src.overlay_images.len = 3
overlays += image('icons/obj/power.dmi', "smes-op[outputting]")
src.overlay_images[1] = image('icons/obj/power.dmi', "smes-op[online]")
src.overlay_images[2] = image('icons/obj/power.dmi', "smes-oc0")
src.overlay_images[3] = image('icons/obj/power.dmi', "smes-og1")
var/image/buffer
buffer = src.overlay_images[1]
buffer.icon_state = "smes-op[online]"
overlays += src.overlay_images[1]
if(!charging && chargemode)
buffer = src.overlay_images[2]
buffer.icon_state = "smes-oc0"
overlays += src.overlay_images[2]
if(inputting == 2)
overlays += image('icons/obj/power.dmi', "smes-oc2")
else if (inputting == 1)
overlays += image('icons/obj/power.dmi', "smes-oc1")
else
buffer = src.overlay_images[2]
buffer.icon_state = "smes-oc1"
overlays += src.overlay_images[2]
if(input_attempt)
overlays += image('icons/obj/power.dmi', "smes-oc0")
var/clevel = chargedisplay()
if(clevel > 0)
buffer = src.overlay_images[3]
buffer.icon_state = "smes-og[clevel]"
overlays += src.overlay_images[3]
if(clevel>0)
overlays += image('icons/obj/power.dmi', "smes-og[clevel]")
return
/obj/machinery/power/smes/attackby(obj/item/I, mob/user, params)
//opening using screwdriver
if(default_deconstruction_screwdriver(user, "[initial(icon_state)]-o", initial(icon_state), I))
@@ -203,7 +211,7 @@
user.visible_message(\
"<span class='alert'>[user.name] cuts the cables and dismantles the power terminal.</span>",\
"You cut the cables and dismantle the power terminal.")
charging = 0 //stop inputting, since we have don't have a terminal anymore
inputting = 0 //stop inputting, since we have don't have a terminal anymore
qdel(terminal)
return
@@ -221,92 +229,70 @@
disconnect_terminal()
return ..()
// create a terminal object pointing towards the SMES
// wires will attach to this
/obj/machinery/power/smes/proc/make_terminal(var/turf/T)
terminal = new/obj/machinery/power/terminal(T)
terminal.dir = get_dir(T,src)
terminal.master = src
/obj/machinery/power/smes/proc/disconnect_terminal()
if(terminal)
terminal.master = null
terminal = null
return round(5.5*charge/(capacity ? capacity : 5e6))
/obj/machinery/power/smes/proc/chargedisplay()
return round(5.5*charge/capacity)
return round(5.5*charge/(capacity ? capacity : 5e6))
#define SMESRATE 0.05
/obj/machinery/power/smes/process()
if(stat & BROKEN)
return
if(stat & BROKEN) return
//store machine state to see if we need to update the icon overlays
var/last_disp = chargedisplay()
var/last_chrg = charging
var/last_onln = online
var/last_chrg = inputting
var/last_onln = outputting
if(terminal)
var/excess = terminal.surplus()
//inputting
if(input_attempt)
var/target_load = min((capacity-charge)/SMESRATE, input_level) // charge at set rate, limited to spare capacity
var/actual_load = draw_power(target_load) // add the load to the terminal side network
charge += actual_load * SMESRATE // increase the charge
if(charging)
if(excess >= 0) // if there's power available, try to charge
if (actual_load >= target_load) // Did we charge at full rate?
inputting = 2
else if (actual_load) // If not, did we charge at least partially?
inputting = 1
else // Or not at all?
inputting = 0
var/load = min((capacity-charge)/SMESRATE, chargelevel) // charge at set rate, limited to spare capacity
//outputting
if(outputting)
output_used = min( charge/SMESRATE, output_level) //limit output to that stored
charge += load * SMESRATE // increase the charge
charge -= output_used*SMESRATE // reduce the storage (may be recovered in /restore() if excessive)
add_load(load) // add the load to the terminal side network
add_avail(output_used) // add output to powernet (smes side)
else // if not enough capcity
charging = 0 // stop charging
chargecount = 0
else
if(chargemode)
if(chargecount > rand(3,6))
charging = 1
chargecount = 0
if(excess > chargelevel)
chargecount++
else
chargecount = 0
else
chargecount = 0
if(online) // if outputting
lastout = min( charge/SMESRATE, output) //limit output to that stored
charge -= lastout*SMESRATE // reduce the storage (may be recovered in /restore() if excessive)
add_avail(lastout) // add output to powernet (smes side)
if(charge < 0.0001)
online = 0 // stop output if charge falls to zero
if(output_used < 0.0001) // either from no charge or set to 0
outputting = 0
investigate_log("lost power and turned <font color='red'>off</font>","singulo")
else if(output_attempt && charge > output_level && output_level > 0)
outputting = 1
else
output_used = 0
// only update icon if state changed
if(last_disp != chargedisplay() || last_chrg != charging || last_onln != online)
updateicon()
if(last_disp != chargedisplay() || last_chrg != inputting || last_onln != outputting)
update_icon()
return
// called after all power processes are finished
// restores charge level to smes if there was excess this ptick
/obj/machinery/power/smes/proc/restore()
if(stat & BROKEN)
return
if(!online)
loaddemand = 0
if(!outputting)
output_used = 0
return
var/excess = powernet.netexcess // this was how much wasn't used on the network last ptick, minus any removed by other SMESes
excess = min(lastout, excess) // clamp it to how much was actually output by this SMES last ptick
excess = min(output_used, excess) // clamp it to how much was actually output by this SMES last ptick
excess = min((capacity-charge)/SMESRATE, excess) // for safety, also limit recharge by space capacity of SMES (shouldn't happen)
@@ -314,23 +300,51 @@
var/clev = chargedisplay()
charge += excess * SMESRATE
charge += excess * SMESRATE // restore unused power
powernet.netexcess -= excess // remove the excess from the powernet, so later SMESes don't try to use it
loaddemand = lastout-excess
output_used -= excess
if(clev != chargedisplay() )
updateicon()
if(clev != chargedisplay() ) //if needed updates the icons overlay
update_icon()
return
//Will return 1 on failure
/obj/machinery/power/smes/proc/make_terminal(const/mob/user)
if (user.loc == loc)
user << "<span class='warning'>You must not be on the same tile as the [src].</span>"
return 1
/obj/machinery/power/smes/add_load(var/amount)
//Direction the terminal will face to
var/tempDir = get_dir(user, src)
switch(tempDir)
if (NORTHEAST, SOUTHEAST)
tempDir = EAST
if (NORTHWEST, SOUTHWEST)
tempDir = WEST
var/turf/tempLoc = get_step(src, reverse_direction(tempDir))
if (istype(tempLoc, /turf/space))
user << "<span class='warning'>You can't build a terminal on space.</span>"
return 1
else if (istype(tempLoc))
if(tempLoc.intact)
user << "<span class='warning'>You must remove the floor plating first.</span>"
return 1
user << "<span class='notice'>You start adding cable to the [src].</span>"
if(do_after(user, 50))
terminal = new /obj/machinery/power/terminal(tempLoc)
terminal.dir = tempDir
terminal.master = src
return 0
return 1
/obj/machinery/power/smes/draw_power(var/amount)
if(terminal && terminal.powernet)
terminal.powernet.load += amount
return terminal.powernet.draw_power(amount)
return 0
/obj/machinery/power/smes/attack_ai(mob/user)
add_fingerprint(user)
add_hiddenprint(user)
ui_interact(user)
/obj/machinery/power/smes/attack_ghost(mob/user)
@@ -344,7 +358,6 @@
return
/obj/machinery/power/smes/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1)
if(stat & BROKEN)
return
@@ -352,14 +365,21 @@
var/data[0]
data["nameTag"] = name_tag
data["storedCapacity"] = round(100.0*charge/capacity, 0.1)
data["charging"] = charging
data["chargeMode"] = chargemode
data["chargeLevel"] = chargelevel
data["charging"] = inputting
data["chargeMode"] = input_attempt
data["chargeLevel"] = input_level
data["chargeMax"] = input_level_max
data["outputOnline"] = online
data["outputLevel"] = output
data["outputOnline"] = output_attempt
data["outputLevel"] = output_level
data["outputMax"] = output_level_max
data["outputLoad"] = round(loaddemand)
data["outputLoad"] = round(output_used)
if(outputting)
data["outputting"] = 2 // smes is outputting
else if(!outputting && output_attempt)
data["outputting"] = 1 // smes is online but not outputting because it's charge level is too low
else
data["outputting"] = 0 // smes is not outputting
// update the ui if it exists, returns null if no ui is passed/found
ui = nanomanager.try_update_ui(user, src, ui_key, ui, data, force_open)
@@ -374,7 +394,6 @@
// auto update every Master Controller tick
ui.set_auto_update(1)
/obj/machinery/power/smes/Topic(href, href_list)
..()
@@ -391,43 +410,39 @@
return 0 // Do not update ui
if( href_list["cmode"] )
chargemode = !chargemode
if(!chargemode)
charging = 0
updateicon()
inputting(!input_attempt)
update_icon()
else if( href_list["online"] )
online = !online
updateicon()
outputting(!output_attempt)
update_icon()
else if( href_list["input"] )
switch( href_list["input"] )
if("min")
chargelevel = 0
input_level = 0
if("max")
chargelevel = input_level_max //30000
input_level = input_level_max
if("set")
chargelevel = input(usr, "Enter new input level (0-[input_level_max])", "SMES Input Power Control", chargelevel) as num
chargelevel = max(0, min(input_level_max, chargelevel)) // clamp to range
input_level = input(usr, "Enter new input level (0-[input_level_max])", "SMES Input Power Control", input_level) as num
input_level = max(0, min(input_level_max, input_level)) // clamp to range
else if( href_list["output"] )
switch( href_list["output"] )
if("min")
output = 0
output_level = 0
if("max")
output = output_level_max //30000
output_level = output_level_max
if("set")
output = input(usr, "Enter new output level (0-[output_level_max])", "SMES Output Power Control", output) as num
output = max(0, min(output_level_max, output)) // clamp to range
output_level = input(usr, "Enter new output level (0-[output_level_max])", "SMES Output Power Control", output_level) as num
output_level = max(0, min(output_level_max, output_level)) // clamp to range
investigate_log("input/output; [chargelevel>output?"<font color='green'>":"<font color='red'>"][chargelevel]/[output]</font> | Output-mode: [online?"<font color='green'>on</font>":"<font color='red'>off</font>"] | Input-mode: [chargemode?"<font color='green'>auto</font>":"<font color='red'>off</font>"] by [usr.key]","singulo")
investigate_log("input/output; [input_level>output_level?"<font color='green'>":"<font color='red'>"][input_level]/[output_level]</font> | Output-mode: [output_attempt?"<font color='green'>on</font>":"<font color='red'>off</font>"] | Input-mode: [input_attempt?"<font color='green'>auto</font>":"<font color='red'>off</font>"] by [usr.key]","singulo")
return 1
/obj/machinery/power/smes/proc/ion_act()
if((src.z in config.station_levels))
if(src.z in config.station_levels)
if(prob(1)) //explosion
world << "\red SMES explosion in [src.loc.loc]"
for(var/mob/M in viewers(src))
M.show_message("\red The [src.name] is making strange noises!", 3, "\red You hear sizzling electronics.", 2)
sleep(10*pick(4,5,6,7,10,14))
@@ -435,11 +450,10 @@
smoke.set_up(3, 0, src.loc)
smoke.attach(src)
smoke.start()
explosion(src.loc, -1, 0, 1, 3, 0)
explosion(src.loc, -1, 0, 1, 3, 1, 0)
qdel(src)
return
if(prob(15)) //Power drain
world << "\red SMES power drain in [src.loc.loc]"
var/datum/effect/effect/system/spark_spread/s = new /datum/effect/effect/system/spark_spread
s.set_up(3, 1, src)
s.start()
@@ -448,45 +462,43 @@
else
emp_act(2)
if(prob(5)) //smoke only
world << "\red SMES smoke in [src.loc.loc]"
var/datum/effect/effect/system/harmless_smoke_spread/smoke = new /datum/effect/effect/system/harmless_smoke_spread()
smoke.set_up(3, 0, src.loc)
smoke.attach(src)
smoke.start()
/obj/machinery/power/smes/proc/inputting(var/do_input)
input_attempt = do_input
if(!input_attempt)
inputting = 0
/obj/machinery/power/smes/proc/outputting(var/do_output)
output_attempt = do_output
if(!output_attempt)
outputting = 0
/obj/machinery/power/smes/emp_act(severity)
online = 0
charging = 0
output = 0
inputting(rand(0,1))
outputting(rand(0,1))
output_level = rand(0, output_level_max)
input_level = rand(0, input_level_max)
charge -= 1e6/severity
if (charge < 0)
charge = 0
spawn(100)
output = initial(output)
charging = initial(charging)
online = initial(online)
update_icon()
..()
/obj/machinery/power/smes/engineering
charge = 1e6 // Engineering starts with some charge for singulo
charge = 1e6 // Engineering starts with some charge for singulo
/obj/machinery/power/smes/magical
name = "magical power storage unit"
desc = "A high-capacity superconducting magnetic energy storage (SMES) unit. Magically produces power."
process()
capacity = INFINITY
charge = INFINITY
..()
capacity = 9000000
output_level = 250000
/proc/rate_control(var/S, var/V, var/C, var/Min=1, var/Max=5, var/Limit=null)
var/href = "<A href='?src=\ref[S];rate control=1;[V]"
var/rate = "[href]=-[Max]'>-</A>[href]=-[Min]'>-</A> [(C?C : 0)] [href]=[Min]'>+</A>[href]=[Max]'>+</A>"
if(Limit) return "[href]=-[Limit]'>-</A>"+rate+"[href]=[Limit]'>+</A>"
return rate
/obj/machinery/power/smes/magical/process()
charge = 5000000
..()
#undef SMESRATE
#undef SMESRATE
+21 -12
View File
@@ -289,15 +289,11 @@
var/lastgen = 0
var/track = 0 // 0= off 1=timed 2=auto (tracker)
var/trackrate = 600 // 300-900 seconds
var/nexttime = 0 // time for a panel to rotate of 1° in manual tracking
var/nexttime = 0 // time for a panel to rotate of 1? in manual tracking
var/obj/machinery/power/tracker/connected_tracker = null
var/list/connected_panels = list()
/obj/machinery/power/solar_control/New()
..()
if(ticker)
initialize()
/obj/machinery/power/solar_control/initialize()
connect_to_network()
/obj/machinery/power/solar_control/Destroy()
@@ -309,11 +305,12 @@
/obj/machinery/power/solar_control/disconnect_from_network()
..()
sun.solars.Remove(src)
if(sun)
sun.solars.Remove(src)
/obj/machinery/power/solar_control/connect_to_network()
var/to_return = ..()
if(powernet) //if connected and not already in solar list...
if(powernet && sun) //if connected and not already in solar list...
sun.solars |= src //... add it
return to_return
@@ -366,9 +363,21 @@
if(cdir > -1)
overlays += image('icons/obj/computer.dmi', "solcon-o", FLY_LAYER, angle2dir(cdir))
/obj/machinery/power/solar_control/attack_ai(mob/user as mob)
src.add_hiddenprint(user)
ui_interact(user)
/obj/machinery/power/solar_control/attack_ghost(mob/user as mob)
ui_interact(user)
/obj/machinery/power/solar_control/attack_hand(mob/user)
if(!..())
ui_interact(user)
if(..(user))
return 1
if(stat & BROKEN)
return
ui_interact(user)
/obj/machinery/power/solar_control/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1)
@@ -438,9 +447,9 @@
connected_tracker.unset_control()
if(track==1 && trackrate) //manual tracking and set a rotation speed
if(nexttime <= world.time) //every time we need to increase/decrease the angle by 1°...
if(nexttime <= world.time) //every time we need to increase/decrease the angle by 1?...
targetdir = (targetdir + trackrate/abs(trackrate) + 360) % 360 //... do it
nexttime += 36000/abs(trackrate) //reset the counter for the next 1°
nexttime += 36000/abs(trackrate) //reset the counter for the next 1?
/obj/machinery/power/solar_control/Topic(href, href_list)
if(..())
+5 -1
View File
@@ -11,7 +11,6 @@
layer = TURF_LAYER
var/obj/machinery/power/master = null
anchored = 1
directwired = 0 // must have a cable on same turf connecting to terminal
layer = 2.6 // a bit above wires
@@ -20,6 +19,11 @@
var/turf/T = src.loc
if(level==1) hide(T.intact)
return
/obj/machinery/power/terminal/Destroy()
if(master)
master.disconnect_terminal()
return ..()
/obj/machinery/power/terminal/hide(var/i)
+5 -5
View File
@@ -23,11 +23,11 @@
/obj/machinery/power/tracker/Destroy()
unset_control() //remove from control computer
return ..()
..()
//set the control of the tracker to a given computer if closer than SOLAR_MAX_DIST
/obj/machinery/power/tracker/proc/set_control(var/obj/machinery/power/solar_control/SC)
if(!SC || (get_dist(src, SC) > SOLAR_MAX_DIST))
if(SC && (get_dist(src, SC) > SOLAR_MAX_DIST))
return 0
control = SC
SC.connected_tracker = src
@@ -58,7 +58,7 @@
if(powernet && (powernet == control.powernet)) //update if we're still in the same powernet
control.cdir = angle
/obj/machinery/power/tracker/attackby(var/obj/item/weapon/W, var/mob/user, params)
/obj/machinery/power/tracker/attackby(var/obj/item/weapon/W, var/mob/user)
if(istype(W, /obj/item/weapon/crowbar))
playsound(src.loc, 'sound/machines/click.ogg', 50, 1)
@@ -70,7 +70,7 @@
S.give_glass()
playsound(src.loc, 'sound/items/Deconstruct.ogg', 50, 1)
user.visible_message("<span class='notice'>[user] takes the glass off the tracker.</span>")
qdel(src)
del(src) // qdel
return
..()
@@ -81,4 +81,4 @@
name = "tracker electronics"
icon = 'icons/obj/doors/door_assembly.dmi'
icon_state = "door_electronics"
w_class = 2.0
w_class = 2.0
-1
View File
@@ -22,7 +22,6 @@
anchored = 1
density = 1
var/obj/machinery/compressor/compressor
directwired = 1
var/turf/simulated/outturf
var/lastgen
-14
View File
@@ -35,20 +35,6 @@
src.disable_wire = pick(w)
w -= src.disable_wire
/obj/machinery/r_n_d/proc/
shock(mob/user, prb)
if(stat & (BROKEN|NOPOWER)) // unpowered, no shock
return 0
if(!prob(prb))
return 0
var/datum/effect/effect/system/spark_spread/s = new /datum/effect/effect/system/spark_spread
s.set_up(5, 1, src)
s.start()
if (electrocute_mob(user, get_area(src), src, 0.7))
return 1
else
return 0
/obj/machinery/r_n_d/attack_hand(mob/user as mob)
if (shocked)
shock(user,50)