Files
Bubberstation/code/game/objects/items/wall_mounted.dm
SyncIt21 aa44be14e8 Makes /datum/component/wall_mounted actually do it's job (#78439)
## About The Pull Request
This component added in #77417 never actually worked. It has 2 problems

**1. Nothing even gets dismounted**


https://github.com/tgstation/tgstation/assets/110812394/8859794c-e2da-4bf2-bf2e-cd44fb240872

This is because a ton of objects in game don't actually pass a callback
when the object is getting dismounted i.e. they pass no params to the
`find_and_hang_on_wall()` proc for e.g.


11ec431834/code/game/objects/items/wall_mounted.dm (L58)

and because the callback is null the action 


11ec431834/code/datums/components/wall_mounted.dm (L54)

never gets executed. Now to combat this in the `Initialize()` proc a
null check is done to ensure the callback is not null

11ec431834/code/datums/components/wall_mounted.dm (L15-L18)

But this code itself is broken for 2 reasons
1. We create a callback using the `CALLBACK` macro they are not the same
as `TYPE_PROC_REF` also we never specify which object this proc ref
should even be called on
2. `on_drop` ends up null anyway because we first check if the param is
null and set its value here

11ec431834/code/datums/components/wall_mounted.dm (L15-L16)
But then we again overwrite `on_drop` with the param passed(which is
null) so it ends up becoming null again

11ec431834/code/datums/components/wall_mounted.dm (L18)

So this never did it's job. Also we simply can't create a callback on
`obj/deconstruct` because this proc accepts a boolean as it's param

11ec431834/code/game/objects/obj_defense.dm (L150)
But we pass the `hanging_param` as its param when invoking the callback

11ec431834/code/datums/components/wall_mounted.dm (L54)

Which would cause undefined behaviour so we have to manually do a null
check for this param and call the `deconstruct` proc explicitly to
ensure correct behaviour


**2. Wall mounts created in round would runtime**

**Reproduction**
1. Use some iron sheets to construct an air alarm wall frame(or any
wallmount of your choice)
4. Put on wall
5. Get stack trace


![Error](https://github.com/tgstation/tgstation/assets/110812394/2f802dc2-faaa-4ee3-aacf-38b83adef17d)

This occurred because the component received an invalid parent when
mounting was attempted.

![Cause](https://github.com/tgstation/tgstation/assets/110812394/aed12757-edf6-4f79-8763-00f4a86251ca)

Which was caused by

11ec431834/code/game/objects/items/wall_mounted.dm (L45)

We should be doing this the other way around i.e. 

`hanging_object.AddComponent(/datum/component/wall_mounted, on_wall)`

But the truth is even this is not required nor is this


11ec431834/code/game/objects/items/wall_mounted.dm (L58)

These 2 lines of code are not necessary because a lot of objects call
`find_and_hang_on_wall()` proc by themselves in their `Initialization()`
proc for e.g.


11ec431834/code/modules/atmospherics/machinery/air_alarm/_air_alarm.dm (L127)

So the work is already done for us. we were just adding the component 2
more times for no reason and causing problems.

## Changelog
🆑
fix: wall mounted objects air alarms, fire alarms etc now actually falls
off/gets destroyed when their attached wall is deconstructed
fix: wall mounts crafted in game also properly falls off/gets destroyed
when their attached wall is deconstructed
/🆑
2023-09-20 16:53:38 +02:00

96 lines
3.4 KiB
Plaintext

/obj/item/wallframe
icon = 'icons/obj/machines/wallmounts.dmi'
custom_materials = list(/datum/material/iron= SHEET_MATERIAL_AMOUNT * 2)
flags_1 = CONDUCT_1
inhand_icon_state = "syringe_kit"
lefthand_file = 'icons/mob/inhands/equipment/medical_lefthand.dmi'
righthand_file = 'icons/mob/inhands/equipment/medical_righthand.dmi'
w_class = WEIGHT_CLASS_SMALL
var/result_path
var/wall_external = FALSE // For frames that are external to the wall they are placed on, like light fixtures and cameras.
var/pixel_shift //The amount of pixels
/obj/item/wallframe/proc/try_build(turf/on_wall, mob/user)
if(get_dist(on_wall,user) > 1)
balloon_alert(user, "you are too far!")
return
var/floor_to_wall = get_dir(user, on_wall)
if(!(floor_to_wall in GLOB.cardinals))
balloon_alert(user, "stand in line with wall!")
return
var/turf/T = get_turf(user)
var/area/A = get_area(T)
if(!isfloorturf(T))
balloon_alert(user, "cannot place here!")
return
if(A.always_unpowered)
balloon_alert(user, "cannot place in this area!")
return
if(check_wall_item(T, floor_to_wall, wall_external))
balloon_alert(user, "already something here!")
return
return TRUE
/obj/item/wallframe/proc/attach(turf/on_wall, mob/user)
if(result_path)
playsound(src.loc, 'sound/machines/click.ogg', 75, TRUE)
user.visible_message(span_notice("[user.name] attaches [src] to the wall."),
span_notice("You attach [src] to the wall."),
span_hear("You hear clicking."))
var/floor_to_wall = get_dir(user, on_wall)
var/obj/hanging_object = new result_path(get_turf(user), floor_to_wall, TRUE)
hanging_object.setDir(floor_to_wall)
if(pixel_shift)
switch(floor_to_wall)
if(NORTH)
hanging_object.pixel_y = pixel_shift
if(SOUTH)
hanging_object.pixel_y = -pixel_shift
if(EAST)
hanging_object.pixel_x = pixel_shift
if(WEST)
hanging_object.pixel_x = -pixel_shift
after_attach(hanging_object)
qdel(src)
/obj/item/wallframe/proc/after_attach(obj/attached_to)
transfer_fingerprints_to(attached_to)
/obj/item/wallframe/screwdriver_act(mob/living/user, obj/item/tool)
// For camera-building borgs
var/turf/T = get_step(get_turf(user), user.dir)
if(iswallturf(T))
T.attackby(src, user)
return TOOL_ACT_TOOLTYPE_SUCCESS
/obj/item/wallframe/wrench_act(mob/living/user, obj/item/tool)
var/metal_amt = round(custom_materials[GET_MATERIAL_REF(/datum/material/iron)]/SHEET_MATERIAL_AMOUNT) //Replace this shit later
var/glass_amt = round(custom_materials[GET_MATERIAL_REF(/datum/material/glass)]/SHEET_MATERIAL_AMOUNT) //Replace this shit later
if(!metal_amt && !glass_amt)
return FALSE
to_chat(user, span_notice("You dismantle [src]."))
tool.play_tool_sound(src)
if(metal_amt)
new /obj/item/stack/sheet/iron(get_turf(src), metal_amt)
if(glass_amt)
new /obj/item/stack/sheet/glass(get_turf(src), glass_amt)
qdel(src)
return TOOL_ACT_TOOLTYPE_SUCCESS
/obj/item/electronics
desc = "Looks like a circuit. Probably is."
icon = 'icons/obj/assemblies/module.dmi'
icon_state = "door_electronics"
inhand_icon_state = "electronic"
lefthand_file = 'icons/mob/inhands/items/devices_lefthand.dmi'
righthand_file = 'icons/mob/inhands/items/devices_righthand.dmi'
flags_1 = CONDUCT_1
w_class = WEIGHT_CLASS_SMALL
custom_materials = list(/datum/material/iron= SMALL_MATERIAL_AMOUNT * 0.5, /datum/material/glass= SMALL_MATERIAL_AMOUNT * 0.5)
grind_results = list(/datum/reagent/iron = 10, /datum/reagent/silicon = 10)
custom_price = PAYCHECK_CREW * 0.5