-
-
Notifications
You must be signed in to change notification settings - Fork 452
/
RSF.dm
260 lines (232 loc) · 9.4 KB
/
RSF.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
/*
CONTAINS:
RSF
*/
///Extracts the related object from a associated list of objects and values, or lists and objects.
#define OBJECT_OR_LIST_ELEMENT(from, input) (islist(input) ? from[input] : input)
/obj/item/rsf
name = "\improper Rapid Service Fabricator (RSF)"
desc = "A device used to rapidly deploy service items."
icon = 'icons/obj/tools.dmi'
icon_state = "rsf" ///The icon state to revert to when the tool is empty (thanks TG)
var/spent_icon_state = "rsf_empty"
lefthand_file = 'icons/mob/inhands/equipment/tools_lefthand.dmi'
righthand_file = 'icons/mob/inhands/equipment/tools_righthand.dmi'
opacity = FALSE
density = FALSE
anchored = FALSE
item_flags = NOBLUDGEON
armor = list(MELEE = 0, BULLET = 0, LASER = 0, ENERGY = 0, BOMB = 0, BIO = 0, RAD = 0, FIRE = 0, ACID = 0)
var/matter = 0 ///The current matter count
var/max_matter = 50 ///The max amount of matter in the device
var/to_dispense ///The type of the object we are going to dispense
var/dispense_cost = 0 ///The cost of the object we are going to dispense
w_class = WEIGHT_CLASS_NORMAL
///An associated list of atoms and charge costs. This can contain a seperate list, as long as it's associated item is an object
var/list/cost_by_item = list(/obj/item/reagent_containers/food/drinks/drinkingglass = 20,
/obj/item/paper = 10,
/obj/item/storage/pill_bottle/dice = 200,
/obj/item/pen = 50,
/obj/item/clothing/mask/cigarette = 10,
/obj/item/plate = 25,
)
var/list/allowed_surfaces = list(/obj/structure/table) ///A list of surfaces that we are allowed to place things on.
var/action_type = "Dispensing" ///The verb that describes what we're doing, for use in text
/obj/item/rsf/Initialize(mapload)
. = ..()
to_dispense = cost_by_item[1]
dispense_cost = cost_by_item[to_dispense]
/obj/item/rsf/examine(mob/user)
. = ..()
. += span_notice("It currently holds [matter]/[max_matter] matter-units.")
/obj/item/rsf/cyborg
matter = 50
/obj/item/rsf/attackby(obj/item/W, mob/user, params)
var/loaded = FALSE
if(istype(W, /obj/item/rcd_ammo))//If the thing we got hit by is in our matter list
var/tempMatter = matter + 10
if(tempMatter > max_matter)
to_chat(user, span_warning("\The [src] can't hold any more matter-units!"))
return
qdel(W)
matter = tempMatter //We add its value
loaded = TRUE
else if(istype(W, /obj/item/stack))
loaded = loadwithsheets(W, user)
else
return ..()
if(loaded)
to_chat(user, span_notice("[src] now holds [matter]/[max_matter] matter-units."))
icon_state = initial(icon_state)//and set the icon state to the initial value it had
playsound(src.loc, 'sound/machines/click.ogg', 10, 1)
/obj/item/rsf/attack_self(mob/user)
playsound(src.loc, 'sound/effects/pop.ogg', 50, 0)
var/target = cost_by_item
var/cost = 0
//Warning, prepare for bodgecode
while(islist(target))//While target is a list we continue the loop
var/picked = show_radial_menu(user, src, formRadial(target), custom_check = CALLBACK(src, PROC_REF(check_menu), user), require_near = TRUE)
if(!check_menu(user) || picked == null)
return
for(var/emem in target)//Back through target agian
var/atom/test = OBJECT_OR_LIST_ELEMENT(target, emem)
if(picked == initial(test.name))//We try and find the entry that matches the radial selection
cost = target[emem]//We cash the cost
target = emem
break
//If we found a list we start it all again, this time looking through its contents.
to_dispense = target //This allows for sublists
dispense_cost = cost
// Change mode
/obj/item/rsf/proc/loadwithsheets(obj/item/stack/S, mob/user)
var/value = S.matter_amount
if(value <= 0)
to_chat(user, span_notice("You can't insert [S.name] into [src]!"))
return FALSE
var/maxsheets = round((max_matter-matter)/value) //calculate the max number of sheets that will fit in RCD
if(maxsheets > 0)
var/amount_to_use = min(S.amount, maxsheets)
S.use(amount_to_use)
matter += value*amount_to_use
to_chat(user, span_notice("You insert [amount_to_use] [S.name] sheets into [src]. "))
return TRUE
to_chat(user, span_warning("You can't insert any more [S.name] sheets into [src]!"))
return FALSE
///Forms a radial menu based off an object in a list, or a list's associated object
/obj/item/rsf/proc/formRadial(from)
var/list/radial_list = list()
for(var/meme in from)//We iterate through all of targets entrys
var/atom/temp = OBJECT_OR_LIST_ELEMENT(from, meme)
//We then add their data into the radial menu
radial_list[initial(temp.name)] = image(icon = initial(temp.icon), icon_state = initial(temp.icon_state))
return radial_list
/obj/item/rsf/proc/check_menu(mob/user)
if(user.incapacitated() || !user.Adjacent(src))
return FALSE
return TRUE
/obj/item/rsf/afterattack(atom/A, mob/user, proximity)
. = ..()
if(!proximity)
return
if(!is_allowed(A, user))
return
if(use_matter(dispense_cost, user))//If we can charge that amount of charge, we do so and return true
playsound(loc, 'sound/machines/click.ogg', 10, TRUE)
var/atom/meme = new to_dispense(get_turf(A))
to_chat(user, span_notice("[action_type] [meme.name]..."))
///A helper proc. checks to see if we can afford the amount of charge that is passed, and if we can docs the charge from our base, and returns TRUE. If we can't we return FALSE
/obj/item/rsf/proc/use_matter(charge, mob/user)
if(iscyborg(user))
var/mob/living/silicon/robot/R = user
var/end_charge = R.cell.charge - charge
if(end_charge < 0)
to_chat(user, span_warning("You do not have enough power to use [src]."))
icon_state = spent_icon_state
return FALSE
R.cell.charge = end_charge
return TRUE
else
if(matter - 1 < 0)
to_chat(user, span_warning("\The [src] doesn't have enough matter-units left."))
icon_state = spent_icon_state
return FALSE
matter--
to_chat(user, span_notice("\The [src] now holds [matter]/[max_matter] matter-units."))
return TRUE
///Helper proc that iterates through all the things we are allowed to spawn on, and sees if the passed atom is one of them
/obj/item/rsf/proc/is_allowed(atom/to_check, mob/user)
for(var/sort in allowed_surfaces)
if(istype(to_check, sort))
return TRUE
to_chat(user, span_warning("\The [src] is unable to place this here!"))
return FALSE
/obj/item/rsf/cookiesynth
name = "Cookie Synthesizer"
desc = "A self-recharging device used to rapidly deploy cookies."
icon_state = "rcd"
spent_icon_state = "rcd"
max_matter = 10
cost_by_item = list(/obj/item/reagent_containers/food/snacks/cookie = 100)
dispense_cost = 100
action_type = "Fabricating"
///Tracks whether or not the cookiesynth is about to print a poisoned cookie
var/toxin = FALSE //This might be better suited to some initialize fuckery, but I don't have a good "poisoned" sprite
var/cooldown = 0 ///Holds a copy of world.time taken the last time the synth gained a charge. Used with cooldowndelay to track when the next charge should be gained
var/cooldowndelay = 10 ///The period between recharges
/obj/item/rsf/cookiesynth/Initialize(mapload)
. = ..()
START_PROCESSING(SSprocessing, src)
/obj/item/rsf/cookiesynth/Destroy()
STOP_PROCESSING(SSprocessing, src)
return ..()
/obj/item/rsf/cookiesynth/attackby()
return
/obj/item/rsf/cookiesynth/emag_act(mob/user, obj/item/card/emag/emag_card)
obj_flags ^= EMAGGED
if(obj_flags & EMAGGED)
to_chat(user, span_warning("You short out [src]'s reagent safety checker!"))
else
to_chat(user, span_warning("You reset [src]'s reagent safety checker!"))
return TRUE
/obj/item/rsf/cookiesynth/attack_self(mob/user)
var/mob/living/silicon/robot/P = null
if(iscyborg(user))
P = user
if(((obj_flags & EMAGGED) || (P && P.emagged)) && !toxin)
toxin = TRUE
to_dispense = /obj/item/reagent_containers/food/snacks/cookie/sleepy
else
toxin = FALSE
to_dispense = /obj/item/reagent_containers/food/snacks/cookie
to_chat(user, "Cookie Synthesizer Reset")
/obj/item/rsf/cookiesynth/process(delta_time)
matter = min(matter += delta_time, max_matter) //We add 1 up to a point
if(matter >= max_matter)
STOP_PROCESSING(SSprocessing, src)
/obj/item/rsf/cookiesynth/afterattack(atom/A, mob/user, proximity)
. = ..()
cooldown = world.time + cooldowndelay
if(!(datum_flags & DF_ISPROCESSING))
START_PROCESSING(SSprocessing, src)
/obj/item/donutsynth
name = "Donut Synthesizer"
desc = "A self-recharging device used to rapidly deploy donuts."
icon = 'icons/obj/tools.dmi'
icon_state = "rcd"
lefthand_file = 'icons/mob/inhands/equipment/tools_lefthand.dmi'
righthand_file = 'icons/mob/inhands/equipment/tools_righthand.dmi'
var/matter = 10
var/cooldown = 0
var/cooldowndelay = 10
w_class = WEIGHT_CLASS_NORMAL
/obj/item/donutsynth/attackby()
return
/obj/item/donutsynth/process()
if(matter < 10)
matter++
/obj/item/donutsynth/afterattack(atom/A, mob/user, proximity)
. = ..()
if(cooldown > world.time)
return
if(!proximity)
return
if (!(istype(A, /obj/structure/table) || isfloorturf(A)))
return
if(matter < 1)
to_chat(user, span_warning("[src] doesn't have enough matter left. Wait for it to recharge!"))
return
if(iscyborg(user))
var/mob/living/silicon/robot/R = user
if(!R.cell || R.cell.charge < 400)
to_chat(user, span_warning("You do not have enough power to use [src]."))
return
var/turf/T = get_turf(A)
playsound(src.loc, 'sound/machines/click.ogg', 10, 1)
to_chat(user, "Fabricating Donut..")
new /obj/item/reagent_containers/food/snacks/donut(T)
if (iscyborg(user))
var/mob/living/silicon/robot/R = user
R.cell.charge -= 100
else
matter--
cooldown = world.time + cooldowndelay