-
-
Notifications
You must be signed in to change notification settings - Fork 452
/
smes.dm
452 lines (378 loc) · 13.7 KB
/
smes.dm
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
// the SMES
// stores power
//Cache defines
#define SMES_OUTPUTTING 7
#define SMES_NOT_OUTPUTTING 8
#define SMES_INPUTTING 9
#define SMES_INPUT_ATTEMPT 10
/obj/machinery/power/smes
name = "power storage unit"
desc = "A high-capacity superconducting magnetic energy storage (SMES) unit."
icon_state = "smes"
density = TRUE
use_power = NO_POWER_USE
circuit = /obj/item/circuitboard/machine/smes
/// Maximum charge of the SMES
var/capacity = 5e8
/// Current charge of the SMES
var/charge = 0
/// TRUE = attempting to charge, FALSE = not attempting to charge
var/input_attempt = TRUE
/// TRUE = actually inputting, FALSE = not inputting
var/inputting = TRUE
/// Desired Power Input Level
var/input_level = 50000
/// Maximum Power Input
var/input_level_max = 200000
/// Last power input
var/input_available = 0
/// TRUE = attempting to output, FALSE = not attempting to output
var/output_attempt = TRUE
/// TRUE = actually outputting, FALSE = not outputting
var/outputting = TRUE
/// Desired Power Output Level
var/output_level = 50000
/// Maximum Power Output
var/output_level_max = 200000
/// Last power output
var/output_used = 0 // amount of power actually outputted. may be less than output_level if the powernet returns excess power
var/obj/machinery/power/terminal/terminal = null
/obj/machinery/power/smes/examine(user)
. = ..()
if(!terminal)
. += span_warning("This SMES has no power terminal!")
/obj/machinery/power/smes/Initialize(mapload)
. = ..()
dir_loop:
for(var/d in GLOB.cardinals)
var/turf/T = get_step(src, d)
for(var/obj/machinery/power/terminal/term in T)
if(term && term.dir == turn(d, 180))
terminal = term
break dir_loop
if(!terminal)
atom_break()
return
terminal.master = src
update_appearance(UPDATE_ICON)
/obj/machinery/power/smes/RefreshParts()
var/IO = 0
var/MC = 0
var/C
for(var/obj/item/stock_parts/capacitor/CP in component_parts)
IO += CP.rating
input_level_max = initial(input_level_max) * IO
output_level_max = initial(output_level_max) * IO
for(var/obj/item/stock_parts/cell/PC in component_parts)
MC += PC.maxcharge
C += PC.charge
capacity = MC / (15000) * 2e7
if(!initial(charge) && !charge)
charge = C / 15000 * 2e7
/obj/machinery/power/smes/attackby(obj/item/I, mob/user, params)
//opening using screwdriver
if(default_deconstruction_screwdriver(user, "[initial(icon_state)]-o", initial(icon_state), I))
update_appearance(UPDATE_ICON)
return
//changing direction using wrench
if(default_change_direction_wrench(user, I))
terminal = null
var/turf/T = get_step(src, dir)
for(var/obj/machinery/power/terminal/term in T)
if(term && term.dir == turn(dir, 180))
terminal = term
terminal.master = src
to_chat(user, span_notice("Terminal found."))
break
if(!terminal)
to_chat(user, span_alert("No power terminal found."))
return
stat &= ~BROKEN
update_appearance(UPDATE_ICON)
return
//building and linking a terminal
if(istype(I, /obj/item/stack/cable_coil))
var/dir = get_dir(user,src)
if(dir & (dir-1))//we don't want diagonal click
return
if(terminal) //is there already a terminal ?
to_chat(user, span_warning("This SMES already has a power terminal!"))
return
if(!panel_open) //is the panel open ?
to_chat(user, span_warning("You must open the maintenance panel first!"))
return
var/turf/T = get_turf(user)
if (T.underfloor_accessibility < UNDERFLOOR_INTERACTABLE) //can we get to the underfloor?
to_chat(user, span_warning("You must first remove the floor plating!"))
return
var/obj/item/stack/cable_coil/C = I
if(C.get_amount() < 10)
to_chat(user, span_warning("You need more wires!"))
return
to_chat(user, span_notice("You start building the power terminal..."))
playsound(src.loc, 'sound/items/deconstruct.ogg', 50, 1)
if(do_after(user, 2 SECONDS, src))
if(C.get_amount() < 10 || !C)
return
var/obj/structure/cable/N = T.get_cable_node() //get the connecting node cable, if there's one
if (prob(50) && electrocute_mob(usr, N, N, 1, TRUE)) //animate the electrocution if uncautious and unlucky
do_sparks(5, TRUE, src)
return
if(!terminal)
C.use(10)
user.visible_message(\
"[user.name] has built a power terminal.",\
span_notice("You build the power terminal."))
//build the terminal and link it to the network
make_terminal(T)
terminal.connect_to_network()
connect_to_network()
return
//crowbarring it !
var/turf/T = get_turf(src)
if(default_deconstruction_crowbar(I))
message_admins("[src] has been deconstructed by [ADMIN_LOOKUPFLW(user)] in [ADMIN_VERBOSEJMP(T)]")
log_game("[src] has been deconstructed by [key_name(user)] at [AREACOORD(src)]")
investigate_log("SMES deconstructed by [key_name(user)] at [AREACOORD(src)]", INVESTIGATE_SINGULO)
investigate_log("SMES deconstructed by [key_name(user)] at [AREACOORD(src)]", INVESTIGATE_SUPERMATTER) // yogs - so supermatter investigate is useful
return
else if(panel_open && I.tool_behaviour == TOOL_CROWBAR)
return
return ..()
/obj/machinery/power/smes/wirecutter_act(mob/living/user, obj/item/I)
//disassembling the terminal
if(terminal && panel_open)
terminal.dismantle(user, I)
return TRUE
/obj/machinery/power/smes/default_deconstruction_crowbar(obj/item/crowbar/C)
if(istype(C) && terminal)
to_chat(usr, span_warning("You must first remove the power terminal!"))
return FALSE
return ..()
/obj/machinery/power/smes/on_deconstruction()
for(var/obj/item/stock_parts/cell/cell in component_parts)
cell.charge = (charge / capacity) * cell.maxcharge
/obj/machinery/power/smes/Destroy()
if(SSticker.IsRoundInProgress())
var/turf/T = get_turf(src)
message_admins("SMES deleted at [ADMIN_VERBOSEJMP(T)]")
log_game("SMES deleted at [AREACOORD(T)]")
investigate_log("<font color='red'>deleted</font> at [AREACOORD(T)]", INVESTIGATE_SINGULO)
investigate_log("<font color='red'>deleted</font> at [AREACOORD(T)]", INVESTIGATE_SUPERMATTER) // yogs - so supermatter investigate is useful
if(terminal)
disconnect_terminal()
return ..()
// create a terminal object pointing towards the SMES
// wires will attach to this
/obj/machinery/power/smes/proc/make_terminal(turf/T)
terminal = new/obj/machinery/power/terminal(T)
terminal.setDir(get_dir(T,src))
terminal.master = src
stat &= ~BROKEN
/obj/machinery/power/smes/disconnect_terminal()
if(terminal)
terminal.master = null
terminal = null
atom_break()
/obj/machinery/power/smes/update_overlays()
. = ..()
if(stat & BROKEN)
return
if(panel_open)
return
if(outputting)
. += "smes-out1"
else
. += "smes-out0"
if(inputting)
. += "smes-inp1"
else if(input_attempt)
. += "smes-inp0"
var/clevel = chargedisplay()
if(clevel > 0)
. += "smes-og[clevel]"
/obj/machinery/power/smes/proc/chargedisplay()
return clamp(round(6.5*charge/capacity),0,6)
/obj/machinery/power/smes/process()
if(stat & BROKEN)
return
//store machine state to see if we need to update the icon overlays
var/last_disp = chargedisplay()
var/last_chrg = inputting
var/last_onln = outputting
//inputting
if(terminal && input_attempt)
input_available = terminal.surplus()
if(inputting)
if(input_available > 0) // if there's power available, try to charge
var/load = min(min((capacity-charge), input_level), input_available) // charge at set rate, limited to spare capacity
charge += load // increase the charge
terminal.add_load(load) // add the load to the terminal side network
else // if not enough capcity
inputting = FALSE // stop inputting
else
if(input_attempt && input_available > 0)
inputting = TRUE
else
inputting = FALSE
//outputting
if(output_attempt)
if(outputting)
output_used = min( charge, output_level) //limit output to that stored
if (add_avail(output_used)) // add output to powernet if it exists (smes side)
charge -= output_used // reduce the storage (may be recovered in /restore() if excessive)
else
outputting = FALSE
if(output_used < 0.0001) // either from no charge or set to 0
outputting = FALSE
investigate_log("SMES lost power and turned <font color='red'>off</font>", INVESTIGATE_SINGULO)
investigate_log("SMES lost power and turned <font color='red'>off</font>", INVESTIGATE_SUPERMATTER) // yogs - so supermatter investigate is useful
else if(output_attempt && charge > output_level && output_level > 0)
outputting = TRUE
else
output_used = 0
else
outputting = FALSE
// only update icon if state changed
if(last_disp != chargedisplay() || last_chrg != inputting || last_onln != outputting)
update_appearance(UPDATE_ICON)
// called after all power processes are finished
// restores charge level to smes if there was excess this ptick
/obj/machinery/power/smes/proc/restore()
if(stat & BROKEN)
return
if(!outputting)
output_used = 0
return
var/excess = powernet.netexcess // this was how much wasn't used on the network last ptick, minus any removed by other SMESes
excess = min(output_used, excess) // clamp it to how much was actually output by this SMES last ptick
excess = min((capacity-charge), excess) // for safety, also limit recharge by space capacity of SMES (shouldn't happen)
// now recharge this amount
var/clev = chargedisplay()
charge += excess // restore unused power
powernet.netexcess -= excess // remove the excess from the powernet, so later SMESes don't try to use it
output_used -= excess
if(clev != chargedisplay() ) //if needed updates the icons overlay
update_appearance(UPDATE_ICON)
return
/obj/machinery/power/smes/ui_interact(mob/user, datum/tgui/ui)
ui = SStgui.try_update_ui(user, src, ui)
if(!ui)
ui = new(user, src, "Smes", name)
ui.open()
/obj/machinery/power/smes/ui_data()
var/list/data = list(
"capacity" = capacity,
"capacityPercent" = round(100*charge/capacity, 0.1),
"charge" = charge,
"inputAttempt" = input_attempt,
"inputting" = inputting,
"inputLevel" = input_level,
"inputLevel_text" = DisplayPower(input_level),
"inputLevelMax" = input_level_max,
"inputAvailable" = input_available,
"outputAttempt" = output_attempt,
"outputting" = outputting,
"outputLevel" = output_level,
"outputLevel_text" = DisplayPower(output_level),
"outputLevelMax" = output_level_max,
"outputUsed" = output_used,
)
return data
/obj/machinery/power/smes/ui_act(action, params)
if(..())
return
switch(action)
if("tryinput")
input_attempt = !input_attempt
log_smes(usr)
update_appearance(UPDATE_ICON)
. = TRUE
if("tryoutput")
output_attempt = !output_attempt
log_smes(usr)
update_appearance(UPDATE_ICON)
. = TRUE
if("input")
var/target = params["target"]
var/adjust = text2num(params["adjust"])
if(target == "input")
target = input("New input target (0-[input_level_max]):", name, input_level) as num|null
if(!isnull(target) && !..())
. = TRUE
else if(target == "min")
target = 0
. = TRUE
else if(target == "max")
target = input_level_max
. = TRUE
else if(adjust)
target = input_level + adjust
. = TRUE
else if(text2num(target) != null)
target = text2num(target)
. = TRUE
if(.)
input_level = clamp(target, 0, input_level_max)
log_smes(usr)
if("output")
var/target = params["target"]
var/adjust = text2num(params["adjust"])
if(target == "input")
target = input("New output target (0-[output_level_max]):", name, output_level) as num|null
if(!isnull(target) && !..())
. = TRUE
else if(target == "min")
target = 0
. = TRUE
else if(target == "max")
target = output_level_max
. = TRUE
else if(adjust)
target = output_level + adjust
. = TRUE
else if(text2num(target) != null)
target = text2num(target)
. = TRUE
if(.)
output_level = clamp(target, 0, output_level_max)
log_smes(usr)
/obj/machinery/power/smes/proc/log_smes(mob/user)
investigate_log("input/output; [input_level>output_level?"<font color='green'>":"<font color='red'>"][input_level]/[output_level]</font> | Charge: [charge] | Output-mode: [output_attempt?"<font color='green'>on</font>":"<font color='red'>off</font>"] | Input-mode: [input_attempt?"<font color='green'>auto</font>":"<font color='red'>off</font>"] by [user ? key_name(user) : "outside forces"]", INVESTIGATE_SINGULO)
investigate_log("input/output; [input_level>output_level?"<font color='green'>":"<font color='red'>"][input_level]/[output_level]</font> | Charge: [charge] | Output-mode: [output_attempt?"<font color='green'>on</font>":"<font color='red'>off</font>"] | Input-mode: [input_attempt?"<font color='green'>auto</font>":"<font color='red'>off</font>"] by [user ? key_name(user) : "outside forces"]", INVESTIGATE_SUPERMATTER) // yogs - so supermatter investigate is useful
/obj/machinery/power/smes/emp_act(severity)
. = ..()
if(. & EMP_PROTECT_SELF)
return
input_attempt = rand(0,1)
inputting = input_attempt
output_attempt = rand(0,1)
outputting = output_attempt
output_level = rand(0, output_level_max)
input_level = rand(0, input_level_max)
charge = max(charge - (1e5 * severity), 0)
update_appearance(UPDATE_ICON)
log_smes()
/obj/machinery/power/smes/engineering
charge = 5e7 // Engineering starts with some charge for singulo
/obj/machinery/power/smes/fullycharged
charge = 5e8 // A fully charged SMES
/obj/machinery/power/smes/empty
charge = 0
/obj/machinery/power/smes/magical
name = "magical power storage unit"
desc = "A high-capacity superconducting magical energy storage (SMES) unit. Magically produces power."
/obj/machinery/power/smes/magical/process()
capacity = INFINITY
charge = INFINITY
..()
/obj/machinery/power/smes/CtrlClick(mob/user)
if(!user.canUseTopic(src, !issilicon(user)))
return
output_attempt = !output_attempt
log_smes(user)
update_appearance(UPDATE_ICON)
#undef SMES_OUTPUTTING
#undef SMES_NOT_OUTPUTTING
#undef SMES_INPUTTING
#undef SMES_INPUT_ATTEMPT