This repository has been archived by the owner on Sep 12, 2021. It is now read-only.
-
-
Notifications
You must be signed in to change notification settings - Fork 66
/
snacks.dm
356 lines (316 loc) · 14.7 KB
/
snacks.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
/** # Snacks
Items in the "Snacks" subcategory are food items that people actually eat. The key points are that they are created
already filled with reagents and are destroyed when empty. Additionally, they make a "munching" noise when eaten.
Notes by Darem: Food in the "snacks" subtype can hold a maximum of 50 units. Generally speaking, you don't want to go over 40
total for the item because you want to leave space for extra condiments. If you want effect besides healing, add a reagent for
it. Try to stick to existing reagents when possible (so if you want a stronger healing effect, just use omnizine). On use
effect (such as the old officer eating a donut code) requires a unique reagent (unless you can figure out a better way).
The nutriment reagent and bitesize variable replace the old heal_amt and amount variables. Each unit of nutriment is equal to
2 of the old heal_amt variable. Bitesize is the rate at which the reagents are consumed. So if you have 6 nutriment and a
bitesize of 2, then it'll take 3 bites to eat. Unlike the old system, the contained reagents are evenly spread among all
the bites. No more contained reagents = no more bites.
Here is an example of the new formatting for anyone who wants to add more food items.
```
/obj/item/reagent_containers/food/snacks/xenoburger //Identification path for the object.
name = "Xenoburger" //Name that displays in the UI.
desc = "Smells caustic. Tastes like heresy." //Duh
icon_state = "xburger" //Refers to an icon in food.dmi
/obj/item/reagent_containers/food/snacks/xenoburger/Initialize() //Don't mess with this. | nO I WILL MESS WITH THIS
. = ..() //Same here.
reagents.add_reagent(/datum/reagent/xenomicrobes, 10) //This is what is in the food item. you may copy/paste
reagents.add_reagent(/datum/reagent/consumable/nutriment, 2) //this line of code for all the contents.
bitesize = 3 //This is the amount each bite consumes.
```
All foods are distributed among various categories. Use common sense.
*/
/obj/item/reagent_containers/food/snacks
name = "snack"
desc = "Yummy."
icon = 'icons/obj/food/food.dmi'
icon_state = null
lefthand_file = 'icons/mob/inhands/misc/food_lefthand.dmi'
righthand_file = 'icons/mob/inhands/misc/food_righthand.dmi'
obj_flags = UNIQUE_RENAME
grind_results = list() //To let them be ground up to transfer their reagents
var/bitesize = 2
var/bitecount = 0
var/trash = null
var/slice_path // for sliceable food. path of the item resulting from the slicing
var/slices_num
var/eatverb
var/dried_type = null
var/dry = 0
var/dunk_amount = 10 // how much reagent is transferred per dunk
var/cooked_type = null //for microwave cooking. path of the resulting item after microwaving
var/filling_color = "#FFFFFF" //color to use when added to custom food.
var/custom_food_type = null //for food customizing. path of the custom food to create
var/junkiness = 0 //for junk food. used to lower human satiety.
var/list/bonus_reagents //the amount of reagents (usually nutriment and vitamin) added to crafted/cooked snacks, on top of the ingredients reagents.
var/customfoodfilling = 1 // whether it can be used as filling in custom food
var/list/tastes // for example list("crisps" = 2, "salt" = 1)
//Placeholder for effect that trigger on eating that aren't tied to reagents.
/obj/item/reagent_containers/food/snacks/add_initial_reagents()
if(tastes && tastes.len)
if(list_reagents)
for(var/rid in list_reagents)
var/amount = list_reagents[rid]
if(rid == /datum/reagent/consumable/nutriment || rid == /datum/reagent/consumable/nutriment/vitamin)
reagents.add_reagent(rid, amount, tastes.Copy())
else
reagents.add_reagent(rid, amount)
else
..()
/obj/item/reagent_containers/food/snacks/proc/On_Consume(mob/living/eater)
if(!eater)
return
if(!reagents.total_volume)
var/mob/living/location = loc
var/obj/item/trash_item = generate_trash(location)
qdel(src)
if(istype(location))
location.put_in_hands(trash_item)
/obj/item/reagent_containers/food/snacks/attack_self(mob/user)
return
/obj/item/reagent_containers/food/snacks/attack(mob/living/M, mob/living/user, def_zone)
if(user.a_intent == INTENT_HARM)
return ..()
if(!eatverb)
eatverb = pick("bite","chew","nibble","gnaw","gobble","chomp")
if(!reagents.total_volume) //Shouldn't be needed but it checks to see if it has anything left in it.
to_chat(user, "<span class='warning'>None of [src] left, oh no!</span>")
qdel(src)
return FALSE
if(iscarbon(M))
if(!canconsume(M, user))
return FALSE
var/fullness = M.nutrition + 10
for(var/datum/reagent/consumable/C in M.reagents.reagent_list) //we add the nutrition value of what we're currently digesting
fullness += C.nutriment_factor * C.volume / C.metabolization_rate
if(M == user) //If you're eating it yourself.
if(junkiness && M.satiety < -150 && M.nutrition > NUTRITION_LEVEL_STARVING + 50 && !HAS_TRAIT(user, TRAIT_VORACIOUS))
to_chat(M, "<span class='warning'>You don't feel like eating any more junk food at the moment!</span>")
return FALSE
else if(fullness <= 50)
user.visible_message("<span class='notice'>[user] hungrily [eatverb]s \the [src], gobbling it down!</span>", "<span class='notice'>You hungrily [eatverb] \the [src], gobbling it down!</span>")
else if(fullness > 50 && fullness < 150)
user.visible_message("<span class='notice'>[user] hungrily [eatverb]s \the [src].</span>", "<span class='notice'>You hungrily [eatverb] \the [src].</span>")
else if(fullness > 150 && fullness < 500)
user.visible_message("<span class='notice'>[user] [eatverb]s \the [src].</span>", "<span class='notice'>You [eatverb] \the [src].</span>")
else if(fullness > 500 && fullness < 600)
user.visible_message("<span class='notice'>[user] unwillingly [eatverb]s a bit of \the [src].</span>", "<span class='notice'>You unwillingly [eatverb] a bit of \the [src].</span>")
else if(fullness > (600 * (1 + M.overeatduration / 2000))) // The more you eat - the more you can eat
user.visible_message("<span class='warning'>[user] cannot force any more of \the [src] to go down [user.p_their()] throat!</span>", "<span class='warning'>You cannot force any more of \the [src] to go down your throat!</span>")
return FALSE
if(HAS_TRAIT(M, TRAIT_VORACIOUS))
M.changeNext_move(CLICK_CD_MELEE * 0.5) //nom nom nom
else
if(!isbrain(M)) //If you're feeding it to someone else.
if(fullness <= (600 * (1 + M.overeatduration / 1000)))
M.visible_message("<span class='danger'>[user] attempts to feed [M] [src].</span>", \
"<span class='userdanger'>[user] attempts to feed you [src].</span>")
else
M.visible_message("<span class='warning'>[user] cannot force any more of [src] down [M]'s throat!</span>", \
"<span class='warning'>[user] cannot force any more of [src] down your throat!</span>")
return FALSE
if(!do_mob(user, M))
return
log_combat(user, M, "fed", reagents.log_list())
M.visible_message("<span class='danger'>[user] forces [M] to eat [src]!</span>", \
"<span class='userdanger'>[user] forces you to eat [src]!</span>")
else
to_chat(user, "<span class='warning'>[M] doesn't seem to have a mouth!</span>")
return
if(reagents) //Handle ingestion of the reagent.
if(M.satiety > -200)
M.satiety -= junkiness
playsound(M.loc,'sound/items/eatfood.ogg', rand(10,50), TRUE)
if(reagents.total_volume)
SEND_SIGNAL(src, COMSIG_FOOD_EATEN, M, user)
var/fraction = min(bitesize / reagents.total_volume, 1)
reagents.trans_to(M, bitesize, transfered_by = user, method = INGEST)
bitecount++
On_Consume(M)
checkLiked(fraction, M)
return TRUE
return 0
/obj/item/reagent_containers/food/snacks/examine(mob/user)
. = ..()
if(!in_container)
switch (bitecount)
if (0)
return
if(1)
. += "[src] was bitten by someone!"
if(2,3)
. += "[src] was bitten [bitecount] times!"
else
. += "[src] was bitten multiple times!"
/obj/item/reagent_containers/food/snacks/attackby(obj/item/W, mob/user, params)
if(istype(W, /obj/item/storage))
..() // -> item/attackby()
return 0
if(istype(W, /obj/item/reagent_containers/food/snacks))
var/obj/item/reagent_containers/food/snacks/S = W
if(custom_food_type && ispath(custom_food_type))
if(S.w_class > WEIGHT_CLASS_SMALL)
to_chat(user, "<span class='warning'>[S] is too big for [src]!</span>")
return 0
if(!S.customfoodfilling || istype(W, /obj/item/reagent_containers/food/snacks/customizable) || istype(W, /obj/item/reagent_containers/food/snacks/pizzaslice/custom) || istype(W, /obj/item/reagent_containers/food/snacks/cakeslice/custom))
to_chat(user, "<span class='warning'>[src] can't be filled with [S]!</span>")
return 0
if(contents.len >= 20)
to_chat(user, "<span class='warning'>You can't add more ingredients to [src]!</span>")
return 0
var/obj/item/reagent_containers/food/snacks/customizable/C = new custom_food_type(get_turf(src))
C.initialize_custom_food(src, S, user)
return 0
var/sharp = W.get_sharpness()
if(sharp)
if(slice(sharp, W, user))
return 1
else
..()
//Called when you finish tablecrafting a snack.
/obj/item/reagent_containers/food/snacks/CheckParts(list/parts_list, datum/crafting_recipe/food/R)
..()
reagents.clear_reagents()
for(var/obj/item/reagent_containers/RC in contents)
RC.reagents.trans_to(reagents, RC.reagents.maximum_volume)
if(istype(R))
contents_loop:
for(var/A in contents)
for(var/B in R.real_parts)
if(istype(A, B))
continue contents_loop
qdel(A)
SSblackbox.record_feedback("tally", "food_made", 1, type)
if(bonus_reagents && bonus_reagents.len)
for(var/r_id in bonus_reagents)
var/amount = bonus_reagents[r_id]
if(r_id == /datum/reagent/consumable/nutriment || r_id == /datum/reagent/consumable/nutriment/vitamin)
reagents.add_reagent(r_id, amount, tastes)
else
reagents.add_reagent(r_id, amount)
/obj/item/reagent_containers/food/snacks/proc/slice(accuracy, obj/item/W, mob/user)
if((slices_num <= 0 || !slices_num) || !slice_path) //is the food sliceable?
return FALSE
if ( \
!isturf(src.loc) || \
!(locate(/obj/structure/table) in src.loc) && \
!(locate(/obj/structure/table/optable) in src.loc) && \
!(locate(/obj/item/storage/bag/tray) in src.loc) \
)
to_chat(user, "<span class='warning'>You cannot slice [src] here! You need a table or at least a tray.</span>")
return FALSE
user.visible_message("[user] slices [src].", "<span class='notice'>You slice [src].</span>")
var/reagents_per_slice = reagents.total_volume/slices_num
for(var/i in 1 to slices_num)
var/obj/item/reagent_containers/food/snacks/slice = new slice_path (loc)
initialize_slice(slice, reagents_per_slice)
qdel(src)
return TRUE
/obj/item/reagent_containers/food/snacks/proc/initialize_slice(obj/item/reagent_containers/food/snacks/slice, reagents_per_slice)
slice.create_reagents(slice.volume)
reagents.trans_to(slice,reagents_per_slice)
if(name != initial(name))
slice.name = "slice of [name]"
if(desc != initial(desc))
slice.desc = "[desc]"
if(foodtype != initial(foodtype))
slice.foodtype = foodtype //if something happens that overrode our food type, make sure the slice carries that over
/obj/item/reagent_containers/food/snacks/proc/generate_trash(atom/location)
if(trash)
if(ispath(trash, /obj/item))
. = new trash(location)
trash = null
return
else if(isitem(trash))
var/obj/item/trash_item = trash
trash_item.forceMove(location)
. = trash
trash = null
return
/obj/item/reagent_containers/food/snacks/proc/update_snack_overlays(obj/item/reagent_containers/food/snacks/S)
cut_overlays()
var/mutable_appearance/filling = mutable_appearance(icon, "[initial(icon_state)]_filling")
if(S.filling_color == "#FFFFFF")
filling.color = pick("#FF0000","#0000FF","#008000","#FFFF00")
else
filling.color = S.filling_color
add_overlay(filling)
// initialize_cooked_food() is called when microwaving the food
/obj/item/reagent_containers/food/snacks/proc/initialize_cooked_food(obj/item/reagent_containers/food/snacks/S, cooking_efficiency = 1)
S.create_reagents(S.volume)
if(reagents)
reagents.trans_to(S, reagents.total_volume)
if(S.bonus_reagents && S.bonus_reagents.len)
for(var/r_id in S.bonus_reagents)
var/amount = S.bonus_reagents[r_id] * cooking_efficiency
if(r_id == /datum/reagent/consumable/nutriment || r_id == /datum/reagent/consumable/nutriment/vitamin)
S.reagents.add_reagent(r_id, amount, tastes)
else
S.reagents.add_reagent(r_id, amount)
/obj/item/reagent_containers/food/snacks/microwave_act(obj/machinery/microwave/M)
var/turf/T = get_turf(src)
var/obj/item/result
if(cooked_type)
result = new cooked_type(T)
if(istype(M))
initialize_cooked_food(result, M.efficiency)
else
initialize_cooked_food(result, 1)
SSblackbox.record_feedback("tally", "food_made", 1, result.type)
else
result = new /obj/item/reagent_containers/food/snacks/badrecipe(T)
if(istype(M) && M.dirty < 100)
M.dirty++
qdel(src)
return result
/obj/item/reagent_containers/food/snacks/Destroy()
if(contents)
for(var/atom/movable/something in contents)
something.forceMove(drop_location())
return ..()
/obj/item/reagent_containers/food/snacks/attack_animal(mob/M)
if(isanimal(M))
if(isdog(M))
var/mob/living/L = M
if(bitecount == 0 || prob(50))
M.manual_emote("nibbles away at \the [src]")
bitecount++
L.taste(reagents) // why should carbons get all the fun?
if(bitecount >= 5)
var/sattisfaction_text = pick("burps from enjoyment", "yaps for more", "woofs twice", "looks at the area where \the [src] was")
if(sattisfaction_text)
M.emote(sattisfaction_text)
qdel(src)
// //////////////////////////////////////////////Store////////////////////////////////////////
/// All the food items that can store an item inside itself, like bread or cake.
/obj/item/reagent_containers/food/snacks/store
w_class = WEIGHT_CLASS_NORMAL
var/stored_item = 0
/obj/item/reagent_containers/food/snacks/store/attackby(obj/item/W, mob/user, params)
..()
if(W.w_class <= WEIGHT_CLASS_SMALL & !istype(W, /obj/item/reagent_containers/food/snacks)) //can't slip snacks inside, they're used for custom foods.
if(W.get_sharpness())
return 0
if(stored_item)
return 0
if(!iscarbon(user))
return 0
if(contents.len >= 20)
to_chat(user, "<span class='warning'>[src] is full.</span>")
return 0
to_chat(user, "<span class='notice'>You slip [W] inside [src].</span>")
user.transferItemToLoc(W, src)
add_fingerprint(user)
contents += W
stored_item = 1
return 1 // no afterattack here
/obj/item/reagent_containers/food/snacks/MouseDrop(atom/over)
var/turf/T = get_turf(src)
var/obj/structure/table/TB = locate(/obj/structure/table) in T
if(TB)
TB.MouseDrop(over)
else
return ..()