添加打断施法;添加技能持续回合衰减;完善技能、特效类型

This commit is contained in:
milimoe 2024-09-10 21:36:08 +08:00
parent 81753d5e2f
commit 700db8e694
Signed by: milimoe
GPG Key ID: 05D280912DA6C69E
8 changed files with 578 additions and 171 deletions

View File

@ -91,6 +91,11 @@ namespace Milimoe.FunGame.Core.Api.Utility
Character character = group.First();
AddCharacter(character, Calculation.Round2Digits(_queue.Count * 0.1), false);
_assistDamage.Add(character, new AssistDetail(character, characters.Where(c => c != character)));
// 初始化技能
foreach (Skill skill in character.Skills)
{
skill.OnSkillGained(this);
}
}
else
{
@ -139,6 +144,11 @@ namespace Milimoe.FunGame.Core.Api.Utility
{
AddCharacter(selectedCharacter, Calculation.Round2Digits(_queue.Count * 0.1), false);
_assistDamage.Add(selectedCharacter, new AssistDetail(selectedCharacter, characters.Where(c => c != selectedCharacter)));
// 初始化技能
foreach (Skill skill in selectedCharacter.Skills)
{
skill.OnSkillGained(this);
}
WriteLine("decided: " + selectedCharacter.Name + "\r\n");
sortedList.Remove(selectedCharacter);
}
@ -276,16 +286,16 @@ namespace Milimoe.FunGame.Core.Api.Utility
{
if (!BeforeTurn(character))
{
return false;
return _isGameEnd;
}
foreach (Effect effect in character.Effects.Where(e => e.Level > 0))
foreach (Effect effect in character.Effects.Where(e => e.Level > 0).ToList())
{
effect.OnTurnStart(character);
}
// 假设基础硬直时间
double baseTime = new Random().Next(10, 30);
// 基础硬直时间
double baseTime = 10;
// 敌人列表
List<Character> enemys = [.. _queue.Where(c => c != character && !c.IsUnselectable)];
@ -294,8 +304,8 @@ namespace Milimoe.FunGame.Core.Api.Utility
List<Character> teammates = [];
// 技能列表
List<Skill> skills = [.. character.Skills.Where(s => s.Level > 0 && s.IsActive && s.Enable && !s.IsInEffect && s.CurrentCD == 0 &&
((s.IsSuperSkill && s.EPCost <= character.EP) || (!s.IsSuperSkill && s.IsMagic && s.MPCost <= character.MP) || (!s.IsSuperSkill && !s.IsMagic && s.EPCost <= character.EP)))];
List<Skill> skills = [.. character.Skills.Where(s => s.Level > 0 && s.SkillType != SkillType.Passive && s.Enable && !s.IsInEffect && s.CurrentCD == 0 &&
(((s.SkillType == SkillType.SuperSkill || s.SkillType == SkillType.Skill) && s.EPCost <= character.EP) || (s.SkillType == SkillType.Magic && s.MPCost <= character.MP)))];
// 作出了什么行动
CharacterActionType type = CharacterActionType.None;
@ -395,8 +405,6 @@ namespace Milimoe.FunGame.Core.Api.Utility
}
else
{
// 完全行动不能会获得10时间硬直
baseTime = 10;
WriteLine("[ " + character + $" ] 完全行动不能!");
}
@ -409,12 +417,9 @@ namespace Milimoe.FunGame.Core.Api.Utility
Character enemy = enemys[new Random().Next(enemys.Count)];
character.NormalAttack.Attack(this, character, enemy);
baseTime = character.NormalAttack.HardnessTime;
foreach (Effect effect in character.Effects.Where(e => e.Level > 0))
foreach (Effect effect in character.Effects.Where(e => e.Level > 0).ToList())
{
if (effect.AlterHardnessTimeAfterNormalAttack(character, baseTime, out double newTime))
{
baseTime = newTime;
}
effect.AlterHardnessTimeAfterNormalAttack(character, ref baseTime);
}
}
}
@ -424,12 +429,12 @@ namespace Milimoe.FunGame.Core.Api.Utility
// 注意FastAuto 模式下,此吟唱逻辑删减了选取目标的逻辑,将选取逻辑放在了实际释放的环节
// 在正常交互式模式下,吟唱前需要先选取目标
Skill skill = skills[new Random().Next(skills.Count)];
if (skill.IsMagic && !skill.IsSuperSkill)
if (skill.SkillType == SkillType.Magic)
{
character.CharacterState = CharacterState.Casting;
_castingSkills.Add(character, skill);
baseTime = skill.CastTime;
foreach (Effect effect in character.Effects.Where(e => e.Level > 0))
foreach (Effect effect in character.Effects.Where(e => e.Level > 0).ToList())
{
effect.OnSkillCasting(character);
}
@ -445,12 +450,9 @@ namespace Milimoe.FunGame.Core.Api.Utility
WriteLine("[ " + character + $" ] 消耗了 {cost:f2} 点能量,释放了{(skill.IsSuperSkill ? "" : "")} {skill.Name}");
skill.Trigger(this, character, enemys, teammates);
foreach (Effect effect in character.Effects)
foreach (Effect effect in character.Effects.Where(e => e.Level > 0).ToList())
{
if (effect.AlterHardnessTimeAfterCastSkill(character, baseTime, out double newTime))
{
baseTime = newTime;
}
effect.AlterHardnessTimeAfterCastSkill(character, ref baseTime);
}
}
}
@ -480,12 +482,9 @@ namespace Milimoe.FunGame.Core.Api.Utility
baseTime = 3;
}
foreach (Effect effect in character.Effects.Where(e => e.Level > 0))
foreach (Effect effect in character.Effects.Where(e => e.Level > 0).ToList())
{
if (effect.AlterHardnessTimeAfterCastSkill(character, baseTime, out double newTime))
{
baseTime = newTime;
}
effect.AlterHardnessTimeAfterCastSkill(character, ref baseTime);
}
}
else if (type == CharacterActionType.CastSuperSkill)
@ -513,12 +512,9 @@ namespace Milimoe.FunGame.Core.Api.Utility
baseTime = 3;
}
foreach (Effect effect in character.Effects.Where(e => e.Level > 0))
foreach (Effect effect in character.Effects.Where(e => e.Level > 0).ToList())
{
if (effect.AlterHardnessTimeAfterCastSkill(character, baseTime, out double newTime))
{
baseTime = newTime;
}
effect.AlterHardnessTimeAfterCastSkill(character, ref baseTime);
}
}
else if (type == CharacterActionType.UseItem)
@ -532,7 +528,7 @@ namespace Milimoe.FunGame.Core.Api.Utility
if (_isGameEnd)
{
return true;
return _isGameEnd;
}
// 减少硬直时间
@ -552,15 +548,34 @@ namespace Milimoe.FunGame.Core.Api.Utility
// 有人想要插队吗?
WillPreCastSuperSkill(character);
foreach (Effect effect in character.Effects.Where(e => e.Level > 0))
foreach (Effect effect in character.Effects.Where(e => e.Level > 0).ToList())
{
effect.OnTurnEnd(character);
// 自身被动不会考虑
if (effect.ControlType == EffectControlType.None && effect.Skill.SkillType == SkillType.Passive)
{
continue;
}
// 在回合结束时移除技能持续回合,而不是等时间流逝
if (!effect.Durative && effect.DurationTurn > 0)
{
// 按回合移除特效
effect.RemainDurationTurn--;
if (effect.RemainDurationTurn <= 0)
{
effect.RemainDurationTurn = 0;
character.Effects.Remove(effect);
effect.OnEffectLost(character);
}
}
}
AfterTurn(character);
WriteLine("");
return false;
return _isGameEnd;
}
/// <summary>
@ -631,13 +646,22 @@ namespace Milimoe.FunGame.Core.Api.Utility
// 移除到时间的特效
foreach (Effect effect in character.Effects.ToList())
{
if (!effect.Skill.IsActive) continue;
if (!effect.Durative || effect.Level == 0)
if (effect.Level == 0)
{
character.Effects.Remove(effect);
continue;
}
effect.OnTimeElapsed(character, timeToReduce);
// 自身被动不会考虑
if (effect.ControlType == EffectControlType.None && effect.Skill.SkillType == SkillType.Passive)
{
continue;
}
if (effect.Durative)
{
effect.RemainDuration = Calculation.Round2Digits(effect.RemainDuration - timeToReduce);
if (effect.RemainDuration <= 0)
{
@ -647,6 +671,7 @@ namespace Milimoe.FunGame.Core.Api.Utility
}
}
}
}
WriteLine("\r\n");
return timeToReduce;
@ -664,12 +689,9 @@ namespace Milimoe.FunGame.Core.Api.Utility
/// <param name="isCritical"></param>
public void DamageToEnemy(Character actor, Character enemy, double damage, bool isNormalAttack, bool isMagicDamage = false, MagicType magicType = MagicType.None, bool isCritical = false)
{
foreach (Effect effect in actor.Effects.Where(e => e.Level > 0))
foreach (Effect effect in actor.Effects.Union(enemy.Effects).Where(e => e.Level > 0).ToList())
{
if (effect.AlterActualDamageAfterCalculation(actor, enemy, damage, isNormalAttack, isMagicDamage, magicType, isCritical, out double newDamage))
{
damage = newDamage;
}
effect.AlterActualDamageAfterCalculation(actor, enemy, ref damage, isNormalAttack, isMagicDamage, magicType, isCritical);
}
if (damage < 0) damage = 0;
if (isMagicDamage)
@ -687,31 +709,25 @@ namespace Milimoe.FunGame.Core.Api.Utility
double ep = GetEP(damage, 0.2, 40);
foreach (Effect effect in actor.Effects)
{
if (effect.AlterEPAfterDamage(actor, ep, out double newep))
{
ep = newep;
}
effect.AlterEPAfterDamage(actor, ref ep);
}
actor.EP += ep;
ep = GetEP(damage, 0.1, 20);
foreach (Effect effect in enemy.Effects.Where(e => e.Level > 0))
foreach (Effect effect in enemy.Effects.Where(e => e.Level > 0).ToList())
{
if (effect.AlterEPAfterGetDamage(enemy, ep, out double newep))
{
ep = newep;
}
effect.AlterEPAfterGetDamage(enemy, ref ep);
}
enemy.EP += ep;
foreach (Effect effect in actor.Effects.Where(e => e.Level > 0))
foreach (Effect effect in actor.Effects.Union(enemy.Effects).Where(e => e.Level > 0).ToList())
{
effect.AfterDamageCalculation(actor, enemy, damage, isMagicDamage, magicType);
effect.AfterDamageCalculation(actor, enemy, damage, isNormalAttack, isMagicDamage, magicType, isCritical);
}
if (enemy.HP < 0)
{
DeathCalculation(actor, enemy);
// 给所有角色的特效广播角色死亡结算
foreach (Effect effect in _queue.SelectMany(c => c.Effects.Where(e => e.Level > 0)))
foreach (Effect effect in _queue.SelectMany(c => c.Effects.Where(e => e.Level > 0).ToList()))
{
effect.AfterDeathCalculation(enemy, actor, _continuousKilling, _earnedMoney);
}
@ -738,31 +754,28 @@ namespace Milimoe.FunGame.Core.Api.Utility
/// 计算物理伤害
/// </summary>
/// <param name="actor"></param>
/// <param name="target"></param>
/// <param name="enemy"></param>
/// <param name="isNormalAttack"></param>
/// <param name="expectedDamage"></param>
/// <param name="finalDamage"></param>
/// <returns></returns>
public DamageResult CalculatePhysicalDamage(Character actor, Character target, bool isNormalAttack, double expectedDamage, out double finalDamage)
public DamageResult CalculatePhysicalDamage(Character actor, Character enemy, bool isNormalAttack, double expectedDamage, out double finalDamage)
{
foreach (Effect effect in actor.Effects.Where(e => e.Level > 0))
foreach (Effect effect in actor.Effects.Union(enemy.Effects).Where(e => e.Level > 0).ToList())
{
if (effect.AlterExpectedDamageBeforeCalculation(actor, target, expectedDamage, isNormalAttack, false, MagicType.None, out double newDamage))
{
expectedDamage = newDamage;
}
effect.AlterExpectedDamageBeforeCalculation(actor, enemy, ref expectedDamage, isNormalAttack, false, MagicType.None);
}
double dice = new Random().NextDouble();
// 闪避判定
if (dice < target.EvadeRate)
if (dice < enemy.EvadeRate)
{
finalDamage = 0;
List<Character> characters = [actor, target];
List<Character> characters = [actor, enemy];
bool isAlterEvaded = false;
foreach (Effect effect in characters.SelectMany(c => c.Effects.Where(e => e.Level > 0)))
foreach (Effect effect in characters.SelectMany(c => c.Effects.Where(e => e.Level > 0).ToList()))
{
isAlterEvaded = effect.OnEvadedTriggered(actor, target, dice);
isAlterEvaded = effect.OnEvadedTriggered(actor, enemy, dice);
}
if (!isAlterEvaded)
{
@ -772,7 +785,7 @@ namespace Milimoe.FunGame.Core.Api.Utility
}
// 物理穿透后的护甲
double penetratedDEF = Calculation.Round2Digits((1 - actor.PhysicalPenetration) * target.DEF);
double penetratedDEF = Calculation.Round2Digits((1 - actor.PhysicalPenetration) * enemy.DEF);
// 物理伤害减免
double physicalDamageReduction = Calculation.Round4Digits(penetratedDEF / (penetratedDEF + 120));
@ -786,7 +799,7 @@ namespace Milimoe.FunGame.Core.Api.Utility
{
finalDamage = Calculation.Round2Digits(finalDamage * actor.CritDMG); // 暴击伤害倍率加成
WriteLine("暴击生效!!");
foreach (Effect effect in actor.Effects.Where(e => e.Level > 0))
foreach (Effect effect in actor.Effects.Where(e => e.Level > 0).ToList())
{
effect.OnCriticalDamageTriggered(actor, dice);
}
@ -801,33 +814,30 @@ namespace Milimoe.FunGame.Core.Api.Utility
/// 计算魔法伤害
/// </summary>
/// <param name="actor"></param>
/// <param name="target"></param>
/// <param name="enemy"></param>
/// <param name="isNormalAttack"></param>
/// <param name="magicType"></param>
/// <param name="expectedDamage"></param>
/// <param name="finalDamage"></param>
/// <returns></returns>
public DamageResult CalculateMagicalDamage(Character actor, Character target, bool isNormalAttack, MagicType magicType, double expectedDamage, out double finalDamage)
public DamageResult CalculateMagicalDamage(Character actor, Character enemy, bool isNormalAttack, MagicType magicType, double expectedDamage, out double finalDamage)
{
foreach (Effect effect in actor.Effects.Where(e => e.Level > 0))
foreach (Effect effect in actor.Effects.Union(enemy.Effects).Where(e => e.Level > 0).ToList())
{
if (effect.AlterExpectedDamageBeforeCalculation(actor, target, expectedDamage, isNormalAttack, true, magicType, out double newDamage))
{
expectedDamage = newDamage;
}
effect.AlterExpectedDamageBeforeCalculation(actor, enemy, ref expectedDamage, isNormalAttack, true, magicType);
}
MagicResistance magicResistance = magicType switch
{
MagicType.Starmark => target.MDF.Starmark,
MagicType.PurityNatural => target.MDF.PurityNatural,
MagicType.PurityContemporary => target.MDF.PurityContemporary,
MagicType.Bright => target.MDF.Bright,
MagicType.Shadow => target.MDF.Shadow,
MagicType.Element => target.MDF.Element,
MagicType.Fleabane => target.MDF.Fleabane,
MagicType.Particle => target.MDF.Particle,
_ => target.MDF.None
MagicType.Starmark => enemy.MDF.Starmark,
MagicType.PurityNatural => enemy.MDF.PurityNatural,
MagicType.PurityContemporary => enemy.MDF.PurityContemporary,
MagicType.Bright => enemy.MDF.Bright,
MagicType.Shadow => enemy.MDF.Shadow,
MagicType.Element => enemy.MDF.Element,
MagicType.Fleabane => enemy.MDF.Fleabane,
MagicType.Particle => enemy.MDF.Particle,
_ => enemy.MDF.None
};
// 魔法穿透后的魔法抗性
@ -842,7 +852,7 @@ namespace Milimoe.FunGame.Core.Api.Utility
{
finalDamage = Calculation.Round2Digits(finalDamage * actor.CritDMG); // 暴击伤害倍率加成
WriteLine("暴击生效!!");
foreach (Effect effect in actor.Effects.Where(e => e.Level > 0))
foreach (Effect effect in actor.Effects.Where(e => e.Level > 0).ToList())
{
effect.OnCriticalDamageTriggered(actor, dice);
}
@ -972,7 +982,7 @@ namespace Milimoe.FunGame.Core.Api.Utility
/// <returns></returns>
public bool CheckCanCast(Character caster, Skill skill, out double cost)
{
if (skill.IsMagic && !skill.IsSuperSkill)
if (skill.SkillType == SkillType.Magic)
{
cost = skill.MPCost;
if (cost > 0 && cost <= caster.MP)
@ -1006,14 +1016,13 @@ namespace Milimoe.FunGame.Core.Api.Utility
/// <returns></returns>
public void WillPreCastSuperSkill(Character character)
{
CharacterState[] checkStates = [CharacterState.Actionable];
// 选取在顺序表一半之后的角色
foreach (Character other in _queue.Where(c => c != character && checkStates.Contains(c.CharacterState) && _queue.IndexOf(c) >= _queue.Count / 2).ToList())
foreach (Character other in _queue.Where(c => c != character && c.CharacterState == CharacterState.Actionable && _queue.IndexOf(c) >= _queue.Count / 2).ToList())
{
// 有 65% 欲望插队
if (new Random().NextDouble() < 0.65)
{
List<Skill> skills = other.Skills.Where(s => s.IsSuperSkill && s.Level > 0 && s.IsActive && s.Enable && !s.IsInEffect && s.CurrentCD == 0 && other.EP >= s.EPCost).ToList();
List<Skill> skills = other.Skills.Where(s => s.Level > 0 && s.SkillType == SkillType.SuperSkill && s.Enable && !s.IsInEffect && s.CurrentCD == 0 && other.EP >= s.EPCost).ToList();
if (skills.Count > 0)
{
Skill skill = skills[new Random().Next(skills.Count)];
@ -1030,7 +1039,7 @@ namespace Milimoe.FunGame.Core.Api.Utility
_hardnessTimes[c] = Calculation.Round2Digits(_hardnessTimes[c] + 0.01);
}
}
foreach (Effect effect in character.Effects.Where(e => e.Level > 0))
foreach (Effect effect in character.Effects.Where(e => e.Level > 0).ToList())
{
effect.OnSkillCasting(character);
}
@ -1038,5 +1047,30 @@ namespace Milimoe.FunGame.Core.Api.Utility
}
}
}
/// <summary>
/// 打断施法
/// </summary>
/// <param name="caster"></param>
/// <param name="interrupter"></param>
public void InterruptCasting(Character caster, Character interrupter)
{
if (_castingSkills.TryGetValue(caster, out Skill? cast))
{
_castingSkills.Remove(caster);
}
else if (_castingSuperSkills.TryGetValue(caster, out cast))
{
_castingSuperSkills.Remove(caster);
}
if (cast != null)
{
WriteLine($"[ {caster} ] 的施法被 [ {interrupter} ] 打断了!!");
foreach (Effect e in cast.Effects.Where(e => e.Level > 0).ToList())
{
e.OnSkillCastInterrupted(caster, interrupter);
}
}
}
}
}

View File

@ -121,6 +121,7 @@ namespace Milimoe.FunGame.Core.Entity
set
{
_Level = Math.Min(Math.Max(1, value), 60);
OnAttributeChanged();
Recovery();
}
}
@ -135,6 +136,11 @@ namespace Milimoe.FunGame.Core.Entity
/// </summary>
public CharacterState CharacterState { get; set; } = CharacterState.Actionable;
/// <summary>
/// 角色目前被特效施加的状态
/// </summary>
public Dictionary<Effect, CharacterState> CharacterEffectStates { get; } = [];
/// <summary>
/// 角色是否是中立的/无敌的 [ 战斗相关 ]
/// </summary>
@ -739,17 +745,14 @@ namespace Milimoe.FunGame.Core.Entity
}
/// <summary>
/// 提升角色的等级
/// 角色的属性发生变化,会影响特殊效果的计算
/// </summary>
/// <param name="up">可为负数</param>
/// <returns></returns>
public int LevelUp(int up = 1)
public void OnAttributeChanged()
{
if (up != 0)
foreach (Effect effect in Effects)
{
Level += up;
effect.OnAttributeChanged(this);
}
return Level;
}
/// <summary>
@ -892,6 +895,11 @@ namespace Milimoe.FunGame.Core.Entity
return builder.ToString();
}
/// <summary>
/// 获取战斗状态的信息
/// </summary>
/// <param name="hardnessTimes"></param>
/// <returns></returns>
public string GetInBattleInfo(double hardnessTimes)
{
StringBuilder builder = new();
@ -900,6 +908,8 @@ namespace Milimoe.FunGame.Core.Entity
builder.AppendLine($"生命值:{HP} / {MaxHP}" + (ExHP + ExHP2 > 0 ? $" [{BaseHP} + {ExHP + ExHP2}]" : ""));
builder.AppendLine($"魔法值:{MP} / {MaxMP}" + (ExMP + ExMP2 > 0 ? $" [{BaseMP} + {ExMP + ExMP2}]" : ""));
builder.AppendLine($"能量值:{EP} / 200");
builder.AppendLine($"攻击力:{ATK}" + (ExATK + ExATK2 > 0 ? $" [{BaseATK} + {ExATK + ExATK2}]" : ""));
builder.AppendLine($"核心属性:{PrimaryAttributeValue}" + (ExPrimaryAttributeValue > 0 ? $" [{BasePrimaryAttributeValue} + {ExPrimaryAttributeValue}]" : ""));
if (CharacterState != CharacterState.Actionable)
{
@ -930,6 +940,66 @@ namespace Milimoe.FunGame.Core.Entity
return builder.ToString();
}
/// <summary>
/// 更新角色的状态
/// </summary>
/// <returns></returns>
public CharacterState UpdateCharacterState()
{
bool isNotActionable = false;
bool isActionRestricted = false;
bool isBattleRestricted = false;
bool isSkillRestricted = false;
foreach (CharacterState state in CharacterEffectStates.Values)
{
if (state == CharacterState.NotActionable)
{
isNotActionable = true;
}
else if (state == CharacterState.ActionRestricted)
{
isActionRestricted = true;
}
else if (state == CharacterState.BattleRestricted)
{
isBattleRestricted = true;
}
else if (state == CharacterState.SkillRestricted)
{
isSkillRestricted = true;
}
}
bool isControl = isNotActionable || isActionRestricted || isBattleRestricted || isSkillRestricted;
bool isCasting = CharacterState == CharacterState.Casting;
bool isPreCastSuperSkill = CharacterState == CharacterState.PreCastSuperSkill;
if (isNotActionable)
{
CharacterState = CharacterState.NotActionable;
}
else if (isActionRestricted)
{
CharacterState = CharacterState.ActionRestricted;
}
else if (isBattleRestricted)
{
CharacterState = CharacterState.BattleRestricted;
}
else if (isSkillRestricted)
{
CharacterState = CharacterState.SkillRestricted;
}
if (!isControl && !isCasting && !isPreCastSuperSkill)
{
CharacterState = CharacterState.Actionable;
}
return CharacterState;
}
/// <summary>
/// 复制一个角色
/// [ 推荐从模组中复制后使用对象 ]

View File

@ -15,6 +15,12 @@ namespace Milimoe.FunGame.Core.Entity
/// </summary>
public Skill Skill { get; } = skill;
/// <summary>
/// 特殊效果类型<para/>
/// 注意:如果技能特效没有原生施加控制效果,请始终保持此属性为 <see cref="EffectControlType.None"/>。
/// </summary>
public virtual EffectControlType ControlType { get; } = EffectControlType.None;
/// <summary>
/// 作用于自身
/// </summary>
@ -46,7 +52,7 @@ namespace Milimoe.FunGame.Core.Entity
/// 持续时间(回合)<para/>
/// 使用此属性需要将 <see cref="Durative"/> 设置为 false。
/// </summary>
public virtual double DurationTurn { get; } = 0;
public virtual int DurationTurn { get; } = 0;
/// <summary>
/// 剩余持续时间
@ -56,7 +62,7 @@ namespace Milimoe.FunGame.Core.Entity
/// <summary>
/// 剩余持续时间(回合)
/// </summary>
public double RemainDurationTurn { get; set; } = 0;
public int RemainDurationTurn { get; set; } = 0;
/// <summary>
/// 魔法类型
@ -76,7 +82,24 @@ namespace Milimoe.FunGame.Core.Entity
/// <summary>
/// 此特效的施加者,用于溯源
/// </summary>
public Character? Source { get; set; } = null;
public virtual Character? Source { get; } = null;
/// <summary>
/// 游戏中的行动顺序表实例,在技能效果被触发时,此实例会获得赋值,使用时需要判断其是否存在
/// </summary>
public ActionQueue? ActionQueue { get; set; } = null;
/// <summary>
/// 输出文本或日志
/// </summary>
public Action<string> WriteLine
{
get
{
if (ActionQueue is null) return Console.WriteLine;
else return ActionQueue.WriteLine;
}
}
/// <summary>
/// 获得此特效时
@ -105,12 +128,9 @@ namespace Milimoe.FunGame.Core.Entity
/// <param name="isNormalAttack"></param>
/// <param name="isMagicDamage"></param>
/// <param name="magicType"></param>
/// <param name="newDamage"></param>
/// <returns>返回 true 表示修改了伤害</returns>
public virtual bool AlterExpectedDamageBeforeCalculation(Character character, Character enemy, double damage, bool isNormalAttack, bool isMagicDamage, MagicType magicType, out double newDamage)
public virtual void AlterExpectedDamageBeforeCalculation(Character character, Character enemy, ref double damage, bool isNormalAttack, bool isMagicDamage, MagicType magicType)
{
newDamage = damage;
return false;
}
/// <summary>
@ -123,12 +143,9 @@ namespace Milimoe.FunGame.Core.Entity
/// <param name="isMagicDamage"></param>
/// <param name="magicType"></param>
/// <param name="isCritical"></param>
/// <param name="newDamage"></param>
/// <returns>返回 true 表示修改了伤害</returns>
public virtual bool AlterActualDamageAfterCalculation(Character character, Character enemy, double damage, bool isNormalAttack, bool isMagicDamage, MagicType magicType, bool isCritical, out double newDamage)
public virtual void AlterActualDamageAfterCalculation(Character character, Character enemy, ref double damage, bool isNormalAttack, bool isMagicDamage, MagicType magicType, bool isCritical)
{
newDamage = damage;
return false;
}
/// <summary>
@ -136,12 +153,9 @@ namespace Milimoe.FunGame.Core.Entity
/// </summary>
/// <param name="character"></param>
/// <param name="baseHardnessTime"></param>
/// <param name="newHardnessTime"></param>
/// <returns>返回 true 表示修改了硬直时间</returns>
public virtual bool AlterHardnessTimeAfterNormalAttack(Character character, double baseHardnessTime, out double newHardnessTime)
public virtual void AlterHardnessTimeAfterNormalAttack(Character character, ref double baseHardnessTime)
{
newHardnessTime = baseHardnessTime;
return false;
}
/// <summary>
@ -149,12 +163,9 @@ namespace Milimoe.FunGame.Core.Entity
/// </summary>
/// <param name="character"></param>
/// <param name="baseHardnessTime"></param>
/// <param name="newHardnessTime"></param>
/// <returns>返回 true 表示修改了硬直时间</returns>
public virtual bool AlterHardnessTimeAfterCastSkill(Character character, double baseHardnessTime, out double newHardnessTime)
public virtual void AlterHardnessTimeAfterCastSkill(Character character, ref double baseHardnessTime)
{
newHardnessTime = baseHardnessTime;
return false;
}
/// <summary>
@ -162,12 +173,9 @@ namespace Milimoe.FunGame.Core.Entity
/// </summary>
/// <param name="character"></param>
/// <param name="baseEP"></param>
/// <param name="newEP"></param>
/// <returns>返回 true 表示修改了获得的能量</returns>
public virtual bool AlterEPAfterDamage(Character character, double baseEP, out double newEP)
public virtual void AlterEPAfterDamage(Character character, ref double baseEP)
{
newEP = baseEP;
return false;
}
/// <summary>
@ -175,12 +183,9 @@ namespace Milimoe.FunGame.Core.Entity
/// </summary>
/// <param name="character"></param>
/// <param name="baseEP"></param>
/// <param name="newEP"></param>
/// <returns>返回 true 表示修改了获得的能量</returns>
public virtual bool AlterEPAfterGetDamage(Character character, double baseEP, out double newEP)
public virtual void AlterEPAfterGetDamage(Character character, ref double baseEP)
{
newEP = baseEP;
return false;
}
/// <summary>
@ -205,12 +210,11 @@ namespace Milimoe.FunGame.Core.Entity
/// <summary>
/// 吟唱结束后释放技能(魔法)/ 直接释放技能(战技/爆发技)
/// </summary>
/// <param name="queue"></param>
/// <param name="caster"></param>
/// <param name="enemys"></param>
/// <param name="teammates"></param>
/// <param name="others"></param>
public virtual void OnSkillCasted(ActionQueue queue, Character caster, List<Character> enemys, List<Character> teammates, Dictionary<string, object> others)
public virtual void OnSkillCasted(Character caster, List<Character> enemys, List<Character> teammates, Dictionary<string, object> others)
{
}
@ -231,9 +235,11 @@ namespace Milimoe.FunGame.Core.Entity
/// <param name="character"></param>
/// <param name="enemy"></param>
/// <param name="damage"></param>
/// <param name="isNormalAttack"></param>
/// <param name="isMagicDamage"></param>
/// <param name="magicType"></param>
public virtual void AfterDamageCalculation(Character character, Character enemy, double damage, bool isMagicDamage, MagicType magicType)
/// <param name="isCritical"></param>
public virtual void AfterDamageCalculation(Character character, Character enemy, double damage, bool isNormalAttack, bool isMagicDamage, MagicType magicType, bool isCritical)
{
}
@ -248,7 +254,7 @@ namespace Milimoe.FunGame.Core.Entity
}
/// <summary>
/// 在特效持有者的回合开始
/// 在特效持有者的回合结束
/// </summary>
/// <param name="character"></param>
public virtual void OnTurnEnd(Character character)
@ -310,6 +316,45 @@ namespace Milimoe.FunGame.Core.Entity
}
/// <summary>
/// 角色属性发生变化
/// </summary>
public virtual void OnAttributeChanged(Character character)
{
}
/// <summary>
/// 对敌人造成技能伤害 [ 强烈建议使用此方法造成伤害而不是自行调用 <see cref="ActionQueue.DamageToEnemy"/> ]
/// </summary>
/// <param name="actor"></param>
/// <param name="enemy"></param>
/// <param name="isMagic"></param>
/// <param name="magicType"></param>
/// <param name="expectedDamage"></param>
/// <returns></returns>
public DamageResult DamageToEnemy(Character actor, Character enemy, bool isMagic, MagicType magicType, double expectedDamage)
{
if (ActionQueue is null) return DamageResult.Evaded;
DamageResult result = !isMagic ? ActionQueue.CalculatePhysicalDamage(actor, enemy, false, expectedDamage, out double damage) : ActionQueue.CalculateMagicalDamage(actor, enemy, false, MagicType, expectedDamage, out damage);
if (result != DamageResult.Evaded)
{
ActionQueue.DamageToEnemy(actor, enemy, damage, false, isMagic, magicType, result == DamageResult.Critical);
return result;
}
return result;
}
/// <summary>
/// 打断施法 [ 尽可能的调用此方法而不是直接调用 <see cref="ActionQueue.InterruptCasting"/>,以防止中断性变更 ]
/// </summary>
/// <param name="caster"></param>
/// <param name="interrupter"></param>
public void InterruptCasting(Character caster, Character interrupter)
{
ActionQueue?.InterruptCasting(caster, interrupter);
}
public override string ToString()
{
StringBuilder builder = new();

View File

@ -15,7 +15,7 @@ namespace Milimoe.FunGame.Core.Entity
/// <summary>
/// 普通攻击说明
/// </summary>
public string Description => $"对目标敌人造成 {Calculation.Round4Digits((1.0 + 0.05 * (Level - 1)) * 100)}% [ {Damage} ] 点{(IsMagic ? CharacterSet.GetMagicName(MagicType) : "")}伤害。";
public string Description => $"对目标敌人造成 {Calculation.Round4Digits((1.0 + 0.05 * (Level - 1)) * 100)}% [ {Damage} ] 点{(IsMagic ? CharacterSet.GetMagicName(MagicType) : "")}。";
/// <summary>
/// 所属的角色
@ -45,12 +45,12 @@ namespace Milimoe.FunGame.Core.Entity
/// <summary>
/// 是否是魔法伤害
/// </summary>
public bool IsMagic { get; } = isMagic;
public bool IsMagic => _IsMagic;
/// <summary>
/// 魔法伤害需要指定魔法类型
/// </summary>
public MagicType MagicType { get; } = magicType;
public MagicType MagicType => _MagicType;
/// <summary>
/// 硬直时间
@ -77,6 +77,17 @@ namespace Milimoe.FunGame.Core.Entity
}
}
/// <summary>
/// 修改伤害类型
/// </summary>
/// <param name="isMagic"></param>
/// <param name="magicType"></param>
public void SetMagicType(bool isMagic, MagicType magicType)
{
_IsMagic = isMagic;
_MagicType = magicType;
}
public override bool Equals(IBaseEntity? other)
{
return other is NormalAttack c && c.Name == Name;
@ -97,5 +108,15 @@ namespace Milimoe.FunGame.Core.Entity
/// 等级
/// </summary>
private int _Level = 0;
/// <summary>
/// 是否是魔法伤害
/// </summary>
private bool _IsMagic = isMagic;
/// <summary>
/// 魔法类型
/// </summary>
private MagicType _MagicType = magicType;
}
}

View File

@ -1,6 +1,7 @@
using System.Text;
using Milimoe.FunGame.Core.Api.Utility;
using Milimoe.FunGame.Core.Interface.Entity;
using Milimoe.FunGame.Core.Library.Constant;
namespace Milimoe.FunGame.Core.Entity
{
@ -42,18 +43,24 @@ namespace Milimoe.FunGame.Core.Entity
}
/// <summary>
/// 是否是主动技能 [ 此项为最高优先级 ]
/// 技能 [ 此项为最高优先级 ]
/// </summary>
[InitRequired]
public bool IsActive { get; set; } = true;
public SkillType SkillType { get; set; }
/// <summary>
/// 是否可用 [ 此项为最高优先级 ]
/// 是否是主动技能 [ 此项为高优先级 ]
/// </summary>
[InitRequired]
public bool IsActive => SkillType != SkillType.Passive;
/// <summary>
/// 是否可用 [ 此项为高优先级 ]
/// </summary>
public bool Enable { get; set; } = true;
/// <summary>
/// 效果持续生效中 [ 此项设置为true后不允许再次释放防止重复释放 ]
/// 效果持续生效中 [ 此项为高优先级 ] [ 此项设置为true后不允许再次释放防止重复释放 ]
/// </summary>
public bool IsInEffect { get; set; } = false;
@ -61,13 +68,13 @@ namespace Milimoe.FunGame.Core.Entity
/// 是否是爆发技 [ 此项为高优先级 ]
/// </summary>
[InitRequired]
public bool IsSuperSkill { get; set; } = false;
public bool IsSuperSkill => SkillType == SkillType.SuperSkill;
/// <summary>
/// 是否属于魔法 [ <see cref="IsActive"/> 必须为 true ],反之为战技
/// </summary>
[InitRequired]
public bool IsMagic { get; set; } = true;
public bool IsMagic => SkillType == SkillType.Magic;
/// <summary>
/// 魔法消耗 [ 魔法 ]
@ -126,51 +133,65 @@ namespace Milimoe.FunGame.Core.Entity
/// </summary>
public Dictionary<string, object> OtherArgs { get; } = [];
protected Skill(bool active = true, bool magic = true, Character? character = null)
/// <summary>
/// 游戏中的行动顺序表实例,在技能效果被触发时,此实例会获得赋值,使用时需要判断其是否存在
/// </summary>
public ActionQueue? ActionQueue { get; set; } = null;
protected Skill(SkillType type, Character? character = null)
{
IsActive = active;
IsMagic = magic;
SkillType = type;
Character = character;
}
protected Skill(bool super = false, Character? character = null)
internal Skill()
{
IsSuperSkill = super;
Character = character;
SkillType = SkillType.Passive;
}
internal Skill() { }
/// <summary>
/// 触发技能升级
/// </summary>
public void OnLevelUp()
{
if (!IsActive)
if (!IsActive && Level > 0)
{
foreach (Effect e in AddInactiveEffectToCharacter())
{
if (Character != null && !Character.Effects.Contains(e))
{
Character.Effects.Add(e);
e.OnEffectGained(Character);
}
}
}
}
/// <summary>
/// 当获得技能时
/// </summary>
/// <param name="queue"></param>
public void OnSkillGained(ActionQueue queue)
{
ActionQueue = queue;
OnLevelUp();
}
/// <summary>
/// 触发技能效果
/// </summary>
public void Trigger(ActionQueue queue, Character actor, List<Character> enemys, List<Character> teammates)
{
ActionQueue = queue;
foreach (Effect e in Effects)
{
e.OnSkillCasted(queue, actor, enemys, teammates, OtherArgs);
e.ActionQueue = ActionQueue;
e.OnSkillCasted(actor, enemys, teammates, OtherArgs);
}
}
/// <summary>
/// 被动技能,需要重写此方法,返回被动特效给角色 [ 此方法会在游戏开始时和技能升级时调用 ]
/// 被动技能,需要重写此方法,返回被动特效给角色 [ 此方法会在技能学习时触发 ]
/// </summary>
/// <returns></returns>
public virtual IEnumerable<Effect> AddInactiveEffectToCharacter()
@ -178,6 +199,10 @@ namespace Milimoe.FunGame.Core.Entity
return [];
}
/// <summary>
/// 返回技能的详细说明
/// </summary>
/// <returns></returns>
public override string ToString()
{
StringBuilder builder = new();

View File

@ -2,7 +2,7 @@
{
public interface IActiveEnable
{
public bool IsActive { get; set; }
public bool Enable { get; set; }
public bool IsActive { get; }
public bool Enable { get; }
}
}

View File

@ -325,6 +325,9 @@ namespace Milimoe.FunGame.Core.Library.Constant
}
public static string GetContinuousKilling(int kills)
{
if (kills > 10) return "超越神的杀戮";
else
{
return kills switch
{
@ -340,6 +343,7 @@ namespace Milimoe.FunGame.Core.Library.Constant
_ => ""
};
}
}
public static string GetCharacterState(CharacterState state)
{

View File

@ -182,10 +182,218 @@ namespace Milimoe.FunGame.Core.Library.Constant
public enum SkillType
{
Active,
/// <summary>
/// 魔法,编号 1xxx
/// </summary>
Magic,
/// <summary>
/// 战技,编号 2xxx
/// </summary>
Skill,
/// <summary>
/// 爆发技,编号 3xxx
/// </summary>
SuperSkill,
/// <summary>
/// 被动,编号 4xxx
/// </summary>
Passive
}
/// <summary>
/// 注意:具有控制效果的特效,应该和技能本身的特效(一般此项为None)区分开来。此效果被赋值会改变一些判断的结果。
/// </summary>
public enum EffectControlType
{
/// <summary>
/// 无特殊效果
/// </summary>
None,
/// <summary>
/// 眩晕,目标无法行动
/// </summary>
Stun,
/// <summary>
/// 冰冻,目标无法行动
/// </summary>
Freeze,
/// <summary>
/// 沉默,目标无法使用技能
/// </summary>
Silence,
/// <summary>
/// 定身
/// </summary>
Root,
/// <summary>
/// 恐惧
/// </summary>
Fear,
/// <summary>
/// 睡眠,目标暂时无法行动,受到伤害后会苏醒
/// </summary>
Sleep,
/// <summary>
/// 击退
/// </summary>
Knockback,
/// <summary>
/// 击倒,目标被击倒在地,暂时无法行动
/// </summary>
Knockdown,
/// <summary>
/// 嘲讽,目标被迫攻击施法者
/// </summary>
Taunt,
/// <summary>
/// 减速,目标行动速度和攻击频率降低
/// </summary>
Slow,
/// <summary>
/// 衰弱,目标的攻击和防御降低
/// </summary>
Weaken,
/// <summary>
/// 中毒,目标在一段时间内持续受到伤害
/// </summary>
Poison,
/// <summary>
/// 燃烧,目标受到火焰伤害,持续一段时间
/// </summary>
Burn,
/// <summary>
/// 流血,目标持续受到物理伤害
/// </summary>
Bleed,
/// <summary>
/// 致盲,目标无法准确攻击,命中率降低
/// </summary>
Blind,
/// <summary>
/// 致残,减少目标的行动或攻击能力
/// </summary>
Cripple,
/// <summary>
/// 护盾,减少受到的伤害或抵消部分伤害
/// </summary>
Shield,
/// <summary>
/// 持续治疗,逐步恢复生命值
/// </summary>
HealOverTime,
/// <summary>
/// 加速,提升行动速度和攻击频率
/// </summary>
Haste,
/// <summary>
/// 无敌,暂时不会受到任何伤害
/// </summary>
Invulnerable,
/// <summary>
/// 伤害提升,增加攻击输出
/// </summary>
DamageBoost,
/// <summary>
/// 防御提升,减少所受伤害
/// </summary>
DefenseBoost,
/// <summary>
/// 暴击提升,增加暴击率或暴击伤害
/// </summary>
CritBoost,
/// <summary>
/// 魔法恢复,增加魔法值回复速度
/// </summary>
ManaRegen,
/// <summary>
/// 破甲,降低目标的防御值
/// </summary>
ArmorBreak,
/// <summary>
/// 降低魔法抗性,目标更容易受到魔法伤害
/// </summary>
MagicResistBreak,
/// <summary>
/// 诅咒,降低目标的属性或给予负面效果
/// </summary>
Curse,
/// <summary>
/// 疲劳,减少目标的攻击或技能效果
/// </summary>
Exhaustion,
/// <summary>
/// 魔力燃烧,消耗目标的魔法值
/// </summary>
ManaBurn,
/// <summary>
/// 魅惑,控制目标替施法者作战
/// </summary>
Charm,
/// <summary>
/// 缴械,目标无法进行普通攻击
/// </summary>
Disarm,
/// <summary>
/// 混乱,目标的行动变得随机化
/// </summary>
Confusion,
/// <summary>
/// 石化,目标无法行动,并大幅增加受到的伤害
/// </summary>
Petrify,
/// <summary>
/// 法术沉默,目标无法施放魔法技能
/// </summary>
SilenceMagic,
/// <summary>
/// 放逐,目标暂时无法被攻击,也无法行动
/// </summary>
Banish,
/// <summary>
/// 毁灭,目标在倒计时结束后受到大量伤害或死亡
/// </summary>
Doom
}
public enum ItemType
{
Active,