using System; using System.Collections.Generic; using System.Linq; using Continentis.MainGame.Character; using Continentis.MainGame.Commands; using NUnit.Framework; using SLSFramework.General; using SLSFramework.UModAssistance; using UnityEngine; namespace Continentis.MainGame.Card { #region Fundamental public partial class CardLogicBase { public List GetElementalKeywords(List overrideKeywords = null) { overrideKeywords ??= contentSubmodule.keywords; return overrideKeywords.Filtered(kw => MainGameManager.Instance.elementTags.Contains(kw)); } public bool HasKeyword(string keyword) { return contentSubmodule.keywords.Contains(keyword); } } #endregion #region Command public partial class CardLogicBase { /// /// 创建一个命令组,组内命令按顺序执行 /// /// 命令模板 protected CommandGroup SingleCommandGroup(params CommandBase[] commands) { return SingleCommandGroup(ExecutionMode.Parallel, commands); } /// /// 创建一个命令组,组内命令按指定顺序执行 /// /// 执行模式,顺序或并行 /// 命令模板 protected virtual CommandGroup SingleCommandGroup( ExecutionMode executionMode = ExecutionMode.Parallel, params CommandBase[] commands) { CommandGroup singleGroup = new CommandGroup(executionMode); foreach (CommandBase template in commands) { singleGroup.AddCommand(template.Clone()); } return singleGroup; } /// /// 对目标列表中的每个目标,依次执行一组有参函数命令,每组命令的参数为targetList中的个体,主体Group顺序执行,单体Group并行执行。 /// /// 目标列表 /// 单体命令模板 protected CommandGroup TargetListCommandGroup(List targetList, params CommandBase[] singleCommands) { return TargetListCommandGroup(targetList, ExecutionMode.Sequential, ExecutionMode.Parallel, singleCommands); } /// /// 对目标列表中的每个目标,依次执行一组有参函数命令,每组命令的参数为targetList中的个体。 /// /// 目标列表 /// 主体Group(各个目标)的执行顺序 /// 单体Group(一个目标中指令)的执行顺序 /// 单体命令模板 protected virtual CommandGroup TargetListCommandGroup( List targetList, ExecutionMode mainExecutionMode = ExecutionMode.Sequential, ExecutionMode singleExecutionMode = ExecutionMode.Parallel, params CommandBase[] singleCommands) { CommandGroup mainGroup = new CommandGroup(mainExecutionMode); foreach (CharacterBase target in targetList) { CommandGroup singleGroup = new CommandGroup(singleExecutionMode); foreach (CommandBase template in singleCommands) { CommandBase clone = template.Clone(); List allCommands = new List(); if (clone is CommandGroup group) { allCommands.AddRange(group.GetAllCommands(true)); } else { allCommands.Add(clone); } foreach (CommandBase cmd in allCommands) { cmd.selfContext.context["Target"] = target; } singleGroup.AddCommand(clone); } mainGroup.AddCommand(singleGroup); } return mainGroup; } } #endregion #region Attack public partial class CardLogicBase { /// /// 获取最终伤害 /// /// 目标 /// 元素标签,若为null则使用卡牌的元素标签 public virtual int GetFinalDamage(CharacterBase target, List elementalTags = null) { return GetFinalDamage(target, elementalTags, out _, out _, out _, out _); } protected virtual int GetFinalDamage(CharacterBase target, List elementalTags, out float baseDamageAfterOffset, out float elementalMultiplier, out float magicMultiplier, out float finalMultiplier) { elementalTags ??= GetElementalKeywords(); //----计算基础伤害增量---- int physicsOffset = 0; if (HasKeyword("Physics") || HasKeyword("Slash") || HasKeyword("Prick") || HasKeyword("Strike")) { physicsOffset = user.GetAttribute("PhysicsDamageDealtOffset"); //物理伤害基础增量 } int magicOffset = 0; if (HasKeyword("Magic") || HasKeyword("Arcane") || HasKeyword("Sorcery")) { magicOffset = user.GetAttribute("MagicDamageDealtOffset"); //魔法伤害基础增量 } //----计算伤害因数---- //计算元素伤害加成,注意,“物理Physics”也是一种元素,因此下方没有“通用物理伤害加成”的计算 elementalMultiplier = 1; foreach (string element in elementalTags) { elementalMultiplier *= user.GetRawAttribute(element + "DamageDealtMultiplier", 1) * target.GetRawAttribute(element + "DamageGainMultiplier", 1); } //计算通用的魔法伤害加成 magicMultiplier = 1; if (HasKeyword("Magic") || HasKeyword("Arcane") || HasKeyword("Sorcery")) { magicMultiplier = user.GetRawAttribute("MagicDamageDealtMultiplier", 1) * target.GetRawAttribute("MagicDamageGainMultiplier", 1); } //计算最终伤害加成 finalMultiplier = user.GetRawAttribute("FinalDamageDealtMultiplier", 1) * target.GetRawAttribute("FinalDamageGainMultiplier", 1); //----计算最终伤害---- baseDamageAfterOffset = attributeSubmodule.GetCurrentAttribute("Damage") + physicsOffset + magicOffset; float finalDamage = baseDamageAfterOffset * elementalMultiplier * magicMultiplier * finalMultiplier; return Mathf.RoundToInt(finalDamage); } } #endregion #region Attributes public partial class CardLogicBase { /// /// 设置可变属性值 /// /// 属性名,通常为 /// 是否为叠加,true为叠加,false为覆盖,true时,originalValue为外部传入值 /// 原始伤害值,仅在additive为true时有效,否则此值被覆盖为BaseAttribute /// 伤害增量 public void SetVariableAttribute(string attributeName, int baseOffset, bool additive = false, int originalValue = 0) { string baseName = "Base" + attributeName; string baseOffsetName = baseName + "Offset"; if (!additive) originalValue = GetAttribute(baseName); SetAttribute(attributeName, originalValue); SetAttribute(baseOffsetName, baseOffset); ModifyAttribute(attributeName, baseOffset); } /// /// 检查卡牌是否具有某属性 /// public bool HasAttribute(string attributeName) { return attributeSubmodule.attributeGroup.current.ContainsKey(attributeName); } /// /// 获取卡牌的属性值 /// public int GetAttribute(string attributeName, int defaultValue = 0) { return attributeSubmodule.GetRoundCurrentAttribute(attributeName, defaultValue); } public float GetRawAttribute(string attributeName, float defaultValue = 0) { return attributeSubmodule.GetCurrentAttribute(attributeName, defaultValue); } /// /// 设置卡牌的属性值 /// public void SetAttribute(string attributeName, int value) { attributeSubmodule.attributeGroup.current[attributeName] = value; } /// /// 设置卡牌的属性值 /// public void SetAttribute(string attributeName, float value) { attributeSubmodule.attributeGroup.current[attributeName] = value; } /// /// 修改卡牌的属性值 /// public void ModifyAttribute(string attributeName, int delta) { attributeSubmodule.attributeGroup.current[attributeName] += delta; } } #endregion #region Buffs public partial class CardLogicBase { /// /// 创建一个角色战斗Buff实例 /// 注意,此函数依赖ModManager的类型注册功能,请确保在Mod加载时已注册对应Buff类型 /// 此函数中的T并不是原型参数,而是获取Mod中注册的类型用的 /// public T CreateCharacterBuff(params object[] parameters) where T :CharacterCombatBuffBase { string buffTypeID = ModManager.GetTypeID(typeof(T)); if (string.IsNullOrEmpty(buffTypeID)) { Debug.LogError($"Failed to get buff name for type {typeof(T).FullName}"); return null; } return ModManager.CreateInstance(buffTypeID, parameters); } public T CreateCharacterBuff(string buffTypeID, params object[] parameters) where T :CharacterCombatBuffBase { if (string.IsNullOrEmpty(buffTypeID)) { Debug.LogError($"Failed to get buff name for type {typeof(T).FullName}"); return null; } return ModManager.CreateInstance(buffTypeID, parameters); } /// /// 创建一个卡牌战斗Buff实例 /// 注意,此函数依赖ModManager的类型注册功能,请确保在Mod加载时已注册对应Buff类型 /// 此函数中的T并不是原型参数,而是获取Mod中注册的类型用的 /// public T CreateCardBuff(params object[] parameters) where T :CardBuffBase { string buffTypeID = ModManager.GetTypeID(typeof(T)); if (string.IsNullOrEmpty(buffTypeID)) { Debug.LogError($"Failed to get buff name for type {typeof(T).FullName}"); return null; } return ModManager.CreateInstance(buffTypeID, parameters); } public T CreateCardBuff(string buffTypeID, params object[] parameters) where T :CardBuffBase { if (string.IsNullOrEmpty(buffTypeID)) { Debug.LogError($"Failed to get buff name for type {typeof(T).FullName}"); return null; } return ModManager.CreateInstance(buffTypeID, parameters); } } #endregion }