Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
16 commits
Select commit Hold shift + click to select a range
09d532f
Fix Loose Loot interaction, Loot Tool saving, and UI closing UX.
google-labs-jules[bot] Jan 24, 2026
3fd620f
Refine E-to-Close logic and fix Loose Loot pickup reliability.
google-labs-jules[bot] Jan 24, 2026
934258d
Refine loot session management, fix persistent windows, and correct a…
google-labs-jules[bot] Jan 25, 2026
e23d0ad
Robustly fix Loot Tool saving and loot session bugs.
google-labs-jules[bot] Jan 25, 2026
398ae7d
Implement dynamic loot pools and data persistence.
google-labs-jules[bot] Jan 25, 2026
839a215
Merge branch 'main' into tarkov-inventory-fixes-phase1-24376826075010…
Cautioncrazy Jan 25, 2026
daa77c8
Finalize Dynamic Loot and Persistence with correct timing.
google-labs-jules[bot] Jan 25, 2026
12b1052
Fix weapon usability sync and refine loot timing.
google-labs-jules[bot] Jan 25, 2026
a90a7de
Enable generic entity usage (Ammo/Addons) in inventory.
google-labs-jules[bot] Jan 25, 2026
de47685
Fix addon weapon models in inventory.
google-labs-jules[bot] Jan 25, 2026
a117ab8
Fix addon weapon models using ViewModel fallback.
google-labs-jules[bot] Jan 25, 2026
153fdfc
Robustly fix addon weapon models using weapons.GetStored.
google-labs-jules[bot] Jan 25, 2026
ae4781c
Fix entity model detection in inventory.
google-labs-jules[bot] Jan 25, 2026
a2b1074
Add Melee/Grenade slots and Swap-on-Equip logic.
google-labs-jules[bot] Jan 25, 2026
c2291e2
Fix addon weapon models and entity detection.
google-labs-jules[bot] Jan 26, 2026
2197adf
Force push of model detection fixes for addon weapons.
google-labs-jules[bot] Jan 26, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
152 changes: 142 additions & 10 deletions Escape from GMOD utils/lua/autorun/server/sv_tarkov_loot_bridge.lua
Original file line number Diff line number Diff line change
Expand Up @@ -19,20 +19,100 @@ local CACHE_ENTITIES = {
["ent_loot_cache_tarkov"] = true -- Added our custom test entity just in case
}

-- LOOT TABLES (Simple list of item IDs from sh_tarkov_inventory.lua)
-- You can expand this list with more specific items
-- LOOT TABLES (Will be rebuilt dynamically)
local LOOT_POOLS = {
["weapons"] = {"weapon_pistol", "weapon_smg1", "medkit"},
["medical"] = {"medkit", "medkit", "tushonka"},
["misc"] = {"scrap", "tushonka", "backpack_scav"},
["rare"] = {"bitcoin", "weapon_smg1", "rig_combine"},
["random"] = {"tushonka", "medkit", "bitcoin", "weapon_pistol", "backpack_scav", "scrap", "rig_combine"}
["weapons"] = {},
["medical"] = {},
["misc"] = {},
["rare"] = {},
["gear"] = {},
["ammo"] = {},
["random"] = {}
}

-- DYNAMIC LOOT POOL GENERATION
local function BuildLootPools()
-- Get All Items from shared registry
local allItems = GetAllTarkovItems()

-- Reset Pools
LOOT_POOLS = {
["weapons"] = {},
["medical"] = {},
["misc"] = {},
["rare"] = {},
["gear"] = {},
["ammo"] = {},
["random"] = {}
}

local count = 0
for id, data in pairs(allItems) do
count = count + 1
table.insert(LOOT_POOLS["random"], id)

local lId = string.lower(id)
local lDesc = string.lower(data.Desc or "")
local lName = string.lower(data.Name or "")

-- Categorize based on ID, Type, or Description
if data.Slot == "Primary" or data.Slot == "Secondary" or string.find(lId, "weapon") then
table.insert(LOOT_POOLS["weapons"], id)
end

if string.find(lId, "med") or string.find(lId, "health") or string.find(lName, "med") then
table.insert(LOOT_POOLS["medical"], id)
end

if string.find(lId, "ammo") or string.find(lDesc, "ammo") then
table.insert(LOOT_POOLS["ammo"], id)
end

-- Gear: Prioritize items with Capacity (Backpacks/Rigs) or Armor
if data.Type == "equip" and not string.find(lId, "weapon") then
if (data.Capacity and data.Capacity > 0) or data.Slot == "Armor" or data.Slot == "Rig" or data.Slot == "Backpack" then
table.insert(LOOT_POOLS["gear"], id)
end
end

if data.Type == "item" then
table.insert(LOOT_POOLS["misc"], id)
end

if string.find(lId, "bitcoin") or string.find(lId, "gold") or string.find(lDesc, "rare") then
table.insert(LOOT_POOLS["rare"], id)
end
end

-- Fallback safety
if #LOOT_POOLS["random"] == 0 then
table.insert(LOOT_POOLS["random"], "tushonka")
end

print("[Tarkov Bridge] Built loot pools with " .. count .. " items.")
end

-- Rebuild pools after entities load (so dynamic items are registered)
hook.Add("InitPostEntity", "TarkovBuildPools", function()
-- MUST RUN AFTER sh_tarkov_inventory's 3-second timer
timer.Simple(5, function()
BuildLootPools()
end)
end)

-- Helper to get random item from pool
local function GetRandomItem(poolName)
local pool = LOOT_POOLS[poolName] or LOOT_POOLS["random"]
return pool[math.random(#pool)]
local pool = LOOT_POOLS[poolName]
-- Fallback to random if pool is empty or invalid
if not pool or #pool == 0 then
pool = LOOT_POOLS["random"]
end

if #pool > 0 then
return pool[math.random(#pool)]
else
return "tushonka" -- Ultimate fallback
end
end

-- Helper to open the loot interface (generates loot if needed)
Expand All @@ -52,7 +132,6 @@ local function OpenLootCache(ply, ent)
ent.CacheInventory[slot] = item
end
end
-- print("[Tarkov Bridge] Generated loot for box.")
end

-- 4. OPEN INVENTORY MENU
Expand Down Expand Up @@ -153,3 +232,56 @@ hook.Add("PlayerUse", "TarkovBridge_Use", function(ply, ent)
-- (e.g. stop the workshop addon from opening its own menu)
return false
end)

-- --- DATA PERSISTENCE ---
-- Loads saved loot cache configurations (Pools) on map start
local function LoadLootData()
local mapName = game.GetMap()
if file.Exists("tarkov_data/" .. mapName .. ".json", "DATA") then
local json = file.Read("tarkov_data/" .. mapName .. ".json", "DATA")
local data = util.JSONToTable(json)

if data then
print("[Tarkov Loot] Loading " .. #data .. " loot caches...")
for _, entry in ipairs(data) do
-- Try to find existing entity first (for map props)
local found = false
local nearby = ents.FindInSphere(entry.pos, 5)
for _, ent in ipairs(nearby) do
if ent:GetClass() == (entry.class or "ent_loot_cache") then -- Only match if class matches (or default)
ent:SetNWString("LootPool", entry.pool)
-- Force update pos/ang just in case
ent:SetPos(entry.pos)
ent:SetAngles(entry.ang)
found = true
break
end
end

-- If not found (it was a spawned entity), respawn it
if not found then
local ent = ents.Create(entry.class or "ent_loot_cache")
if IsValid(ent) then
ent:SetPos(entry.pos)
ent:SetAngles(entry.ang)
ent:Spawn()
ent:SetNWString("LootPool", entry.pool)
-- Ensure it doesn't fall through world if physics sleep
local phys = ent:GetPhysicsObject()
if IsValid(phys) then phys:EnableMotion(false) end
end
end
end
end
else
print("[Tarkov Loot] No saved data for map: " .. mapName)
end
end

-- DELAYED LOADING: Wait for other addons (like workshop map props) to spawn
hook.Add("InitPostEntity", "TarkovLoadLoot", function()
timer.Simple(5, LoadLootData)
end)
hook.Add("PostCleanupMap", "TarkovLoadLootClean", function()
timer.Simple(5, LoadLootData)
end)
Loading