From babab2fbd9f4768a05617148a740153758ca9e1c Mon Sep 17 00:00:00 2001
From: PollardTheDragon <144391971+PollardTheDragon@users.noreply.github.com>
Date: Thu, 4 Sep 2025 02:29:41 -0400
Subject: [PATCH] Adds Graves (#30153)
* Adds Graves
* Fixes
* Apply suggestions from code review
Co-authored-by: Luc <89928798+lewcc@users.noreply.github.com>
Signed-off-by: PollardTheDragon <144391971+PollardTheDragon@users.noreply.github.com>
* Adds attack log to burying people
* Apply suggestions from code review
Signed-off-by: Burzah <116982774+Burzah@users.noreply.github.com>
---------
Signed-off-by: PollardTheDragon <144391971+PollardTheDragon@users.noreply.github.com>
Signed-off-by: Burzah <116982774+Burzah@users.noreply.github.com>
Co-authored-by: Luc <89928798+lewcc@users.noreply.github.com>
Co-authored-by: Burzah <116982774+Burzah@users.noreply.github.com>
---
code/modules/mining/gravestones.dm | 133 +++++++++++++++++++++++++++++
code/modules/mining/ores_coins.dm | 3 +-
icons/obj/structures/grave.dmi | Bin 0 -> 1144 bytes
paradise.dme | 1 +
4 files changed, 136 insertions(+), 1 deletion(-)
create mode 100644 code/modules/mining/gravestones.dm
create mode 100644 icons/obj/structures/grave.dmi
diff --git a/code/modules/mining/gravestones.dm b/code/modules/mining/gravestones.dm
new file mode 100644
index 00000000000..816a5edc43f
--- /dev/null
+++ b/code/modules/mining/gravestones.dm
@@ -0,0 +1,133 @@
+/obj/structure/grave
+ name = "grave"
+ desc = "Rest in peace."
+ max_integrity = 100
+ icon = 'icons/obj/structures/grave.dmi'
+ icon_state = "grave_basalt_open"
+ anchored = TRUE
+ layer = BELOW_OBJ_LAYER
+ new_attack_chain = TRUE
+ /// What does the grave contain?
+ var/atom/buried
+ /// What does the headstone say?
+ var/headstone_message = "taken before their time."
+
+/obj/structure/grave/Initialize(mapload)
+ . = ..()
+ var/turf/item_turf = get_turf(src)
+ if(!ispath(item_turf.baseturf, /turf/simulated/floor/plating/asteroid))
+ var/obj/item/stack/ore/glass/sand_pile = new /obj/item/stack/ore/glass(get_turf(src))
+ sand_pile.amount = 5
+ visible_message("With nowhere to dig, [src] falls apart.")
+ // In case somehow something is buried here already
+ dig_up()
+ return INITIALIZE_HINT_QDEL
+ update_icon(UPDATE_ICON_STATE)
+
+/obj/structure/grave/examine(mob/user)
+ . = ..()
+ if(buried && ismob(buried))
+ . += "Here lies [buried], [headstone_message]."
+ if(buried)
+ . += "You can dig up [src] with a shovel or other digging tool."
+ else
+ . += "You can bury an object here by clicking on [src] with the object."
+ . += "You can bury a mob or person here by clicking on [src] with the mob or person strongly grabbed."
+
+/obj/structure/grave/update_icon_state()
+ . = ..()
+ var/turf/item_turf = get_turf(src)
+ if(ispath(item_turf.baseturf, /turf/simulated/floor/plating/asteroid/basalt))
+ icon_state = "grave_basalt"
+ else
+ icon_state = "grave_sand"
+ if(buried)
+ icon_state += "_closed"
+ else
+ icon_state += "_open"
+
+/obj/structure/grave/update_overlays()
+ . = ..()
+ overlays.Cut()
+ if(buried && ismob(buried))
+ . += pick("marker_cross", "marker_lightstone", "marker_darkstone")
+
+/obj/structure/grave/item_interaction(mob/living/user, obj/item/used, list/modifiers)
+ if(user.a_intent == INTENT_HARM)
+ return ..()
+
+ if(is_pen(used))
+ headstone_message = tgui_input_text(user, "Input headstone message", "Headstone", "[headstone_message]")
+ return ITEM_INTERACT_COMPLETE
+
+ if(istype(used, /obj/item/shovel) || istype(used, /obj/item/pickaxe))
+ to_chat(user, "You begin to dig up [src] with [used].")
+ playsound(loc, 'sound/effects/shovel_dig.ogg', 50, TRUE)
+ if(do_after(user, 10 SECONDS, target = src))
+ dig_up()
+ return ITEM_INTERACT_COMPLETE
+
+ if(buried)
+ to_chat(user, "The grave is already full.")
+ return ITEM_INTERACT_COMPLETE
+
+ if(istype(used, /obj/item/grab)) // Burying Mobs
+ var/obj/item/grab/G = used
+ if(G.state < GRAB_AGGRESSIVE)
+ to_chat(user, "You need a stronger grip on [G.affecting] to bury [G.affecting.p_them()]!")
+ return ITEM_INTERACT_COMPLETE
+ if(HAS_TRAIT(user, TRAIT_PACIFISM) && G.affecting.stat != DEAD)
+ to_chat(user, "Burying [G.affecting] in [src] might hurt [G.affecting.p_them()]!")
+ return ITEM_INTERACT_COMPLETE
+ visible_message("[user] starts to bury [G.affecting] in [src]!", \
+ "[user] starts to bury [G.affecting]!")
+ to_chat(G.affecting, "[user] is burying you alive!")
+ log_admin("[user] started to bury [G.affecting] in [src]")
+ if(do_after(user, 10 SECONDS, target = G.affecting))
+ log_attack(user, G.affecting, "buried [G.affecting] in [src].")
+ bury(user, G.affecting)
+ else // Burying Objects
+ visible_message("[user] starts to bury [used] in [src]!", \
+ "[user] starts to bury [used]!")
+ if(do_after(user, 10 SECONDS, target = used))
+ bury(user, used)
+ playsound(loc, 'sound/effects/shovel_dig.ogg', 50, TRUE)
+
+ return ITEM_INTERACT_COMPLETE
+
+/obj/structure/grave/return_obj_air() // If you're buried alive, suffocate
+ var/datum/gas_mixture/vacuum = new()
+ return vacuum
+
+/obj/structure/grave/container_resist(mob/living)
+ to_chat(living, "You begin to dig out of [src]! This will take about 30 seconds.")
+ if(do_after(living, 30 SECONDS, target = src))
+ dig_up()
+
+/obj/structure/grave/proc/bury(mob/living/user, atom/thing_to_bury)
+ if(isobj(thing_to_bury))
+ var/obj/bury_me = thing_to_bury
+ if(bury_me.flags & NODROP || !user.transfer_item_to(bury_me, src))
+ to_chat(user, "[bury_me] is stuck to your hand!")
+ return
+ bury_me.forceMove(src)
+ if(ismob(thing_to_bury))
+ var/mob/bury_me = thing_to_bury
+ bury_me.forceMove(src)
+ buried = thing_to_bury
+ playsound(loc, 'sound/effects/shovel_dig.ogg', 50, TRUE)
+ update_icon(UPDATE_ICON_STATE)
+ update_icon(UPDATE_OVERLAYS)
+
+/obj/structure/grave/proc/dig_up()
+ if(!buried)
+ return
+ if(isobj(buried))
+ var/obj/dig_up_me = buried
+ dig_up_me.forceMove(get_turf(src))
+ if(ismob(buried))
+ var/mob/dig_up_me = buried
+ dig_up_me.forceMove(get_turf(src))
+ buried = null
+ playsound(loc, 'sound/effects/shovel_dig.ogg', 50, TRUE)
+ update_icon(UPDATE_OVERLAYS | UPDATE_ICON_STATE)
diff --git a/code/modules/mining/ores_coins.dm b/code/modules/mining/ores_coins.dm
index c044d83562d..92a4be08974 100644
--- a/code/modules/mining/ores_coins.dm
+++ b/code/modules/mining/ores_coins.dm
@@ -63,7 +63,8 @@
. += "You can throw this into people's eyes!"
GLOBAL_LIST_INIT(sand_recipes, list(\
- new /datum/stack_recipe("sandstone", /obj/item/stack/sheet/mineral/sandstone, 1, 1, 50)\
+ new /datum/stack_recipe("sandstone", /obj/item/stack/sheet/mineral/sandstone, 1, 1, 50),
+ new /datum/stack_recipe("grave", /obj/structure/grave, 5, time = 10 SECONDS, one_per_turf = TRUE, on_floor = TRUE)
))
/obj/item/stack/ore/glass/Initialize(mapload, new_amount, merge = TRUE)
diff --git a/icons/obj/structures/grave.dmi b/icons/obj/structures/grave.dmi
new file mode 100644
index 0000000000000000000000000000000000000000..72972f065aaa474954ba4580341714ca9341e57a
GIT binary patch
literal 1144
zcmV-;1c&>HP)C0001rP)t-s0000L
z6%`~TBnk=&FE1~ne_VlHJdbNg2L}glTuGpOS&V2!rh;FbcvZ2DYFS7)rGZ|gfL*YR
zX`y{us)l2oc~-57X0D27pL0
zB_kfFDZ*Bkpc$}4y%?iRW5QNXkQ-t;|{uFOsq^0y=Um>i`+6L1^c0+xA
zW4(&R)6TH-F|b>zbJKRcsxO^fkk|&VPO92$rFdEsr(_O$DJHbz6q7ktk|RV+vKR>#
z)K_3|QHKZmLJDJv({3lljbO%){!R=oFq%w;!JB_N)_i8e40K1*0|n;XuzTNwWAK8sHC*erX=*BH4d22
z_kX>vZaHYF$~n{7Zw5@FO!m{SmBeU75ClOG1VIo4K@bE%5JWC)z(xNxFA%usjv_A^uKWRxvF25zP^6DkU@#fUs0O+N`NV$fq*lpP+W~#B&h9R(WEM?
zas>>HZ2pXwP*oe4IP@}TgG!7Mgf*z8d?%%xNKN(d-h8ONfT{-njfL{|83ed#0=+hj
z4+W-}z_haS*Y!Tgk1{Y5(q@oO;6NbiKIf4s0QKik@zZB1A0dS=I*NsSat5)0*9B3G~eU4q*C2B(O>n2|Pj98Ppbho~Sht*#bq__+bY|35?VASF3SIU>2tS^Vg#b
zAydFCLEL~gl57FH25fVgG=8RL>B<4RwKfX$+!6
zNWJ^}kT>XM&@|i}L~6NV9UA*}sBs-pxEZFYg&AKiu|LoT3{QaNj6($kF*-i(z7g1O
zLWi)t@$+E_x#I*u5ClOG1VIo4LEMg3gO9H@SFGQ4-OEdd8mz&t>)NXsw4F%+Gg!AK
zfvXv8TFWLqzFk|k|F6JCg9~gml)za6ecvAuxIqH_4i(r0fuzAU2%KR60!RpuycbAi
z0LgoS(=$-jU(+E#)vhx~AtqpssjfX$0E+K`{XQw+&Oz)fbm!n1XJNm4-2=$z=66IY
zfdQupK=C6@cpFII?gINBYr@;mgTOr_(C5It7l9xMf*=Uu#{2