This commit is contained in:
RavingManiac
2014-10-27 20:48:25 +08:00
47 changed files with 2329 additions and 1961 deletions

View File

@@ -164,6 +164,11 @@
#include "code\datums\spells\trigger.dm" #include "code\datums\spells\trigger.dm"
#include "code\datums\spells\turf_teleport.dm" #include "code\datums\spells\turf_teleport.dm"
#include "code\datums\spells\wizard.dm" #include "code\datums\spells\wizard.dm"
#include "code\datums\wires\apc.dm"
#include "code\datums\wires\smartfridge.dm"
#include "code\datums\wires\suit_storage_unit.dm"
#include "code\datums\wires\vending.dm"
#include "code\datums\wires\wires.dm"
#include "code\defines\obj.dm" #include "code\defines\obj.dm"
#include "code\defines\obj\weapon.dm" #include "code\defines\obj\weapon.dm"
#include "code\defines\procs\admin.dm" #include "code\defines\procs\admin.dm"
@@ -433,9 +438,9 @@
#include "code\game\mecha\equipment\tools\medical_tools.dm" #include "code\game\mecha\equipment\tools\medical_tools.dm"
#include "code\game\mecha\equipment\tools\tools.dm" #include "code\game\mecha\equipment\tools\tools.dm"
#include "code\game\mecha\equipment\weapons\weapons.dm" #include "code\game\mecha\equipment\weapons\weapons.dm"
#include "code\game\mecha\hoverpod\hoverpod.dm"
#include "code\game\mecha\medical\medical.dm" #include "code\game\mecha\medical\medical.dm"
#include "code\game\mecha\medical\odysseus.dm" #include "code\game\mecha\medical\odysseus.dm"
#include "code\game\mecha\working\hoverpod.dm"
#include "code\game\mecha\working\ripley.dm" #include "code\game\mecha\working\ripley.dm"
#include "code\game\mecha\working\working.dm" #include "code\game\mecha\working\working.dm"
#include "code\game\objects\empulse.dm" #include "code\game\objects\empulse.dm"
@@ -1137,7 +1142,6 @@
#include "code\modules\power\breaker_box.dm" #include "code\modules\power\breaker_box.dm"
#include "code\modules\power\cable.dm" #include "code\modules\power\cable.dm"
#include "code\modules\power\cable_heavyduty.dm" #include "code\modules\power\cable_heavyduty.dm"
#include "code\modules\power\cable_logic.dm"
#include "code\modules\power\cell.dm" #include "code\modules\power\cell.dm"
#include "code\modules\power\engine.dm" #include "code\modules\power\engine.dm"
#include "code\modules\power\fractal_reactor.dm" #include "code\modules\power\fractal_reactor.dm"

View File

@@ -61,7 +61,6 @@ max volume of phoron storeable by the field = the total volume of a number of ti
idle_power_usage = 50 idle_power_usage = 50
active_power_usage = 500 //multiplied by field strength active_power_usage = 500 //multiplied by field strength
var/cached_power_avail = 0 var/cached_power_avail = 0
directwired = 1
anchored = 0 anchored = 0
var/state = 0 var/state = 0
@@ -120,7 +119,6 @@ max volume of phoron storeable by the field = the total volume of a number of ti
state = 2 state = 2
user << "You weld the [src] to the floor." user << "You weld the [src] to the floor."
connect_to_network() connect_to_network()
src.directwired = 1
else else
user << "\red You need more welding fuel to complete this task." user << "\red You need more welding fuel to complete this task."
if(2) if(2)
@@ -134,7 +132,6 @@ max volume of phoron storeable by the field = the total volume of a number of ti
state = 1 state = 1
user << "You cut the [src] free from the floor." user << "You cut the [src] free from the floor."
disconnect_from_network() disconnect_from_network()
src.directwired = 0
else else
user << "\red You need more welding fuel to complete this task." user << "\red You need more welding fuel to complete this task."
return return

View File

@@ -19,7 +19,6 @@
use_power = 1 use_power = 1
idle_power_usage = 10 idle_power_usage = 10
active_power_usage = 500 active_power_usage = 500
directwired = 0
var/remote_access_enabled = 1 var/remote_access_enabled = 1
var/cached_power_avail = 0 var/cached_power_avail = 0
var/emergency_insert_ready = 0 var/emergency_insert_ready = 0

View File

@@ -400,6 +400,37 @@ proc/listclearnulls(list/list)
//world.log << " output: [out.len]" //world.log << " output: [out.len]"
return reverselist(out) return reverselist(out)
/proc/dd_sortedObjectList(var/list/L, var/cache=list())
if(L.len < 2)
return L
var/middle = L.len / 2 + 1 // Copy is first,second-1
return dd_mergeObjectList(dd_sortedObjectList(L.Copy(0,middle), cache), dd_sortedObjectList(L.Copy(middle), cache), cache) //second parameter null = to end of list
/proc/dd_mergeObjectList(var/list/L, var/list/R, var/list/cache)
var/Li=1
var/Ri=1
var/list/result = new()
while(Li <= L.len && Ri <= R.len)
var/LLi = L[Li]
var/RRi = R[Ri]
var/LLiV = cache[LLi]
var/RRiV = cache[RRi]
if(!LLiV)
LLiV = LLi:dd_SortValue()
cache[LLi] = LLiV
if(!RRiV)
RRiV = RRi:dd_SortValue()
cache[RRi] = RRiV
if(LLiV < RRiV)
result += L[Li++]
else
result += R[Ri++]
if(Li <= L.len)
return (result + L.Copy(Li, 0))
return (result + R.Copy(Ri, 0))
/*
proc/dd_sortedObjectList(list/incoming) proc/dd_sortedObjectList(list/incoming)
/* /*
Use binary search to order by dd_SortValue(). Use binary search to order by dd_SortValue().
@@ -456,7 +487,7 @@ proc/dd_sortedObjectList(list/incoming)
sorted_list += current_sort_object sorted_list += current_sort_object
sorted_list += list_bottom sorted_list += list_bottom
return sorted_list return sorted_list
*/
proc/dd_sortedtextlist(list/incoming, case_sensitive = 0) proc/dd_sortedtextlist(list/incoming, case_sensitive = 0)
// Returns a new list with the text values sorted. // Returns a new list with the text values sorted.

View File

@@ -351,16 +351,10 @@ datum/controller/game_controller/proc/process_pipenets()
continue continue
pipe_networks.Cut(i,i+1) pipe_networks.Cut(i,i+1)
datum/controller/game_controller/proc/process_powernets() /datum/controller/game_controller/proc/process_powernets()
last_thing_processed = /datum/powernet last_thing_processed = /datum/powernet
var/i = 1 for(var/datum/powernet/Powernet in powernets)
while(i<=powernets.len) Powernet.reset()
var/datum/powernet/Powernet = powernets[i]
if(Powernet)
Powernet.process()
i++
continue
powernets.Cut(i,i+1)
datum/controller/game_controller/proc/process_nano() datum/controller/game_controller/proc/process_nano()
var/i = 1 var/i = 1

View File

@@ -450,6 +450,15 @@ var/list/all_supply_groups = list("Operations","Security","Hospitality","Enginee
containertype = /obj/structure/closet/crate containertype = /obj/structure/closet/crate
containername = "Wooden planks crate" containername = "Wooden planks crate"
group = "Engineering" group = "Engineering"
/datum/supply_packs/plastic50
name = "50 plastic sheets"
contains = list(/obj/item/stack/sheet/mineral/plastic)
amount = 50
cost = 10
containertype = /obj/structure/closet/crate
containername = "Plastic sheets crate"
group = "Engineering"
/datum/supply_packs/smescoil /datum/supply_packs/smescoil
name = "Superconducting Magnetic Coil" name = "Superconducting Magnetic Coil"

78
code/datums/wires/apc.dm Normal file
View File

@@ -0,0 +1,78 @@
/datum/wires/apc
holder_type = /obj/machinery/power/apc
wire_count = 4
var/const/APC_WIRE_IDSCAN = 1
var/const/APC_WIRE_MAIN_POWER1 = 2
var/const/APC_WIRE_MAIN_POWER2 = 4
var/const/APC_WIRE_AI_CONTROL = 8
/datum/wires/apc/GetInteractWindow()
var/obj/machinery/power/apc/A = holder
. += ..()
. += text("<br>\n[(A.locked ? "The APC is locked." : "The APC is unlocked.")]<br>\n[(A.shorted ? "The APCs power has been shorted." : "The APC is working properly!")]<br>\n[(A.aidisabled ? "The 'AI control allowed' light is off." : "The 'AI control allowed' light is on.")]")
/datum/wires/apc/CanUse(var/mob/living/L)
var/obj/machinery/power/apc/A = holder
if(A.wiresexposed)
return 1
return 0
/datum/wires/apc/UpdatePulsed(var/index)
var/obj/machinery/power/apc/A = holder
switch(index)
if(APC_WIRE_IDSCAN)
A.locked = 0
spawn(300)
if(A)
A.locked = 1
A.updateDialog()
if (APC_WIRE_MAIN_POWER1, APC_WIRE_MAIN_POWER2)
if(A.shorted == 0)
A.shorted = 1
spawn(1200)
if(A && !IsIndexCut(APC_WIRE_MAIN_POWER1) && !IsIndexCut(APC_WIRE_MAIN_POWER2))
A.shorted = 0
A.updateDialog()
if (APC_WIRE_AI_CONTROL)
if (A.aidisabled == 0)
A.aidisabled = 1
spawn(10)
if(A && !IsIndexCut(APC_WIRE_AI_CONTROL))
A.aidisabled = 0
A.updateDialog()
A.updateDialog()
/datum/wires/apc/UpdateCut(var/index, var/mended)
var/obj/machinery/power/apc/A = holder
switch(index)
if(APC_WIRE_MAIN_POWER1, APC_WIRE_MAIN_POWER2)
if(!mended)
A.shock(usr, 50)
A.shorted = 1
else if(!IsIndexCut(APC_WIRE_MAIN_POWER1) && !IsIndexCut(APC_WIRE_MAIN_POWER2))
A.shorted = 0
A.shock(usr, 50)
if(APC_WIRE_AI_CONTROL)
if(!mended)
if (A.aidisabled == 0)
A.aidisabled = 1
else
if (A.aidisabled == 1)
A.aidisabled = 0
A.updateDialog()

View File

@@ -0,0 +1,52 @@
/datum/wires/smartfridge
holder_type = /obj/machinery/smartfridge
wire_count = 3
var/const/SMARTFRIDGE_WIRE_ELECTRIFY = 1
var/const/SMARTFRIDGE_WIRE_THROW = 2
var/const/SMARTFRIDGE_WIRE_IDSCAN = 4
/datum/wires/smartfridge/CanUse(var/mob/living/L)
var/obj/machinery/smartfridge/S = holder
if(!istype(L, /mob/living/silicon))
if(S.seconds_electrified)
if(S.shock(L, 100))
return 0
if(S.panel_open)
return 1
return 0
/datum/wires/smartfridge/Interact(var/mob/living/user)
if(CanUse(user))
var/obj/machinery/smartfridge/S = holder
S.attack_hand(user)
/datum/wires/smartfridge/GetInteractWindow()
var/obj/machinery/smartfridge/S = holder
. += ..()
. += "<BR>The orange light is [S.seconds_electrified ? "off" : "on"].<BR>"
. += "The red light is [S.shoot_inventory ? "off" : "blinking"].<BR>"
. += "A [S.scan_id ? "purple" : "yellow"] light is on.<BR>"
/datum/wires/smartfridge/UpdatePulsed(var/index)
var/obj/machinery/smartfridge/S = holder
switch(index)
if(SMARTFRIDGE_WIRE_THROW)
S.shoot_inventory = !S.shoot_inventory
if(SMARTFRIDGE_WIRE_ELECTRIFY)
S.seconds_electrified = 30
if(SMARTFRIDGE_WIRE_IDSCAN)
S.scan_id = !S.scan_id
/datum/wires/smartfridge/UpdateCut(var/index, var/mended)
var/obj/machinery/smartfridge/S = holder
switch(index)
if(SMARTFRIDGE_WIRE_THROW)
S.shoot_inventory = !mended
if(SMARTFRIDGE_WIRE_ELECTRIFY)
if(mended)
S.seconds_electrified = 0
else
S.seconds_electrified = -1
if(SMARTFRIDGE_WIRE_IDSCAN)
S.scan_id = 1

View File

@@ -0,0 +1,52 @@
/datum/wires/suit_storage_unit
holder_type = /obj/machinery/suit_cycler
wire_count = 3
var/const/SUIT_STORAGE_WIRE_ELECTRIFY = 1
var/const/SUIT_STORAGE_WIRE_SAFETY = 2
var/const/SUIT_STORAGE_WIRE_LOCKED = 4
/datum/wires/suit_storage_unit/CanUse(var/mob/living/L)
var/obj/machinery/suit_cycler/S = holder
if(!istype(L, /mob/living/silicon))
if(S.electrified)
if(S.shock(L, 100))
return 0
if(S.panel_open)
return 1
return 0
/datum/wires/suit_storage_unit/Interact(var/mob/living/user)
if(CanUse(user))
var/obj/machinery/suit_cycler/S = holder
S.attack_hand(user)
/datum/wires/suit_storage_unit/GetInteractWindow()
var/obj/machinery/suit_cycler/S = holder
. += ..()
. += "<BR>The orange light is [S.electrified ? "off" : "on"].<BR>"
. += "The red light is [S.safeties ? "off" : "blinking"].<BR>"
. += "The yellow light is [S.locked ? "on" : "off"].<BR>"
/datum/wires/suit_storage_unit/UpdatePulsed(var/index)
var/obj/machinery/suit_cycler/S = holder
switch(index)
if(SUIT_STORAGE_WIRE_SAFETY)
S.safeties = !S.safeties
if(SUIT_STORAGE_WIRE_ELECTRIFY)
S.electrified = 30
if(SUIT_STORAGE_WIRE_LOCKED)
S.locked = !S.locked
/datum/wires/suit_storage_unit/UpdateCut(var/index, var/mended)
var/obj/machinery/suit_cycler/S = holder
switch(index)
if(SUIT_STORAGE_WIRE_SAFETY)
S.safeties = mended
if(SUIT_STORAGE_WIRE_LOCKED)
S.locked = mended
if(SUIT_STORAGE_WIRE_ELECTRIFY)
if(mended)
S.electrified = 0
else
S.electrified = -1

View File

@@ -0,0 +1,58 @@
/datum/wires/vending
holder_type = /obj/machinery/vending
wire_count = 4
var/const/VENDING_WIRE_THROW = 1
var/const/VENDING_WIRE_CONTRABAND = 2
var/const/VENDING_WIRE_ELECTRIFY = 4
var/const/VENDING_WIRE_IDSCAN = 8
/datum/wires/vending/CanUse(var/mob/living/L)
var/obj/machinery/vending/V = holder
if(!istype(L, /mob/living/silicon))
if(V.seconds_electrified)
if(V.shock(L, 100))
return 0
if(V.panel_open)
return 1
return 0
/datum/wires/vending/Interact(var/mob/living/user)
if(CanUse(user))
var/obj/machinery/vending/V = holder
V.attack_hand(user)
/datum/wires/vending/GetInteractWindow()
var/obj/machinery/vending/V = holder
. += ..()
. += "<BR>The orange light is [V.seconds_electrified ? "off" : "on"].<BR>"
. += "The red light is [V.shoot_inventory ? "off" : "blinking"].<BR>"
. += "The green light is [V.extended_inventory ? "on" : "off"].<BR>"
. += "The [V.scan_id ? "purple" : "yellow"] light is on.<BR>"
/datum/wires/vending/UpdatePulsed(var/index)
var/obj/machinery/vending/V = holder
switch(index)
if(VENDING_WIRE_THROW)
V.shoot_inventory = !V.shoot_inventory
if(VENDING_WIRE_CONTRABAND)
V.extended_inventory = !V.extended_inventory
if(VENDING_WIRE_ELECTRIFY)
V.seconds_electrified = 30
if(VENDING_WIRE_IDSCAN)
V.scan_id = !V.scan_id
/datum/wires/vending/UpdateCut(var/index, var/mended)
var/obj/machinery/vending/V = holder
switch(index)
if(VENDING_WIRE_THROW)
V.shoot_inventory = !mended
if(VENDING_WIRE_CONTRABAND)
V.extended_inventory = 0
if(VENDING_WIRE_ELECTRIFY)
if(mended)
V.seconds_electrified = 0
else
V.seconds_electrified = -1
if(VENDING_WIRE_IDSCAN)
V.scan_id = 1

293
code/datums/wires/wires.dm Normal file
View File

@@ -0,0 +1,293 @@
// Wire datums. Created by Giacomand.
// Was created to replace a horrible case of copy and pasted code with no care for maintability.
// Goodbye Door wires, Cyborg wires, Vending Machine wires, Autolathe wires
// Protolathe wires, APC wires and Camera wires!
#define MAX_FLAG 65535
var/list/same_wires = list()
// 12 colours, if you're adding more than 12 wires then add more colours here
var/list/wireColours = list("red", "blue", "green", "black", "orange", "brown", "gold", "gray", "cyan", "navy", "purple", "pink")
/datum/wires
var/random = 0 // Will the wires be different for every single instance.
var/atom/holder = null // The holder
var/holder_type = null // The holder type; used to make sure that the holder is the correct type.
var/wire_count = 0 // Max is 16
var/wires_status = 0 // BITFLAG OF WIRES
var/list/wires = list()
var/list/signallers = list()
var/table_options = " align='center'"
var/row_options1 = " width='80px'"
var/row_options2 = " width='260px'"
var/window_x = 370
var/window_y = 470
/datum/wires/New(var/atom/holder)
..()
src.holder = holder
if(!istype(holder, holder_type))
CRASH("Our holder is null/the wrong type!")
return
// Generate new wires
if(random)
GenerateWires()
// Get the same wires
else
// We don't have any wires to copy yet, generate some and then copy it.
if(!same_wires[holder_type])
GenerateWires()
same_wires[holder_type] = src.wires.Copy()
else
var/list/wires = same_wires[holder_type]
src.wires = wires // Reference the wires list.
/datum/wires/proc/GenerateWires()
var/list/colours_to_pick = wireColours.Copy() // Get a copy, not a reference.
var/list/indexes_to_pick = list()
//Generate our indexes
for(var/i = 1; i < MAX_FLAG && i < (1 << wire_count); i += i)
indexes_to_pick += i
colours_to_pick.len = wire_count // Downsize it to our specifications.
while(colours_to_pick.len && indexes_to_pick.len)
// Pick and remove a colour
var/colour = pick_n_take(colours_to_pick)
// Pick and remove an index
var/index = pick_n_take(indexes_to_pick)
src.wires[colour] = index
//wires = shuffle(wires)
/datum/wires/proc/Interact(var/mob/living/user)
var/html = null
if(holder && CanUse(user))
html = GetInteractWindow()
if(html)
user.set_machine(holder)
else
user.unset_machine()
// No content means no window.
user << browse(null, "window=wires")
return
var/datum/browser/popup = new(user, "wires", holder.name, window_x, window_y)
popup.set_content(html)
popup.set_title_image(user.browse_rsc_icon(holder.icon, holder.icon_state))
popup.open()
/datum/wires/proc/GetInteractWindow()
var/html = "<div class='block'>"
html += "<h3>Exposed Wires</h3>"
html += "<table[table_options]>"
for(var/colour in wires)
html += "<tr>"
html += "<td[row_options1]><font color='[colour]'>[capitalize(colour)]</font></td>"
html += "<td[row_options2]>"
html += "<A href='?src=\ref[src];action=1;cut=[colour]'>[IsColourCut(colour) ? "Mend" : "Cut"]</A>"
html += " <A href='?src=\ref[src];action=1;pulse=[colour]'>Pulse</A>"
html += " <A href='?src=\ref[src];action=1;attach=[colour]'>[IsAttached(colour) ? "Detach" : "Attach"] Signaller</A></td></tr>"
html += "</table>"
html += "</div>"
return html
/datum/wires/Topic(href, href_list)
..()
if(in_range(holder, usr) && isliving(usr))
var/mob/living/L = usr
if(CanUse(L) && href_list["action"])
var/obj/item/I = L.get_active_hand()
holder.add_hiddenprint(L)
if(href_list["cut"]) // Toggles the cut/mend status
if(istype(I, /obj/item/weapon/wirecutters))
var/colour = href_list["cut"]
CutWireColour(colour)
else
L << "<span class='error'>You need wirecutters!</span>"
else if(href_list["pulse"])
if(istype(I, /obj/item/device/multitool))
var/colour = href_list["pulse"]
PulseColour(colour)
else
L << "<span class='error'>You need a multitool!</span>"
else if(href_list["attach"])
var/colour = href_list["attach"]
// Detach
if(IsAttached(colour))
var/obj/item/O = Detach(colour)
if(O)
L.put_in_hands(O)
// Attach
else
if(istype(I, /obj/item/device/assembly/signaler))
L.drop_item()
Attach(colour, I)
else
L << "<span class='error'>You need a remote signaller!</span>"
// Update Window
Interact(usr)
if(href_list["close"])
usr << browse(null, "window=wires")
usr.unset_machine(holder)
//
// Overridable Procs
//
// Called when wires cut/mended.
/datum/wires/proc/UpdateCut(var/index, var/mended)
return
// Called when wire pulsed. Add code here.
/datum/wires/proc/UpdatePulsed(var/index)
return
/datum/wires/proc/CanUse(var/mob/living/L)
return 1
// Example of use:
/*
var/const/BOLTED= 1
var/const/SHOCKED = 2
var/const/SAFETY = 4
var/const/POWER = 8
/datum/wires/door/UpdateCut(var/index, var/mended)
var/obj/machinery/door/airlock/A = holder
switch(index)
if(BOLTED)
if(!mended)
A.bolt()
if(SHOCKED)
A.shock()
if(SAFETY )
A.safety()
*/
//
// Helper Procs
//
/datum/wires/proc/PulseColour(var/colour)
PulseIndex(GetIndex(colour))
/datum/wires/proc/PulseIndex(var/index)
if(IsIndexCut(index))
return
UpdatePulsed(index)
/datum/wires/proc/GetIndex(var/colour)
if(wires[colour])
var/index = wires[colour]
return index
else
CRASH("[colour] is not a key in wires.")
//
// Is Index/Colour Cut procs
//
/datum/wires/proc/IsColourCut(var/colour)
var/index = GetIndex(colour)
return IsIndexCut(index)
/datum/wires/proc/IsIndexCut(var/index)
return (index & wires_status)
//
// Signaller Procs
//
/datum/wires/proc/IsAttached(var/colour)
if(signallers[colour])
return 1
return 0
/datum/wires/proc/GetAttached(var/colour)
if(signallers[colour])
return signallers[colour]
return null
/datum/wires/proc/Attach(var/colour, var/obj/item/device/assembly/signaler/S)
if(colour && S)
if(!IsAttached(colour))
signallers[colour] = S
S.loc = holder
S.connected = src
return S
/datum/wires/proc/Detach(var/colour)
if(colour)
var/obj/item/device/assembly/signaler/S = GetAttached(colour)
if(S)
signallers -= colour
S.connected = null
S.loc = holder.loc
return S
/datum/wires/proc/Pulse(var/obj/item/device/assembly/signaler/S)
for(var/colour in signallers)
if(S == signallers[colour])
PulseColour(colour)
break
//
// Cut Wire Colour/Index procs
//
/datum/wires/proc/CutWireColour(var/colour)
var/index = GetIndex(colour)
CutWireIndex(index)
/datum/wires/proc/CutWireIndex(var/index)
if(IsIndexCut(index))
wires_status &= ~index
UpdateCut(index, 1)
else
wires_status |= index
UpdateCut(index, 0)
/datum/wires/proc/RandomCut()
var/r = rand(1, wires.len)
CutWireIndex(r)
/datum/wires/proc/CutAll()
for(var/i = 1; i < MAX_FLAG && i < (1 << wire_count); i += i)
CutWireIndex(i)
/datum/wires/proc/IsAllCut()
if(wires_status == (1 << wire_count) - 1)
return 1
return 0
//
//Shuffle and Mend
//
/datum/wires/proc/Shuffle()
wires_status = 0
GenerateWires()

View File

@@ -884,18 +884,10 @@ var/list/ghostteleportlocs = list()
name = "\improper Dormitories" name = "\improper Dormitories"
icon_state = "Sleep" icon_state = "Sleep"
/area/crew_quarters/sleep/engi
name = "\improper Engineering Dormitories"
icon_state = "Sleep"
/area/crew_quarters/sleep/engi_wash /area/crew_quarters/sleep/engi_wash
name = "\improper Engineering Washroom" name = "\improper Engineering Washroom"
icon_state = "toilet" icon_state = "toilet"
/area/crew_quarters/sleep/sec
name = "\improper Security Dormitories"
icon_state = "Sleep"
/area/crew_quarters/sleep/bedrooms /area/crew_quarters/sleep/bedrooms
name = "\improper Dormitory Bedroom" name = "\improper Dormitory Bedroom"
icon_state = "Sleep" icon_state = "Sleep"
@@ -1080,6 +1072,10 @@ var/list/ghostteleportlocs = list()
name = "\improper Engineering Foyer" name = "\improper Engineering Foyer"
icon_state = "engine" icon_state = "engine"
engineering_supply
name = "Engineering Supply"
icon_state = "engine_supply"
break_room break_room
name = "\improper Engineering Break Room" name = "\improper Engineering Break Room"
icon_state = "engine" icon_state = "engine"

View File

@@ -206,7 +206,7 @@
return return
/area/proc/updateicon() /area/proc/updateicon()
if ((fire || eject || party) && ((!requires_power)?(!requires_power):power_environ))//If it doesn't require power, can still activate this proc. if ((fire || eject || party) && (!requires_power||power_environ) && !lighting_space)//If it doesn't require power, can still activate this proc.
if(fire && !eject && !party) if(fire && !eject && !party)
icon_state = "blue" icon_state = "blue"
/*else if(atmosalm && !fire && !eject && !party) /*else if(atmosalm && !fire && !eject && !party)
@@ -234,6 +234,8 @@
return 1 return 1
if(master.always_unpowered) if(master.always_unpowered)
return 0 return 0
if(src.lighting_space)
return 0 // Nope sorry
switch(chan) switch(chan)
if(EQUIP) if(EQUIP)
return master.power_equip return master.power_equip
@@ -245,12 +247,10 @@
return 0 return 0
// called when power status changes // called when power status changes
/area/proc/power_change() /area/proc/power_change()
master.powerupdate = 2
for(var/area/RA in related) for(var/area/RA in related)
for(var/obj/machinery/M in RA) // for each machine in the area for(var/obj/machinery/M in RA) // for each machine in the area
M.power_change() // reverify power status (to update icons etc.) M.power_change() // reverify power status (to update icons etc.)
if (fire || eject || party) if (fire || eject || party)
RA.updateicon() RA.updateicon()
@@ -265,7 +265,6 @@
used += master.used_environ used += master.used_environ
if(TOTAL) if(TOTAL)
used += master.used_light + master.used_equip + master.used_environ used += master.used_light + master.used_equip + master.used_environ
return used return used
/area/proc/clear_usage() /area/proc/clear_usage()
@@ -274,7 +273,6 @@
master.used_environ = 0 master.used_environ = 0
/area/proc/use_power(var/amount, var/chan) /area/proc/use_power(var/amount, var/chan)
switch(chan) switch(chan)
if(EQUIP) if(EQUIP)
master.used_equip += amount master.used_equip += amount

View File

@@ -22,11 +22,14 @@
var/shoot_inventory = 0 var/shoot_inventory = 0
var/locked = 0 var/locked = 0
var/panel_open = 0 //Hacking a smartfridge var/panel_open = 0 //Hacking a smartfridge
var/wires = 7 var/scan_id = 1
var/const/WIRE_SHOCK = 1 var/datum/wires/smartfridge/wires = null
var/const/WIRE_SHOOTINV = 2
var/const/WIRE_SCANID = 3 //Only used by the secure smartfridge, but required by the cut, mend and pulse procs.
/obj/machinery/smartfridge/New()
wires = new(src)
/obj/machinery/smartfridge/Del()
del(wires) // qdel
/obj/machinery/smartfridge/proc/accept_check(var/obj/item/O as obj) /obj/machinery/smartfridge/proc/accept_check(var/obj/item/O as obj)
if(istype(O,/obj/item/weapon/reagent_containers/food/snacks/grown/) || istype(O,/obj/item/seeds/)) if(istype(O,/obj/item/weapon/reagent_containers/food/snacks/grown/) || istype(O,/obj/item/seeds/))
@@ -217,6 +220,8 @@
if(seconds_electrified != 0) if(seconds_electrified != 0)
if(shock(user, 100)) if(shock(user, 100))
return return
if(panel_open)
wires.Interact(user)
ui_interact(user) ui_interact(user)
@@ -248,26 +253,6 @@
if (items.len > 0) if (items.len > 0)
data["contents"] = items data["contents"] = items
var/list/vendwires = null
if (is_secure)
vendwires = list(
"Violet" = 1,
"Orange" = 2,
"Green" = 3)
else
vendwires = list(
"Blue" = 1,
"Red" = 2,
"Black" = 3)
var/list/vendor_wires[0]
for (var/wire in vendwires)
var is_uncut = wires & APCWireColorToFlag[vendwires[wire]]
vendor_wires.Add(list(list("wire" = wire, "cut" = !is_uncut, "index" = vendwires[wire])))
if (vendor_wires.len > 0)
data["wires"] = vendor_wires
ui = nanomanager.try_update_ui(user, src, ui_key, ui, data, force_open) ui = nanomanager.try_update_ui(user, src, ui_key, ui, data, force_open)
if (!ui) if (!ui)
ui = new(user, src, ui_key, "smartfridge.tmpl", src.name, 400, 500) ui = new(user, src, ui_key, "smartfridge.tmpl", src.name, 400, 500)
@@ -306,82 +291,8 @@
return 1 return 1
return 1 return 1
if (panel_open)
if (href_list["cutwire"])
if (!( istype(usr.get_active_hand(), /obj/item/weapon/wirecutters) ))
user << "You need wirecutters!"
return 1
var/wire_index = text2num(href_list["cutwire"])
if (isWireColorCut(wire_index))
mend(wire_index)
else
cut(wire_index)
return 1
if (href_list["pulsewire"])
if (!istype(usr.get_active_hand(), /obj/item/device/multitool))
usr << "You need a multitool!"
return 1
var/wire_index = text2num(href_list["pulsewire"])
if (isWireColorCut(wire_index))
usr << "You can't pulse a cut wire."
return 1
pulse(wire_index)
return 1
return 0 return 0
/*************
* Hacking
**************/
/obj/machinery/smartfridge/proc/cut(var/wireColor)
var/wireFlag = APCWireColorToFlag[wireColor]
var/wireIndex = APCWireColorToIndex[wireColor]
src.wires &= ~wireFlag
switch(wireIndex)
if(WIRE_SHOCK)
src.seconds_electrified = -1
if (WIRE_SHOOTINV)
if(!src.shoot_inventory)
src.shoot_inventory = 1
if(WIRE_SCANID)
src.locked = 1
/obj/machinery/smartfridge/proc/mend(var/wireColor)
var/wireFlag = APCWireColorToFlag[wireColor]
var/wireIndex = APCWireColorToIndex[wireColor]
src.wires |= wireFlag
switch(wireIndex)
if(WIRE_SHOCK)
src.seconds_electrified = 0
if (WIRE_SHOOTINV)
src.shoot_inventory = 0
if(WIRE_SCANID)
src.locked = 0
/obj/machinery/smartfridge/proc/pulse(var/wireColor)
var/wireIndex = APCWireColorToIndex[wireColor]
switch(wireIndex)
if(WIRE_SHOCK)
src.seconds_electrified = 30
if(WIRE_SHOOTINV)
src.shoot_inventory = !src.shoot_inventory
if(WIRE_SCANID)
src.locked = -1
/obj/machinery/smartfridge/proc/isWireColorCut(var/wireColor)
var/wireFlag = APCWireColorToFlag[wireColor]
return ((src.wires & wireFlag) == 0)
/obj/machinery/smartfridge/proc/isWireCut(var/wireIndex)
var/wireFlag = APCIndexToFlag[wireIndex]
return ((src.wires & wireFlag) == 0)
/obj/machinery/smartfridge/proc/throw_item() /obj/machinery/smartfridge/proc/throw_item()
var/obj/throw_item = null var/obj/throw_item = null
var/mob/living/target = locate() in view(7,src) var/mob/living/target = locate() in view(7,src)

View File

@@ -27,7 +27,6 @@
var/safetieson = 1 var/safetieson = 1
var/cycletime_left = 0 var/cycletime_left = 0
//The units themselves///////////////// //The units themselves/////////////////
/obj/machinery/suit_storage_unit/standard_unit /obj/machinery/suit_storage_unit/standard_unit
@@ -591,13 +590,7 @@
var/locked = 1 // If locked, nothing can be taken from or added to the cycler. var/locked = 1 // If locked, nothing can be taken from or added to the cycler.
var/panel_open = 0 // Hacking! var/panel_open = 0 // Hacking!
var/can_repair // If set, the cycler can repair hardsuits. var/can_repair // If set, the cycler can repair hardsuits.
// Wiring bollocks.
var/wires = 15
var/electrified = 0 var/electrified = 0
var/const/WIRE_EXTEND = 1 // Safeties
var/const/WIRE_SCANID = 2 // Locked status
var/const/WIRE_SHOCK = 3 // What it says on the tin.
//Departments that the cycler can paint suits to look like. //Departments that the cycler can paint suits to look like.
var/list/departments = list("Engineering","Mining","Medical","Security","Atmos") var/list/departments = list("Engineering","Mining","Medical","Security","Atmos")
@@ -611,12 +604,20 @@
var/obj/item/clothing/suit/space/rig/suit = null var/obj/item/clothing/suit/space/rig/suit = null
var/obj/item/clothing/head/helmet/space/helmet = null var/obj/item/clothing/head/helmet/space/helmet = null
var/datum/wires/suit_storage_unit/wires = null
/obj/machinery/suit_cycler/New() /obj/machinery/suit_cycler/New()
..() ..()
wires = new(src)
target_department = departments[1] target_department = departments[1]
target_species = species[1] target_species = species[1]
if(!target_department || !target_species) del(src) if(!target_department || !target_species) del(src)
/obj/machinery/suit_cycler/Del()
del(wires) // qdel
wires = null
/obj/machinery/suit_cycler/engineering /obj/machinery/suit_cycler/engineering
name = "Engineering suit cycler" name = "Engineering suit cycler"
model_text = "Engineering" model_text = "Engineering"
@@ -820,31 +821,15 @@
dat += "<A href='?src=\ref[src];apply_paintjob=1'><br>\[apply customisation routine\]</a><br><hr>" dat += "<A href='?src=\ref[src];apply_paintjob=1'><br>\[apply customisation routine\]</a><br><hr>"
if(panel_open) if(panel_open)
var/list/vendwires = list( dat += wires()
"Violet" = 1,
"Orange" = 2,
"Goldenrod" = 3,
)
dat += "<h2><B>Access Panel</B></h2>"
for(var/wiredesc in vendwires)
var/is_uncut = src.wires & APCWireColorToFlag[vendwires[wiredesc]]
dat += "[wiredesc] wire: "
if(!is_uncut)
dat += "<a href='?src=\ref[src];cutwire=[vendwires[wiredesc]]'>Mend</a>"
else
dat += "<a href='?src=\ref[src];cutwire=[vendwires[wiredesc]]'>Cut</a> "
dat += "<a href='?src=\ref[src];pulsewire=[vendwires[wiredesc]]'>Pulse</a> "
dat += "<br>"
dat += "<br>"
dat += "The orange light is [(electrified == 0) ? "off" : "on"].<BR>"
dat += "The red light is [safeties ? "blinking" : "off"].<BR>"
dat += "The yellow light is [locked ? "on" : "off"].<BR>"
user << browse(dat, "window=suit_cycler") user << browse(dat, "window=suit_cycler")
onclose(user, "suit_cycler") onclose(user, "suit_cycler")
return return
/obj/machinery/suit_cycler/proc/wires()
return wires.GetInteractWindow()
/obj/machinery/suit_cycler/Topic(href, href_list) /obj/machinery/suit_cycler/Topic(href, href_list)
if(href_list["eject_suit"]) if(href_list["eject_suit"])
if(!suit) return if(!suit) return
@@ -916,27 +901,6 @@
if(radiation_level > 1) if(radiation_level > 1)
suit.clean_blood() suit.clean_blood()
else if ((href_list["cutwire"]) && (src.panel_open))
var/twire = text2num(href_list["cutwire"])
if (!( istype(usr.get_active_hand(), /obj/item/weapon/wirecutters) ))
usr << "You need wirecutters!"
return
if (src.isWireColorCut(twire))
src.mend(twire)
else
src.cut(twire)
else if ((href_list["pulsewire"]) && (src.panel_open))
var/twire = text2num(href_list["pulsewire"])
if (!istype(usr.get_active_hand(), /obj/item/device/multitool))
usr << "You need a multitool!"
return
if (src.isWireColorCut(twire))
usr << "You can't pulse a cut wire."
return
else
src.pulse(twire)
src.updateUsrDialog() src.updateUsrDialog()
return return
@@ -1017,46 +981,6 @@
return return
//HACKING PROCS, MOSTLY COPIED FROM VENDING MACHINES
/obj/machinery/suit_cycler/proc/isWireColorCut(var/wireColor)
var/wireFlag = APCWireColorToFlag[wireColor]
return ((src.wires & wireFlag) == 0)
/obj/machinery/suit_cycler/proc/isWireCut(var/wireIndex)
var/wireFlag = APCIndexToFlag[wireIndex]
return ((src.wires & wireFlag) == 0)
/obj/machinery/suit_cycler/proc/cut(var/wireColor)
var/wireFlag = APCWireColorToFlag[wireColor]
var/wireIndex = APCWireColorToIndex[wireColor]
src.wires &= ~wireFlag
switch(wireIndex)
if(WIRE_EXTEND)
safeties = 0
if(WIRE_SHOCK)
electrified = -1
if (WIRE_SCANID)
locked = 0
/obj/machinery/suit_cycler/proc/mend(var/wireColor)
var/wireFlag = APCWireColorToFlag[wireColor]
var/wireIndex = APCWireColorToIndex[wireColor] //not used in this function
src.wires |= wireFlag
switch(wireIndex)
if(WIRE_SHOCK)
src.electrified = 0
/obj/machinery/suit_cycler/proc/pulse(var/wireColor)
var/wireIndex = APCWireColorToIndex[wireColor]
switch(wireIndex)
if(WIRE_EXTEND)
safeties = !locked
if(WIRE_SHOCK)
electrified = 30
if (WIRE_SCANID)
locked = !locked
//There HAS to be a less bloated way to do this. TODO: some kind of table/icon name coding? ~Z //There HAS to be a less bloated way to do this. TODO: some kind of table/icon name coding? ~Z
/obj/machinery/suit_cycler/proc/apply_paintjob() /obj/machinery/suit_cycler/proc/apply_paintjob()

View File

@@ -56,12 +56,9 @@
var/shut_up = 1 //Stop spouting those godawful pitches! var/shut_up = 1 //Stop spouting those godawful pitches!
var/extended_inventory = 0 //can we access the hidden inventory? var/extended_inventory = 0 //can we access the hidden inventory?
var/panel_open = 0 //Hacking that vending machine. Gonna get a free candy bar. var/panel_open = 0 //Hacking that vending machine. Gonna get a free candy bar.
var/wires = 15 var/scan_id = 1
var/obj/item/weapon/coin/coin var/obj/item/weapon/coin/coin
var/const/WIRE_EXTEND = 1 var/datum/wires/vending/wires = null
var/const/WIRE_SCANID = 2
var/const/WIRE_SHOCK = 3
var/const/WIRE_SHOOTINV = 4
var/check_accounts = 0 // 1 = requires PIN and checks accounts. 0 = You slide an ID, it vends, SPACE COMMUNISM! var/check_accounts = 0 // 1 = requires PIN and checks accounts. 0 = You slide an ID, it vends, SPACE COMMUNISM!
var/obj/item/weapon/spacecash/ewallet/ewallet var/obj/item/weapon/spacecash/ewallet/ewallet
@@ -69,6 +66,7 @@
/obj/machinery/vending/New() /obj/machinery/vending/New()
..() ..()
wires = new(src)
spawn(4) spawn(4)
src.slogan_list = text2list(src.product_slogans, ";") src.slogan_list = text2list(src.product_slogans, ";")
@@ -87,6 +85,14 @@
return return
/obj/machinery/vending/Del()
del(wires) // qdel
wires = null
if(coin)
del(coin) // qdel
coin = null
..()
/obj/machinery/vending/ex_act(severity) /obj/machinery/vending/ex_act(severity)
switch(severity) switch(severity)
if(1.0) if(1.0)
@@ -354,36 +360,19 @@
dat += "</TT>" dat += "</TT>"
if(panel_open) if(panel_open)
var/list/vendwires = list( dat += wires()
"Violet" = 1,
"Orange" = 2,
"Goldenrod" = 3,
"Green" = 4,
)
dat += "<br><hr><br><B>Access Panel</B><br>"
for(var/wiredesc in vendwires)
var/is_uncut = src.wires & APCWireColorToFlag[vendwires[wiredesc]]
dat += "[wiredesc] wire: "
if(!is_uncut)
dat += "<a href='?src=\ref[src];cutwire=[vendwires[wiredesc]]'>Mend</a>"
else
dat += "<a href='?src=\ref[src];cutwire=[vendwires[wiredesc]]'>Cut</a> "
dat += "<a href='?src=\ref[src];pulsewire=[vendwires[wiredesc]]'>Pulse</a> "
dat += "<br>"
dat += "<br>" if(product_slogans != "")
dat += "The orange light is [(src.seconds_electrified == 0) ? "off" : "on"].<BR>" dat += "The speaker switch is [shut_up ? "off" : "on"]. <a href='?src=\ref[src];togglevoice=[1]'>Toggle</a>"
dat += "The red light is [src.shoot_inventory ? "off" : "blinking"].<BR>"
dat += "The green light is [src.extended_inventory ? "on" : "off"].<BR>"
dat += "The [(src.wires & WIRE_SCANID) ? "purple" : "yellow"] light is on.<BR>"
if (product_slogans != "")
dat += "The speaker switch is [src.shut_up ? "off" : "on"]. <a href='?src=\ref[src];togglevoice=[1]'>Toggle</a>"
user << browse(dat, "window=vending") user << browse(dat, "window=vending")
onclose(user, "") onclose(user, "")
return return
// returns the wire panel text
/obj/machinery/vending/proc/wires()
return wires.GetInteractWindow()
/obj/machinery/vending/Topic(href, href_list) /obj/machinery/vending/Topic(href, href_list)
if(stat & (BROKEN|NOPOWER)) if(stat & (BROKEN|NOPOWER))
return return
@@ -425,9 +414,9 @@
usr << "\red The vending machine refuses to interface with you, as you are not in its target demographic!" usr << "\red The vending machine refuses to interface with you, as you are not in its target demographic!"
return return
if ((!src.allowed(usr)) && (!src.emagged) && (src.wires & WIRE_SCANID)) //For SECURE VENDING MACHINES YEAH if((!allowed(usr)) && !emagged && scan_id) //For SECURE VENDING MACHINES YEAH
usr << "\red Access denied." //Unless emagged of course usr << "<span class='warning'>Access denied.</span>" //Unless emagged of course
flick(src.icon_deny,src) flick(icon_deny,src)
return return
var/idx=text2num(href_list["vend"]) var/idx=text2num(href_list["vend"])
@@ -458,27 +447,6 @@
src.updateUsrDialog() src.updateUsrDialog()
return return
else if ((href_list["cutwire"]) && (src.panel_open))
var/twire = text2num(href_list["cutwire"])
if (!( istype(usr.get_active_hand(), /obj/item/weapon/wirecutters) ))
usr << "You need wirecutters!"
return
if (src.isWireColorCut(twire))
src.mend(twire)
else
src.cut(twire)
else if ((href_list["pulsewire"]) && (src.panel_open))
var/twire = text2num(href_list["pulsewire"])
if (!istype(usr.get_active_hand(), /obj/item/device/multitool))
usr << "You need a multitool!"
return
if (src.isWireColorCut(twire))
usr << "You can't pulse a cut wire."
return
else
src.pulse(twire)
else if ((href_list["togglevoice"]) && (src.panel_open)) else if ((href_list["togglevoice"]) && (src.panel_open))
src.shut_up = !src.shut_up src.shut_up = !src.shut_up
@@ -490,8 +458,8 @@
return return
/obj/machinery/vending/proc/vend(datum/data/vending_product/R, mob/user) /obj/machinery/vending/proc/vend(datum/data/vending_product/R, mob/user)
if ((!src.allowed(user)) && (!src.emagged) && (src.wires & WIRE_SCANID)) //For SECURE VENDING MACHINES YEAH if((!allowed(usr)) && !emagged && scan_id) //For SECURE VENDING MACHINES YEAH
user << "\red Access denied." //Unless emagged of course usr << "<span class='warning'>Access denied.</span>" //Unless emagged of course
flick(src.icon_deny,src) flick(src.icon_deny,src)
return return
src.vend_ready = 0 //One thing at a time!! src.vend_ready = 0 //One thing at a time!!
@@ -618,51 +586,6 @@
src.visible_message("\red <b>[src] launches [throw_item.name] at [target.name]!</b>") src.visible_message("\red <b>[src] launches [throw_item.name] at [target.name]!</b>")
return 1 return 1
/obj/machinery/vending/proc/isWireColorCut(var/wireColor)
var/wireFlag = APCWireColorToFlag[wireColor]
return ((src.wires & wireFlag) == 0)
/obj/machinery/vending/proc/isWireCut(var/wireIndex)
var/wireFlag = APCIndexToFlag[wireIndex]
return ((src.wires & wireFlag) == 0)
/obj/machinery/vending/proc/cut(var/wireColor)
var/wireFlag = APCWireColorToFlag[wireColor]
var/wireIndex = APCWireColorToIndex[wireColor]
src.wires &= ~wireFlag
switch(wireIndex)
if(WIRE_EXTEND)
src.extended_inventory = 0
if(WIRE_SHOCK)
src.seconds_electrified = -1
if (WIRE_SHOOTINV)
if(!src.shoot_inventory)
src.shoot_inventory = 1
/obj/machinery/vending/proc/mend(var/wireColor)
var/wireFlag = APCWireColorToFlag[wireColor]
var/wireIndex = APCWireColorToIndex[wireColor] //not used in this function
src.wires |= wireFlag
switch(wireIndex)
// if(WIRE_SCANID)
if(WIRE_SHOCK)
src.seconds_electrified = 0
if (WIRE_SHOOTINV)
src.shoot_inventory = 0
/obj/machinery/vending/proc/pulse(var/wireColor)
var/wireIndex = APCWireColorToIndex[wireColor]
switch(wireIndex)
if(WIRE_EXTEND)
src.extended_inventory = !src.extended_inventory
// if (WIRE_SCANID)
if (WIRE_SHOCK)
src.seconds_electrified = 30
if (WIRE_SHOOTINV)
src.shoot_inventory = !src.shoot_inventory
/* /*
* Vending machine types * Vending machine types
*/ */

View File

@@ -95,6 +95,9 @@
return return
/obj/item/mecha_parts/mecha_equipment/proc/can_attach(obj/mecha/M as obj) /obj/item/mecha_parts/mecha_equipment/proc/can_attach(obj/mecha/M as obj)
if(M.equipment.len >= M.max_equip)
return 0
if (ispath(required_type)) if (ispath(required_type))
return istype(M, required_type) return istype(M, required_type)

View File

@@ -365,9 +365,7 @@
if(!PN) if(!PN)
PN = new() PN = new()
powernets += PN PN.add_cable(NC)
NC.powernet = PN
PN.cables += NC
NC.mergeConnectedNetworks(NC.d2) NC.mergeConnectedNetworks(NC.d2)
//NC.mergeConnectedNetworksOnTurf() //NC.mergeConnectedNetworksOnTurf()

View File

@@ -5,7 +5,7 @@
energy_drain = 10 energy_drain = 10
var/dam_force = 20 var/dam_force = 20
var/obj/mecha/working/ripley/cargo_holder var/obj/mecha/working/ripley/cargo_holder
required_type = /obj/mecha/working required_type = list(/obj/mecha/working, /obj/mecha/hoverpod) //so that hoverpods are a bit more useful as space transportation
attach(obj/mecha/M as obj) attach(obj/mecha/M as obj)
..() ..()
@@ -1163,6 +1163,10 @@
if (!usr.Adjacent(src)) if (!usr.Adjacent(src))
return return
if (!isturf(usr.loc))
usr << "\red You can't reach the passenger compartment from here."
return
if(iscarbon(usr)) if(iscarbon(usr))
var/mob/living/carbon/C = usr var/mob/living/carbon/C = usr
if(C.handcuffed) if(C.handcuffed)

View File

@@ -1,96 +1,69 @@
/obj/mecha/working/hoverpod /obj/mecha/hoverpod
desc = "Stubby and round, this space-capable craft is an ancient favorite." desc = "Stubby and round, this space-capable craft is an ancient favorite."
name = "Hover Pod" name = "Hover Pod"
icon_state = "engineering_pod" icon_state = "engineering_pod"
initial_icon = "engineering_pod" initial_icon = "engineering_pod"
internal_damage_threshold = 80
step_in = 4 step_in = 4
step_energy_drain = 5 step_energy_drain = 10
max_temperature = 20000 max_temperature = 20000
health = 150 health = 150
infra_luminosity = 6 infra_luminosity = 6
wreckage = /obj/effect/decal/mecha_wreckage/hoverpod wreckage = /obj/effect/decal/mecha_wreckage/hoverpod
var/list/cargo = new var/list/cargo = new
var/cargo_capacity = 3 var/cargo_capacity = 3
max_equip = 3 max_equip = 2
var/datum/effect/effect/system/ion_trail_follow/ion_trail
//duplicate of parent proc, but without space drifting /obj/mecha/hoverpod/New()
/obj/mecha/working/hoverpod/dyndomove(direction) ..()
if(!can_move) var/turf/T = get_turf(src)
return 0 if(T.z != 2)
if(src.pr_inertial_movement.active()) new /obj/item/mecha_parts/mecha_tracking(src)
return 0
if(!has_charge(step_energy_drain)) ion_trail = new /datum/effect/effect/system/ion_trail_follow()
return 0 ion_trail.set_up(src)
var/move_result = 0 ion_trail.start()
if(hasInternalDamage(MECHA_INT_CONTROL_LOST))
move_result = mechsteprand() /obj/mecha/hoverpod/range_action(atom/target as obj|mob|turf)
else if(src.dir!=direction) return
move_result = mechturn(direction)
else //No space drifting
move_result = mechstep(direction) /obj/mecha/hoverpod/check_for_support()
if(move_result) //does the hoverpod have enough charge left to stabilize itself?
can_move = 0 if (has_charge(step_energy_drain))
use_power(step_energy_drain) if (!ion_trail.on)
/*if(istype(src.loc, /turf/space)) ion_trail.start()
if(!src.check_for_support())
src.pr_inertial_movement.start(list(src,direction))
src.log_message("Movement control lost. Inertial movement started.")*/
if(do_after(step_in))
can_move = 1
return 1 return 1
return 0
ion_trail.stop()
return ..()
//these three procs overriden to play different sounds //these three procs overriden to play different sounds
/obj/mecha/working/hoverpod/mechturn(direction) /obj/mecha/hoverpod/mechturn(direction)
dir = direction dir = direction
//playsound(src,'sound/machines/hiss.ogg',40,1) //playsound(src,'sound/machines/hiss.ogg',40,1)
return 1 return 1
/obj/mecha/working/hoverpod/mechstep(direction) /obj/mecha/hoverpod/mechstep(direction)
var/result = step(src,direction) var/result = step(src,direction)
if(result) if(result)
playsound(src,'sound/machines/hiss.ogg',40,1) playsound(src,'sound/machines/hiss.ogg',40,1)
return result return result
/obj/mecha/working/hoverpod/mechsteprand() /obj/mecha/hoverpod/mechsteprand()
var/result = step_rand(src) var/result = step_rand(src)
if(result) if(result)
playsound(src,'sound/machines/hiss.ogg',40,1) playsound(src,'sound/machines/hiss.ogg',40,1)
return result return result
/* /obj/mecha/hoverpod/Exit(atom/movable/O)
/obj/mecha/working/hoverpod/New()
..()
return
*/
/obj/mecha/working/hoverpod/combatpod
desc = "An ancient, ghetto fighter." // Ideally would have a seperate icon.
name = "Combat Hoverpod"
/obj/mecha/working/hoverpod/combatpod/New()
..()
var/obj/item/mecha_parts/mecha_equipment/ME = new /obj/item/mecha_parts/mecha_equipment/weapon/energy/laser
ME.attach(src)
ME = new /obj/item/mecha_parts/mecha_equipment/weapon/ballistic/missile_rack/explosive
ME.attach(src)
/obj/mecha/working/hoverpod/shuttlepod
desc = "Who knew a tiny ball could fit three people?"
/obj/mecha/working/hoverpod/shuttlepod/New()
..()
var/obj/item/mecha_parts/mecha_equipment/ME = new /obj/item/mecha_parts/mecha_equipment/tool/passenger
ME.attach(src)
ME = new /obj/item/mecha_parts/mecha_equipment/tool/passenger
ME.attach(src)
/obj/mecha/working/hoverpod/Exit(atom/movable/O)
if(O in cargo) if(O in cargo)
return 0 return 0
return ..() return ..()
/obj/mecha/working/hoverpod/Topic(href, href_list) /obj/mecha/hoverpod/Topic(href, href_list)
..() ..()
if(href_list["drop_from_cargo"]) if(href_list["drop_from_cargo"])
var/obj/O = locate(href_list["drop_from_cargo"]) var/obj/O = locate(href_list["drop_from_cargo"])
@@ -105,7 +78,7 @@
return return
/obj/mecha/working/hoverpod/get_stats_part() /obj/mecha/hoverpod/get_stats_part()
var/output = ..() var/output = ..()
output += "<b>Cargo Compartment Contents:</b><div style=\"margin-left: 15px;\">" output += "<b>Cargo Compartment Contents:</b><div style=\"margin-left: 15px;\">"
if(src.cargo.len) if(src.cargo.len)
@@ -116,7 +89,7 @@
output += "</div>" output += "</div>"
return output return output
/obj/mecha/working/hoverpod/Del() /obj/mecha/hoverpod/Del()
for(var/mob/M in src) for(var/mob/M in src)
if(M==src.occupant) if(M==src.occupant)
continue continue
@@ -130,4 +103,32 @@
T.Entered(A) T.Entered(A)
step_rand(A) step_rand(A)
..() ..()
return return
//Hoverpod variants
/* Commented out the combatpod as they can't reattach their equipment if it ever gets dropped,
* and making a special exception for them seems lame.
/obj/mecha/hoverpod/combatpod
desc = "An ancient, run-down combat spacecraft." // Ideally would have a seperate icon.
name = "Combat Hoverpod"
health = 200
internal_damage_threshold = 35
/obj/mecha/hoverpod/combatpod/New()
..()
var/obj/item/mecha_parts/mecha_equipment/ME = new /obj/item/mecha_parts/mecha_equipment/weapon/energy/laser
ME.attach(src)
ME = new /obj/item/mecha_parts/mecha_equipment/weapon/ballistic/missile_rack/explosive
ME.attach(src)
*/
/obj/mecha/hoverpod/shuttlepod
desc = "Who knew a tiny ball could fit three people?"
/obj/mecha/hoverpod/shuttlepod/New()
..()
var/obj/item/mecha_parts/mecha_equipment/ME = new /obj/item/mecha_parts/mecha_equipment/tool/passenger
ME.attach(src)
ME = new /obj/item/mecha_parts/mecha_equipment/tool/passenger
ME.attach(src)

View File

@@ -97,10 +97,7 @@
SetLuminosity(12) SetLuminosity(12)
// found a powernet, so drain up to max power from it // found a powernet, so drain up to max power from it
var/drained = PN.draw_power(drain_rate)
var/drained = min ( drain_rate, PN.avail )
PN.newload += drained
power_drained += drained
// if tried to drain more than available on powernet // if tried to drain more than available on powernet
// now look for APCs and drain their cells // now look for APCs and drain their cells

View File

@@ -70,5 +70,5 @@
/obj/structure/largecrate/hoverpod/attackby(obj/item/weapon/W as obj, mob/user as mob) /obj/structure/largecrate/hoverpod/attackby(obj/item/weapon/W as obj, mob/user as mob)
if(istype(W, /obj/item/weapon/crowbar)) if(istype(W, /obj/item/weapon/crowbar))
new /obj/mecha/working/hoverpod(loc) new /obj/mecha/hoverpod(loc)
..() ..()

View File

@@ -186,10 +186,6 @@ var/list/globalAirlockWireColorToFlag = RandomAirlockWires()
var/list/globalAirlockIndexToFlag var/list/globalAirlockIndexToFlag
var/list/globalAirlockIndexToWireColor var/list/globalAirlockIndexToWireColor
var/list/globalAirlockWireColorToIndex var/list/globalAirlockWireColorToIndex
var/list/APCWireColorToFlag = RandomAPCWires()
var/list/APCIndexToFlag
var/list/APCIndexToWireColor
var/list/APCWireColorToIndex
var/list/BorgWireColorToFlag = RandomBorgWires() var/list/BorgWireColorToFlag = RandomBorgWires()
var/list/BorgIndexToFlag var/list/BorgIndexToFlag
var/list/BorgIndexToWireColor var/list/BorgIndexToWireColor

View File

@@ -13,6 +13,7 @@
var/frequency = 1457 var/frequency = 1457
var/delay = 0 var/delay = 0
var/airlock_wire = null var/airlock_wire = null
var/datum/wires/connected = null
var/datum/radio_frequency/radio_connection var/datum/radio_frequency/radio_connection
var/deadman = 0 var/deadman = 0
@@ -118,7 +119,9 @@
pulse(var/radio = 0) pulse(var/radio = 0)
if(istype(src.loc, /obj/machinery/door/airlock) && src.airlock_wire && src.wires) if(src.connected && src.wires)
connected.Pulse(src)
else if(istype(src.loc, /obj/machinery/door/airlock) && src.airlock_wire && src.wires)
var/obj/machinery/door/airlock/A = src.loc var/obj/machinery/door/airlock/A = src.loc
A.pulse(src.airlock_wire) A.pulse(src.airlock_wire)
else if(holder) else if(holder)

View File

@@ -63,7 +63,7 @@
var/obj/item/stack/cable_coil/CC = new/obj/item/stack/cable_coil(user.loc) var/obj/item/stack/cable_coil/CC = new/obj/item/stack/cable_coil(user.loc)
CC.amount = 1 CC.amount = 1
CC.updateicon() CC.update_icon()
overlays = list() overlays = list()
string_attached = null string_attached = null
user << "\blue You detach the string from the coin." user << "\blue You detach the string from the coin."

View File

@@ -95,4 +95,12 @@
O.loc = src.loc O.loc = src.loc
usr << "\blue You empty the ore box" usr << "\blue You empty the ore box"
return return
/obj/structure/ore_box/ex_act(severity)
if(severity == 1.0 || (severity < 3.0 && prob(50)))
for (var/obj/item/weapon/ore/O in contents)
O.loc = src.loc
O.ex_act(severity++)
del(src)
return

File diff suppressed because it is too large Load Diff

View File

@@ -239,21 +239,15 @@
var/last_overcharge = overcharge_percent var/last_overcharge = overcharge_percent
if(terminal) if(terminal)
var/excess = terminal.surplus() if(chargemode)
var/target_load = min((capacity-charge)/SMESRATE, chargelevel) // 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 (actual_load >= target_load) // did the powernet have enough power available for us?
if(excess >= 0) // if there's power available, try to charge
var/load = min((capacity * 1.5 - charge)/SMESRATE, chargelevel) // charge at set rate, limited to spare capacity
load = add_load(load) // add the load to the terminal side network
charge += load * SMESRATE // increase the charge
else // if not enough capacity
charging = 0 // stop charging
else
if (chargemode && excess > 0 && excess >= chargelevel)
charging = 1 charging = 1
else
charging = 0
if(online) // if outputting if(online) // if outputting
lastout = min( charge/SMESRATE, output) //limit output to that stored lastout = min( charge/SMESRATE, output) //limit output to that stored

View File

@@ -80,13 +80,14 @@
C.breaker_box = src C.breaker_box = src
var/datum/powernet/PN = new() var/datum/powernet/PN = new()
PN.number = powernets.len + 1 PN.add_cable(C)
powernets += PN
PN.cables += C
C.mergeConnectedNetworks(C.d2) C.mergeConnectedNetworks(C.d2)
C.mergeConnectedNetworksOnTurf() C.mergeConnectedNetworksOnTurf()
if(C.d2 & (C.d2 - 1))// if the cable is layed diagonally, check the others 2 possible directions
C.mergeDiagonalsNetworks(C.d2)
else else
icon_state = icon_state_off icon_state = icon_state_off
for(var/obj/structure/cable/C in src.loc) for(var/obj/structure/cable/C in src.loc)

View File

@@ -1,29 +1,27 @@
// attach a wire to a power machine - leads from the turf you are standing on ///////////////////////////////
//CABLE STRUCTURE
///////////////////////////////
/obj/machinery/power/attackby(obj/item/weapon/W, mob/user)
if(istype(W, /obj/item/stack/cable_coil)) ////////////////////////////////
// Definitions
////////////////////////////////
var/obj/item/stack/cable_coil/coil = W /* Cable directions (d1 and d2)
var/turf/T = user.loc
if(T.intact || !istype(T, /turf/simulated/floor)) 9 1 5
return \ | /
8 - 0 - 4
/ | \
10 2 6
if(get_dist(src, user) > 1) If d1 = 0 and d2 = 0, there's no cable
return If d1 = 0 and d2 = dir, it's a O-X cable, getting from the center of the tile to dir (knot cable)
If d1 = dir1 and d2 = dir2, it's a full X-X cable, getting from dir1 to dir2
By design, d1 is the smallest direction and d2 is the highest
*/
if(!directwired) // only for attaching to directwired machines
return
coil.turf_place(T, user)
return
else
..()
return
// the power cable object
/obj/structure/cable /obj/structure/cable
level = 1 level = 1
anchored =1 anchored =1
@@ -74,17 +72,20 @@
var/turf/T = src.loc // hide if turf is not intact var/turf/T = src.loc // hide if turf is not intact
if(level==1) hide(T.intact) if(level==1) hide(T.intact)
cable_list += src cable_list += src //add it to the global cable list
update_icon()
/obj/structure/cable/Del() // called when a cable is deleted /obj/structure/cable/Del() // called when a cable is deleted
if(!defer_powernet_rebuild) // set if network will be rebuilt manually if(powernet)
if(powernet) cut_cable_from_powernet() // update the powernets
powernet.cut_cable(src) // update the powernets cable_list -= src //remove it from global cable list
cable_list -= src ..() // then go ahead and delete the cable
..() // then go ahead and delete the cable
///////////////////////////////////
// General procedures
///////////////////////////////////
//If underfloor, hide the cable
/obj/structure/cable/hide(var/i) /obj/structure/cable/hide(var/i)
if(level == 1 && istype(loc, /turf)) if(level == 1 && istype(loc, /turf))
@@ -92,17 +93,25 @@
updateicon() updateicon()
/obj/structure/cable/proc/updateicon() /obj/structure/cable/proc/updateicon()
icon_state = "[d1]-[d2]" if(invisibility)
alpha = invisibility ? 127 : 255 icon_state = "[d1]-[d2]-f"
else
icon_state = "[d1]-[d2]"
// returns the powernet this cable belongs to // returns the powernet this cable belongs to
/obj/structure/cable/proc/get_powernet() //TODO: remove this as it is obsolete /obj/structure/cable/proc/get_powernet() //TODO: remove this as it is obsolete
return powernet return powernet
//Telekinesis has no effect on a cable
/obj/structure/cable/attack_tk(mob/user) /obj/structure/cable/attack_tk(mob/user)
return return
// Items usable on a cable :
// - Wirecutters : cut it duh !
// - Cable coil : merge cables
// - Multitool : get the power currently passing through the cable
//
/obj/structure/cable/attackby(obj/item/W, mob/user) /obj/structure/cable/attackby(obj/item/W, mob/user)
var/turf/T = src.loc var/turf/T = src.loc
@@ -110,13 +119,11 @@
return return
if(istype(W, /obj/item/weapon/wirecutters)) if(istype(W, /obj/item/weapon/wirecutters))
///// Z-Level Stuff ///// Z-Level Stuff
if(src.d1 == 12 || src.d2 == 12) if(src.d1 == 12 || src.d2 == 12)
user << "<span class='warning'>You must cut this cable from above.</span>" user << "<span class='warning'>You must cut this cable from above.</span>"
return return
///// Z-Level Stuff ///// Z-Level Stuff
if(breaker_box) if(breaker_box)
user << "\red This cable is connected to nearby breaker box. Use breaker box to interact with it." user << "\red This cable is connected to nearby breaker box. Use breaker box to interact with it."
return return
@@ -142,22 +149,23 @@
if(c.d1 == 12 || c.d2 == 12) if(c.d1 == 12 || c.d2 == 12)
c.Del() c.Del()
///// Z-Level Stuff ///// Z-Level Stuff
investigate_log("was cut by [key_name(usr, usr.client)] in [user.loc.loc]","wires")
del(src) del(src) // qdel
return
return // not needed, but for clarity
else if(istype(W, /obj/item/stack/cable_coil)) else if(istype(W, /obj/item/stack/cable_coil))
var/obj/item/stack/cable_coil/coil = W var/obj/item/stack/cable_coil/coil = W
if (coil.get_amount() < 1)
user << "Not enough cable"
return
coil.cable_join(src, user) coil.cable_join(src, user)
else if(istype(W, /obj/item/device/multitool)) else if(istype(W, /obj/item/device/multitool))
var/datum/powernet/PN = get_powernet() // find the powernet if(powernet && (powernet.avail > 0)) // is it powered?
user << "<span class='warning'>[powernet.avail]W in power network.</span>"
if(PN && (PN.avail > 0)) // is it powered?
user << "<span class='warning'>[PN.avail]W in power network.</span>"
else else
user << "<span class='warning'>The cable is not powered.</span>" user << "<span class='warning'>The cable is not powered.</span>"
@@ -171,7 +179,6 @@
src.add_fingerprint(user) src.add_fingerprint(user)
// shock the user with probability prb // shock the user with probability prb
/obj/structure/cable/proc/shock(mob/user, prb, var/siemens_coeff = 1.0) /obj/structure/cable/proc/shock(mob/user, prb, var/siemens_coeff = 1.0)
if(!prob(prb)) if(!prob(prb))
return 0 return 0
@@ -183,24 +190,296 @@
else else
return 0 return 0
//explosion handling
/obj/structure/cable/ex_act(severity) /obj/structure/cable/ex_act(severity)
switch(severity) switch(severity)
if(1.0) if(1.0)
del(src) del(src) // qdel
if(2.0) if(2.0)
if (prob(50)) if (prob(50))
new/obj/item/stack/cable_coil(src.loc, src.d1 ? 2 : 1, color) new/obj/item/stack/cable_coil(src.loc, src.d1 ? 2 : 1, color)
del(src) del(src) // qdel
if(3.0) if(3.0)
if (prob(25)) if (prob(25))
new/obj/item/stack/cable_coil(src.loc, src.d1 ? 2 : 1, color) new/obj/item/stack/cable_coil(src.loc, src.d1 ? 2 : 1, color)
del(src) del(src) // qdel
return return
// the cable coil object, used for laying cable obj/structure/cable/proc/cableColor(var/colorC)
var/color_n = "#DD0000"
if(colorC)
color_n = colorC
color = color_n
////////////////////////////////////////////
// Power related
///////////////////////////////////////////
obj/structure/cable/proc/add_avail(var/amount)
if(powernet)
powernet.newavail += amount
obj/structure/cable/proc/add_load(var/amount)
if(powernet)
powernet.load += amount
obj/structure/cable/proc/surplus()
if(powernet)
return powernet.avail-powernet.load
else
return 0
obj/structure/cable/proc/avail()
if(powernet)
return powernet.avail
else
return 0
/////////////////////////////////////////////////
// Cable laying helpers
////////////////////////////////////////////////
//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
// merge with the powernets of power objects in the given direction
/obj/structure/cable/proc/mergeConnectedNetworks(var/direction)
var/fdir = (!direction)? 0 : turn(direction, 180) //flip the direction, to match with the source position on its turf
if(!(d1 == direction || d2 == direction)) //if the cable is not pointed in this direction, do nothing
return
var/turf/TB = get_step(src, direction)
for(var/obj/structure/cable/C in TB)
if(!C)
continue
if(src == C)
continue
if(C.d1 == fdir || C.d2 == fdir) //we've got a matching cable in the neighbor turf
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
// merge with the powernets of power objects in the source turf
/obj/structure/cable/proc/mergeConnectedNetworksOnTurf()
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.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 // 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
var/obj/machinery/power/M = AM
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
//////////////////////////////////////////////
// Powernets handling helpers
//////////////////////////////////////////////
//if powernetless_only = 1, will only get connections without powernet
/obj/structure/cable/proc/get_connections(var/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
else if(d1) //if not a node cable
T = get_step(src, d1)
if(T)
. += power_list(T, src, turn(d1, 180), powernetless_only) //get adjacents matching cables
if(d1&(d1-1)) //diagonal direction, must check the 4 possibles adjacents tiles
T = get_step(src,d1&3) // go north/south
if(T)
. += power_list(T, src, d1 ^ 3, powernetless_only) //get diagonally matching cables
T = get_step(src,d1&12) // go east/west
if(T)
. += power_list(T, src, d1 ^ 12, powernetless_only) //get diagonally matching cables
. += 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)
. += power_list(T, src, turn(d2, 180), powernetless_only) //get adjacents matching cables
if(d2&(d2-1)) //diagonal direction, must check the 4 possibles adjacents tiles
T = get_step(src,d2&3) // go north/south
if(T)
. += power_list(T, src, d2 ^ 3, powernetless_only) //get diagonally matching cables
T = get_step(src,d2&12) // go east/west
if(T)
. += power_list(T, src, d2 ^ 12, powernetless_only) //get diagonally matching cables
. += power_list(loc, src, d2, powernetless_only) //get on turf matching cables
return .
//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) // qdel
// cut the cable's powernet at this cable and updates the powergrid
/obj/structure/cable/proc/cut_cable_from_powernet()
var/turf/T1 = loc
var/list/P_list
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...
P_list += power_list(loc, src, d1, 0, cable_only = 1)//... and on turf
if(P_list.len == 0)//if nothing in both list, then the cable was a lone cable, just delete it and its powernet
powernet.remove_cable(src)
for(var/obj/machinery/power/P in T1)//check if it was powering a machine
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 (and delete powernet)
return
// remove the cut cable from its turf and powernet, so that it doesn't get count in propagate_network worklist
loc = null
powernet.remove_cable(src) //remove the cut cable from its powernet
var/datum/powernet/newPN = new()// creates a new powernet...
propagate_network(P_list[1], newPN)//... and propagates it to the other side of the cable
// Disconnect machines connected to nodes
if(d1 == 0) // if we cut a node (O-X) cable
for(var/obj/machinery/power/P in T1)
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
///////////////////////////////////////////////
////////////////////////////////
// Definitions
////////////////////////////////
#define MAXCOIL 30 #define MAXCOIL 30
/obj/item/stack/cable_coil /obj/item/stack/cable_coil
name = "cable coil" name = "cable coil"
icon = 'icons/obj/power.dmi' icon = 'icons/obj/power.dmi'
@@ -219,10 +498,12 @@
item_state = "coil" item_state = "coil"
attack_verb = list("whipped", "lashed", "disciplined", "flogged") attack_verb = list("whipped", "lashed", "disciplined", "flogged")
suicide_act(mob/user) /obj/item/stack/cable_coil/suicide_act(mob/user)
viewers(user) << "<span class='warning'><b>[user] is strangling \himself with the [src.name]! It looks like \he's trying to commit suicide.</b></span>" if(locate(/obj/structure/stool) in user.loc)
return(OXYLOSS) user.visible_message("<span class='suicide'>[user] is making a noose with the [src.name]! It looks like \he's trying to commit suicide.</span>")
else
user.visible_message("<span class='suicide'>[user] is strangling \himself with the [src.name]! It looks like \he's trying to commit suicide.</span>")
return(OXYLOSS)
/obj/item/stack/cable_coil/New(loc, length = MAXCOIL, var/param_color = null) /obj/item/stack/cable_coil/New(loc, length = MAXCOIL, var/param_color = null)
..() ..()
@@ -233,10 +514,38 @@
color = item_color color = item_color
pixel_x = rand(-2,2) pixel_x = rand(-2,2)
pixel_y = rand(-2,2) pixel_y = rand(-2,2)
updateicon() update_icon()
update_wclass() update_wclass()
/obj/item/stack/cable_coil/proc/updateicon() ///////////////////////////////////
// General procedures
///////////////////////////////////
//you can use wires to heal robotics
/obj/item/stack/cable_coil/attack(mob/M as mob, mob/user as mob)
if(istype(M,/mob/living/carbon/human))
var/mob/living/carbon/human/H = M
var/datum/organ/external/S = H.get_organ(user.zone_sel.selecting)
if(!(S.status & ORGAN_ROBOT) || user.a_intent != "help")
return ..()
if(H.species.flags & IS_SYNTHETIC)
if(M == user)
user << "\red You can't repair damage to your own body - it's against OH&S."
return
if(S.burn_dam > 0 && use(1))
S.heal_damage(0,15,0,1)
user.visible_message("\red \The [user] repairs some burn damage on \the [M]'s [S.display_name] with \the [src].")
return
else
user << "Nothing to fix!"
else
return ..()
/obj/item/stack/cable_coil/update_icon()
if (!color) if (!color)
color = pick(COLOR_RED, COLOR_BLUE, COLOR_GREEN, COLOR_ORANGE, COLOR_WHITE, COLOR_PINK, COLOR_YELLOW, COLOR_CYAN) color = pick(COLOR_RED, COLOR_BLUE, COLOR_GREEN, COLOR_ORANGE, COLOR_WHITE, COLOR_PINK, COLOR_YELLOW, COLOR_CYAN)
item_color = color item_color = color
@@ -259,12 +568,13 @@
/obj/item/stack/cable_coil/examine() /obj/item/stack/cable_coil/examine()
set src in view(1) set src in view(1)
if(amount == 1) if(get_amount() == 1)
usr << "A short piece of power cable." usr << "A short piece of power cable."
else if(amount == 2) else if(get_amount() == 2)
usr << "A piece of power cable." usr << "A piece of power cable."
else else
usr << "A coil of power cable. There are [amount] lengths of cable in the coil." usr << "A coil of power cable. There are [get_amount()] lengths of cable in the coil."
/obj/item/stack/cable_coil/verb/make_restraint() /obj/item/stack/cable_coil/verb/make_restraint()
set name = "Make Cable Restraints" set name = "Make Cable Restraints"
@@ -274,26 +584,28 @@
if(ishuman(M) && !M.restrained() && !M.stat && !M.paralysis && ! M.stunned) if(ishuman(M) && !M.restrained() && !M.stat && !M.paralysis && ! M.stunned)
if(!istype(usr.loc,/turf)) return if(!istype(usr.loc,/turf)) return
if(src.amount <= 14) if(src.amount <= 14)
usr << "<span class='warning'>You need at least 15 lengths to make restraints!</span>" usr << "\red You need at least 15 lengths to make restraints!"
return return
var/obj/item/weapon/handcuffs/cable/B = new /obj/item/weapon/handcuffs/cable(usr.loc) var/obj/item/weapon/handcuffs/cable/B = new /obj/item/weapon/handcuffs/cable(usr.loc)
B.color = item_color B.icon_state = "cuff_[item_color]"
usr << "<span class='notice'>You wind some cable together to make some restraints.</span>" usr << "\blue You wind some cable together to make some restraints."
src.use(15) src.use(15)
else else
usr << "<span class='notice'>\blue You cannot do that.</span>" usr << "\blue You cannot do that."
..() ..()
// Items usable on a cable coil :
// - Wirecutters : cut them duh !
// - Cable coil : merge cables
/obj/item/stack/cable_coil/attackby(obj/item/weapon/W, mob/user) /obj/item/stack/cable_coil/attackby(obj/item/weapon/W, mob/user)
..()
if( istype(W, /obj/item/weapon/wirecutters) && src.amount > 1) if( istype(W, /obj/item/weapon/wirecutters) && src.amount > 1)
src.amount-- src.amount--
new/obj/item/stack/cable_coil(user.loc, 1,item_color) new/obj/item/stack/cable_coil(user.loc, 1,item_color)
user << "<span class='notice'>You cut a piece off the cable coil.</span>" user << "You cut a piece off the cable coil."
src.updateicon() src.update_icon()
src.update_wclass()
return return
else if(istype(W, /obj/item/stack/cable_coil))
else if( istype(W, /obj/item/stack/cable_coil) )
var/obj/item/stack/cable_coil/C = W var/obj/item/stack/cable_coil/C = W
if(C.amount >= MAXCOIL) if(C.amount >= MAXCOIL)
user << "The coil is too long, you cannot add any more cable to it." user << "The coil is too long, you cannot add any more cable to it."
@@ -301,54 +613,65 @@
if( (C.amount + src.amount <= MAXCOIL) ) if( (C.amount + src.amount <= MAXCOIL) )
user << "You join the cable coils together." user << "You join the cable coils together."
C.add(src.amount) // give it cable C.give(src.amount) // give it cable
src.use(src.amount) // make sure this one cleans up right src.use(src.amount) // make sure this one cleans up right
return
else else
var/amt = MAXCOIL - C.amount var/amt = MAXCOIL - C.amount
user << "You transfer [amt] length\s of cable from one coil to the other." user << "You transfer [amt] length\s of cable from one coil to the other."
C.add(amt) C.give(amt)
src.use(amt) src.use(amt)
return return
..()
/obj/item/stack/cable_coil/attack_hand(mob/user as mob) //remove cables from the stack
if (user.get_inactive_hand() == src) /* This is probably reduntant
var/obj/item/stack/cable_coil/F = new /obj/item/stack/cable_coil(user, 1, color) /obj/item/stack/cable_coil/use(var/used)
F.copy_evidences(src) if(src.amount < used)
user.put_in_hands(F) return 0
src.add_fingerprint(user) else if (src.amount == used)
F.add_fingerprint(user) if(ismob(loc)) //handle mob icon update
use(1) var/mob/M = loc
M.unEquip(src)
qdel(src)
return 1
else else
..() amount -= used
return update_icon()
return 1
*/
/obj/item/stack/cable_coil/use(var/used) /obj/item/stack/cable_coil/use(var/used)
. = ..() . = ..()
updateicon() update_icon()
update_wclass()
return return
/obj/item/stack/cable_coil/add(var/extra) //add cables to the stack
. = ..() /obj/item/stack/cable_coil/proc/give(var/extra)
updateicon() if(amount + extra > MAXCOIL)
update_wclass() amount = MAXCOIL
return else
amount += extra
update_icon()
///////////////////////////////////////////////
// Cable laying procedures
//////////////////////////////////////////////
// called when cable_coil is clicked on a turf/simulated/floor // called when cable_coil is clicked on a turf/simulated/floor
/obj/item/stack/cable_coil/proc/turf_place(turf/simulated/floor/F, mob/user) /obj/item/stack/cable_coil/proc/turf_place(turf/simulated/floor/F, mob/user)
if(!isturf(user.loc)) if(!isturf(user.loc))
return return
if(get_dist(F,user) > 1) if(get_amount() < 1) // Out of cable
user << "<span class='warning'>You can't lay cable at a place that far away.</span>" user << "There is no cable left."
return return
if(F.intact) // if floor is intact, complain if(get_dist(F,user) > 1) // Too far
user << "<span class='warning'>You can't lay cable there unless the floor tiles are removed.</span>" user << "You can't lay cable at a place that far away."
return
if(F.intact) // Ff floor is intact, complain
user << "You can't lay cable there unless the floor tiles are removed."
return return
else else
@@ -382,9 +705,8 @@
C.add_fingerprint(user) C.add_fingerprint(user)
C.updateicon() C.updateicon()
C.powernet = new() var/datum/powernet/PN = new()
powernets += C.powernet PN.add_cable(C)
C.powernet.cables += C
C.mergeConnectedNetworks(C.d2) C.mergeConnectedNetworks(C.d2)
C.mergeConnectedNetworksOnTurf() C.mergeConnectedNetworksOnTurf()
@@ -396,15 +718,12 @@
D.add_fingerprint(user) D.add_fingerprint(user)
D.updateicon() D.updateicon()
D.powernet = C.powernet PN.add_cable(D)
D.powernet.cables += D
D.mergeConnectedNetworksOnTurf() D.mergeConnectedNetworksOnTurf()
// do the normal stuff // do the normal stuff
else else
///// Z-Level Stuff ///// Z-Level Stuff
for(var/obj/structure/cable/LC in F) for(var/obj/structure/cable/LC in F)
if((LC.d1 == dirn && LC.d2 == 0 ) || ( LC.d2 == dirn && LC.d1 == 0)) if((LC.d1 == dirn && LC.d2 == 0 ) || ( LC.d2 == dirn && LC.d1 == 0))
user << "There's already a cable at that position." user << "There's already a cable at that position."
@@ -414,32 +733,32 @@
C.cableColor(item_color) C.cableColor(item_color)
C.d1 = 0 //set up the new cable
C.d1 = 0 //it's a O-X node cable
C.d2 = dirn C.d2 = dirn
C.add_fingerprint(user) C.add_fingerprint(user)
C.updateicon() C.updateicon()
C.powernet = new() //create a new powernet with the cable, if needed it will be merged later
powernets += C.powernet var/datum/powernet/PN = new()
C.powernet.cables += C PN.add_cable(C)
C.mergeConnectedNetworks(C.d2) C.mergeConnectedNetworks(C.d2) //merge the powernet with adjacents powernets
C.mergeConnectedNetworksOnTurf() C.mergeConnectedNetworksOnTurf() //merge the powernet with on turf powernets
if(C.d2 & (C.d2 - 1))// if the cable is layed diagonally, check the others 2 possible directions
C.mergeDiagonalsNetworks(C.d2)
use(1) use(1)
if (C.shock(user, 50)) if (C.shock(user, 50))
if (prob(50)) //fail if (prob(50)) //fail
new/obj/item/stack/cable_coil(C.loc, 1, C.color) new/obj/item/stack/cable_coil(C.loc, 1, C.color)
del(C) del(C) // qdel
//src.laying = 1
//last = C
// called when cable_coil is click on an installed obj/cable // called when cable_coil is click on an installed obj/cable
// or click on a turf that already contains a "node" cable
/obj/item/stack/cable_coil/proc/cable_join(obj/structure/cable/C, mob/user) /obj/item/stack/cable_coil/proc/cable_join(obj/structure/cable/C, mob/user)
var/turf/U = user.loc var/turf/U = user.loc
if(!isturf(U)) if(!isturf(U))
return return
@@ -450,18 +769,20 @@
return return
if(get_dist(C, user) > 1) // make sure it's close enough if(get_dist(C, user) > 1) // make sure it's close enough
user << "<span class='warning'>You can't lay cable at a place that far away.</span>" user << "You can't lay cable at a place that far away."
return return
if(U == T) // do nothing if we clicked a cable we're standing on if(U == T) //if clicked on the turf we're standing on, try to put a cable in the direction we're facing
return // may change later if can think of something logical to do turf_place(T,user)
return
var/dirn = get_dir(C, user) var/dirn = get_dir(C, user)
if(C.d1 == dirn || C.d2 == dirn) // one end of the clicked cable is pointing towards us // 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 if(U.intact) // can't place a cable if the floor is complete
user << "<span class='warning'>You can't lay cable there unless the floor tiles are removed.</span>" user << "You can't lay cable there unless the floor tiles are removed."
return return
else else
// cable is pointing at us, we're standing on an open tile // cable is pointing at us, we're standing on an open tile
@@ -471,7 +792,7 @@
for(var/obj/structure/cable/LC in U) // check to make sure there's not a cable there already 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) if(LC.d1 == fdirn || LC.d2 == fdirn)
user << "<span class='warning'>There's already a cable at that position.</span>" user << "There's already a cable at that position."
return return
var/obj/structure/cable/NC = new(U) var/obj/structure/cable/NC = new(U)
@@ -482,19 +803,27 @@
NC.add_fingerprint() NC.add_fingerprint()
NC.updateicon() NC.updateicon()
if(C.powernet) //create a new powernet with the cable, if needed it will be merged later
NC.powernet = C.powernet var/datum/powernet/newPN = new()
NC.powernet.cables += NC newPN.add_cable(NC)
NC.mergeConnectedNetworks(NC.d2)
NC.mergeConnectedNetworksOnTurf() 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) use(1)
if (NC.shock(user, 50)) if (NC.shock(user, 50))
if (prob(50)) //fail if (prob(50)) //fail
new/obj/item/stack/cable_coil(NC.loc, 1, NC.color) new/obj/item/stack/cable_coil(NC.loc, 1, NC.color)
del(NC) del(NC) // qdel
return return
else if(C.d1 == 0) // exisiting cable doesn't point at our position, so see if it's a stub
// exisiting cable doesn't point at our position, so see if it's a stub
else if(C.d1 == 0)
// if so, make it a full cable pointing from it's old direction to our dirn // if so, make it a full cable pointing from it's old direction to our dirn
var/nd1 = C.d2 // these will be the new directions var/nd1 = C.d2 // these will be the new directions
var/nd2 = dirn var/nd2 = dirn
@@ -509,7 +838,7 @@
if(LC == C) // skip the cable we're interacting with if(LC == C) // skip the cable we're interacting with
continue continue
if((LC.d1 == nd1 && LC.d2 == nd2) || (LC.d1 == nd2 && LC.d2 == nd1) ) // make sure no cable matches either direction if((LC.d1 == nd1 && LC.d2 == nd2) || (LC.d1 == nd2 && LC.d2 == nd1) ) // make sure no cable matches either direction
user << "<span class='warning'>There's already a cable at that position.</span>" user << "There's already a cable at that position."
return return
@@ -522,90 +851,30 @@
C.updateicon() C.updateicon()
C.mergeConnectedNetworks(C.d1) C.mergeConnectedNetworks(C.d1) //merge the powernets...
C.mergeConnectedNetworks(C.d2) C.mergeConnectedNetworks(C.d2) //...in the two new cable directions
C.mergeConnectedNetworksOnTurf() 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) use(1)
if (C.shock(user, 50)) if (C.shock(user, 50))
if (prob(50)) //fail if (prob(50)) //fail
new/obj/item/stack/cable_coil(C.loc, 2, C.color) new/obj/item/stack/cable_coil(C.loc, 2, C.color)
del(C) del(C) // qdel
return
C.denode()// this call may have disconnected some cables that terminated on the centre of the turf, if so split the powernets.
return return
/obj/structure/cable/proc/mergeConnectedNetworks(var/direction) //////////////////////////////
var/turf/TB // Misc.
if(!(d1 == direction || d2 == direction)) /////////////////////////////
return
TB = get_step(src, direction)
for(var/obj/structure/cable/TC in TB)
if(!TC)
continue
if(src == TC)
continue
var/fdir = (!direction)? 0 : turn(direction, 180)
if(TC.d1 == fdir || TC.d2 == fdir)
if(!TC.powernet)
TC.powernet = new()
powernets += TC.powernet
TC.powernet.cables += TC
if(powernet)
merge_powernets(powernet,TC.powernet)
else
powernet = TC.powernet
powernet.cables += src
/obj/structure/cable/proc/mergeConnectedNetworksOnTurf()
if(!powernet)
powernet = new()
powernets += powernet
powernet.cables += src
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
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
else if(istype(AM,/obj/machinery/power))
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
obj/structure/cable/proc/cableColor(var/colorC)
var/color_n = "#DD0000"
if(colorC)
color_n = colorC
color = color_n
/obj/item/stack/cable_coil/cut /obj/item/stack/cable_coil/cut
item_state = "coil2" item_state = "coil2"
@@ -615,7 +884,7 @@ obj/structure/cable/proc/cableColor(var/colorC)
src.amount = rand(1,2) src.amount = rand(1,2)
pixel_x = rand(-2,2) pixel_x = rand(-2,2)
pixel_y = rand(-2,2) pixel_y = rand(-2,2)
updateicon() update_icon()
update_wclass() update_wclass()
/obj/item/stack/cable_coil/yellow /obj/item/stack/cable_coil/yellow
@@ -642,27 +911,3 @@ obj/structure/cable/proc/cableColor(var/colorC)
/obj/item/stack/cable_coil/random/New() /obj/item/stack/cable_coil/random/New()
item_color = pick(COLOR_RED, COLOR_BLUE, COLOR_GREEN, COLOR_WHITE, COLOR_PINK, COLOR_YELLOW, COLOR_CYAN) item_color = pick(COLOR_RED, COLOR_BLUE, COLOR_GREEN, COLOR_WHITE, COLOR_PINK, COLOR_YELLOW, COLOR_CYAN)
..() ..()
/obj/item/stack/cable_coil/attack(mob/M as mob, mob/user as mob)
if(hasorgans(M))
var/datum/organ/external/S = M:get_organ(user.zone_sel.selecting)
if(!(S.status & ORGAN_ROBOT) || user.a_intent != "help")
return ..()
if(istype(M,/mob/living/carbon/human))
var/mob/living/carbon/human/H = M
if(H.species.flags & IS_SYNTHETIC)
if(M == user)
user << "\red You can't repair damage to your own body - it's against OH&S."
return
if(S.burn_dam > 0 && use(1))
S.heal_damage(0,15,0,1)
user.visible_message("\red \The [user] repairs some burn damage on \the [M]'s [S.display_name] with \the [src].")
return
else
user << "Nothing to fix!"
else
return ..()

View File

@@ -10,7 +10,6 @@
icon_state = "tracker" //ICON stolen from solar tracker. There is no need to make new texture for debug item icon_state = "tracker" //ICON stolen from solar tracker. There is no need to make new texture for debug item
anchored = 1 anchored = 1
density = 1 density = 1
directwired = 1
var/power_generation_rate = 2000000 //Defaults to 2MW of power. Should be enough to run SMES charging on full 2 times. var/power_generation_rate = 2000000 //Defaults to 2MW of power. Should be enough to run SMES charging on full 2 times.
var/powernet_connection_failed = 0 var/powernet_connection_failed = 0

View File

@@ -48,7 +48,6 @@ display round(lastgen) and phorontank amount
icon_state = "portgen0" icon_state = "portgen0"
density = 1 density = 1
anchored = 0 anchored = 0
directwired = 0
use_power = 0 use_power = 0
var/active = 0 var/active = 0

View File

@@ -1,10 +1,16 @@
//////////////////////////////
// POWER MACHINERY BASE CLASS
//////////////////////////////
/////////////////////////////
// Definitions
/////////////////////////////
/obj/machinery/power /obj/machinery/power
name = null name = null
icon = 'icons/obj/power.dmi' icon = 'icons/obj/power.dmi'
anchored = 1.0 anchored = 1.0
var/datum/powernet/powernet = null 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 use_power = 0
idle_power_usage = 0 idle_power_usage = 0
active_power_usage = 0 active_power_usage = 0
@@ -13,19 +19,23 @@
disconnect_from_network() disconnect_from_network()
..() ..()
///////////////////////////////
// General procedures
//////////////////////////////
// common helper procs for all power machines // common helper procs for all power machines
/obj/machinery/power/proc/add_avail(var/amount) /obj/machinery/power/proc/add_avail(var/amount)
if(powernet) if(powernet)
powernet.newavail += amount powernet.newavail += amount
/obj/machinery/power/proc/add_load(var/amount) /obj/machinery/power/proc/draw_power(var/amount)
if(powernet) if(powernet)
return powernet.draw_power(amount) return powernet.draw_power(amount)
return 0 return 0
/obj/machinery/power/proc/surplus() /obj/machinery/power/proc/surplus()
if(powernet) if(powernet)
return powernet.surplus() return powernet.avail-powernet.load
else else
return 0 return 0
@@ -35,18 +45,18 @@
else else
return 0 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). // returns true if the area has power on given channel (or doesn't require power).
// defaults to power_channel // defaults to power_channel
/obj/machinery/proc/powered(var/chan = -1) // defaults to power_channel
/obj/machinery/proc/powered(var/chan = -1)
if(!src.loc) if(!src.loc)
return 0 return 0
//This is bad. This makes machines which are switched off not update their stat flag correctly when power_change() is called. if(!use_power)
//If use_power is 0, then you probably shouldn't be checking power to begin with. return 1
//if(!use_power)
// return 1
var/area/A = src.loc.loc // make sure it's in an area var/area/A = src.loc.loc // make sure it's in an area
if(!A || !isarea(A) || !A.master) if(!A || !isarea(A) || !A.master)
@@ -56,75 +66,127 @@
return A.master.powered(chan) // return power status of the area return A.master.powered(chan) // return power status of the area
// increment the power usage stats for an 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(var/amount, var/chan = -1, var/autocalled = 0) // defaults to power_channel var/area/A = get_area(src) // make sure it's in an area
var/area/A = src.loc.loc // make sure it's in an area
if(!A || !isarea(A) || !A.master) if(!A || !isarea(A) || !A.master)
return return
if(chan == -1) if(chan == -1)
chan = power_channel chan = power_channel
A.master.use_power(amount, chan) A.master.use_power(amount, chan)
if(!autocalled)
log_power_update_request(A.master, src)
A.master.powerupdate = 2 // Decremented by 2 each GC tick, since it's not auto power change we're going to update power twice.
return 1
//The master_area optional argument can be used to save on a lot of processing if the master area is already known. This is mainly intended for when this proc is called by the master controller. /obj/machinery/proc/power_change() // called whenever the power settings of the containing area change
/obj/machinery/proc/power_change(var/area/master_area = null) // called whenever the power settings of the containing area change
// by default, check equipment channel & set flag // by default, check equipment channel & set flag
// can override if needed // can override if needed
var/has_power if(powered(power_channel))
if (master_area)
has_power = master_area.powered(power_channel)
else
has_power = powered(power_channel)
if(has_power)
stat &= ~NOPOWER stat &= ~NOPOWER
else else
stat |= NOPOWER stat |= NOPOWER
return
// the powernet datum // connect the machine to a powernet if a node cable is present on the turf
// each contiguous network of cables & nodes /obj/machinery/power/proc/connect_to_network()
var/turf/T = src.loc
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
// rebuild all power networks from scratch C.powernet.add_machine(src)
/hook/startup/proc/buildPowernets()
return makepowernets()
/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)
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
return 1 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
// 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(W, /obj/item/stack/cable_coil))
var/obj/item/stack/cable_coil/coil = W
var/turf/T = user.loc
if(T.intact || !istype(T, /turf/simulated/floor))
return
if(get_dist(src, user) > 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()
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.powernet) continue
if(C.d1 == cdir || C.d2 == cdir)
. += 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) // the cable is a node cable
. += C
return .
///////////////////////////////////////////
// GLOBAL PROCS for powernets handling
//////////////////////////////////////////
// returns a list of all power-related objects (nodes, cable, junctions) in turf, // returns a list of all power-related objects (nodes, cable, junctions) in turf,
// excluding source, that match the direction d // excluding source, that match the direction d
// if unmarked==1, only return those with no powernet // if unmarked==1, only return those with no powernet
/proc/power_list(var/turf/T, var/source, var/d, var/unmarked=0) /proc/power_list(var/turf/T, var/source, var/d, var/unmarked=0, var/cable_only = 0)
. = list() . = list()
var/fdir = (!d)? 0 : turn(d, 180) var/fdir = (!d)? 0 : turn(d, 180) // the opposite direction to d (or 0 if d==0)
// the opposite direction to d (or 0 if d==0)
///// Z-Level Stuff ///// Z-Level Stuff
var/Zdir var/Zdir
if(d==11) if(d==11)
@@ -134,16 +196,15 @@
else else
Zdir = 999 Zdir = 999
///// Z-Level Stuff ///// Z-Level Stuff
// world.log << "d=[d] fdir=[fdir]"
for(var/AM in T) for(var/AM in T)
if(AM == source) continue //we don't want to return source if(AM == source) continue //we don't want to return source
if(istype(AM,/obj/machinery/power)) if(!cable_only && istype(AM,/obj/machinery/power))
var/obj/machinery/power/P = AM 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(!unmarked || !P.powernet) //if unmarked=1 we only return things with no powernet
if(P.directwired || (d == 0)) if(d == 0)
. += P . += P
else if(istype(AM,/obj/structure/cable)) else if(istype(AM,/obj/structure/cable))
@@ -154,115 +215,82 @@
if(C.d1 == fdir || C.d2 == fdir || C.d1 == Zdir || C.d2 == Zdir) if(C.d1 == fdir || C.d2 == fdir || C.d1 == Zdir || C.d2 == Zdir)
///// Z-Level Stuff ///// Z-Level Stuff
. += C . += C
else if(C.d1 == turn(C.d2, 180)) else if(C.d1 == d || C.d2 == d)
. += C . += C
return . return .
/hook/startup/proc/buildPowernets()
return makepowernets()
/obj/structure/cable/proc/get_connections() // rebuild all power networks from scratch - only called at world creation or by the admin verb
. = list() // this will be a list of all connected power objects /proc/makepowernets()
var/turf/T = loc for(var/datum/powernet/PN in powernets)
del(PN)
powernets.Cut()
///// Z-Level Stuff for(var/obj/structure/cable/PC in cable_list)
if(d1) if(!PC.powernet)
if(d1 <= 10) var/datum/powernet/NewPN = new()
T = get_step(src, d1) NewPN.add_cable(PC)
if(T) propagate_network(PC,PC.powernet)
. += power_list(T, src, d1, 1)
else 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)
else if(!d1)
if(T)
. += power_list(T, src, d1, 1)
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)
else
T = get_step(src, d2)
if(T)
. += power_list(T, src, d2, 1)
///// Z-Level Stuff
return .
/obj/machinery/power/proc/get_connections()
. = list()
if(!directwired)
return get_indirect_connections()
var/cdir
for(var/card in cardinal)
var/turf/T = get_step(loc,card)
cdir = get_dir(T,loc)
for(var/obj/structure/cable/C in T)
if(C.powernet) continue
if(C.d1 == cdir || C.d2 == cdir)
. += C
return .
/obj/machinery/power/proc/get_indirect_connections()
. = list()
for(var/obj/structure/cable/C in loc)
if(C.powernet) continue
if(C.d1 == 0)
. += C
return .
/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 return 1
/obj/machinery/power/proc/disconnect_from_network() //remove the old powernet and replace it with a new one throughout the network.
if(!powernet) /proc/propagate_network(var/obj/O, var/datum/powernet/PN)
//world << " no powernet" //world.log << "propagating new network"
return 0 var/list/worklist = list()
powernet.nodes -= src var/list/found_machines = list()
powernet = null var/index = 1
//world << "powernet null" var/obj/P = null
return 1
/turf/proc/get_cable_node() worklist+=O //start propagating from the passed object
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() while(index<=worklist.len) //until we've exhausted all power objects
for(var/area/RA in src.related) P = worklist[index] //get the next power object found
var/obj/machinery/power/apc/FINDME = locate() in RA index++
if (FINDME)
return FINDME
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
//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
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
var/temp = net1
net1 = net2
net2 = temp
//merge net2 into net1
for(var/obj/structure/cable/Cable in net2.cables) //merge cables
net1.add_cable(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
return net1
//Determines how strong could be shock, deals damage to mob, uses power. //Determines how strong could be shock, deals damage to mob, uses power.
//M is a mob who touched wire/whatever //M is a mob who touched wire/whatever
@@ -271,17 +299,11 @@
//No animations will be performed by this proc. //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) /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 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)) if(istype(M,/mob/living/carbon/human))
var/mob/living/carbon/human/H = M var/mob/living/carbon/human/H = M
if(H.species.insulated) if(H.gloves)
return 0
else if(H.gloves)
var/obj/item/clothing/gloves/G = H.gloves var/obj/item/clothing/gloves/G = H.gloves
if(G.siemens_coefficient == 0) if(G.siemens_coefficient == 0) return 0 //to avoid spamming with insulated glvoes on
return 0 //to avoid spamming with insulated glvoes on
var/area/source_area var/area/source_area
if(istype(power_source,/area)) if(istype(power_source,/area))
@@ -327,11 +349,10 @@
var/drained_energy = drained_hp*20 var/drained_energy = drained_hp*20
if (source_area) if (source_area)
source_area.use_power(drained_energy) source_area.use_power(drained_energy/CELLRATE)
else if (istype(power_source,/datum/powernet)) else if (istype(power_source,/datum/powernet))
//var/drained_power = drained_energy/CELLRATE //convert from "joules" to "watts" <<< NO. THIS IS WRONG. CELLRATE DOES NOT CONVERT TO OR FROM JOULES. var/drained_power = drained_energy/CELLRATE //convert from "joules" to "watts"
PN.draw_power(drained_energy) PN.load+=drained_power
else if (istype(power_source, /obj/item/weapon/cell)) else if (istype(power_source, /obj/item/weapon/cell))
cell.use(drained_energy*CELLRATE) //convert to units of charge. cell.use(drained_energy)
return drained_energy return drained_energy

View File

@@ -1,29 +1,80 @@
/datum/powernet /datum/powernet
var/list/cables = list() // all cables & junctions var/list/cables = list() // all cables & junctions
var/list/nodes = list() // all APCs & sources 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/newload = 0
var/load = 0
var/newavail = 0
var/avail = 0
var/viewload = 0
var/number = 0
var/perapc = 0 // per-apc avilability var/perapc = 0 // per-apc avilability
var/perapc_excess = 0 var/perapc_excess = 0
var/netexcess = 0 var/netexcess = 0 // excess power on the powernet (typically avail-load)
/datum/powernet/proc/process() /datum/powernet/New()
load = newload powernets += src
newload = 0
avail = newavail /datum/powernet/Del()
newavail = 0 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
viewload = 0.8*viewload + 0.2*load //add a power machine to the current powernet
//Warning : this proc DON'T check if the machine exists
viewload = round(viewload) /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
//handles the power changes in the powernet
//called every ticks by the powernet controller
/datum/powernet/proc/reset()
var/numapc = 0 var/numapc = 0
if(nodes && nodes.len) // Added to fix a bad list bug -- TLE if(nodes && nodes.len) // Added to fix a bad list bug -- TLE
@@ -41,165 +92,24 @@
perapc_excess += min(netexcess/numapc, (avail - perapc) - perapc_excess) perapc_excess += min(netexcess/numapc, (avail - perapc) - perapc_excess)
else else
perapc_excess = 0 perapc_excess = 0
perapc = avail/numapc + perapc_excess perapc = avail/numapc + perapc_excess
if( netexcess > 100) // if there was excess power last cycle if(netexcess > 100 && nodes && nodes.len) // if there was excess power last cycle
if(nodes && nodes.len) for(var/obj/machinery/power/smes/S in nodes) // find the SMESes in the network
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
if(S.powernet == src)
S.restore() // and restore some of the power that was used
else
error("[S.name] (\ref[S]) had a [S.powernet ? "different (\ref[S.powernet])" : "null"] powernet to our powernet (\ref[src]).")
nodes.Remove(S)
//updates the viewed load (as seen on power computers)
viewload = 0.8*viewload + 0.2*load
viewload = round(viewload)
//reset the powernet
load = 0
//Returns the amount of available power avail = newavail
/datum/powernet/proc/surplus() newavail = 0
return max(avail - newload, 0)
//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)
//Attempts to draw power from a powernet. Returns the actual amount of power drawn
/datum/powernet/proc/draw_power(var/requested_amount)
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
/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"
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/get_electrocute_damage() /datum/powernet/proc/get_electrocute_damage()
switch(avail)/* switch(avail)
if (1300000 to INFINITY)
return min(rand(70,150),rand(70,150))
if (750000 to 1300000)
return min(rand(50,115),rand(50,115))
if (100000 to 750000-1)
return min(rand(35,101),rand(35,101))
if (75000 to 100000-1)
return min(rand(30,95),rand(30,95))
if (50000 to 75000-1)
return min(rand(25,80),rand(25,80))
if (25000 to 50000-1)
return min(rand(20,70),rand(20,70))
if (10000 to 25000-1)
return min(rand(20,65),rand(20,65))
if (1000 to 10000-1)
return min(rand(10,20),rand(10,20))*/
if (1000000 to INFINITY) if (1000000 to INFINITY)
return min(rand(50,160),rand(50,160)) return min(rand(50,160),rand(50,160))
if (200000 to 1000000) if (200000 to 1000000)
@@ -213,53 +123,23 @@
else else
return 0 return 0
/proc/powernet_nextlink(var/obj/O, var/datum/powernet/PN) ////////////////////////////////////////////////
var/list/P // Misc.
///////////////////////////////////////////////
while(1)
if( istype(O,/obj/structure/cable) )
var/obj/structure/cable/C = O
C.powernet = PN
P = C.get_connections()
else if(O.anchored && istype(O,/obj/machinery/power)) // return a knot cable (O-X) if one is present in the turf
var/obj/machinery/power/M = O // null if there's none
M.powernet = PN /turf/proc/get_cable_node()
P = M.get_connections() if(!istype(src, /turf/simulated/floor))
return null
for(var/obj/structure/cable/C in src)
if(C.d1 == 0)
return C
return null
else /area/proc/get_apc()
return for(var/area/RA in src.related)
var/obj/machinery/power/apc/FINDME = locate() in RA
if(P.len == 0) return if (FINDME)
return FINDME
O = P[1]
for(var/L = 2 to P.len)
powernet_nextlink(P[L], PN)
//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
//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
var/temp = net1
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
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
del(net2)
return net1

View File

@@ -8,7 +8,6 @@ var/global/list/rad_collectors = list()
icon_state = "ca" icon_state = "ca"
anchored = 0 anchored = 0
density = 1 density = 1
directwired = 1
req_access = list(access_engine_equip) req_access = list(access_engine_equip)
// use_power = 0 // use_power = 0
var/obj/item/weapon/tank/phoron/P = null var/obj/item/weapon/tank/phoron/P = null

View File

@@ -40,7 +40,6 @@
..() ..()
if(state == 2 && anchored) if(state == 2 && anchored)
connect_to_network() connect_to_network()
src.directwired = 1
/obj/machinery/power/emitter/Del() /obj/machinery/power/emitter/Del()
message_admins("Emitter deleted at ([x],[y],[z] - <A HREF='?_src_=holder;adminplayerobservecoodjump=1;X=[x];Y=[y];Z=[z]'>JMP</a>)",0,1) message_admins("Emitter deleted at ([x],[y],[z] - <A HREF='?_src_=holder;adminplayerobservecoodjump=1;X=[x];Y=[y];Z=[z]'>JMP</a>)",0,1)
@@ -106,7 +105,8 @@
return return
if(((src.last_shot + src.fire_delay) <= world.time) && (src.active == 1)) if(((src.last_shot + src.fire_delay) <= world.time) && (src.active == 1))
if(surplus() >= active_power_usage && add_load(active_power_usage) >= active_power_usage) //does the laser have enough power to shoot? var/actual_load = draw_power(active_power_usage)
if(actual_load >= active_power_usage) //does the laser have enough power to shoot?
if(!powered) if(!powered)
powered = 1 powered = 1
update_icon() update_icon()
@@ -125,13 +125,13 @@
else else
src.fire_delay = rand(min_burst_delay, max_burst_delay) src.fire_delay = rand(min_burst_delay, max_burst_delay)
src.shot_number = 0 src.shot_number = 0
//need to calculate the power per shot as the emitter doesn't fire continuously. //need to calculate the power per shot as the emitter doesn't fire continuously.
var/burst_time = (min_burst_delay + max_burst_delay)/2 + 2*(burst_shots-1) var/burst_time = (min_burst_delay + max_burst_delay)/2 + 2*(burst_shots-1)
var/power_per_shot = active_power_usage * (burst_time/10) / burst_shots var/power_per_shot = active_power_usage * (burst_time/10) / burst_shots
var/obj/item/projectile/beam/emitter/A = new /obj/item/projectile/beam/emitter( src.loc ) var/obj/item/projectile/beam/emitter/A = new /obj/item/projectile/beam/emitter( src.loc )
A.damage = round(power_per_shot/EMITTER_DAMAGE_POWER_TRANSFER) A.damage = round(power_per_shot/EMITTER_DAMAGE_POWER_TRANSFER)
playsound(src.loc, 'sound/weapons/emitter.ogg', 25, 1) playsound(src.loc, 'sound/weapons/emitter.ogg', 25, 1)
if(prob(35)) if(prob(35))
var/datum/effect/effect/system/spark_spread/s = new /datum/effect/effect/system/spark_spread var/datum/effect/effect/system/spark_spread/s = new /datum/effect/effect/system/spark_spread
@@ -198,7 +198,6 @@
state = 2 state = 2
user << "You weld the [src] to the floor." user << "You weld the [src] to the floor."
connect_to_network() connect_to_network()
src.directwired = 1
else else
user << "\red You need more welding fuel to complete this task." user << "\red You need more welding fuel to complete this task."
if(2) if(2)
@@ -212,7 +211,6 @@
state = 1 state = 1
user << "You cut the [src] free from the floor." user << "You cut the [src] free from the floor."
disconnect_from_network() disconnect_from_network()
src.directwired = 0
else else
user << "\red You need more welding fuel to complete this task." user << "\red You need more welding fuel to complete this task."
return return

View File

@@ -92,7 +92,7 @@
//TODO: Add a meter to tell players how much charge we are actually getting, and only set charging to 0 when we are unable to get any charge at all. //TODO: Add a meter to tell players how much charge we are actually getting, and only set charging to 0 when we are unable to get any charge at all.
if(chargemode) if(chargemode)
var/target_load = min((capacity-charge)/SMESRATE, chargelevel) // charge at set rate, limited to spare capacity var/target_load = min((capacity-charge)/SMESRATE, chargelevel) // charge at set rate, limited to spare capacity
var/actual_load = add_load(target_load) // add the load to the terminal side network var/actual_load = draw_power(target_load) // add the load to the terminal side network
charge += actual_load * SMESRATE // increase the charge charge += actual_load * SMESRATE // increase the charge
if (actual_load >= target_load) // did the powernet have enough power available for us? if (actual_load >= target_load) // did the powernet have enough power available for us?
@@ -174,7 +174,7 @@
return 1 return 1
/obj/machinery/power/smes/add_load(var/amount) /obj/machinery/power/smes/draw_power(var/amount)
if(terminal && terminal.powernet) if(terminal && terminal.powernet)
return terminal.powernet.draw_power(amount) return terminal.powernet.draw_power(amount)
return 0 return 0
@@ -385,11 +385,4 @@
charge = 5000000 charge = 5000000
..() ..()
/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
#undef SMESRATE #undef SMESRATE

View File

@@ -1,20 +1,8 @@
//This file was auto-corrected by findeclaration.exe on 25.5.2012 20:42:33
#define SOLAR_MAX_DIST 40 #define SOLAR_MAX_DIST 40
#define SOLARGENRATE 1500 #define SOLARGENRATE 1500
var/list/solars_list = list() var/list/solars_list = list()
// This will choose whether to get the solar list from the powernet or the powernet nodes,
// depending on the size of the nodes.
/obj/machinery/power/proc/get_solars_powernet()
if(!powernet)
return list()
if(solars_list.len < powernet.nodes)
return solars_list
else
return powernet.nodes
/obj/machinery/power/solar /obj/machinery/power/solar
name = "solar panel" name = "solar panel"
desc = "A solar electrical generator." desc = "A solar electrical generator."
@@ -22,7 +10,6 @@ var/list/solars_list = list()
icon_state = "sp_base" icon_state = "sp_base"
anchored = 1 anchored = 1
density = 1 density = 1
directwired = 1
use_power = 0 use_power = 0
idle_power_usage = 0 idle_power_usage = 0
active_power_usage = 0 active_power_usage = 0
@@ -30,26 +17,32 @@ var/list/solars_list = list()
var/health = 10 var/health = 10
var/obscured = 0 var/obscured = 0
var/sunfrac = 0 var/sunfrac = 0
var/adir = SOUTH var/adir = SOUTH // actual dir
var/ndir = SOUTH var/ndir = SOUTH // target dir
var/turn_angle = 0 var/turn_angle = 0
var/obj/machinery/power/solar_control/control = null var/obj/machinery/power/solar_control/control = null
/obj/machinery/power/solar/New(var/turf/loc, var/obj/item/solar_assembly/S, var/process = 1) /obj/machinery/power/solar/New(var/turf/loc, var/obj/item/solar_assembly/S)
..(loc) ..(loc)
Make(S) Make(S)
connect_to_network(process) connect_to_network()
/obj/machinery/power/solar/Del()
/obj/machinery/power/solar/disconnect_from_network() unset_control() //remove from control computer
..() ..()
solars_list.Remove(src)
/obj/machinery/power/solar/connect_to_network(var/process) //set the control of the panel to a given computer if closer than SOLAR_MAX_DIST
..() /obj/machinery/power/solar/proc/set_control(var/obj/machinery/power/solar_control/SC)
if(process) if(SC && (get_dist(src, SC) > SOLAR_MAX_DIST))
solars_list.Add(src) return 0
control = SC
return 1
//set the control of the panel to null and removes it from the control list of the previous control computer if needed
/obj/machinery/power/solar/proc/unset_control()
if(control)
control.connected_panels.Remove(src)
control = null
/obj/machinery/power/solar/proc/Make(var/obj/item/solar_assembly/S) /obj/machinery/power/solar/proc/Make(var/obj/item/solar_assembly/S)
if(!S) if(!S)
@@ -57,14 +50,17 @@ var/list/solars_list = list()
S.glass_type = /obj/item/stack/sheet/glass S.glass_type = /obj/item/stack/sheet/glass
S.anchored = 1 S.anchored = 1
S.loc = src S.loc = src
if(S.glass_type == /obj/item/stack/sheet/rglass) //if the panel is in reinforced glass
health *= 2 //this need to be placed here, because panels already on the map don't have an assembly linked to
update_icon() update_icon()
/obj/machinery/power/solar/attackby(obj/item/weapon/W, mob/user) /obj/machinery/power/solar/attackby(obj/item/weapon/W, mob/user)
if(iscrowbar(W)) if(istype(W, /obj/item/weapon/crowbar))
playsound(src.loc, 'sound/machines/click.ogg', 50, 1) playsound(src.loc, 'sound/machines/click.ogg', 50, 1)
user.visible_message("<span class='notice'>[user] begins to take the glass off the solar panel.</span>")
if(do_after(user, 50)) if(do_after(user, 50))
var/obj/item/solar_assembly/S = locate() in src var/obj/item/solar_assembly/S = locate() in src
if(S) if(S)
@@ -72,7 +68,7 @@ var/list/solars_list = list()
S.give_glass() S.give_glass()
playsound(src.loc, 'sound/items/Deconstruct.ogg', 50, 1) playsound(src.loc, 'sound/items/Deconstruct.ogg', 50, 1)
user.visible_message("<span class='notice'>[user] takes the glass off the solar panel.</span>") user.visible_message("<span class='notice'>[user] takes the glass off the solar panel.</span>")
del(src) del(src) // qdel
return return
else if (W) else if (W)
src.add_fingerprint(user) src.add_fingerprint(user)
@@ -94,7 +90,7 @@ var/list/solars_list = list()
else else
new /obj/item/weapon/shard(src.loc) new /obj/item/weapon/shard(src.loc)
new /obj/item/weapon/shard(src.loc) new /obj/item/weapon/shard(src.loc)
del(src) del(src) // qdel
return return
return return
@@ -109,65 +105,64 @@ var/list/solars_list = list()
src.dir = angle2dir(adir) src.dir = angle2dir(adir)
return return
//calculates the fraction of the sunlight that the panel recieves
/obj/machinery/power/solar/proc/update_solar_exposure() /obj/machinery/power/solar/proc/update_solar_exposure()
if(!sun) if(!sun)
return return
if(obscured) if(obscured)
sunfrac = 0 sunfrac = 0
return return
var/p_angle = abs((360+adir)%360 - (360+sun.angle)%360)
//find the smaller angle between the direction the panel is facing and the direction of the sun (the sign is not important here)
var/p_angle = min(abs(adir - sun.angle), 360 - abs(adir - sun.angle))
if(p_angle > 90) // if facing more than 90deg from sun, zero output if(p_angle > 90) // if facing more than 90deg from sun, zero output
sunfrac = 0 sunfrac = 0
return return
sunfrac = cos(p_angle) ** 2
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 ?
/obj/machinery/power/solar/process()//TODO: remove/add this from machines to save on processing as needed ~Carn PRIORITY /obj/machinery/power/solar/process()//TODO: remove/add this from machines to save on processing as needed ~Carn PRIORITY
if(stat & BROKEN) return if(stat & BROKEN)
if(!control) return return
if(!sun || !control) //if there's no sun or the panel is not linked to a solar control computer, no need to proceed
return
if(adir != ndir) if(powernet)
adir = (360+adir+dd_range(-10,10,ndir-adir))%360 if(powernet == control.powernet)//check if the panel is still connected to the computer
update_icon() if(obscured) //get no light from the sun, so don't generate power
update_solar_exposure() return
var/sgen = SOLARGENRATE * sunfrac
if(obscured) return add_avail(sgen)
var/sgen = SOLARGENRATE * sunfrac
add_avail(sgen)
if(powernet && control)
if(powernet.nodes[control])
control.gen += sgen control.gen += sgen
else //if we're no longer on the same powernet, remove from control computer
unset_control()
/obj/machinery/power/solar/proc/broken() /obj/machinery/power/solar/proc/broken()
stat |= BROKEN stat |= BROKEN
unset_control()
update_icon() update_icon()
return return
/obj/machinery/power/solar/meteorhit()
if(stat & !BROKEN)
broken()
else
del(src)
/obj/machinery/power/solar/ex_act(severity) /obj/machinery/power/solar/ex_act(severity)
switch(severity) switch(severity)
if(1.0) if(1.0)
del(src)
if(prob(15)) if(prob(15))
new /obj/item/weapon/shard( src.loc ) new /obj/item/weapon/shard( src.loc )
del(src) // qdel
return return
if(2.0) if(2.0)
if (prob(25)) if (prob(25))
new /obj/item/weapon/shard( src.loc ) new /obj/item/weapon/shard( src.loc )
del(src) del(src) // qdel
return return
if (prob(50)) if (prob(50))
broken() broken()
if(3.0) if(3.0)
if (prob(25)) if (prob(25))
broken() broken()
@@ -187,6 +182,29 @@ var/list/solars_list = list()
. = PROCESS_KILL . = PROCESS_KILL
return return
//trace towards sun to see if we're in shadow
/obj/machinery/power/solar/proc/occlusion()
var/ax = x // start at the solar panel
var/ay = y
var/turf/T = null
for(var/i = 1 to 20) // 20 steps is enough
ax += sun.dx // do step
ay += sun.dy
T = locate( round(ax,0.5),round(ay,0.5),z)
if(T.x == 1 || T.x==world.maxx || T.y==1 || T.y==world.maxy) // not obscured if we reach the edge
break
if(T.density) // if we hit a solid turf, panel is obscured
obscured = 1
return
obscured = 0 // if hit the edge or stepped 20 times, not obscured
update_solar_exposure()
// //
// Solar Assembly - For construction of solar arrays. // Solar Assembly - For construction of solar arrays.
@@ -218,13 +236,13 @@ var/list/solars_list = list()
/obj/item/solar_assembly/attackby(var/obj/item/weapon/W, var/mob/user) /obj/item/solar_assembly/attackby(var/obj/item/weapon/W, var/mob/user)
if(!anchored && isturf(loc)) if(!anchored && isturf(loc))
if(iswrench(W)) if(istype(W, /obj/item/weapon/wrench))
anchored = 1 anchored = 1
user.visible_message("<span class='notice'>[user] wrenches the solar assembly into place.</span>") user.visible_message("<span class='notice'>[user] wrenches the solar assembly into place.</span>")
playsound(src.loc, 'sound/items/Ratchet.ogg', 75, 1) playsound(src.loc, 'sound/items/Ratchet.ogg', 75, 1)
return 1 return 1
else else
if(iswrench(W)) if(istype(W, /obj/item/weapon/wrench))
anchored = 0 anchored = 0
user.visible_message("<span class='notice'>[user] unwrenches the solar assembly from it's place.</span>") user.visible_message("<span class='notice'>[user] unwrenches the solar assembly from it's place.</span>")
playsound(src.loc, 'sound/items/Ratchet.ogg', 75, 1) playsound(src.loc, 'sound/items/Ratchet.ogg', 75, 1)
@@ -241,18 +259,19 @@ var/list/solars_list = list()
else else
new /obj/machinery/power/solar(get_turf(src), src) new /obj/machinery/power/solar(get_turf(src), src)
else else
user << "<span class='warning'>You need two sheets of glass to put them on the solar assembly.</span>" user << "<span class='warning'>You need two sheets of glass to put them into a solar panel.</span>"
return
return 1 return 1
if(!tracker) if(!tracker)
if(istype(W, /obj/item/weapon/tracker_electronics)) if(istype(W, /obj/item/weapon/tracker_electronics))
tracker = 1 tracker = 1
user.drop_item() user.drop_item()
del(W) del(W) // qdel
user.visible_message("<span class='notice'>[user] inserts the electronics into the solar assembly.</span>") user.visible_message("<span class='notice'>[user] inserts the electronics into the solar assembly.</span>")
return 1 return 1
else else
if(iscrowbar(W)) if(istype(W, /obj/item/weapon/crowbar))
new /obj/item/weapon/tracker_electronics(src.loc) new /obj/item/weapon/tracker_electronics(src.loc)
tracker = 0 tracker = 0
user.visible_message("<span class='notice'>[user] takes out the electronics from the solar assembly.</span>") user.visible_message("<span class='notice'>[user] takes out the electronics from the solar assembly.</span>")
@@ -270,18 +289,18 @@ var/list/solars_list = list()
icon_state = "solar" icon_state = "solar"
anchored = 1 anchored = 1
density = 1 density = 1
directwired = 1
use_power = 1 use_power = 1
idle_power_usage = 5 idle_power_usage = 250
active_power_usage = 20
var/id = 0 var/id = 0
var/cdir = 0 var/cdir = 0
var/targetdir = 0 // target angle in manual tracking (since it updates every game minute)
var/gen = 0 var/gen = 0
var/lastgen = 0 var/lastgen = 0
var/track = 0 // 0=off 1=manual 2=automatic var/track = 0 // 0= off 1=timed 2=auto (tracker)
var/trackrate = 60 // Measured in tenths of degree per minute (i.e. defaults to 6.0 deg/min) var/trackrate = 600 // 300-900 seconds
var/trackdir = 1 // -1=CCW, 1=CW var/nexttime = 0 // time for a panel to rotate of 1<> in manual tracking
var/nexttime = 0 // Next clock time that manual tracking will move the array var/obj/machinery/power/tracker/connected_tracker = null
var/list/connected_panels = list()
/obj/machinery/power/solar_control/New() /obj/machinery/power/solar_control/New()
@@ -290,14 +309,55 @@ var/list/solars_list = list()
initialize() initialize()
connect_to_network() connect_to_network()
/obj/machinery/power/solar_control/Del()
for(var/obj/machinery/power/solar/M in connected_panels)
M.unset_control()
if(connected_tracker)
connected_tracker.unset_control()
..()
/obj/machinery/power/solar_control/disconnect_from_network() /obj/machinery/power/solar_control/disconnect_from_network()
..() ..()
solars_list.Remove(src) solars_list.Remove(src)
/obj/machinery/power/solar_control/connect_to_network() /obj/machinery/power/solar_control/connect_to_network()
..() var/to_return = ..()
if(powernet) //if connected and not already in solar_list...
solars_list |= src //... add it
return to_return
//search for unconnected panels and trackers in the computer powernet and connect them
/obj/machinery/power/solar_control/proc/search_for_connected()
if(powernet) if(powernet)
solars_list.Add(src) for(var/obj/machinery/power/M in powernet.nodes)
if(istype(M, /obj/machinery/power/solar))
var/obj/machinery/power/solar/S = M
if(!S.control) //i.e unconnected
S.set_control(src)
connected_panels |= S
else if(istype(M, /obj/machinery/power/tracker))
if(!connected_tracker) //if there's already a tracker connected to the computer don't add another
var/obj/machinery/power/tracker/T = M
if(!T.control) //i.e unconnected
connected_tracker = T
T.set_control(src)
//called by the sun controller, update the facing angle (either manually or via tracking) and rotates the panels accordingly
/obj/machinery/power/solar_control/proc/update()
if(stat & (NOPOWER | BROKEN))
return
switch(track)
if(1)
if(trackrate) //we're manual tracking. If we set a rotation speed...
cdir = targetdir //...the current direction is the targetted one (and rotates panels to it)
if(2) // auto-tracking
if(connected_tracker)
connected_tracker.set_angle(sun.angle)
set_panels(cdir)
updateDialog()
/obj/machinery/power/solar_control/initialize() /obj/machinery/power/solar_control/initialize()
..() ..()
@@ -315,22 +375,42 @@ var/list/solars_list = list()
return return
icon_state = "solar" icon_state = "solar"
overlays.Cut() overlays.Cut()
if(cdir > 0) if(cdir > -1)
overlays += image('icons/obj/computer.dmi', "solcon-o", FLY_LAYER, angle2dir(cdir)) overlays += image('icons/obj/computer.dmi', "solcon-o", FLY_LAYER, angle2dir(cdir))
return return
/obj/machinery/power/solar_control/attack_ai(mob/user)
add_fingerprint(user)
if(stat & (BROKEN | NOPOWER)) return
interact(user)
/obj/machinery/power/solar_control/attack_hand(mob/user) /obj/machinery/power/solar_control/attack_hand(mob/user)
add_fingerprint(user) if(!..())
if(stat & (BROKEN | NOPOWER)) return interact(user)
interact(user)
/obj/machinery/power/solar_control/interact(mob/user)
var/t = "<B><span class='highlight'>Generated power</span></B> : [round(lastgen)] W<BR>"
t += "<B><span class='highlight'>Orientation</span></B>: [rate_control(src,"cdir","[cdir]&deg",1,15)] ([angle2text(cdir)])<BR>"
t += "<B><span class='highlight'>Tracking:</B><div class='statusDisplay'>"
switch(track)
if(0)
t += "<span class='linkOn'>Off</span> <A href='?src=\ref[src];track=1'>Timed</A> <A href='?src=\ref[src];track=2'>Auto</A><BR>"
if(1)
t += "<A href='?src=\ref[src];track=0'>Off</A> <span class='linkOn'>Timed</span> <A href='?src=\ref[src];track=2'>Auto</A><BR>"
if(2)
t += "<A href='?src=\ref[src];track=0'>Off</A> <A href='?src=\ref[src];track=1'>Timed</A> <span class='linkOn'>Auto</span><BR>"
t += "Tracking Rate: [rate_control(src,"tdir","[trackrate] deg/h ([trackrate<0 ? "CCW" : "CW"])",1,30,180)]</div><BR>"
t += "<B><span class='highlight'>Connected devices:</span></B><div class='statusDisplay'>"
t += "<A href='?src=\ref[src];search_connected=1'>Search for devices</A><BR>"
t += "Solar panels : [connected_panels.len] connected<BR>"
t += "Solar tracker : [connected_tracker ? "<span class='good'>Found</span>" : "<span class='bad'>Not found</span>"]</div><BR>"
t += "<A href='?src=\ref[src];close=1'>Close</A>"
var/datum/browser/popup = new(user, "solar", name)
popup.set_content(t)
popup.open()
return
/obj/machinery/power/solar_control/attackby(I as obj, user as mob) /obj/machinery/power/solar_control/attackby(I as obj, user as mob)
if(istype(I, /obj/item/weapon/screwdriver)) if(istype(I, /obj/item/weapon/screwdriver))
@@ -347,7 +427,7 @@ var/list/solars_list = list()
A.state = 3 A.state = 3
A.icon_state = "3" A.icon_state = "3"
A.anchored = 1 A.anchored = 1
del(src) del(src) // qdel
else else
user << "\blue You disconnect the monitor." user << "\blue You disconnect the monitor."
var/obj/structure/computerframe/A = new /obj/structure/computerframe( src.loc ) var/obj/structure/computerframe/A = new /obj/structure/computerframe( src.loc )
@@ -358,12 +438,11 @@ var/list/solars_list = list()
A.state = 4 A.state = 4
A.icon_state = "4" A.icon_state = "4"
A.anchored = 1 A.anchored = 1
del(src) del(src) // qdel
else else
src.attack_hand(user) src.attack_hand(user)
return return
/obj/machinery/power/solar_control/process() /obj/machinery/power/solar_control/process()
lastgen = gen lastgen = gen
gen = 0 gen = 0
@@ -371,130 +450,73 @@ var/list/solars_list = list()
if(stat & (NOPOWER | BROKEN)) if(stat & (NOPOWER | BROKEN))
return return
//use_power(250) if(connected_tracker) //NOTE : handled here so that we don't add trackers to the processing list
if(track==1 && nexttime < world.time && trackdir*trackrate) if(connected_tracker.powernet != powernet)
// Increments nexttime using itself and not world.time to prevent drift connected_tracker.unset_control()
nexttime = nexttime + 6000/trackrate
// Nudges array 1 degree in desired direction
cdir = (cdir+trackdir+360)%360
set_panels(cdir)
update_icon()
src.updateDialog() 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<>...
targetdir = (targetdir + trackrate/abs(trackrate) + 360) % 360 //... do it
// called by solar tracker when sun position changes nexttime += 36000/abs(trackrate) //reset the counter for the next 1<>
/obj/machinery/power/solar_control/proc/tracker_update(var/angle)
if(track != 2 || stat & (NOPOWER | BROKEN))
return
cdir = angle
set_panels(cdir)
update_icon()
src.updateDialog()
/obj/machinery/power/solar_control/interact(mob/user)
if(stat & (BROKEN | NOPOWER)) return
if ( (get_dist(src, user) > 1 ))
if (!istype(user, /mob/living/silicon))
user.unset_machine()
user << browse(null, "window=solcon")
return
add_fingerprint(user)
user.set_machine(src)
var/t = "<TT><B>Solar Generator Control</B><HR><PRE>"
t += "<B>Generated power</B> : [round(lastgen)] W<BR>"
t += "Station Rotational Period: [60/abs(sun.rate)] minutes<BR>"
t += "Station Rotational Direction: [sun.rate<0 ? "CCW" : "CW"]<BR>"
t += "Star Orientation: [sun.angle]&deg ([angle2text(sun.angle)])<BR>"
t += "Array Orientation: [rate_control(src,"cdir","[cdir]&deg",1,10,60)] ([angle2text(cdir)])<BR>"
t += "<BR><HR><BR>"
t += "Tracking: "
switch(track)
if(0)
t += "<B>Off</B> <A href='?src=\ref[src];track=1'>Manual</A> <A href='?src=\ref[src];track=2'>Automatic</A><BR>"
if(1)
t += "<A href='?src=\ref[src];track=0'>Off</A> <B>Manual</B> <A href='?src=\ref[src];track=2'>Automatic</A><BR>"
if(2)
t += "<A href='?src=\ref[src];track=0'>Off</A> <A href='?src=\ref[src];track=1'>Manual</A> <B>Automatic</B><BR>"
t += "Manual Tracking Rate: [rate_control(src,"tdir","[trackrate/10]&deg/min ([trackdir<0 ? "CCW" : "CW"])",1,10)]<BR>"
t += "Manual Tracking Direction: "
switch(trackdir)
if(-1)
t += "<A href='?src=\ref[src];trackdir=1'>CW</A> <B>CCW</B><BR>"
if(1)
t += "<B>CW</B> <A href='?src=\ref[src];trackdir=-1'>CCW</A><BR>"
t += "<A href='?src=\ref[src];close=1'>Close</A></TT>"
user << browse(t, "window=solcon")
onclose(user, "solcon")
return
updateDialog()
/obj/machinery/power/solar_control/Topic(href, href_list) /obj/machinery/power/solar_control/Topic(href, href_list)
if(..()) if(..())
usr << browse(null, "window=solcon") usr << browse(null, "window=solcon")
usr.unset_machine() usr.unset_machine()
return return 0
if(href_list["close"] ) if(href_list["close"] )
usr << browse(null, "window=solcon") usr << browse(null, "window=solcon")
usr.unset_machine() usr.unset_machine()
return return 0
if(href_list["dir"])
cdir = text2num(href_list["dir"])
set_panels(cdir)
update_icon()
if(href_list["rate control"]) if(href_list["rate control"])
if(href_list["cdir"]) if(href_list["cdir"])
src.cdir = dd_range(0,359,(360+src.cdir+text2num(href_list["cdir"]))%360) src.cdir = dd_range(0,359,(360+src.cdir+text2num(href_list["cdir"]))%360)
src.targetdir = src.cdir
if(track == 2) //manual update, so losing auto-tracking
track = 0
spawn(1) spawn(1)
set_panels(cdir) set_panels(cdir)
update_icon()
if(href_list["tdir"]) if(href_list["tdir"])
src.trackrate = dd_range(0,360,src.trackrate+text2num(href_list["tdir"])) src.trackrate = dd_range(-7200,7200,src.trackrate+text2num(href_list["tdir"]))
if(src.trackrate) nexttime = world.time + 6000/trackrate if(src.trackrate) nexttime = world.time + 36000/abs(trackrate)
if(href_list["track"]) if(href_list["track"])
if(src.trackrate) nexttime = world.time + 6000/trackrate
track = text2num(href_list["track"]) track = text2num(href_list["track"])
if(powernet && (track == 2)) if(track == 2)
if(!solars_list.Find(src,1,0)) if(connected_tracker)
solars_list.Add(src) connected_tracker.set_angle(sun.angle)
for(var/obj/machinery/power/tracker/T in get_solars_powernet()) set_panels(cdir)
if(powernet.nodes[T]) else if (track == 1) //begin manual tracking
cdir = T.sun_angle src.targetdir = src.cdir
break if(src.trackrate) nexttime = world.time + 36000/abs(trackrate)
set_panels(targetdir)
if(href_list["trackdir"]) if(href_list["search_connected"])
trackdir = text2num(href_list["trackdir"]) src.search_for_connected()
if(connected_tracker && track == 2)
set_panels(cdir) connected_tracker.set_angle(sun.angle)
update_icon() src.set_panels(cdir)
src.updateUsrDialog()
return
interact(usr)
return 1
//rotates the panel to the passed angle
/obj/machinery/power/solar_control/proc/set_panels(var/cdir) /obj/machinery/power/solar_control/proc/set_panels(var/cdir)
if(!powernet) return
for(var/obj/machinery/power/solar/S in get_solars_powernet()) for(var/obj/machinery/power/solar/S in connected_panels)
if(powernet.nodes[S]) S.adir = cdir //instantly rotates the panel
if(get_dist(S, src) < SOLAR_MAX_DIST) S.occlusion()//and
if(!S.control) S.update_icon() //update it
S.control = src
S.ndir = cdir update_icon()
/obj/machinery/power/solar_control/power_change() /obj/machinery/power/solar_control/power_change()
..() ..()
if(!(stat & NOPOWER)) update_icon()
update_icon()
else
spawn(rand(0, 15))
update_icon()
/obj/machinery/power/solar_control/proc/broken() /obj/machinery/power/solar_control/proc/broken()
@@ -502,16 +524,11 @@ var/list/solars_list = list()
update_icon() update_icon()
/obj/machinery/power/solar_control/meteorhit()
broken()
return
/obj/machinery/power/solar_control/ex_act(severity) /obj/machinery/power/solar_control/ex_act(severity)
switch(severity) switch(severity)
if(1.0) if(1.0)
//SN src = null //SN src = null
del(src) del(src) // qdel
return return
if(2.0) if(2.0)
if (prob(50)) if (prob(50))
@@ -535,3 +552,9 @@ var/list/solars_list = list()
/obj/item/weapon/paper/solar /obj/item/weapon/paper/solar
name = "paper- 'Going green! Setup your own solar array instructions.'" name = "paper- 'Going green! Setup your own solar array instructions.'"
info = "<h1>Welcome</h1><p>At greencorps we love the environment, and space. With this package you are able to help mother nature and produce energy without any usage of fossil fuel or phoron! Singularity energy is dangerous while solar energy is safe, which is why it's better. Now here is how you setup your own solar array.</p><p>You can make a solar panel by wrenching the solar assembly onto a cable node. Adding a glass panel, reinforced or regular glass will do, will finish the construction of your solar panel. It is that easy!</p><p>Now after setting up 19 more of these solar panels you will want to create a solar tracker to keep track of our mother nature's gift, the sun. These are the same steps as before except you insert the tracker equipment circuit into the assembly before performing the final step of adding the glass. You now have a tracker! Now the last step is to add a computer to calculate the sun's movements and to send commands to the solar panels to change direction with the sun. Setting up the solar computer is the same as setting up any computer, so you should have no trouble in doing that. You do need to put a wire node under the computer, and the wire needs to be connected to the tracker.</p><p>Congratulations, you should have a working solar array. If you are having trouble, here are some tips. Make sure all solar equipment are on a cable node, even the computer. You can always deconstruct your creations if you make a mistake.</p><p>That's all to it, be safe, be green!</p>" info = "<h1>Welcome</h1><p>At greencorps we love the environment, and space. With this package you are able to help mother nature and produce energy without any usage of fossil fuel or phoron! Singularity energy is dangerous while solar energy is safe, which is why it's better. Now here is how you setup your own solar array.</p><p>You can make a solar panel by wrenching the solar assembly onto a cable node. Adding a glass panel, reinforced or regular glass will do, will finish the construction of your solar panel. It is that easy!</p><p>Now after setting up 19 more of these solar panels you will want to create a solar tracker to keep track of our mother nature's gift, the sun. These are the same steps as before except you insert the tracker equipment circuit into the assembly before performing the final step of adding the glass. You now have a tracker! Now the last step is to add a computer to calculate the sun's movements and to send commands to the solar panels to change direction with the sun. Setting up the solar computer is the same as setting up any computer, so you should have no trouble in doing that. You do need to put a wire node under the computer, and the wire needs to be connected to the tracker.</p><p>Congratulations, you should have a working solar array. If you are having trouble, here are some tips. Make sure all solar equipment are on a cable node, even the computer. You can always deconstruct your creations if you make a mistake.</p><p>That's all to it, be safe, be green!</p>"
/proc/rate_control(var/S, var/V, var/C, var/Min=1, var/Max=5, var/Limit=null) //How not to name vars
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

View File

@@ -11,7 +11,6 @@
layer = TURF_LAYER layer = TURF_LAYER
var/obj/machinery/power/master = null var/obj/machinery/power/master = null
anchored = 1 anchored = 1
directwired = 0 // must have a cable on same turf connecting to terminal
layer = 2.6 // a bit above wires layer = 2.6 // a bit above wires
@@ -21,6 +20,10 @@
if(level==1) hide(T.intact) if(level==1) hide(T.intact)
return return
/obj/machinery/power/terminal/Del()
if(master)
master.disconnect_terminal()
return ..()
/obj/machinery/power/terminal/hide(var/i) /obj/machinery/power/terminal/hide(var/i)
if(i) if(i)

View File

@@ -10,55 +10,58 @@
icon_state = "tracker" icon_state = "tracker"
anchored = 1 anchored = 1
density = 1 density = 1
directwired = 1 use_power = 0
use_power = 0 // doesn't use APC power
var/power_usage = 500 //W
var/id = 0
var/sun_angle = 0 // sun angle as set by sun datum 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) /obj/machinery/power/tracker/New(var/turf/loc, var/obj/item/solar_assembly/S)
..(loc) ..(loc)
Make(S)
connect_to_network()
/obj/machinery/power/tracker/Del()
unset_control() //remove from control computer
..()
//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))
return 0
control = SC
return 1
//set the control of the tracker to null and removes it from the previous control computer if needed
/obj/machinery/power/tracker/proc/unset_control()
if(control)
control.connected_tracker = null
control = null
/obj/machinery/power/tracker/proc/Make(var/obj/item/solar_assembly/S)
if(!S) if(!S)
S = new /obj/item/solar_assembly(src) S = new /obj/item/solar_assembly(src)
S.glass_type = /obj/item/stack/sheet/glass S.glass_type = /obj/item/stack/sheet/glass
S.tracker = 1 S.tracker = 1
S.anchored = 1 S.anchored = 1
S.loc = src S.loc = src
connect_to_network() update_icon()
/obj/machinery/power/tracker/disconnect_from_network() //updates the tracker icon and the facing angle for the control computer
..()
solars_list.Remove(src)
/obj/machinery/power/tracker/connect_to_network()
..()
solars_list.Add(src)
// called by datum/sun/calc_position() as sun's angle changes
/obj/machinery/power/tracker/proc/set_angle(var/angle) /obj/machinery/power/tracker/proc/set_angle(var/angle)
sun_angle = angle sun_angle = angle
//set icon dir to show sun illumination //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 dir = turn(NORTH, -angle - 22.5) // 22.5 deg bias ensures, e.g. 67.5-112.5 is EAST
// check we can draw power if(powernet && (powernet == control.powernet)) //update if we're still in the same powernet
if(stat & NOPOWER) control.cdir = angle
return
// find all solar controls and update them
// currently, just update all controllers in world
// ***TODO: better communication system using network
if(powernet)
for(var/obj/machinery/power/solar_control/C in get_solars_powernet())
if(powernet.nodes[C])
if(get_dist(C, src) < SOLAR_MAX_DIST)
C.tracker_update(angle)
/obj/machinery/power/tracker/attackby(var/obj/item/weapon/W, var/mob/user) /obj/machinery/power/tracker/attackby(var/obj/item/weapon/W, var/mob/user)
if(iscrowbar(W)) if(istype(W, /obj/item/weapon/crowbar))
playsound(src.loc, 'sound/machines/click.ogg', 50, 1) playsound(src.loc, 'sound/machines/click.ogg', 50, 1)
user.visible_message("<span class='notice'>[user] begins to take the glass off the solar tracker.</span>")
if(do_after(user, 50)) if(do_after(user, 50))
var/obj/item/solar_assembly/S = locate() in src var/obj/item/solar_assembly/S = locate() in src
if(S) if(S)
@@ -66,20 +69,10 @@
S.give_glass() S.give_glass()
playsound(src.loc, 'sound/items/Deconstruct.ogg', 50, 1) playsound(src.loc, 'sound/items/Deconstruct.ogg', 50, 1)
user.visible_message("<span class='notice'>[user] takes the glass off the tracker.</span>") user.visible_message("<span class='notice'>[user] takes the glass off the tracker.</span>")
del(src) del(src) // qdel
return return
..() ..()
// timed process
// make sure we can draw power from the powernet
/obj/machinery/power/tracker/process()
if(surplus() >= power_usage && add_load(power_usage) >= power_usage)
stat &= ~NOPOWER
else
stat |= NOPOWER
// Tracker Electronic // Tracker Electronic
/obj/item/weapon/tracker_electronics /obj/item/weapon/tracker_electronics
@@ -87,4 +80,4 @@
name = "tracker electronics" name = "tracker electronics"
icon = 'icons/obj/doors/door_assembly.dmi' icon = 'icons/obj/doors/door_assembly.dmi'
icon_state = "door_electronics" icon_state = "door_electronics"
w_class = 2.0 w_class = 2.0

View File

@@ -22,7 +22,6 @@
anchored = 1 anchored = 1
density = 1 density = 1
var/obj/machinery/compressor/compressor var/obj/machinery/compressor/compressor
directwired = 1
var/turf/simulated/outturf var/turf/simulated/outturf
var/lastgen var/lastgen
@@ -30,7 +29,7 @@
name = "Gas turbine control computer" name = "Gas turbine control computer"
desc = "A computer to remotely control a gas turbine" desc = "A computer to remotely control a gas turbine"
icon = 'icons/obj/computer.dmi' icon = 'icons/obj/computer.dmi'
icon_state = "airtunnel0e" icon_state = "turbinecomp"
circuit = /obj/item/weapon/circuitboard/turbine_control circuit = /obj/item/weapon/circuitboard/turbine_control
anchored = 1 anchored = 1
density = 1 density = 1

View File

@@ -70,12 +70,12 @@
var/shieldload = between(500, max_stored_power - storedpower, power_draw) //what we try to draw var/shieldload = between(500, max_stored_power - storedpower, power_draw) //what we try to draw
shieldload = PN.draw_power(shieldload) //what we actually get shieldload = PN.draw_power(shieldload) //what we actually get
storedpower += shieldload storedpower += shieldload
//If we're still in the red, then there must not be enough available power to cover our load. //If we're still in the red, then there must not be enough available power to cover our load.
if(storedpower <= 0) if(storedpower <= 0)
power = 0 power = 0
return 0 return 0
power = 1 // IVE GOT THE POWER! power = 1 // IVE GOT THE POWER!
return 1 return 1

View File

@@ -107,14 +107,14 @@
/obj/machinery/shield_capacitor/process() /obj/machinery/shield_capacitor/process()
if (!anchored) if (!anchored)
active = 0 active = 0
//see if we can connect to a power net. //see if we can connect to a power net.
var/datum/powernet/PN var/datum/powernet/PN
var/turf/T = src.loc var/turf/T = src.loc
var/obj/structure/cable/C = T.get_cable_node() var/obj/structure/cable/C = T.get_cable_node()
if (C) if (C)
PN = C.powernet PN = C.powernet
if (PN) if (PN)
var/power_draw = between(0, max_charge - stored_charge, charge_rate) //what we are trying to draw var/power_draw = between(0, max_charge - stored_charge, charge_rate) //what we are trying to draw
power_draw = PN.draw_power(power_draw) //what we actually get power_draw = PN.draw_power(power_draw) //what we actually get
@@ -138,7 +138,7 @@
active = !active active = !active
if( href_list["charge_rate"] ) if( href_list["charge_rate"] )
charge_rate = between(10000, charge_rate + text2num(href_list["charge_rate"]), max_charge_rate) charge_rate = between(10000, charge_rate + text2num(href_list["charge_rate"]), max_charge_rate)
updateDialog() updateDialog()
/obj/machinery/shield_capacitor/power_change() /obj/machinery/shield_capacitor/power_change()

Binary file not shown.

Before

Width:  |  Height:  |  Size: 72 KiB

After

Width:  |  Height:  |  Size: 72 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 24 KiB

After

Width:  |  Height:  |  Size: 24 KiB

File diff suppressed because it is too large Load Diff

View File

@@ -4,7 +4,7 @@ Used In File(s): \code\game\machinery\computer\crew.dm
--> -->
{{for data.crewmembers}} {{for data.crewmembers}}
{{if value.sensor_type == 3}} {{if value.sensor_type == 3}}
<div class="mapIcon mapIcon16 rank-{{:value.rank.ckey()}} {{:value.dead ? 'dead' : 'alive'}}" style="left: {{:(value.x)}}px; bottom: {{:(value.y)}}px;" unselectable="on"> <div class="mapIcon mapIcon16 rank-{{:value.rank.ckey()}} {{:value.dead ? 'dead' : 'alive'}}" style="left: {{:(value.x)}}px; bottom: {{:(value.y - 1)}}px;" unselectable="on">
<div class="tooltip hidden"> <div class="tooltip hidden">
{{:value.name}} ({{:value.dead ? "<span class='bad'>Deceased</span>" : "<span class='good'>Living</span>"}}) (<span class="oxyloss">{{:value.oxy}}</span>/<span class="toxin">{{:value.tox}}</span>/<span class="burn">{{:value.fire}}</span>/<span class="brute">{{:value.brute}}</span>) ({{:value.area}}: {{:value.x}}, {{:value.y}}) {{:value.name}} ({{:value.dead ? "<span class='bad'>Deceased</span>" : "<span class='good'>Living</span>"}}) (<span class="oxyloss">{{:value.oxy}}</span>/<span class="toxin">{{:value.tox}}</span>/<span class="burn">{{:value.fire}}</span>/<span class="brute">{{:value.brute}}</span>) ({{:value.area}}: {{:value.x}}, {{:value.y}})
</div> </div>