/
machine_wand.dm
182 lines (161 loc) · 6.9 KB
/
machine_wand.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
///When EMPed, how long the remote will be disabled for by default.
#define EMP_TIMEOUT_DURATION (2 MINUTES)
/obj/item/machine_remote
name = "machine wand"
desc = "A remote for controlling machines and bots around the station."
icon = 'icons/obj/antags/syndicate_tools.dmi'
icon_state = "weakpoint_locator"
inhand_icon_state = "weakpoint_locator"
lefthand_file = 'icons/mob/inhands/items/devices_lefthand.dmi'
righthand_file = 'icons/mob/inhands/items/devices_righthand.dmi'
w_class = WEIGHT_CLASS_NORMAL
///If we're unable to be used, this is how long we have left to wait.
COOLDOWN_DECLARE(timeout_time)
///The appearance put onto machines being actively controlled.
var/mutable_appearance/bug_appearance
///Direct reference to the moving bug effect that moves towards machines we direct it at.
var/obj/effect/bug_moving/moving_bug
///The machine that's currently being controlled.
var/atom/movable/controlling_machine_or_bot
/obj/item/machine_remote/Initialize(mapload)
. = ..()
bug_appearance = mutable_appearance('icons/effects/effects.dmi', "fly-surrounding", ABOVE_WINDOW_LAYER)
register_context()
/obj/item/machine_remote/Destroy(force)
. = ..()
if(controlling_machine_or_bot)
remove_old_machine()
QDEL_NULL(moving_bug)
QDEL_NULL(bug_appearance)
/obj/item/machine_remote/examine(mob/user)
. = ..()
if(controlling_machine_or_bot)
. += span_notice("It is currently controlling [controlling_machine_or_bot]. Use in-hand to interact with it.")
/obj/item/machine_remote/add_context(atom/source, list/context, obj/item/held_item, mob/user)
if(controlling_machine_or_bot)
context[SCREENTIP_CONTEXT_LMB] = "Use [controlling_machine_or_bot]"
context[SCREENTIP_CONTEXT_ALT_LMB] = "Flush Control"
return CONTEXTUAL_SCREENTIP_SET
return NONE
/obj/item/machine_remote/proc/on_control_destroy(obj/machinery/source)
SIGNAL_HANDLER
remove_old_machine()
/obj/item/machine_remote/ui_interact(mob/user, datum/tgui/ui)
if(!COOLDOWN_FINISHED(src, timeout_time))
playsound(src, 'sound/machines/synth_no.ogg', 30 , TRUE)
say("Remote control disabled temporarily. Please try again soon.")
return FALSE
if(!controlling_machine_or_bot)
return
if(controlling_machine_or_bot.ui_interact(user, ui))
return
controlling_machine_or_bot.interact(user) //no ui, interact instead (to open windoors and such)
/obj/item/machine_remote/ui_act(action, list/params, datum/tgui/ui, datum/ui_state/state)
. = ..()
if(controlling_machine_or_bot)
return controlling_machine_or_bot.ui_act(action, params, ui, state)
/obj/item/machine_remote/click_alt(mob/user)
if(moving_bug) //we have a bug in transit, so let's kill it.
QDEL_NULL(moving_bug)
return CLICK_ACTION_BLOCKING
if(!controlling_machine_or_bot)
return CLICK_ACTION_BLOCKING
say("Remote control over [controlling_machine_or_bot] stopped.")
remove_old_machine()
return CLICK_ACTION_SUCCESS
/obj/item/machine_remote/afterattack(atom/target, mob/user, proximity_flag, click_parameters)
. = ..()
if(!COOLDOWN_FINISHED(src, timeout_time))
playsound(src, 'sound/machines/synth_no.ogg', 30 , TRUE)
say("Remote control disabled temporarily. Please try again soon.")
return FALSE
if(!ismachinery(target) && !isbot(target))
return
if(moving_bug) //we have a bug in transit already, so let's kill it.
QDEL_NULL(moving_bug)
var/turf/spawning_turf = (controlling_machine_or_bot ? get_turf(controlling_machine_or_bot) : get_turf(src))
moving_bug = new(spawning_turf, src, target)
remove_old_machine()
///Sets a controlled machine to a new machine, if possible. Checks if AIs can even control it.
/obj/item/machine_remote/proc/set_controlled_machine(obj/machinery/new_machine)
if(controlling_machine_or_bot == new_machine)
return
remove_old_machine()
if(istype(new_machine, /obj/machinery/power/apc))
var/obj/machinery/power/apc/new_apc = new_machine
if(new_apc.aidisabled)
say("AI wire cut, machine uncontrollable.")
return
else if(istype(new_machine, /obj/machinery/door/airlock))
var/obj/machinery/door/airlock/new_airlock = new_machine
if(!new_airlock.canAIControl())
say("AI wire cut, machine uncontrollable.")
return
controlling_machine_or_bot = new_machine
controlling_machine_or_bot.add_overlay(bug_appearance)
RegisterSignal(controlling_machine_or_bot, COMSIG_QDELETING, PROC_REF(on_control_destroy))
RegisterSignal(controlling_machine_or_bot, COMSIG_ATOM_EMP_ACT, PROC_REF(on_machine_emp))
///Removes the machine being controlled as the current machine, taking its signals and overlays with it.
/obj/item/machine_remote/proc/remove_old_machine()
if(!controlling_machine_or_bot)
return
UnregisterSignal(controlling_machine_or_bot, list(COMSIG_ATOM_EMP_ACT, COMSIG_QDELETING))
controlling_machine_or_bot.cut_overlay(bug_appearance)
controlling_machine_or_bot = null
///Called when the machine we're controlling is EMP, removing our control from it.
/obj/item/machine_remote/proc/on_machine_emp(datum/source, severity, protection)
SIGNAL_HANDLER
if(severity & EMP_PROTECT_CONTENTS)
return
disable_remote(EMP_TIMEOUT_DURATION)
/obj/item/machine_remote/proc/disable_remote(timeout_duration)
remove_old_machine()
COOLDOWN_START(src, timeout_time, timeout_duration)
///The effect of the bug moving towards the selected machinery to mess with.
/obj/effect/bug_moving
name = "bug"
desc = "Where da bug goin?"
icon_state = "fly"
obj_flags = CAN_BE_HIT
max_integrity = 20
uses_integrity = TRUE
plane = ABOVE_GAME_PLANE
layer = FLY_LAYER
movement_type = PHASING
///The controller that's sending us out to the machine.
var/obj/item/machine_remote/controller
///The machine we are trying to get remote access to.
var/atom/movable/thing_moving_towards
/obj/effect/bug_moving/Initialize(mapload, obj/item/machine_remote/controller, atom/movable/thing_moving_towards)
. = ..()
if(!controller)
CRASH("a moving bug has been created by something that isn't a machine remote controller!")
if(!thing_moving_towards)
CRASH("a moving bug has been created but isn't moving towards anything!")
src.controller = controller
src.thing_moving_towards = thing_moving_towards
var/datum/move_loop/loop = GLOB.move_manager.home_onto(src, thing_moving_towards, delay = 5, flags = MOVEMENT_LOOP_NO_DIR_UPDATE)
RegisterSignal(loop, COMSIG_MOVELOOP_POSTPROCESS, PROC_REF(reached_destination_check))
RegisterSignal(thing_moving_towards, COMSIG_QDELETING, PROC_REF(on_machine_del))
/obj/effect/bug_moving/Destroy(force)
if(controller)
controller.moving_bug = null
controller = null
thing_moving_towards = null
return ..()
/obj/effect/bug_moving/emp_act(severity)
. = ..()
if(. & EMP_PROTECT_SELF)
return
controller.disable_remote(EMP_TIMEOUT_DURATION)
qdel(src)
/obj/effect/bug_moving/proc/reached_destination_check(datum/move_loop/source, result)
SIGNAL_HANDLER
if(!Adjacent(thing_moving_towards))
return
controller.set_controlled_machine(thing_moving_towards)
qdel(src)
/obj/effect/bug_moving/proc/on_machine_del(datum/move_loop/source)
SIGNAL_HANDLER
qdel(src)
#undef EMP_TIMEOUT_DURATION