diff --git a/Daedalic Entertainment GmbH/Barotrauma/WorkshopMods/Installed/2795927223/filelist.xml b/Daedalic Entertainment GmbH/Barotrauma/WorkshopMods/Installed/2795927223/filelist.xml
new file mode 100644
index 00000000..1d230f59
--- /dev/null
+++ b/Daedalic Entertainment GmbH/Barotrauma/WorkshopMods/Installed/2795927223/filelist.xml
@@ -0,0 +1,2 @@
+
+
\ No newline at end of file
diff --git a/Daedalic Entertainment GmbH/Barotrauma/WorkshopMods/Installed/2913302583/TalentTrees.xml b/Daedalic Entertainment GmbH/Barotrauma/WorkshopMods/Installed/2913302583/TalentTrees.xml
new file mode 100644
index 00000000..78be8fbd
--- /dev/null
+++ b/Daedalic Entertainment GmbH/Barotrauma/WorkshopMods/Installed/2913302583/TalentTrees.xml
@@ -0,0 +1,8640 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Daedalic Entertainment GmbH/Barotrauma/WorkshopMods/Installed/2913302583/endocrinebooster.xml b/Daedalic Entertainment GmbH/Barotrauma/WorkshopMods/Installed/2913302583/endocrinebooster.xml
new file mode 100644
index 00000000..d2545ee6
--- /dev/null
+++ b/Daedalic Entertainment GmbH/Barotrauma/WorkshopMods/Installed/2913302583/endocrinebooster.xml
@@ -0,0 +1,51 @@
+
+
+
+ -
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Daedalic Entertainment GmbH/Barotrauma/WorkshopMods/Installed/2913302583/filelist.xml b/Daedalic Entertainment GmbH/Barotrauma/WorkshopMods/Installed/2913302583/filelist.xml
new file mode 100644
index 00000000..e526a206
--- /dev/null
+++ b/Daedalic Entertainment GmbH/Barotrauma/WorkshopMods/Installed/2913302583/filelist.xml
@@ -0,0 +1,4 @@
+
+
+
+
\ No newline at end of file
diff --git a/Daedalic Entertainment GmbH/Barotrauma/WorkshopMods/Installed/2950383008/CSharp/Client/ItemBox.cs b/Daedalic Entertainment GmbH/Barotrauma/WorkshopMods/Installed/2950383008/CSharp/Client/ItemBox.cs
new file mode 100644
index 00000000..c07762f7
--- /dev/null
+++ b/Daedalic Entertainment GmbH/Barotrauma/WorkshopMods/Installed/2950383008/CSharp/Client/ItemBox.cs
@@ -0,0 +1,323 @@
+using Barotrauma.Items.Components;
+using Barotrauma;
+using HarmonyLib;
+using Microsoft.Xna.Framework;
+using Microsoft.Xna.Framework.Graphics;
+using System.Collections.Generic;
+using System;
+using System.ComponentModel;
+using Barotrauma.Networking;
+using System.Linq;
+
+namespace BaroMod_sjx
+{
+ partial class ItemBoxImpl
+ {
+
+ [HarmonyPatch(typeof(Inventory), nameof(Inventory.DrawSlot))]
+ class Patch_DrawSlot
+ {
+ public class context
+ {
+ public SpriteBatch spriteBatch;
+
+ public Inventory inventory;
+ public Sprite? indicatorSprite;
+ public Sprite? emptyIndicatorSprite;
+ public Sprite? itemSprite;
+ public Rectangle conditionIndicatorArea;
+
+ public int max_value;
+ public int cur_value;
+ public Vector2 sprite_pos;
+ public float sprite_scale;
+ public float rotation;
+ public Color spriteColor;
+ public context(SpriteBatch sb, Inventory inv, Sprite? full, Sprite? empty, Sprite? item, Rectangle area, int max, int cur, Vector2 sp, float ss, float rot, Color sc)
+ {
+ spriteBatch = sb;
+ inventory = inv;
+ indicatorSprite = full;
+ emptyIndicatorSprite = empty;
+ itemSprite = item;
+ conditionIndicatorArea = area;
+ max_value = max;
+ cur_value = cur;
+ sprite_pos = sp;
+ sprite_scale = ss;
+ rotation = rot;
+ spriteColor = sc;
+ }
+ }
+
+ static private void Invoke_DrawItemStateIndicator(
+ SpriteBatch spriteBatch, Inventory inventory,
+ Sprite indicatorSprite, Sprite emptyIndicatorSprite, Rectangle containedIndicatorArea, float containedState,
+ bool pulsate = false)
+ {
+ AccessTools.Method(typeof(Inventory), "DrawItemStateIndicator")!
+ .Invoke(null, new object[] { spriteBatch, inventory, indicatorSprite, emptyIndicatorSprite, containedIndicatorArea, containedState, pulsate });
+ }
+
+ private static Sprite? GetTargetSprite(ConditionStorage conditionStorage, Inventory iv)
+ {
+ Inventory.ItemSlot target_slot;
+ {
+ Inventory.ItemSlot[] slots = (AccessTools.Field(typeof(Inventory), "slots").GetValue(iv)! as Inventory.ItemSlot[])!;
+ if (conditionStorage.slotIndex >= slots.Length)
+ {
+ DebugConsole.LogError($"ConditionStorage of {(iv.Owner as Item)!.Prefab.Identifier} specified index {conditionStorage.slotIndex} out of {slots.Length}!");
+ return null;
+ }
+ target_slot = slots[conditionStorage.slotIndex];
+ }
+ if (target_slot.Any())
+ {
+ Item i = target_slot.First();
+ return i.Prefab.InventoryIcon ?? i.Sprite;
+ }
+ else
+ {
+ return null;
+ }
+ }
+
+ public static bool Prefix(out context? __state,
+ SpriteBatch spriteBatch, Inventory inventory, VisualSlot slot, Item item, int slotIndex)
+ {
+ if (inventory != null && item != null && get_componentsByType(item).TryGetValue(typeof(ConditionStorage), out List? comps))
+ {
+ ConditionStorage conditionStorage = (comps.First() as ConditionStorage)!;
+ if (!conditionStorage.showIcon && !conditionStorage.showCount)
+ {
+ __state = null;
+ return true;
+ }
+
+
+ Rectangle rect = slot.Rect;
+ rect.Location += slot.DrawOffset.ToPoint();
+
+ if (slot.HighlightColor.A > 0)
+ {
+ float inflateAmount = (slot.HighlightColor.A / 255.0f) * slot.HighlightScaleUpAmount * 0.5f;
+ rect.Inflate(rect.Width * inflateAmount, rect.Height * inflateAmount);
+ }
+
+ var itemContainer = item.GetComponent();
+
+ Sprite? indicatorSprite;
+ Sprite? emptyIndicatorSprite;
+ Rectangle conditionIndicatorArea;
+ if (conditionStorage.showCount)
+ {
+
+
+ if (itemContainer is null)
+ {
+ DebugConsole.LogError($"Item {item.Prefab.Identifier} has ConditionStorage but no ItemContainer!");
+ __state = null;
+ return true;
+ }
+ if (itemContainer.InventoryTopSprite != null || itemContainer.InventoryBottomSprite != null)
+ {
+ __state = null;
+ return true;
+ }
+ int dir = slot.SubInventoryDir;
+
+ if (itemContainer.ShowContainedStateIndicator)
+ {
+ conditionIndicatorArea = new Rectangle(rect.X, rect.Bottom - (int)(10 * GUI.Scale), rect.Width, (int)(10 * GUI.Scale));
+ }
+ else
+ {
+ conditionIndicatorArea = new Rectangle(
+ rect.X, dir < 0 ? rect.Bottom + HUDLayoutSettings.Padding / 2 : rect.Y - HUDLayoutSettings.Padding / 2 - Inventory.ContainedIndicatorHeight,
+ rect.Width, Inventory.ContainedIndicatorHeight);
+ conditionIndicatorArea.Inflate(-4, 0);
+ }
+
+
+ GUIComponentStyle indicatorStyle = GUIStyle.GetComponentStyle("ContainedStateIndicator.Default")!;
+ indicatorSprite = indicatorStyle.GetDefaultSprite();
+ emptyIndicatorSprite = indicatorStyle.GetSprite(GUIComponent.ComponentState.Hover);
+ }
+ else
+ {
+ indicatorSprite = null;
+ emptyIndicatorSprite = null;
+ conditionIndicatorArea = new Rectangle();
+ }
+
+ Vector2 itemPos;
+ float scale;
+ float rotation;
+ Sprite? item_sprite;
+ Color spriteColor;
+
+ if (conditionStorage.showIcon)
+ {
+ item_sprite = GetTargetSprite(conditionStorage, itemContainer.Inventory!);
+ if (item_sprite != null)
+ {
+ scale = Math.Min(Math.Min((rect.Width - 10) / item_sprite.size.X, (rect.Height - 10) / item_sprite.size.Y), 2.0f);
+ itemPos = rect.Center.ToVector2();
+ if (itemPos.Y > GameMain.GraphicsHeight)
+ {
+ itemPos.Y -= Math.Min(
+ (itemPos.Y + item_sprite.size.Y / 2 * scale) - GameMain.GraphicsHeight,
+ (itemPos.Y - item_sprite.size.Y / 2 * scale) - rect.Y);
+ }
+
+ rotation = 0.0f;
+ if (slot.HighlightColor.A > 0)
+ {
+ rotation = (float)Math.Sin(slot.HighlightTimer * MathHelper.TwoPi) * slot.HighlightTimer * 0.3f;
+ }
+
+ spriteColor = item_sprite == item.Sprite ? item.GetSpriteColor() : item.GetInventoryIconColor();
+ }
+ else
+ {
+ scale = 1.0f;
+ rotation = 0.0f;
+ spriteColor = Color.White;
+ }
+ }
+ else
+ {
+ item_sprite = null;
+ scale = 1.0f;
+ rotation = 0.0f;
+ spriteColor = Color.White;
+ }
+ Vector2 center = rect.Center.ToVector2() + (new Vector2(conditionStorage.iconShiftX, conditionStorage.iconShiftY)) * slot.Rect.Size.ToVector2() * 0.5f;
+ __state = new context(spriteBatch, inventory, indicatorSprite, emptyIndicatorSprite, item_sprite,
+ conditionIndicatorArea, conditionStorage.maxItemCount, conditionStorage.currentItemCount, center,
+ scale * conditionStorage.iconScale, rotation, spriteColor);
+ }
+ else
+ {
+ __state = null;
+ }
+ return true;
+ }
+ public static void Postfix(context? __state)
+ {
+ if (__state != null)
+ {
+ __state.itemSprite?.Draw(__state.spriteBatch, __state.sprite_pos, __state.spriteColor, __state.rotation, __state.sprite_scale);
+ if (__state.indicatorSprite != null && __state.emptyIndicatorSprite != null)
+ {
+ Invoke_DrawItemStateIndicator(__state.spriteBatch, __state.inventory, __state.indicatorSprite, __state.emptyIndicatorSprite, __state.conditionIndicatorArea,
+ __state.cur_value / (float)__state.max_value);
+ string info_text = $"{__state.cur_value}/{__state.max_value}";
+ float text_scale = 0.75f;
+ Vector2 info_size = GUIStyle.SmallFont.MeasureString(info_text) * text_scale;
+ GUIStyle.SmallFont.DrawString(__state.spriteBatch, info_text, __state.conditionIndicatorArea.Center.ToVector2() - (info_size * 0.5f), Color.White, 0.0f, Vector2.Zero, text_scale, SpriteEffects.None, 0.0f);
+ }
+ }
+ }
+ }
+ }
+
+ partial class ConditionStorage : ItemComponent, IServerSerializable
+ {
+ private CoroutineHandle? resetPredictionCoroutine = null;
+ private int? last_server_update_count = null;
+ private float resetPredictionTimer = 1.0f;
+
+ float last_update_time = 0;
+
+ const double remove_time = 1.0;
+
+ class ItemStackedInfo
+ {
+ public Item target;
+ public Inventory removed_from;
+ public Character user;
+ public double timestamp;
+ public int slot;
+ public ItemStackedInfo(Item item, Character character, Inventory removedFrom, int from_slot)
+ {
+ target = item;
+ removed_from = removedFrom;
+ user = character;
+ slot = from_slot;
+ timestamp = Timing.TotalTime;
+ }
+ }
+
+ // keep a list of items removed on client side so that they can be put back into container after timeour
+ private List removed = new List();
+
+
+ void RemoveItem_track(Item item, Character user, Inventory removedFrom, int slot)
+ {
+ removed.Add(new ItemStackedInfo(item, user, removedFrom, slot));
+ }
+
+ void UpdateRemovedItems()
+ {
+ var copy = removed.CreateCopy();
+ foreach (var item in copy)
+ {
+ // updated from server to be removed
+ if (item.target.Removed)
+ {
+ removed.Remove(item);
+ }
+ // timeout for removed item. put it back.
+ else if (Timing.TotalTime - item.timestamp > remove_time)
+ {
+ if (!item.removed_from.TryPutItem(item.target, item.slot, false, false, item.user, false, false))
+ {
+ item.target.Drop(item.user, true, true);
+ }
+ removed.Remove(item);
+ }
+ }
+ if (removed.Any())
+ {
+ IsActive = true;
+ }
+ }
+
+ partial void OnCountPredictionChanged()
+ {
+ if (GameMain.Client == null || !last_server_update_count.HasValue) { return; }
+ if (resetPredictionCoroutine == null || !CoroutineManager.IsCoroutineRunning(resetPredictionCoroutine))
+ {
+ resetPredictionCoroutine = CoroutineManager.StartCoroutine(ResetPredictionAfterDelay());
+ }
+ }
+
+ private IEnumerable ResetPredictionAfterDelay()
+ {
+ while (resetPredictionTimer > 0.0f)
+ {
+ resetPredictionTimer -= CoroutineManager.DeltaTime;
+ yield return CoroutineStatus.Running;
+ }
+ if (last_server_update_count.HasValue) { SetItemCount(last_server_update_count.Value, false); }
+ resetPredictionCoroutine = null;
+ yield return CoroutineStatus.Success;
+ }
+
+ public void ClientEventRead(IReadMessage msg, float sendingTime)
+ {
+ if (last_update_time <= sendingTime)
+ {
+ last_update_time = sendingTime;
+ last_server_update_count = msg.ReadRangedInteger(0, maxItemCount);
+ SetItemCount(last_server_update_count.Value, true);
+ }
+ else
+ {
+ // discard the number, but still extract it from stream.
+ msg.ReadRangedInteger(0, maxItemCount);
+ }
+ }
+ }
+}
diff --git a/Daedalic Entertainment GmbH/Barotrauma/WorkshopMods/Installed/2950383008/CSharp/ItemBox.sln b/Daedalic Entertainment GmbH/Barotrauma/WorkshopMods/Installed/2950383008/CSharp/ItemBox.sln
new file mode 100644
index 00000000..7dc8d315
--- /dev/null
+++ b/Daedalic Entertainment GmbH/Barotrauma/WorkshopMods/Installed/2950383008/CSharp/ItemBox.sln
@@ -0,0 +1,41 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio Version 17
+VisualStudioVersion = 17.3.32825.248
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ItemBoxClient", "ItemBoxClient.csproj", "{D6EE7363-56EC-442E-8A50-C12111C41B59}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ItemBoxServer", "ItemBoxServer.csproj", "{35F1A00E-3387-47F2-BC89-6DB51BF829F4}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Any CPU = Debug|Any CPU
+ Debug|x64 = Debug|x64
+ Release|Any CPU = Release|Any CPU
+ Release|x64 = Release|x64
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {D6EE7363-56EC-442E-8A50-C12111C41B59}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {D6EE7363-56EC-442E-8A50-C12111C41B59}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {D6EE7363-56EC-442E-8A50-C12111C41B59}.Debug|x64.ActiveCfg = Debug|x64
+ {D6EE7363-56EC-442E-8A50-C12111C41B59}.Debug|x64.Build.0 = Debug|x64
+ {D6EE7363-56EC-442E-8A50-C12111C41B59}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {D6EE7363-56EC-442E-8A50-C12111C41B59}.Release|Any CPU.Build.0 = Release|Any CPU
+ {D6EE7363-56EC-442E-8A50-C12111C41B59}.Release|x64.ActiveCfg = Release|x64
+ {D6EE7363-56EC-442E-8A50-C12111C41B59}.Release|x64.Build.0 = Release|x64
+ {35F1A00E-3387-47F2-BC89-6DB51BF829F4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {35F1A00E-3387-47F2-BC89-6DB51BF829F4}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {35F1A00E-3387-47F2-BC89-6DB51BF829F4}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {35F1A00E-3387-47F2-BC89-6DB51BF829F4}.Debug|x64.Build.0 = Debug|Any CPU
+ {35F1A00E-3387-47F2-BC89-6DB51BF829F4}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {35F1A00E-3387-47F2-BC89-6DB51BF829F4}.Release|Any CPU.Build.0 = Release|Any CPU
+ {35F1A00E-3387-47F2-BC89-6DB51BF829F4}.Release|x64.ActiveCfg = Release|Any CPU
+ {35F1A00E-3387-47F2-BC89-6DB51BF829F4}.Release|x64.Build.0 = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+ GlobalSection(ExtensibilityGlobals) = postSolution
+ SolutionGuid = {BE43C433-493F-4E78-9590-A780226B0FB3}
+ EndGlobalSection
+EndGlobal
diff --git a/Daedalic Entertainment GmbH/Barotrauma/WorkshopMods/Installed/2950383008/CSharp/ItemBoxClient.csproj b/Daedalic Entertainment GmbH/Barotrauma/WorkshopMods/Installed/2950383008/CSharp/ItemBoxClient.csproj
new file mode 100644
index 00000000..993d29d4
--- /dev/null
+++ b/Daedalic Entertainment GmbH/Barotrauma/WorkshopMods/Installed/2950383008/CSharp/ItemBoxClient.csproj
@@ -0,0 +1,46 @@
+
+
+
+ net6.0
+ enable
+ enable
+ AnyCPU;x64
+
+
+
+ 1701;1702;CS0122
+ $(DefineConstants)TRACE;CLIENT
+
+
+
+ 1701;1702;CS0122
+ $(DefineConstants)TRACE;CLIENT
+
+
+
+ 1701;1702;CS0122
+ $(DefineConstants)TRACE;CLIENT
+
+
+
+ 1701;1702;CS0122
+ $(DefineConstants)TRACE;CLIENT
+
+
+
+
+ ..\Refs\0Harmony.dll
+
+
+ ..\Refs\Client\Barotrauma.dll
+
+
+ ..\Refs\MonoGame.Framework.Windows.NetStandard.dll
+
+
+ ..\Refs\XNATypes.dll
+
+
+
+
+
diff --git a/Daedalic Entertainment GmbH/Barotrauma/WorkshopMods/Installed/2950383008/CSharp/ItemBoxServer.csproj b/Daedalic Entertainment GmbH/Barotrauma/WorkshopMods/Installed/2950383008/CSharp/ItemBoxServer.csproj
new file mode 100644
index 00000000..f9a9b8e3
--- /dev/null
+++ b/Daedalic Entertainment GmbH/Barotrauma/WorkshopMods/Installed/2950383008/CSharp/ItemBoxServer.csproj
@@ -0,0 +1,34 @@
+
+
+
+ net6.0
+ enable
+ enable
+
+
+
+ $(DefineConstants)TRACE;SERVER
+
+
+
+ $(DefineConstants)TRACE;SERVER
+
+
+
+ ..\Refs\0Harmony.dll
+
+
+ ..\Refs\Server\DedicatedServer.dll
+
+
+ ..\Refs\MonoGame.Framework.Windows.NetStandard.dll
+
+
+ ..\Refs\Server\NetScriptAssembly.dll
+
+
+ ..\Refs\XNATypes.dll
+
+
+
+
diff --git a/Daedalic Entertainment GmbH/Barotrauma/WorkshopMods/Installed/2950383008/CSharp/RunConfig.xml b/Daedalic Entertainment GmbH/Barotrauma/WorkshopMods/Installed/2950383008/CSharp/RunConfig.xml
new file mode 100644
index 00000000..5796b9a9
--- /dev/null
+++ b/Daedalic Entertainment GmbH/Barotrauma/WorkshopMods/Installed/2950383008/CSharp/RunConfig.xml
@@ -0,0 +1,5 @@
+
+
+ Standard
+ Standard
+
\ No newline at end of file
diff --git a/Daedalic Entertainment GmbH/Barotrauma/WorkshopMods/Installed/2950383008/CSharp/Server/ItemBox.cs b/Daedalic Entertainment GmbH/Barotrauma/WorkshopMods/Installed/2950383008/CSharp/Server/ItemBox.cs
new file mode 100644
index 00000000..4a59392a
--- /dev/null
+++ b/Daedalic Entertainment GmbH/Barotrauma/WorkshopMods/Installed/2950383008/CSharp/Server/ItemBox.cs
@@ -0,0 +1,57 @@
+using Barotrauma;
+using HarmonyLib;
+using System.Reflection;
+using System.Linq;
+using Barotrauma.Items.Components;
+using System.Collections.Generic;
+using System;
+using Microsoft.Xna.Framework;
+using System.ComponentModel;
+using Barotrauma.Networking;
+
+namespace BaroMod_sjx
+{
+
+ partial class ConditionStorage : ItemComponent, IServerSerializable
+ {
+ /*
+ private CoroutineHandle? sendStateCoroutine;
+ private int lastSentState;
+ private float sendStateTimer;
+ */
+ partial void OnCountPredictionChanged()
+ {
+ /*
+ sendStateTimer = 0.5f;
+ if (sendStateCoroutine == null)
+ {
+ sendStateCoroutine = CoroutineManager.StartCoroutine(SendStateAfterDelay());
+ }*/
+ }
+
+ /*
+ private IEnumerable SendStateAfterDelay()
+ {
+ while (sendStateTimer > 0.0f)
+ {
+ sendStateTimer -= CoroutineManager.DeltaTime;
+ yield return CoroutineStatus.Running;
+ }
+
+ if (Item.Removed || GameMain.NetworkMember == null)
+ {
+ yield return CoroutineStatus.Success;
+ }
+
+ sendStateCoroutine = null;
+ if (lastSentState != currentItemCount) { Item.CreateServerEvent(this); }
+ yield return CoroutineStatus.Success;
+ }*/
+
+ public void ServerEventWrite(IWriteMessage msg, Client c, NetEntityEvent.IData? extraData = null)
+ {
+ EventData eventData = ExtractEventData(extraData);
+ msg.WriteRangedInteger(eventData.ItemCount, 0, maxItemCount);
+ }
+ }
+}
\ No newline at end of file
diff --git a/Daedalic Entertainment GmbH/Barotrauma/WorkshopMods/Installed/2950383008/CSharp/Shared/ItemBox.cs b/Daedalic Entertainment GmbH/Barotrauma/WorkshopMods/Installed/2950383008/CSharp/Shared/ItemBox.cs
new file mode 100644
index 00000000..ec300418
--- /dev/null
+++ b/Daedalic Entertainment GmbH/Barotrauma/WorkshopMods/Installed/2950383008/CSharp/Shared/ItemBox.cs
@@ -0,0 +1,408 @@
+using Barotrauma;
+using HarmonyLib;
+using System.Reflection;
+using System.Linq;
+using Barotrauma.Items.Components;
+using System.Collections.Generic;
+using System;
+using Microsoft.Xna.Framework;
+using System.ComponentModel;
+using Barotrauma.Networking;
+
+namespace BaroMod_sjx
+{
+ partial class ItemBoxImpl : ACsMod
+ {
+ const string harmony_id = "com.sjx.ItemIOFramework";
+ /*
+ const string box_identifier = "ItemBox";
+ const float max_condition = 1.0f;
+ const int item_count = 1024;
+ const float increment = max_condition / item_count;
+ */
+ private readonly Harmony harmony;
+
+ public ItemBoxImpl()
+ {
+ harmony = new Harmony(harmony_id);
+ harmony.PatchAll(Assembly.GetExecutingAssembly());
+ Barotrauma.DebugConsole.AddWarning("Loaded ItemBox Impl");
+ }
+
+ public override void Stop()
+ {
+ harmony.UnpatchAll(harmony_id);
+ }
+
+
+
+ static Dictionary> get_componentsByType(Item item)
+ {
+ return (AccessTools.Field(typeof(Item), "componentsByType").GetValue(item)! as Dictionary>)!;
+ }
+
+ [HarmonyPatch(typeof(Inventory))]
+ class Patch_PutItem
+ {
+ static MethodBase TargetMethod()
+ {
+ Barotrauma.DebugConsole.AddWarning("Patch_PutItem TargetMethod");
+ return AccessTools.Method(typeof(Inventory), "PutItem");
+ }
+
+ public class context
+ {
+ public Character user;
+ public ConditionStorage target;
+ public context(Character user, ConditionStorage target)
+ {
+ this.user = user;
+ this.target = target;
+ }
+ }
+
+ public static bool Prefix(Inventory __instance, Character user, int i, out context? __state)
+ {
+ __state = null;
+ ConditionStorage? target = ConditionStorage.GetFromInventory(__instance);
+ if (target != null && i == target.slotIndex)
+ {
+ __state = new context(user, target);
+ }
+ return true;
+ }
+ public static void Postfix(context? __state)
+ {
+ if (__state != null)
+ {
+ __state.target.OnPutItemDone(__state.user);
+ }
+ }
+ }
+
+ [HarmonyPatch(typeof(Inventory), nameof(Inventory.RemoveItem))]
+ class Patch_RemoveItem
+ {
+ public static bool Prefix(Inventory __instance, out ConditionStorage? __state, Item item)
+ {
+ __state = null;
+ // do not add items if sub is unloading or if removed for overflow.
+ if (!Submarine.Unloading)
+ {
+ ConditionStorage? target = ConditionStorage.GetFromInventory(__instance);
+ if (target != null)
+ {
+ if (target.GetSlot()?.Contains(item) ?? false)
+ {
+ if (target.flag_remove_no_spawn)
+ {
+ target.flag_remove_no_spawn = false;
+ }
+ else
+ {
+ target.QualityStacked = item.Quality;
+ target.ConditionStacked = item.Condition;
+ target.item_type = item.Prefab;
+ __state = target;
+ }
+ }
+ }
+ }
+ return true;
+ }
+ public static void Postfix(ConditionStorage? __state)
+ {
+ if (__state != null)
+ {
+ __state.OnRemoveItemDone();
+ }
+ }
+ }
+
+ [HarmonyPatch(typeof(Inventory))]
+ class Patch_TrySwapping
+ {
+ static MethodBase TargetMethod()
+ {
+ return AccessTools.Method(typeof(Inventory), "TrySwapping");
+ }
+
+ public static bool Prefix(Inventory __instance, Item item, ref bool __result)
+ {
+ if (ConditionStorage.GetFromInventory(__instance) != null ||
+ (item != null && item.ParentInventory != null && ConditionStorage.GetFromInventory(item.ParentInventory) != null))
+ {
+ __result = false;
+ return false;
+ }
+ return true;
+ }
+ }
+
+ [HarmonyPatch(typeof(Inventory))]
+ class Patch_CreateNetworkEvent
+ {
+ static MethodBase TargetMethod()
+ {
+ return AccessTools.Method(typeof(Inventory), "CreateNetworkEvent");
+ }
+
+ public static bool Prefix(Inventory __instance, out ConditionStorage? __state)
+ {
+ __state = null;
+ if (GameMain.NetworkMember != null)
+ {
+ __state = ConditionStorage.GetFromInventory(__instance);
+ }
+ return true;
+ }
+
+ public static void Postfix(ConditionStorage? __state)
+ {
+ if (__state != null)
+ {
+ __state.SyncItemCount();
+ }
+ }
+ }
+ }
+
+ partial class ConditionStorage : ItemComponent
+ {
+ private readonly struct EventData : IEventData
+ {
+ public readonly int ItemCount;
+
+ public EventData(int ItemCount)
+ {
+ this.ItemCount = ItemCount;
+ }
+ }
+
+ [Serialize(0, IsPropertySaveable.No, description: "Index of the stacking slot in same item's ItemContainer component")]
+ public int slotIndex { get; private set; }
+
+ [Serialize(true, IsPropertySaveable.No, description: "Shows count and percentage of stacking item")]
+ public bool showCount { get; private set; }
+
+ [Serialize(1024, IsPropertySaveable.No, description: "Maximum number of items stacked within")]
+ public int maxItemCount { get; private set; }
+
+ [Serialize(true, IsPropertySaveable.No, description: "Shows icon of stacking item")]
+ public bool showIcon { get; private set; }
+
+ [Serialize(0.6f, IsPropertySaveable.No, description: "icon scale compared to full")]
+ public float iconScale { get; private set; }
+
+ [Serialize(0.0f, IsPropertySaveable.No, description: "shift x of icon")]
+ public float iconShiftX { get; private set; }
+
+ [Serialize(0.1f, IsPropertySaveable.No, description: "shift y of icon, down is positive")]
+ public float iconShiftY { get; private set; }
+
+ [Editable(minValue: 0, maxValue: int.MaxValue), Serialize(0, IsPropertySaveable.Yes, description: "Current item count")]
+ // camel case needed for save compatibility
+ public int currentItemCount
+ {
+ get => _currentItemCount;
+ // assume set by
+ set
+ {
+ SetItemCount(value, false);
+ }
+ }
+
+ void SetItemCount(int value, bool is_network_event = false)
+ {
+ if (is_network_event || GameMain.NetworkMember == null || GameMain.NetworkMember.IsServer)
+ // authoritative number. will need to send to client later if server.
+ {
+ if (value != _currentItemCount)
+ {
+ OnCountActualChanged();
+ }
+ }
+ // predicted number. need to be reset later
+ else
+ {
+ if (value != _currentItemCount)
+ {
+ OnCountPredictionChanged();
+ }
+ }
+ IsActive = true;
+ _currentItemCount = value;
+ }
+
+ public ItemInventory itemInventory => Item.OwnInventory;
+ public ItemContainer itemContainer => Item.GetComponent();
+
+ public int _currentItemCount;
+
+ // replace setting parent container hack, so that harpoon guns work correctly
+ public bool flag_remove_no_spawn;
+
+ partial void OnCountActualChanged();
+ partial void OnCountPredictionChanged();
+
+
+ [Editable, Serialize("", IsPropertySaveable.Yes, description: "current stacked item")]
+ public Identifier ItemIdentifier
+ {
+ get
+ {
+ return item_type?.Identifier ?? "";
+ }
+ set
+ {
+ if (value.IsEmpty)
+ {
+ item_type = null;
+ }
+ else
+ {
+ item_type = ItemPrefab.Find("", value.ToIdentifier());
+ }
+ }
+ }
+
+ public ItemPrefab? item_type;
+
+ [Editable(MinValueInt = 0, MaxValueInt = Quality.MaxQuality), Serialize(0, IsPropertySaveable.Yes, description: "current stacked item quality")]
+ public int QualityStacked { get; set; }
+
+ [Editable, Serialize(float.NaN, IsPropertySaveable.Yes, description: "current stacked item condition")]
+ public float ConditionStacked { get; set; }
+
+
+
+ public ConditionStorage(Item item, ContentXElement element) : base(item, element) { }
+
+ public bool IsFull => currentItemCount >= maxItemCount;
+ public bool IsEmpty() => currentItemCount <= 0;
+
+ public void SyncItemCount()
+ {
+#if SERVER
+ Item.CreateServerEvent(this, new EventData(currentItemCount));
+#endif
+ }
+
+ public override void Update(float deltaTime, Camera cam)
+ {
+ base.Update(deltaTime, cam);
+ SyncItemCount();
+ IsActive = false;
+ }
+
+ public static int SlotPreserveCount(ItemPrefab prefab, Inventory inventory, ItemContainer container, int slot_index)
+ {
+ int resolved_stack_size = Math.Min(Math.Min(prefab.GetMaxStackSize(inventory), container.GetMaxStackSize(slot_index)), Inventory.MaxPossibleStackSize);
+ if (resolved_stack_size <= 1)
+ {
+ return 1;
+ }
+ else
+ {
+ return resolved_stack_size - 1;
+ }
+ }
+
+ public static ConditionStorage? GetFromInventory(Inventory inventory)
+ {
+ if (inventory.Owner is Item parentItem)
+ {
+ return parentItem.GetComponent();
+ }
+ else
+ {
+ return null;
+ }
+ }
+
+ public Inventory.ItemSlot? GetSlot()
+ {
+ Inventory.ItemSlot[] slots = (AccessTools.Field(typeof(Inventory), "slots").GetValue(itemInventory)! as Inventory.ItemSlot[])!;
+ if (slotIndex >= slots.Length)
+ {
+ DebugConsole.LogError($"ConditionStorage of {Item.Prefab.Identifier} specified index {slotIndex} out of {slots.Length}!");
+ return null;
+ }
+ return slots[slotIndex];
+ }
+
+ public void OnPutItemDone(Character user)
+ {
+ ItemContainer container = itemContainer;
+ Inventory.ItemSlot target_slot;
+ {
+ Inventory.ItemSlot[] slots = (AccessTools.Field(typeof(Inventory), "slots").GetValue(itemInventory)! as Inventory.ItemSlot[])!;
+ if (slotIndex >= slots.Length)
+ {
+ DebugConsole.LogError($"ConditionStorage of {Item.Prefab.Identifier} specified index {slotIndex} out of {slots.Length}!");
+ return;
+ }
+ target_slot = slots[slotIndex];
+ }
+
+ if (target_slot.Items.Any())
+ {
+ QualityStacked = target_slot.Items.First().Quality;
+ ConditionStacked = target_slot.Items.First().Condition;
+ item_type = target_slot.Items.First().Prefab;
+ if (!IsFull)
+ {
+ //bool edited = false;
+ int preserve = SlotPreserveCount(target_slot.Items.First().Prefab, itemInventory, container, slotIndex);
+ var it = target_slot.Items.ToArray().AsEnumerable().GetEnumerator();
+ while (it.MoveNext() && !IsFull)
+ {
+ if (preserve > 0)
+ {
+ preserve--;
+ }
+ else if (Entity.Spawner != null)
+ {
+ // client cannot despawn items, single player needs to despawn
+ Entity.Spawner.AddItemToRemoveQueue(it.Current);
+ SetItemCount(currentItemCount + 1);
+ flag_remove_no_spawn = true;
+ itemInventory.RemoveItem(it.Current);
+ break;
+ }
+ }
+ }
+ }
+ }
+
+ public void OnRemoveItemDone()
+ {
+ Inventory.ItemSlot target_slot;
+ {
+ Inventory.ItemSlot[] slots = (AccessTools.Field(typeof(Inventory), "slots").GetValue(itemInventory)! as Inventory.ItemSlot[])!;
+ if (slotIndex >= slots.Length)
+ {
+ DebugConsole.LogError($"ConditionStorage of {(itemInventory.Owner as Item)!.Prefab.Identifier} specified index {slotIndex} out of {slots.Length}!");
+ return;
+ }
+ target_slot = slots[slotIndex];
+ }
+
+ int preserve = SlotPreserveCount(item_type!, itemInventory, itemContainer, slotIndex);
+ int spawn_count = preserve - target_slot.Items.Count;
+ int can_spawn = Math.Min(spawn_count, currentItemCount);
+
+ // other may be queued, so spawn only one
+ if (can_spawn > 0)
+ {
+ if (Entity.Spawner != null)
+ {
+ SetItemCount(currentItemCount - 1);
+
+ Item.Spawner.AddItemToSpawnQueue(item_type, itemInventory,
+ ConditionStacked, QualityStacked, spawnIfInventoryFull: true);
+ }
+ }
+ }
+ }
+}
diff --git a/Daedalic Entertainment GmbH/Barotrauma/WorkshopMods/Installed/2950383008/XML/ItemBox.xml b/Daedalic Entertainment GmbH/Barotrauma/WorkshopMods/Installed/2950383008/XML/ItemBox.xml
new file mode 100644
index 00000000..9f4507b2
--- /dev/null
+++ b/Daedalic Entertainment GmbH/Barotrauma/WorkshopMods/Installed/2950383008/XML/ItemBox.xml
@@ -0,0 +1,14 @@
+
+-
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Daedalic Entertainment GmbH/Barotrauma/WorkshopMods/Installed/2950383008/XML/Text/English.xml b/Daedalic Entertainment GmbH/Barotrauma/WorkshopMods/Installed/2950383008/XML/Text/English.xml
new file mode 100644
index 00000000..df924a03
--- /dev/null
+++ b/Daedalic Entertainment GmbH/Barotrauma/WorkshopMods/Installed/2950383008/XML/Text/English.xml
@@ -0,0 +1,5 @@
+
+
+ Item Box
+ Stack your stackable items in one entity.
+
\ No newline at end of file
diff --git a/Daedalic Entertainment GmbH/Barotrauma/WorkshopMods/Installed/2950383008/XML/Text/SimplifiedChinese.xml b/Daedalic Entertainment GmbH/Barotrauma/WorkshopMods/Installed/2950383008/XML/Text/SimplifiedChinese.xml
new file mode 100644
index 00000000..63173b51
--- /dev/null
+++ b/Daedalic Entertainment GmbH/Barotrauma/WorkshopMods/Installed/2950383008/XML/Text/SimplifiedChinese.xml
@@ -0,0 +1,5 @@
+
+
+ 物品箱
+ 让你可叠加的物品叠加在一个实体上面
+
\ No newline at end of file
diff --git a/Daedalic Entertainment GmbH/Barotrauma/WorkshopMods/Installed/2950383008/filelist.xml b/Daedalic Entertainment GmbH/Barotrauma/WorkshopMods/Installed/2950383008/filelist.xml
new file mode 100644
index 00000000..b86aace9
--- /dev/null
+++ b/Daedalic Entertainment GmbH/Barotrauma/WorkshopMods/Installed/2950383008/filelist.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Daedalic Entertainment GmbH/Barotrauma/WorkshopMods/Installed/3389755246/ExtinguisherComponent.Png b/Daedalic Entertainment GmbH/Barotrauma/WorkshopMods/Installed/3389755246/ExtinguisherComponent.Png
new file mode 100644
index 00000000..3ead257f
--- /dev/null
+++ b/Daedalic Entertainment GmbH/Barotrauma/WorkshopMods/Installed/3389755246/ExtinguisherComponent.Png
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:cbc84d7b4edd2365079225de33a0dd963d9fd9f1569288599a8c4aab0b2c77dd
+size 6007
diff --git a/Daedalic Entertainment GmbH/Barotrauma/WorkshopMods/Installed/3389755246/ExtinguisherComponent.gif b/Daedalic Entertainment GmbH/Barotrauma/WorkshopMods/Installed/3389755246/ExtinguisherComponent.gif
new file mode 100644
index 00000000..097aa3ef
Binary files /dev/null and b/Daedalic Entertainment GmbH/Barotrauma/WorkshopMods/Installed/3389755246/ExtinguisherComponent.gif differ
diff --git a/Daedalic Entertainment GmbH/Barotrauma/WorkshopMods/Installed/3389755246/ExtinguisherComponent.pfi b/Daedalic Entertainment GmbH/Barotrauma/WorkshopMods/Installed/3389755246/ExtinguisherComponent.pfi
new file mode 100644
index 00000000..5c10c3e5
Binary files /dev/null and b/Daedalic Entertainment GmbH/Barotrauma/WorkshopMods/Installed/3389755246/ExtinguisherComponent.pfi differ
diff --git a/Daedalic Entertainment GmbH/Barotrauma/WorkshopMods/Installed/3389755246/ExtinguisherComponent.xml b/Daedalic Entertainment GmbH/Barotrauma/WorkshopMods/Installed/3389755246/ExtinguisherComponent.xml
new file mode 100644
index 00000000..3f952b44
--- /dev/null
+++ b/Daedalic Entertainment GmbH/Barotrauma/WorkshopMods/Installed/3389755246/ExtinguisherComponent.xml
@@ -0,0 +1,306 @@
+
+
+ -
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ -
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Daedalic Entertainment GmbH/Barotrauma/WorkshopMods/Installed/3389755246/FlamerComponent.Png b/Daedalic Entertainment GmbH/Barotrauma/WorkshopMods/Installed/3389755246/FlamerComponent.Png
new file mode 100644
index 00000000..01fa40cc
--- /dev/null
+++ b/Daedalic Entertainment GmbH/Barotrauma/WorkshopMods/Installed/3389755246/FlamerComponent.Png
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:10a130780cb051b867ed17a38eb201061fab2e84fd3bce9fb3cea46c0c12cde8
+size 6032
diff --git a/Daedalic Entertainment GmbH/Barotrauma/WorkshopMods/Installed/3389755246/filelist.xml b/Daedalic Entertainment GmbH/Barotrauma/WorkshopMods/Installed/3389755246/filelist.xml
new file mode 100644
index 00000000..4cc73b63
--- /dev/null
+++ b/Daedalic Entertainment GmbH/Barotrauma/WorkshopMods/Installed/3389755246/filelist.xml
@@ -0,0 +1,4 @@
+
+
+
+
\ No newline at end of file
diff --git a/Daedalic Entertainment GmbH/Barotrauma/WorkshopMods/Installed/3406279065/CSharp/Client/BmsUtil.cs b/Daedalic Entertainment GmbH/Barotrauma/WorkshopMods/Installed/3406279065/CSharp/Client/BmsUtil.cs
new file mode 100644
index 00000000..3991eb42
--- /dev/null
+++ b/Daedalic Entertainment GmbH/Barotrauma/WorkshopMods/Installed/3406279065/CSharp/Client/BmsUtil.cs
@@ -0,0 +1,78 @@
+using System.Linq;
+using Barotrauma;
+using Barotrauma.Items.Components;
+
+using Barotrauma.Extensions;
+using System.Collections.Generic;
+
+namespace BmsUtils
+{
+ public static class Util
+ {
+ private static List GetStackBoxIndex(ItemInventory inv)
+ {
+ var stackBoxsIndex = new List();
+ for (var i = 0; i < inv.Capacity; i++)
+ {
+ var items = inv.GetItemsAt(i).ToList();
+ if (items.None()) { continue; }
+ if (items.First().Prefab.Identifier.ToString() == "StackBox" && items.First().OwnInventories.First().AllItemsMod.Any())
+ {
+ stackBoxsIndex.Add(i);
+ }
+ }
+ return stackBoxsIndex;
+ }
+ public static void PushItems(bool toStackBox = false)
+ {
+
+ var controlCharacter = Character.Controlled;
+ var selectedContainer = controlCharacter.SelectedItem?.GetComponent();
+ var leftHandItems = controlCharacter.Inventory.GetItemsAt(5).FirstOrDefault()?.OwnInventory;
+ var rightHandItems = controlCharacter.Inventory.GetItemsAt(6).FirstOrDefault()?.OwnInventory;
+
+ if (leftHandItems != null)
+ {
+ for (var i = 0; i < leftHandItems.Capacity; i++)
+ {
+ foreach (var item in leftHandItems.GetItemsAt(i).ToList())
+ {
+ if (toStackBox)
+ {
+ foreach (var boxIndex in GetStackBoxIndex(selectedContainer.Inventory))
+ {
+ selectedContainer.Inventory.TryPutItem(item, boxIndex, allowSwapping: false, allowCombine: true, user: null, createNetworkEvent: true);
+ }
+
+ }
+ else
+ {
+ selectedContainer.Inventory.TryPutItem(item, controlCharacter, createNetworkEvent: true, ignoreCondition: true);
+ }
+ }
+ }
+ }
+ if (rightHandItems != null)
+ {
+ for (var i = 0; i < rightHandItems.Capacity; i++)
+ {
+ foreach (var item in rightHandItems.GetItemsAt(i).ToList())
+ {
+ if (toStackBox)
+ {
+ foreach (var boxIndex in GetStackBoxIndex(selectedContainer.Inventory))
+ {
+ selectedContainer.Inventory.TryPutItem(item, boxIndex, allowSwapping: false, allowCombine: true, user: null, createNetworkEvent: true);
+ }
+
+ }
+ else
+ {
+ selectedContainer.Inventory.TryPutItem(item, controlCharacter, createNetworkEvent: true, ignoreCondition: true);
+ }
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/Daedalic Entertainment GmbH/Barotrauma/WorkshopMods/Installed/3406279065/CSharp/Client/Bmsmod.cs b/Daedalic Entertainment GmbH/Barotrauma/WorkshopMods/Installed/3406279065/CSharp/Client/Bmsmod.cs
new file mode 100644
index 00000000..41005052
--- /dev/null
+++ b/Daedalic Entertainment GmbH/Barotrauma/WorkshopMods/Installed/3406279065/CSharp/Client/Bmsmod.cs
@@ -0,0 +1,92 @@
+using System.Reflection;
+using Barotrauma.Extensions;
+using Microsoft.Xna.Framework;
+using HarmonyLib;
+using System.Linq;
+using Barotrauma;
+using BmsUtils;
+
+// debug
+// using System.Diagnostics;
+
+namespace Bms_Harmony
+{
+ partial class BmsHarmony : ACsMod
+ {
+ const string harmony_id = "com.Bms.Harmony";
+ private readonly Harmony harmony;
+
+ public override void Stop()
+ {
+ harmony.UnpatchAll(harmony_id);
+ }
+
+ public BmsHarmony()
+ {
+ harmony = new Harmony(harmony_id);
+ harmony.PatchAll(Assembly.GetExecutingAssembly());
+ Barotrauma.DebugConsole.AddWarning("Loaded BmsHarmony");
+ }
+
+ [HarmonyPatch(typeof(Barotrauma.Items.Components.ItemContainer))]
+ class Patch_MergeStacks
+ {
+ static MethodBase TargetMethod()
+ {
+ Barotrauma.DebugConsole.AddWarning("Patch_MergeStacks TargetMethod");
+ return AccessTools.Method(typeof(Barotrauma.Items.Components.ItemContainer), "MergeStacks");
+ }
+ static bool Prefix(Barotrauma.Items.Components.ItemContainer __instance)
+ {
+ for (int i = 0; i < __instance.Inventory.Capacity - 1; i++)
+ {
+ var items = __instance.Inventory.GetItemsAt(i).ToList();
+ if (items.None()) { continue; }
+ if (items.First().Prefab.Identifier.ToString() == "StackBox" &&
+ items.First().OwnInventories.First().AllItemsMod.Any())
+ {
+ for (int j = 0; j < __instance.Inventory.Capacity - 1; j++)
+ {
+ var items2 = __instance.Inventory.GetItemsAt(j).ToList();
+ if (items2.None()) { continue; }
+ if (items2.First().Prefab.Identifier.ToString() != "StackBox")
+ {
+ items2.ForEach(it => __instance.Inventory.TryPutItem(it, i, allowSwapping: false, allowCombine: true, user: null, createNetworkEvent: false));
+ continue;
+ }
+
+ }
+ }
+ }
+ return true;
+ }
+ }
+
+ [HarmonyPatch(typeof(Barotrauma.Items.Components.ItemContainer))]
+ class Patch_CreateGUI
+ {
+ static MethodBase TargetMethod()
+ {
+ Barotrauma.DebugConsole.AddWarning("Patch_CreateGUI TargetMethod");
+ return AccessTools.Method(typeof(Barotrauma.Items.Components.ItemContainer), "CreateGUI");
+ }
+
+ static void Postfix(Barotrauma.Items.Components.ItemContainer __instance)
+ {
+ if (__instance.Inventory.Capacity > 1)
+ {
+ var layoutGroup = __instance.GuiFrame.FindChild(c => c is Barotrauma.GUILayoutGroup, recursive: true);
+ new GUIButton(new RectTransform(Vector2.One, layoutGroup.RectTransform, scaleBasis: ScaleBasis.Smallest), style: "PushButton")
+ {
+ ToolTip = TextManager.Get("bms.pushicon"),
+ OnClicked = (btn, userdata) =>
+ {
+ Util.PushItems(true);
+ return true;
+ }
+ };
+ }
+ }
+ }
+ }
+}
diff --git a/Daedalic Entertainment GmbH/Barotrauma/WorkshopMods/Installed/3406279065/CSharp/RunConfig.xml b/Daedalic Entertainment GmbH/Barotrauma/WorkshopMods/Installed/3406279065/CSharp/RunConfig.xml
new file mode 100644
index 00000000..5796b9a9
--- /dev/null
+++ b/Daedalic Entertainment GmbH/Barotrauma/WorkshopMods/Installed/3406279065/CSharp/RunConfig.xml
@@ -0,0 +1,5 @@
+
+
+ Standard
+ Standard
+
\ No newline at end of file
diff --git a/Daedalic Entertainment GmbH/Barotrauma/WorkshopMods/Installed/3406279065/LICENSE b/Daedalic Entertainment GmbH/Barotrauma/WorkshopMods/Installed/3406279065/LICENSE
new file mode 100644
index 00000000..50bc8779
--- /dev/null
+++ b/Daedalic Entertainment GmbH/Barotrauma/WorkshopMods/Installed/3406279065/LICENSE
@@ -0,0 +1,21 @@
+MIT License
+
+Copyright (c) 2025 Diemoe
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
diff --git a/Daedalic Entertainment GmbH/Barotrauma/WorkshopMods/Installed/3406279065/Text/English.xml b/Daedalic Entertainment GmbH/Barotrauma/WorkshopMods/Installed/3406279065/Text/English.xml
new file mode 100644
index 00000000..2770bfba
--- /dev/null
+++ b/Daedalic Entertainment GmbH/Barotrauma/WorkshopMods/Installed/3406279065/Text/English.xml
@@ -0,0 +1,6 @@
+
+
+
+ All transferred to item box
+
+
\ No newline at end of file
diff --git a/Daedalic Entertainment GmbH/Barotrauma/WorkshopMods/Installed/3406279065/Text/Push.png b/Daedalic Entertainment GmbH/Barotrauma/WorkshopMods/Installed/3406279065/Text/Push.png
new file mode 100644
index 00000000..5d074843
--- /dev/null
+++ b/Daedalic Entertainment GmbH/Barotrauma/WorkshopMods/Installed/3406279065/Text/Push.png
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:13e2b051bb4cca27befc98490a5a11745a83726c1a24686f2b842b5efd50427c
+size 653
diff --git a/Daedalic Entertainment GmbH/Barotrauma/WorkshopMods/Installed/3406279065/Text/SimplifiedChinese.xml b/Daedalic Entertainment GmbH/Barotrauma/WorkshopMods/Installed/3406279065/Text/SimplifiedChinese.xml
new file mode 100644
index 00000000..17be29c6
--- /dev/null
+++ b/Daedalic Entertainment GmbH/Barotrauma/WorkshopMods/Installed/3406279065/Text/SimplifiedChinese.xml
@@ -0,0 +1,6 @@
+
+
+
+ 全部转移至物品箱
+
+
\ No newline at end of file
diff --git a/Daedalic Entertainment GmbH/Barotrauma/WorkshopMods/Installed/3406279065/Text/style.xml b/Daedalic Entertainment GmbH/Barotrauma/WorkshopMods/Installed/3406279065/Text/style.xml
new file mode 100644
index 00000000..03dceedd
--- /dev/null
+++ b/Daedalic Entertainment GmbH/Barotrauma/WorkshopMods/Installed/3406279065/Text/style.xml
@@ -0,0 +1,6 @@
+
+
\ No newline at end of file
diff --git a/Daedalic Entertainment GmbH/Barotrauma/WorkshopMods/Installed/3406279065/filelist.xml b/Daedalic Entertainment GmbH/Barotrauma/WorkshopMods/Installed/3406279065/filelist.xml
new file mode 100644
index 00000000..0e8fce35
--- /dev/null
+++ b/Daedalic Entertainment GmbH/Barotrauma/WorkshopMods/Installed/3406279065/filelist.xml
@@ -0,0 +1,7 @@
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Daedalic Entertainment GmbH/Barotrauma/WorkshopMods/Installed/3413495302/Lua/Autorun/ReloadLua.lua b/Daedalic Entertainment GmbH/Barotrauma/WorkshopMods/Installed/3413495302/Lua/Autorun/ReloadLua.lua
new file mode 100644
index 00000000..1ce9dc0b
--- /dev/null
+++ b/Daedalic Entertainment GmbH/Barotrauma/WorkshopMods/Installed/3413495302/Lua/Autorun/ReloadLua.lua
@@ -0,0 +1,466 @@
+if SERVER then return end
+
+LuaUserData.RegisterType("Barotrauma.Items.Components.ItemContainer+SlotRestrictions")
+LuaUserData.RegisterType('System.Collections.Immutable.ImmutableArray`1[[Barotrauma.Items.Components.ItemContainer+SlotRestrictions, Barotrauma]]')
+LuaUserData.MakeFieldAccessible(Descriptors['Barotrauma.Items.Components.ItemContainer'], 'slotRestrictions')
+LuaUserData.MakeFieldAccessible(Descriptors['Barotrauma.ItemInventory'], 'slots')
+LuaUserData.MakeFieldAccessible(Descriptors["Barotrauma.CharacterInventory"], "slots")
+
+ -- 配置重试参数
+ local RETRY_CONFIG = {
+ INTERVAL = 0.3, -- 重试间隔(秒)
+ MAX_ATTEMPTS = 3, -- 最大尝试次数
+ VALIDITY_DURATION = 5,-- 记录有效期(秒)
+ GENERATION_INTERVAL = 0.5 -- 分代时间间隔
+ }
+
+ -- 状态存储表
+ local retryQueue = {} -- 结构:
+ -- {
+ -- [magID] =
+ -- {
+ -- generations =
+ -- {
+ -- [generationID] = { attempts, nextAttempt, expiry },
+ -- ...
+ -- },
+ -- mag = entityRef
+ -- },
+ -- ...
+ -- }
+
+local function isSlotFull(slotRestriction, slot)
+ return slotRestriction.MaxStackSize - #slot.items
+end
+
+local function tryPutItemsInInventory(character, hand, anotherhand, handInv, handIEnumerable, anotherhandIEnumerable)
+
+ -- 重试队列管理
+ local function addToRetryQueue(mag)
+ if not mag then return end
+
+ local currentTime = Timer.GetTime()
+ local magID = mag.ID
+
+ -- 生成分代ID(每0.5秒为一个分代)
+ local generationID = math.floor(currentTime / RETRY_CONFIG.GENERATION_INTERVAL)
+
+ -- 初始化队列条目
+ if not retryQueue[magID] then
+ retryQueue[magID] = {
+ mag = mag,
+ generations = {}
+ }
+ end
+
+ -- 更新分代记录
+ local entry = retryQueue[magID]
+ if not entry.generations[generationID] then
+ entry.generations[generationID] = {
+ attempts = 0,
+ nextAttempt = currentTime + RETRY_CONFIG.INTERVAL,
+ expiry = currentTime + RETRY_CONFIG.VALIDITY_DURATION
+ }
+ else
+ -- 延长该分代的过期时间
+ entry.generations[generationID].expiry = currentTime + RETRY_CONFIG.VALIDITY_DURATION
+ end
+
+ -- print(string.format("Added generation %d for %s", generationID, mag.Name))
+ end
+
+ if not handInv then return end
+
+ local handInvSlots = handInv.slots
+
+ local function getPlayerInvItemsWithoutHand()
+ local playerInvItems = character.Inventory.AllItemsMod
+ -- 去除双手持有的物品,避免在双持情况下互相抢弹药
+ for i = #playerInvItems, 1, -1 do
+ local item = playerInvItems[i]
+ if (hand and item.ID == hand.ID) or (anotherhand and item.ID == anotherhand.ID) then
+ table.remove(playerInvItems, i)
+ end
+ end
+ return playerInvItems
+ end
+
+ -- 内部堆叠实现(原tryStackMagzine拆分)
+ local function tryStackMagazineInternal(mag)
+ if not mag or mag.ConditionPercentage > 0 then
+ return false
+ end
+
+ -- 原有堆叠逻辑
+ local function tryStackInInventory(inventory, Mag)
+ local identifier = Mag.Prefab.Identifier
+ for i, slot in ipairs(inventory.slots) do
+ for _, item in ipairs(slot.items) do
+ if item.HasTag("weapon") then goto continue end
+ if item.Prefab.Identifier.Equals(identifier) and item.ConditionPercentage == 0 and item.ID ~= Mag.ID then -- 只有空弹匣可堆叠
+ if inventory.CanBePutInSlot(Mag, i-1) then
+ inventory.TryPutItem(Mag, i-1, false, true, nil)
+ return true
+ end
+ end
+ ::continue::
+ end
+ end
+ return false
+ end
+
+ -- 尝试玩家库存
+ if tryStackInInventory(character.Inventory, mag) then
+ return true
+ end
+
+ -- 尝试子容器
+ for item in getPlayerInvItemsWithoutHand() do
+ if item.OwnInventory and tryStackInInventory(item.OwnInventory, mag) then
+ return true
+ end
+ end
+
+ return false
+ end
+
+ -- 外部入口函数(替换原tryStackMagzine)
+ local function tryStackMagzine(mag)
+ if not mag then return false end
+
+ -- 立即尝试
+ local success = tryStackMagazineInternal(mag)
+
+ -- 失败时加入队列
+ if not success then
+ -- 防止重复添加
+ addToRetryQueue(mag)
+ end
+
+ return success
+ end
+
+ -- -- 堆叠弹匣
+ -- local function tryStackMagzine(Mag)
+ -- if Mag == nil or Mag.ConditionPercentage ~= 0 then return false end
+ -- local function tryStackInInventory(inventory, Mag)
+ -- local identifier = Mag.Prefab.Identifier
+ -- for i, slot in ipairs(inventory.slots) do
+ -- for _, item in ipairs(slot.items) do
+ -- if item.HasTag("weapon") then goto continue end
+ -- if item.Prefab.Identifier.Equals(identifier) and item.ConditionPercentage == 0 and item.ID ~= Mag.ID then -- 只有空弹匣可堆叠
+ -- if inventory.TryPutItem(Mag, i-1, false, true, nil) then
+ -- return true
+ -- end
+ -- end
+ -- ::continue::
+ -- end
+ -- end
+ -- return false
+ -- end
+
+ -- -- 尝试将弹匣堆叠到玩家物品栏1-10
+ -- if tryStackInInventory(character.Inventory, Mag) then
+ -- return true
+ -- end
+
+ -- -- 尝试将弹匣堆叠到玩家背包、衣服等子物品栏
+ -- for item in getPlayerInvItemsWithoutHand() do
+ -- if item.OwnInventory then
+ -- if tryStackInInventory(item.OwnInventory, Mag) then
+ -- return true
+ -- end
+ -- end
+ -- end
+ -- return false
+ -- end
+
+ -- 卸载弹匣
+ local function unloadMag(index)
+ local unloadedMag = handInvSlots[index].items[1]
+
+ -- 尝试堆叠弹匣
+ if tryStackMagzine(unloadedMag) then return true end
+
+ local slots = character.Inventory.slots
+ -- 如果都失败了,优先尝试将弹匣放入玩家背包、衣服子物品栏
+ for i = #slots, 1, -1 do
+ if i == 4 or i == 5 or i == 8 then
+ if character.Inventory.TryPutItem(unloadedMag, i-1, false, true, nil) then
+ return true
+ end
+ end
+ end
+
+ -- 然后尝试将弹匣放入玩家物品栏1-10
+ for i = #slots, 1, -1 do
+ if i <= 8 or i == 19 then goto continue end
+ if character.Inventory.CanBePutInSlot(unloadedMag, i-1) then
+ character.Inventory.TryPutItem(unloadedMag, i-1, false, false, nil)
+ return true
+ end
+ ::continue::
+ end
+
+ -- 保底情况,将弹匣丢到地面,暂时视为false,目前bool未使用
+ unloadedMag.Drop(character, true, true)
+ return false
+ end
+
+ -- 根据 index 构建一个含有所有可用的弹药/弹匣的 table,参数 num 是要寻找的数量
+ local function findAvailableItemInPlayerInv(index, num)
+ local itemTable = {}
+
+ for item in getPlayerInvItemsWithoutHand() do
+ local count = 0
+
+ -- 忽略掉所有带武器标签的物品,避免从其他武器中抢弹药
+ if item.HasTag("weapon") then goto continue end
+ if handInv.CanBePutInSlot(item, index) and item.ConditionPercentage > 0 then
+ if itemTable[item.Prefab.Identifier.value] == nil then itemTable[item.Prefab.Identifier.value] = {} end
+
+ table.insert(itemTable[item.Prefab.Identifier.value], item)
+ count = count + 1
+ if count >= num then break end
+ end
+ if item.OwnInventory then
+ for item2 in item.OwnInventory.AllItemsMod do
+ if handInv.CanBePutInSlot(item2, index) and item2.ConditionPercentage > 0 then
+ if itemTable[item2.Prefab.Identifier.value] == nil then itemTable[item2.Prefab.Identifier.value] = {} end
+
+ table.insert(itemTable[item2.Prefab.Identifier.value], item2)
+ count = count + 1
+ if count >= num then break end
+ end
+ end
+ end
+ ::continue::
+ end
+
+ local maxLength = 0
+ local maxElement = {}
+ for identifier, items in pairs(itemTable) do
+ if #items > maxLength then
+ maxLength = #items
+ maxElement = itemTable[identifier]
+ end
+ end
+
+ return maxElement
+ end
+
+ -- 根据 index 寻找可用的弹匣,但不要装入unloadedMag
+ local function findAvailableMagInPlayerInv(index, unloadedMag)
+ for item in getPlayerInvItemsWithoutHand() do
+ -- 忽略掉所有带武器标签的物品,避免从其他武器中抢弹药
+ if item.HasTag("weapon") then goto continue end
+ if item and item.ID ~= unloadedMag.ID and handInv.CanBePutInSlot(item, index) and item.ConditionPercentage > 0 then
+ return item
+ end
+ if item.OwnInventory then
+ for item2 in item.OwnInventory.AllItemsMod do
+ if item2 and item2.ID ~= unloadedMag.ID and handInv.CanBePutInSlot(item2, index) and item2.ConditionPercentage > 0 then
+ return item2
+ end
+ end
+ end
+ ::continue::
+ end
+ return nil
+ end
+
+ -- 根据 identifier 构建一个含有所有可用的弹药/弹匣的 table,参数 num 是要寻找的数量
+ local function findAvailableItemWithIdentifier(identifier, num)
+ local findTable = {}
+ local count = 0
+ for item in getPlayerInvItemsWithoutHand() do
+ -- 忽略掉所有带武器标签的物品,避免从其他武器中抢弹药
+ if item.HasTag("weapon") then goto continue end
+
+ if item.Prefab.Identifier.Equals(identifier) then
+ table.insert(findTable, item)
+ count = count + 1
+ if count >= num then
+ return findTable
+ end
+ end
+ if item.OwnInventory then
+ for item2 in item.OwnInventory.AllItemsMod do
+ if item2.Prefab.Identifier.Equals(identifier) then
+ table.insert(findTable, item2)
+ count = count + 1
+ if count >= num then
+ return findTable
+ end
+ end
+ end
+ end
+ ::continue::
+ end
+ return findTable
+ end
+
+ -- 根据 identifier 返回一个可用于堆叠已有弹匣的物品
+ local function findAvailableForStackingInPlayerInv(identifier)
+ local itemList = {}
+ for item in getPlayerInvItemsWithoutHand() do
+ if item.HasTag("weapon") then goto continue end
+ if item.Prefab.Identifier.Equals(identifier) and item.ConditionPercentage > 0 then
+ table.insert(itemList, item)
+ end
+ if item.OwnInventory then
+ for item2 in item.OwnInventory.AllItemsMod do
+ if item2.Prefab.Identifier.Equals(identifier) and item2.ConditionPercentage > 0 then
+ table.insert(itemList, item2)
+ end
+ end
+ end
+ ::continue::
+ end
+ -- 对 itemList 依照 ConditionPercentage 进行升序排序
+ table.sort(itemList, function(a, b) return a.ConditionPercentage < b.ConditionPercentage end)
+
+ return itemList
+ end
+
+ local function putItem(item, index, isForStacking, isForSplitting)
+ if item == nil or item.ConditionPercentage == 0 or item == hand or item == anotherhand then return end
+ if not handInv.TryPutItem(item, index, isForStacking, isForSplitting, character, true, true)
+ then return false end -- 如果上弹失败,则返回false
+ return true
+ end
+
+ -- 对枪械中每个 SlotRestriction 进行处理
+ local itemContainer = handInv.Container
+ local i = math.max(itemContainer.ContainedStateIndicatorSlot + 1, 1) -- 准确定位弹匣的slot
+ local handInvSlotRestriction = itemContainer.slotRestrictions[i-1]
+ -- 空物品情况
+ if #handInvSlots[i].items == 0 then
+ for _, item in ipairs(findAvailableItemInPlayerInv(i - 1, isSlotFull(handInvSlotRestriction, handInvSlots[i]))) do
+ putItem(item, i - 1, false, false)
+ end
+ -- 已有可堆叠弹药的情况
+ elseif #handInvSlots[i].items > 0 and isSlotFull(handInvSlotRestriction, handInvSlots[i]) > 0 then
+ for _, item in ipairs(findAvailableItemWithIdentifier(handInvSlots[i].items[1].Prefab.Identifier, isSlotFull(handInvSlotRestriction, handInvSlots[i]))) do
+ putItem(item, i - 1, false, false)
+ end
+ end
+ -- 已有弹匣的情况
+ if isSlotFull(handInvSlotRestriction, handInvSlots[i]) == 0 and #handInvSlots[i].items == 1 and handInvSlots[i].items[1].ConditionPercentage ~= 100 then
+ local itemlist = findAvailableForStackingInPlayerInv(handInvSlots[i].items[1].Prefab.Identifier)
+ local item = itemlist[1]
+ if (#itemlist == 1 and handInvSlots[i].items[1].ConditionPercentage == 0) or (item and item.ConditionPercentage ~=100 and handInvSlots[i].items[1].ConditionPercentage == 0) then --特殊情况,只剩一个弹匣下处理堆叠问题
+ unloadMag(i)
+ putItem(item, i - 1, true, true)
+ end
+ if not putItem(item, i - 1, true, true) then -- 如果上弹失败,卸载弹匣
+ local unloadedMag = handInvSlots[i].items[1]
+ unloadMag(i)
+ -- 如果此时双手武器未装备,重新装备武器
+ local currentHand = character.Inventory.GetItemInLimbSlot(handIEnumerable[1])
+ local currentAnotherHand = character.Inventory.GetItemInLimbSlot(anotherhandIEnumerable[1])
+ if (currentHand == hand and currentAnotherHand == anotherhand) ~= true then
+ if hand and anotherhand and hand.ID == anotherhand.ID then -- 如果为双手武器
+ for _, handSlotType in ipairs { InvSlotType.LeftHand, InvSlotType.RightHand } do
+ local handSlotIndex = character.Inventory.FindLimbSlot(handSlotType)
+ if handSlotIndex >= 0 then
+ character.Inventory.TryPutItem(hand, handSlotIndex, true, false, character, true, true)
+ end
+ end
+ else -- 如果为单手武器或者双持武器
+ character.Inventory.TryPutItem(hand, character, handIEnumerable, true, true)
+ character.Inventory.TryPutItem(anotherhand, character, anotherhandIEnumerable, true, true)
+ end
+ end
+ local findMag = findAvailableMagInPlayerInv(i - 1, unloadedMag)
+ if #itemlist == 0 and unloadedMag.ConditionPercentage > 0 and findMag == nil then
+ putItem(unloadedMag, i - 1, false, false)
+ else
+ putItem(findMag, i - 1, false, false)
+ end
+ end
+ tryStackMagzine(item) -- 尝试堆叠空弹匣
+ end
+
+ -- 注册每帧检查,在多人游戏对tryStackMagazine进行重试
+ Hook.Add("think", "magazineRetrySystem", function()
+ if not retryQueue then return end
+ local currentTime = Timer.GetTime()
+
+ -- 遍历所有条目
+ for magID, entry in pairs(retryQueue) do
+ local mag = entry.mag
+ local hasValidGenerations = false
+
+ -- 实体有效性检查
+ if not mag or mag.ID ~= magID then
+ retryQueue[magID] = nil
+ goto continue
+ end
+
+ for genID, genRecord in pairs(entry.generations) do
+ -- 清理过期分代
+ if currentTime > genRecord.expiry then
+ entry.generations[genID] = nil
+ -- print("Generation expired:", genID)
+ goto next_generation
+ end
+
+ -- 执行重试条件检查
+ if currentTime >= genRecord.nextAttempt then
+ -- 执行重试
+ local success = tryStackMagazineInternal(mag)
+
+ if success then
+ -- 成功时清除全部分代
+ retryQueue[magID] = nil
+ -- print("Success via generation:", genID)
+ goto continue
+ else
+ -- 更新重试状态
+ genRecord.attempts = genRecord.attempts + 1
+ genRecord.nextAttempt = currentTime + RETRY_CONFIG.INTERVAL
+
+ -- 超过最大尝试次数
+ if genRecord.attempts >= RETRY_CONFIG.MAX_ATTEMPTS then
+ entry.generations[genID] = nil
+ -- print("Max attempts for generation:", genID)
+ end
+ end
+ end
+
+ hasValidGenerations = true
+ ::next_generation::
+ end
+
+ -- 清理空条目
+ if not hasValidGenerations then
+ retryQueue[magID] = nil
+ end
+
+ ::continue::
+ end
+ end)
+end
+
+Hook.Patch("Barotrauma.Character", "ControlLocalPlayer", function(instance, ptable)
+ if retryQueue == nil then Hook.Remove("think", "magazineRetrySystem") end
+ if not PlayerInput.KeyHit(Keys.R) then return end
+ local Character = instance
+ if not Character then return end
+
+ local rightHand = Character.Inventory.GetItemInLimbSlot(InvSlotType.RightHand)
+ local leftHand = Character.Inventory.GetItemInLimbSlot(InvSlotType.LeftHand)
+ local rightHandIEnumerable = {InvSlotType.RightHand}
+ local leftHandIEnumerable = {InvSlotType.LeftHand}
+
+ if not rightHand and not leftHand then return end
+
+ if rightHand and rightHand.HasTag("weapon") then
+ tryPutItemsInInventory(Character, rightHand, leftHand, rightHand.OwnInventory, rightHandIEnumerable, leftHandIEnumerable)
+ end
+
+ if leftHand and not leftHand.Equals(rightHand) and leftHand.HasTag("weapon") then
+ tryPutItemsInInventory(Character, leftHand, rightHand, leftHand.OwnInventory, leftHandIEnumerable, rightHandIEnumerable)
+ end
+end, Hook.HookMethodType.After)
diff --git a/Daedalic Entertainment GmbH/Barotrauma/WorkshopMods/Installed/3413495302/PressRtoReload.png b/Daedalic Entertainment GmbH/Barotrauma/WorkshopMods/Installed/3413495302/PressRtoReload.png
new file mode 100644
index 00000000..40a17f2e
--- /dev/null
+++ b/Daedalic Entertainment GmbH/Barotrauma/WorkshopMods/Installed/3413495302/PressRtoReload.png
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:d7cbe3c1f9d524fad4ae2f22246159e984ee832371f9016cc95375ddf86c4448
+size 26231
diff --git a/Daedalic Entertainment GmbH/Barotrauma/WorkshopMods/Installed/3413495302/Reload.code-workspace b/Daedalic Entertainment GmbH/Barotrauma/WorkshopMods/Installed/3413495302/Reload.code-workspace
new file mode 100644
index 00000000..eece1027
--- /dev/null
+++ b/Daedalic Entertainment GmbH/Barotrauma/WorkshopMods/Installed/3413495302/Reload.code-workspace
@@ -0,0 +1,41 @@
+{
+ "folders": [
+ {
+ "path": "."
+ },
+ ],
+ "settings": {
+ "Lua.diagnostics.libraryFiles": "Enable",
+ "Lua.workspace.library": [
+ "D:/Projects/Barotrauma/types/client",
+ "D:/Projects/Barotrauma/types/shared",
+ ],
+
+ "Lua.diagnostics.disable": [
+ "param-type-mismatch",
+ "return-type-mismatch",
+ "undefined-field",
+ "need-check-nil",
+ "assign-type-mismatch",
+ "redundant-return-value",
+ "missing-parameter",
+ "undefined-global",
+ "missing-return-value",
+ "undefined-doc-name",
+ "missing-return",
+ "cast-local-type",
+ "deprecated",
+ ],
+ },
+ "launch": {
+ "version": "0.2.0",
+ "configurations": [
+ {
+ "name": "MoonSharp Attach",
+ "type": "moonsharp-debug",
+ "request": "attach",
+ "debugServer" : 41912
+ }
+ ]
+ }
+}
\ No newline at end of file
diff --git a/Daedalic Entertainment GmbH/Barotrauma/WorkshopMods/Installed/3413495302/filelist.xml b/Daedalic Entertainment GmbH/Barotrauma/WorkshopMods/Installed/3413495302/filelist.xml
new file mode 100644
index 00000000..1788f076
--- /dev/null
+++ b/Daedalic Entertainment GmbH/Barotrauma/WorkshopMods/Installed/3413495302/filelist.xml
@@ -0,0 +1,2 @@
+
+
\ No newline at end of file
diff --git a/Daedalic Entertainment GmbH/Barotrauma/WorkshopMods/Installed/3438745304/Assets/CUI.png b/Daedalic Entertainment GmbH/Barotrauma/WorkshopMods/Installed/3438745304/Assets/CUI.png
new file mode 100644
index 00000000..e9f759f0
--- /dev/null
+++ b/Daedalic Entertainment GmbH/Barotrauma/WorkshopMods/Installed/3438745304/Assets/CUI.png
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:79204bd67761e8abf0b8ddb0d4f313ae829f963feee896242e3fa465cbcba3e0
+size 5884
diff --git a/Daedalic Entertainment GmbH/Barotrauma/WorkshopMods/Installed/3438745304/Assets/Default Styles.xml b/Daedalic Entertainment GmbH/Barotrauma/WorkshopMods/Installed/3438745304/Assets/Default Styles.xml
new file mode 100644
index 00000000..521dd166
--- /dev/null
+++ b/Daedalic Entertainment GmbH/Barotrauma/WorkshopMods/Installed/3438745304/Assets/Default Styles.xml
@@ -0,0 +1,73 @@
+
+
+
+ CUIPalette.Component.Background
+ CUIPalette.Component.Border
+ CUIPalette.Handle.Background
+ CUIPalette.Handle.Grabbed
+
+
+ CUIPalette.Frame.Background
+ CUIPalette.Frame.Border
+
+
+ CUIPalette.Component.Text
+ Transparent
+ Transparent
+ [4,0]
+
+
+ CUIPalette.Input.Text
+ CUIPalette.Input.Border
+ CUIPalette.Input.Background
+
+
+ CUIPalette.Button.Background
+ CUIPalette.Button.Border
+ CUIPalette.Button.Disabled
+ [4,2]
+ [0.5,0.5]
+
+
+ CUIPalette.Button.Background
+ CUIPalette.Button.Disabled
+
+
+ CUIPalette.Button.Background
+ CUIPalette.Button.Border
+ CUIPalette.Button.Background
+
+
+ CUIPalette.CloseButton.Background
+ Transparent
+
+
+ Transparent
+ Transparent
+ CUIPalette.DDOption.Hover
+ CUIPalette.DDOption.Text
+ [0,0]
+ [4,0]
+
+
+ Transparent
+ Transparent
+
+
+ CUIPalette.Main.Text
+
+
+ White
+ Black
+
+
+ Transparent
+
+
+ Transparent
+
+
+ Transparent
+ Transparent
+
+
\ No newline at end of file
diff --git a/Daedalic Entertainment GmbH/Barotrauma/WorkshopMods/Installed/3438745304/Assets/Interaction icons sharp.png b/Daedalic Entertainment GmbH/Barotrauma/WorkshopMods/Installed/3438745304/Assets/Interaction icons sharp.png
new file mode 100644
index 00000000..29e70290
--- /dev/null
+++ b/Daedalic Entertainment GmbH/Barotrauma/WorkshopMods/Installed/3438745304/Assets/Interaction icons sharp.png
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:f6e6e1f37f5c6d11e034983fd62001a0e7a86ed6200d0031dab8235e5a27e3ef
+size 14791
diff --git a/Daedalic Entertainment GmbH/Barotrauma/WorkshopMods/Installed/3438745304/Assets/Interaction icons.png b/Daedalic Entertainment GmbH/Barotrauma/WorkshopMods/Installed/3438745304/Assets/Interaction icons.png
new file mode 100644
index 00000000..6730aae6
--- /dev/null
+++ b/Daedalic Entertainment GmbH/Barotrauma/WorkshopMods/Installed/3438745304/Assets/Interaction icons.png
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:48e73051969cb0b2b3f534b24dd655d5dad73345931ea5d1f4b3ceb9d4b6bb18
+size 20615
diff --git a/Daedalic Entertainment GmbH/Barotrauma/WorkshopMods/Installed/3438745304/Assets/PaletteDemo.xml b/Daedalic Entertainment GmbH/Barotrauma/WorkshopMods/Installed/3438745304/Assets/PaletteDemo.xml
new file mode 100644
index 00000000..6ae13d75
--- /dev/null
+++ b/Daedalic Entertainment GmbH/Barotrauma/WorkshopMods/Installed/3438745304/Assets/PaletteDemo.xml
@@ -0,0 +1,23 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Daedalic Entertainment GmbH/Barotrauma/WorkshopMods/Installed/3438745304/Assets/Palettes/Sets/Blue.xml b/Daedalic Entertainment GmbH/Barotrauma/WorkshopMods/Installed/3438745304/Assets/Palettes/Sets/Blue.xml
new file mode 100644
index 00000000..331fdedf
--- /dev/null
+++ b/Daedalic Entertainment GmbH/Barotrauma/WorkshopMods/Installed/3438745304/Assets/Palettes/Sets/Blue.xml
@@ -0,0 +1,55 @@
+
+
+
+
+
+
+
+
+
+
+
+
+ 178,178,255,255
+
+
+
+
+
+
+
+
+
+
+
+
+ 197,178,255,255
+
+
+
+
+
+
+
+
+
+
+
+
+ 178,216,255,255
+
+
+
+
+
+
+
+
+
+
+
+
+ 216,178,255,255
+
+
+
\ No newline at end of file
diff --git a/Daedalic Entertainment GmbH/Barotrauma/WorkshopMods/Installed/3438745304/CSharp/Client/CrabUI/Animations/CUIAnimation.cs b/Daedalic Entertainment GmbH/Barotrauma/WorkshopMods/Installed/3438745304/CSharp/Client/CrabUI/Animations/CUIAnimation.cs
new file mode 100644
index 00000000..610b5721
--- /dev/null
+++ b/Daedalic Entertainment GmbH/Barotrauma/WorkshopMods/Installed/3438745304/CSharp/Client/CrabUI/Animations/CUIAnimation.cs
@@ -0,0 +1,260 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Reflection;
+using System.Diagnostics;
+using System.IO;
+
+using Barotrauma;
+using Microsoft.Xna.Framework;
+
+namespace QICrabUI
+{
+ ///
+ /// WIP, can animate any property on any object
+ /// Can run back and forth in [0..1] interval and
+ /// interpolate any property between StartValue and EndValue
+ ///
+ public class CUIAnimation
+ {
+ internal static void InitStatic()
+ {
+ CUI.OnDispose += () => ActiveAnimations.Clear();
+ }
+
+ public static HashSet ActiveAnimations = new();
+ ///
+ /// This is called in CUIUpdate
+ ///
+ internal static void UpdateAllAnimations(double time)
+ {
+ foreach (CUIAnimation animation in ActiveAnimations)
+ {
+ animation.Step(time);
+ }
+ }
+
+ public bool Debug { get; set; }
+ public static float StartLambda = 0.0f;
+ public static float EndLambda = 1.0f;
+
+
+ private object target;
+ ///
+ /// Object containing animated property
+ ///
+ public object Target
+ {
+ get => target;
+ set
+ {
+ target = value;
+ UpdateSetter();
+ }
+ }
+ private bool active;
+ public bool Active
+ {
+ get => active;
+ set
+ {
+ if (Blocked || active == value) return;
+ active = value;
+
+ if (active) ActiveAnimations.Add(this);
+ else ActiveAnimations.Remove(this);
+ ApplyValue();
+ }
+ }
+
+ ///
+ /// In seconds
+ ///
+ public double Duration
+ {
+ get => 1.0 / Speed * Timing.Step;
+ set
+ {
+ double steps = value / Timing.Step;
+ Speed = 1.0 / steps;
+ }
+ }
+
+ public double ReverseDuration
+ {
+ get => 1.0 / (BackSpeed ?? 0) * Timing.Step;
+ set
+ {
+ double steps = value / Timing.Step;
+ BackSpeed = 1.0 / steps;
+ }
+ }
+
+ ///
+ /// Will prevent it from starting
+ ///
+ public bool Blocked { get; set; }
+ ///
+ /// Progress of animation [0..1]
+ ///
+ public double Lambda { get; set; }
+ ///
+ /// Lambda increase per update step, calculated when you set Duration
+ ///
+ public double Speed { get; set; } = 0.01;
+ public double? BackSpeed { get; set; }
+ ///
+ /// If true animation won't stop when reaching end, it will change direction
+ ///
+ public bool Bounce { get; set; }
+ ///
+ /// Straight, Reverse
+ ///
+ public CUIDirection Direction { get; set; }
+ ///
+ /// Value will be interpolated between these values
+ ///
+ public object StartValue { get; set; }
+ public object EndValue { get; set; }
+
+ private string property;
+ private Action