diff --git a/code/modules/food_and_drinks/kitchen_machinery/cooker.dm b/code/modules/food_and_drinks/kitchen_machinery/cooker.dm index 5df528da14b..db54faf3631 100644 --- a/code/modules/food_and_drinks/kitchen_machinery/cooker.dm +++ b/code/modules/food_and_drinks/kitchen_machinery/cooker.dm @@ -20,6 +20,10 @@ ///Set to TRUE if the machine supports upgrades / deconstruction, or else it will ignore stuff like screwdrivers and parts exchangers var/upgradeable = FALSE var/datum/looping_sound/kitchen/deep_fryer/soundloop + /// Time between special attacks + var/special_attack_cooldown_time = 5 SECONDS + /// Whether or not a special attack can be performed right now + var/special_attack_on_cooldown = FALSE /obj/machinery/cooker/Initialize(mapload) . = ..() @@ -45,13 +49,69 @@ /obj/machinery/cooker/proc/setRegents(obj/item/reagent_containers/OldReg, obj/item/reagent_containers/NewReg) OldReg.reagents.trans_to(NewReg, OldReg.reagents.total_volume) +/** + * Perform the special grab interaction. + * Return TRUE to drop the grab or FALSE to keep the grab afterwards. + */ +/obj/machinery/cooker/proc/special_attack(mob/user, mob/living/carbon/target, obj/item/grab/G) + to_chat(user, "This is ridiculous. You can not fit [target] in this [src].") + return FALSE + +/obj/machinery/cooker/shove_impact(mob/living/target, mob/living/attacker) + if(special_attack_on_cooldown) + return FALSE + + if(!on) + // only do a special interaction if it's actually cooking something + return FALSE + + . = special_attack_shove(target, attacker) + addtimer(VARSET_CALLBACK(src, special_attack_on_cooldown, FALSE), special_attack_cooldown_time) + +/** + * Perform a special shove attack. + * The return value of this proc gets passed up to shove_impact, so returning TRUE will prevent any further shove handling (like knockdown). + */ +/obj/machinery/cooker/proc/special_attack_shove(mob/living/target, mob/living/attacker) + return FALSE + +/** + * Verify if we would be able to perform our grab attack. + */ +/obj/machinery/cooker/proc/can_grab_attack(obj/item/grab/G, mob/user, verbose = FALSE) + if(special_attack_on_cooldown) + return FALSE + if(!istype(G)) + return FALSE + if(!iscarbon(G.affecting)) + if(verbose) + to_chat(user, "You can't shove that in there!") + return FALSE + if(G.state < GRAB_AGGRESSIVE) + if(verbose) + to_chat(user, "You need a better grip to do that!") + return FALSE + return TRUE + +/obj/machinery/cooker/proc/special_attack_grab(obj/item/grab/G, mob/user) + if(!can_grab_attack(G, user, FALSE)) // do it silently, but still make sure this isn't called without sanity checking first + return FALSE + var/result = special_attack(user, G.affecting, G) + user.changeNext_move(CLICK_CD_MELEE) + special_attack_on_cooldown = TRUE + addtimer(VARSET_CALLBACK(src, special_attack_on_cooldown, FALSE), special_attack_cooldown_time) + if(result && !isnull(G) && !QDELETED(G)) + qdel(G) + + return TRUE // end the attack chain + // check if you can put it in the machine /obj/machinery/cooker/proc/checkValid(obj/item/check, mob/user) if(on) to_chat(user, "[src] is still active!") return FALSE if(istype(check, /obj/item/grab)) - return special_attack(check, user) + return can_grab_attack(check, user, TRUE) // tell the user here if(has_specials && checkSpecials(check)) return TRUE if(istype(check, /obj/item/reagent_containers/food/snacks) || emagged) @@ -147,6 +207,8 @@ else L.death() break + if(istype(I, /obj/item/grab)) + return special_attack_grab(I, user) addtimer(CALLBACK(src, PROC_REF(finish_cook), I, user), cooktime) /obj/machinery/cooker/proc/finish_cook(obj/item/I, mob/user, params) @@ -190,11 +252,6 @@ if(default_deconstruction_screwdriver(user, openicon, officon, I)) return TRUE - - -/obj/machinery/cooker/proc/special_attack(obj/item/grab/G, mob/user) - return 0 - // MAKE SURE TO OVERRIDE THESE ON THE MACHINE IF IT HAS SPECIAL FOOD INTERACTIONS! // FAILURE TO OVERRIDE WILL RESULT IN FAILURE TO PROPERLY HANDLE SPECIAL INTERACTIONS! --FalseIncarnate /obj/machinery/cooker/proc/checkSpecials(obj/item/I) diff --git a/code/modules/food_and_drinks/kitchen_machinery/deep_fryer.dm b/code/modules/food_and_drinks/kitchen_machinery/deep_fryer.dm index 361051f3e8d..fff98c5a86e 100644 --- a/code/modules/food_and_drinks/kitchen_machinery/deep_fryer.dm +++ b/code/modules/food_and_drinks/kitchen_machinery/deep_fryer.dm @@ -84,26 +84,33 @@ emagged = TRUE return -/obj/machinery/cooker/deepfryer/special_attack(obj/item/grab/G, mob/user) - if(ishuman(G.affecting)) - if(G.state < GRAB_AGGRESSIVE) - to_chat(user, "You need a better grip to do that!") - return 0 - var/mob/living/carbon/human/C = G.affecting - var/obj/item/organ/external/head/head = C.get_organ("head") - if(!istype(head)) - to_chat(user, "This person doesn't have a head!") - return 0 - C.visible_message("[user] dunks [C]'s face into [src]!", \ - "[user] dunks your face into [src]!") - C.emote("scream") - user.changeNext_move(CLICK_CD_MELEE) - C.apply_damage(25, BURN, "head") //25 fire damage and disfigurement because your face was just deep fried! - head.disfigure() - add_attack_logs(user, G.affecting, "Deep-fried with [src]") - qdel(G) //Removes the grip so the person MIGHT have a small chance to run the fuck away and to prevent rapid dunks. - return 0 - return 0 +/obj/machinery/cooker/deepfryer/special_attack_shove(mob/living/target, mob/living/attacker) + target.visible_message( + "[attacker] shoves [target] against [src], and [target] reaches into the hot oil trying to catch [target.p_their()] fall!", + "[attacker] shoves you into [src], your hands landing in hot oil!", + "You hear a splash and a loud sizzle." + ) + target.apply_damage(10, BURN, BODY_ZONE_PRECISE_L_HAND) + target.apply_damage(10, BURN, BODY_ZONE_PRECISE_R_HAND) + playsound(src, 'sound/goonstation/misc/drinkfizz.ogg', 25) + return FALSE + +/obj/machinery/cooker/deepfryer/special_attack(mob/user, mob/living/carbon/target) + var/obj/item/organ/external/head/head = target.get_organ("head") + if(!istype(head)) + to_chat(user, "This person doesn't have a head!") + return FALSE // you'll probably get smacked against it + target.visible_message( + "[user] dunks [target]'s face into [src]!", + "[user] dunks your face into [src]!", + "You hear a splash and a loud sizzle." + ) + playsound(src, "sound/machines/kitchen/deep_fryer_emerge.ogg", 100) + target.emote("scream") + target.apply_damage(45, BURN, "head") // 45 fire damage and disfigurement because your face was just deep fried! + head.disfigure() + add_attack_logs(user, target, "Deep-fried with [src]") + return TRUE /// Make foam consisting of burning oil. /obj/machinery/cooker/deepfryer/proc/make_foam(ice_amount) diff --git a/code/modules/food_and_drinks/kitchen_machinery/grill_new.dm b/code/modules/food_and_drinks/kitchen_machinery/grill_new.dm index 9234a1c535a..d44d9e3caad 100644 --- a/code/modules/food_and_drinks/kitchen_machinery/grill_new.dm +++ b/code/modules/food_and_drinks/kitchen_machinery/grill_new.dm @@ -44,18 +44,24 @@ E += M.rating efficiency = round((E/2), 1) // There's 2 lasers, so halve the effect on the efficiency to keep it balanced -/obj/machinery/kitchen_machine/grill/special_attack(obj/item/grab/G, mob/user) - if(ishuman(G.affecting)) - if(G.state < GRAB_AGGRESSIVE) - to_chat(user, "You need a better grip to do that!") - return 0 - var/mob/living/carbon/human/C = G.affecting - C.visible_message("[user] forces [C] onto [src], searing [C]'s body!", \ - "[user] forces you onto [src]! It burns!") - C.emote("scream") - user.changeNext_move(CLICK_CD_MELEE) - C.adjustFireLoss(30) - add_attack_logs(user, G.affecting, "Burned with [src]") - qdel(G) //Removes the grip to prevent rapid sears and give you a chance to run - return 0 - return 0 +/obj/machinery/kitchen_machine/grill/special_attack_shove(mob/user, mob/living/carbon/target) + target.visible_message( + "[user] shoves [target] onto [src], the active grill surface searing [user.p_them()]!", + "[user] shoves you onto [src], and the hot surface sears you!", + ) + target.adjustFireLoss(15) + +/obj/machinery/kitchen_machine/grill/special_attack(mob/user, mob/living/carbon/target, from_grab) + target.visible_message( + "[user] forces [target] onto [src]'s hot cooking surface, searing [target]'s body!", + "[user] forces you onto [src]! HOT HOT HOT!", + "You hear some meat being put on to cook." + ) + + target.emote("scream") + playsound(src, "sound/machines/kitchen/grill_mid.ogg", 100) + target.adjustFireLoss(30) + target.forceMove(get_turf(src)) + target.Weaken(2 SECONDS) + add_attack_logs(user, target, "Burned with [src]") + return TRUE diff --git a/code/modules/food_and_drinks/kitchen_machinery/kitchen_machine.dm b/code/modules/food_and_drinks/kitchen_machinery/kitchen_machine.dm index 1c8eb739f9a..28298addbb6 100644 --- a/code/modules/food_and_drinks/kitchen_machinery/kitchen_machine.dm +++ b/code/modules/food_and_drinks/kitchen_machinery/kitchen_machine.dm @@ -25,6 +25,10 @@ ///Sound used when starting and ending cooking var/datum/looping_sound/kitchen/soundloop var/soundloop_type + /// Time between special attacks + var/special_attack_cooldown_time = 7 SECONDS + /// Whether or not a special attack can be performed right now + var/special_attack_on_cooldown = FALSE /******************* * Initialising @@ -111,8 +115,9 @@ if(!(R.id in GLOB.cooking_reagents[recipe_type])) to_chat(user, "Your [O] contains components unsuitable for cookery.") return TRUE - else if(istype(O,/obj/item/grab)) - return special_attack(O, user) + else if(istype(O, /obj/item/grab)) + var/obj/item/grab/G = O + return special_attack_grab(G, user) else to_chat(user, "You have no idea what you can cook with [O].") return TRUE @@ -141,8 +146,49 @@ /obj/machinery/kitchen_machine/attack_ai(mob/user) return FALSE -/obj/machinery/kitchen_machine/proc/special_attack(obj/item/grab/G, mob/user) - to_chat(user, "This is ridiculous. You can not fit [G.affecting] in this [src].") +/obj/machinery/kitchen_machine/proc/special_attack_grab(obj/item/grab/G, mob/user) + if(special_attack_on_cooldown) + return FALSE + if(!istype(G)) + return FALSE + if(!iscarbon(G.affecting)) + to_chat(user, "You can't shove that in there!") + return FALSE + if(G.state < GRAB_AGGRESSIVE) + to_chat(user, "You need a better grip to do that!") + return FALSE + var/result = special_attack(user, G.affecting, TRUE) + user.changeNext_move(CLICK_CD_MELEE) + special_attack_on_cooldown = TRUE + addtimer(VARSET_CALLBACK(src, special_attack_on_cooldown, FALSE), special_attack_cooldown_time) + if(result && !isnull(G) && !QDELETED(G)) + qdel(G) + + return TRUE + +/** + * Perform the special grab interaction. + * Return TRUE to drop the grab or FALSE to keep the grab afterwards. + */ +/obj/machinery/kitchen_machine/proc/special_attack(mob/user, mob/living/carbon/target, obj/item/grab/G) + to_chat(user, "This is ridiculous. You can not fit [target] in this [src].") + return FALSE + +/obj/machinery/kitchen_machine/shove_impact(mob/living/target, mob/living/attacker) + if(special_attack_on_cooldown) + return FALSE + + if(!operating) + // only do a special interaction if it's actually cooking something + return FALSE + + return special_attack_shove(target, attacker) + +/** + * Perform a special shove attack. + * The return value of this proc gets passed up to shove_impact, so returning TRUE will prevent any further shove handling (like knockdown). + */ +/obj/machinery/kitchen_machine/proc/special_attack_shove(mob/living/target, mob/living/attacker) return FALSE /******************** diff --git a/code/modules/food_and_drinks/kitchen_machinery/oven_new.dm b/code/modules/food_and_drinks/kitchen_machinery/oven_new.dm index ecf8850c546..6abaa5d8d0d 100644 --- a/code/modules/food_and_drinks/kitchen_machinery/oven_new.dm +++ b/code/modules/food_and_drinks/kitchen_machinery/oven_new.dm @@ -44,24 +44,17 @@ E += M.rating efficiency = round((E/2), 1) // There's 2 lasers, so halve the effect on the efficiency to keep it balanced -/obj/machinery/kitchen_machine/oven/special_attack(obj/item/grab/G, mob/user) - if(ishuman(G.affecting)) - if(G.state < GRAB_AGGRESSIVE) - to_chat(user, "You need a better grip to do that!") - return 0 - var/mob/living/carbon/human/C = G.affecting - var/obj/item/organ/external/head/head = C.get_organ("head") - if(!istype(head)) - to_chat(user, "This person doesn't have a head!") - return 0 - C.visible_message("[user] bashes [C]'s head in [src]'s door!", \ - "[user] bashes your head in [src]'s door! It feels rather hot in the oven!") - C.emote("scream") - user.changeNext_move(CLICK_CD_MELEE) - C.apply_damage(5, BURN, "head") //5 fire damage, 15 brute damage, and weakening because your head was just in a hot oven with the door bashing into your neck! - C.apply_damage(15, BRUTE, "head") - C.Weaken(4 SECONDS) - add_attack_logs(user, G.affecting, "Smashed with [src]") - qdel(G) //Removes the grip to prevent rapid bashes. With the weaken, you PROBABLY can't run unless they are slow to grab you again... - return 0 - return 0 +/obj/machinery/kitchen_machine/oven/special_attack(mob/user, mob/living/target) + var/obj/item/organ/external/head/head = target.get_organ("head") + if(!istype(head)) + to_chat(user, "This person doesn't have a head!") + return FALSE + target.visible_message("[user] bashes [target]'s head in [src]'s door!", \ + "[user] bashes your head in [src]'s door! It feels rather hot in the oven!") + target.apply_damage(25, BURN, "head") //5 fire damage, 15 brute damage, and weakening because your head was just in a hot oven with the door bashing into your neck! + target.apply_damage(25, BRUTE, "head") + target.Weaken(4 SECONDS) // With the weaken, you PROBABLY can't run unless they are slow to grab you again... + target.emote("scream") + playsound(src, "sound/machines/kitchen/oven_loop_end.ogg", 100) + add_attack_logs(user, target, "Smashed with [src]") + return TRUE