diff --git a/code/game/objects/items/toys.dm b/code/game/objects/items/toys.dm index fd8b8fb31fc..40d2e763b71 100644 --- a/code/game/objects/items/toys.dm +++ b/code/game/objects/items/toys.dm @@ -2148,3 +2148,218 @@ /obj/item/toy/pool_noodle/orange color = COLOR_ORANGE + +/obj/item/toy/bucket_and_spade + name = "small bucket and spade" + desc = "Only useful for sculpting." + icon = 'icons/obj/toy.dmi' + icon_state = "bucket_and_spade" + materials = list(MAT_PLASTIC = 2000) + +/obj/item/toy/bucket_and_spade/interact_with_atom(atom/target, mob/living/user, list/modifiers) + if(!istype(target, /turf/simulated/floor/beach/sand)) + return ..() + if(length(target.contents)) + var/obj/structure/sand_sculpture/sculpture = (locate(/obj/structure/sand_sculpture) in target) + if(!sculpture) + to_chat(user, SPAN_NOTICE("There are too many things in the way to build a sculpture here.")) + return ITEM_INTERACT_COMPLETE + if(user.a_intent == INTENT_HARM) + sculpture.take_damage(5, BRUTE) + return ITEM_INTERACT_COMPLETE + sculpture.interact_sculpture(user, src) + return ITEM_INTERACT_COMPLETE + + var/list/obj/structure/sand_sculpture/valid_sculptures = typesof(/obj/structure/sand_sculpture) + var/list/picker_list = list() + for(var/each_sculpture in valid_sculptures) + var/obj/structure/sand_sculpture/picker_sculpture = each_sculpture + picker_list |= list(picker_sculpture::name = picker_sculpture) + var/obj/structure/sand_sculpture/chosen_sculpture = tgui_input_list(user, "Choose which sculpture to build:", "Choosing sculpture", picker_list) + + if(!chosen_sculpture) + return ITEM_INTERACT_COMPLETE + if(!user.can_reach(target)) + return ..() + + chosen_sculpture = picker_list[chosen_sculpture] + + visible_message( + SPAN_NOTICE("[user] starts sculpting on [target] with [src]."), + SPAN_NOTICE("You start sculpting on [target] with [src]."), + SPAN_NOTICE("You hear shuffling and packing of sand nearby.")) + playsound(loc, 'sound/effects/sculptures/sand_buildstart.ogg', 80, TRUE) + + if(!do_after(user = user, delay = 8 SECONDS, target = target)) + to_chat(user, SPAN_NOTICE("You stop building [chosen_sculpture::name].")) + return ITEM_INTERACT_COMPLETE + visible_message( + SPAN_NOTICE("[user] builds \a [chosen_sculpture::name] on [target]."), + SPAN_NOTICE("You finish building \the [chosen_sculpture::name] on [target].")) + playsound(loc, 'sound/effects/sculptures/sand_buildfinish.ogg', 80, TRUE) + new chosen_sculpture(target) + return ITEM_INTERACT_COMPLETE + +/obj/structure/sand_sculpture + name = "ruined sand sculpture" + desc = "Oh. That's unfortunate." + icon = 'icons/obj/sculptures.dmi' + var/base_icon = 'icons/obj/sculptures.dmi' + icon_state = "sand_ruined" + // easy to destroy + max_integrity = 100 + integrity_failure = 99 + +/obj/structure/sand_sculpture/Initialize(mapload) + . = ..() + var/static/list/loc_connections = list( + COMSIG_ATOM_ENTERED = PROC_REF(on_atom_entered), + ) + AddElement(/datum/element/connect_loc, loc_connections) + update_icon() + +/obj/structure/sand_sculpture/update_overlays() + . = ..() + overlays.Cut() + + var/icon/silhouette = icon(icon, icon_state + "_mask") + var/turf/simulated/underlay_source = get_turf(src) + var/icon/underlay_icon = icon(underlay_source.icon, underlay_source.icon_state) + silhouette.Blend(underlay_icon, ICON_MULTIPLY) + . += silhouette + . += icon(base_icon, icon_state) + +/obj/structure/sand_sculpture/proc/on_atom_entered(datum/source, mob/living/entered) + if(istype(entered)) + take_damage(5, BRUTE) + +/obj/structure/sand_sculpture/item_interaction(mob/living/user, obj/item/used, list/modifiers) + if(!istype(used, /obj/item/toy/bucket_and_spade) || user.a_intent == INTENT_HARM) + return ..() + + interact_sculpture(user, used) + return ITEM_INTERACT_COMPLETE + +/obj/structure/sand_sculpture/attacked_by(obj/item/attacker, mob/living/user, params) + if(..()) + return FINISH_ATTACK + + take_damage(5, BRUTE) + return FINISH_ATTACK + +/obj/structure/sand_sculpture/attack_hand(mob/user) + if(user.a_intent == INTENT_HARM) + take_damage(5, BRUTE) + return + interact_sculpture(user) + +/obj/structure/sand_sculpture/proc/interact_sculpture(mob/user, obj/item/tool = null) + if(!user.can_reach(src)) + return + // repairing or dismantling with hands only will take longer + var/speed_modifier = istype(tool, /obj/item/toy/bucket_and_spade) ? 1 : 2 + var/choice = "Nothing" + if(icon_state == initial(icon_state)) + choice = tgui_alert(usr, "What would you like to do with the sculpture?", "Sculpture action", list("Dismantle", "Nothing")) + else + choice = tgui_alert(usr, "What would you like to do with the sculpture?", "Sculpture action", list("Repair", "Dismantle", "Nothing")) + if(choice == "Nothing" || !choice) + return + if(!user.can_reach(src)) + return + + visible_message( + SPAN_NOTICE("[user] starts [choice == "Repair" ? "repairing" : "dismantling"] \the [src]."), + SPAN_NOTICE("You start [choice == "Repair" ? "repairing" : "dismantling"] \the [src]."), + SPAN_NOTICE("You hear shuffling and packing of sand nearby.")) + playsound(loc, 'sound/effects/sculptures/sand_buildstart.ogg', 80, TRUE) + + if(do_after(user = user, delay = (choice == "Repair" ? 50 * speed_modifier : 20 * speed_modifier), target = src)) + if(choice == "Repair") + icon_state = initial(icon_state) + name = initial(name) + desc = initial(desc) + update_icon() + obj_integrity = max_integrity + visible_message( + SPAN_NOTICE("[user] repairs [src]."), + SPAN_NOTICE("You finish repairing [src].")) + playsound(loc, 'sound/effects/sculptures/sand_buildfinish.ogg', 80, TRUE) + else + qdel(src) + return + take_damage(5, BRUTE) + +/obj/structure/sand_sculpture/move_from_pull(atom/movable/puller, turf/target_turf, puller_glide_size) + take_damage(5, BRUTE, sound_effect = FALSE) + puller.stop_pulling() + +/obj/structure/sand_sculpture/play_attack_sound(damage_amount, damage_type = BRUTE, damage_flag = 0) + switch(damage_type) + if(BRUTE) + playsound(loc, 'sound/effects/sculptures/sand_hit.ogg', 90, TRUE) + if(BURN) + playsound(loc, 'sound/effects/sculptures/sand_hit.ogg', 70, TRUE) + +/obj/structure/sand_sculpture/obj_break(damage_flag) + if(icon_state == "sand_ruined") + return + visible_message( + SPAN_WARNING("[src] collapses!"), + SPAN_WARNING("[src] collapses before you!"), + SPAN_NOTICE("You hear a pile of sand collapse.")) + playsound(loc, 'sound/effects/sculptures/sand_collapse.ogg', 100, TRUE) + name = "ruined sand sculpture" + desc = "Oh. That's unfortunate." + icon_state = "sand_ruined" + update_icon() + +/obj/structure/sand_sculpture/mermaid + name = "mermaid sand sculpture" + desc = "Legend has it this creature exists, somewhere out there among the stars." + icon_state = "sand_mermaid" + +/obj/structure/sand_sculpture/merman + name = "merman sand sculpture" + desc = "Legend has it this creature exists, somewhere out there among the stars." + icon_state = "sand_merman" + +/obj/structure/sand_sculpture/starship + name = "sandship sculpture" + desc = "Boldly building where no man has built before." + icon_state = "sand_starship" + +/obj/structure/sand_sculpture/bar + name = "sand bar" + desc = "You can order a beach feast, but good luck drinking it." + icon_state = "sand_bar" + +/obj/structure/sand_sculpture/castle + name = "sand castle" + desc = "A classic fortress to guard your valuable shells and seaweed." + icon_state = "sand_castle" + +/obj/structure/sand_sculpture/corgi + name = "sand corgi" + desc = "Legend has it theis creature exists inside the very halls of a Nanotrasen station." + icon_state = "sand_corgi" + +/obj/structure/sand_sculpture/secbot + name = "sandbot" + desc = "You're fairly sure it would try to arrest you if it had any moving parts." + icon_state = "sand_secbot" + +/obj/structure/sand_sculpture/oyster + name = "sand pearl oyster" + desc = "That's the second biggest pearl you've ever seen. It must be worth a lot of sand dollars." + icon_state = "sand_shell" + +/obj/structure/sand_sculpture/crab + name = "sand crab" + desc = "If you add just enough water, it could become a mud crab." + icon_state = "sand_crab" + +/obj/structure/sand_sculpture/nad + name = "nuclear authentication dune" + desc = "The codes are crudely scored into the flat sand." + icon_state = "sand_nad" diff --git a/code/modules/crafting/recipes.dm b/code/modules/crafting/recipes.dm index 57a000a1748..78cb3410644 100644 --- a/code/modules/crafting/recipes.dm +++ b/code/modules/crafting/recipes.dm @@ -1411,3 +1411,9 @@ reqs = list(/obj/item/stack/sheet/wood = 2, /obj/item/stack/sheet/cloth = 1) category = CAT_MISC + +/datum/crafting_recipe/bucket_and_spade + name = "Small bucket and spade" + result = list(/obj/item/toy/bucket_and_spade) + reqs = list(/obj/item/stack/sheet/plastic = 2) + category = CAT_MISC diff --git a/icons/obj/sculptures.dmi b/icons/obj/sculptures.dmi new file mode 100644 index 00000000000..c2d1908321d Binary files /dev/null and b/icons/obj/sculptures.dmi differ diff --git a/icons/obj/toy.dmi b/icons/obj/toy.dmi index 2418d5ab0f6..f1809adebe1 100644 Binary files a/icons/obj/toy.dmi and b/icons/obj/toy.dmi differ diff --git a/sound/Attributions.txt b/sound/Attributions.txt index 89fbf457200..9be2d1a0b20 100644 --- a/sound/Attributions.txt +++ b/sound/Attributions.txt @@ -34,3 +34,4 @@ items/beach_chair_hit_1.ogg was compressed to ogg from "screen door open 1.wav" items/pool_noodle_hit.ogg was compressed to ogg from "cardboard box hit 28.wav" in https://filmcow.itch.io/filmcow-sfx-4 's "Hits & Crunches 48kHz.zip" under their FilmCow Royalty Free SFX Library License Agreement +effects/sculptures/sand_buildfinish.ogg, sand_buildstart.ogg, sand_collapse.ogg, and sand_hit.ogg were compressed to ogg from "sand foley 14.wav", "sand foley 31.wav", "sand falling 4.wav", and "sand hit ground 2.wav" in https://filmcow.itch.io/filmcow-sfx-3 's "Beads & Sand 48kHz.zip" under their FilmCow Royalty Free SFX Library License Agreement. \ No newline at end of file diff --git a/sound/effects/sculptures/sand_buildfinish.ogg b/sound/effects/sculptures/sand_buildfinish.ogg new file mode 100644 index 00000000000..c1556741fff Binary files /dev/null and b/sound/effects/sculptures/sand_buildfinish.ogg differ diff --git a/sound/effects/sculptures/sand_buildstart.ogg b/sound/effects/sculptures/sand_buildstart.ogg new file mode 100644 index 00000000000..27ae5d57738 Binary files /dev/null and b/sound/effects/sculptures/sand_buildstart.ogg differ diff --git a/sound/effects/sculptures/sand_collapse.ogg b/sound/effects/sculptures/sand_collapse.ogg new file mode 100644 index 00000000000..c3fb5f554e8 Binary files /dev/null and b/sound/effects/sculptures/sand_collapse.ogg differ diff --git a/sound/effects/sculptures/sand_hit.ogg b/sound/effects/sculptures/sand_hit.ogg new file mode 100644 index 00000000000..dcc9efdf545 Binary files /dev/null and b/sound/effects/sculptures/sand_hit.ogg differ