Files
Continentis/Assets/Scripts/MainGame/Card/CardData/CardData.cs

253 lines
10 KiB
C#
Raw Normal View History

2025-10-03 00:02:43 -04:00
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using Continentis.MainGame.Character;
2025-10-23 00:49:44 -04:00
using SLSFramework.General;
2025-10-03 00:02:43 -04:00
using UnityEngine;
2025-10-23 00:49:44 -04:00
using NaughtyAttributes;
using SLSFramework.UModAssistance;
2025-10-03 00:02:43 -04:00
using UnityEngine.Serialization;
2025-10-23 00:49:44 -04:00
#if UNITY_EDITOR
using UnityEditor;
#endif
2025-10-03 00:02:43 -04:00
namespace Continentis.MainGame.Card
{
public enum CardType
{
Attack = 0,
Skill = 10,
Power = 20,
Status = 30,
Curse = 40,
Item = 50,
}
[CreateAssetMenu(menuName = "Continentis/MainGame/Card/CardData", fileName = "CardData")]
2025-10-23 00:49:44 -04:00
public partial class CardData : ScriptableObject
2025-10-03 00:02:43 -04:00
{
2025-10-23 00:49:44 -04:00
[FormerlySerializedAs("cardLogicClassName")] [Header("Fundamental")]
public string classFullName;
public string displayName;
public Rarity cardRarity;
2025-10-03 00:02:43 -04:00
public CardType cardType;
2025-10-23 00:49:44 -04:00
public List<string> tags;
2025-10-03 00:02:43 -04:00
public Sprite cardSprite;
2025-10-23 00:49:44 -04:00
public string functionText;
2025-10-03 00:02:43 -04:00
public string cardDescription;
2025-10-23 00:49:44 -04:00
[Header("Intention")]
public float baseWeight = 1f;
2025-10-03 00:02:43 -04:00
2025-10-23 00:49:44 -04:00
[Header("Attributes")]
2025-10-03 00:02:43 -04:00
[Tooltip("可变属性这个属性会自动设置BaseAttr进入Original设置AttrBaseAttrOffset=0以及DisplayAttr进入Current")]
2025-10-23 00:49:44 -04:00
public SerializableDictionary<string, float> variableAttributes = new SerializableDictionary<string, float>();
2025-10-03 00:02:43 -04:00
[Tooltip("基础属性,不会改变,通常情况下不会直接使用")]
2025-10-23 00:49:44 -04:00
public SerializableDictionary<string, float> originalAttributes = new SerializableDictionary<string, float>();
2025-10-03 00:02:43 -04:00
2025-10-23 00:49:44 -04:00
[FormerlySerializedAs("endowingCurrentAttributes")] [Tooltip("初始化时赋予给CurrentAttributes的属性第一栏是属性名第二栏是初始化时使用对应名称的OriginalAttributes的留空则默认为0如果是float数字则直接使用该数字")]
public SerializableDictionary<string, string> runtimeCurrentAttributes = new SerializableDictionary<string, string>();
2025-10-03 00:02:43 -04:00
2025-10-23 00:49:44 -04:00
[Header("Upgrade")]
2025-10-03 00:02:43 -04:00
public CardUpgradeNode upgradeNode;
2025-10-23 00:49:44 -04:00
[Header("References")]
public List<string> prefabRefs = new List<string>();
public List<string> derivativeCardDataRefs = new List<string>();
public List<string> derivativeCharacterDataRefs = new List<string>();
}
public partial class CardData
{
public string ModName => classFullName.Split('_').First();
public string ClassName => classFullName.Split('_').Last();
public bool HasTag(string tag)
{
return tags.Contains(tag);
}
public bool HasKeyword(string keyword)
{
return functionText.Contains($"$Keyword(\"{keyword}\")");
}
}
public partial class CardData
{
public static CardData Get(string dataID)
{
return ModManager.GetData<CardData>(dataID);
}
2025-10-03 00:02:43 -04:00
}
public partial class CardData
{
/// <summary>
/// 生成卡牌实例
/// </summary>
/// <param name="owner">卡牌持有者</param>
/// <param name="pileName">初始卡堆名称,默认为"Draw"</param>
/// <param name="index">插入位置默认为0</param>
2025-10-23 00:49:44 -04:00
public CardInstance GenerateCardInstance(ICardOwner owner, string pileName = "Draw", int index = -1)
2025-10-03 00:02:43 -04:00
{
CardInstance cardInstance = new CardInstance(GenerateCardLogic(), owner, pileName, index);
2025-10-23 00:49:44 -04:00
cardInstance.cardLogic.Initialize();
2025-10-03 00:02:43 -04:00
return cardInstance;
}
2025-10-23 00:49:44 -04:00
/// <summary>
/// 生成卡牌逻辑实例
/// </summary>
2025-10-03 00:02:43 -04:00
public CardLogicBase GenerateCardLogic()
{
2025-10-23 00:49:44 -04:00
Type cardLogicType = AppDomain.CurrentDomain.GetAssemblies()
.SelectMany(assembly => assembly.GetTypes())
.FirstOrDefault(t => typeof(CardLogicBase).IsAssignableFrom(t) && t.Name == this.classFullName);//TODO: 后续优化为共用字典
if(cardLogicType == null)
{
Debug.LogError($"Card class '{classFullName}' not found in assemblies.");
return null;
}
if (Activator.CreateInstance(cardLogicType) is CardLogicBase cardLogic)
2025-10-03 00:02:43 -04:00
{
cardLogic.cardData = this;
cardLogic.Setup();
return cardLogic;
}
2025-10-23 00:49:44 -04:00
Debug.LogError($"Card class '{classFullName}' not found or could not be instantiated.");
2025-10-03 00:02:43 -04:00
return null;
}
/// <summary>
2025-10-23 00:49:44 -04:00
/// 通过索引获取衍生卡牌数据
2025-10-03 00:02:43 -04:00
/// </summary>
2025-10-23 00:49:44 -04:00
public CardData GetDerivativeCardData(int index)
2025-10-03 00:02:43 -04:00
{
2025-10-23 00:49:44 -04:00
return ModManager.GetData<CardData>(derivativeCardDataRefs[index]);
}
/// <summary>
/// 通过索引获取衍生角色数据
/// </summary>
/// <param name="index"></param>
/// <returns></returns>
public CharacterData GetDerivativeCharacterData(int index)
{
return ModManager.GetData<CharacterData>(derivativeCharacterDataRefs[index]);
2025-10-03 00:02:43 -04:00
}
}
#if UNITY_EDITOR
public partial class CardData
2025-10-23 00:49:44 -04:00
{/*
2025-10-03 00:02:43 -04:00
private void SetCardIdentifier()
{
cardIdentifier = cardClass.Name;
2025-10-23 00:49:44 -04:00
int underscoreIndex = cardClass.Name.IndexOf('_');
string cardNamePart = cardClass.Name.Substring(underscoreIndex + 1);
string result = Regex.Replace(cardNamePart, "([a-z])([A-Z])", "$1 $2");
cardName = result;
2025-10-03 00:02:43 -04:00
}
private void CreateUpgradeNode()
{
upgradeNode = new CardUpgradeNode(this);
}
private IEnumerable<ValueDropdownItem<Type>> GetLogicTypes()
{
IEnumerable<Type> 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<Type>(path, type);
}
}
2025-10-23 00:49:44 -04:00
2025-10-03 00:02:43 -04:00
[FoldoutGroup("Functions")]
[Button("从所有的DefaultCollection中粘贴默认属性")]
public void PasteDefaultAttributes()
{
List<CardAttributesDefaultCollection> targetCollections = new List<CardAttributesDefaultCollection>();
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<ScriptableObject>(path);
Type assetType = collection.GetType();
string assetNamespace = assetType.Namespace;
2025-10-23 00:49:44 -04:00
// 检查目录是否有效,是否在"Assets/Mods/"下,并且是否以"/Characters/DefaultCollections"结尾
2025-10-03 00:02:43 -04:00
if (!string.IsNullOrEmpty(directory) &&
assetNamespace == typeof(CardAttributesDefaultCollection).Namespace &&
2025-10-23 00:49:44 -04:00
directory.StartsWith("Assets/Mods/") &&
2025-10-03 00:02:43 -04:00
directory.EndsWith("/Cards/DefaultCollections"))
{
// 3. 如果路径和命名空间都符合要求,则将该资产添加到目标列表中
CardAttributesDefaultCollection defaultList = collection as CardAttributesDefaultCollection;
targetCollections.Add(defaultList);
Debug.Log($"Loaded DefaultStringList from: {path}");
}
}
2025-10-23 00:49:44 -04:00
Dictionary<string, float> variableAttributes = new Dictionary<string, float>();
2025-10-03 00:02:43 -04:00
Dictionary<string, float> originalAttributes = new Dictionary<string, float>();
Dictionary<string, string> endowingCurrentAttributes = new Dictionary<string, string>();
foreach (CardAttributesDefaultCollection collection in targetCollections)
{
2025-10-23 00:49:44 -04:00
collection.variableAttributes.PasteDictionary(variableAttributes);
2025-10-03 00:02:43 -04:00
collection.originalAttributes.PasteDictionary(originalAttributes);
collection.endowingCurrentAttributes.PasteDictionary(endowingCurrentAttributes);
}
2025-10-23 00:49:44 -04:00
variableAttributes.PasteDictionary(this.variableAttributes);
2025-10-03 00:02:43 -04:00
originalAttributes.PasteDictionary(this.originalAttributes);
endowingCurrentAttributes.PasteDictionary(this.endowingCurrentAttributes);
Debug.Log($"Pasted default attributes to file {this.name}");
2025-10-23 00:49:44 -04:00
}*/
2025-10-03 00:02:43 -04:00
}
#endif
}