This repository was archived by the owner on May 22, 2025. It is now read-only.
-
-
Notifications
You must be signed in to change notification settings - Fork 458
Expand file tree
/
Copy pathfields.dm
More file actions
328 lines (280 loc) · 12 KB
/
fields.dm
File metadata and controls
328 lines (280 loc) · 12 KB
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
//Movable and easily code-modified fields! Allows for custom AOE effects that affect movement and anything inside of them, and can do custom turf effects!
//Supports automatic recalculation/reset on movement.
//If there's any way to make this less CPU intensive than I've managed, gimme a call or do it yourself! - kevinz000
//Field shapes
#define FIELD_NO_SHAPE 0 //Does not update turfs automatically
#define FIELD_SHAPE_RADIUS_SQUARE 1 //Uses current_range and square_depth_up/down
#define FIELD_SHAPE_CUSTOM_SQUARE 2 //Uses square_height and square_width and square_depth_up/down
//Proc to make fields. make_field(field_type, field_params_in_associative_list)
/proc/make_field(field_type, list/field_params, override_checks = FALSE, start_field = TRUE)
var/datum/proximity_monitor/advanced/F = new field_type()
if(!F.assume_params(field_params) && !override_checks)
QDEL_NULL(F)
if(!F.check_variables() && !override_checks)
QDEL_NULL(F)
if(start_field && (F || override_checks))
F.Initialize()
return F
/datum/proximity_monitor/advanced
var/name = "\improper Energy Field"
//Field setup specifications
var/field_shape = FIELD_NO_SHAPE
var/square_height = 0
var/square_width = 0
var/square_depth_up = 0
var/square_depth_down = 0
//Processing
var/process_inner_turfs = FALSE //Don't do this unless it's absolutely necessary
var/process_edge_turfs = FALSE //Don't do this either unless it's absolutely necessary, you can just track what things are inside manually or on the initial setup.
var/requires_processing = FALSE
var/setup_edge_turfs = FALSE //Setup edge turfs/all field turfs. Set either or both to ON when you need it, it's defaulting to off unless you do to save CPU.
var/setup_field_turfs = FALSE
var/use_host_turf = FALSE //For fields from items carried on mobs to check turf instead of loc...
var/list/turf/field_turfs = list()
var/list/turf/edge_turfs = list()
var/list/turf/field_turfs_new = list()
var/list/turf/edge_turfs_new = list()
/datum/proximity_monitor/advanced/Destroy()
full_cleanup()
STOP_PROCESSING(SSfields, src)
return ..()
/datum/proximity_monitor/advanced/proc/assume_params(list/field_params)
var/pass_check = TRUE
for(var/param in field_params)
if(vars[param] || isnull(vars[param]) || (param in vars))
vars[param] = field_params[param]
else
pass_check = FALSE
return pass_check
/datum/proximity_monitor/advanced/proc/check_variables()
var/pass = TRUE
if(field_shape == FIELD_NO_SHAPE) //If you're going to make a manually updated field you shouldn't be using automatic checks so don't.
pass = FALSE
if(current_range < 0 || square_height < 0 || square_width < 0 || square_depth_up < 0 || square_depth_down < 0)
pass = FALSE
if(!istype(host))
pass = FALSE
return pass
/datum/proximity_monitor/advanced/process()
if(process_inner_turfs)
for(var/turf/T in field_turfs)
process_inner_turf(T)
CHECK_TICK //Really crappy lagchecks, needs improvement once someone starts using processed fields.
if(process_edge_turfs)
for(var/turf/T in edge_turfs)
process_edge_turf(T)
CHECK_TICK //Same here.
/datum/proximity_monitor/advanced/proc/process_inner_turf(turf/T)
/datum/proximity_monitor/advanced/proc/process_edge_turf(turf/T)
/datum/proximity_monitor/advanced/New()
if(requires_processing)
START_PROCESSING(SSfields, src)
/datum/proximity_monitor/advanced/proc/Initialize()
setup_field()
post_setup_field()
/datum/proximity_monitor/advanced/proc/full_cleanup() //Full cleanup for when you change something that would require complete resetting.
for(var/turf/T in edge_turfs)
cleanup_edge_turf(T)
for(var/turf/T in field_turfs)
cleanup_field_turf(T)
/datum/proximity_monitor/advanced/proc/check_movement()
if(!use_host_turf)
if(host.loc != last_host_loc)
last_host_loc = host.loc
return TRUE
else
if(get_turf(host) != last_host_loc)
last_host_loc = get_turf(host)
return TRUE
return FALSE
/datum/proximity_monitor/advanced/proc/recalculate_field(ignore_movement_check = FALSE) //Call every time the field moves (done automatically if you use update_center) or a setup specification is changed.
if(!(ignore_movement_check || check_movement()) && (field_shape != FIELD_NO_SHAPE))
return
update_new_turfs()
var/list/turf/needs_setup = field_turfs_new.Copy()
if(setup_field_turfs)
for(var/turf/T in field_turfs)
if(!(T in needs_setup))
cleanup_field_turf(T)
else
needs_setup -= T
CHECK_TICK
for(var/turf/T in needs_setup)
setup_field_turf(T)
CHECK_TICK
if(setup_edge_turfs)
for(var/turf/T in edge_turfs)
cleanup_edge_turf(T)
CHECK_TICK
for(var/turf/T in edge_turfs_new)
setup_edge_turf(T)
CHECK_TICK
/datum/proximity_monitor/advanced/proc/field_turf_canpass(atom/movable/AM, obj/effect/abstract/proximity_checker/advanced/field_turf/F, turf/entering)
return TRUE
/datum/proximity_monitor/advanced/proc/field_turf_uncross(atom/movable/AM, obj/effect/abstract/proximity_checker/advanced/field_turf/F)
return TRUE
/datum/proximity_monitor/advanced/proc/field_turf_crossed(atom/movable/AM, obj/effect/abstract/proximity_checker/advanced/field_turf/F)
return TRUE
/datum/proximity_monitor/advanced/proc/field_turf_uncrossed(atom/movable/AM, obj/effect/abstract/proximity_checker/advanced/field_turf/F)
return TRUE
/datum/proximity_monitor/advanced/proc/field_edge_canpass(atom/movable/AM, obj/effect/abstract/proximity_checker/advanced/field_edge/F, turf/entering)
return TRUE
/datum/proximity_monitor/advanced/proc/field_edge_uncross(atom/movable/AM, obj/effect/abstract/proximity_checker/advanced/field_edge/F)
return TRUE
/datum/proximity_monitor/advanced/proc/field_edge_crossed(atom/movable/AM, obj/effect/abstract/proximity_checker/advanced/field_edge/F)
return TRUE
/datum/proximity_monitor/advanced/proc/field_edge_uncrossed(atom/movable/AM, obj/effect/abstract/proximity_checker/advanced/field_edge/F)
return TRUE
/datum/proximity_monitor/advanced/HandleMove()
var/atom/_host = host
var/atom/new_host_loc = _host.loc
if(last_host_loc != new_host_loc)
recalculate_field()
/datum/proximity_monitor/advanced/proc/post_setup_field()
/datum/proximity_monitor/advanced/proc/setup_field()
update_new_turfs()
if(setup_field_turfs)
for(var/turf/T in field_turfs_new)
setup_field_turf(T)
CHECK_TICK
if(setup_edge_turfs)
for(var/turf/T in edge_turfs_new)
setup_edge_turf(T)
CHECK_TICK
/datum/proximity_monitor/advanced/proc/cleanup_field_turf(turf/T)
qdel(field_turfs[T])
field_turfs -= T
/datum/proximity_monitor/advanced/proc/cleanup_edge_turf(turf/T)
qdel(edge_turfs[T])
edge_turfs -= T
/datum/proximity_monitor/advanced/proc/setup_field_turf(turf/T)
field_turfs[T] = new /obj/effect/abstract/proximity_checker/advanced/field_turf(T, src)
/datum/proximity_monitor/advanced/proc/setup_edge_turf(turf/T)
edge_turfs[T] = new /obj/effect/abstract/proximity_checker/advanced/field_edge(T, src)
/datum/proximity_monitor/advanced/proc/update_new_turfs()
if(!istype(host))
return FALSE
var/turf/center = get_turf(host)
field_turfs_new = list()
edge_turfs_new = list()
switch(field_shape)
if(FIELD_NO_SHAPE)
return FALSE
if(FIELD_SHAPE_RADIUS_SQUARE)
for(var/turf/T in block(locate(center.x-current_range,center.y-current_range,center.z-square_depth_down),locate(center.x+current_range, center.y+current_range,center.z+square_depth_up)))
field_turfs_new += T
edge_turfs_new = field_turfs_new.Copy()
if(current_range >= 1)
var/list/turf/center_turfs = list()
for(var/turf/T in block(locate(center.x-current_range+1,center.y-current_range+1,center.z-square_depth_down),locate(center.x+current_range-1, center.y+current_range-1,center.z+square_depth_up)))
center_turfs += T
for(var/turf/T in center_turfs)
edge_turfs_new -= T
if(FIELD_SHAPE_CUSTOM_SQUARE)
for(var/turf/T in block(locate(center.x-square_width,center.y-square_height,center.z-square_depth_down),locate(center.x+square_width, center.y+square_height,center.z+square_depth_up)))
field_turfs_new += T
edge_turfs_new = field_turfs_new.Copy()
if(square_height >= 1 && square_width >= 1)
var/list/turf/center_turfs = list()
for(var/turf/T in block(locate(center.x-square_width+1,center.y-square_height+1,center.z-square_depth_down),locate(center.x+square_width-1, center.y+square_height-1,center.z+square_depth_up)))
center_turfs += T
for(var/turf/T in center_turfs)
edge_turfs_new -= T
//Gets edge direction/corner, only works with square radius/WDH fields!
/datum/proximity_monitor/advanced/proc/get_edgeturf_direction(turf/T, turf/center_override = null)
var/turf/checking_from = get_turf(host)
if(istype(center_override))
checking_from = center_override
if(field_shape != FIELD_SHAPE_RADIUS_SQUARE && field_shape != FIELD_SHAPE_CUSTOM_SQUARE)
return
if(!(T in edge_turfs))
return
switch(field_shape)
if(FIELD_SHAPE_RADIUS_SQUARE)
if(((T.x == (checking_from.x + current_range)) || (T.x == (checking_from.x - current_range))) && ((T.y == (checking_from.y + current_range)) || (T.y == (checking_from.y - current_range))))
return get_dir(checking_from, T)
if(T.x == (checking_from.x + current_range))
return EAST
if(T.x == (checking_from.x - current_range))
return WEST
if(T.y == (checking_from.y - current_range))
return SOUTH
if(T.y == (checking_from.y + current_range))
return NORTH
if(FIELD_SHAPE_CUSTOM_SQUARE)
if(((T.x == (checking_from.x + square_width)) || (T.x == (checking_from.x - square_width))) && ((T.y == (checking_from.y + square_height)) || (T.y == (checking_from.y - square_height))))
return get_dir(checking_from, T)
if(T.x == (checking_from.x + square_width))
return EAST
if(T.x == (checking_from.x - square_width))
return WEST
if(T.y == (checking_from.y - square_height))
return SOUTH
if(T.y == (checking_from.y + square_height))
return NORTH
//DEBUG FIELDS
/datum/proximity_monitor/advanced/debug
name = "\improper Color Matrix Field"
field_shape = FIELD_SHAPE_RADIUS_SQUARE
current_range = 5
var/set_fieldturf_color = "#aaffff"
var/set_edgeturf_color = "#ffaaff"
setup_field_turfs = TRUE
setup_edge_turfs = TRUE
/datum/proximity_monitor/advanced/debug/setup_edge_turf(turf/T)
T.color = set_edgeturf_color
..()
/datum/proximity_monitor/advanced/debug/cleanup_edge_turf(turf/T)
T.color = initial(T.color)
..()
if(T in field_turfs)
T.color = set_fieldturf_color
/datum/proximity_monitor/advanced/debug/setup_field_turf(turf/T)
T.color = set_fieldturf_color
..()
/datum/proximity_monitor/advanced/debug/cleanup_field_turf(turf/T)
T.color = initial(T.color)
..()
//DEBUG FIELD ITEM
/obj/item/multitool/field_debug
name = "strange multitool"
desc = "Seems to project a colored field!"
var/list/field_params = list("field_shape" = FIELD_SHAPE_RADIUS_SQUARE, "current_range" = 5, "set_fieldturf_color" = "#aaffff", "set_edgeturf_color" = "#ffaaff")
var/field_type = /datum/proximity_monitor/advanced/debug
var/operating = FALSE
var/datum/proximity_monitor/advanced/current = null
var/mob/listeningTo
/obj/item/multitool/field_debug/Initialize(mapload)
. = ..()
START_PROCESSING(SSobj, src)
/obj/item/multitool/field_debug/Destroy()
STOP_PROCESSING(SSobj, src)
QDEL_NULL(current)
listeningTo = null
return ..()
/obj/item/multitool/field_debug/proc/setup_debug_field()
var/list/new_params = field_params.Copy()
new_params["host"] = src
current = make_field(field_type, new_params)
/obj/item/multitool/field_debug/attack_self(mob/user)
operating = !operating
to_chat(user, "You turn [src] [operating? "on":"off"].")
UnregisterSignal(listeningTo, COMSIG_MOVABLE_MOVED)
listeningTo = null
if(!istype(current) && operating)
RegisterSignal(user, COMSIG_MOVABLE_MOVED, PROC_REF(on_mob_move))
listeningTo = user
setup_debug_field()
else if(!operating)
QDEL_NULL(current)
/obj/item/multitool/field_debug/dropped()
. = ..()
if(listeningTo)
UnregisterSignal(listeningTo, COMSIG_MOVABLE_MOVED)
listeningTo = null
/obj/item/multitool/field_debug/proc/on_mob_move()
check_turf(get_turf(src))
/obj/item/multitool/field_debug/process()
check_turf(get_turf(src))
/obj/item/multitool/field_debug/proc/check_turf(turf/T)
current.HandleMove()