if getgenv().RivalsCosmeticsCleanup then pcall(getgenv().RivalsCosmeticsCleanup) end local rs = game:GetService("ReplicatedStorage") local http = game:GetService("HttpService") local plr = game:GetService("Players").LocalPlayer local lib = require(rs.Modules.CosmeticLibrary) local replicated = require(rs.Modules.ReplicatedClass) local vmClass = require(plr.PlayerScripts.Modules.ClientReplicatedClasses.ClientFighter.ClientItem.ClientViewModel) local viewModels = plr.PlayerScripts.Assets.ViewModels local classes = plr.PlayerScripts.Modules.ViewModels local pdc = require(plr:WaitForChild("PlayerScripts").Controllers:WaitForChild("PlayerDataController")) local equipRemote = rs.Remotes.Data.EquipCosmetic local folder = "Cryptic Hub" local file = folder .. "/Rivals Cosmetics.json" local slots = { Skin = true, Wrap = true, Charm = true, Finisher = true } local added = {} local saved = {} local alive = true local swaps = {} local swapping local moduleCache = {} local oldNc local oldGet = replicated.Get local oldVmGet = rawget(vmClass, "Get") local function get(key) local ok, v = pcall(pdc.CurrentData.Get, pdc.CurrentData, key) return ok and v or nil end local function flush() pcall(function() if not isfolder(folder) then makefolder(folder) end writefile(file, http:JSONEncode(saved)) end) end local function find(weapon) local list = get("WeaponInventory") if not list then return end for _, w in pairs(list) do if w.Name == weapon then return w end end end local inv = get("CosmeticInventory") for name in pairs(lib.Cosmetics) do if inv and inv[name] == nil then inv[name] = true added[name] = true end end pcall(function() if isfile(file) then saved = http:JSONDecode(readfile(file)) end end) for weapon, picks in pairs(saved) do local w = find(weapon) if w then for slot, entry in pairs(picks) do if slots[slot] and lib.Cosmetics[entry.Name] then w[slot] = entry end end end end local function baseOf(name) local cosmetic = lib.Cosmetics[name] if cosmetic and cosmetic.Type == "Skin" and cosmetic.ItemName then return cosmetic.ItemName end return name end local function compatible(skinName, heldName) local skinModel = viewModels:FindFirstChild(skinName, true) local heldModel = viewModels:FindFirstChild(heldName, true) if not skinModel or not heldModel then return false end for _, child in ipairs(heldModel:GetChildren()) do if not skinModel:FindFirstChild(child.Name) then return false end end return true end replicated.Get = function(self, key) if alive and slots[key] then local data = rawget(self, "Data") local picks = data and saved[baseOf(data.Name)] local entry = picks and picks[key] if entry ~= nil then return entry end end return oldGet(self, key) end local function moduleOf(name) local cached = moduleCache[name] if cached == nil then local found = classes:FindFirstChild(name, true) cached = found and found:IsA("ModuleScript") and found or false moduleCache[name] = cached end return cached or nil end local function installSwap(weapon) if swaps[weapon] then return end local defaultModule = moduleOf(weapon) if not defaultModule then return end local ok, class = pcall(require, defaultModule) if not ok or type(class) ~= "table" or type(rawget(class, "new")) ~= "function" then return end local origNew = class.new swaps[weapon] = { class = class, origNew = origNew } class.new = function(...) local picks = alive and saved[weapon] local skin = picks and picks.Skin local skinModule = skin and moduleOf(skin.Name) if skinModule and not swapping and viewModels:FindFirstChild(skin.Name, true) and (skinModule.Parent == defaultModule.Parent or skinModule.Parent == defaultModule) then local loaded, skinClass = pcall(require, skinModule) if loaded and type(skinClass) == "table" and type(skinClass.new) == "function" then swapping = { weapon = weapon, skin = skin.Name } local built, object = pcall(skinClass.new, ...) swapping = nil if built then return object end end end return origNew(...) end end for weapon, picks in pairs(saved) do if picks.Skin then installSwap(weapon) end end vmClass.Get = function(self, key) if alive and key == "Name" then local data = rawget(self, "Data") if data then if swapping and baseOf(data.Name) == swapping.weapon then return swapping.skin end local picks = saved[baseOf(data.Name)] local skin = picks and picks.Skin if skin and not moduleOf(skin.Name) and compatible(skin.Name, data.Name) then return skin.Name end end end return (oldVmGet or replicated.Get)(self, key) end local function refreshHeld(weapon, slot) if slot ~= "Wrap" and slot ~= "Charm" then return end for _, obj in ipairs(getgc(true)) do if type(obj) == "table" and type(rawget(obj, "Data")) == "table" and rawget(obj, "ClientItem") and rawget(obj, "Model") and baseOf(obj.Data.Name) == weapon then local entry = saved[weapon] and saved[weapon][slot] obj.Data[slot] = entry local signal = obj._value_changed_events and obj._value_changed_events[slot] if signal then pcall(signal.Fire, signal, entry) end if slot == "Wrap" and obj._UpdateWrap then pcall(obj._UpdateWrap, obj) end end end end local function equip(weapon, slot, name, extra) local w = find(weapon) if not w then return false end local entry if name then entry = { Name = name, Inverted = slot == "Wrap" and extra and extra.IsInverted or nil } end w[slot] = entry saved[weapon] = saved[weapon] or {} saved[weapon][slot] = entry if slot == "Skin" and entry then installSwap(weapon) end flush() refreshHeld(weapon, slot) return true end oldNc = hookmetamethod(game, "__namecall", newcclosure(function(self, ...) if alive and self == equipRemote and not checkcaller() and getnamecallmethod() == "FireServer" then local weapon, slot, name, extra = ... if slots[slot] and (name == nil or lib.Cosmetics[name]) and equip(weapon, slot, name, extra) then return end end return oldNc(self, ...) end)) getgenv().RivalsCosmeticsCleanup = function() alive = false replicated.Get = oldGet vmClass.Get = oldVmGet for _, swap in pairs(swaps) do swap.class.new = swap.origNew end local cur = get("CosmeticInventory") if cur then for name in pairs(added) do cur[name] = nil end end getgenv().RivalsCosmeticsCleanup = nil end