/
apc_tool_act.dm
492 lines (441 loc) · 16.9 KB
/
apc_tool_act.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
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
//attack with an item - open/close cover, insert cell, or (un)lock interface
/obj/machinery/power/apc/item_interaction(mob/living/user, obj/item/tool, list/modifiers)
. = NONE
if(HAS_TRAIT(tool, TRAIT_APC_SHOCKING))
. = fork_outlet_act(user, tool)
if(.)
return .
if(tool.GetID())
togglelock(user)
return ITEM_INTERACT_SUCCESS
if(istype(tool, /obj/item/stock_parts/cell))
. = cell_act(user, tool)
else if(istype(tool, /obj/item/stack/cable_coil))
. = cable_act(user, tool, LAZYACCESS(modifiers, RIGHT_CLICK))
else if(istype(tool, /obj/item/electronics/apc))
. = electronics_act(user, tool)
else if(istype(tool, /obj/item/electroadaptive_pseudocircuit))
. = pseudocircuit_act(user, tool)
else if(istype(tool, /obj/item/wallframe/apc))
. = wallframe_act(user, tool)
if(.)
return .
if(panel_open && !opened && is_wire_tool(tool))
wires.interact(user)
return ITEM_INTERACT_SUCCESS
return .
/// Called when we interact with the APC with an item with which we can get shocked when we stuff it into an APC
/obj/machinery/power/apc/proc/fork_outlet_act(mob/living/user, obj/item/tool)
var/metal = 0
var/shock_source = null
metal += LAZYACCESS(tool.custom_materials, GET_MATERIAL_REF(/datum/material/iron))//This prevents wooden rolling pins from shocking the user
if(cell || terminal) //The mob gets shocked by whichever powersource has the most electricity
if(cell && terminal)
shock_source = cell.charge > terminal.powernet.avail ? cell : terminal.powernet
else
shock_source = terminal?.powernet || cell
if(shock_source && metal && (panel_open || opened)) //Now you're cooking with electricity
if(!electrocute_mob(user, shock_source, src, siemens_coeff = 1, dist_check = TRUE))//People with insulated gloves just attack the APC normally. They're just short of magical anyway
return NONE
do_sparks(5, TRUE, src)
user.visible_message(span_notice("[user.name] shoves [tool] into the internal components of [src], erupting into a cascade of sparks!"))
if(shock_source == cell)//If the shock is coming from the cell just fully discharge it, because it's funny
cell.use(cell.charge)
return ITEM_INTERACT_SUCCESS
/// Called when we interact with the APC with a cell, attempts to insert it
/obj/machinery/power/apc/proc/cell_act(mob/living/user, obj/item/stock_parts/cell/new_cell)
if(!opened)
return NONE
if(cell)
balloon_alert(user, "cell already installed!")
return ITEM_INTERACT_BLOCKING
if(machine_stat & MAINT)
balloon_alert(user, "no connector for a cell!")
return ITEM_INTERACT_BLOCKING
if(!user.transferItemToLoc(new_cell, src))
return ITEM_INTERACT_BLOCKING
cell = new_cell
user.visible_message(span_notice("[user.name] inserts the power cell to [src.name]!"))
balloon_alert(user, "cell inserted")
update_appearance()
return ITEM_INTERACT_SUCCESS
/// Checks if we can place a terminal on the APC
/obj/machinery/power/apc/proc/can_place_terminal(mob/living/user, obj/item/stack/cable_coil/installing_cable, silent = TRUE)
if(!opened)
return FALSE
var/turf/host_turf = get_turf(src)
if(host_turf.underfloor_accessibility < UNDERFLOOR_INTERACTABLE)
if(!silent && user)
balloon_alert(user, "remove the floor plating!")
return FALSE
if(!isnull(terminal))
if(!silent && user)
balloon_alert(user, "already wired!")
return FALSE
if(!has_electronics)
if(!silent && user)
balloon_alert(user, "no board to wire!")
return FALSE
if(panel_open)
if(!silent && user)
balloon_alert(user, "wires prevent placing a terminal!")
return FALSE
if(installing_cable.get_amount() < 10)
if(!silent && user)
balloon_alert(user, "need ten lengths of cable!")
return FALSE
return TRUE
/// Called when we interact with the APC with a cable, attempts to wire the APC and create a terminal
/obj/machinery/power/apc/proc/cable_act(mob/living/user, obj/item/stack/cable_coil/installing_cable, is_right_clicking)
if(!opened)
return NONE
if(!can_place_terminal(user, installing_cable, silent = FALSE))
return ITEM_INTERACT_BLOCKING
var/terminal_cable_layer = cable_layer // Default to machine's cable layer
if(is_right_clicking)
var/choice = tgui_input_list(user, "Select Power Input Cable Layer", "Select Cable Layer", GLOB.cable_name_to_layer)
if(isnull(choice) \
|| !user.is_holding(installing_cable) \
|| !user.Adjacent(src) \
|| user.incapacitated() \
|| !can_place_terminal(user, installing_cable, silent = TRUE) \
)
return ITEM_INTERACT_BLOCKING
terminal_cable_layer = GLOB.cable_name_to_layer[choice]
user.visible_message(span_notice("[user.name] starts addding cables to the APC frame."))
balloon_alert(user, "adding cables...")
playsound(src, 'sound/items/deconstruct.ogg', 50, TRUE)
if(!do_after(user, 2 SECONDS, target = src))
return ITEM_INTERACT_BLOCKING
if(!can_place_terminal(user, installing_cable, silent = TRUE))
return ITEM_INTERACT_BLOCKING
var/turf/our_turf = get_turf(src)
var/obj/structure/cable/cable_node = our_turf.get_cable_node(terminal_cable_layer)
if(prob(50) && electrocute_mob(usr, cable_node, cable_node, 1, TRUE))
do_sparks(5, TRUE, src)
return ITEM_INTERACT_BLOCKING
installing_cable.use(10)
user.visible_message(span_notice("[user.name] adds cables to the APC frame."))
balloon_alert(user, "cables added")
make_terminal(terminal_cable_layer)
terminal.connect_to_network()
return ITEM_INTERACT_SUCCESS
/// Called when we interact with the APC with APC electronics, attempts to install the board
/obj/machinery/power/apc/proc/electronics_act(mob/living/user, obj/item/electronics/apc/installing_board)
if(!opened)
return NONE
if(has_electronics)
balloon_alert(user, "there is already a board!")
return ITEM_INTERACT_BLOCKING
if(machine_stat & BROKEN)
balloon_alert(user, "the frame is damaged!")
return ITEM_INTERACT_BLOCKING
user.visible_message(span_notice("[user.name] inserts the power control board into [src]."))
balloon_alert(user, "inserting the board...")
playsound(loc, 'sound/items/deconstruct.ogg', 50, TRUE)
if(!do_after(user, 1 SECONDS, target = src) || has_electronics)
return ITEM_INTERACT_BLOCKING
has_electronics = APC_ELECTRONICS_INSTALLED
locked = FALSE
balloon_alert(user, "board installed")
qdel(installing_board)
return ITEM_INTERACT_SUCCESS
/// Called when we interact with the APC with an electroadaptive pseudocircuit, used by cyborgs to install a board or weak cell
/obj/machinery/power/apc/proc/pseudocircuit_act(mob/living/user, obj/item/electroadaptive_pseudocircuit/pseudocircuit)
if(!has_electronics)
if(machine_stat & BROKEN)
balloon_alert(user, "frame is too damaged!")
return ITEM_INTERACT_BLOCKING
if(!pseudocircuit.adapt_circuit(user, circuit_cost = 0.05 * STANDARD_CELL_CHARGE))
return ITEM_INTERACT_BLOCKING
user.visible_message(
span_notice("[user] fabricates a circuit and places it into [src]."),
span_notice("You adapt a power control board and click it into place in [src]'s guts."),
)
has_electronics = APC_ELECTRONICS_INSTALLED
locked = FALSE
return ITEM_INTERACT_SUCCESS
if(!cell)
if(machine_stat & MAINT)
balloon_alert(user, "no board for a cell!")
return ITEM_INTERACT_BLOCKING
if(!pseudocircuit.adapt_circuit(user, circuit_cost = 0.5 * STANDARD_CELL_CHARGE))
return ITEM_INTERACT_BLOCKING
var/obj/item/stock_parts/cell/crap/empty/bad_cell = new(src)
bad_cell.forceMove(src)
cell = bad_cell
user.visible_message(
span_notice("[user] fabricates a weak power cell and places it into [src]."),
span_warning("Your [pseudocircuit.name] whirrs with strain as you create a weak power cell and place it into [src]!"),
)
update_appearance()
return ITEM_INTERACT_SUCCESS
balloon_alert(user, "has both board and cell!")
return ITEM_INTERACT_BLOCKING
/// Called when we interact with the APC with and APC frame, used for replacing a damaged cover/frame
/obj/machinery/power/apc/proc/wallframe_act(mob/living/user, obj/item/wallframe/apc/wallframe)
if(!opened)
return NONE
if(!(machine_stat & BROKEN || opened == APC_COVER_REMOVED || atom_integrity < max_integrity)) // There is nothing to repair
balloon_alert(user, "no reason for repairs!")
return ITEM_INTERACT_BLOCKING
if((machine_stat & BROKEN) && opened == APC_COVER_REMOVED && has_electronics && terminal) // Cover is the only thing broken, we do not need to remove elctronicks to replace cover
user.visible_message(span_notice("[user.name] replaces missing APC's cover."))
balloon_alert(user, "replacing APC's cover...")
if(!do_after(user, 2 SECONDS, target = src)) // replacing cover is quicker than replacing whole frame
return ITEM_INTERACT_BLOCKING
balloon_alert(user, "cover replaced")
qdel(wallframe)
update_integrity(30) //needs to be welded to fully repair but can work without
set_machine_stat(machine_stat & ~(BROKEN|MAINT))
opened = APC_COVER_OPENED
update_appearance()
return ITEM_INTERACT_SUCCESS
if(has_electronics)
balloon_alert(user, "remove the board inside!")
return ITEM_INTERACT_BLOCKING
user.visible_message(span_notice("[user.name] replaces the damaged APC frame with a new one."))
balloon_alert(user, "replacing damaged frame...")
if(!do_after(user, 5 SECONDS, target = src))
return ITEM_INTERACT_BLOCKING
balloon_alert(user, "replaced frame")
qdel(wallframe)
set_machine_stat(machine_stat & ~BROKEN)
atom_integrity = max_integrity
if(opened == APC_COVER_REMOVED)
opened = APC_COVER_OPENED
update_appearance()
return ITEM_INTERACT_SUCCESS
/obj/machinery/power/apc/crowbar_act(mob/user, obj/item/crowbar)
. = TRUE
//Prying off broken cover
if((opened == APC_COVER_CLOSED || opened == APC_COVER_OPENED) && (machine_stat & BROKEN))
crowbar.play_tool_sound(src)
balloon_alert(user, "prying...")
if(!crowbar.use_tool(src, user, 5 SECONDS))
return
opened = APC_COVER_REMOVED
balloon_alert(user, "cover removed")
update_appearance()
return
//Opening and closing cover
if((!opened && opened != APC_COVER_REMOVED) && !(machine_stat & BROKEN))
if(coverlocked && !(machine_stat & MAINT)) // locked...
balloon_alert(user, "cover is locked!")
return
else if(panel_open)
balloon_alert(user, "wires prevents opening it!")
return
else
opened = APC_COVER_OPENED
update_appearance()
return
if((opened && has_electronics == APC_ELECTRONICS_SECURED) && !(machine_stat & BROKEN))
opened = APC_COVER_CLOSED
coverlocked = TRUE //closing cover relocks it
balloon_alert(user, "locking the cover")
update_appearance()
return
//Taking out the electronics
if(!opened || has_electronics != APC_ELECTRONICS_INSTALLED)
return
if(terminal)
balloon_alert(user, "disconnect wires first!")
return
crowbar.play_tool_sound(src)
if(!crowbar.use_tool(src, user, 50))
return
if(has_electronics != APC_ELECTRONICS_INSTALLED)
return
has_electronics = APC_ELECTRONICS_MISSING
if(machine_stat & BROKEN)
user.visible_message(span_notice("[user.name] breaks the power control board inside [name]!"), \
span_hear("You hear a crack."))
balloon_alert(user, "charred board breaks")
return
else if(obj_flags & EMAGGED)
obj_flags &= ~EMAGGED
user.visible_message(span_notice("[user.name] discards an emagged power control board from [name]!"))
balloon_alert(user, "emagged board discarded")
return
else if(malfhack)
user.visible_message(span_notice("[user.name] discards a strangely programmed power control board from [name]!"))
balloon_alert(user, "reprogrammed board discarded")
malfai = null
malfhack = 0
return
user.visible_message(span_notice("[user.name] removes the power control board from [name]!"))
balloon_alert(user, "removed the board")
new /obj/item/electronics/apc(loc)
return
/obj/machinery/power/apc/screwdriver_act(mob/living/user, obj/item/W)
if(..())
return TRUE
. = TRUE
if(!opened)
if(obj_flags & EMAGGED)
balloon_alert(user, "interface is broken!")
return
toggle_panel_open()
balloon_alert(user, "wires [panel_open ? "exposed" : "unexposed"]")
W.play_tool_sound(src)
update_appearance()
return
if(cell)
user.visible_message(span_notice("[user] removes \the [cell] from [src]!"))
balloon_alert(user, "cell removed")
var/turf/user_turf = get_turf(user)
cell.forceMove(user_turf)
cell.update_appearance()
cell = null
charging = APC_NOT_CHARGING
update_appearance()
return
switch (has_electronics)
if(APC_ELECTRONICS_INSTALLED)
has_electronics = APC_ELECTRONICS_SECURED
set_machine_stat(machine_stat & ~MAINT)
W.play_tool_sound(src)
balloon_alert(user, "board fastened")
if(APC_ELECTRONICS_SECURED)
has_electronics = APC_ELECTRONICS_INSTALLED
set_machine_stat(machine_stat | MAINT)
W.play_tool_sound(src)
balloon_alert(user, "board unfastened")
else
balloon_alert(user, "no board to fasten!")
return
update_appearance()
/obj/machinery/power/apc/wirecutter_act(mob/living/user, obj/item/W)
. = ..()
if(terminal && opened)
terminal.dismantle(user, W)
return TRUE
/obj/machinery/power/apc/welder_act(mob/living/user, obj/item/welder)
. = ..()
//repairing the cover
if((atom_integrity < max_integrity) && has_electronics)
if(opened == APC_COVER_REMOVED)
balloon_alert(user, "no cover to repair!")
return
if (machine_stat & BROKEN)
balloon_alert(user, "too damaged to repair!")
return
if(!welder.tool_start_check(user, amount=1))
return
balloon_alert(user, "repairing...")
if(welder.use_tool(src, user, 4 SECONDS, volume = 50))
update_integrity(min(atom_integrity += 50,max_integrity))
balloon_alert(user, "repaired")
return ITEM_INTERACT_SUCCESS
//disassembling the frame
if(!opened || has_electronics || terminal)
return
if(!welder.tool_start_check(user, amount=1))
return
user.visible_message(span_notice("[user.name] welds [src]."), \
span_hear("You hear welding."))
balloon_alert(user, "welding the APC frame")
if(!welder.use_tool(src, user, 50, volume=50))
return
if((machine_stat & BROKEN) || opened == APC_COVER_REMOVED)
new /obj/item/stack/sheet/iron(loc)
user.visible_message(span_notice("[user.name] cuts [src] apart with [welder]."))
balloon_alert(user, "disassembled the broken frame")
else
new /obj/item/wallframe/apc(loc)
user.visible_message(span_notice("[user.name] cuts [src] from the wall with [welder]."))
balloon_alert(user, "cut the frame from the wall")
qdel(src)
return TRUE
/obj/machinery/power/apc/rcd_vals(mob/user, obj/item/construction/rcd/the_rcd)
if(!(the_rcd.upgrade & RCD_UPGRADE_SIMPLE_CIRCUITS))
return FALSE
if(!has_electronics)
if(machine_stat & BROKEN)
balloon_alert(user, "frame is too damaged!")
return FALSE
return list("delay" = 2 SECONDS, "cost" = 1)
if(!cell)
if(machine_stat & MAINT)
balloon_alert(user, "no board for a cell!")
return FALSE
return list("delay" = 5 SECONDS, "cost" = 10)
balloon_alert(user, "has both board and cell!")
return FALSE
/obj/machinery/power/apc/rcd_act(mob/user, obj/item/construction/rcd/the_rcd, list/rcd_data)
if(!(the_rcd.upgrade & RCD_UPGRADE_SIMPLE_CIRCUITS) || rcd_data["[RCD_DESIGN_MODE]"] != RCD_WALLFRAME)
return FALSE
if(!has_electronics)
if(machine_stat & BROKEN)
balloon_alert(user, "frame is too damaged!")
return
balloon_alert(user, "control board placed")
has_electronics = TRUE
locked = TRUE
return TRUE
if(!cell)
if(machine_stat & MAINT)
balloon_alert(user, "no board for a cell!")
return FALSE
var/obj/item/stock_parts/cell/crap/empty/C = new(src)
C.forceMove(src)
cell = C
balloon_alert(user, "power cell installed")
update_appearance()
return TRUE
balloon_alert(user, "has both board and cell!")
return FALSE
/obj/machinery/power/apc/emag_act(mob/user, obj/item/card/emag/emag_card)
if((obj_flags & EMAGGED) || malfhack)
return FALSE
if(opened)
balloon_alert(user, "close the cover first!")
return FALSE
else if(panel_open)
balloon_alert(user, "close the panel first!")
return FALSE
else if(machine_stat & (BROKEN|MAINT))
balloon_alert(user, "nothing happens!")
return FALSE
else
flick("apc-spark", src)
playsound(src, SFX_SPARKS, 75, TRUE, SHORT_RANGE_SOUND_EXTRARANGE)
obj_flags |= EMAGGED
locked = FALSE
balloon_alert(user, "interface damaged")
update_appearance()
flicker_hacked_icon()
return TRUE
// damage and destruction acts
/obj/machinery/power/apc/emp_act(severity)
. = ..()
if(!(. & EMP_PROTECT_CONTENTS))
if(cell)
cell.emp_act(severity)
if(occupier)
occupier.emp_act(severity)
if(. & EMP_PROTECT_SELF)
return
lighting = APC_CHANNEL_OFF
equipment = APC_CHANNEL_OFF
environ = APC_CHANNEL_OFF
update_appearance()
update()
addtimer(CALLBACK(src, PROC_REF(reset), APC_RESET_EMP), 60 SECONDS)
/obj/machinery/power/apc/proc/togglelock(mob/living/user)
if(obj_flags & EMAGGED)
balloon_alert(user, "interface is broken!")
else if(opened)
balloon_alert(user, "close the cover first!")
else if(panel_open)
balloon_alert(user, "close the panel first!")
else if(machine_stat & (BROKEN|MAINT))
balloon_alert(user, "nothing happens!")
else
if(allowed(usr) && !wires.is_cut(WIRE_IDSCAN) && !malfhack && !remote_control_user)
locked = !locked
balloon_alert(user, locked ? "locked" : "unlocked")
update_appearance()
else
balloon_alert(user, "access denied!")