diff --git a/code/controllers/subsystem/acid.dm b/code/controllers/subsystem/acid.dm
deleted file mode 100644
index 25d080a1b1..0000000000
--- a/code/controllers/subsystem/acid.dm
+++ /dev/null
@@ -1,37 +0,0 @@
-SUBSYSTEM_DEF(acid)
- name = "Acid"
- priority = FIRE_PRIORITY_ACID
- flags = SS_NO_INIT|SS_BACKGROUND
- runlevels = RUNLEVEL_GAME | RUNLEVEL_POSTGAME
-
- var/list/currentrun = list()
- var/list/processing = list()
-
-/datum/controller/subsystem/acid/stat_entry(msg)
- msg = "P:[length(processing)]"
- return ..()
-
-
-/datum/controller/subsystem/acid/fire(resumed = 0)
- if (!resumed)
- src.currentrun = processing.Copy()
-
- //cache for sanic speed (lists are references anyways)
- var/list/currentrun = src.currentrun
-
- while (currentrun.len)
- var/obj/O = currentrun[currentrun.len]
- currentrun.len--
- if (!O || QDELETED(O))
- processing -= O
- if (MC_TICK_CHECK)
- return
- continue
-
- if(O.acid_level && O.acid_processing())
- else
- O.update_icon()
- processing -= O
-
- if (MC_TICK_CHECK)
- return
diff --git a/code/datums/components/acid.dm b/code/datums/components/acid.dm
new file mode 100644
index 0000000000..2e3784dc97
--- /dev/null
+++ b/code/datums/components/acid.dm
@@ -0,0 +1,65 @@
+/datum/component/acid
+ dupe_mode = COMPONENT_DUPE_UNIQUE_PASSARGS
+ var/level = 0
+
+/datum/component/acid/Initialize(acidpwr, acid_volume)
+ if(!isobj(parent))
+ return COMPONENT_INCOMPATIBLE
+ var/obj/O = parent
+ var/acid_cap = acidpwr * 300
+ level = min(acidpwr * acid_volume, acid_cap)
+ START_PROCESSING(SSprocessing, src)
+ RegisterSignal(parent, COMSIG_ATOM_UPDATE_OVERLAYS, .proc/add_acid_overlay)
+ if(isitem(parent))
+ RegisterSignal(parent, COMSIG_ATOM_ATTACK_HAND, .proc/on_attack_hand)
+ O.update_icon()
+
+/datum/component/acid/proc/on_attack_hand(datum/source, mob/user)
+ var/obj/item/I = parent
+ if(istype(I) && level > 20 && !ismob(I.loc))// so we can still remove the clothes on us that have acid.
+ var/mob/living/carbon/C = user
+ if(istype(C))
+ if(!C.gloves || (!(C.gloves.resistance_flags & (UNACIDABLE|ACID_PROOF))))
+ to_chat(user, "The acid on [I] burns your hand!")
+ var/obj/item/bodypart/affecting = C.get_bodypart("[(user.active_hand_index % 2 == 0) ? "r" : "l" ]_arm")
+ if(affecting && affecting.receive_damage( 0, 5 )) // 5 burn damage
+ C.update_damage_overlays()
+
+/datum/component/acid/InheritComponent(datum/component/C, i_am_original, acidpwr, acid_volume)
+ if(!i_am_original)
+ return
+ var/acid_cap = acidpwr * 300
+ if(level < acid_cap)
+ if(C)
+ var/datum/component/acid/other = C
+ level = min(level + other.level, acid_cap)
+ else
+ level = min(level + acidpwr * acid_volume, acid_cap)
+
+/datum/component/acid/Destroy()
+ STOP_PROCESSING(SSprocessing, src)
+ var/obj/O = parent
+ level = 0
+ O.update_overlays()
+ return ..()
+
+/datum/component/acid/process()
+ var/obj/O = parent
+ if(!istype(O))
+ qdel(src)
+ return PROCESS_KILL
+ if(!(O.resistance_flags & ACID_PROOF))
+ if(prob(33))
+ playsound(O.loc, 'sound/items/welder.ogg', 150, 1)
+ O.take_damage(min(1 + round(sqrt(level)*0.3), 300), BURN, "acid", 0)
+
+ level = max(level - (5 + 3*round(sqrt(level))), 0)
+ if(level <= 0)
+ qdel(src)
+ return PROCESS_KILL
+ else
+ O.update_icon()
+ return TRUE
+
+/datum/component/acid/proc/add_acid_overlay(atom/source, list/overlay_list)
+ overlay_list += GLOB.acid_overlay
diff --git a/code/game/objects/effects/alien_acid.dm b/code/game/objects/effects/alien_acid.dm
index 6496b392c3..40d950332c 100644
--- a/code/game/objects/effects/alien_acid.dm
+++ b/code/game/objects/effects/alien_acid.dm
@@ -9,6 +9,7 @@
resistance_flags = FIRE_PROOF | UNACIDABLE | ACID_PROOF
layer = ABOVE_NORMAL_TURF_LAYER
var/turf/target
+ var/acid_level = 0 // Removed from obj, so it goes here now
/obj/effect/acid/Initialize(mapload, acid_pwr, acid_amt)
@@ -42,7 +43,7 @@
for(var/obj/O in target)
if(prob(20) && !(resistance_flags & UNACIDABLE))
- if(O.acid_level < acid_level*0.3)
+ if(O.acid_level() < acid_level*0.3)
var/acid_used = min(acid_level*0.05, 20)
O.acid_act(10, acid_used)
acid_level = max(0, acid_level - acid_used*10)
diff --git a/code/game/objects/items.dm b/code/game/objects/items.dm
index cbfd5ef5a0..cd486ccf6b 100644
--- a/code/game/objects/items.dm
+++ b/code/game/objects/items.dm
@@ -352,15 +352,6 @@ GLOBAL_VAR_INIT(embedpocalypse, FALSE) // if true, all items will be able to emb
C.update_damage_overlays()
return
- if(acid_level > 20 && ismob(loc))// so we can still remove the clothes on us that have acid.
- var/mob/living/carbon/C = user
- if(istype(C))
- if(!C.gloves || (!(C.gloves.resistance_flags & (UNACIDABLE|ACID_PROOF))))
- to_chat(user, "The acid on [src] burns your hand!")
- var/obj/item/bodypart/affecting = C.get_bodypart("[(user.active_hand_index % 2 == 0) ? "r" : "l" ]_arm")
- if(affecting && affecting.receive_damage( 0, 5 )) // 5 burn damage
- C.update_damage_overlays()
-
if(!(interaction_flags_item & INTERACT_ITEM_ATTACK_HAND_PICKUP)) //See if we're supposed to auto pickup.
return
diff --git a/code/game/objects/obj_defense.dm b/code/game/objects/obj_defense.dm
index 02f2009667..cc2e6412eb 100644
--- a/code/game/objects/obj_defense.dm
+++ b/code/game/objects/obj_defense.dm
@@ -204,32 +204,23 @@ GLOBAL_DATUM_INIT(acid_overlay, /mutable_appearance, mutable_appearance('icons/e
//the obj's reaction when touched by acid
/obj/acid_act(acidpwr, acid_volume)
if(!(resistance_flags & UNACIDABLE) && acid_volume)
-
- if(!acid_level)
- SSacid.processing[src] = src
- update_icon()
- var/acid_cap = acidpwr * 300 //so we cannot use huge amounts of weak acids to do as well as strong acids.
- if(acid_level < acid_cap)
- acid_level = min(acid_level + acidpwr * acid_volume, acid_cap)
+ AddComponent(/datum/component/acid, acidpwr, acid_volume)
return 1
-//the proc called by the acid subsystem to process the acid that's on the obj
-/obj/proc/acid_processing()
- . = 1
- if(!(resistance_flags & ACID_PROOF))
- if(prob(33))
- playsound(loc, 'sound/items/welder.ogg', 150, 1)
- take_damage(min(1 + round(sqrt(acid_level)*0.3), 300), BURN, "acid", 0)
-
- acid_level = max(acid_level - (5 + 3*round(sqrt(acid_level))), 0)
- if(!acid_level)
- return 0
-
//called when the obj is destroyed by acid.
/obj/proc/acid_melt()
- SSacid.processing -= src
+ var/datum/component/acid/acid = GetComponent(/datum/component/acid)
+ if(acid)
+ acid.RemoveComponent()
deconstruct(FALSE)
+/obj/proc/acid_level()
+ var/datum/component/acid/acid = GetComponent(/datum/component/acid)
+ if(acid)
+ return acid.level
+ else
+ return 0
+
//// FIRE
/obj/fire_act(exposed_temperature, exposed_volume)
diff --git a/code/game/objects/objs.dm b/code/game/objects/objs.dm
index a9a891464b..ca4428db57 100644
--- a/code/game/objects/objs.dm
+++ b/code/game/objects/objs.dm
@@ -22,8 +22,6 @@
var/resistance_flags = NONE // INDESTRUCTIBLE | LAVA_PROOF | FIRE_PROOF | ON_FIRE | UNACIDABLE | ACID_PROOF
- var/acid_level = 0 //how much acid is on that obj
-
var/persistence_replacement //have something WAY too amazing to live to the next round? Set a new path here. Overuse of this var will make me upset.
var/current_skin //the item reskin
var/list/unique_reskin //List of options to reskin.
@@ -369,8 +367,6 @@
/obj/update_overlays()
. = ..()
- if(acid_level)
- . += GLOB.acid_overlay
if(resistance_flags & ON_FIRE)
. += GLOB.fire_overlay
diff --git a/code/game/objects/structures/watercloset.dm b/code/game/objects/structures/watercloset.dm
index 01c62a7901..9a2b4aab1a 100644
--- a/code/game/objects/structures/watercloset.dm
+++ b/code/game/objects/structures/watercloset.dm
@@ -354,10 +354,10 @@
. = SEND_SIGNAL(O, COMSIG_COMPONENT_CLEAN_ACT, CLEAN_WEAK)
. = O.clean_blood()
O.remove_atom_colour(WASHABLE_COLOUR_PRIORITY)
- if(isitem(O))
- var/obj/item/I = O
- I.acid_level = 0
- I.extinguish()
+ var/datum/component/acid/acid = O.GetComponent(/datum/component/acid)
+ if(acid)
+ acid.level = 0
+ O.extinguish()
/obj/machinery/shower/proc/wash_turf()
if(isturf(loc))
@@ -601,7 +601,9 @@
busy = FALSE
SEND_SIGNAL(O, COMSIG_COMPONENT_CLEAN_ACT, CLEAN_WEAK)
O.clean_blood()
- O.acid_level = 0
+ var/datum/component/acid/acid = O.GetComponent(/datum/component/acid)
+ if(acid)
+ acid.level = 0
create_reagents(5)
reagents.add_reagent(dispensedreagent, 5)
reagents.reaction(O, TOUCH)
diff --git a/code/modules/mob/living/carbon/carbon.dm b/code/modules/mob/living/carbon/carbon.dm
index e4d6f5253e..7aa6cbe736 100644
--- a/code/modules/mob/living/carbon/carbon.dm
+++ b/code/modules/mob/living/carbon/carbon.dm
@@ -961,7 +961,9 @@
/mob/living/carbon/ExtinguishMob()
for(var/X in get_equipped_items())
var/obj/item/I = X
- I.acid_level = 0 //washes off the acid on our clothes
+ var/datum/component/acid/acid = I.GetComponent(/datum/component/acid)
+ if(acid)
+ acid.level = 0
I.extinguish() //extinguishes our clothes
..()
diff --git a/code/modules/reagents/chemistry/reagents/other_reagents.dm b/code/modules/reagents/chemistry/reagents/other_reagents.dm
index 593d77f959..0c70f47c53 100644
--- a/code/modules/reagents/chemistry/reagents/other_reagents.dm
+++ b/code/modules/reagents/chemistry/reagents/other_reagents.dm
@@ -287,7 +287,9 @@
/datum/reagent/water/reaction_obj(obj/O, reac_volume)
O.extinguish()
- O.acid_level = 0
+ var/datum/component/acid/acid = O.GetComponent(/datum/component/acid)
+ if(acid)
+ acid.level = 0
// cubes
if(istype(O, /obj/item/reagent_containers/food/snacks/cube))
var/obj/item/reagent_containers/food/snacks/cube/cube = O
diff --git a/code/modules/research/xenobiology/crossbreeding/_status_effects.dm b/code/modules/research/xenobiology/crossbreeding/_status_effects.dm
index f3e14993ed..62e68e5b0e 100644
--- a/code/modules/research/xenobiology/crossbreeding/_status_effects.dm
+++ b/code/modules/research/xenobiology/crossbreeding/_status_effects.dm
@@ -622,7 +622,9 @@
var/obj/O = owner.get_active_held_item()
if(O)
O.extinguish() //All shamelessly copied from water's reaction_obj, since I didn't seem to be able to get it here for some reason.
- O.acid_level = 0
+ var/datum/component/acid/acid = O.GetComponent(/datum/component/acid)
+ if(acid)
+ acid.level = 0
// Monkey cube
if(istype(O, /obj/item/reagent_containers/food/snacks/cube))
to_chat(owner, "[linked_extract] kept your hands wet! It makes [O] expand!")
diff --git a/tgstation.dme b/tgstation.dme
index ed85c32cc4..a581e97a59 100644
--- a/tgstation.dme
+++ b/tgstation.dme
@@ -306,7 +306,6 @@
#include "code\controllers\configuration\entries\respawns.dm"
#include "code\controllers\configuration\entries\stamina_combat.dm"
#include "code\controllers\subsystem\achievements.dm"
-#include "code\controllers\subsystem\acid.dm"
#include "code\controllers\subsystem\activity.dm"
#include "code\controllers\subsystem\adjacent_air.dm"
#include "code\controllers\subsystem\air.dm"
@@ -459,6 +458,7 @@
#include "code\datums\brain_damage\special.dm"
#include "code\datums\brain_damage\split_personality.dm"
#include "code\datums\components\_component.dm"
+#include "code\datums\components\acid.dm"
#include "code\datums\components\activity.dm"
#include "code\datums\components\anti_magic.dm"
#include "code\datums\components\armor_plate.dm"