Files
Bubberstation/code/datums/components/crafting/atmospheric.dm
Bloop 1e443894b5 [MANUAL MIRROR] Fixes toilet bongs, and fixes a serious bug in the crafting system (#18921)
* Fixes toilet bongs, and fixes a serious bug in the crafting system (#72893)

The PR everyone has been waiting for...fixed toilet bong crafting. Now
you can craft them just as before using the new crafting system.

![image](https://user-images.githubusercontent.com/13398309/213944308-74b3e50e-965d-4e69-9025-d011764b3247.png)

In attempting to fix this I encountered one of the gnarliest, nastiest,
meanest and most infuriatingly difficult to debug bugs I have come
across so far. And it's existed for as long as the crafting system has,
but due to unique circumstances it has been allowed to go unnoticed this
whole time.

Technical details below. Full list of changes here:

- crafting recipes can now contain structures as part of their
requirements
- removed deprecated var 'additional_req_tex' and changed text to use
the 'steps' list instead so they actually show in the gui
- toilet bongs are now passable terrain like normal toilets are
- fixed an atrocious bug with crafting that was by pure coincidence not
causing any problems
- this bug would prevent any recipes that did not contain a material
from deleting properly
- this bug would also cause any recipes that are supposed to use but not
consume machinery to consume them regardless

---

Basically, the bug that took me hours upon hours of debugging and
head-scratching to find is this:

from crafting.dm:
```
	main_loop:
		for(var/path_key in requirements)
			amt = R.reqs[path_key] || R.machinery[path_key]
			if(!amt)//since machinery can have 0 aka CRAFTING_MACHINERY_USE - i.e. use it, don't consume it!
				continue main_loop
```
specifically this line:

`amt = R.reqs[path_key] || R.machinery[path_key] `

The culprit ended up being that if you do machinery[path_key] on an
empty list, it can lead to very unexpected behavior (see: EXITING THE
FUNCTION without actually doing anything).

I spent so much time thinking that item deletion wasn't working because
amt was being set to 0, false, or null perhaps when no, it wasn't that.
The function was just exiting out even before the (!amt) check due to
the atrocities committed by someone before me.

Setting amt = `R.reqs[path_key] || R.machinery[path_key]` on the other
hand always evaluates to a positive integer (either the successfully
retrieved reqs amt, or a 1 from the OR expression). It was only by
coincidence that the code did what it was supposed to, because:

1) Every single recipe has R_reqs, so the first part will never cause
the function-exiting failure because the list is never empty.
2) As for the second part of the expression, there are no recipes that
make use of CRAFTING_MACHINERY_USE, so the fact that machinery[path_key]
was never actually being accessed and thus set to a var (which is what
causes the function to exit) didn't matter.

So these two things together have basically allowed a really bad bug to
go unnoticed this whole time. I only noticed it because when trying to
add a third part to the expression it just did not work at all how you
would expect.

The solution is rather simply to add a check like so:
```

	main_loop:
		for(var/path_key in requirements)
			amt = R.reqs?[path_key] || R.machinery?[path_key]
			if(!amt)//since machinery can have 0 aka CRAFTING_MACHINERY_USE - i.e. use it, don't consume it!
				continue main_loop
```

Fixes https://github.com/Skyrat-SS13/Skyrat-tg/issues/18732 .

Fixes a bug with crafting that would inevitably torment someone else as
soon as they tried to add the right kind of recipe, if that hasn't
already happened by now.

<details>
<summary>Toilet bongs are back baby!!</summary>

![image](https://user-images.githubusercontent.com/13398309/213941079-ae7d007a-ca92-4de3-9de6-7a156b4a0618.png)

</details>

🆑
fix: toilet bongs crafting recipes
fix: fixed crafting itself
refactor: cleaned up some old code in the recipes file, added support
for structures in recipes
/🆑

* Update tgui/packages/tgui/interfaces/PersonalCrafting.tsx

Co-authored-by: GoldenAlpharex <58045821+GoldenAlpharex@users.noreply.github.com>

* Update tgui/packages/tgui/interfaces/PersonalCrafting.tsx

Co-authored-by: GoldenAlpharex <58045821+GoldenAlpharex@users.noreply.github.com>

Co-authored-by: GoldenAlpharex <58045821+GoldenAlpharex@users.noreply.github.com>
2023-01-26 16:45:53 -05:00

338 lines
11 KiB
Plaintext

/datum/crafting_recipe/bluespace_vendor_mount
name = "Bluespace Vendor Wall Mount"
result = /obj/item/wallframe/bluespace_vendor_mount
time = 6 SECONDS
reqs = list(
/obj/item/stack/sheet/iron = 15,
/obj/item/stack/sheet/glass = 10,
/obj/item/stack/cable_coil = 10,
)
category = CAT_ATMOSPHERIC
/datum/crafting_recipe/pipe
name = "Smart pipe fitting"
tool_behaviors = list(TOOL_WRENCH)
result = /obj/item/pipe/quaternary/pipe
reqs = list(/obj/item/stack/sheet/iron = 1)
time = 0.5 SECONDS
category = CAT_ATMOSPHERIC
/datum/crafting_recipe/pipe/on_craft_completion(mob/user, atom/result)
var/obj/item/pipe/crafted_pipe = result
crafted_pipe.pipe_type = /obj/machinery/atmospherics/pipe/smart
crafted_pipe.pipe_color = COLOR_VERY_LIGHT_GRAY
crafted_pipe.p_init_dir = ALL_CARDINALS
crafted_pipe.setDir(SOUTH)
crafted_pipe.update()
/datum/crafting_recipe/layer_adapter
name = "Layer manifold fitting"
tool_behaviors = list(TOOL_WRENCH, TOOL_WELDER)
result = /obj/item/pipe/binary/layer_adapter
reqs = list(
/obj/item/pipe = 1,
/obj/item/stack/sheet/iron = 1,
)
time = 1 SECONDS
category = CAT_ATMOSPHERIC
/datum/crafting_recipe/layer_adapter/check_requirements(mob/user, list/collected_requirements)
return atmos_pipe_check(user, collected_requirements)
/datum/crafting_recipe/layer_adapter/on_craft_completion(mob/user, atom/result)
var/obj/item/pipe/crafted_pipe = result
crafted_pipe.pipe_type = /obj/machinery/atmospherics/pipe/layer_manifold
crafted_pipe.pipe_color = COLOR_VERY_LIGHT_GRAY
crafted_pipe.setDir(user.dir)
crafted_pipe.update()
/datum/crafting_recipe/color_adapter
name = "Color adapter fitting"
tool_behaviors = list(TOOL_WRENCH, TOOL_WELDER)
result = /obj/item/pipe/binary/color_adapter
reqs = list(
/obj/item/pipe = 1,
/obj/item/stack/sheet/iron = 1,
)
time = 1 SECONDS
category = CAT_ATMOSPHERIC
/datum/crafting_recipe/color_adapter/check_requirements(mob/user, list/collected_requirements)
return atmos_pipe_check(user, collected_requirements)
/datum/crafting_recipe/color_adapter/on_craft_completion(mob/user, atom/result)
var/obj/item/pipe/crafted_pipe = result
crafted_pipe.pipe_type = /obj/machinery/atmospherics/pipe/color_adapter
crafted_pipe.pipe_color = COLOR_VERY_LIGHT_GRAY
crafted_pipe.setDir(user.dir)
crafted_pipe.update()
/datum/crafting_recipe/he_pipe
name = "H/E pipe fitting"
tool_behaviors = list(TOOL_WRENCH, TOOL_WELDER)
result = /obj/item/pipe/quaternary/he_pipe
reqs = list(
/obj/item/pipe = 1,
/obj/item/stack/sheet/iron = 1,
)
time = 1 SECONDS
category = CAT_ATMOSPHERIC
/datum/crafting_recipe/he_pipe/check_requirements(mob/user, list/collected_requirements)
return atmos_pipe_check(user, collected_requirements)
/datum/crafting_recipe/he_pipe/on_craft_completion(mob/user, atom/result)
var/obj/item/pipe/crafted_pipe = result
crafted_pipe.pipe_type = /obj/machinery/atmospherics/pipe/heat_exchanging/manifold4w
crafted_pipe.pipe_color = COLOR_VERY_LIGHT_GRAY
crafted_pipe.setDir(user.dir)
crafted_pipe.update()
/datum/crafting_recipe/he_junction
name = "H/E junction fitting"
tool_behaviors = list(TOOL_WRENCH, TOOL_WELDER)
result = /obj/item/pipe/directional/he_junction
reqs = list(
/obj/item/pipe = 1,
/obj/item/stack/sheet/iron = 1,
)
time = 1 SECONDS
category = CAT_ATMOSPHERIC
/datum/crafting_recipe/he_junction/check_requirements(mob/user, list/collected_requirements)
return atmos_pipe_check(user, collected_requirements)
/datum/crafting_recipe/he_junction/on_craft_completion(mob/user, atom/result)
var/obj/item/pipe/crafted_pipe = result
crafted_pipe.pipe_type = /obj/machinery/atmospherics/pipe/heat_exchanging/junction
crafted_pipe.pipe_color = COLOR_VERY_LIGHT_GRAY
crafted_pipe.setDir(user.dir)
crafted_pipe.update()
/datum/crafting_recipe/pressure_pump
name = "Pressure pump fitting"
tool_behaviors = list(TOOL_WRENCH, TOOL_WELDER)
result = /obj/item/pipe/binary/pressure_pump
reqs = list(
/obj/item/pipe = 1,
/obj/item/stack/sheet/iron = 5,
/obj/item/stack/cable_coil = 5,
)
time = 2 SECONDS
category = CAT_ATMOSPHERIC
/datum/crafting_recipe/pressure_pump/check_requirements(mob/user, list/collected_requirements)
return atmos_pipe_check(user, collected_requirements)
/datum/crafting_recipe/pressure_pump/on_craft_completion(mob/user, atom/result)
var/obj/item/pipe/crafted_pipe = result
crafted_pipe.pipe_type = /obj/machinery/atmospherics/components/binary/pump
crafted_pipe.pipe_color = COLOR_VERY_LIGHT_GRAY
crafted_pipe.setDir(user.dir)
crafted_pipe.update()
/datum/crafting_recipe/manual_valve
name = "Manual valve fitting"
tool_behaviors = list(TOOL_WRENCH, TOOL_WELDER)
result = /obj/item/pipe/binary/manual_valve
reqs = list(
/obj/item/pipe = 1,
/obj/item/stack/sheet/iron = 1,
)
time = 2 SECONDS
category = CAT_ATMOSPHERIC
/datum/crafting_recipe/manual_valve/check_requirements(mob/user, list/collected_requirements)
return atmos_pipe_check(user, collected_requirements)
/datum/crafting_recipe/manual_valve/on_craft_completion(mob/user, atom/result)
var/obj/item/pipe/crafted_pipe = result
crafted_pipe.pipe_type = /obj/machinery/atmospherics/components/binary/valve
crafted_pipe.pipe_color = COLOR_VERY_LIGHT_GRAY
crafted_pipe.setDir(user.dir)
crafted_pipe.update()
/datum/crafting_recipe/vent
name = "Vent pump fitting"
tool_behaviors = list(TOOL_WRENCH, TOOL_WELDER)
result = /obj/item/pipe/directional/vent
reqs = list(
/obj/item/pipe = 1,
/obj/item/stack/sheet/iron = 5,
/obj/item/stack/cable_coil = 5,
)
time = 2 SECONDS
category = CAT_ATMOSPHERIC
/datum/crafting_recipe/vent/check_requirements(mob/user, list/collected_requirements)
return atmos_pipe_check(user, collected_requirements)
/datum/crafting_recipe/vent/on_craft_completion(mob/user, atom/result)
var/obj/item/pipe/crafted_pipe = result
crafted_pipe.pipe_type = /obj/machinery/atmospherics/components/unary/vent_pump
crafted_pipe.pipe_color = COLOR_VERY_LIGHT_GRAY
crafted_pipe.setDir(user.dir)
crafted_pipe.update()
/datum/crafting_recipe/scrubber
name = "Scrubber fitting"
tool_behaviors = list(TOOL_WRENCH, TOOL_WELDER)
result = /obj/item/pipe/directional/scrubber
reqs = list(
/obj/item/pipe = 1,
/obj/item/stack/sheet/iron = 5,
/obj/item/stack/cable_coil = 5,
)
time = 2 SECONDS
category = CAT_ATMOSPHERIC
/datum/crafting_recipe/scrubber/check_requirements(mob/user, list/collected_requirements)
return atmos_pipe_check(user, collected_requirements)
/datum/crafting_recipe/scrubber/on_craft_completion(mob/user, atom/result)
var/obj/item/pipe/crafted_pipe = result
crafted_pipe.pipe_type = /obj/machinery/atmospherics/components/unary/vent_scrubber
crafted_pipe.pipe_color = COLOR_VERY_LIGHT_GRAY
crafted_pipe.setDir(user.dir)
crafted_pipe.update()
/datum/crafting_recipe/filter
name = "Filter fitting"
tool_behaviors = list(TOOL_WRENCH, TOOL_WELDER)
result = /obj/item/pipe/trinary/flippable/filter
reqs = list(
/obj/item/pipe = 1,
/obj/item/stack/sheet/iron = 5,
/obj/item/stack/cable_coil = 5,
)
time = 2 SECONDS
category = CAT_ATMOSPHERIC
/datum/crafting_recipe/filter/check_requirements(mob/user, list/collected_requirements)
return atmos_pipe_check(user, collected_requirements)
/datum/crafting_recipe/filter/on_craft_completion(mob/user, atom/result)
var/obj/item/pipe/crafted_pipe = result
crafted_pipe.pipe_type = /obj/machinery/atmospherics/components/trinary/filter
crafted_pipe.pipe_color = COLOR_VERY_LIGHT_GRAY
crafted_pipe.setDir(user.dir)
crafted_pipe.update()
/datum/crafting_recipe/mixer
name = "Mixer fitting"
tool_behaviors = list(TOOL_WRENCH, TOOL_WELDER)
result = /obj/item/pipe/trinary/flippable/mixer
reqs = list(
/obj/item/pipe = 1,
/obj/item/stack/sheet/iron = 5,
/obj/item/stack/cable_coil = 5,
)
time = 2 SECONDS
category = CAT_ATMOSPHERIC
/datum/crafting_recipe/mixer/check_requirements(mob/user, list/collected_requirements)
return atmos_pipe_check(user, collected_requirements)
/datum/crafting_recipe/mixer/on_craft_completion(mob/user, atom/result)
var/obj/item/pipe/crafted_pipe = result
crafted_pipe.pipe_type = /obj/machinery/atmospherics/components/trinary/mixer
crafted_pipe.pipe_color = COLOR_VERY_LIGHT_GRAY
crafted_pipe.setDir(user.dir)
crafted_pipe.update()
/datum/crafting_recipe/connector
name = "Portable connector fitting"
tool_behaviors = list(TOOL_WRENCH, TOOL_WELDER)
result = /obj/item/pipe/directional/connector
reqs = list(
/obj/item/pipe = 1,
/obj/item/stack/sheet/iron = 1,
)
time = 2 SECONDS
category = CAT_ATMOSPHERIC
/datum/crafting_recipe/connector/check_requirements(mob/user, list/collected_requirements)
return atmos_pipe_check(user, collected_requirements)
/datum/crafting_recipe/connector/on_craft_completion(mob/user, atom/result)
var/obj/item/pipe/crafted_pipe = result
crafted_pipe.pipe_type = /obj/machinery/atmospherics/components/unary/portables_connector
crafted_pipe.pipe_color = COLOR_VERY_LIGHT_GRAY
crafted_pipe.setDir(user.dir)
crafted_pipe.update()
/datum/crafting_recipe/passive_vent
name = "Passive vent fitting"
tool_behaviors = list(TOOL_WRENCH, TOOL_WELDER)
result = /obj/item/pipe/directional/passive_vent
reqs = list(
/obj/item/pipe = 1,
/obj/item/stack/sheet/iron = 1,
)
time = 2 SECONDS
category = CAT_ATMOSPHERIC
/datum/crafting_recipe/passive_vent/check_requirements(mob/user, list/collected_requirements)
return atmos_pipe_check(user, collected_requirements)
/datum/crafting_recipe/passive_vent/on_craft_completion(mob/user, atom/result)
var/obj/item/pipe/crafted_pipe = result
crafted_pipe.pipe_type = /obj/machinery/atmospherics/components/unary/passive_vent
crafted_pipe.pipe_color = COLOR_VERY_LIGHT_GRAY
crafted_pipe.setDir(user.dir)
crafted_pipe.update()
/datum/crafting_recipe/injector
name = "Outlet injector fitting"
tool_behaviors = list(TOOL_WRENCH, TOOL_WELDER)
result = /obj/item/pipe/directional/injector
reqs = list(
/obj/item/pipe = 1,
/obj/item/stack/sheet/iron = 1,
/obj/item/stack/cable_coil = 5,
)
time = 2 SECONDS
category = CAT_ATMOSPHERIC
/datum/crafting_recipe/injector/check_requirements(mob/user, list/collected_requirements)
return atmos_pipe_check(user, collected_requirements)
/datum/crafting_recipe/injector/on_craft_completion(mob/user, atom/result)
var/obj/item/pipe/crafted_pipe = result
crafted_pipe.pipe_type = /obj/machinery/atmospherics/components/unary/outlet_injector
crafted_pipe.pipe_color = COLOR_VERY_LIGHT_GRAY
crafted_pipe.setDir(user.dir)
crafted_pipe.update()
/datum/crafting_recipe/he_exchanger
name = "Heat exchanger fitting"
tool_behaviors = list(TOOL_WRENCH, TOOL_WELDER)
result = /obj/item/pipe/directional/he_exchanger
reqs = list(
/obj/item/pipe = 1,
/obj/item/stack/sheet/plasteel = 1,
)
time = 2 SECONDS
category = CAT_ATMOSPHERIC
/datum/crafting_recipe/he_exchanger/check_requirements(mob/user, list/collected_requirements)
return atmos_pipe_check(user, collected_requirements)
/datum/crafting_recipe/he_exchanger/on_craft_completion(mob/user, atom/result)
var/obj/item/pipe/crafted_pipe = result
crafted_pipe.pipe_type = /obj/machinery/atmospherics/components/unary/heat_exchanger
crafted_pipe.pipe_color = COLOR_VERY_LIGHT_GRAY
crafted_pipe.setDir(user.dir)
crafted_pipe.update()
/datum/crafting_recipe/steam_vent
name = "Steam Vent"
result = /obj/structure/steam_vent
time = 0.8 SECONDS
reqs = list(
/obj/item/stack/sheet/iron = 2,
/obj/item/stack/tile/iron = 1,
/obj/item/stock_parts/water_recycler = 1,
)
category = CAT_ATMOSPHERIC