diff --git a/code/datums/components/crafting/recipes/tools.dm b/code/datums/components/crafting/recipes/tools.dm index 71f3e57b6aa9..1aea51b0d5c5 100644 --- a/code/datums/components/crafting/recipes/tools.dm +++ b/code/datums/components/crafting/recipes/tools.dm @@ -55,6 +55,16 @@ ////CONTAINERS///// +/datum/crafting_recipe/jar + name = "Glass Jar" + time = 60 + reqs = list( + /obj/item/stack/sheet/mineral/wood = 3, + /obj/item/stack/sheet/leather = 2, + /obj/item/stack/sheet/glass = 5) + result = /obj/item/reagent_containers/glass/beaker/jar + category = CAT_TOOL + /datum/crafting_recipe/woodbucket name = "Wooden Bucket" time = 30 diff --git a/code/modules/reagents/reagent_containers/glass.dm b/code/modules/reagents/reagent_containers/glass.dm index 686a77a69966..59fe82d19366 100755 --- a/code/modules/reagents/reagent_containers/glass.dm +++ b/code/modules/reagents/reagent_containers/glass.dm @@ -17,14 +17,13 @@ return if(!reagents || !reagents.total_volume) - to_chat(user, "[src] is empty!") + to_chat(user, span_warning("[src] is empty!")) return if(istype(M)) if(user.a_intent == INTENT_HARM) var/R - M.visible_message("[user] splashes the contents of [src] onto [M]!", \ - "[user] splashes the contents of [src] onto you!") + M.visible_message(span_danger("[user] splashes the contents of [src] onto [M]!"), span_userdanger("[user] splashes the contents of [src] onto you!")) if(reagents) for(var/datum/reagent/A in reagents.reagent_list) R += "[A] ([num2text(A.volume)])," @@ -37,17 +36,15 @@ reagents.clear_reagents() else if(M != user) - M.visible_message("[user] attempts to feed [M] something from [src].", \ - "[user] attempts to feed you something from [src].") + M.visible_message(span_danger("[user] attempts to feed [M] something from [src]."), span_userdanger("[user] attempts to feed you something from [src].")) if(!do_mob(user, M)) return if(!reagents || !reagents.total_volume) return // The drink might be empty after the delay, such as by spam-feeding - M.visible_message("[user] feeds [M] something from [src].", \ - "[user] feeds you something from [src].") + M.visible_message(span_danger("[user] feeds [M] something from [src]."), span_userdanger("[user] feeds you something from [src].")) log_combat(user, M, "fed", reagents.log_list()) else - to_chat(user, "You swallow a gulp of [src].") + to_chat(user, span_notice("You swallow a gulp of [src].")) SEND_SIGNAL(src, COMSIG_GLASS_DRANK, M, user) addtimer(CALLBACK(reagents, TYPE_PROC_REF(/datum/reagents, trans_to), M, 5, TRUE, TRUE, FALSE, user, FALSE, INGEST), 5) playsound(M.loc,'sound/items/drink.ogg', rand(10,50), TRUE) @@ -73,32 +70,31 @@ if(target.is_refillable()) //Something like a glass. Player probably wants to transfer TO it. if(!reagents.total_volume) - to_chat(user, "[src] is empty!") + to_chat(user, span_warning("[src] is empty!")) return if(target.reagents.holder_full()) - to_chat(user, "[target] is full.") + to_chat(user, span_warning("[target] is full.")) return var/trans = reagents.trans_to(target, amount_per_transfer_from_this, transfered_by = user) - to_chat(user, "You transfer [trans] unit\s of the solution to [target].") + to_chat(user, span_notice("You transfer [trans] unit\s of the solution to [target].")) else if(target.is_drainable()) //A dispenser. Transfer FROM it TO us. if(!target.reagents.total_volume) - to_chat(user, "[target] is empty and can't be refilled!") + to_chat(user, span_warning("[target] is empty and can't be refilled!")) return if(reagents.holder_full()) - to_chat(user, "[src] is full.") + to_chat(user, span_warning("[src] is full.")) return var/trans = target.reagents.trans_to(src, amount_per_transfer_from_this, transfered_by = user) - to_chat(user, "You fill [src] with [trans] unit\s of the contents of [target].") + to_chat(user, span_notice("You fill [src] with [trans] unit\s of the contents of [target].")) else if(reagents.total_volume) if(user.a_intent == INTENT_HARM) - user.visible_message("[user] splashes the contents of [src] onto [target]!", \ - "You splash the contents of [src] onto [target].") + user.visible_message(span_danger("[user] splashes the contents of [src] onto [target]!"), span_notice("You splash the contents of [src] onto [target].")) reagents.expose(target, TOUCH) reagents.clear_reagents() @@ -106,15 +102,15 @@ var/hotness = I.get_temperature() if(hotness && reagents) reagents.expose_temperature(hotness) - to_chat(user, "You heat [name] with [I]!") + to_chat(user, span_notice("You heat [name] with [I]!")) if(istype(I, /obj/item/food/egg)) //breaking eggs var/obj/item/food/egg/E = I if(reagents) if(reagents.total_volume >= reagents.maximum_volume) - to_chat(user, "[src] is full.") + to_chat(user, span_notice("[src] is full.")) else - to_chat(user, "You break [E] in [src].") + to_chat(user, span_notice("You break [E] in [src].")) E.reagents.trans_to(src, E.reagents.total_volume, transfered_by = user) qdel(E) return @@ -145,15 +141,104 @@ /obj/item/reagent_containers/glass/beaker/get_part_rating() return reagents.maximum_volume +/* +* Jars +* Apparently water bottles in drinks.dm have all this code for sealing +* and unsealing themselves with a visible cap. But they also have this +* junk code for flipping bottles. Im unsure how to feel about making +* a duplicate of the code but without flipping. +* -IP +*/ /obj/item/reagent_containers/glass/beaker/jar name = "jar" - desc = "A jar for goops and powders. It can hold up to 40 units." + desc = "A jar for goops and powders. It can hold up to 50 units." icon = 'icons/obj/chemical.dmi' icon_state = "jar" fill_icon_state = "jar" volume = 50 - spillable = FALSE - fill_icon_thresholds = list(0, 10, 30, 50) + var/cap_icon_state = "jar_top" + var/cap_on = TRUE + var/cap_lost = FALSE + var/mutable_appearance/cap_overlay + fill_icon_thresholds = list(0, 10, 25, 35, 50) + +/obj/item/reagent_containers/glass/beaker/jar/Initialize() + . = ..() + cap_overlay = mutable_appearance(icon, cap_icon_state) + if(cap_on) + spillable = FALSE + update_icon() + +/obj/item/reagent_containers/glass/beaker/jar/update_overlays() + . = ..() + if(cap_on) + . += cap_overlay + +/obj/item/reagent_containers/glass/beaker/jar/examine(mob/user) + . = ..() + if(cap_lost) + . += span_notice("The cap seems to be missing.") + else if(cap_on) + . += span_notice("The cap is firmly on to prevent spilling. Alt-click to remove the cap.") + else + . += span_notice("The cap has been taken off. Alt-click to put a cap on.") + +/obj/item/reagent_containers/glass/beaker/jar/AltClick(mob/user) + . = ..() + if(cap_lost) + to_chat(user, span_warning("The cap seems to be missing! Where did it go?")) + return + + var/fumbled = HAS_TRAIT(user, TRAIT_CLUMSY) && prob(5) + if(cap_on || fumbled) + cap_on = FALSE + spillable = TRUE + animate(src, transform = null, time = 2, loop = 0) + if(fumbled) + to_chat(user, span_warning("You fumble with [src]'s cap! The cap falls onto the ground and simply vanishes. Where the hell did it go?")) + cap_lost = TRUE + else + to_chat(user, span_notice("You remove the cap from [src].")) + else + cap_on = TRUE + spillable = FALSE + to_chat(user, span_notice("You put the cap on [src].")) + update_icon() + +/obj/item/reagent_containers/glass/beaker/jar/is_refillable() + if(cap_on) + return FALSE + return ..() + +/obj/item/reagent_containers/glass/beaker/jar/is_drainable() + if(cap_on) + return FALSE + return ..() + +/obj/item/reagent_containers/glass/beaker/jar/attack(mob/target, mob/user, def_zone) + if(!target) + return + + if(user.a_intent != INTENT_HARM) + if(cap_on && reagents.total_volume && istype(target)) + to_chat(user, span_warning("You must remove the cap before you can do that!")) + return + + return ..() + + if(!cap_on) + SplashReagents(target) + +/obj/item/reagent_containers/glass/beaker/jar/afterattack(obj/target, mob/user, proximity) + if(cap_on && (target.is_refillable() || target.is_drainable() || (reagents.total_volume && user.a_intent == INTENT_HARM))) + to_chat(user, span_warning("You must remove the cap before you can do that!")) + return + + else if(istype(target, /obj/item/reagent_containers/glass/beaker/jar)) + var/obj/item/reagent_containers/glass/beaker/jar/WB = target + if(WB.cap_on) + to_chat(user, span_warning("[WB] has a cap firmly twisted on!")) + return ..() /obj/item/reagent_containers/glass/beaker/jar/pudding name = "jar of pudding" @@ -305,13 +390,13 @@ /obj/item/reagent_containers/glass/bucket/attackby(obj/O, mob/user, params) if(istype(O, /obj/item/mop)) if(reagents.total_volume < 1) - to_chat(user, "[src] is out of water!") + to_chat(user, span_warning("[src] is out of water!")) else reagents.trans_to(O, 5, transfered_by = user) - to_chat(user, "You wet [O] in [src].") + to_chat(user, span_notice("You wet [O] in [src].")) playsound(loc, 'sound/effects/slosh.ogg', 25, TRUE) else if(isprox(O)) //This works with wooden buckets for now. Somewhat unintended, but maybe someone will add sprites for it soon(TM) - to_chat(user, "You add [O] to [src].") + to_chat(user, span_notice("You add [O] to [src].")) qdel(O) qdel(src) user.put_in_hands(new /obj/item/bot_assembly/cleanbot) @@ -322,7 +407,7 @@ ..() if (slot == ITEM_SLOT_HEAD) if(reagents.total_volume) - to_chat(user, "[src]'s contents spill all over you!") + to_chat(user, span_userdanger("[src]'s contents spill all over you!")) reagents.expose(user, TOUCH) reagents.clear_reagents() reagents.flags = NONE @@ -364,43 +449,43 @@ if(grinded) grinded.forceMove(drop_location()) grinded = null - to_chat(user, "You eject the item inside.") + to_chat(user, span_notice("You eject the item inside.")) /obj/item/reagent_containers/glass/mortar/attackby(obj/item/I, mob/living/carbon/human/user) ..() if(istype(I,/obj/item/pestle)) if(grinded) if(user.getStaminaLoss() > 50) - to_chat(user, "You are too tired to work!") + to_chat(user, span_warning("You are too tired to work!")) return - to_chat(user, "You start grinding...") + to_chat(user, span_notice("You start grinding...")) if((do_after(user, 25, target = src)) && grinded) user.adjustStaminaLoss(40) if(grinded.juice_results) //prioritize juicing grinded.on_juice() reagents.add_reagent_list(grinded.juice_results) - to_chat(user, "You juice [grinded] into a fine liquid.") + to_chat(user, span_notice("You juice [grinded] into a fine liquid.")) QDEL_NULL(grinded) return grinded.on_grind() reagents.add_reagent_list(grinded.grind_results) if(grinded.reagents) //food and pills grinded.reagents.trans_to(src, grinded.reagents.total_volume, transfered_by = user) - to_chat(user, "You break [grinded] into powder.") + to_chat(user, span_notice("You break [grinded] into powder.")) QDEL_NULL(grinded) return return else - to_chat(user, "There is nothing to grind!") + to_chat(user, span_warning("There is nothing to grind!")) return if(grinded) - to_chat(user, "There is something inside already!") + to_chat(user, span_warning("There is something inside already!")) return if(I.juice_results || I.grind_results) I.forceMove(src) grinded = I return - to_chat(user, "You can't grind this!") + to_chat(user, span_warning("You can't grind this!")) /obj/item/reagent_containers/glass/saline name = "saline canister" diff --git a/icons/obj/chemical.dmi b/icons/obj/chemical.dmi index 266dcf63e68e..9c62b88a007c 100644 Binary files a/icons/obj/chemical.dmi and b/icons/obj/chemical.dmi differ diff --git a/icons/obj/reagentfillings.dmi b/icons/obj/reagentfillings.dmi index 51bc7977be0f..e52059175237 100644 Binary files a/icons/obj/reagentfillings.dmi and b/icons/obj/reagentfillings.dmi differ