From 42d25fea27ceac4d2ea331c34f0c93ad23ea0c61 Mon Sep 17 00:00:00 2001
From: Nathan Winters <100448493+CinnamonSnowball@users.noreply.github.com>
Date: Tue, 12 Dec 2023 21:25:12 +0100
Subject: [PATCH] Fixes washing machines sometimes bluespacing crayons (#23385)
* Fix crayon refs not being nulled when opening "empty" washing machines
* all my homies hate magic numbers
* why was this a thing
* all my homies hate using 0|1 as bools
* ever heard of personal space
* `locate()` cleanup
* Spring cleaning
* Remove unused washing machine state
* whoops
* DGamerL review
* Typecache is the way
* Remove extraneous string initialization
* Negative feedback message consistency
* Documentation my beloved
---
code/game/machinery/washing_machine.dm | 271 ++++++++++++-------------
1 file changed, 130 insertions(+), 141 deletions(-)
diff --git a/code/game/machinery/washing_machine.dm b/code/game/machinery/washing_machine.dm
index 4eefbfe2685..6e3243d9c6b 100644
--- a/code/game/machinery/washing_machine.dm
+++ b/code/game/machinery/washing_machine.dm
@@ -1,3 +1,12 @@
+#define OPEN_EMPTY 1
+#define CLOSED_EMPTY 2
+#define OPEN_FULL 3
+#define CLOSED_FULL 4
+#define RUNNING 5
+//#define OPEN_BLOODY 6 is tied to an unused icon state
+#define CLOSED_BLOODY 7
+#define RUNNING_BLOODY 8
+
/obj/machinery/washing_machine
name = "washing machine"
desc = "Gets rid of those pesky bloodstains, or your money back!"
@@ -5,21 +14,42 @@
icon_state = "wm_10"
density = TRUE
anchored = TRUE
- var/state = 1
- //1 = empty, open door
- //2 = empty, closed door
- //3 = full, open door
- //4 = full, closed door
- //5 = running
- //6 = blood, open door
- //7 = blood, closed door
- //8 = blood, running
+ /// Integer ID corresponding to whether the machine can accept more items, is running, will produce gibs, etc.
+ var/state = OPEN_EMPTY
var/panel = FALSE
- //FALSE = closed
- //TRUE = open
- var/hacked = TRUE //Bleh, screw hacking, let's have it hacked by default.
- var/gibs_ready = 0
+ var/gibs_ready = FALSE
var/obj/crayon
+ /// Typecache of washable items
+ var/list/can_be_washed = list(
+ /obj/item/stack/sheet/hairlesshide,
+ /obj/item/clothing/under,
+ /obj/item/clothing/mask,
+ /obj/item/clothing/head,
+ /obj/item/clothing/gloves,
+ /obj/item/clothing/shoes,
+ /obj/item/clothing/suit,
+ /obj/item/bedsheet
+ )
+ /// Typecache of items that do not fit, overrides the whitelist
+ var/list/does_not_fit = list(
+ /obj/item/clothing/under/plasmaman,
+ /obj/item/clothing/suit/space,
+ /obj/item/clothing/suit/syndicatefake,
+ /obj/item/clothing/suit/cyborg_suit,
+ /obj/item/clothing/suit/bomb_suit,
+ /obj/item/clothing/suit/armor,
+ /obj/item/clothing/mask/gas,
+ /obj/item/clothing/mask/cigarette,
+ /obj/item/clothing/head/syndicatefake,
+ /obj/item/clothing/head/helmet,
+ /obj/item/clothing/gloves/furgloves
+ )
+
+/obj/machinery/washing_machine/Initialize(mapload)
+ . = ..()
+
+ can_be_washed = typecacheof(can_be_washed)
+ does_not_fit = typecacheof(does_not_fit)
/obj/machinery/washing_machine/examine(mob/user)
. = ..()
@@ -31,52 +61,51 @@
start(user)
/obj/machinery/washing_machine/proc/start(mob/user)
- if(state != 4)
+ if(state != CLOSED_FULL)
to_chat(user, "The washing machine cannot run in this state.")
return
- if(locate(/mob,contents))
- state = 8
+ if(locate(/mob) in src)
+ state = RUNNING_BLOODY
else
- state = 5
+ state = RUNNING
update_icon(UPDATE_ICON_STATE)
sleep(200)
- for(var/atom/A in contents)
+ for(var/atom/A in src)
A.clean_blood()
//Tanning!
- for(var/obj/item/stack/sheet/hairlesshide/HH in contents)
- var/obj/item/stack/sheet/wetleather/WL = new(src)
- WL.amount = HH.amount
+ for(var/obj/item/stack/sheet/hairlesshide/HH in src)
+ new /obj/item/stack/sheet/wetleather(src, HH.amount)
qdel(HH)
if(crayon)
var/wash_color
- if(istype(crayon,/obj/item/toy/crayon))
+ if(istype(crayon, /obj/item/toy/crayon))
var/obj/item/toy/crayon/CR = crayon
wash_color = CR.colourName
- else if(istype(crayon,/obj/item/stamp))
+ else if(istype(crayon, /obj/item/stamp))
var/obj/item/stamp/ST = crayon
wash_color = ST.item_color
if(wash_color)
- var/new_jumpsuit_icon_state = ""
- var/new_jumpsuit_item_state = ""
- var/new_jumpsuit_name = ""
- var/new_glove_icon_state = ""
- var/new_glove_item_state = ""
- var/new_glove_name = ""
- var/new_bandana_icon_state = ""
- var/new_bandana_item_state = ""
- var/new_bandana_name = ""
- var/new_shoe_icon_state = ""
- var/new_shoe_name = ""
- var/new_sheet_icon_state = ""
- var/new_sheet_name = ""
- var/new_sheet_item_state = ""
- var/new_softcap_icon_state = ""
- var/new_softcap_name = ""
+ var/new_jumpsuit_icon_state
+ var/new_jumpsuit_item_state
+ var/new_jumpsuit_name
+ var/new_glove_icon_state
+ var/new_glove_item_state
+ var/new_glove_name
+ var/new_bandana_icon_state
+ var/new_bandana_item_state
+ var/new_bandana_name
+ var/new_shoe_icon_state
+ var/new_shoe_name
+ var/new_sheet_icon_state
+ var/new_sheet_name
+ var/new_sheet_item_state
+ var/new_softcap_icon_state
+ var/new_softcap_name
var/new_desc = "The colors are a bit dodgy."
for(var/T in typesof(/obj/item/clothing/under))
var/obj/item/clothing/under/J = new T
@@ -131,7 +160,7 @@
break
qdel(H)
if(new_jumpsuit_icon_state && new_jumpsuit_item_state && new_jumpsuit_name)
- for(var/obj/item/clothing/under/J in contents)
+ for(var/obj/item/clothing/under/J in src)
if(!J.dyeable)
continue
J.item_state = new_jumpsuit_item_state
@@ -140,7 +169,7 @@
J.name = new_jumpsuit_name
J.desc = new_desc
if(new_glove_icon_state && new_glove_item_state && new_glove_name)
- for(var/obj/item/clothing/gloves/color/G in contents)
+ for(var/obj/item/clothing/gloves/color/G in src)
if(!G.dyeable)
continue
G.item_state = new_glove_item_state
@@ -150,19 +179,19 @@
if(!istype(G, /obj/item/clothing/gloves/color/black/thief))
G.desc = new_desc
if(new_shoe_icon_state && new_shoe_name)
- for(var/obj/item/clothing/shoes/S in contents)
+ for(var/obj/item/clothing/shoes/S in src)
if(!S.dyeable)
continue
- if(S.chained == 1)
- S.chained = 0
+ if(S.chained)
+ S.chained = FALSE
S.slowdown = SHOES_SLOWDOWN
- new /obj/item/restraints/handcuffs( src )
+ new /obj/item/restraints/handcuffs(src)
S.icon_state = new_shoe_icon_state
S.item_color = wash_color
S.name = new_shoe_name
S.desc = new_desc
if(new_bandana_icon_state && new_bandana_name)
- for(var/obj/item/clothing/mask/bandana/M in contents)
+ for(var/obj/item/clothing/mask/bandana/M in src)
if(!M.dyeable)
continue
M.item_state = new_bandana_item_state
@@ -171,14 +200,14 @@
M.name = new_bandana_name
M.desc = new_desc
if(new_sheet_icon_state && new_sheet_name)
- for(var/obj/item/bedsheet/B in contents)
+ for(var/obj/item/bedsheet/B in src)
B.icon_state = new_sheet_icon_state
B.item_color = wash_color
B.item_state = new_sheet_item_state
B.name = new_sheet_name
B.desc = new_desc
if(new_softcap_icon_state && new_softcap_name)
- for(var/obj/item/clothing/head/soft/H in contents)
+ for(var/obj/item/clothing/head/soft/H in src)
if(!H.dyeable)
continue
H.icon_state = new_softcap_icon_state
@@ -188,143 +217,103 @@
QDEL_NULL(crayon)
- if(locate(/mob,contents))
- state = 7
- gibs_ready = 1
+ if(locate(/mob) in src)
+ state = CLOSED_BLOODY
+ gibs_ready = TRUE
else
- state = 4
+ state = CLOSED_FULL
update_icon(UPDATE_ICON_STATE)
/obj/machinery/washing_machine/update_icon_state()
icon_state = "wm_[state][panel]"
-/obj/machinery/washing_machine/attackby(obj/item/W as obj, mob/user as mob, params)
+/obj/machinery/washing_machine/attackby(obj/item/W, mob/user, params)
if(default_unfasten_wrench(user, W))
return
- if(istype(W,/obj/item/toy/crayon) ||istype(W,/obj/item/stamp))
- if(state in list( 1, 3, 6))
+ if(istype(W, /obj/item/toy/crayon) || istype(W, /obj/item/stamp))
+ if(state in list(OPEN_EMPTY, OPEN_FULL))
if(!crayon)
user.drop_item()
crayon = W
- crayon.loc = src
+ crayon.forceMove(src)
update_icon(UPDATE_ICON_STATE)
else
return ..()
else
return ..()
- else if(istype(W,/obj/item/grab))
- if((state == 1) && hacked)
+ else if(istype(W, /obj/item/grab))
+ if(state == OPEN_EMPTY)
var/obj/item/grab/G = W
if(ishuman(G.assailant) && iscorgi(G.affecting))
- G.affecting.loc = src
+ G.affecting.forceMove(src)
qdel(G)
- state = 3
+ state = OPEN_FULL
update_icon(UPDATE_ICON_STATE)
else
return ..()
- else if(istype(W,/obj/item/stack/sheet/hairlesshide) || \
- istype(W,/obj/item/clothing/under) || \
- istype(W,/obj/item/clothing/mask) || \
- istype(W,/obj/item/clothing/head) || \
- istype(W,/obj/item/clothing/gloves) || \
- istype(W,/obj/item/clothing/shoes) || \
- istype(W,/obj/item/clothing/suit) || \
- istype(W,/obj/item/bedsheet))
-
- //YES, it's hardcoded... saves a var/can_be_washed for every single clothing item.
- if(istype(W,/obj/item/clothing/under/plasmaman))
- to_chat(user, "This item does not fit.")
- return
- if(istype(W,/obj/item/clothing/suit/space))
- to_chat(user, "This item does not fit.")
- return
- if(istype(W,/obj/item/clothing/suit/syndicatefake))
- to_chat(user, "This item does not fit.")
- return
-// if(istype(W,/obj/item/clothing/suit/powered))
-// to_chat(user, "This item does not fit.")
-// return
- if(istype(W,/obj/item/clothing/suit/cyborg_suit))
- to_chat(user, "This item does not fit.")
- return
- if(istype(W,/obj/item/clothing/suit/bomb_suit))
- to_chat(user, "This item does not fit.")
- return
- if(istype(W,/obj/item/clothing/suit/armor))
- to_chat(user, "This item does not fit.")
- return
- if(istype(W,/obj/item/clothing/mask/gas))
- to_chat(user, "This item does not fit.")
- return
- if(istype(W,/obj/item/clothing/mask/cigarette))
- to_chat(user, "This item does not fit.")
- return
- if(istype(W,/obj/item/clothing/head/syndicatefake))
- to_chat(user, "This item does not fit.")
- return
-// if(istype(W,/obj/item/clothing/head/powered))
-// to_chat(user, "This item does not fit.")
-// return
- if(istype(W,/obj/item/clothing/head/helmet))
- to_chat(user, "This item does not fit.")
- return
- if(istype(W,/obj/item/clothing/gloves/furgloves))
- to_chat(user, "This item does not fit.")
+ else if(is_type_in_typecache(W, can_be_washed))
+ if(is_type_in_typecache(W, does_not_fit))
+ to_chat(user, "This item does not fit.")
return
if(istype(W, /obj/item/clothing/gloves/color/black/krav_maga/sec))
to_chat(user, "Washing these gloves would fry the electronics!")
return
- if(W.flags & NODROP) //if "can't drop" item
- to_chat(user, "\The [W] is stuck to your hand, you cannot put it in the washing machine!")
+ if(W.flags & NODROP)
+ to_chat(user, "[W] is stuck to your hand!")
return
- if(contents.len < 5)
- if(state in list(1, 3))
+ if(length(contents) < 5)
+ if(state in list(OPEN_EMPTY, OPEN_FULL))
user.drop_item()
- W.loc = src
- state = 3
+ W.forceMove(src)
+ state = OPEN_FULL
else
- to_chat(user, "You can't put the item in right now.")
+ to_chat(user, "The door is closed!")
else
- to_chat(user, "The washing machine is full.")
+ to_chat(user, "[src] is full!")
update_icon(UPDATE_ICON_STATE)
else
return ..()
-/obj/machinery/washing_machine/attack_hand(mob/user as mob)
+/obj/machinery/washing_machine/attack_hand(mob/user)
switch(state)
- if(1)
- state = 2
- if(2)
- state = 1
- for(var/atom/movable/O in contents)
- O.loc = src.loc
- if(3)
- state = 4
- if(4)
- state = 3
- for(var/atom/movable/O in contents)
- O.loc = src.loc
+ if(OPEN_EMPTY)
+ state = CLOSED_EMPTY
+ if(CLOSED_EMPTY)
+ for(var/atom/movable/O in src)
+ O.forceMove(loc)
crayon = null
- state = 1
- if(5)
+ state = OPEN_EMPTY
+ if(OPEN_FULL)
+ state = CLOSED_FULL
+ if(CLOSED_FULL)
+ for(var/atom/movable/O in src)
+ O.forceMove(loc)
+ crayon = null
+ state = OPEN_EMPTY
+ if(RUNNING)
to_chat(user, "[src] is busy.")
- if(6)
- state = 7
- if(7)
+ if(CLOSED_BLOODY)
if(gibs_ready)
- gibs_ready = 0
- if(locate(/mob,contents))
- var/mob/M = locate(/mob,contents)
+ gibs_ready = FALSE
+ if(locate(/mob) in src)
+ var/mob/M = locate() in src
M.gib()
- for(var/atom/movable/O in contents)
- O.loc = src.loc
+ for(var/atom/movable/O in src)
+ O.forceMove(loc)
crayon = null
- state = 1
-
+ state = OPEN_EMPTY
update_icon(UPDATE_ICON_STATE)
/obj/machinery/washing_machine/deconstruct(disassembled = TRUE)
new /obj/item/stack/sheet/metal(drop_location(), 2)
qdel(src)
+
+#undef OPEN_EMPTY
+#undef CLOSED_EMPTY
+#undef OPEN_FULL
+#undef CLOSED_FULL
+#undef RUNNING
+#undef CLOSED_BLOODY
+#undef RUNNING_BLOODY