Files
Continentis/Assets/Scripts/MainGame/Card/CardAssistanceFunctions.cs
SoulliesOfficial c3c4a17440 测试
2025-10-26 00:23:50 -04:00

284 lines
11 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
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 bool HasTag(string tag)
{
return tags.Contains(tag);
}
public List<string> GetElementTags(List<string> tags = null)
{
tags ??= this.tags;
return tags.Filtered((tag) => MainGameManager.Instance.elementTags.Contains(tag));
}
public bool HasKeyword(string keyword)
{
return contentSubmodule.keywords.Contains(keyword);
}
}
#endregion
#region Command
public partial class CardLogicBase
{
/// <summary>
/// 创建一个命令组,组内命令按顺序执行
/// </summary>
/// <param name="commands">命令模板</param>
protected CommandGroup SingleCommandGroup(params CommandBase[] commands)
{
return SingleCommandGroup(ExecutionMode.Parallel, commands);
}
/// <summary>
/// 创建一个命令组,组内命令按指定顺序执行
/// </summary>
/// <param name="executionMode">执行模式,顺序或并行</param>
/// <param name="commands">命令模板</param>
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;
}
/// <summary>
/// 对目标列表中的每个目标依次执行一组有参函数命令每组命令的参数为targetList中的个体主体Group顺序执行单体Group并行执行。
/// </summary>
/// <param name="targetList">目标列表</param>
/// <param name="singleCommands">单体命令模板</param>
protected CommandGroup TargetListCommandGroup(List<CharacterBase> targetList,
params CommandBase[] singleCommands)
{
return TargetListCommandGroup(targetList, ExecutionMode.Sequential, ExecutionMode.Parallel, singleCommands);
}
/// <summary>
/// 对目标列表中的每个目标依次执行一组有参函数命令每组命令的参数为targetList中的个体。
/// </summary>
/// <param name="targetList">目标列表</param>
/// <param name="mainExecutionMode">主体Group各个目标的执行顺序</param>
/// <param name="singleExecutionMode">单体Group一个目标中指令的执行顺序</param>
/// <param name="singleCommands">单体命令模板</param>
protected virtual CommandGroup TargetListCommandGroup(
List<CharacterBase> 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();
if (clone is CommandGroup group)
{
foreach (CommandBase cmd in group.commands)
{
cmd.selfContext.context["Target"] = target;
}
}//TODO: 变成递归
clone.selfContext.context["Target"] = target;
singleGroup.AddCommand(clone);
}
mainGroup.AddCommand(singleGroup);
}
return mainGroup;
}
}
#endregion
#region Attack
public partial class CardLogicBase
{
/// <summary>
/// 获取最终伤害
/// </summary>
/// <param name="target">目标</param>
/// <param name="elementalTags">元素标签若为null则使用卡牌的元素标签</param>
public virtual int GetFinalDamage(CharacterBase target, List<string> elementalTags = null)
{
return GetFinalDamage(target, elementalTags, out _, out _, out _, out _);
}
protected virtual int GetFinalDamage(CharacterBase target, List<string> elementalTags,
out float baseDamageAfterOffset, out float elementalMultiplier, out float magicMultiplier, out float finalMultiplier)
{
elementalTags ??= GetElementTags();
//----计算基础伤害增量----
int physicsOffset = 0;
if (HasTag("Physics") || HasKeyword("Slash") || HasKeyword("Prick") || HasKeyword("Strike"))
{
physicsOffset = user.GetAttribute("PhysicsDamageDealtOffset"); //物理伤害基础增量
}
int magicOffset = 0;
if (HasTag("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 (HasTag("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
{
/// <summary>
/// 设置可变属性值
/// </summary>
/// <param name="attributeName">属性名,通常为</param>
/// <param name="additive">是否为叠加true为叠加false为覆盖true时originalValue为外部传入值</param>
/// <param name="originalValue">原始伤害值仅在additive为true时有效否则此值被覆盖为BaseAttribute</param>
/// <param name="baseOffset">伤害增量</param>
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);
}
/// <summary>
/// 检查卡牌是否具有某属性
/// </summary>
public bool HasAttribute(string attributeName)
{
return attributeSubmodule.attributeGroup.current.ContainsKey(attributeName);
}
/// <summary>
/// 获取卡牌的属性值
/// </summary>
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);
}
/// <summary>
/// 设置卡牌的属性值
/// </summary>
public void SetAttribute(string attributeName, int value)
{
attributeSubmodule.attributeGroup.current[attributeName] = value;
}
/// <summary>
/// 设置卡牌的属性值
/// </summary>
public void SetAttribute(string attributeName, float value)
{
attributeSubmodule.attributeGroup.current[attributeName] = value;
}
/// <summary>
/// 修改卡牌的属性值
/// </summary>
public void ModifyAttribute(string attributeName, int delta)
{
attributeSubmodule.attributeGroup.current[attributeName] += delta;
}
}
#endregion
#region Buffs
public partial class CardLogicBase
{
/// <summary>
/// 创建一个角色战斗Buff实例
/// 注意此函数依赖ModManager的类型注册功能请确保在Mod加载时已注册对应Buff类型
/// 此函数中的T并不是原型参数而是获取Mod中注册的类型用的
/// </summary>
protected T CreateCharacterBuff<T>(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<T>(buffTypeID, parameters);
}
protected T CreateCharacterBuff<T>(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<T>(buffTypeID, parameters);
}
}
#endregion
}