diff --git a/code/game/objects/structures/watercloset.dm b/code/game/objects/structures/watercloset.dm index e7decd0e285..29630bd481f 100644 --- a/code/game/objects/structures/watercloset.dm +++ b/code/game/objects/structures/watercloset.dm @@ -482,7 +482,7 @@ var/empty_amount = RG.reagents.trans_to(src, RG.amount_per_transfer_from_this) var/max_reagents = RG.reagents.maximum_volume user.visible_message("[user] empties [empty_amount == max_reagents ? "all of \the [RG]" : "some of \the [RG]"] into \a [src].") - playsound(src.loc, 'sound/effects/pour.ogg', 10, 1) + playsound(src.loc, /decl/sound_category/generic_pour_sound, 10, 1) return // Filling/empying Syringes diff --git a/code/game/sound.dm b/code/game/sound.dm index 2b2cd4dc86b..33aef1d44a6 100644 --- a/code/game/sound.dm +++ b/code/game/sound.dm @@ -565,6 +565,12 @@ 'sound/items/wield/generic3.ogg' ) +/decl/sound_category/generic_pour_sound + sounds = list( + 'sound/effects/pour1.ogg', + 'sound/effects/pour2.ogg' + ) + /decl/sound_category/wield_generic_sound sounds = list( 'sound/items/wield/generic1.ogg', @@ -684,6 +690,22 @@ 'sound/weapons/laserstrong.ogg' ) +/decl/sound_category/shaker_shaking + sounds = list( + 'sound/items/shaking1.ogg', + 'sound/items/shaking2.ogg', + 'sound/items/shaking3.ogg', + 'sound/items/shaking4.ogg', + 'sound/items/shaking5.ogg', + 'sound/items/shaking6.ogg' + ) + +/decl/sound_category/shaker_lid_off + sounds = list( + 'sound/items/shaker_lid_off1.ogg', + 'sound/items/shaker_lid_off2.ogg' + ) + /decl/sound_category/quick_arcade // quick punchy arcade sounds sounds = list( 'sound/arcade/get_fuel.ogg', diff --git a/code/modules/reagents/Chemistry-Recipes.dm b/code/modules/reagents/Chemistry-Recipes.dm index 64600d22771..5413af640be 100644 --- a/code/modules/reagents/Chemistry-Recipes.dm +++ b/code/modules/reagents/Chemistry-Recipes.dm @@ -1720,7 +1720,7 @@ result = /decl/reagent/alcohol/goldschlager required_reagents = list(/decl/reagent/alcohol/vodka = 10, /decl/reagent/gold = 1) mix_message = null - reaction_sound = 'sound/effects/pour.ogg' + reaction_sound = /decl/sound_category/generic_pour_sound result_amount = 10 /datum/chemical_reaction/drink/patron diff --git a/code/modules/reagents/reagent_containers.dm b/code/modules/reagents/reagent_containers.dm index 6943e5be562..57c622a178b 100644 --- a/code/modules/reagents/reagent_containers.dm +++ b/code/modules/reagents/reagent_containers.dm @@ -306,6 +306,9 @@ return 1 var/trans = reagents.trans_to(target, amount_per_transfer_from_this) - playsound(src, 'sound/effects/pour.ogg', 25, 1) to_chat(user, "You transfer [trans] units of the solution to [target].") + on_pour() return 1 + +/obj/item/reagent_containers/proc/on_pour() + playsound(src, /decl/sound_category/generic_pour_sound, 25, 1) \ No newline at end of file diff --git a/code/modules/reagents/reagent_containers/borghydro.dm b/code/modules/reagents/reagent_containers/borghydro.dm index bf61cccaa35..9ad4122566d 100644 --- a/code/modules/reagents/reagent_containers/borghydro.dm +++ b/code/modules/reagents/reagent_containers/borghydro.dm @@ -1,6 +1,9 @@ /obj/item/reagent_containers/hypospray/borghypo name = "cyborg hypospray" desc = "An advanced chemical synthesizer and injection system, designed for heavy-duty medical equipment." + desc_info = "Stationbound synthesizers produce specific reagents dependent on the selected module, which you can select by using it. \ + The reagents recharge automatically at the cost of energy.
Alt Click the synthesizer to change the transfer amount." + desc_fluff = null icon = 'icons/obj/syringe.dmi' item_state = "hypo" icon_state = "borghypo" @@ -33,9 +36,10 @@ var/decl/reagent/R = decls_repository.get_decl(T) reagent_names += R.name + update_icon() START_PROCESSING(SSprocessing, src) -/obj/item/reagent_containers/hypospray/borghypo/update_icon() +/obj/item/reagent_containers/hypospray/borghypo/update_icon() // To do: Will work on the Medical Synthesizer in a future PR -Vrow return /obj/item/reagent_containers/hypospray/borghypo/Destroy() @@ -54,6 +58,7 @@ if(reagent_volumes[T] < volume) R.cell.use(charge_cost) reagent_volumes[T] = min(reagent_volumes[T] + 5, volume) + update_icon() return 1 /obj/item/reagent_containers/hypospray/borghypo/inject(var/mob/living/M, var/mob/user, proximity) @@ -61,18 +66,19 @@ return if(!reagent_volumes[reagent_ids[mode]]) - to_chat(user,"The injector is empty.") + to_chat(user, SPAN_WARNING("The injector is empty.")) return - - user.visible_message("[user] injects [M] with their hypospray!", "You inject [M] with your hypospray!", "You hear a hissing noise.") - to_chat(M,"You feel a tiny prick!") + + user.visible_message(SPAN_NOTICE("[user] injects [M] with their hypospray!"), SPAN_NOTICE("You inject [M] with your hypospray!"), SPAN_NOTICE("You hear a hissing noise.")) + to_chat(M, SPAN_NOTICE("You feel a tiny prick!")) if(M.reagents) var/t = min(amount_per_transfer_from_this, reagent_volumes[reagent_ids[mode]]) M.reagents.add_reagent(reagent_ids[mode], t) reagent_volumes[reagent_ids[mode]] -= t admin_inject_log(user, M, src, reagent_ids[mode], reagents.get_temperature(), t) - to_chat(user,"[t] units injected. [reagent_volumes[reagent_ids[mode]]] units remaining.") + to_chat(user, SPAN_NOTICE("[t] units injected. [reagent_volumes[reagent_ids[mode]]] units remaining.")) + update_icon() return /obj/item/reagent_containers/hypospray/borghypo/afterattack(atom/target, mob/user, proximity) @@ -103,27 +109,47 @@ playsound(loc, 'sound/effects/pop.ogg', 50, 0) mode = t var/decl/reagent/R = decls_repository.get_decl(reagent_ids[mode]) - to_chat(usr, "Synthesizer is now producing '[R.name]'.") + to_chat(usr, SPAN_NOTICE("Synthesizer is now producing '[R.name]'.")) + update_icon() /obj/item/reagent_containers/hypospray/borghypo/examine(mob/user) if(!..(user, 2)) return var/decl/reagent/R = decls_repository.get_decl(reagent_ids[mode]) - - to_chat(user, "It is currently producing [R.name] and has [reagent_volumes[reagent_ids[mode]]] out of [volume] units left.") + to_chat(user, SPAN_NOTICE("It is currently producing [R.name] and has [reagent_volumes[reagent_ids[mode]]] out of [volume] units left.")) /obj/item/reagent_containers/hypospray/borghypo/service name = "cyborg drink synthesizer" - desc = "A portable drink dispenser." - icon = 'icons/obj/drinks.dmi' - icon_state = "shaker" + desc = "A portable drink synthesizer and dispenser." + icon = 'icons/obj/shaker.dmi' + icon_state = "drink_synth" charge_cost = 20 recharge_time = 3 volume = 60 possible_transfer_amounts = list(5, 10, 20, 30) reagent_ids = list(/decl/reagent/alcohol/beer, /decl/reagent/alcohol/coffee/kahlua, /decl/reagent/alcohol/whiskey, /decl/reagent/alcohol/wine, /decl/reagent/alcohol/vodka, /decl/reagent/alcohol/gin, /decl/reagent/alcohol/rum, /decl/reagent/alcohol/tequila, /decl/reagent/alcohol/vermouth, /decl/reagent/alcohol/cognac, /decl/reagent/alcohol/ale, /decl/reagent/alcohol/mead, /decl/reagent/water, /decl/reagent/sugar, /decl/reagent/drink/ice, /decl/reagent/drink/tea, /decl/reagent/drink/icetea, /decl/reagent/drink/space_cola, /decl/reagent/drink/spacemountainwind, /decl/reagent/drink/dr_gibb, /decl/reagent/drink/spaceup, /decl/reagent/drink/tonic, /decl/reagent/drink/sodawater, /decl/reagent/drink/lemon_lime, /decl/reagent/drink/orangejuice, /decl/reagent/drink/limejuice, /decl/reagent/drink/watermelonjuice, /decl/reagent/drink/coffee, /decl/reagent/drink/coffee/espresso) +/obj/item/reagent_containers/hypospray/borghypo/service/update_icon() + underlays.Cut() + cut_overlays() + + var/rid = reagent_ids[mode] + var/decl/reagent/R = decls_repository.get_decl(rid) + if(reagent_volumes[rid]) + var/mutable_appearance/filling = mutable_appearance('icons/obj/shaker.dmi', "[icon_state]-0") + var/percent = round((reagent_volumes[rid] / volume) * 100) + switch(percent) + if(0 to 9) filling.icon_state = "[icon_state]-0" + if(10 to 19) filling.icon_state = "[icon_state]-10" + if(20 to 39) filling.icon_state = "[icon_state]-20" + if(40 to 59) filling.icon_state = "[icon_state]-40" + if(60 to 79) filling.icon_state = "[icon_state]-60" + if(80 to 90) filling.icon_state = "[icon_state]-80" + if(91 to INFINITY) filling.icon_state = "[icon_state]-100" + filling.color = R.get_color() + add_overlay(filling) + /obj/item/reagent_containers/hypospray/borghypo/service/attack(var/mob/M, var/mob/user) return @@ -135,11 +161,11 @@ return if(!reagent_volumes[reagent_ids[mode]]) - to_chat(user, "[src] is out of this reagent, give it some time to refill.") + to_chat(user, SPAN_NOTICE("[src] is out of this reagent, give it some time to refill.")) return if(!REAGENTS_FREE_SPACE(target.reagents)) - to_chat(user, "[target] is full.") + to_chat(user, SPAN_NOTICE("[target] is full.")) return var/rid = reagent_ids[mode] @@ -148,5 +174,16 @@ var/amt = min(amount_per_transfer_from_this, reagent_volumes[rid]) target.reagents.add_reagent(rid, amt, temperature = temp) reagent_volumes[rid] -= amt - to_chat(user, "You transfer [amt] units of the solution to [target].") + to_chat(user, SPAN_NOTICE("You transfer [amt] units of [R.name] to [target].")) + playsound(src.loc, /decl/sound_category/generic_pour_sound, 50, 1) + dispense() return + +/obj/item/reagent_containers/hypospray/borghypo/service/proc/dispense() + var/decl/reagent/R = decls_repository.get_decl(reagent_ids[mode]) + var/mutable_appearance/reagent_overlay = mutable_appearance('icons/obj/shaker.dmi', "disp") + reagent_overlay.color = R.get_color() + underlays += reagent_overlay + underlays += image('icons/obj/shaker.dmi', "[icon_state]-disp") + flick("disp-mask", src) + update_icon() \ No newline at end of file diff --git a/code/modules/reagents/reagent_containers/food/drinks.dm b/code/modules/reagents/reagent_containers/food/drinks.dm index 612e9835d4a..f09e6bce3d2 100644 --- a/code/modules/reagents/reagent_containers/food/drinks.dm +++ b/code/modules/reagents/reagent_containers/food/drinks.dm @@ -427,20 +427,184 @@ If you add a drink with no empty icon sprite, ensure it is flagged as NO_EMPTY_I /obj/item/reagent_containers/food/drinks/shaker name = "shaker" desc = "A metal shaker to mix drinks in." + desc_info = "Alt Click the shaker to twist the cap closed/loose. If the cap is loose, use the shaker to remove it. Without a cap, use the shaker again to remove the top. \ + If the shaker has a top fitted, you can Alt Click the shaker to change the transfer amount. Without a top, the transfer amount changes to max automatically." + icon = 'icons/obj/shaker.dmi' icon_state = "shaker" + item_state = "shaker" + contained_sprite = TRUE + filling_states = "10;25;50;75;80;100" unacidable = TRUE amount_per_transfer_from_this = 10 + possible_transfer_amounts = list(10, 30, 60) volume = 120 center_of_mass = list("x"=16, "y"=8) var/last_shake = 0 + var/twisted = FALSE + var/obj/item/shaker_top/top + var/obj/item/reagent_containers/food/drinks/shaker_cup/cap + +/obj/item/reagent_containers/food/drinks/shaker/Initialize() + . = ..() + top = new(src) + cap = new(src) + update_icon() + +/obj/item/reagent_containers/food/drinks/shaker/Destroy() + QDEL_NULL(top) + QDEL_NULL(cap) + return ..() + +/obj/item/reagent_containers/food/drinks/shaker/update_icon() + cut_overlays() + if(top) + icon_state = "shakertop" + item_state = "shakertop" + else + icon_state = initial(icon_state) + item_state = icon_state + if(reagents.total_volume) + var/mutable_appearance/filling = mutable_appearance('icons/obj/shaker.dmi', "[icon_state]-[get_filling_state()]") + filling.color = reagents.get_color() + add_overlay(filling) + if(cap) + add_overlay("shaker_cap") + update_held_icon() + +/obj/item/reagent_containers/food/drinks/shaker/AltClick(mob/user) + if(cap) + toggle_twist() + return + if(top) + set_APTFT() + return /obj/item/reagent_containers/food/drinks/shaker/attack_self(mob/user) + if(!twisted) + if(cap) + to_chat(user, SPAN_NOTICE("You remove \the [src]'s [cap].")) + user.put_in_hands(cap) + flags |= OPENCONTAINER + cap = null + playsound(src.loc, /decl/sound_category/shaker_lid_off, 50, 1) + update_icon() + return + if(top) + toggle_top() + return + to_chat(user, SPAN_WARNING("It would be a bad idea to shake it without it being closed.")) + return if(last_shake <= world.time - 10) //Spam limiter. last_shake = world.time - playsound(src.loc, 'sound/items/soda_shaking.ogg', 50, 1) + playsound(src.loc, /decl/sound_category/shaker_shaking, 50, 1) src.add_fingerprint(user) return +/obj/item/reagent_containers/food/drinks/shaker/attackby(obj/item/W, mob/user) + if(istype(W, /obj/item/reagent_containers/food/drinks/shaker_cup)) + if(cap) + to_chat(user, SPAN_WARNING("\The [src] already has \a [cap].")) + return TRUE + if(W.reagents.total_volume > 0) + var/obj/item/reagent_containers/food/drinks/shaker_cup/C = W + C.standard_pour_into(user, src) + return TRUE + if(!top) + to_chat(user, SPAN_WARNING("\The [src] lacks a top to fit \the [W] on.")) + return TRUE + to_chat(user, SPAN_NOTICE("You put \the [W] onto \the [src].")) + user.drop_from_inventory(W, src) + flags ^= OPENCONTAINER + cap = W + playsound(src.loc, /decl/sound_category/shaker_lid_off, 50, 1) + update_icon() + return TRUE + if(istype(W, /obj/item/shaker_top)) + if(top) + to_chat(user, SPAN_WARNING("\The [src] already has \a [top].")) + return TRUE + to_chat(user, SPAN_NOTICE("You fit \the [W] onto \the [src].")) + amount_per_transfer_from_this = 10 + user.drop_from_inventory(W, src) + top = W + playsound(src.loc, /decl/sound_category/shaker_lid_off, 50, 1) + update_icon() + return TRUE + return ..() + +/obj/item/reagent_containers/food/drinks/shaker/on_pour() + if(!top) + playsound(src, 'sound/effects/pour_big.ogg', 50, 1) + return + return ..() + +/obj/item/reagent_containers/food/drinks/shaker/verb/toggle_twist() + set category = "Object" + set name = "Twist Cap" + set src in usr + + if(!cap) + to_chat(usr, SPAN_WARNING("\The [src] doesn't have a cap!")) + return + twisted = !twisted + to_chat(usr, SPAN_NOTICE("You twist \the [cap] [twisted ? "closed for a tight seal" : "loose"].")) + update_icon() + +/obj/item/reagent_containers/food/drinks/shaker/verb/toggle_top() + set category = "Object" + set name = "Remove Top" + set src in usr + + if(cap) + to_chat(usr, SPAN_WARNING("You must remove \the [cap] first!")) + return + if(!top) + to_chat(usr, SPAN_WARNING("\The [src] doesn't have a top to remove!")) + return + to_chat(usr, SPAN_NOTICE("You remove \the [src]'s [top].")) + amount_per_transfer_from_this = 120 + usr.put_in_hands(top) + top = null + playsound(src.loc, /decl/sound_category/shaker_lid_off, 50, 1) + update_icon() + +/obj/item/shaker_top + name = "shaker top" + desc = "A metal shaker top with an in-built filter on the bottom." + desc_info = "When fitted on a shaker, you can Alt Click the shaker to change transfer amount of the shaker." + icon = 'icons/obj/shaker.dmi' + icon_state = "shaker_top" + item_state = "shaker_top" + contained_sprite = TRUE + drop_sound = 'sound/items/drop/bottle.ogg' + pickup_sound = null + center_of_mass = list("x" = 16, "y" = 16) + +/obj/item/reagent_containers/food/drinks/shaker_cup + name = "shaker cap" + desc = "A metal shaker cap that also doubles as a metal cup to measure liquids, or to drink from." + desc_info = "Alt Click the cap to change the transfer amount." + icon = 'icons/obj/shaker.dmi' + icon_state = "shaker_cup" + item_state = "shaker_cup" + contained_sprite = TRUE + filling_states = "50;100" + pickup_sound = null + volume = 10 + possible_transfer_amounts = list(1,2,3,4,5,10) + center_of_mass = list("x" = 16, "y" = 16) + +/obj/item/reagent_containers/food/drinks/shaker_cup/update_icon() + cut_overlays() + + if(reagents?.total_volume) + var/mutable_appearance/filling = mutable_appearance('icons/obj/shaker.dmi', "[icon_state]-[get_filling_state()]") + filling.color = reagents.get_color() + add_overlay(filling) + +/obj/item/reagent_containers/food/drinks/shaker_cup/AltClick(mob/user) + set_APTFT() + /obj/item/reagent_containers/food/drinks/teapot name = "teapot" desc = "An elegant teapot. It simply oozes class." @@ -503,11 +667,13 @@ If you add a drink with no empty icon sprite, ensure it is flagged as NO_EMPTY_I /obj/item/reagent_containers/food/drinks/flask/vacuumflask/Initialize() . = ..() cup = new(src) + flags ^= OPENCONTAINER /obj/item/reagent_containers/food/drinks/flask/vacuumflask/attack_self(mob/user) if(cup) to_chat(user, SPAN_NOTICE("You remove \the [src]'s cap.")) user.put_in_hands(cup) + flags |= OPENCONTAINER cup = null update_icon() @@ -517,10 +683,11 @@ If you add a drink with no empty icon sprite, ensure it is flagged as NO_EMPTY_I to_chat(user, SPAN_WARNING("\The [src] already has a cap.")) return TRUE if(W.reagents.total_volume + reagents.total_volume > volume) - to_chat(user, SPAN_WARNING("There's too much fluid in both the cap and the flask!")) + to_chat(user, SPAN_WARNING("There's too much fluid in both the cap and \the [src]!")) return TRUE to_chat(user, SPAN_NOTICE("You put the cap onto \the [src].")) user.drop_from_inventory(W, src) + flags ^= OPENCONTAINER cup = W cup.reagents.trans_to_holder(reagents, cup.reagents.total_volume) update_icon() diff --git a/code/modules/reagents/reagent_containers/food/snacks.dm b/code/modules/reagents/reagent_containers/food/snacks.dm index 24446cc93fd..214e6f1ab40 100644 --- a/code/modules/reagents/reagent_containers/food/snacks.dm +++ b/code/modules/reagents/reagent_containers/food/snacks.dm @@ -187,7 +187,7 @@ var/obj/item/material/kitchen/utensil/U = W if(istype(W,/obj/item/material/kitchen/utensil/fork)&&(is_liquid)) to_chat(user, SPAN_NOTICE("You uselessly pass \the [U] through \the [src].")) - playsound(user.loc, 'sound/effects/pour.ogg', 10, 1) + playsound(user.loc, /decl/sound_category/generic_pour_sound, 10, 1) return else if(U.scoop_food) diff --git a/html/changelogs/shaker_top_cap.yml b/html/changelogs/shaker_top_cap.yml new file mode 100644 index 00000000000..921758b0ad7 --- /dev/null +++ b/html/changelogs/shaker_top_cap.yml @@ -0,0 +1,13 @@ +author: Vrow, KingOfThePing + +delete-after: True + +changes: + - imagedel: "Removed old shaker sprite." + - imageadd: "Added a new shaker that is more metallic, with additional detachable top and cap, as well as in-hands for them." + - imageadd: "Added a unique new cyborg drink sythesizer sprite, with visible filling color so you can see what you have selected!" + - soundadd: "Added several shaking sounds for the shaker, removing the cap/top sounds, a big pour sound, and a new generic pouring sound." + - rscadd: "You can now remove the new shaker's top, and also the cap that doubles as a mini cup!" + - tweak: "The cyborg drink synthesizer now tells you what reagent you have just transferred to stuff." + - bugfix: "Fixed being able to pour stuff into a capped vacuum flask." + - bugfix: "Fixed cyborg synthesizer's inaccurate desc_info, and cleared the desc_fluff from them as well." \ No newline at end of file diff --git a/icons/obj/drinks.dmi b/icons/obj/drinks.dmi index a0b3216fe9b..33838345a95 100644 Binary files a/icons/obj/drinks.dmi and b/icons/obj/drinks.dmi differ diff --git a/icons/obj/shaker.dmi b/icons/obj/shaker.dmi new file mode 100644 index 00000000000..166dc69823d Binary files /dev/null and b/icons/obj/shaker.dmi differ diff --git a/sound/effects/pour.ogg b/sound/effects/pour1.ogg similarity index 100% rename from sound/effects/pour.ogg rename to sound/effects/pour1.ogg diff --git a/sound/effects/pour2.ogg b/sound/effects/pour2.ogg new file mode 100644 index 00000000000..1296b68c18a Binary files /dev/null and b/sound/effects/pour2.ogg differ diff --git a/sound/effects/pour_big.ogg b/sound/effects/pour_big.ogg new file mode 100644 index 00000000000..668456ae188 Binary files /dev/null and b/sound/effects/pour_big.ogg differ diff --git a/sound/items/shaker_lid_off1.ogg b/sound/items/shaker_lid_off1.ogg new file mode 100644 index 00000000000..8e4ab5a6ffd Binary files /dev/null and b/sound/items/shaker_lid_off1.ogg differ diff --git a/sound/items/shaker_lid_off2.ogg b/sound/items/shaker_lid_off2.ogg new file mode 100644 index 00000000000..ab7794c7962 Binary files /dev/null and b/sound/items/shaker_lid_off2.ogg differ diff --git a/sound/items/shaking1.ogg b/sound/items/shaking1.ogg new file mode 100644 index 00000000000..4c4d9ab8555 Binary files /dev/null and b/sound/items/shaking1.ogg differ diff --git a/sound/items/shaking2.ogg b/sound/items/shaking2.ogg new file mode 100644 index 00000000000..fd7a29ad855 Binary files /dev/null and b/sound/items/shaking2.ogg differ diff --git a/sound/items/shaking3.ogg b/sound/items/shaking3.ogg new file mode 100644 index 00000000000..39b48a3313f Binary files /dev/null and b/sound/items/shaking3.ogg differ diff --git a/sound/items/shaking4.ogg b/sound/items/shaking4.ogg new file mode 100644 index 00000000000..74041b1beac Binary files /dev/null and b/sound/items/shaking4.ogg differ diff --git a/sound/items/shaking5.ogg b/sound/items/shaking5.ogg new file mode 100644 index 00000000000..b7e6a41fe86 Binary files /dev/null and b/sound/items/shaking5.ogg differ diff --git a/sound/items/shaking6.ogg b/sound/items/shaking6.ogg new file mode 100644 index 00000000000..c1f5c98f380 Binary files /dev/null and b/sound/items/shaking6.ogg differ