using System; using System.Collections.Generic; using System.IO; using System.Linq; using Continentis.MainGame.Character; using Sirenix.OdinInspector; using SoulliesFramework.General; using UnityEditor; using UnityEngine; using UnityEngine.Serialization; namespace Continentis.MainGame.Card { public enum CardRarity { None = 0, Common = 10, Uncommon = 20, Rare = 30, Epic = 40, Legendary = 50, Divine = 60 } public enum CardType { Attack = 0, Skill = 10, Power = 20, Status = 30, Curse = 40, Item = 50, } [CreateAssetMenu(menuName = "Continentis/MainGame/Card/CardData", fileName = "CardData")] public partial class CardData : SerializedScriptableObject { [Title("Fundamental")] [ValueDropdown("GetLogicTypes", IsUniqueList = true)] [OnValueChanged("SetCardIdentifier")] public Type cardClass; public string cardName; public string cardIdentifier; public CardRarity cardRarity; public CardType cardType; public Sprite cardSprite; [TextArea(1, 10)] public string cardDescription; [FormerlySerializedAs("tags")] public List functionalTags; public List elementalTags; public float baseWeight = 1f; [Searchable] [Title("References")] public Dictionary prefabs = new Dictionary(); [Searchable] public List derivativeCardDataList = new List(); [Title("Attributes")] [Searchable] [Tooltip("可变属性,这个属性会自动设置BaseAttr进入Original,设置Attr,BaseAttrOffset=0,以及DisplayAttr进入Current")] public Dictionary variableAttributes = new Dictionary(); [Searchable] [Tooltip("基础属性,不会改变,通常情况下不会直接使用")] public Dictionary originalAttributes = new Dictionary(); [Searchable] [Tooltip("初始化时赋予给CurrentAttributes的属性,第一栏是属性名,第二栏是初始化时使用对应名称的OriginalAttributes的,留空则默认为0,如果是float数字则直接使用该数字")] public Dictionary endowingCurrentAttributes = new Dictionary(); [Title("Upgrade")] [InlineButton("CreateUpgradeNode", "Create")] public CardUpgradeNode upgradeNode; } public partial class CardData { /// /// 生成卡牌实例 /// /// 卡牌持有者 /// 初始卡堆名称,默认为"Draw" /// 插入位置,默认为0 public CardInstance GenerateCardInstance(ICardOwner owner, string pileName = "Draw", int index = 0) { CardInstance cardInstance = new CardInstance(GenerateCardLogic(), owner, pileName, index); cardInstance.cardLogic.InitialRefresh(); return cardInstance; } public CardLogicBase GenerateCardLogic() { if (Activator.CreateInstance(cardClass) is CardLogicBase cardLogic) { cardLogic.cardData = this; cardLogic.Setup(); return cardLogic; } Debug.LogError($"Card class '{cardClass}' not found or could not be instantiated."); return null; } /// /// 通过名称获取衍生卡牌数据 /// public CardData GetDerivativeCardData(string cardName) { return derivativeCardDataList.FirstOrDefault(card => card.cardName == cardName); } } #if UNITY_EDITOR public partial class CardData { private void SetCardIdentifier() { cardIdentifier = cardClass.Name; } private void CreateUpgradeNode() { upgradeNode = new CardUpgradeNode(this); } private IEnumerable> GetLogicTypes() { IEnumerable types = AppDomain.CurrentDomain.GetAssemblies() .SelectMany(assembly => assembly.GetTypes()) .Where(t => typeof(CardLogicBase).IsAssignableFrom(t) && !t.IsAbstract && !t.IsInterface); // 我们将从命名空间中移除这个公共前缀,让路径更简洁 string commonNamespacePrefix = "Continentis.Mods"; foreach (var type in types) { string path = "Uncategorized/" + type.Name; // 默认路径 if (type.Namespace != null && type.Namespace.StartsWith(commonNamespacePrefix)) { // 1. 移除公共前缀 string formattedNamespace = type.Namespace.Substring(commonNamespacePrefix.Length); // 2. 移除特定的子命名空间部分(例如 "Cards") formattedNamespace = formattedNamespace.Replace(".Cards", ""); // 3. 将点 '.' 替换为斜杠 '/' 来创建分组 formattedNamespace = formattedNamespace.Replace('.', '/'); // 4. 组合成最终的路径 path = formattedNamespace + "/" + type.Name; } yield return new ValueDropdownItem(path, type); } } [FoldoutGroup("Functions")] [Button("从所有的DefaultCollection中粘贴默认属性")] public void PasteDefaultAttributes() { List targetCollections = new List(); string[] guids = AssetDatabase.FindAssets("t:CardAttributesDefaultCollection"); foreach (string guid in guids) { // 将GUID转换为资产的路径 string path = AssetDatabase.GUIDToAssetPath(guid); // 2. 验证每个资产的路径是否完全符合您指定的结构 // 使用 Path.GetDirectoryName 获取文件所在的目录 // 并统一使用'/'作为路径分隔符,以兼容不同操作系统 string directory = Path.GetDirectoryName(path)?.Replace('\\', '/'); Debug.Log($"Checking asset at path: {path}, directory: {directory}"); // 加载资产以检查其命名空间 ScriptableObject collection = AssetDatabase.LoadAssetAtPath(path); Type assetType = collection.GetType(); string assetNamespace = assetType.Namespace; // 检查目录是否有效,是否在"Assets/CoreMods/"下,并且是否以"/Characters/DefaultCollections"结尾 if (!string.IsNullOrEmpty(directory) && assetNamespace == typeof(CardAttributesDefaultCollection).Namespace && directory.StartsWith("Assets/CoreMods/") && directory.EndsWith("/Cards/DefaultCollections")) { // 3. 如果路径和命名空间都符合要求,则将该资产添加到目标列表中 CardAttributesDefaultCollection defaultList = collection as CardAttributesDefaultCollection; targetCollections.Add(defaultList); Debug.Log($"Loaded DefaultStringList from: {path}"); } } Dictionary originalAttributes = new Dictionary(); Dictionary endowingCurrentAttributes = new Dictionary(); foreach (CardAttributesDefaultCollection collection in targetCollections) { collection.originalAttributes.PasteDictionary(originalAttributes); collection.endowingCurrentAttributes.PasteDictionary(endowingCurrentAttributes); } originalAttributes.PasteDictionary(this.originalAttributes); endowingCurrentAttributes.PasteDictionary(this.endowingCurrentAttributes); Debug.Log($"Pasted default attributes to file {this.name}"); } [FoldoutGroup("Functions")] [Button("自动设置需要加权(名称中带有Base)的属性")] private void AutoSetUpWeightedAttributes() { List baseAttributeNames = originalAttributes .Where(attr => attr.Key.Contains("Base")) .Select(attr => attr.Key).ToList(); List attributeNames = baseAttributeNames .Select(attr => attr.Replace("Base", "")).ToList(); List baseOffsetAttributeName = baseAttributeNames .Select(attr => attr + "Offset").ToList(); List displayAttributeNames = baseAttributeNames .Select(attr => attr.Replace("Base", "Display")).ToList(); for (int index = 0; index < baseAttributeNames.Count; index++) { endowingCurrentAttributes.TryAdd(attributeNames[index], baseAttributeNames[index]); endowingCurrentAttributes.TryAdd(baseOffsetAttributeName[index], "0"); endowingCurrentAttributes.TryAdd(displayAttributeNames[index], baseAttributeNames[index]); } } } #endif }