diff --git a/code/game/mecha/equipment/tools/medical_tools.dm b/code/game/mecha/equipment/tools/medical_tools.dm index 36e06a0d793..a64a8485aff 100644 --- a/code/game/mecha/equipment/tools/medical_tools.dm +++ b/code/game/mecha/equipment/tools/medical_tools.dm @@ -365,9 +365,7 @@ if(!PN) PN = new() - powernets += PN - NC.powernet = PN - PN.cables += NC + PN.add_cable(NC) NC.mergeConnectedNetworks(NC.d2) //NC.mergeConnectedNetworksOnTurf() diff --git a/code/modules/power/breaker_box.dm b/code/modules/power/breaker_box.dm index b951b379e43..e0469d6da00 100644 --- a/code/modules/power/breaker_box.dm +++ b/code/modules/power/breaker_box.dm @@ -80,9 +80,7 @@ C.breaker_box = src var/datum/powernet/PN = new() - PN.number = powernets.len + 1 - powernets += PN - PN.cables += C + PN.add_cable(C) C.mergeConnectedNetworks(C.d2) C.mergeConnectedNetworksOnTurf() diff --git a/code/modules/power/cable.dm b/code/modules/power/cable.dm index 73a3eca3c43..4ec599d6371 100644 --- a/code/modules/power/cable.dm +++ b/code/modules/power/cable.dm @@ -382,9 +382,8 @@ C.add_fingerprint(user) C.updateicon() - C.powernet = new() - powernets += C.powernet - C.powernet.cables += C + var/datum/powernet/PN = new() + PN.add_cable(C) C.mergeConnectedNetworks(C.d2) C.mergeConnectedNetworksOnTurf() @@ -396,8 +395,7 @@ D.add_fingerprint(user) D.updateicon() - D.powernet = C.powernet - D.powernet.cables += D + PN.add_cable(D) D.mergeConnectedNetworksOnTurf() @@ -419,13 +417,14 @@ C.add_fingerprint(user) C.updateicon() - C.powernet = new() - powernets += C.powernet - C.powernet.cables += C + var/datum/powernet/PN = new() + PN.add_cable(C) C.mergeConnectedNetworks(C.d2) C.mergeConnectedNetworksOnTurf() + if(C.d2 & (C.d2 - 1))// if the cable is layed diagonally, check the others 2 possible directions + C.mergeDiagonalsNetworks(C.d2) use(1) if (C.shock(user, 50)) @@ -454,8 +453,9 @@ return - if(U == T) // do nothing if we clicked a cable we're standing on - return // may change later if can think of something logical to do + if(U == T) //if clicked on the turf we're standing on, try to put a cable in the direction we're facing + turf_place(T,user) + return var/dirn = get_dir(C, user) @@ -482,11 +482,16 @@ NC.add_fingerprint() NC.updateicon() - if(C.powernet) - NC.powernet = C.powernet - NC.powernet.cables += NC - NC.mergeConnectedNetworks(NC.d2) - NC.mergeConnectedNetworksOnTurf() + //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 @@ -526,14 +531,67 @@ C.mergeConnectedNetworks(C.d2) C.mergeConnectedNetworksOnTurf() + if(C.d1 & (C.d1 - 1))// if the cable is layed diagonally, check the others 2 possible directions + C.mergeDiagonalsNetworks(C.d1) + + if(C.d2 & (C.d2 - 1))// if the cable is layed diagonally, check the others 2 possible directions + C.mergeDiagonalsNetworks(C.d2) + use(1) if (C.shock(user, 50)) if (prob(50)) //fail new/obj/item/stack/cable_coil(C.loc, 2, C.color) del(C) + return + C.denode()// this call may have disconnected some cables that terminated on the centre of the turf, if so split the powernets. return +//handles merging diagonally matching cables +//for info : direction^3 is flipping horizontally, direction^12 is flipping vertically +/obj/structure/cable/proc/mergeDiagonalsNetworks(var/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 + + for(var/obj/structure/cable/C in T) + + if(!C) + continue + + if(src == C) + continue + + if(C.d1 == (direction^3) || C.d2 == (direction^3)) //we've got a diagonally matching cable + if(!C.powernet) //if the matching cable somehow got no powernet, make him one (should not happen for cables) + var/datum/powernet/newPN = new() + newPN.add_cable(C) + + if(powernet) //if we already have a powernet, then merge the two powernets + merge_powernets(powernet,C.powernet) + else + C.powernet.add_cable(src) //else, we simply connect to the matching cable powernet + + //the same from the second direction component (east/west) + T = get_step(src, direction&12)//go east/west + + for(var/obj/structure/cable/C in T) + + if(!C) + continue + + if(src == C) + continue + if(C.d1 == (direction^12) || C.d2 == (direction^12)) //we've got a diagonally matching cable + if(!C.powernet) //if the matching cable somehow got no powernet, make him one (should not happen for cables) + var/datum/powernet/newPN = new() + newPN.add_cable(C) + + if(powernet) //if we already have a powernet, then merge the two powernets + merge_powernets(powernet,C.powernet) + else + C.powernet.add_cable(src) //else, we simply connect to the matching cable powernet + /obj/structure/cable/proc/mergeConnectedNetworks(var/direction) var/turf/TB if(!(d1 == direction || d2 == direction)) @@ -553,53 +611,69 @@ if(TC.d1 == fdir || TC.d2 == fdir) if(!TC.powernet) - TC.powernet = new() - powernets += TC.powernet - TC.powernet.cables += TC + var/datum/powernet/PN = new() + PN.add_cable(TC) if(powernet) merge_powernets(powernet,TC.powernet) else - powernet = TC.powernet - powernet.cables += src - - - + TC.powernet.add_cable(src) +// merge with the powernets of power objects in the source turf /obj/structure/cable/proc/mergeConnectedNetworksOnTurf() - if(!powernet) - powernet = new() - powernets += powernet - powernet.cables += src + var/list/to_connect = list() + if(!powernet) //if we somehow have no powernet, make one (should not happen for cables) + var/datum/powernet/newPN = new() + newPN.add_cable(src) + + //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)) var/obj/structure/cable/C = AM - if(C.powernet == powernet) continue - if(C.powernet) - merge_powernets(powernet, C.powernet) - else - C.powernet = powernet - powernet.cables += C + 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) + 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)) var/obj/machinery/power/apc/N = AM - if(!N.terminal) continue - if(N.terminal.powernet) - merge_powernets(powernet, N.terminal.powernet) - else - N.terminal.powernet = powernet - powernet.nodes[N.terminal] = N.terminal + if(!N.terminal) continue // APC are connected through their terminal - else if(istype(AM,/obj/machinery/power)) + 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 var/obj/machinery/power/M = AM - if(M.powernet == powernet) continue - if(M.powernet) - merge_powernets(powernet, M.powernet) - else - M.powernet = powernet - powernet.nodes[M] = M + if(M.powernet == powernet) + continue + + to_connect += M //we'll connect the machines after all cables are merged + + //now that cables are done, let's connect found machines + for(var/obj/machinery/power/PM in to_connect) + if(!PM.connect_to_network()) + PM.disconnect_from_network() //if we somehow can't connect the machine to the new powernet, remove it from the old nonetheless + +//should be called after placing a cable which extends another cable, creating a "smooth" cable that no longer terminates in the centre of a turf. +//needed as this can, unlike other placements, disconnect cables +/obj/structure/cable/proc/denode() + var/turf/T1 = loc + 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) + var/datum/powernet/PN = new() + 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 + del(PN) obj/structure/cable/proc/cableColor(var/colorC) var/color_n = "#DD0000" diff --git a/code/modules/power/power.dm b/code/modules/power/power.dm index 82936a1dc83..c28a786698f 100644 --- a/code/modules/power/power.dm +++ b/code/modules/power/power.dm @@ -101,7 +101,6 @@ 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) @@ -231,22 +230,24 @@ . += C 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 - 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 + if(!T || !istype(T)) + return 0 + + 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) - //world << " no powernet" return 0 - powernet.nodes -= src - powernet = null - //world << "powernet null" + powernet.remove_machine(src) return 1 /turf/proc/get_cable_node() diff --git a/code/modules/power/powernet.dm b/code/modules/power/powernet.dm index 1fbcc6f1c9a..72635968f6b 100644 --- a/code/modules/power/powernet.dm +++ b/code/modules/power/powernet.dm @@ -8,11 +8,61 @@ var/avail = 0 var/viewload = 0 var/number = 0 - + var/perapc = 0 // per-apc avilability var/perapc_excess = 0 var/netexcess = 0 +/datum/powernet/New() + powernets += src + +/datum/powernet/Del() + powernets -= src + +/datum/powernet/proc/is_empty() + return !cables.len && !nodes.len + +//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 + +//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 + /datum/powernet/proc/process() load = newload newload = 0 @@ -41,7 +91,7 @@ perapc_excess += min(netexcess/numapc, (avail - perapc) - perapc_excess) else perapc_excess = 0 - + perapc = avail/numapc + perapc_excess if( netexcess > 100) // if there was excess power last cycle @@ -70,7 +120,7 @@ var/surplus = max(avail - newload, 0) var/actual_draw = min(requested_amount, surplus) newload += actual_draw - + return actual_draw // cut a powernet at this cable object @@ -151,9 +201,7 @@ 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 + PN.add_cable(Cable) continue i++ @@ -258,8 +306,39 @@ 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 + net1.add_cable(Cable) del(net2) - return net1 \ No newline at end of file + return net1 + +//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 + continue + + //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 \ No newline at end of file