Allow for placing certain items directly on the floor, with precision (#90805)

## About The Pull Request

So I really wanted to do the stereotypical "really I'm just a
construction worker" break-in bit, but then quickly realized you can't
even place warning cones on the floor! You have to awkwardly drop them,
or put them on a table and move them off!
Thinking about that, I remembered my similar annoyance with candles for
rituals or wet floor signs when playing a janitor.

Initially this was intended to include the ability to stack warning
cones for easy storage and placement, but I realized that was taking a
_lot_ more time than making the other items placeable on the floor.
Because of this, I decided to atomize the much less complex part off
into this pr.

So here, in this pr, we add a simple element
`/datum/element/floor_placeable` and apply it to a list of items for
which I think "placing it on the floor" makes enough sense as an
interaction.

As a side to this, we add the plastic pickup/drop noises to wet floor
signs and warning cones, because they're made of plastic and it's
leagues better than being entirely inaudible.
We remove `var/cooldown = 0` from `/obj/item/toy/cattoy` because it
wasn't used.
## Why It's Good For The Game

Can't do the stereotypical hazard vest break-in in _style_ without the
ability to actually place the cones:

![image](https://github.com/user-attachments/assets/d9e8707b-87a2-4463-8bac-a5d8adf917c7)

Oh man is it so much less of a pain to make fancy schmancy rituals when
you don't have to place candles on tables and drag them off for it to
work:

![image](https://github.com/user-attachments/assets/c8d4966e-29b8-48bc-ac0b-c357157d4ba3)

It's really funny to be able to play with toys on the floor:

![image](https://github.com/user-attachments/assets/d604157e-4a90-4e50-a44f-0e9f2f63aeac)
## Changelog
🆑
add: Certain items can now be placed directly on the floor in the
clicked on location. This currently includes warning cones, wet floor
signs, candles, action figures, plushies, mech toys, and a list of other
toys.
sound: Warning cones now use plastic pickup/drop sounds.
sound: Wet floor signs now use plastic pickup/drop sounds.
/🆑
This commit is contained in:
_0Steven
2025-04-28 16:58:45 +02:00
committed by GitHub
parent 0a7e5ac24b
commit 886cf157bc
9 changed files with 80 additions and 2 deletions
+41
View File
@@ -0,0 +1,41 @@
/**
* Simple behaviour for allowing the item to be placed on a specific position on an open turf by clicking there.
*/
/datum/element/floor_placeable
/datum/element/floor_placeable/Attach(datum/target)
. = ..()
if(!isitem(target))
return ELEMENT_INCOMPATIBLE
RegisterSignal(target, COMSIG_ATOM_EXAMINE_TAGS, PROC_REF(get_examine_tags))
RegisterSignal(target, COMSIG_ITEM_INTERACTING_WITH_ATOM, PROC_REF(on_interact_with_atom))
/datum/element/floor_placeable/Detach(datum/source)
. = ..()
UnregisterSignal(source, list(
COMSIG_ATOM_EXAMINE_TAGS,
COMSIG_ITEM_INTERACTING_WITH_ATOM,
))
/datum/element/floor_placeable/proc/get_examine_tags(atom/source, mob/user, list/examine_list)
SIGNAL_HANDLER
examine_list["floor placeable"] = "This item can be placed directly on the floor."
/datum/element/floor_placeable/proc/on_interact_with_atom(obj/item/source, mob/living/user, atom/interacting_with, list/modifiers)
SIGNAL_HANDLER
if(!isopenturf(interacting_with))
return NONE
if(user.combat_mode)
return NONE
if(source.item_flags & ABSTRACT)
return NONE
if(!user.transferItemToLoc(source, interacting_with, silent = FALSE))
return ITEM_INTERACT_BLOCKING
// Items are centered by default, but we move them if click ICON_X and ICON_Y are available
if(LAZYACCESS(modifiers, ICON_X) && LAZYACCESS(modifiers, ICON_Y))
// Clamp it so that the icon never moves more than 16 pixels in either direction (thus leaving the turf)
source.pixel_x = clamp(text2num(LAZYACCESS(modifiers, ICON_X)) - 16, -(ICON_SIZE_X*0.5), ICON_SIZE_X*0.5)
source.pixel_y = clamp(text2num(LAZYACCESS(modifiers, ICON_Y)) - 16, -(ICON_SIZE_Y*0.5), ICON_SIZE_Y*0.5)
return ITEM_INTERACT_SUCCESS
@@ -561,6 +561,7 @@
/obj/item/flashlight/flare/candle/Initialize(mapload)
. = ..()
AddElement(/datum/element/floor_placeable)
AddElement(/datum/element/update_icon_updates_onmob)
/**
+1
View File
@@ -8,6 +8,7 @@
attack_verb_simple = list("thump", "whomp", "bump")
w_class = WEIGHT_CLASS_SMALL
resistance_flags = FLAMMABLE
floor_placeable = TRUE
var/list/squeak_override //Weighted list; If you want your plush to have different squeak sounds use this
var/stuffed = TRUE //If the plushie has stuffing in it
var/obj/item/grenade/grenade //You can remove the stuffing from a plushie and add a grenade to it for *nefarious uses*
+1
View File
@@ -19,6 +19,7 @@
verb_exclaim = "beeps"
verb_yell = "beeps"
w_class = WEIGHT_CLASS_SMALL
floor_placeable = TRUE
/// Timer when it'll be off cooldown
var/timer = 0
/// Cooldown between play sessions
+19 -2
View File
@@ -33,6 +33,14 @@
force = 0
worn_icon_state = "nothing"
/// Can this toy be placed on the floor?
var/floor_placeable = FALSE
/obj/item/toy/Initialize(mapload)
. = ..()
if(floor_placeable)
AddElement(/datum/element/floor_placeable)
/*
* Balloons
*/
@@ -292,6 +300,7 @@
throw_speed = 2
throw_range = 5
force = 0
floor_placeable = TRUE
/obj/item/toy/balloon_animal/guy
name = "balloon guy"
@@ -868,6 +877,7 @@
icon = 'icons/obj/toys/toy.dmi'
icon_state = "owlprize"
w_class = WEIGHT_CLASS_SMALL
floor_placeable = TRUE
var/cooldown = FALSE
var/messages = list("I'm super generic!", "Mathematics class is of variable difficulty!")
var/span = "danger"
@@ -967,6 +977,7 @@
icon = 'icons/obj/toys/toy.dmi'
icon_state = "nuketoyidle"
w_class = WEIGHT_CLASS_SMALL
floor_placeable = TRUE
var/cooldown = 0
/obj/item/toy/nuke/attack_self(mob/user)
@@ -1011,6 +1022,7 @@
icon_state = "minimeteor"
inhand_icon_state = "minimeteor"
w_class = WEIGHT_CLASS_SMALL
floor_placeable = TRUE
/obj/item/toy/minimeteor/emag_act(mob/user, obj/item/card/emag/emag_card)
if (obj_flags & EMAGGED)
@@ -1037,6 +1049,7 @@
icon = 'icons/obj/devices/assemblies.dmi'
icon_state = "bigred"
w_class = WEIGHT_CLASS_SMALL
floor_placeable = TRUE
var/cooldown = 0
/obj/item/toy/redbutton/attack_self(mob/user)
@@ -1146,6 +1159,7 @@
name = "xenomorph action figure"
desc = "MEGA presents the new Xenos Isolated action figure! Comes complete with realistic sounds! Pull back string to use."
w_class = WEIGHT_CLASS_SMALL
floor_placeable = TRUE
var/cooldown = 0
/obj/item/toy/toy_xeno/attack_self(mob/user)
@@ -1170,8 +1184,8 @@
icon = 'icons/obj/toys/toy.dmi'
icon_state = "toy_mouse"
w_class = WEIGHT_CLASS_SMALL
var/cooldown = 0
resistance_flags = FLAMMABLE
floor_placeable = TRUE
/*
@@ -1181,10 +1195,11 @@
name = "\improper Non-Specific Action Figure action figure"
icon = 'icons/obj/toys/toy.dmi'
icon_state = "nuketoy"
w_class = WEIGHT_CLASS_SMALL
floor_placeable = TRUE
var/cooldown = 0
var/toysay = "What the fuck did you do?"
var/toysound = 'sound/machines/click.ogg'
w_class = WEIGHT_CLASS_SMALL
/obj/item/toy/figure/Initialize(mapload)
. = ..()
@@ -1417,6 +1432,7 @@
icon = 'icons/obj/toys/toy.dmi'
icon_state = "puppet"
inhand_icon_state = "puppet"
floor_placeable = TRUE
var/doll_name = "Dummy"
//Add changing looks when i feel suicidal about making 20 inhands for these.
@@ -1440,6 +1456,7 @@
desc = "May you always have a shell in your pocket and sand in your shoes. Whatever that's supposed to mean."
icon = 'icons/obj/fluff/beach.dmi'
icon_state = "shell1"
floor_placeable = TRUE
var/static/list/possible_colors = list("" = 2, COLOR_PURPLE_GRAY = 1, COLOR_OLIVE = 1, COLOR_PALE_BLUE_GRAY = 1, COLOR_RED_GRAY = 1)
/obj/item/toy/seashell/Initialize(mapload)
+4
View File
@@ -115,6 +115,10 @@
icon_state = "candle4"
custom_materials = null
/obj/item/trash/candle/Initialize(mapload)
. = ..()
AddElement(/datum/element/floor_placeable)
/obj/item/trash/flare
name = "burnt flare"
icon = 'icons/obj/lighting.dmi'
+6
View File
@@ -13,8 +13,14 @@
w_class = WEIGHT_CLASS_SMALL
attack_verb_continuous = list("warns", "cautions", "smashes")
attack_verb_simple = list("warn", "caution", "smash")
pickup_sound = 'sound/items/handling/materials/plastic_pick_up.ogg'
drop_sound = 'sound/items/handling/materials/plastic_drop.ogg'
resistance_flags = NONE
/obj/item/clothing/head/cone/Initialize(mapload)
. = ..()
AddElement(/datum/element/floor_placeable)
/obj/item/clothing/head/cone/worn_overlays(mutable_appearance/standing, isinhands, icon_file)
. = ..()
if(!isinhands)
+6
View File
@@ -14,6 +14,8 @@
body_parts_covered = CHEST|GROIN
attack_verb_continuous = list("warns", "cautions", "smashes")
attack_verb_simple = list("warn", "caution", "smash")
pickup_sound = 'sound/items/handling/materials/plastic_pick_up.ogg'
drop_sound = 'sound/items/handling/materials/plastic_drop.ogg'
armor_type = /datum/armor/suit_caution
species_exception = list(/datum/species/golem)
allowed = list(
@@ -24,3 +26,7 @@
/datum/armor/suit_caution
melee = 5
/obj/item/clothing/suit/caution/Initialize(mapload)
. = ..()
AddElement(/datum/element/floor_placeable)
+1
View File
@@ -1527,6 +1527,7 @@
#include "code\datums\elements\falling_hazard.dm"
#include "code\datums\elements\firestacker.dm"
#include "code\datums\elements\fish_safe_storage.dm"
#include "code\datums\elements\floor_placeable.dm"
#include "code\datums\elements\floorloving.dm"
#include "code\datums\elements\footstep.dm"
#include "code\datums\elements\footstep_override.dm"