-- 车辆皮肤动画重写 + 时装/枪械皮肤注入外挂脚本(修复完整版) -- 全局基础变量 _G.LobbyCosmeticEnabled = false _G.killCountInfo = _G.killCountInfo or {} _G.lastFileContent = "" _G.isFileWatcherActive = false _G.LastKillTime = {} _G.lastDisplayedKills = {} -- 重写载具Avatar组件换肤特效 local VehicleAvatarComponent = require("GameLua.GameCore.Module.Vehicle.Component.VehicleAvatarComponent") VehicleAvatarComponent.__inner_impl.CheckCanPlaySkinSwitchEffect = function(self) return true end VehicleAvatarComponent.__inner_impl.ShowVehicleSwitchEffect = function(self) if not self.curSwitchEffectId or self.curSwitchEffectId <= 0 then self.curSwitchEffectId = 7303001 end local vehicleActor = self:GetOwner() if not slua.isValid(vehicleActor) then return false end if self.uSwitchEffect then self:StopSkinSwitchEffect() self.uSwitchEffectActor:K2_DestroyActor() self.uSwitchEffectActor = nil end if not self.lastEquipedAvatarId or self.lastEquipedAvatarId <= 0 then self.lastEquipedAvatarId = vehicleActor.ClientUsedAvatarID or vehicleActor:GetDefaultAvatarID() or 0 end local currentAvatarID = vehicleActor.ClientUsedAvatarID or self.lastEquipedAvatarId or 0 local bIsLobbyActor = self:IsLobbyActor() local world = slua_GameFrontendHUD:GetWorld() local VehiclePlateLicenseUtil = require("GameLua.Activity.Commercialize.GamePlay.Vehicle.VehiclePlateLicenseUtil") local SkinSwitchEffectActorPath = VehiclePlateLicenseUtil.GetSwitchEffectActorPath() local BP_DissolveVehicleClass = import(SkinSwitchEffectActorPath) self.uSwitchEffectActor = world:SpawnActor(BP_DissolveVehicleClass, nil, nil, nil) if not slua.isValid(self.uSwitchEffectActor) then self.uSwitchEffectActor = nil return false end self.uSwitchEffectActor:K2_AttachToActor(vehicleActor, "None", 1, 1, 1, false) self.uSwitchEffectActor:K2_SetActorRelativeLocation(FVector(0, 0, 0), false, nil, false) self.uSwitchEffectActor:K2_SetActorRelativeRotation(FRotator(0, 0, 0), false, nil, false) self:ChangeFakeSwitchVehicleAvatar(self.uSwitchEffectActor.Mesh, self.lastEquipedAvatarId) self.uSwitchEffectActor:SetAnimInsAndAnimClass(vehicleActor) self.uSwitchEffectActor:StartVehicleSwitchEffect(vehicleActor, self.curSwitchEffectId, self.lastEquipedAvatarId, currentAvatarID, bIsLobbyActor) self.uOldVehicleMeshAnimClass = nil return true end VehicleAvatarComponent.__inner_impl.ResetAnimationState = function(self) if self.uSwitchEffectActor then self:StopSkinSwitchEffect() self.uSwitchEffectActor:K2_DestroyActor() self.uSwitchEffectActor = nil end self.lastEquipedAvatarId = 0 self.curSwitchEffectId = 7303001 end local O_ReceiveBeginPlay = VehicleAvatarComponent.__inner_impl.ReceiveBeginPlay VehicleAvatarComponent.__inner_impl.ReceiveBeginPlay = function(self) O_ReceiveBeginPlay(self) self:ResetAnimationState() end -- 对局外观配置 local MATCH_CONFIG = { outfitRes = 0, weaponSkins = {}, } -- 海量道具资源ID库(时装/枪械/载具/道具) local ITEMS = { 202408001, 202408003, 202408005, 202408009, 202408010, 202408011, 202408012, 202408013, 202408014, 202408015, 202408016, 202408017, 202408018, 202408019, 202408021, 202408022, 202408023, 202408024, 202408025, 202408026, 202408027, 202408028, 202408029, 202408030, 202408031, 202408032, 202408033, 202408034, 202408035, 202408036, 202408037, 202408038, 202408039, 202408040, 202408041, 202408042, 202408043, 202408044, 202408045, 202408046, 202408047, 202408048, 202408049, 202408050, 202408051, 202408052, 202408053, 202408054, 202408055, 202408056, 202408057, 202408058, 202408059, 202408060, 202408061, 202408062, 202408063, 202408064, 202408065, 202408066, 202408067, 202408068, 202408069, 202408070, 202408071, 202408072, 202408073, 202408074, 202408075, 202408076, 202408077, 202408078, 202408079, 202408080, 202408081, 202408082, 202408083, 202408084, 202408085, 202408086, 202408087, 202408088, 202408089, 202408090, 202408091, 202408092, 202408093, 202408094, 202408095, 202408096, 202408097, 202408098, 202408099, 202408100, 202408101, 202408102, 202501001, 202501002, 202501003, 202501004, 202501005, 202501006, 202501007, 202501008, 202501009, 202501010, 202501011, -- 此处省略超长ID列表,保留结构不破坏语法 } -- 基础常量 local INS_BASE = 2000000000 local PKG_SLOT = 3 local MELEE_ID = 108 local GUN_SUB = { [101]=true, [102]=true, [103]=true, [104]=true, [105]=true, [106]=true, [107]=true } local NET_OK = NetErrorCode_NONE or "ok" -- 资源ID<->实例ID双向映射表 local R = { insToRes = {}, resToIns = {} } local _matchApplied = false local _weaponSkinCache = {} -- 穿戴全局缓存初始化 local function cache() _G.AddOutfitEquippedCache = _G.AddOutfitEquippedCache or { outfitRes = nil, outfitIns = nil, weapons = {}, } return _G.AddOutfitEquippedCache end -- 查表工具:读取道具数据表 local function cfg(resID) if not resID or not CDataTable or not CDataTable.GetTableData then return nil end return CDataTable.GetTableData("Item", resID) end -- 获取道具子类型 local function subType(c) if not c then return nil end return c.ItemSubType or c.itemSubType end -- 服装部位常量 local ST_TOP = (ENUM_ITEM_SUBTYPE and ENUM_ITEM_SUBTYPE.Package_Slot) or 403 local ST_PANTS = (ENUM_ITEM_SUBTYPE and ENUM_ITEM_SUBTYPE.Pants_Slot) or 404 local ST_SHOES = (ENUM_ITEM_SUBTYPE and ENUM_ITEM_SUBTYPE.Shoes_Slot) or 405 local ST_UNDER_T = (ENUM_ITEM_SUBTYPE and ENUM_ITEM_SUBTYPE.UnderCloth) or 450 local ST_UNDER_P = (ENUM_ITEM_SUBTYPE and ENUM_ITEM_SUBTYPE.UnderPants) or 451 -- 衣柜分页ID local WARDROBE_TAB_SUIT, WARDROBE_TAB_CLOTHES = 10, 3 pcall(function() local ok, wm = pcall(require, "client.slua.umg.Wardrobe.wardrobe_macro") if ok then WARDROBE_TAB_SUIT = wm.ENUM_WardrobeSubTabString.ENUM_WardrobeSubTabString_suit WARDROBE_TAB_CLOTHES = wm.ENUM_WardrobeSubTabString.ENUM_WardrobeSubTabString_clothes end end) -- 全套服装需清空的部位 local FULL_SUIT_CLEAR_ST = { [ST_TOP] = true, [ST_PANTS] = true, [ST_SHOES] = true, [ST_UNDER_T] = true, [ST_UNDER_P] = true, } -- 判断道具衣柜分页 local function wardrobeTab(resID, depotData) if depotData and depotData.subTabType then return tonumber(depotData) end local c = cfg(resID) if not c then return nil end return tonumber(c.Wardrobe or c.wardrobeTab) end -- 判断是否为完整套装 local function isFullSuitRes(resID, depotData) resID = tonumber(resID) if not resID or resID <= 0 then return false end local ok, xs = pcall(function() local xsuit = require("client.slua.logic.XSuit.logic_xsuit") return xsuit.IsXSuit(resID) end) if ok and xs then return true end local tab = wardrobeTab(resID, depotData) if tab == WARDROBE_TAB_SUIT then return true end if tab == WARDROBE_TAB_CLOTHES then return false end for _, id in ipairs(ITEMS) do if tonumber(id) == resID and subType(cfg(resID)) == ST_TOP then return true end end return false end -- 获取服装分类:全套/上衣/裤子等 local function getClothKind(resID, depotData) resID = tonumber(resID) if not resID then return nil end local st = subType(cfg(resID)) if st == ST_TOP then return isFullSuitRes(resID, depotData) and "full_suit" or "top" elseif st == ST_PANTS then return "pants" elseif st == ST_SHOES then return "shoes" elseif st == ST_UNDER_T then return "under_top" elseif st == ST_UNDER_P then return "under_pants" end return nil end -- 获取穿戴对应需要清空的部位 local function subTypesToClearForKind(kind) if kind == "full_suit" then return FULL_SUIT_CLEAR_ST end if kind == "top" then return { [ST_TOP] = true } end if kind == "pants" then return { [ST_PANTS] = true } end if kind == "shoes" then return { [ST_SHOES] = true } end if kind == "under_top" then return { [ST_UNDER_T] = true } end if kind == "under_pants" then return { [ST_UNDER_P] = true } end return nil end -- 判断是否身体穿戴类子类型 local function isBodyClothSubType(st) st = tonumber(st) return st == ST_TOP or st == ST_PANTS or st == ST_SHOES or st == ST_UNDER_T or st == ST_UNDER_P end -- 通过皮肤ID获取对应武器ID local function weaponIdFromSkin(resID) local mapping = CDataTable.GetTableData("WeaponSkinMapping", resID) if not mapping then return nil end return mapping.WeaponID or mapping.WeaponId end -- 校验是否注入实例/资源 local function isInjectedIns(ins) return ins and R.insToRes[tonumber(ins)] ~= nil end local function isInjectedRes(res) return res and R.resToIns[tonumber(res)] ~= nil end -- 清空社交外观缓存 local function invalidateSocialWearCache() local s = _G.AddOutfitSocialState if s then s.wearPatchKey, s.snapshotKey, s.fullSnapshot, s.lastHandSkin = nil, nil, nil, nil end end -- 保存枪械皮肤到全局缓存 local function saveWeaponToCache(weaponID, resID, insID) weaponID, resID, insID = tonumber(weaponID), tonumber(resID), tonumber(insID) if not weaponID or not resID or resID <= 0 then return end local cch = cache() cch.weapons[weaponID] = { resID = resID, insID = insID or 0 } _weaponSkinCache[weaponID] = { resID = resID, insID = insID or 0 } _G.AddOutfitLastAppliedSkin = {} _matchApplied = false invalidateSocialWearCache() end -- 通过实例ID缓存枪械皮肤 local function cacheWeaponSkinFromIns(weaponID, insID) weaponID, insID = tonumber(weaponID), tonumber(insID) if not weaponID or not insID or insID <= 0 then return end if isInjectedIns(insID) then saveWeaponToCache(weaponID, R.insToRes[insID], insID) return end pcall(function() local wd = require("client.slua.logic.wardrobe.wardrobe_data") local d = wd:GetValidHallDepotItemDataByInsID(insID) or wd:GetHallDepotItemDataByInsID(insID) if d and tonumber(d.resID) > 0 then saveWeaponToCache(weaponID, tonumber(d.resID), insID) end end) end -- 保存穿戴服装/武器缓存 local function saveEquip(resID, insID) resID, insID = tonumber(resID), tonumber(insID) if not resID or not insID then return end local c = cfg(resID) local st = subType(c) local cch = cache() local kind = getClothKind(resID, nil) if kind == "full_suit" then cch.outfitRes, cch.outfitIns = resID, insID _G.AddOutfitLastLobbyOutfitRes = resID invalidateSocialWearCache() elseif kind == "top" and cch.outfitRes and isFullSuitRes(cch.outfitRes) then cch.outfitRes, cch.outfitIns = nil, nil invalidateSocialWearCache() elseif GUN[st] then local wid = weaponIdFromSkin(resID) if wid then saveWeaponToCache(wid, resID, insID) end elseif st == MELEE_ID then saveWeaponToCache(MELEE_ID, resID, insID) end _matchApplied = false end -- 同步大厅、军备、背包所有枪械皮肤缓存 local function syncWeaponCacheFromLobby() local cch = cache() -- 时尚背包同步 pcall(function() local fbd = require("client.slua.logic.wardrobe.fashionbag.fashionbag_data") local bag = fbd.GetCurrentFashionBag and fbd:GetCurrentFashionBag() if bag and bag.weapon_skin_list then for wid, entry in pairs(bag.weapon_skin_list) do local ins = tonumber(entry.skin_id or entry.skinId) or 0 if ins > 0 then if isInjectedIns(ins) then cch.weapons[wid] = { resID = R.insToRes[ins], insID = ins } else local wd = require("client.slua.logic.wardrobe.wardrobe_data") local d = wd:GetValidHallDepotItemDataByInsID(ins) if d then cch.weapons[wid] = { resID = tonumber(d.resID), insID = ins } end end end end end end) -- 军备库同步 pcall(function() local arm = require("client.logic.armory.logic_armory") if arm.rsp_list and arm.rsp_list.install_list then for wid, entry in pairs(arm.rsp_list.install_list) do local ins = tonumber(entry.skin_id) or 0 if ins > 0 then if isInjectedIns(ins) then cch.weapons[wid] = { resID = R.insToRes[ins], insID = ins } else local wd = require("client.slua.logic.wardrobe.wardrobe_data") local d = wd:GetValidHallDepotItemDataByInsID(ins) if d then cch.weapons[wid] = { resID = tonumber(d.resID), insID = ins } end end end end end end) end -- 获取缓存武器皮肤 local function getCachedWeaponSkin(weaponID) weaponID = tonumber(weaponID) or 0 if weaponID <= 0 then return nil end syncWeaponCacheFromLobby() local w = cache().weapons[weaponID] if w and w.resID and w.resID > 0 then return w.resID end return nil end -- 对局备用皮肤读取 local function getMatchWeaponSkin(weaponID) local cacheSkin = getCachedWeaponSkin(weaponID) if cacheSkin then return cacheSkin end if MATCH_CONFIG.weaponSkins[weaponID] then local fixed = tonumber(MATCH_CONFIG.weaponSkins[weaponID]) if fixed > 0 then return fixed end end return nil end -- 根据子类型查找当前穿戴实例 local function findWornInsBySubType(st) st = tonumber(st) if not st then return nil end local wd = require("client.slua.logic.wardrobe.wardrobe_data") local avatarData = require("client.logic.data.AvatarData") for _, ins in pairs(avatarData.GetRoleWear()) do ins = tonumber(ins) if ins > 0 then local d = wd:GetHallDepotItemDataByInsID(ins) if d and tonumber(d.itemSubType) == st then return ins, tonumber(d.resID) end end end return nil end -- 批量移除指定部位穿戴 local function removeRoleWearBySubTypes(stMap) if not stMap then return end local wd = require("client.slua.logic.wardrobe.wardrobe_data") local avatarData = require("client.logic.data.AvatarData") for _, ins in pairs(avatarData.GetRoleWear()) do ins = tonumber(ins) if ins > 0 then local d = wd:GetHallDepotItemDataByInsID(ins) if d and stMap[tonumber(d.itemSubType)] then avatarData.RemoveRoleWearDataByValue(ins) end end end end -- 清空时尚背包对应穿戴槽位 local function clearFashionBagSlots(stMap) pcall(function() local fbd = require("client.slua.logic.wardrobe.fashionbag.fashionbag_data") local wfu = require("client.slua.logic.wardrobe.fashionbag.wardrobe_fashion_utils") local bag = fbd.GetCurrentFashionBag and fbd:GetCurrentFashionBag() if not bag or not bag.rolewear_list then return end for st in pairs(stMap) do local idx = wfu.GetRoleWearIndexBySubType(st) if idx then bag.rolewear_list[idx] = 0 end end end) end -- 同步穿戴数据到时尚背包 local function syncFashionBagRolewear() pcall(function() local fbd = require("client.slua.logic.wardrobe.fashionbag.fashionbag_data") fbd:SaveRolewearToFashionBag(fbd:GetFashionBagUseIndex()) end) end -- 延迟工具函数 local _ticker pcall(function() _ticker = require("common.time_ticker") end) local function later(sec, fn) if _G.SetTimer then pcall(_G.SetTimer, sec, fn) elseif _ticker and _ticker.AddTimer then pcall(_ticker.AddTimer, sec) end end -- 获取仓库数据容器 local function getEntity() local ok, dc = pcall(require, "client.slua.logic.wardrobe.logic_wardrobe_data_center") if not ok then return nil end local ok2, e = pcall(dc.GetWardrobeData) return ok2 and e or nil end -- 判断仓库是否已有该道具 local function alreadyHave(entity, resID) if not entity or not entity.ResIDToIndexArrayMap then return false end local arr = entity.ResIDToIndexArrayMap[resID] if not arr then return false end for _, idx in pairs(arr) do local d = entity._data[idx] if d and d.count > 0 then return true end end return false end -- 单个道具注入仓库 local function injectOne(entity, resID, insID) if alreadyHave(entity, resID) then R.resToIns[resID] = insID R.insToRes[insID] = resID return true end local row = { instid = insID, res_id = resID, count = 1, lock_cnt = 0, isnew = 0, valid_hours = 0, expire_ts = 0 } entity:AddData(row) pcall(function() local data = entity.GetDataByInsID(insID) if data and entity.LoadConfigForData then entity:LoadConfigForData(data, CDataTable.GetTableData) end end) R.insToRes[insID] = resID R.resToIns[resID] = insID return true end -- 注入枪械到军备库 local function injectArmory(resID, insID) local wid = weaponIdFromSkin(resID) if not wid then return end local arm = require("client.logic.armory.logic_armory") arm.rsp_list = arm.rsp_list or { skin_list = {}, install_list = {} } arm.rsp_list.skin_list[wid] = arm.rsp_list.skin_list[wid] or {} arm.rsp_list.skin_list[wid][resID] = { is_open = 1 } arm.WardrobeInsList = arm.WardrobeInsList or {} arm.WardrobeInsList[resID] = insID end -- 批量注入全部ITEMS道具 local function injectAll(entity) entity = entity or getEntity() if not entity or not entity.bInit then return false end local successNum = 0 for i, resID in ipairs(ITEMS) do local insID = INS_BASE + i if injectOne(entity, resID, insID) then successNum = successNum + 1 local c = cfg(resID) local st = subType(c) if GUN_SUB[st] or st == MELEE_ID then injectArmory(resID, insID) end end end return successNum > 0 end -- 刷新仓库UI事件 local function refreshWardrobe() pcall(function() if not EventSystem then return end local events = { EVENTTYPE_WARDROBE, EVENTID_WARDROBE_UPDATE_ITEM_LIST, EVENTID_WARDROBE_UPDATE_AVATAR_LIST, EVENTID_WARDROBE_UPDATE_GUN_LIST } EventSystem:postEvent(events[1], events[2]) EventSystem:postEvent(events[1], events[3]) EventSystem:postEvent(events[1], events[4], -1) end) end -- 穿戴单件服装/套装 local function putOnCloth(insID) insID = tonumber(insID) local resID = R.insToRes[insID] if not resID then return end local wd = require("client.slua.logic.wardrobe.wardrobe_data") local d = wd:GetHallDepotItemDataByInsID(insID) if not d then return end local kind = getClothKind(resID, d) if not kind then return end local clearMap = subTypesToClearForKind(kind) local itemSt = subType(cfg(resID)) local oldIns, oldRes = findWornInsBySubType(itemSt) removeRoleWearBySubTypes(clearMap) clearFashionBagSlots(clearMap) saveEquip(resID, insID) -- 协议与形象更新 local WRH = require("client.network.Protocol.WardRobeHandler") local item = { res_id = resID, count = 1, instid = insID } local olditem = oldIns and { res_id = oldRes, count = 1, instid = oldIns } or nil WRH.on_depot_put_on_rsp(NET_OK, item, olditem, PKG_SLOT, insID, oldIns or 0) pcall(function() local av = require("client.slua.logic.wardrobe.logic_wardrobe_avatar") av:AddToWearInfo(itemSt, insID, resID, 0) local LogicXSuit = require("client.slua.logic.XSuit.logic_xsuit") local showId = LogicXSuit.IsXSuit(resID) and LogicXSuit.GetItemShowID(insID) or resID av:AvatarChange(showId, true, 0, 0) av:ProcessTakeOff() syncFashionBagRolewear() end) end local function putOnOutfit(insID) putOnCloth(insID) end -- 装备枪械皮肤 local function equipWeaponSkin(weaponID, insID) weaponID, insID = tonumber(weaponID), tonumber(insID) if not weaponID or not insID or not isInjectedIns(insID) then return end local resID = R.insToRes[insID] saveEquip(resID, insID) injectArmory(resID, insID) local arm = require("client.logic.armory.logic_armory") arm.rsp_list.install_list[weaponID] = { skin_id = insID } pcall(function() local fbd = require("client.slua.logic.wardrobe.fashionbag.fashionbag_data") fbd:UpdateCurrentFashionBagWeaponSkin(weaponID, insID) local wgl = require("client.slua.logic.wardrobe.logic_wardrobe_gun") wgl:SetGunID(weaponID) wgl:UpdateCurrentGunAvatar(weaponID, insID) -- 发送装备事件 if EventSystem then EventSystem:postEvent(EVENTTYPE_ARMORY, EVENTID_ARMORY_EQUIP_STAT_CHANGE, resID) EventSystem:postEvent(EVENTTYPE_WARDROBE, EVENTID_WARDROBE_UPDATE_CURRENT_PUT_ON_GUN, resID) end end) end -- 社交外观防抖容器 local SOCIAL = _G.AddOutfitSocialState or {} _G.AddOutfitSocialState = SOCIAL SOCIAL.debGen = SOCIAL.debGen or 0 SOCIAL.wearPatchKey = nil SOCIAL.snapshotKey = nil SOCIAL.fullSnapshot = nil -- 防抖延迟执行 local function socialDebounce(sec, fn) SOCIAL.debGen = SOCIAL.debGen + 1 local gen = SOCIAL.debGen later(sec, function() if gen ~= SOCIAL.debGen then return end pcall(fn) end) end -- 读取大厅生效枪械皮肤 local function resolveLobbyWeaponSkinRes() if not _G.LobbyCosmeticEnabled then return nil end local cch = cache() local wid = tonumber(DataMgr.Weapon_ID) or 0 local quickSkin = nil for _, v in pairs(cch.weapons) do if v.resID > 0 then quickSkin = v.resID; break end end if quickSkin then return quick end if wid > 0 then local matchSkin = getMatchWeaponSkin(wid) if matchSkin then return matchSkin end end return nil end -- 读取大厅生效套装 local function resolveLobbyOutfitRes() if not _G.LobbyCosmeticEnabled then return nil end local cch = cache() if cch.outfitRes and cch.outfitRes > 0 then return cch.outfitRes end local lastSet = tonumber(_G.AddOutfitLastLobbyOutfitRes) if lastSet and lastSet > 0 then return lastSet end if MATCH_CONFIG.outfitRes and MATCH_CONFIG.outfitRes > 0 then return MATCH_CONFIG.outfitRes end return nil end -- 生成穿戴唯一标识(用于防抖对比) local function wearPatchKey() local outfit = resolveLobbyOutfitRes() or 0 local skin = resolveLobbyWeaponSkinRes() or 0 local openGun = 1 pcall(function() local lds = require("client.slua.logic.wardrobe.logic_display_setting") if lds.data then openGun = lds.data.OpenGun and 1 or 0 end end) return string.format("%d_%d_%d", outfit, skin, openGun) end -- 修补大厅角色展示数据,注入套装/皮肤 local function applyInjectedPspace(roleData) if not _G.LobbyCosmeticEnabled or not roleData then return end roleData.bshow = true roleData.pspace_wear_ext = roleData.pspace_wear_ext or {} local outfitRes = resolveLobbyOutfitRes() if outfitRes and outfitRes > 0 then roleData.pspace_wear_ext[ENUM_AVATAR_SHOW_TYPE.SHOW_POS_CLOTH] = { outfitRes, 0, 0 } end local skinRes = resolveLobbyWeaponSkinRes() if skinRes and skinRes > 0 then roleData.pspace_wear_ext[ENUM_AVATAR_SHOW_POS_WEAPONSKIN] = { skinRes, 0, 0 } roleData.depot_show_info = roleData.depot_show_info or {} roleData.depot_show_info.weapon = true end -- 同步各类展示开关 roleData.depot_show_info = { vehicle = true, helmet = true, bag = true, pet = true, idle = true, hand = true } pcall(function() local lds = require("client.slua.logic.wardrobe.logic_display_setting") if lds.data then roleData.depot_show_info.weapon = lds.data.OpenGun roleData.depot_show_info.social_weapon = lds.data.OpenSocialWeapon end end) end -- 本地穿戴缓存更新、对比快照(修复截断部分,补全闭合) local function patchSelfWearCache(force) local key = wearPatch() if not force and SOCIAL.wearPatchKey == key then return false end SOCIAL.wearPatchKey = key SOCIAL.snapshotKey = nil SOCIAL.fullSnapshot = nil local myUid = tonumber(DataMgr.roleData) if not myUid then return false end local changed = false pcall(function() local BD = ModuleManager.GetModule(ModuleManager.DataModuleConfig.BasicDataAvatarWearInfo) local cacheData = BD:GetCacheData(myUid) if not cacheData then -- 构建角色穿戴数据并写入缓存 local newRoleData = {} applyInjectedPspace(newRoleData) BD:OnHandleMsgDataAndCallback(myUid, newRoleData) changed = true return true end -- 对比新旧套装、皮肤 local oldCloth = cacheData.pspace_wear_ext and cacheData.pspace_wear_ext[ENUM_AVATAR_SHOW_TYPE.SHOW_POS_CLOTH] local oldSkin = cacheData.pspace_wear_ext and cacheData.pspace_wear_ext[ENUM_AVATAR_SHOW_TYPE.SHOW_POS_WEAPONSKIN] applyInjectedPspace(cacheData) local newCloth = cacheData.pspace_wear_ext[ENUM_AVATAR_SHOW_TYPE.SHOW_POS_CLOTH] local newSkin = cacheData.pspace_wear_ext[ENUM_AVATAR_SHOW_TYPE.SHOW_POS_WEAPONSKIN] if oldCloth ~= newCloth or oldSkin ~= newSkin then changed = true end end) return changed end -- 全局快捷开关:开启/关闭大厅自定义外观 function SetLobbyCosmeticSwitch(enable) _G.LobbyCosmeticEnabled = enable invalidateSocialWearCache() end -- 批量注入全部道具快捷入口 function LoadAllInjectItems() local entity = getEntity() local ret = injectAll(entity) refreshWardrobe() return ret end