Example #1
0
 //util funcs
 static float GetSpeedyPathModifier(Player player)
 {
     if (!player.IsSwiming() && !player.InInterior())
     {
         GroundType groundtype = GetGroundType(player);
         if (_speedModifiers.ContainsKey(groundtype))
         {
             _activeStatusText = _groundTypeStrings[groundtype].Value;
             return(_speedModifiers[groundtype].Value);
         }
         //fallback to biome speed
         Heightmap.Biome playerBiome = player.GetCurrentBiome();
         //Handle new biomes "gracefully"
         if (!_untamedSpeedModifiers.ContainsKey(playerBiome))
         {
             Logger.LogWarning($"New biome {playerBiome.ToString()}. Unsure how to Handle. Falling back to None.");
             playerBiome = Heightmap.Biome.None;
         }
         _activeStatusText = "$biome_" + playerBiome.ToString().ToLower();
         if (_biomeTypeStrings.ContainsKey(playerBiome) && _biomeTypeStrings[playerBiome].Value != "default")
         {
             _activeStatusText = _biomeTypeStrings[playerBiome].Value;
         }
         return(_untamedSpeedModifiers[playerBiome].Value);
     }
     return(1.0f);
 }
Example #2
0
        private static void ModifyPresetScenePreview(ConCommandArgs args)
        {
            var value   = args.GetArgInt(0);
            var pathSet = GetPathSet(UnityEngine.SceneManagement.SceneManager.GetActiveScene().name);

            if (pathSet == null)
            {
                _logger.LogWarning($"Could not find chosen pathSet for current scene ({UnityEngine.SceneManagement.SceneManager.GetActiveScene().name})!");
                return;
            }
            PatchScene(pathSet, value);
        }
Example #3
0
        internal void Awake()
        {
            this.FPSBoost();

            try
            {
                if (FindObjectsOfType <ModEntryPoint>().Length > 1)
                {
                    Logger.LogWarning(string.Format("Another instance of {0} was instantiated. Will destroy this: {1}",
                                                    typeof(ModEntryPoint),
                                                    gameObject.GetInstanceID()
                                                    ));
                    DestroyImmediate(this);
                }
                else
                {
                    new Harmony(MOD_GUID).PatchAll(System.Reflection.Assembly.GetExecutingAssembly());
                    Logger.LogInfo("Successfully patched via Harmony.");
                }
            }
            catch (Exception arg)
            {
                Logger.LogError(string.Format("Failed to patch via Harmony. Error: {0}", arg));
            }
        }
 private static void RequestConfigFromServer()
 {
     if (!ZNet.IsServer() && ZNet.GetConnectionStatus() == ZNet.ConnectionStatus.Connected)
     {
         long?serverPeerID = AccessTools.Method(typeof(ZRoutedRpc), "GetServerPeerID").Invoke(ZRoutedRpc.instance, null) as long?;
         ZRoutedRpc.instance.InvokeRoutedRPC((long)serverPeerID, Config.RPC_SYNC_GUID, new object[] { new ZPackage() });
         Logger.LogInfo($"Authoritative Config Registered -> {Config.RPC_SYNC_GUID}");
         Debug.Log(Config.Instance._mod.Info.Metadata.Name + ": Authoritative Config Requested -> " + Config.RPC_SYNC_GUID);
     }
     else if (!ZNet.IsServer())
     {
         Logger.LogWarning($"Failed to Request Configs. Bad Peer? Too Early?");
     }
 }
Example #5
0
        private void FunnyLanguage()
        {
            PhysicalFileSystem physicalFileSystem = new PhysicalFileSystem();

            Main.fileSystem = new SubFileSystem(physicalFileSystem, physicalFileSystem.ConvertPathFromInternal(Assets.assemblyDir), true);
            if (fileSystem.DirectoryExists("/language/")) //Uh, it exists and we make sure to not shit up R2Api
            {
                RoR2.Language.collectLanguageRootFolders += delegate(List <DirectoryEntry> list)
                {
                    list.Add(fileSystem.GetDirectoryEntry("/language/"));
                };
            }
            else
            {
                _logger.LogWarning("Language directory is missing!");
            }
        }
        static TranslationHelper()
        {
            var xua = Type.GetType("XUnity.AutoTranslator.Plugin.Core.ITranslator, XUnity.AutoTranslator.Plugin.Core", false);

            if (xua != null && xua.GetMethods().Any(x => x.Name == "TranslateAsync"))
            {
                _translatorCallback = (s, action) =>
                {
                    // The lambda doesn't get its types resolved until it's called so this doesn't crash here if the type doesn't exist
                    AutoTranslator.Default.TranslateAsync(s, result => { if (result.Succeeded)
                                                                         {
                                                                             action(result.TranslatedText);
                                                                         }
                                                          });
                };
            }
            else
            {
                var logger = new BepInEx.Logging.ManualLogSource("MakerSearch");
                logger.LogWarning("Could not find method AutoTranslator.Default.TranslateAsync, item translations will be limited or unavailable");
                _translatorCallback = null;
            }
        }
Example #7
0
        public static void Debug(object obj, int level, int line, string caller, string path)
        {
            var msg = $"{DateTime.Now.ToString("yyyy/MM/dd HH:mm:ss")} {path.Split('\\').Last()} {caller}:{line} {obj}";

            switch (level)
            {
            case 0:
                log.LogMessage(msg);
                break;

            case 1:
                log.LogWarning(msg);
                break;

            case 2:
                log.LogError(msg);
                break;

            default:
                log.LogFatal(msg);
                break;
            }
        }
Example #8
0
 public static ILCursor LogFull(this ILCursor cursor, BepInEx.Logging.ManualLogSource logger)
 {
     logger.LogWarning(cursor.Context);
     return(cursor);
 }
Example #9
0
        public static void CopyCurrentCharaOverlayByController(ChaControl sourceChaCtrl, ChaControl targetChaCtrl, bool[] isChecked)
        {
            MonoBehaviour sourceController = sourceChaCtrl.GetComponents <MonoBehaviour>().FirstOrDefault(x => Equals(x.GetType().Name, "CharaOverlaysBasedOnCoordinateController"));
            MonoBehaviour targetController = targetChaCtrl.GetComponents <MonoBehaviour>().FirstOrDefault(x => Equals(x.GetType().Name, "CharaOverlaysBasedOnCoordinateController"));

            object sourceOverlays = sourceController.GetProperty("CurrentOverlay").ToDictionaryWithoutType();
            object targetOverlays = targetController.GetProperty("CurrentOverlay").ToDictionaryWithoutType();

            object result = sourceOverlays.ToDictionaryWithoutType();   //Clone it to use the structure

            result.RemoveAll(x => true);

            _ = sourceOverlays.ForEach((x) => {
                DictionaryEntry d = (DictionaryEntry)x;
                int checkCase     = -1;
                switch (Convert.ToInt32(d.Key))
                {
                case 1:
                case 3:
                    checkCase = 2;
                    break;

                case 2:
                case 4:
                    checkCase = 1;
                    break;

                case 5:
                case 6:
                    checkCase = 0;
                    break;

                case 0:
                    break;

                default:
                    Logger.LogWarning("Cast failed while reading overlays from KK_COBOC!");
                    break;
                }
                if (checkCase >= 0 && checkCase < isChecked.Length)
                {
                    if (isChecked[checkCase])
                    {
                        result.Add(d.Key, ((byte[])d.Value).Clone());
                    }
                    else if (targetOverlays.TryGetValue(d.Key, out object val))
                    {
                        result.Add(d.Key, ((byte[])val).Clone());
                    }
                    else
                    {
                        result.Add(d.Key, new byte[] { });
                    }
                }
            });

            if (targetController.SetProperty("CurrentOverlay", result))
            {
                //單眼
                if (isChecked[0])
                {
                    int[] sourceIris = (int[])sourceController.GetField("IrisDisplaySide");
                    int[] targetIris = (int[])targetController.GetField("IrisDisplaySide");
                    int   sourceType = sourceChaCtrl.fileStatus.coordinateType;
                    int   targetType = targetChaCtrl.fileStatus.coordinateType;
                    if (sourceIris.Length > sourceType && targetIris.Length > targetType)
                    {
                        targetIris[targetType] = sourceIris[sourceType];
                    }
                    targetController.SetField("IrisDisplaySide", targetIris);
                }
                targetController.Invoke("OverwriteOverlay");
                Logger.LogDebug($"Copy Current CharaOverlay {sourceChaCtrl.fileParam.fullname} -> {targetChaCtrl.fileParam.fullname}: {isChecked[0]} {isChecked[1]} {isChecked[2]}");
            }
        }
Example #10
0
        public void Awake()
        {
            ModLogger = this.Logger;

            using (var stream = Assembly.GetExecutingAssembly().GetManifestResourceStream("Tempest.tempest_assets"))
            {
                MainAssets = AssetBundle.LoadFromStream(stream);
            }

            //ModLogger.LogInfo("----------------------ASSETS--------------------");
            //foreach (var asset in MainAssets.GetAllAssetNames())
            //{
            //    ModLogger.LogMessage(asset);
            //}

            if (Helpers.InDebugMode())
            {
                ModLogger.LogWarning("Tempest has been compiled in debug mode!");
            }

            ModLogger.LogInfo("----------------------SYSTEMS--------------------");
            var SystemTypes = Assembly.GetExecutingAssembly().GetTypes().Where(type => !type.IsAbstract && type.IsSubclassOf(typeof(BaseSystem)));

            foreach (var systemType in SystemTypes)
            {
                BaseSystem system = (BaseSystem)System.Activator.CreateInstance(systemType);

                if (!Helpers.InDebugMode() && system.StripFromRelease)
                {
                    ModLogger.LogWarning("System: " + systemType.Name + " stripped from release!");
                    continue;
                }

                system.Init(this);
                ModLogger.LogInfo("System: " + systemType.Name + " initialized!");
            }

            ModLogger.LogInfo("----------------------ITEMS--------------------");
            var ItemTypes = Assembly.GetExecutingAssembly().GetTypes().Where(type => !type.IsAbstract && type.IsSubclassOf(typeof(BaseItem)));

            foreach (var itemType in ItemTypes)
            {
                BaseItem item = (BaseItem)System.Activator.CreateInstance(itemType);
                if (ValidateItem(item, Items))
                {
                    item.Init(Config);
                    CustomItems.Add(item.ItemDef.name, item.ItemDef);
                    ModLogger.LogInfo("Item: " + item.ItemName + " initialized!");
                }
                else
                {
                    ModLogger.LogWarning("Item: " + item.ItemName + " disabled!");
                }
            }

            ModLogger.LogInfo("----------------------EQUIPMENT--------------------");
            var EquipmetTypes = Assembly.GetExecutingAssembly().GetTypes().Where(type => !type.IsAbstract && type.IsSubclassOf(typeof(BaseEquipment)));

            foreach (var EquipmetType in EquipmetTypes)
            {
                BaseEquipment equipment = (BaseEquipment)System.Activator.CreateInstance(EquipmetType);
                equipment.Init(Config);

                ModLogger.LogInfo("Equpment: " + equipment.EquipmentName + " initialized!");
            }

            ModLogger.LogInfo("----------------------TEMPEST DONE--------------------");
        }
Example #11
0
        public static void Modify()
        {
            foreach (var body in BodyCatalog.allBodyPrefabs.ToList())
            {
                if (!body)
                {
                    continue;
                }
                if (bannedBodyNames.Contains(body.name))
                {
                    _logger.LogWarning($"Skipping {body.name}!");
                    continue;
                }

                _logger.LogMessage($"Working on {body.name}");
                var skillLocator = body.GetComponent <SkillLocator>();
                if (!skillLocator)
                {
                    _logger.LogError("No SkillLocator, continuing.");
                    continue;
                }

                var esmList = body.GetComponents <EntityStateMachine>().ToList();
                if (esmList.Count <= 0)
                {
                    _logger.LogWarning("No Entity State Machines, continuing.");
                    continue;
                }

                foreach (var entityStateMachines in body.GetComponents <EntityStateMachine>().ToList())
                {
                    if (entityStateMachines.customName == "Body")
                    {
                        continue;
                    }
                    Destroy(entityStateMachines);
                }
                var primaryState   = CreateEntityStateMachine(body, primaryName);
                var secondaryState = CreateEntityStateMachine(body, secondaryName);
                var utilityState   = CreateEntityStateMachine(body, utilityName);
                var specialState   = CreateEntityStateMachine(body, specialName);

                var networkStateMachine = body.GetComponent <NetworkStateMachine>();
                if (networkStateMachine)
                {
                    networkStateMachine.stateMachines = new EntityStateMachine[]
                    {
                        primaryState,
                        secondaryState,
                        utilityState,
                        specialState
                    };
                }

                if (skillLocator.primary)
                {
                    //skillLocator.primary.skillDef.activationStateMachineName = primaryState.customName;
                    foreach (var variant in skillLocator.primary.skillFamily.variants)
                    {
                        _logger.LogMessage($"Modifying PRIMARY skillDef {variant.skillDef.skillNameToken}");
                        variant.skillDef.activationStateMachineName = primaryState.customName;
                    }
                }
                if (skillLocator.secondary)
                {
                    //skillLocator.secondary.skillDef.activationStateMachineName = primaryState.customName;
                    foreach (var variant in skillLocator.secondary.skillFamily.variants)
                    {
                        _logger.LogMessage($"Modifying SECONDARY skillDef {variant.skillDef.skillNameToken}");
                        variant.skillDef.activationStateMachineName = primaryState.customName;
                    }
                }
                if (skillLocator.utility)
                {
                    //skillLocator.utility.skillDef.activationStateMachineName = primaryState.customName;
                    foreach (var variant in skillLocator.utility.skillFamily.variants)
                    {
                        _logger.LogMessage($"Modifying UTILITY skillDef {variant.skillDef.skillNameToken}");
                        variant.skillDef.activationStateMachineName = primaryState.customName;
                    }
                }
                if (skillLocator.special)
                {
                    //skillLocator.special.skillDef.activationStateMachineName = primaryState.customName;
                    foreach (var variant in skillLocator.special.skillFamily.variants)
                    {
                        _logger.LogMessage($"Modifying SPECIAL skillDef {variant.skillDef.skillNameToken}");
                        variant.skillDef.activationStateMachineName = primaryState.customName;
                    }
                }
            }
        }
        private static void Initialize()
        {
            #region [AssetBundle Loading - Put the AssetBundles folder in the Game root folder!]

            if (testAssetBundle == null)
            {
                if (File.Exists(AppDomain.CurrentDomain.BaseDirectory + "\\AssetBundles\\testassetbundle"))
                {
                    log.LogMessage(" ");
                    log.LogMessage("Trying to Load AssetBundle...");
                    testAssetBundle = Il2CppAssetBundleManager.LoadFromFile(AppDomain.CurrentDomain.BaseDirectory + "\\AssetBundles\\testassetbundle");
                    if (testAssetBundle == null)
                    {
                        log.LogMessage("AssetBundle Failed to Load!"); return;
                    }

                    #region [Print out asset names/paths]

                    log.LogMessage("Assets:");
                    foreach (var asset in testAssetBundle.AllAssetNames())
                    {
                        log.LogMessage("   Asset Name: " + asset.ToString());
                    }

                    #endregion

                    #region [Test Loading a prefab and instantiating it]

                    /*
                     *
                     * // NOTE: There's currently a error in Unhollower that throws a NullReference exception, but the object and components DO get instantiated
                     * // but the prefab doesn't display. It and it's components are running though.
                     *
                     * log.LogMessage("Trying to Load Prefab...");
                     *
                     * var prefab = testAssetBundle.LoadAsset<GameObject>("SOME PREFAB ASSET");
                     * if (prefab != null)
                     * {
                     *  log.LogMessage("Asset Loaded!");
                     *
                     *  // Instantiate the object
                     *  log.LogMessage("Trying to Instantiate Prefab...");
                     *  var t = Instantiate(prefab, new Vector3(0f, 0f), Quaternion.identity);
                     *  if (t != null) { log.LogMessage("Prefab Instantiated! Position: " + t.transform.position.ToString()); } else { log.LogMessage("Failed to Instantiated Prefab!"); }
                     *
                     #region[Test adding a custom component and make sure it works]
                     *//*
                     *  if (t != null)
                     *  {
                     *      log.LogMessage("Test adding a custom component and make sure it works");
                     *      var type = UnhollowerRuntimeLib.Il2CppType.Of<WindowDragHandler>();
                     *      comp = t.AddComponent(type).Cast<WindowDragHandler>();
                     *      log.LogMessage("Component testBool: " + comp.testBool.ToString());
                     *  }
                     *//*
                     #endregion
                     * }
                     * else { log.LogMessage("Failed to Load Asset!"); }
                     */
                    #endregion

                    log.LogMessage("Complete!");
                }
                else
                {
                    log.LogWarning("Skipping AssetBundle Loading - testassetBundle Doesn't Exist at: " + AppDomain.CurrentDomain.BaseDirectory + "\\AssetBundles\\testassetbundle");
                    log.LogWarning("Make sure the 'AssetBundles' folder from the Git Repo exists in the Game's root folder!");
                }
            }

            #endregion

            // Create a uGUI UI
            instance.CreateUI();

            #region [Display HotKeys]

            log.LogMessage(" ");
            log.LogMessage("HotKeys:");
            log.LogMessage("   Shift+Delete = Enable/Disable Option Toggle");
            log.LogMessage("   Keypress + optionToggle = Display Mouse/World/Viewport Positions for Debugging");
            log.LogMessage("   A = Dump All Scene's Objects (w/ optionToggle True prints components also)");
            log.LogMessage("   R = Dump Current Scene's Root Objects w/ Values (w/ optionToggle True prints components also)");
            log.LogMessage("   S = Display Scene Details");
            log.LogMessage("   U = Test Creating UI Elements");
            log.LogMessage("   X = Dump Objects to XML (w/ optionToggle uses FindObjectsOfType<>() (Finds more, but loss of Hierarchy)");
            log.LogMessage("   T = Toggle GUI GameObject Tooltip w/ optionToggle (Drag mouse around while holding down mouse button)");
            log.LogMessage("   Tab = Test Unity MonoBehavior Events");
            log.LogMessage(" ");

            #endregion

            initialized = true;
        }
Example #13
0
        /// <summary>
        /// 寫入Material Editor資料
        /// </summary>
        /// <param name="sourceChaCtrl"></param>
        /// <param name="sourceSlot"></param>
        /// <param name="targetChaCtrl"></param>
        /// <param name="targetSlot"></param>
        /// <param name="gameObject">對象GameObject</param>
        /// <param name="objectType">對象分類</param>
        private static void SetMaterialEditorData(ChaControl sourceChaCtrl, int sourceSlot, ChaControl targetChaCtrl, int targetSlot, GameObject gameObject, ObjectType objectType)
        {
            if (sourceChaCtrl != MaterialEditor_Support.sourceChaCtrl || targetChaCtrl != MaterialEditor_Support.targetChaCtrl)
            {
                GetControllerAndBackupData(sourceChaCtrl, targetChaCtrl);
            }

            //是否有執行到
            bool doFlag = false;

            for (int i = 0; i < storedValueInfos.Length; i++)
            {
                bool            doFlag2     = false;
                StoredValueInfo storedValue = storedValueInfos[i];
                object          target      = TargetMaterialBackup[storedValue.listName].ToListWithoutType();

                //加入
                object objAdded = SourceMaterialBackup[storedValue.listName].ToListWithoutType().Where(x =>
                                                                                                       (int)x.GetField("ObjectType") == (int)objectType &&
                                                                                                       (int)x.GetField("CoordinateIndex") == sourceChaCtrl.fileStatus.coordinateType &&
                                                                                                       (int)x.GetField("Slot") == sourceSlot
                                                                                                       ).ForEach((x) => {
                    doFlag2    = true;
                    Renderer r = null;
                    Material m = null;

                    if (i == 1)
                    {
                        r = Extension.Extension.InvokeStatic(MaterialAPI, "GetRendererList", new object[] { gameObject })?.ToList <Renderer>().Where(y => y.name == (string)x.GetField("RendererName"))?.FirstOrDefault();
                        if (r == null)
                        {
                            Logger.LogWarning($"Missing Renderer: {(string)x.GetField("RendererName")}!");
                            doFlag2 = false;
                            return;
                        }
                    }
                    else
                    {
                        m = Extension.Extension.InvokeStatic(MaterialAPI, "GetMaterials", new object[] { gameObject, (string)x.GetField("MaterialName") })?.ToList <Material>()?.FirstOrDefault();
                        if (m == null)
                        {
                            Logger.LogWarning($"Missing Material: {(string)x.GetField("MaterialName")}!");
                            doFlag2 = false;
                            return;
                        }
                    }

                    switch (i)
                    {
                    case 0:     //MaterialShader
                        TargetMaterialEditorController.Invoke(storedValue.setFunctionName, new object[] {
                            targetSlot,
                            m,
                            x.GetField("ShaderName"),
                            gameObject,
                            true
                        });
                        if (null != x.GetField("RenderQueueOriginal"))
                        {
                            TargetMaterialEditorController.Invoke("SetMaterialShaderRenderQueue", new object[] {
                                targetSlot,
                                m,
                                x.GetField("RenderQueue"),
                                gameObject,
                                true
                            });
                        }
                        break;

                    case 1:     //RendererProperty
                        TargetMaterialEditorController.Invoke(storedValue.setFunctionName, new object[] {
                            targetSlot,
                            r,
                            x.GetField("Property"),
                            x.GetField("Value"),
                            gameObject,
                            true
                        });
                        break;

                    case 2:     //MaterialFloatProperty
                        TargetMaterialEditorController.Invoke(storedValue.setFunctionName, new object[] {
                            targetSlot,
                            m,
                            x.GetField("Property"),
                            (float)Convert.ToDouble(x.GetField("Value")),
                            gameObject,
                            true
                        });
                        break;

                    case 3:     //MaterialColorProperty
                        TargetMaterialEditorController.Invoke(storedValue.setFunctionName, new object[] {
                            targetSlot,
                            m,
                            x.GetField("Property"),
                            x.GetField("Value"),
                            gameObject,
                            true
                        });
                        break;

                    case 4:     //MaterialTextureProperty
                        //Texture
                        int?texID = (int?)x.GetField("TexID");
                        if (texID.HasValue && SourceTextureDictionaryBackup.TryGetValue(texID.Value, out object textureHolder) && textureHolder.GetProperty("Data") is byte[] BA)
                        {
                            string tempPath = Path.Combine(CacheDirectory.FullName, DateTime.UtcNow.Ticks + "_" + texID);
                            File.WriteAllBytes(tempPath, BA);
                            TargetMaterialEditorController.Invoke("SetMaterialTextureFromFile", new object[] {
                                targetSlot,
                                m,
                                x.GetField("Property"),
                                tempPath,
                                gameObject,
                                false
                            });

                            File.Delete(tempPath);

                            //Offset
                            if (null != x.GetField("OffsetOriginal"))
                            {
                                TargetMaterialEditorController.Invoke("SetMaterialTextureOffset", new object[] {
                                    targetSlot,
                                    m,
                                    x.GetField("Property"),
                                    x.GetField("Offset"),
                                    gameObject,
                                    true
                                });
                            }
                            //Scale
                            if (null != x.GetField("ScaleOriginal"))
                            {
                                TargetMaterialEditorController.Invoke("SetMaterialTextureScale", new object[] {
                                    targetSlot,
                                    m,
                                    x.GetField("Property"),
                                    x.GetField("Scale"),
                                    gameObject,
                                    true
                                });
                            }
                        }
                        break;
                    }
                });

                if (doFlag2)
                {
                    if (objAdded.Count() > 0)
                    {
                        GetExtDataFromController(targetChaCtrl, out TargetMaterialBackup, out TargetTextureDictionaryBackup);
                        Logger.LogDebug($"--->Change {objAdded.Count()} {storedValue.className}");
                    }
                }
                doFlag |= doFlag2;
            }

            if (objectType == ObjectType.Accessory)
            {
                if (doFlag)
                {
                    Logger.LogDebug($"-->Set Material Editor Data: {sourceChaCtrl.fileParam.fullname} Slot{sourceSlot} -> {targetChaCtrl.fileParam.fullname} Slot{targetSlot}");
                }
                else
                {
                    Logger.LogDebug($"-->No Material Editor Backup to set: {sourceChaCtrl.fileParam.fullname} {sourceSlot}");
                }
            }
            else if (objectType == ObjectType.Clothing)
            {
                if (doFlag)
                {
                    Logger.LogDebug($"-->Set Material Editor Data: {sourceChaCtrl.fileParam.fullname} {Enum.GetName(typeof(ChaFileDefine.ClothesKind), sourceSlot)} -> {targetChaCtrl.fileParam.fullname} {Enum.GetName(typeof(ChaFileDefine.ClothesKind), targetSlot)}");
                }
                else
                {
                    Logger.LogDebug($"-->No Material Editor Backup to set: {sourceChaCtrl.fileParam.fullname} {Enum.GetName(typeof(ChaFileDefine.ClothesKind), sourceSlot)}");
                }
            }
        }