diff --git a/code/__defines/misc.dm b/code/__defines/misc.dm
index afbf69eacdd..eaf542868ea 100644
--- a/code/__defines/misc.dm
+++ b/code/__defines/misc.dm
@@ -286,7 +286,9 @@
#define get_turf(A) (get_step(A, 0))
#define QDELETED(TARGET) (!TARGET || TARGET.gcDestroyed)
-#define QDEL_NULL(thing) qdel(thing); thing = null
+#define QDEL_NULL(item) qdel(item); item = null
+// Shim until addtimer is merged or I figure out if it is safe to use scheduler for this.
+#define QDEL_IN(OBJ, TIME) spawn(TIME) qdel(OBJ)
//Recipe type defines. Used to determine what machine makes them
#define MICROWAVE 0x1
diff --git a/code/_onclick/hud/parallax.dm b/code/_onclick/hud/parallax.dm
index ced3f8681ff..b45dce4e0f0 100644
--- a/code/_onclick/hud/parallax.dm
+++ b/code/_onclick/hud/parallax.dm
@@ -27,14 +27,12 @@ var/list/parallax_icon[(GRID_WIDTH**2)*3]
blend_mode = BLEND_ADD
layer = AREA_LAYER
plane = PLANE_SPACE_PARALLAX
- globalscreen = 1
var/parallax_speed = 0
/obj/screen/plane_master
appearance_flags = PLANE_MASTER
screen_loc = "CENTER,CENTER"
- globalscreen = 1
-
+
/obj/screen/plane_master/parallax_master
plane = PLANE_SPACE_PARALLAX
blend_mode = BLEND_MULTIPLY
@@ -74,15 +72,15 @@ var/list/parallax_icon[(GRID_WIDTH**2)*3]
var/client/C = mymob.client
if(!C.parallax_master)
- C.parallax_master = getFromPool(/obj/screen/plane_master/parallax_master)
+ C.parallax_master = new /obj/screen/plane_master/parallax_master
if(!C.parallax_spacemaster)
- C.parallax_spacemaster = getFromPool(/obj/screen/plane_master/parallax_spacemaster)
+ C.parallax_spacemaster = new /obj/screen/plane_master/parallax_spacemaster
if(!C.parallax_dustmaster)
- C.parallax_dustmaster = getFromPool(/obj/screen/plane_master/parallax_dustmaster)
+ C.parallax_dustmaster = new /obj/screen/plane_master/parallax_dustmaster
if(!C.parallax.len)
for(var/obj/screen/parallax/bgobj in parallax_icon)
- var/obj/screen/parallax/parallax_layer = getFromPool(/obj/screen/parallax)
+ var/obj/screen/parallax/parallax_layer = new /obj/screen/parallax
parallax_layer.appearance = bgobj.appearance
parallax_layer.base_offset_x = bgobj.base_offset_x
parallax_layer.base_offset_y = bgobj.base_offset_y
@@ -182,7 +180,7 @@ var/list/parallax_icon[(GRID_WIDTH**2)*3]
pixel_y += WORLD_ICON_SIZE * round(i/PARALLAX_IMAGE_WIDTH)
for(var/i in 0 to ((GRID_WIDTH**2)-1))
- var/obj/screen/parallax/parallax_layer = getFromPool(/obj/screen/parallax)
+ var/obj/screen/parallax/parallax_layer = new /obj/screen/parallax
var/list/L = list()
for(var/j in 1 to PARALLAX_IMAGE_TILES)
@@ -199,7 +197,7 @@ var/list/parallax_icon[(GRID_WIDTH**2)*3]
index++
for(var/i in 0 to ((GRID_WIDTH**2)-1))
- var/obj/screen/parallax/parallax_layer = getFromPool(/obj/screen/parallax)
+ var/obj/screen/parallax/parallax_layer = new /obj/screen/parallax
var/list/L = list()
for(var/j in 1 to PARALLAX_IMAGE_TILES)
@@ -216,7 +214,7 @@ var/list/parallax_icon[(GRID_WIDTH**2)*3]
index++
for(var/i in 0 to ((GRID_WIDTH**2)-1))
- var/obj/screen/parallax/parallax_layer = getFromPool(/obj/screen/parallax)
+ var/obj/screen/parallax/parallax_layer = new /obj/screen/parallax
var/list/L = list()
for(var/j in 1 to PARALLAX_IMAGE_TILES)
if(plane3[j+i*PARALLAX_IMAGE_TILES] <= PARALLAX2_ICON_NUMBER)
diff --git a/code/_onclick/hud/screen_objects.dm b/code/_onclick/hud/screen_objects.dm
index a9fc180e2a1..5fe3f7f7bd6 100644
--- a/code/_onclick/hud/screen_objects.dm
+++ b/code/_onclick/hud/screen_objects.dm
@@ -12,10 +12,10 @@
layer = 20.0
unacidable = 1
var/obj/master = null //A reference to the object in the slot. Grabs or items, generally.
- var/globalscreen = 0 // TODO: Screen pooling.
/obj/screen/Destroy()
master = null
+ screen_loc = null
return ..()
/obj/screen/text
diff --git a/code/_onclick/telekinesis.dm b/code/_onclick/telekinesis.dm
index 7344eed309a..9585d0b4c43 100644
--- a/code/_onclick/telekinesis.dm
+++ b/code/_onclick/telekinesis.dm
@@ -74,13 +74,19 @@ var/const/tk_maxrange = 15
var/atom/movable/focus = null
var/mob/living/host = null
+/obj/item/tk_grab/Destroy()
+ if (host)
+ host.remove_from_mob(src)
+ host = null
+ focus = null
+ return ..()
+
/obj/item/tk_grab/dropped(mob/user as mob)
if(focus && user && loc != user && loc != user.loc) // drop_item() gets called when you tk-attack a table/closet with an item
if(focus.Adjacent(loc))
focus.loc = loc
loc = null
- spawn(1)
- qdel(src)
+ QDEL_IN(src, 1)
return
//stops TK grabs being equipped anywhere but into hands
@@ -157,7 +163,7 @@ var/const/tk_maxrange = 15
/obj/item/tk_grab/proc/apply_focus_overlay()
if(!focus) return
- var/obj/effect/overlay/O = getFromPool(/obj/effect/overlay, locate(focus.x,focus.y,focus.z))
+ var/obj/effect/overlay/O = new(locate(focus.x,focus.y,focus.z))
O.name = "sparkles"
O.anchored = 1
O.density = 0
@@ -166,9 +172,7 @@ var/const/tk_maxrange = 15
O.icon = 'icons/effects/effects.dmi'
O.icon_state = "nothing"
flick("empdisable",O)
- spawn(5)
- qdel(O)
- return
+ QDEL_IN(O, 5)
/obj/item/tk_grab/update_icon()
overlays.Cut()
diff --git a/code/game/machinery/computer/message.dm b/code/game/machinery/computer/message.dm
index c8ddad2a140..b8f1638c4bd 100644
--- a/code/game/machinery/computer/message.dm
+++ b/code/game/machinery/computer/message.dm
@@ -33,6 +33,12 @@
..()
spark_system = bind_spark(src, 5)
+/obj/machinery/computer/message_monitor/Destroy()
+ QDEL_NULL(spark_system)
+ linkedServer = null
+ customrecepient = null
+ return ..()
+
/obj/machinery/computer/message_monitor/attackby(obj/item/weapon/O as obj, mob/living/user as mob)
if(stat & (NOPOWER|BROKEN))
..()
diff --git a/code/game/machinery/teleporter.dm b/code/game/machinery/teleporter.dm
index 640e5cfa2f8..e83fba6d060 100644
--- a/code/game/machinery/teleporter.dm
+++ b/code/game/machinery/teleporter.dm
@@ -179,6 +179,11 @@
underlays += image('icons/obj/stationobjs.dmi', icon_state = "tele-wires")
spark_system = bind_spark(src, 5, alldirs)
+/obj/machinery/teleport/hub/Destroy()
+ QDEL_NULL(spark_system)
+ com = null
+ return ..()
+
/obj/machinery/teleport/hub/Bumped(M as mob|obj)
spawn()
if (src.icon_state == "tele1")
diff --git a/code/game/machinery/vending.dm b/code/game/machinery/vending.dm
index bc658b7faf8..c8aebd18d8c 100644
--- a/code/game/machinery/vending.dm
+++ b/code/game/machinery/vending.dm
@@ -237,7 +237,7 @@
anchored = !anchored
return
- else
+ else if (!is_borg_item(W))
for(var/datum/data/vending_product/R in product_records)
if(istype(W, R.product_path))
@@ -245,6 +245,8 @@
qdel(W)
return
..()
+ else
+ ..()
/**
* Receive payment with cashmoney.
diff --git a/code/game/mecha/equipment/tracking_beacon.dm b/code/game/mecha/equipment/tracking_beacon.dm
index 92787c3873d..d45b7d7aab5 100644
--- a/code/game/mecha/equipment/tracking_beacon.dm
+++ b/code/game/mecha/equipment/tracking_beacon.dm
@@ -12,6 +12,10 @@
if (in_mecha())
exo_beacons.Add(src)//For the sake of exosuits which spawn with a preinstalled tracking beacon
+/obj/item/mecha_parts/mecha_tracking/Destroy()
+ exo_beacons.Remove(src)
+ return ..()
+
/obj/item/mecha_parts/mecha_tracking/proc/get_mecha_info()
if(!in_mecha())
return 0
diff --git a/code/game/objects/items/devices/PDA/cart.dm b/code/game/objects/items/devices/PDA/cart.dm
index 2c91285e084..85bde90cc4a 100644
--- a/code/game/objects/items/devices/PDA/cart.dm
+++ b/code/game/objects/items/devices/PDA/cart.dm
@@ -116,7 +116,7 @@
/obj/item/weapon/cartridge/signal/Destroy()
qdel(radio)
- ..()
+ return ..()
/obj/item/weapon/cartridge/quartermaster
name = "\improper Space Parts & Space Vendors cartridge"
@@ -436,7 +436,7 @@
else
JaniData["user_loc"] = list("x" = 0, "y" = 0)
var/MopData[0]
- for(var/obj/item/weapon/mop/M in world)
+ for(var/obj/item/weapon/mop/M in global.janitorial_supplies)
var/turf/ml = get_turf(M)
if(ml)
if(ml.z != cl.z)
@@ -447,9 +447,8 @@
if(!MopData.len)
MopData[++MopData.len] = list("x" = 0, "y" = 0, dir=null, status = null)
-
var/BucketData[0]
- for(var/obj/structure/mopbucket/B in world)
+ for(var/obj/structure/mopbucket/B in global.janitorial_supplies)
var/turf/bl = get_turf(B)
if(bl)
if(bl.z != cl.z)
@@ -461,7 +460,7 @@
BucketData[++BucketData.len] = list("x" = 0, "y" = 0, dir=null, status = null)
var/CbotData[0]
- for(var/mob/living/bot/cleanbot/B in world)
+ for(var/mob/living/bot/cleanbot/B in global.janitorial_supplies)
var/turf/bl = get_turf(B)
if(bl)
if(bl.z != cl.z)
@@ -469,23 +468,19 @@
var/direction = get_dir(src,B)
CbotData[++CbotData.len] = list("x" = bl.x, "y" = bl.y, "dir" = uppertext(dir2text(direction)), "status" = B.on ? "Online" : "Offline")
-
if(!CbotData.len)
CbotData[++CbotData.len] = list("x" = 0, "y" = 0, dir=null, status = null)
var/CartData[0]
- for(var/obj/structure/janitorialcart/B in world)
+ for(var/obj/structure/janitorialcart/B in global.janitorial_supplies)
var/turf/bl = get_turf(B)
if(bl)
if(bl.z != cl.z)
continue
var/direction = get_dir(src,B)
- CartData[++CartData.len] = list("x" = bl.x, "y" = bl.y, "dir" = uppertext(dir2text(direction)), "status" = B.reagents.total_volume/100)
+ CartData[++CartData.len] = list("x" = bl.x, "y" = bl.y, "dir" = uppertext(dir2text(direction)), "status" = B.get_short_status())
if(!CartData.len)
CartData[++CartData.len] = list("x" = 0, "y" = 0, dir=null, status = null)
-
-
-
JaniData["mops"] = MopData
JaniData["buckets"] = BucketData
JaniData["cleanbots"] = CbotData
@@ -495,9 +490,6 @@
return values
-
-
-
/obj/item/weapon/cartridge/Topic(href, href_list)
..()
diff --git a/code/game/objects/items/weapons/cards_ids.dm b/code/game/objects/items/weapons/cards_ids.dm
index fa1078aeec9..8dfbc83145f 100644
--- a/code/game/objects/items/weapons/cards_ids.dm
+++ b/code/game/objects/items/weapons/cards_ids.dm
@@ -120,6 +120,10 @@ var/const/NO_EMAG_ACT = -50
var/rank = null //actual job
var/dorm = 0 // determines if this ID has claimed a dorm already
+/obj/item/weapon/card/id/Destroy()
+ mob = null
+ return ..()
+
/obj/item/weapon/card/id/examine(mob/user)
set src in oview(1)
if(in_range(usr, src))
diff --git a/code/game/objects/items/weapons/material/twohanded.dm b/code/game/objects/items/weapons/material/twohanded.dm
index 492b70d2428..2d59c848e4b 100644
--- a/code/game/objects/items/weapons/material/twohanded.dm
+++ b/code/game/objects/items/weapons/material/twohanded.dm
@@ -106,6 +106,7 @@
var/obj/item/weapon/material/twohanded/offhand/O = user.get_inactive_hand()
if(O && istype(O))
+ user.u_equip(O)
O.unwield()
else //Trying to wield it
@@ -137,9 +138,17 @@
default_material = "placeholder"
/obj/item/weapon/material/twohanded/offhand/unwield()
+ if (ismob(loc))
+ var/mob/living/our_mob = loc
+ our_mob.remove_from_mob(src)
+
qdel(src)
/obj/item/weapon/material/twohanded/offhand/wield()
+ if (ismob(loc))
+ var/mob/living/our_mob = loc
+ our_mob.remove_from_mob(src)
+
qdel(src)
/obj/item/weapon/material/twohanded/offhand/update_icon()
diff --git a/code/game/objects/items/weapons/melee/energy.dm b/code/game/objects/items/weapons/melee/energy.dm
index 3c0f7623b63..45d9aef2c6c 100644
--- a/code/game/objects/items/weapons/melee/energy.dm
+++ b/code/game/objects/items/weapons/melee/energy.dm
@@ -18,6 +18,10 @@
spark_system = bind_spark(src, 5)
..()
+/obj/item/weapon/melee/energy/Destroy()
+ QDEL_NULL(spark_system)
+ return ..()
+
/obj/item/weapon/melee/energy/proc/activate(mob/living/user)
anchored = 1
if(active)
diff --git a/code/game/objects/items/weapons/mop.dm b/code/game/objects/items/weapons/mop.dm
index e50ce867967..e60df528ed1 100644
--- a/code/game/objects/items/weapons/mop.dm
+++ b/code/game/objects/items/weapons/mop.dm
@@ -12,9 +12,14 @@
var/mopping = 0
var/mopcount = 0
-
/obj/item/weapon/mop/New()
+ ..()
create_reagents(30)
+ janitorial_supplies |= src
+
+/obj/item/weapon/mop/Destroy()
+ janitorial_supplies -= src
+ return ..()
/obj/item/weapon/mop/afterattack(atom/A, mob/user, proximity)
if(!proximity) return
diff --git a/code/game/objects/structures/janicart.dm b/code/game/objects/structures/janicart.dm
index f2ad59d0cdf..753af5a8e10 100644
--- a/code/game/objects/structures/janicart.dm
+++ b/code/game/objects/structures/janicart.dm
@@ -22,8 +22,21 @@
var/has_items = 0//This is set true whenever the cart has anything loaded/mounted on it
var/dismantled = 0//This is set true after the object has been dismantled to avoid an infintie loop
-///obj/structure/janitorialcart/New()
+/obj/structure/janitorialcart/New()
+ ..()
+ janitorial_supplies |= src
+/obj/structure/janitorialcart/Destroy()
+ janitorial_supplies -= src
+ QDEL_NULL(mybag)
+ QDEL_NULL(mymop)
+ QDEL_NULL(myspray)
+ QDEL_NULL(myreplacer)
+ QDEL_NULL(mybucket)
+ return ..()
+
+/obj/structure/janitorialcart/proc/get_short_status()
+ return "Contents: [english_list(contents)]"
/obj/structure/janitorialcart/examine(mob/user)
if(..(user, 1))
diff --git a/code/game/objects/structures/mop_bucket.dm b/code/game/objects/structures/mop_bucket.dm
index 6e3807c30cf..00bb35a041a 100644
--- a/code/game/objects/structures/mop_bucket.dm
+++ b/code/game/objects/structures/mop_bucket.dm
@@ -10,12 +10,17 @@
/obj/structure/mopbucket/New()
- create_reagents(100)
..()
+ create_reagents(100)
+ janitorial_supplies |= src
+
+/obj/structure/mobbucket/Destroy()
+ janitorial_supplies -= src
+ return ..()
/obj/structure/mopbucket/examine(mob/user)
if(..(user, 1))
- user << "[src] \icon[src] contains [reagents.total_volume] unit\s of water!"
+ user << "Contains [reagents.total_volume] unit\s of water."
/obj/structure/mopbucket/attackby(obj/item/I, mob/user)
if(istype(I, /obj/item/weapon/mop))
diff --git a/code/game/objects/structures/window_spawner.dm b/code/game/objects/structures/window_spawner.dm
index a1cec9eb55c..966d6e8e0e1 100644
--- a/code/game/objects/structures/window_spawner.dm
+++ b/code/game/objects/structures/window_spawner.dm
@@ -35,7 +35,7 @@
/obj/effect/wingrille_spawn/proc/activate()
if(activated) return
if (!locate(/obj/structure/grille) in get_turf(src))
- var/obj/structure/grille/G = getFromPool(/obj/structure/grille, src.loc)
+ var/obj/structure/grille/G = new /obj/structure/grille(src.loc)
handle_grille_spawn(G)
var/list/neighbours = list()
for (var/dir in cardinal)
@@ -49,7 +49,7 @@
found_connection = 1
qdel(W)
if(!found_connection)
- var/obj/structure/window/new_win = getFromPool(win_path, src.loc)
+ var/obj/structure/window/new_win = new win_path(src.loc)
new_win.set_dir(dir)
handle_window_spawn(new_win)
else
diff --git a/code/game/turfs/initialization/maintenance.dm b/code/game/turfs/initialization/maintenance.dm
index 833c0cd68dc..558f6385882 100644
--- a/code/game/turfs/initialization/maintenance.dm
+++ b/code/game/turfs/initialization/maintenance.dm
@@ -15,9 +15,10 @@
T.update_dirt()
if(prob(2))
- getFromPool(junk(), T)
+ var/type = junk()
+ new type(T)
if(prob(2))
- getFromPool(/obj/effect/decal/cleanable/blood/oil, T)
+ new /obj/effect/decal/cleanable/blood/oil(T)
if(prob(25)) // Keep in mind that only "corners" get any sort of web
attempt_web(T, cardinal_turfs)
@@ -54,7 +55,7 @@ var/global/list/random_junk
var/turf/neighbour = get_step(T, dir)
if(neighbour && neighbour.density)
if(dir == WEST)
- getFromPool(/obj/effect/decal/cleanable/cobweb, T)
+ new /obj/effect/decal/cleanable/cobweb(T)
if(dir == EAST)
- getFromPool(/obj/effect/decal/cleanable/cobweb2, T)
+ new /obj/effect/decal/cleanable/cobweb2(T)
return
diff --git a/code/game/turfs/turf.dm b/code/game/turfs/turf.dm
index 7a1bfad07a1..fb8ab56af28 100644
--- a/code/game/turfs/turf.dm
+++ b/code/game/turfs/turf.dm
@@ -143,7 +143,7 @@ var/const/enterloopsanity = 100
M.make_floating(0)
..()
var/objects = 0
- if(A && (A.flags & PROXMOVE))
+ if(A && (A.flags & PROXMOVE) && A.simulated)
for(var/atom/movable/thing in range(1))
if(objects > enterloopsanity) break
objects++
diff --git a/code/global.dm b/code/global.dm
index 74fb936d0f3..1ef56d9bf1b 100644
--- a/code/global.dm
+++ b/code/global.dm
@@ -15,6 +15,7 @@ var/global/list/active_diseases = list()
var/global/list/med_hud_users = list() // List of all entities using a medical HUD.
var/global/list/sec_hud_users = list() // List of all entities using a security HUD.
var/global/list/hud_icon_reference = list()
+var/global/list/janitorial_supplies = list() // List of all the janitorial supplies on the map that the PDA cart may be tracking.
var/global/list/global_mutations = list() // List of hidden mutation things.
diff --git a/code/modules/client/preference_setup/general/02_language.dm b/code/modules/client/preference_setup/general/02_language.dm
index bc2d74e32fb..b147871ffd2 100644
--- a/code/modules/client/preference_setup/general/02_language.dm
+++ b/code/modules/client/preference_setup/general/02_language.dm
@@ -75,6 +75,9 @@
else
var/new_lang = input(user, "Select an additional language", "Character Generation", null) as null|anything in available_languages
if(new_lang)
- pref.alternate_languages |= new_lang
+ if (pref.alternate_languages.len >= S.num_alternate_languages)
+ alert(user, "You have already selected the maximum number of alternate languages for this species!")
+ else
+ pref.alternate_languages |= new_lang
return TOPIC_REFRESH
return ..()
diff --git a/code/modules/economy/ATM.dm b/code/modules/economy/ATM.dm
index 3c211144a71..85edb8f37e7 100644
--- a/code/modules/economy/ATM.dm
+++ b/code/modules/economy/ATM.dm
@@ -32,12 +32,19 @@ log transactions
var/obj/item/weapon/card/held_card
var/editing_security_level = 0
var/view_screen = NO_SCREEN
- var/datum/effect_system/sparks/spark_system
-/obj/machinery/atm/New()
+/obj/machinery/atm/initialize()
..()
machine_id = "[station_name()] RT #[num_financial_terminals++]"
- spark_system = bind_spark(src, 5)
+
+/obj/machinery/atm/Destroy()
+ authenticated_account = null
+ if (held_card)
+ held_card.forceMove(loc)
+ held_card = null
+
+ return ..()
+
/obj/machinery/atm/process()
if(stat & NOPOWER)
@@ -66,7 +73,7 @@ log transactions
//short out the machine, shoot sparks, spew money!
emagged = 1
- spark_system.queue()
+ spark(src, 5, alldirs)
spawn_money(rand(100,500),src.loc)
//we don't want to grief people by locking their id in an emagged ATM
release_held_id(user)
diff --git a/code/modules/mining/drilling/drill.dm b/code/modules/mining/drilling/drill.dm
index eead474c3c2..54b1879704e 100644
--- a/code/modules/mining/drilling/drill.dm
+++ b/code/modules/mining/drilling/drill.dm
@@ -55,6 +55,10 @@
RefreshParts()
+/obj/machinery/mining/drill/Destroy()
+ QDEL_NULL(spark_system)
+ return ..()
+
/obj/machinery/mining/drill/process()
if(need_player_check)
diff --git a/code/modules/mob/dead/observer/observer.dm b/code/modules/mob/dead/observer/observer.dm
index 15765004498..b90e90b0538 100644
--- a/code/modules/mob/dead/observer/observer.dm
+++ b/code/modules/mob/dead/observer/observer.dm
@@ -13,6 +13,7 @@ var/global/list/image/ghost_sightless_images = list() //this is a list of images
blinded = 0
anchored = 1 // don't get pushed around
invisibility = INVISIBILITY_OBSERVER
+ simulated = FALSE
var/can_reenter_corpse
var/datum/hud/living/carbon/hud = null // hud
var/bootime = 0
diff --git a/code/modules/mob/living/bot/cleanbot.dm b/code/modules/mob/living/bot/cleanbot.dm
index 23ee3510c46..1508c3056e5 100644
--- a/code/modules/mob/living/bot/cleanbot.dm
+++ b/code/modules/mob/living/bot/cleanbot.dm
@@ -52,6 +52,8 @@ var/list/cleanbot_types // Going to use this to generate a list of types once th
listener = new /obj/cleanbot_listener(src)
listener.cleanbot = src
+ janitorial_supplies |= src
+
if(radio_controller)
radio_controller.add_object(listener, beacon_freq, filter = RADIO_NAVBEACONS)
@@ -61,6 +63,7 @@ var/list/cleanbot_types // Going to use this to generate a list of types once th
patrol_path = null
target = null
ignorelist = null
+ janitorial_supplies -= src
/mob/living/bot/cleanbot/proc/handle_target()
if(target.clean_marked && target.clean_marked != src)
diff --git a/code/modules/mob/living/carbon/carbon.dm b/code/modules/mob/living/carbon/carbon.dm
index 29da49536fe..f7857ed2899 100644
--- a/code/modules/mob/living/carbon/carbon.dm
+++ b/code/modules/mob/living/carbon/carbon.dm
@@ -17,13 +17,10 @@
germ_level++
/mob/living/carbon/Destroy()
- qdel(ingested)
- qdel(touching)
+ QDEL_NULL(touching)
// We don't qdel(bloodstr) because it's the same as qdel(reagents)
for(var/guts in internal_organs)
qdel(guts)
- for(var/food in stomach_contents)
- qdel(food)
return ..()
/mob/living/carbon/rejuvenate()
diff --git a/code/modules/mob/living/carbon/human/death.dm b/code/modules/mob/living/carbon/human/death.dm
index 847715dd270..75731569f93 100644
--- a/code/modules/mob/living/carbon/human/death.dm
+++ b/code/modules/mob/living/carbon/human/death.dm
@@ -39,20 +39,21 @@
var/obj/item/organ/external/head = get_organ("head")
var/mob/living/simple_animal/borer/B
- for(var/I in head.implants)
- if(istype(I,/mob/living/simple_animal/borer))
- B = I
- if(B)
- if(!B.ckey && ckey && B.controlling)
- B.ckey = ckey
- B.controlling = 0
- if(B.host_brain.ckey)
- ckey = B.host_brain.ckey
- B.host_brain.ckey = null
- B.host_brain.name = "host brain"
- B.host_brain.real_name = "host brain"
+ if (head)
+ for(var/I in head.implants)
+ if(istype(I,/mob/living/simple_animal/borer))
+ B = I
+ if(B)
+ if(!B.ckey && ckey && B.controlling)
+ B.ckey = ckey
+ B.controlling = 0
+ if(B.host_brain.ckey)
+ ckey = B.host_brain.ckey
+ B.host_brain.ckey = null
+ B.host_brain.name = "host brain"
+ B.host_brain.real_name = "host brain"
- verbs -= /mob/living/carbon/proc/release_control
+ verbs -= /mob/living/carbon/proc/release_control
callHook("death", list(src, gibbed))
diff --git a/code/modules/mob/living/carbon/human/human.dm b/code/modules/mob/living/carbon/human/human.dm
index ebd8b3b2bc8..e9fa53899a0 100644
--- a/code/modules/mob/living/carbon/human/human.dm
+++ b/code/modules/mob/living/carbon/human/human.dm
@@ -81,8 +81,30 @@
human_mob_list -= src
for(var/organ in organs)
qdel(organ)
- if (DS)
- qdel(DS)//prevents the dionastats holding onto references and blocking GC
+ organs = null
+ internal_organs_by_name = null
+ internal_organs = null
+ organs_by_name = null
+ bad_internal_organs = null
+ bad_external_organs = null
+
+ QDEL_NULL(DS)
+ // qdel and null out our equipment.
+ QDEL_NULL(shoes)
+ QDEL_NULL(belt)
+ QDEL_NULL(gloves)
+ QDEL_NULL(glasses)
+ QDEL_NULL(head)
+ QDEL_NULL(l_ear)
+ QDEL_NULL(r_ear)
+ QDEL_NULL(wear_id)
+ QDEL_NULL(r_store)
+ QDEL_NULL(l_store)
+ QDEL_NULL(s_store)
+ QDEL_NULL(wear_suit)
+ // Do this last so the mob's stuff doesn't drop on del.
+ QDEL_NULL(w_uniform)
+
return ..()
/mob/living/carbon/human/Stat()
diff --git a/code/modules/mob/living/living.dm b/code/modules/mob/living/living.dm
index 408554a6ea9..923cc05d5bc 100644
--- a/code/modules/mob/living/living.dm
+++ b/code/modules/mob/living/living.dm
@@ -782,3 +782,11 @@ default behaviour is:
src << "You are now \the [src]!"
src << "Remember to stay in character for a mob of this type!"
return 1
+
+/mob/living/Destroy()
+ for (var/thing in stomach_contents)
+ qdel(thing)
+ stomach_contents = null
+ QDEL_NULL(ingested)
+
+ return ..()
diff --git a/code/modules/mob/living/silicon/robot/robot.dm b/code/modules/mob/living/silicon/robot/robot.dm
index b168c5561df..b48af64d22a 100644
--- a/code/modules/mob/living/silicon/robot/robot.dm
+++ b/code/modules/mob/living/silicon/robot/robot.dm
@@ -248,6 +248,7 @@
connected_ai.connected_robots -= src
qdel(wires)
wires = null
+ QDEL_NULL(spark_system)
return ..()
/mob/living/silicon/robot/proc/set_module_sprites(var/list/new_sprites)
diff --git a/code/modules/mob/living/simple_animal/friendly/farm_animals.dm b/code/modules/mob/living/simple_animal/friendly/farm_animals.dm
index d7ca060dbb4..ca7bed3bd9b 100644
--- a/code/modules/mob/living/simple_animal/friendly/farm_animals.dm
+++ b/code/modules/mob/living/simple_animal/friendly/farm_animals.dm
@@ -179,6 +179,7 @@
beg_for_food = 0
density = 0
mob_size = 0.75//just a rough estimate, the real value should be way lower
+ hunger_enabled = FALSE
/mob/living/simple_animal/chick/New()
..()
@@ -227,6 +228,7 @@ var/global/chicken_count = 0
holder_type = /obj/item/weapon/holder/chicken
density = 0
mob_size = 2
+ hunger_enabled = FALSE
/mob/living/simple_animal/chicken/New()
..()
@@ -256,14 +258,17 @@ var/global/chicken_count = 0
var/obj/item/weapon/reagent_containers/food/snacks/grown/G = O
if(G.seed && G.seed.kitchen_tag == "wheat")
if(!stat && eggsleft < 8)
- user.visible_message("\blue [user] feeds [O] to [name]! It clucks happily.","\blue You feed [O] to [name]! It clucks happily.")
+ user.visible_message(
+ span("notice", "\The [user] feeds \the [O] to \the [name]! It clucks happily."),
+ span("notice", "You feed \the [O] to \the [name]! It clucks happily."),
+ "You hear a cluck.")
user.drop_item()
qdel(O)
eggsleft += rand(1, 4)
else
- user << "\blue [name] doesn't seem hungry!"
+ user << "\The [name] doesn't seem hungry!"
else
- user << "[name] doesn't seem interested in that."
+ user << "\The [name] doesn't seem interested in that."
else
..()
diff --git a/code/modules/mob/living/simple_animal/hostile/bear.dm b/code/modules/mob/living/simple_animal/hostile/bear.dm
index 3d7bac69506..aac5e123f6b 100644
--- a/code/modules/mob/living/simple_animal/hostile/bear.dm
+++ b/code/modules/mob/living/simple_animal/hostile/bear.dm
@@ -439,9 +439,8 @@
spark_system = bind_spark(src, 5)
/mob/living/simple_animal/hostile/bear/spatial/Destroy()
- if (spark_system)
- qdel(spark_system)
- ..()
+ QDEL_NULL(spark_system)
+ return ..()
//Called when we want to bypass ticks and attack immediately. For example in response to being shot
//This calls several procs and some duplicated code from the parent class to immediately put us in an assault state and lash out
diff --git a/code/modules/organs/organ.dm b/code/modules/organs/organ.dm
index 750cd99080b..c0db16020eb 100644
--- a/code/modules/organs/organ.dm
+++ b/code/modules/organs/organ.dm
@@ -28,6 +28,7 @@ var/list/organ_cache = list()
var/emp_coeff = 1 //coefficient for damages taken by EMP, if the organ is robotic.
/obj/item/organ/Destroy()
+ processing_objects -= src
if(!owner)
return ..()
@@ -44,6 +45,9 @@ var/list/organ_cache = list()
if(src in owner.contents)
owner.contents -= src
+ owner = null
+ QDEL_NULL(dna)
+
return ..()
/obj/item/organ/proc/update_health()
diff --git a/code/modules/power/apc.dm b/code/modules/power/apc.dm
index 28e7398548c..fb81b76cbcb 100644
--- a/code/modules/power/apc.dm
+++ b/code/modules/power/apc.dm
@@ -195,6 +195,8 @@
cell.forceMove(loc)
cell = null
+ QDEL_NULL(spark_system)
+
// Malf AI, removes the APC from AI's hacked APCs list.
if((hacker) && (hacker.hacked_apcs) && (src in hacker.hacked_apcs))
hacker.hacked_apcs -= src
diff --git a/code/modules/power/singularity/emitter.dm b/code/modules/power/singularity/emitter.dm
index 9dfede5a99e..36bc0afd9ec 100644
--- a/code/modules/power/singularity/emitter.dm
+++ b/code/modules/power/singularity/emitter.dm
@@ -33,6 +33,10 @@
..()
spark_system = bind_spark(src, 5, alldirs)
+/obj/machinery/power/emitter/Destroy()
+ QDEL_NULL(spark_system)
+ return ..()
+
/obj/machinery/power/emitter/verb/rotate()
set name = "Rotate"
set category = "Object"
@@ -56,6 +60,7 @@
log_game("Emitter deleted at ([x],[y],[z])")
investigate_log("deleted at ([x],[y],[z])","singulo")
qdel(wifi_receiver)
+ qdel(spark_system)
wifi_receiver = null
return ..()
diff --git a/code/modules/reagents/dispenser/cartridge.dm b/code/modules/reagents/dispenser/cartridge.dm
index 2f7369cba0d..570fb0b0742 100644
--- a/code/modules/reagents/dispenser/cartridge.dm
+++ b/code/modules/reagents/dispenser/cartridge.dm
@@ -36,6 +36,13 @@
set category = "Object"
set src in view(usr, 1)
+ if (!ishuman(usr))
+ return
+
+ if (usr.stat)
+ usr << "You cannot do that in your current state."
+ return
+
setLabel(L, usr)
/obj/item/weapon/reagent_containers/chem_disp_cartridge/proc/setLabel(L, mob/user = null)
diff --git a/code/modules/supermatter/supermatter.dm b/code/modules/supermatter/supermatter.dm
index 131cca980ef..bf08fa1d8c3 100644
--- a/code/modules/supermatter/supermatter.dm
+++ b/code/modules/supermatter/supermatter.dm
@@ -98,7 +98,7 @@
/obj/machinery/power/supermatter/Destroy()
- qdel(radio)
+ QDEL_NULL(radio)
. = ..()
/obj/machinery/power/supermatter/proc/explode()
diff --git a/html/changelogs/lohikar-PR-1933.yml b/html/changelogs/lohikar-PR-1933.yml
new file mode 100644
index 00000000000..f73c5fcf840
--- /dev/null
+++ b/html/changelogs/lohikar-PR-1933.yml
@@ -0,0 +1,9 @@
+author: Lohikar
+delete-after: True
+changes:
+ - bugfix: "NanoTrasen has issued a software update to standard Janitor PDAs; changelogs note custodial supply locator now actually works."
+ - bugfix: "Standard-issue automatic flasher units have been exorcised and should no longer be triggered by the dead."
+ - bugfix: "After complaints about chickens showing cannibalistic tendencies, Centcomm has changed chicken suppliers."
+ - bugfix: "Station-issued chemical dispensers are no longer produced in a haunted factory and should not be affected by the dead."
+ - bugfix: "Vending machines have been given a talking to after several synthetics reported tools being forcibly removed for stocking."
+ - bugfix: "It is no longer possible to add more languages than your species is physically capable of learning."