Merge pull request #11393 from Fox-McCloud/powernet-refactor

TG Powernet Refactor
This commit is contained in:
variableundefined
2019-04-30 12:42:53 +08:00
committed by GitHub
33 changed files with 602 additions and 719 deletions
+1 -4
View File
@@ -950,9 +950,6 @@ var/gamma_ship_location = 1 // 0 = station , 1 = space
for(var/obj/machinery/mech_bay_recharge_port/P in toArea)
P.update_recharge_turf()
for(var/obj/machinery/power/apc/A in toArea)
A.init()
if(gamma_ship_location)
gamma_ship_location = 0
else
@@ -1096,7 +1093,7 @@ var/gamma_ship_location = 1 // 0 = station , 1 = space
dat += "<tr><td><b>" + id + "</b></td>"
dat += "<td>" + ckey + "</td>"
dat += "<td><a href='?src=[UID()];force_discord_unlink=[ckey]'>Unlink</td></tr>"
dat += "</table></body></html>"
usr << browse(dat, "window=duplicates;size=500x480")
@@ -13,10 +13,10 @@
if(battery_module && battery_module.battery && battery_module.battery.charge)
var/obj/item/stock_parts/cell/cell = battery_module.battery
if(cell.use(amount * CELLRATE))
if(cell.use(amount * GLOB.CELLRATE))
return TRUE
else // Discharge the cell anyway.
cell.use(min(amount*CELLRATE, cell.charge))
cell.use(min(amount*GLOB.CELLRATE, cell.charge))
return FALSE
return FALSE
@@ -39,7 +39,7 @@
data["powermonitor"] = attached ? TRUE : FALSE
if(attached)
var/datum/powernet/powernet = attached.get_powernet()
var/datum/powernet/powernet = attached.powernet
data["poweravail"] = powernet.avail
data["powerload"] = powernet.viewload
data["powerdemand"] = powernet.load
@@ -20,7 +20,7 @@
return
if(use_power(charge_rate, charging=1))
holder.give_power(charge_rate * CELLRATE)
holder.give_power(charge_rate * GLOB.CELLRATE)
/obj/item/computer_hardware/recharger/APC
+38 -42
View File
@@ -46,7 +46,6 @@
name = "area power controller"
desc = "A control terminal for the area electrical systems."
icon_state = "apc0"
anchored = 1
use_power = NO_POWER_USE
req_access = list(access_engine_equip)
siemens_strength = 1
@@ -55,7 +54,7 @@
var/areastring = null
var/obj/item/stock_parts/cell/cell
var/start_charge = 90 // initial cell charge %
var/cell_type = 2500
var/cell_type = 2500 //Base cell has 2500 capacity. Enter the path of a different cell you want to use. cell determines charge rates, max capacity, ect. These can also be changed with other APC vars, but isn't recommended to minimize the risk of accidental usage of dirty editted APCs
var/opened = 0 //0=closed, 1=opened, 2=cover removed
var/shorted = 0
var/lighting = 3
@@ -137,40 +136,35 @@
/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)
/obj/machinery/power/apc/New(turf/loc, ndir, building = 0)
if(!armor)
armor = list(melee = 20, bullet = 20, laser = 10, energy = 100, bomb = 30, bio = 100, rad = 100)
..()
GLOB.apcs += src
GLOB.apcs = sortAtom(GLOB.apcs)
wires = new(src)
wires = new(src)
// offset 24 pixels in direction of dir
// this allows the APC to be embedded in a wall, yet still inside an area
if(building)
dir = ndir
src.tdir = dir // to fix Vars bug
dir = SOUTH
setDir(ndir)
tdir = dir // to fix Vars bug
setDir(SOUTH)
pixel_x = (src.tdir & 3)? 0 : (src.tdir == 4 ? 24 : -24)
pixel_y = (src.tdir & 3)? (src.tdir ==1 ? 24 : -24) : 0
if(building==0)
init()
else
if(building)
area = get_area(src)
area.apc |= src
opened = 1
operating = 0
name = "[area.name] APC"
stat |= MAINT
src.update_icon()
spawn(5)
src.update()
update_icon()
addtimer(CALLBACK(src, .proc/update), 5)
/obj/machinery/power/apc/Destroy()
GLOB.apcs -= src
@@ -193,14 +187,17 @@
// create a terminal object at the same position as original turf loc
// wires will attach to this
terminal = new/obj/machinery/power/terminal(src.loc)
terminal.dir = tdir
terminal.setDir(tdir)
terminal.master = src
/obj/machinery/power/apc/proc/init()
/obj/machinery/power/apc/Initialize(mapload)
. = ..()
if(!mapload)
return
has_electronics = 2 //installed and secured
// is starting with a power cell installed, create it and set its charge level
if(cell_type)
src.cell = new/obj/item/stock_parts/cell(src)
cell = new/obj/item/stock_parts/cell(src)
cell.maxcharge = cell_type // cell_type is maximum charge (old default was 1000 or 2500 (values one and two respectively)
cell.charge = start_charge * cell.maxcharge / 100 // (convert percentage to actual value)
@@ -219,12 +216,12 @@
area = get_area_name(areastring)
name = "\improper [area.name] APC"
area.apc |= src
update_icon()
make_terminal()
spawn(5)
src.update()
addtimer(CALLBACK(src, .proc/update), 5)
/obj/machinery/power/apc/examine(mob/user)
if(..(user, 1))
@@ -1084,14 +1081,9 @@
else
return 0
//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)
/obj/machinery/power/apc/add_load(amount)
if(terminal && terminal.powernet)
return terminal.powernet.draw_power(amount)
return 0
terminal.add_load(amount)
/obj/machinery/power/apc/avail()
if(terminal)
@@ -1100,7 +1092,6 @@
return 0
/obj/machinery/power/apc/process()
if(stat & (BROKEN|MAINT))
return
if(!area.requires_power)
@@ -1136,18 +1127,21 @@
if(cell && !shorted)
// 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, GLOB.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
var/draw = draw_power(cellused/CELLRATE) // draw the power needed to charge this cell
cell.give(draw * CELLRATE)
cell.give(cellused)
add_load(cellused/GLOB.CELLRATE) // add the load used to recharge the cell
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?
var/draw = draw_power(excess)
cell.charge = min(cell.maxcharge, cell.charge + CELLRATE * draw) //recharge with what we can
if((cell.charge/GLOB.CELLRATE + excess) >= lastused_total) // can we draw enough from cell+grid to cover last usage?
cell.charge = min(cell.maxcharge, cell.charge + GLOB.CELLRATE * excess) //recharge with what we can
add_load(excess) // so draw what we can from the grid
charging = 0
else // not enough power available to run the last tick!
charging = 0
chargecount = 0
@@ -1200,14 +1194,12 @@
autoflag = 0
// now trickle-charge the cell
if(src.attempt_charging())
if(chargemode && charging == 1 && operating)
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)
ch = draw_power(ch/CELLRATE) // Removes the power we're taking from the grid
cell.give(ch*CELLRATE) // actually recharge the cell
var/ch = min(excess*GLOB.CELLRATE, cell.maxcharge*GLOB.CHARGELEVEL)
add_load(ch/GLOB.CELLRATE) // Removes the power we're taking from the grid
cell.give(ch) // actually recharge the cell
else
charging = 0 // stop charging
@@ -1220,12 +1212,12 @@
if(chargemode)
if(!charging)
if(excess > cell.maxcharge*CHARGELEVEL)
if(excess > cell.maxcharge*GLOB.CHARGELEVEL)
chargecount++
else
chargecount = 0
if(chargecount >= 10)
if(chargecount == 10)
chargecount = 0
charging = 1
@@ -1292,9 +1284,13 @@
lighting = 0
equipment = 0
environ = 0
update_icon()
update()
spawn(600)
equipment = 3
environ = 3
update_icon()
update()
..()
/obj/machinery/power/apc/ex_act(severity)
+142 -115
View File
@@ -59,21 +59,18 @@ By design, d1 is the smallest direction and d2 is the highest
/obj/structure/cable/white
color = COLOR_WHITE
/obj/structure/cable/New()
..()
/obj/structure/cable/Initialize(mapload)
. = ..()
// ensure d1 & d2 reflect the icon_state for entering and exiting cable
var/dash = findtext(icon_state, "-")
d1 = text2num(copytext( icon_state, 1, dash ))
d2 = text2num(copytext( icon_state, dash+1 ))
d1 = text2num( copytext( icon_state, 1, dash ) )
d2 = text2num( copytext( icon_state, dash+1 ) )
var/turf/T = src.loc // hide if turf is not intact
if(level==1) hide(T.intact)
var/turf/T = get_turf(src) // hide if turf is not intact
if(level == 1)
hide(T.intact)
LAZYADD(GLOB.cable_list, src) //add it to the global cable list
@@ -83,14 +80,23 @@ By design, d1 is the smallest direction and d2 is the highest
LAZYREMOVE(GLOB.cable_list, src) //remove it from global cable list
return ..() // then go ahead and delete the cable
/obj/structure/cable/deconstruct(disassembled = TRUE)
var/turf/T = get_turf(src)
if(d1) // 0-X cables are 1 unit, X-X cables are 2 units long
new/obj/item/stack/cable_coil(T, 2, paramcolor = color)
else
new/obj/item/stack/cable_coil(T, 1, paramcolor = color)
qdel(src)
///////////////////////////////////
// General procedures
///////////////////////////////////
//If underfloor, hide the cable
/obj/structure/cable/hide(var/i)
/obj/structure/cable/hide(i)
if(level == 1 && istype(loc, /turf))
if(level == 1 && isturf(loc))
invisibility = i ? 101 : 0
updateicon()
@@ -101,9 +107,49 @@ By design, d1 is the smallest direction and d2 is the highest
icon_state = "[d1]-[d2]"
// returns the powernet this cable belongs to
/obj/structure/cable/proc/get_powernet() //TODO: remove this as it is obsolete
return powernet
////////////////////////////////////////////
// Power related
///////////////////////////////////////////
// All power generation handled in add_avail()
// Machines should use add_load(), surplus(), avail()
// Non-machines should use add_delayedload(), delayed_surplus(), newavail()
/obj/structure/cable/proc/add_avail(amount)
if(powernet)
powernet.newavail += amount
/obj/structure/cable/proc/add_load(amount)
if(powernet)
powernet.load += amount
/obj/structure/cable/proc/surplus()
if(powernet)
return Clamp(powernet.avail-powernet.load, 0, powernet.avail)
else
return 0
/obj/structure/cable/proc/avail()
if(powernet)
return powernet.avail
else
return 0
/obj/structure/cable/proc/add_delayedload(amount)
if(powernet)
powernet.delayedload += amount
/obj/structure/cable/proc/delayed_surplus()
if(powernet)
return Clamp(powernet.newavail - powernet.delayedload, 0, powernet.newavail)
else
return 0
/obj/structure/cable/proc/newavail()
if(powernet)
return powernet.newavail
else
return 0
//Telekinesis has no effect on a cable
/obj/structure/cable/attack_tk(mob/user)
@@ -120,47 +166,19 @@ By design, d1 is the smallest direction and d2 is the highest
if(T.intact)
return
if(istype(W, /obj/item/wirecutters))
///// Z-Level Stuff
/* if(src.d1 == 12 || src.d2 == 12)
to_chat(user, "<span class='warning'>You must cut this cable from above.</span>")
return */
///// Z-Level Stuff
/* if(breaker_box)
to_chat(user, "<span class='warning'>This cable is connected to nearby breaker box. Use breaker box to interact with it.</span>")
return */
if(iswirecutter(W))
if(shock(user, 50))
return
if(src.d1) // 0-X cables are 1 unit, X-X cables are 2 units long
new/obj/item/stack/cable_coil(T, 2, paramcolor = color)
else
new/obj/item/stack/cable_coil(T, 1, paramcolor = color)
for(var/mob/O in viewers(src, null))
O.show_message("<span class='warning'>[user] cuts the cable.</span>", 1)
///// Z-Level Stuff
/*if(src.d1 == 11 || src.d2 == 11)
var/turf/controllerlocation = locate(1, 1, z)
for(var/obj/effect/landmark/zcontroller/controller in controllerlocation)
if(controller.down)
var/turf/below = locate(src.x, src.y, controller.down_target)
for(var/obj/structure/cable/c in below)
if(c.d1 == 12 || c.d2 == 12)
c.qdel()*/
///// Z-Level Stuff
user.visible_message("[user] cuts the cable.", "<span class='notice'>You cut the cable.</span>")
investigate_log("was cut by [key_name(usr, 1)] in [get_area(user)]([T.x], [T.y], [T.z] - [ADMIN_JMP(T)])","wires")
qdel(src) // qdel
deconstruct()
return
else if(istype(W, /obj/item/stack/cable_coil))
var/obj/item/stack/cable_coil/coil = W
if(coil.get_amount() < 1)
to_chat(user, "Not enough cable")
to_chat(user, "<span class='warning'>Not enough cable!</span>")
return
coil.cable_join(src, user)
@@ -173,11 +191,9 @@ By design, d1 is the smallest direction and d2 is the highest
else if(istype(W, /obj/item/multitool))
if(powernet && (powernet.avail > 0)) // is it powered?
to_chat(user, "<span class='warning'>[powernet.avail]W in power network.</span>")
to_chat(user, "<span class='danger'>Total power: [DisplayPower(powernet.avail)]\nLoad: [DisplayPower(powernet.load)]\nExcess power: [DisplayPower(surplus())]</span>")
else
to_chat(user, "<span class='warning'>The cable is not powered.</span>")
to_chat(user, "<span class='danger'>The cable is not powered.</span>")
shock(user, 5, 0.2)
else if(istype(W, /obj/item/toy/crayon))
@@ -188,7 +204,7 @@ By design, d1 is the smallest direction and d2 is the highest
if(W.flags & CONDUCT)
shock(user, 50, 0.7)
src.add_fingerprint(user)
add_fingerprint(user)
// shock the user with probability prb
/obj/structure/cable/proc/shock(mob/user, prb, siemens_coeff = 1)
@@ -200,21 +216,22 @@ By design, d1 is the smallest direction and d2 is the highest
else
return FALSE
/obj/structure/cable/singularity_pull(S, current_size)
..()
if(current_size >= STAGE_FIVE)
deconstruct()
//explosion handling
/obj/structure/cable/ex_act(severity)
switch(severity)
if(1.0)
if(1)
qdel(src) // qdel
if(2.0)
if(2)
if(prob(50))
new/obj/item/stack/cable_coil(get_turf(src), src.d1 ? 2 : 1, paramcolor = color)
qdel(src) // qdel
if(3.0)
deconstruct()
if(3)
if(prob(25))
new/obj/item/stack/cable_coil(get_turf(src), src.d1 ? 2 : 1, paramcolor = color)
qdel(src) // qdel
return
deconstruct()
obj/structure/cable/proc/cable_color(var/colorC)
if(colorC)
@@ -235,7 +252,7 @@ obj/structure/cable/proc/cable_color(var/colorC)
//handles merging diagonally matching cables
//for info : direction^3 is flipping horizontally, direction^12 is flipping vertically
/obj/structure/cable/proc/mergeDiagonalsNetworks(var/direction)
/obj/structure/cable/proc/mergeDiagonalsNetworks(direction)
//search for and merge diagonally matching cables from the first direction component (north/south)
var/turf/T = get_step(src, direction&3)//go north/south
@@ -279,7 +296,7 @@ obj/structure/cable/proc/cable_color(var/colorC)
C.powernet.add_cable(src) //else, we simply connect to the matching cable powernet
// merge with the powernets of power objects in the given direction
/obj/structure/cable/proc/mergeConnectedNetworks(var/direction)
/obj/structure/cable/proc/mergeConnectedNetworks(direction)
var/fdir = (!direction)? 0 : turn(direction, 180) //flip the direction, to match with the source position on its turf
@@ -317,25 +334,27 @@ obj/structure/cable/proc/cable_color(var/colorC)
//first let's add turf cables to our powernet
//then we'll connect machines on turf with a node cable is present
for(var/AM in loc)
if(istype(AM,/obj/structure/cable))
if(istype(AM, /obj/structure/cable))
var/obj/structure/cable/C = AM
if(C.d1 == d1 || C.d2 == d1 || C.d1 == d2 || C.d2 == d2) //only connected if they have a common direction
if(C.powernet == powernet) continue
if(C.powernet == powernet)
continue
if(C.powernet)
merge_powernets(powernet, C.powernet)
else
powernet.add_cable(C) //the cable was powernetless, let's just add it to our powernet
else if(istype(AM,/obj/machinery/power/apc))
else if(istype(AM, /obj/machinery/power/apc))
var/obj/machinery/power/apc/N = AM
if(!N.terminal) continue // APC are connected through their terminal
if(!N.terminal)
continue // APC are connected through their terminal
if(N.terminal.powernet == powernet)
continue
to_connect += N.terminal //we'll connect the machines after all cables are merged
else if(istype(AM,/obj/machinery/power)) //other power machines
else if(istype(AM, /obj/machinery/power)) //other power machines
var/obj/machinery/power/M = AM
if(M.powernet == powernet)
@@ -353,23 +372,10 @@ obj/structure/cable/proc/cable_color(var/colorC)
//////////////////////////////////////////////
//if powernetless_only = 1, will only get connections without powernet
/obj/structure/cable/proc/get_connections(var/powernetless_only = 0)
/obj/structure/cable/proc/get_connections(powernetless_only = 0)
. = list() // this will be a list of all connected power objects
var/turf/T
///// Z-Level Stuff
/* if(d1 == 11 || d1 == 12)
var/turf/controllerlocation = locate(1, 1, z)
for(var/obj/effect/landmark/zcontroller/controller in controllerlocation)
if(controller.up && d1 == 12)
T = locate(src.x, src.y, controller.up_target)
if(T)
. += power_list(T, src, 11, 1)
if(controller.down && d1 == 11)
T = locate(src.x, src.y, controller.down_target)
if(T)
. += power_list(T, src, 12, 1) */
///// Z-Level Stuff
//get matching cables from the first direction
if(d1) //if not a node cable
T = get_step(src, d1)
@@ -386,20 +392,6 @@ obj/structure/cable/proc/cable_color(var/colorC)
. += power_list(loc, src, d1, powernetless_only) //get on turf matching cables
///// Z-Level Stuff
/*if(d2 == 11 || d2 == 12)
var/turf/controllerlocation = locate(1, 1, z)
for(var/obj/effect/landmark/zcontroller/controller in controllerlocation)
if(controller.up && d2 == 12)
T = locate(src.x, src.y, controller.up_target)
if(T)
. += power_list(T, src, 11, 1)
if(controller.down && d2 == 11)
T = locate(src.x, src.y, controller.down_target)
if(T)
. += power_list(T, src, 12, 1)
///// Z-Level Stuff
else */
//do the same on the second direction (which can't be 0)
T = get_step(src, d2)
if(T)
@@ -420,7 +412,8 @@ obj/structure/cable/proc/cable_color(var/colorC)
//needed as this can, unlike other placements, disconnect cables
/obj/structure/cable/proc/denode()
var/turf/T1 = loc
if(!T1) return
if(!T1)
return
var/list/powerlist = power_list(T1,src,0,0) //find the other cables that ended in the centre of the turf, with or without a powernet
if(powerlist.len>0)
@@ -428,13 +421,19 @@ obj/structure/cable/proc/cable_color(var/colorC)
propagate_network(powerlist[1],PN) //propagates the new powernet beginning at the source cable
if(PN.is_empty()) //can happen with machines made nodeless when smoothing cables
qdel(PN) // qdel
qdel(PN)
/obj/structure/cable/proc/auto_propogate_cut_cable(obj/O)
if(O && !QDELETED(O))
var/datum/powernet/newPN = new()// creates a new powernet...
propagate_network(O, newPN)//... and propagates it to the other side of the cable
// cut the cable's powernet at this cable and updates the powergrid
/obj/structure/cable/proc/cut_cable_from_powernet()
/obj/structure/cable/proc/cut_cable_from_powernet(remove=TRUE)
var/turf/T1 = loc
var/list/P_list
if(!T1) return
if(!T1)
return
if(d1)
T1 = get_step(T1, d1)
P_list = power_list(T1, src, turn(d1,180),0,cable_only = 1) // what adjacently joins on to cut cable...
@@ -452,11 +451,13 @@ obj/structure/cable/proc/cable_color(var/colorC)
var/obj/O = P_list[1]
// remove the cut cable from its turf and powernet, so that it doesn't get count in propagate_network worklist
loc = null
if(remove)
loc = null
powernet.remove_cable(src) //remove the cut cable from its powernet
// queue it to rebuild
SSmachines.deferred_powernet_rebuilds += O
// addtimer(CALLBACK(O, .proc/auto_propogate_cut_cable, O), 0) //so we don't rebuild the network X times when singulo/explosion destroys a line of X cables
// Disconnect machines connected to nodes
if(d1 == 0) // if we cut a node (O-X) cable
@@ -464,6 +465,7 @@ obj/structure/cable/proc/cable_color(var/colorC)
if(!P.connect_to_network()) //can't find a node cable on a the turf to connect to
P.disconnect_from_network() //remove from current network
///////////////////////////////////////////////
// The cable coil object, used for laying cable
///////////////////////////////////////////////
@@ -472,9 +474,7 @@ obj/structure/cable/proc/cable_color(var/colorC)
// Definitions
////////////////////////////////
var/global/list/datum/stack_recipe/cable_coil_recipes = list(
new /datum/stack_recipe/cable_restraints("cable restraints", /obj/item/restraints/handcuffs/cable, 15),
)
GLOBAL_LIST_INIT(cable_coil_recipes, list (new/datum/stack_recipe("cable restraints", /obj/item/restraints/handcuffs/cable, 15)))
/obj/item/stack/cable_coil
name = "cable coil"
@@ -514,7 +514,7 @@ var/global/list/datum/stack_recipe/cable_coil_recipes = list(
pixel_x = rand(-2,2)
pixel_y = rand(-2,2)
update_icon()
recipes = cable_coil_recipes
recipes = GLOB.cable_coil_recipes
update_wclass()
///////////////////////////////////
@@ -657,7 +657,7 @@ var/global/list/datum/stack_recipe/cable_coil_recipes = list(
to_chat(user, "<span class='warning'>You can't lay cable at a place that far away!</span>")
return
var/dirn = null
var/dirn
if(!dirnew) //If we weren't given a direction, come up with one! (Called as null from catwalk.dm and floor.dm)
if(user.loc == T)
dirn = user.dir //If laying on the tile we're on, lay in the direction we're facing
@@ -694,7 +694,7 @@ var/global/list/datum/stack_recipe/cable_coil_recipes = list(
if(C.shock(user, 50))
if(prob(50)) //fail
new /obj/item/stack/cable_coil(get_turf(C), 1, paramcolor = C.color)
qdel(C) // qdel
C.deconstruct()
return C
@@ -711,7 +711,7 @@ var/global/list/datum/stack_recipe/cable_coil_recipes = list(
return
if(get_dist(C, user) > 1) // make sure it's close enough
to_chat(user, "You can't lay cable at a place that far away.")
to_chat(user, "<span class='warning'>You can't lay cable at a place that far away!</span>")
return
@@ -724,13 +724,41 @@ var/global/list/datum/stack_recipe/cable_coil_recipes = list(
// one end of the clicked cable is pointing towards us
if(C.d1 == dirn || C.d2 == dirn)
if(U.intact) // can't place a cable if the floor is complete
to_chat(user, "You can't lay cable there unless the floor tiles are removed.")
to_chat(user, "<span class='warning'>You can't lay cable there unless the floor tiles are removed!</span>")
return
else
// cable is pointing at us, we're standing on an open tile
// so create a stub pointing at the clicked cable on our tile
place_turf(U, user, turn(dirn, 180))
var/fdirn = turn(dirn, 180) // the opposite direction
for(var/obj/structure/cable/LC in U) // check to make sure there's not a cable there already
if(LC.d1 == fdirn || LC.d2 == fdirn)
to_chat(user, "<span class='warning'>There's already a cable at that position!</span>")
return
var/obj/structure/cable/NC = get_new_cable (U)
NC.d1 = 0
NC.d2 = fdirn
NC.add_fingerprint(user)
NC.update_icon()
//create a new powernet with the cable, if needed it will be merged later
var/datum/powernet/newPN = new()
newPN.add_cable(NC)
NC.mergeConnectedNetworks(NC.d2) //merge the powernet with adjacents powernets
NC.mergeConnectedNetworksOnTurf() //merge the powernet with on turf powernets
if(NC.d2 & (NC.d2 - 1))// if the cable is layed diagonally, check the others 2 possible directions
NC.mergeDiagonalsNetworks(NC.d2)
use(1)
if(NC.shock(user, 50))
if(prob(50)) //fail
NC.deconstruct()
return
// exisiting cable doesn't point at our position, so see if it's a stub
@@ -749,7 +777,7 @@ var/global/list/datum/stack_recipe/cable_coil_recipes = list(
if(LC == C) // skip the cable we're interacting with
continue
if((LC.d1 == nd1 && LC.d2 == nd2) || (LC.d1 == nd2 && LC.d2 == nd1) ) // make sure no cable matches either direction
to_chat(user, "There's already a cable at that position.")
to_chat(user, "<span class='warning'>There's already a cable at that position!</span>")
return
@@ -776,8 +804,7 @@ var/global/list/datum/stack_recipe/cable_coil_recipes = list(
if(C.shock(user, 50))
if(prob(50)) //fail
new/obj/item/stack/cable_coil(get_turf(C), 2, paramcolor = C.color)
qdel(C) // qdel
C.deconstruct()
return
C.denode()// this call may have disconnected some cables that terminated on the centre of the turf, if so split the powernets.
@@ -790,8 +817,8 @@ var/global/list/datum/stack_recipe/cable_coil_recipes = list(
/obj/item/stack/cable_coil/cut
item_state = "coil2"
/obj/item/stack/cable_coil/cut/New(loc)
..()
/obj/item/stack/cable_coil/cut/Initialize(mapload)
. = ..()
src.amount = rand(1,2)
pixel_x = rand(-2,2)
pixel_y = rand(-2,2)
+2 -2
View File
@@ -85,8 +85,8 @@ var/const/GRAV_NEEDS_WRENCH = 3
// Generator which spawns with the station.
//
/obj/machinery/gravity_generator/main/station/Initialize()
..()
/obj/machinery/gravity_generator/main/station/Initialize(mapload)
. = ..()
setup_parts()
middle.overlays += "activated"
update_list()
+85 -71
View File
@@ -9,7 +9,7 @@
/obj/machinery/power
name = null
icon = 'icons/obj/power.dmi'
anchored = 1.0
anchored = TRUE
on_blueprints = TRUE
var/datum/powernet/powernet = null
use_power = NO_POWER_USE
@@ -25,18 +25,24 @@
//////////////////////////////
// common helper procs for all power machines
/obj/machinery/power/proc/add_avail(var/amount)
// All power generation handled in add_avail()
// Machines should use add_load(), surplus(), avail()
// Non-machines should use add_delayedload(), delayed_surplus(), newavail()
/obj/machinery/power/proc/add_avail(amount)
if(powernet)
powernet.newavail += amount
return TRUE
else
return FALSE
/obj/machinery/power/proc/draw_power(var/amount)
/obj/machinery/power/proc/add_load(amount)
if(powernet)
return powernet.draw_power(amount)
return 0
powernet.load += amount
/obj/machinery/power/proc/surplus()
if(powernet)
return powernet.avail-powernet.load
return Clamp(powernet.avail-powernet.load, 0, powernet.avail)
else
return 0
@@ -46,9 +52,19 @@
else
return 0
/obj/machinery/power/proc/load()
/obj/machinery/power/proc/add_delayedload(amount)
if(powernet)
return powernet.load
powernet.delayedload += amount
/obj/machinery/power/proc/delayed_surplus()
if(powernet)
return Clamp(powernet.newavail - powernet.delayedload, 0, powernet.newavail)
else
return 0
/obj/machinery/power/proc/newavail()
if(powernet)
return powernet.newavail
else
return 0
@@ -58,21 +74,20 @@
// 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) // defaults to power_channel
if(!loc)
return 0
return FALSE
if(!use_power)
return 1
return TRUE
var/area/A = get_area(src) // make sure it's in an area
if(!A)
return 0 // if not, then not powered
return FALSE // if not, then not powered
if(chan == -1)
chan = power_channel
return A.powered(chan) // return power status of the area
// increment the power usage stats for an area
/obj/machinery/proc/use_power(var/amount, var/chan = -1) // defaults to power_channel
/obj/machinery/proc/use_power(amount, chan = -1) // defaults to power_channel
var/area/A = get_area(src) // make sure it's in an area
if(!A)
return
@@ -103,43 +118,36 @@
/obj/machinery/power/proc/connect_to_network()
var/turf/T = src.loc
if(!T || !istype(T))
return 0
return FALSE
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
return FALSE
C.powernet.add_machine(src)
return 1
return TRUE
// remove and disconnect the machine from its current powernet
/obj/machinery/power/proc/disconnect_from_network()
if(!powernet)
return 0
return FALSE
powernet.remove_machine(src)
return 1
return TRUE
// 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/W, mob/user)
if(istype(W, /obj/item/stack/cable_coil))
var/obj/item/stack/cable_coil/coil = W
/obj/machinery/power/attackby(obj/item/I, mob/user, params)
if(istype(I, /obj/item/stack/cable_coil))
var/obj/item/stack/cable_coil/coil = I
var/turf/T = user.loc
if(T.intact || !istype(T, /turf/simulated/floor))
if(T.intact || !isfloorturf(T))
return
if(get_dist(src, user) > 1)
return
coil.place_turf(T, user)
return
else
..()
return
return ..()
///////////////////////////////////////////
// Powernet handling helpers
@@ -159,7 +167,8 @@
cdir = get_dir(T,loc)
for(var/obj/structure/cable/C in T)
if(C.powernet) continue
if(C.powernet)
continue
if(C.d1 == cdir || C.d2 == cdir)
. += C
return .
@@ -186,7 +195,8 @@
/obj/machinery/power/proc/get_indirect_connections()
. = list()
for(var/obj/structure/cable/C in loc)
if(C.powernet) continue
if(C.powernet)
continue
if(C.d1 == 0) // the cable is a node cable
. += C
return .
@@ -199,44 +209,32 @@
// 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)
/proc/power_list(turf/T, source, d, unmarked=0, 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
if(!cable_only && istype(AM,/obj/machinery/power))
for(var/AM in T)
if(AM == source)
continue //we don't want to return source
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(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))
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)
if(C.d1 == d || C.d2 == d)
. += C
return .
//remove the old powernet and replace it with a new one throughout the network.
/proc/propagate_network(var/obj/O, var/datum/powernet/PN)
//log_world("propagating new network")
/proc/propagate_network(obj/O, datum/powernet/PN)
var/list/worklist = list()
var/list/found_machines = list()
var/index = 1
@@ -248,13 +246,13 @@
P = worklist[index] //get the next power object found
index++
if( istype(P,/obj/structure/cable))
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))
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
@@ -268,7 +266,7 @@
//Merge two powernets, the bigger (in cable length term) absorbing the other
/proc/merge_powernets(var/datum/powernet/net1, var/datum/powernet/net2)
/proc/merge_powernets(datum/powernet/net1, datum/powernet/net2)
if(!net1 || !net2) //if one of the powernet doesn't exist, return
return
@@ -285,8 +283,6 @@
for(var/obj/structure/cable/Cable in net2.cables) //merge cables
net1.add_cable(Cable)
if(!net2) return net1
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
@@ -299,14 +295,12 @@
//source is an object caused electrocuting (airlock, grille, etc)
//No animations will be performed by this proc.
/proc/electrocute_mob(mob/living/M, power_source, obj/source, siemens_coeff = 1, dist_check = FALSE)
if(!istype(M))
return FALSE
if(istype(M.loc,/obj/mecha))
if(!M || ismecha(M.loc))
return FALSE //feckin mechs are dumb
if(dist_check)
if(!in_range(source, M))
return FALSE
if(istype(M,/mob/living/carbon/human))
if(ishuman(M))
var/mob/living/carbon/human/H = M
if(H.gloves)
var/obj/item/clothing/gloves/G = H.gloves
@@ -326,7 +320,7 @@
if(istype(power_source, /datum/powernet))
PN = power_source
else if(istype(power_source,/obj/item/stock_parts/cell))
else if(istype(power_source, /obj/item/stock_parts/cell))
cell = power_source
else if(istype(power_source, /obj/machinery/power/apc))
var/obj/machinery/power/apc/apc = power_source
@@ -357,10 +351,30 @@
var/drained_energy = drained_hp*20
if(source_area)
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"
drained_power = PN.draw_power(drained_power)
else if(istype(power_source, /obj/item/stock_parts/cell))
source_area.use_power(drained_energy/GLOB.CELLRATE)
else if(istype(power_source, /datum/powernet))
var/drained_power = drained_energy/GLOB.CELLRATE //convert from "joules" to "watts"
PN.delayedload += (min(drained_power, max(PN.newavail - PN.delayedload, 0)))
else if (istype(power_source, /obj/item/stock_parts/cell))
cell.use(drained_energy)
return drained_energy
////////////////////////////////////////////////
// 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(!can_have_cabling())
return null
for(var/obj/structure/cable/C in src)
if(C.d1 == 0)
return C
return null
/area/proc/get_apc()
for(var/obj/machinery/power/apc/APC in GLOB.apcs)
if(APC.area == src)
return APC
+22 -77
View File
@@ -1,19 +1,19 @@
////////////////////////////////////////////
// POWERNET DATUM
// each contiguous network of cables & nodes
/////////////////////////////////////
/datum/powernet
var/number // unique id
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/viewavail = 0 // the available power as it appears on the power console (gradually updated)
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.
var/netexcess = 0 // excess power on the powernet (typically avail-load)///////
var/delayedload = 0 // load applied to powernet between power ticks.
/datum/powernet/New()
SSmachines.powernets += src
@@ -31,31 +31,21 @@
SSmachines.powernets -= src
return ..()
//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)
/datum/powernet/proc/remove_cable(obj/structure/cable/C)
cables -= C
C.powernet = null
if(is_empty())//the powernet is now empty...
qdel(src)///... delete it - qdel
qdel(src)///... delete it
//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)
/datum/powernet/proc/add_cable(obj/structure/cable/C)
if(C.powernet)// if C already has a powernet...
if(C.powernet == src)
return
@@ -67,16 +57,16 @@
//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)
/datum/powernet/proc/remove_machine(obj/machinery/power/M)
nodes -=M
M.powernet = null
if(is_empty())//the powernet is now empty...
qdel(src)///... delete it - qdel
qdel(src)///... delete it
//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)
/datum/powernet/proc/add_machine(obj/machinery/power/M)
if(M.powernet)// if M already has a powernet...
if(M.powernet == src)
return
@@ -85,45 +75,23 @@
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++
//see if there's a surplus of power remaining in the powernet and stores unused power in the SMES
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)
// update power consoles
viewavail = round(0.8 * viewavail + 0.2 * avail)
viewload = round(0.8 * viewload + 0.2 * load)
//reset the powernet
load = 0
// reset the powernet
load = delayedload
delayedload = 0
avail = newavail
newavail = 0
@@ -131,27 +99,4 @@
if(avail >= 1000)
return Clamp(20 + round(avail / 25000), 20, 195) + rand(-5, 5)
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
return 0
+2 -2
View File
@@ -15,8 +15,8 @@ var/global/list/rad_collectors = list()
var/locked = 0
var/drainratio = 1
/obj/machinery/power/rad_collector/New()
..()
/obj/machinery/power/rad_collector/Initialize(mapload)
. = ..()
rad_collectors += src
/obj/machinery/power/rad_collector/Destroy()
+60 -40
View File
@@ -23,18 +23,25 @@
var/frequency = 0
var/id_tag = null
var/projectile_type = /obj/item/projectile/beam/emitter
var/projectile_sound = 'sound/weapons/emitter.ogg'
var/datum/radio_frequency/radio_connection
var/datum/effect_system/spark_spread/sparks
/obj/machinery/power/emitter/New()
..()
/obj/machinery/power/emitter/Initialize(mapload)
. = ..()
component_parts = list()
component_parts += new /obj/item/circuitboard/emitter(null)
component_parts += new /obj/item/stock_parts/micro_laser(null)
component_parts += new /obj/item/stock_parts/manipulator(null)
RefreshParts()
if(state == 2 && anchored)
connect_to_network()
sparks = new
sparks.attach(src)
sparks.set_up(5, 1, src)
if(frequency)
set_frequency(frequency)
/obj/machinery/power/emitter/RefreshParts()
var/max_firedelay = 120
@@ -79,13 +86,6 @@
return
rotate()
/obj/machinery/power/emitter/Initialize()
..()
if(state == 2 && anchored)
connect_to_network()
if(frequency)
set_frequency(frequency)
/obj/machinery/power/emitter/multitool_menu(var/mob/user,var/obj/item/multitool/P)
return {"
<ul>
@@ -182,10 +182,9 @@
src.active = 0
update_icon()
return
if(((src.last_shot + src.fire_delay) <= world.time) && (src.active == 1))
var/actual_load = draw_power(active_power_usage)
if(actual_load >= active_power_usage) //does the laser have enough power to shoot?
if(active == TRUE)
if(!active_power_usage || surplus() >= active_power_usage)
add_load(active_power_usage)
if(!powered)
powered = 1
update_icon()
@@ -197,36 +196,57 @@
investigate_log("lost power and turned <font color='red'>off</font>","singulo")
return
src.last_shot = world.time
if(src.shot_number < 3)
src.fire_delay = 2
src.shot_number++
else
src.fire_delay = rand(minimum_fire_delay,maximum_fire_delay)
src.shot_number = 0
if(!check_delay())
return FALSE
fire_beam()
var/obj/item/projectile/beam/emitter/A = new /obj/item/projectile/beam/emitter(src.loc)
/obj/machinery/power/emitter/proc/check_delay()
if((last_shot + fire_delay) <= world.time)
return TRUE
return FALSE
A.dir = src.dir
playsound(get_turf(src), 'sound/weapons/emitter.ogg', 25, 1)
if(prob(35))
sparks.start()
switch(dir)
if(NORTH)
A.yo = 20
A.xo = 0
if(EAST)
A.yo = 0
A.xo = 20
if(WEST)
A.yo = 0
A.xo = -20
else // Any other
A.yo = -20
A.xo = 0
A.fire() //TODO: Carn: check this out
/obj/machinery/power/emitter/proc/fire_beam()
var/obj/item/projectile/P = new projectile_type(get_turf(src))
playsound(get_turf(src), projectile_sound, 50, TRUE)
if(prob(35))
sparks.start()
switch(dir)
if(NORTH)
P.yo = 20
P.xo = 0
if(NORTHEAST)
P.yo = 20
P.xo = 20
if(EAST)
P.yo = 0
P.xo = 20
if(SOUTHEAST)
P.yo = -20
P.xo = 20
if(WEST)
P.yo = 0
P.xo = -20
if(SOUTHWEST)
P.yo = -20
P.xo = -20
if(NORTHWEST)
P.yo = 20
P.xo = -20
else // Any other
P.yo = -20
P.xo = 0
last_shot = world.time
if(shot_number < 3)
fire_delay = 20
shot_number ++
else
fire_delay = rand(minimum_fire_delay, maximum_fire_delay)
shot_number = 0
P.setDir(dir)
P.starting = loc
P.fire()
return P
/obj/machinery/power/emitter/attackby(obj/item/W, mob/user, params)
if(istype(W, /obj/item/multitool))
@@ -48,8 +48,8 @@ field_generator power level display
overlays += "+p[power_level]"
/obj/machinery/field/generator/New()
..()
/obj/machinery/field/generator/Initialize(mapload)
. = ..()
fields = list()
connected_gens = list()
@@ -2,11 +2,12 @@
name = "Accelerated Particles"
desc = "Small things moving very fast."
icon = 'icons/obj/machines/particle_accelerator.dmi'
icon_state = "particle"//Need a new icon for this
anchored = 1
density = 1
icon_state = "particle"
anchored = TRUE
density = FALSE
var/movement_range = 10
var/energy = 10
var/speed = 1
/obj/effect/accelerated_particle/weak
movement_range = 8
@@ -21,50 +22,45 @@
energy = 50
/obj/effect/accelerated_particle/New(loc, dir = 2)
src.loc = loc
src.dir = dir
/obj/effect/accelerated_particle/New(loc)
..()
if(movement_range > 20)
movement_range = 20
spawn(0)
move(1)
return
addtimer(CALLBACK(src, .proc/move), 1)
/obj/effect/accelerated_particle/Bump(atom/A)
if(A)
if(ismob(A))
if(isliving(A))
toxmob(A)
if((istype(A,/obj/machinery/the_singularitygen))||(istype(A,/obj/singularity/)))
A:energy += energy
return
else if(istype(A, /obj/machinery/the_singularitygen))
var/obj/machinery/the_singularitygen/S = A
S.energy += energy
else if(istype(A, /obj/singularity))
var/obj/singularity/S = A
S.energy += energy
/obj/effect/accelerated_particle/Bumped(atom/A)
if(ismob(A))
Bump(A)
return
/obj/effect/accelerated_particle/Crossed(atom/A)
if(isliving(A))
toxmob(A)
/obj/effect/accelerated_particle/ex_act(severity)
qdel(src)
/obj/effect/accelerated_particle/singularity_pull()
return
/obj/effect/accelerated_particle/proc/toxmob(var/mob/living/M)
M.apply_effect((energy*6),IRRADIATE,0)
M.updatehealth()
return
/obj/effect/accelerated_particle/proc/toxmob(mob/living/M)
M.apply_effect((energy * 6), IRRADIATE, 0)
/obj/effect/accelerated_particle/proc/move(var/lag)
/obj/effect/accelerated_particle/proc/move()
if(!step(src,dir))
src.loc = get_step(src,dir)
forceMove(get_step(src, dir))
movement_range--
if(movement_range <= 0)
if(movement_range == 0)
qdel(src)
else
sleep(lag)
move(lag)
sleep(speed)
move()
@@ -19,11 +19,11 @@
var/parts = null
var/datum/wires/particle_acc/control_box/wires = null
/obj/machinery/particle_accelerator/control_box/New()
/obj/machinery/particle_accelerator/control_box/Initialize(mapload)
. = ..()
wires = new(src)
connected_parts = list()
update_icon()
..()
/obj/machinery/particle_accelerator/control_box/Destroy()
if(active)
@@ -29,21 +29,20 @@
return 0
/obj/structure/particle_accelerator/particle_emitter/proc/emit_particle(var/strength = 0)
/obj/structure/particle_accelerator/particle_emitter/proc/emit_particle(strength = 0)
if((last_shot + fire_delay) <= world.time)
last_shot = world.time
var/obj/effect/accelerated_particle/A = null
var/turf/T = get_step(src, dir)
var/turf/T = get_turf(src)
var/obj/effect/accelerated_particle/P
switch(strength)
if(0)
A = new/obj/effect/accelerated_particle/weak(T, dir)
P = new/obj/effect/accelerated_particle/weak(T)
if(1)
A = new/obj/effect/accelerated_particle(T, dir)
P = new/obj/effect/accelerated_particle(T)
if(2)
A = new/obj/effect/accelerated_particle/strong(T, dir)
P = new/obj/effect/accelerated_particle/strong(T)
if(3)
A = new/obj/effect/accelerated_particle/powerful(T, dir)
if(A)
A.dir = dir
return 1
return 0
P = new/obj/effect/accelerated_particle/powerful(T)
P.setDir(dir)
return TRUE
return FALSE
@@ -3,8 +3,4 @@
desc_holder = "This part uses electromagnetic waves to focus the Alpha particles."
icon = 'icons/obj/machines/particle_accelerator.dmi'
icon_state = "power_box"
reference = "power_box"
/obj/structure/particle_accelerator/power_box/update_icon()
..()
return
reference = "power_box"
+60 -59
View File
@@ -11,20 +11,20 @@
name = "power storage unit"
desc = "A high-capacity superconducting magnetic energy storage (SMES) unit."
icon_state = "smes"
density = 1
anchored = 1
density = TRUE
use_power = NO_POWER_USE
var/capacity = 5e6 // maximum charge
var/charge = 0 // 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_attempt = TRUE // 1 = attempting to charge, 0 = not attempting to charge
var/inputting = TRUE // 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_attempt = TRUE // 1 = attempting to output, 0 = not attempting to output
var/outputting = TRUE // 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
@@ -34,13 +34,11 @@
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
/obj/machinery/power/smes/New()
..()
/obj/machinery/power/smes/Initialize(mapload)
. = ..()
component_parts = list()
component_parts += new /obj/item/circuitboard/smes(null)
component_parts += new /obj/item/stock_parts/cell/high(null)
@@ -52,28 +50,22 @@
component_parts += new /obj/item/stack/cable_coil(null, 5)
RefreshParts()
spawn(5)
if(!powernet)
connect_to_network()
dir_loop:
for(var/d in cardinal)
var/turf/T = get_step(src, d)
for(var/obj/machinery/power/terminal/term in T)
if(term && term.dir == turn(d, 180))
terminal = term
break dir_loop
dir_loop:
for(var/d in cardinal)
var/turf/T = get_step(src, d)
for(var/obj/machinery/power/terminal/term in T)
if(term && term.dir == turn(d, 180))
terminal = term
break dir_loop
if(!terminal)
stat |= BROKEN
return
terminal.master = src
if(!terminal.powernet)
terminal.connect_to_network()
update_icon()
return
if(!terminal)
stat |= BROKEN
return
terminal.master = src
update_icon()
/obj/machinery/power/smes/upgraded/New()
..()
/obj/machinery/power/smes/upgraded/Initialize(mapload)
. = ..()
component_parts = list()
component_parts += new /obj/item/circuitboard/smes(null)
component_parts += new /obj/item/stock_parts/cell/hyper(null)
@@ -222,8 +214,8 @@
return round(5.5*charge/(capacity ? capacity : 5e6))
/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()
@@ -231,33 +223,46 @@
var/last_onln = outputting
//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(terminal && input_attempt)
input_available = terminal.surplus()
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
if(inputting)
if(input_available > 0) // if there's power available, try to charge
var/load = min(min((capacity-charge)/SMESRATE, input_level), input_available) // charge at set rate, limited to spare capacity
charge += load * SMESRATE // increase the charge
terminal.add_load(load) // add the load to the terminal side network
else // if not enough capcity
inputting = FALSE // stop inputting
else
if(input_attempt && input_available > 0)
inputting = TRUE
else
inputting = FALSE
//outputting
if(outputting)
output_used = min( charge/SMESRATE, output_level) //limit output to that stored
if(output_attempt)
if(outputting)
output_used = min( charge/SMESRATE, output_level) //limit output to that stored
charge -= output_used*SMESRATE // reduce the storage (may be recovered in /restore() if excessive)
if (add_avail(output_used)) // add output to powernet if it exists (smes side)
charge -= output_used*SMESRATE // reduce the storage (may be recovered in /restore() if excessive)
else
outputting = FALSE
add_avail(output_used) // add output to powernet (smes side)
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
if(output_used < 0.0001) // either from no charge or set to 0
outputting = FALSE
investigate_log("lost power and turned <font color='red'>off</font>", "singulo")
else if(output_attempt && charge > output_level && output_level > 0)
outputting = TRUE
else
output_used = 0
else
output_used = 0
outputting = FALSE
// only update icon if state changed
if(last_disp != chargedisplay() || last_chrg != inputting || last_onln != outputting)
@@ -333,11 +338,6 @@
return 0
return 1
/obj/machinery/power/smes/draw_power(var/amount)
if(terminal && terminal.powernet)
return terminal.powernet.draw_power(amount)
return 0
/obj/machinery/power/smes/attack_ai(mob/user)
add_hiddenprint(user)
ui_interact(user)
@@ -483,7 +483,8 @@
output_level = 250000
/obj/machinery/power/smes/magical/process()
charge = 5000000
capacity = INFINITY
charge = INFINITY
..()
#undef SMESRATE
+4 -5
View File
@@ -6,8 +6,7 @@
desc = "A solar panel. Generates electricity when in contact with sunlight."
icon = 'icons/obj/power.dmi'
icon_state = "sp_base"
anchored = 1
density = 1
density = TRUE
use_power = NO_POWER_USE
idle_power_usage = 0
active_power_usage = 0
@@ -20,8 +19,8 @@
var/turn_angle = 0
var/obj/machinery/power/solar_control/control = null
/obj/machinery/power/solar/New(var/turf/loc, var/obj/item/solar_assembly/S)
..(loc)
/obj/machinery/power/solar/Initialize(mapload, obj/item/solar_assembly/S)
. = ..()
Make(S)
connect_to_network()
@@ -118,7 +117,7 @@
return
sunfrac = cos(p_angle) ** 2
//isn't the power recieved from the incoming light proportionnal to cos(p_angle) (Lambert's cosine law) rather than cos(p_angle)^2 ?
//isn't the power received from the incoming light proportionnal to cos(p_angle) (Lambert's cosine law) rather than cos(p_angle)^2 ?
/obj/machinery/power/solar/process()//TODO: remove/add this from machines to save on processing as needed ~Carn PRIORITY
if(stat & BROKEN)
-84
View File
@@ -1,84 +0,0 @@
//This is a power switch. When turned on it looks at the cables around the tile that it's on and notes which cables are trying to connect to it.
//After it knows this it creates the number of cables from the center to each of the cables attempting to conenct. These cables cannot be removed
//with wirecutters. When the switch is turned off it removes all the cables on the tile it's on.
//The switch uses a 5s delay to prevent powernet change spamming.
/*
/obj/structure/powerswitch
name = "power switch"
desc = "A switch that controls power."
icon = 'icons/obj/power.dmi'
icon_state = "switch-dbl-up"
var/icon_state_on = "switch-dbl-down"
var/icon_state_off = "switch-dbl-up"
density = 0
anchored = 1
var/on = 0 //up is off, down is on
var/busy = 0 //set to 1 when you start pulling
/obj/structure/powerswitch/simple
icon_state = "switch-up"
icon_state_on = "switch-down"
icon_state_off = "switch-up"
/obj/structure/powerswitch/examine(mob/user)
..(user)
if(on)
to_chat(user, "The switch is in the on position")
else
to_chat(user, "The switch is in the off position")
/obj/structure/powerswitch/attack_ai(mob/user)
to_chat(user, "<span class='warning'>You're an AI. This is a manual switch. It's not going to work.</span>")
return
/obj/structure/powerswitch/attack_hand(mob/user)
if(busy)
to_chat(user, "<span class='warning'>This switch is already being toggled.</span>")
return
..()
busy = 1
for(var/mob/O in viewers(user))
O.show_message(text("<span class='warning'>[user] starts pulling the [src].</span>"), 1)
if(do_after(user, 50, target = src))
set_state(!on)
for(var/mob/O in viewers(user))
O.show_message(text("<span class='warning'>[user] flips the [src] into the [on ? </span>"on": "off"] position."), 1)
busy = 0
/obj/structure/powerswitch/proc/set_state(var/state)
on = state
if(on)
icon_state = icon_state_on
var/list/connection_dirs = list()
for(var/direction in list(1,2,4,8,5,6,9,10))
for(var/obj/structure/cable/C in get_step(src,direction))
if(C.d1 == turn(direction, 180) || C.d2 == turn(direction, 180))
connection_dirs += direction
break
for(var/direction in connection_dirs)
var/obj/structure/cable/C = new/obj/structure/cable(src.loc)
C.d1 = 0
C.d2 = direction
C.icon_state = "[C.d1]-[C.d2]"
C.power_switch = src
var/datum/powernet/PN = new()
PN.number = powernets.len + 1
powernets += PN
C.netnum = PN.number
PN.cables += C
C.mergeConnectedNetworks(C.d2)
C.mergeConnectedNetworksOnTurf()
else
icon_state = icon_state_off
for(var/obj/structure/cable/C in src.loc)
qdel(C)
*/
+9 -10
View File
@@ -8,25 +8,24 @@
icon_state = "term"
desc = "It's an underfloor wiring terminal for power equipment."
level = 1
layer = TURF_LAYER
layer = WIRE_TERMINAL_LAYER //a bit above wires
var/obj/machinery/power/master = null
anchored = 1
layer = 2.6 // a bit above wires
/obj/machinery/power/terminal/New()
..()
var/turf/T = src.loc
if(level==1) hide(T.intact)
return
/obj/machinery/power/terminal/Initialize(mapload)
. = ..()
var/turf/T = get_turf(src)
if(level == 1)
hide(T.intact)
/obj/machinery/power/terminal/Destroy()
if(master)
master.disconnect_terminal()
master = null
return ..()
/obj/machinery/power/terminal/hide(var/i)
/obj/machinery/power/terminal/hide(i)
if(i)
invisibility = 101
icon_state = "term-f"
+5 -5
View File
@@ -12,8 +12,8 @@
var/last_zap = 0
var/datum/wires/tesla_coil/wires = null
/obj/machinery/power/tesla_coil/New()
..()
/obj/machinery/power/tesla_coil/Initialize(mapload)
. = ..()
component_parts = list()
component_parts += new /obj/item/circuitboard/tesla_coil(null)
component_parts += new /obj/item/stock_parts/capacitor(null)
@@ -77,7 +77,7 @@
var/coeff = (20 - ((input_power_multiplier - 1) * 3))
coeff = max(coeff, 10)
var/power = (powernet.avail/2)
draw_power(power)
add_load(power)
playsound(src.loc, 'sound/magic/lightningshock.ogg', 100, 1, extrarange = 5)
tesla_zap(src, 10, power/(coeff/2))
@@ -89,8 +89,8 @@
anchored = 0
density = 1
/obj/machinery/power/grounding_rod/New()
..()
/obj/machinery/power/grounding_rod/Initialize(mapload)
. = ..()
component_parts = list()
component_parts += new /obj/item/circuitboard/grounding_rod(null)
component_parts += new /obj/item/stock_parts/capacitor(null)
+9 -10
View File
@@ -8,16 +8,15 @@
desc = "A solar directional tracker."
icon = 'icons/obj/power.dmi'
icon_state = "tracker"
anchored = 1
density = 1
density = TRUE
use_power = NO_POWER_USE
var/id = 0
var/sun_angle = 0 // sun angle as set by sun datum
var/obj/machinery/power/solar_control/control = null
/obj/machinery/power/tracker/New(var/turf/loc, var/obj/item/solar_assembly/S)
..(loc)
/obj/machinery/power/tracker/Initialize(mapload, obj/item/solar_assembly/S)
. = ..()
Make(S)
connect_to_network()
@@ -26,7 +25,7 @@
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)
/obj/machinery/power/tracker/proc/set_control(obj/machinery/power/solar_control/SC)
if(SC && (get_dist(src, SC) > SOLAR_MAX_DIST))
return 0
control = SC
@@ -39,21 +38,21 @@
control.connected_tracker = null
control = null
/obj/machinery/power/tracker/proc/Make(var/obj/item/solar_assembly/S)
/obj/machinery/power/tracker/proc/Make(obj/item/solar_assembly/S)
if(!S)
S = new /obj/item/solar_assembly(src)
S.glass_type = /obj/item/stack/sheet/glass
S.tracker = 1
S.anchored = 1
S.loc = src
S.anchored = TRUE
S.forceMove(src)
update_icon()
//updates the tracker icon and the facing angle for the control computer
/obj/machinery/power/tracker/proc/set_angle(var/angle)
/obj/machinery/power/tracker/proc/set_angle(angle)
sun_angle = angle
//set icon dir to show sun illumination
dir = turn(NORTH, -angle - 22.5) // 22.5 deg bias ensures, e.g. 67.5-112.5 is EAST
setDir(turn(NORTH, -angle - 22.5)) // 22.5 deg bias ensures, e.g. 67.5-112.5 is EAST
if(powernet && (powernet == control.powernet)) //update if we're still in the same powernet
control.cdir = angle
+4 -5
View File
@@ -7,7 +7,6 @@
name = "treadmill"
desc = "A power-generating treadmill."
layer = 2.2
anchored = 1
use_power = NO_POWER_USE
var/speed = 0
@@ -18,8 +17,8 @@
var/list/mobs_running[0]
var/id = null // for linking to monitor
/obj/machinery/power/treadmill/Initialize()
..()
/obj/machinery/power/treadmill/Initialize(mapload)
. = ..()
if(anchored)
connect_to_network()
@@ -138,8 +137,8 @@
var/frame = 0 // on 0, show labels, on 1 show numbers
var/redeem_immediately = 0 // redeem immediately for holding cell
/obj/machinery/treadmill_monitor/Initialize()
..()
/obj/machinery/treadmill_monitor/Initialize(mapload)
. = ..()
if(id)
for(var/obj/machinery/power/treadmill/T in GLOB.machines)
if(T.id == id)
+4 -12
View File
@@ -64,8 +64,8 @@
// the inlet stage of the gas turbine electricity generator
/obj/machinery/power/compressor/New()
..()
/obj/machinery/power/compressor/Initialize(mapload)
. = ..()
component_parts = list()
component_parts += new /obj/item/circuitboard/power_compressor(null)
component_parts += new /obj/item/stock_parts/manipulator(null)
@@ -80,10 +80,6 @@
gas_contained = new
inturf = get_step(src, dir)
/obj/machinery/power/compressor/Initialize()
..()
locate_machinery()
if(!turbine)
stat |= BROKEN
@@ -185,8 +181,8 @@
#define TURBGENQ 100000
#define TURBGENG 0.5
/obj/machinery/power/turbine/New()
..()
/obj/machinery/power/turbine/Initialize(mapload)
. = ..()
component_parts = list()
component_parts += new /obj/item/circuitboard/power_turbine(src)
component_parts += new /obj/item/stock_parts/capacitor(src)
@@ -200,10 +196,6 @@
// The outlet is pointed at the direction of the turbine component
outturf = get_step(src, dir)
/obj/machinery/power/turbine/Initialize()
..()
locate_machinery()
if(!compressor)
stat |= BROKEN