mirror of
https://github.com/ParadiseSS13/Paradise.git
synced 2026-08-26 05:27:01 +01:00
Powernet rework
This commit is contained in:
@@ -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"
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
var/delay = 0
|
||||
var/datum/radio_frequency/radio_connection
|
||||
var/airlock_wire = null
|
||||
|
||||
|
||||
New()
|
||||
..()
|
||||
if(!radio_controller)
|
||||
|
||||
+186
-190
@@ -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
|
||||
|
||||
+520
-263
File diff suppressed because it is too large
Load Diff
+176
-301
@@ -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
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
@@ -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
@@ -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(..())
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -22,7 +22,6 @@
|
||||
anchored = 1
|
||||
density = 1
|
||||
var/obj/machinery/compressor/compressor
|
||||
directwired = 1
|
||||
var/turf/simulated/outturf
|
||||
var/lastgen
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
Reference in New Issue
Block a user