diff --git a/Entity/Item/Item.cs b/Entity/Item/Item.cs index 666fb65..16e52b1 100644 --- a/Entity/Item/Item.cs +++ b/Entity/Item/Item.cs @@ -248,7 +248,7 @@ namespace Milimoe.FunGame.Core.Entity { foreach (Skill skill in Skills.Passives) { - List effects = [.. Character.Effects.Where(e => e.Skill == skill && e.Level > 0 && !e.IsBeingTemporaryDispelled)]; + List effects = [.. Character.Effects.Where(e => e.Skill == skill && e.IsInEffect)]; foreach (Effect e in effects) { Character.Effects.Remove(e); diff --git a/Entity/Skill/Effect.cs b/Entity/Skill/Effect.cs index 90a72aa..a0e4154 100644 --- a/Entity/Skill/Effect.cs +++ b/Entity/Skill/Effect.cs @@ -55,15 +55,25 @@ namespace Milimoe.FunGame.Core.Entity /// public virtual bool DurativeWithoutDuration { get; set; } = false; + /// + /// 附属于某个特效 + /// + public Effect? ParentEffect { get; set; } = null; + /// /// 是否是某个特效的附属 /// - public virtual bool IsSubsidiary { get; set; } = false; + public bool IsSubsidiary => ParentEffect != null; + + /// + /// 是否强制在状态栏中隐藏 + /// + public virtual bool ForceHideInStatusBar { get; set; } = false; /// /// 是否显示在状态栏 /// - public bool ShowInStatusBar => Skill.Item is null || (Durative && Duration > 0) || DurationTurn > 0 || DurativeWithoutDuration || IsSubsidiary; + public bool ShowInStatusBar => !ForceHideInStatusBar && !IsSubsidiary && (Skill.Item is null || (Durative && Duration > 0) || DurationTurn > 0 || DurativeWithoutDuration); /// /// 特效是否生效 diff --git a/Entity/Skill/NormalAttack.cs b/Entity/Skill/NormalAttack.cs index db5c023..a4f3bfe 100644 --- a/Entity/Skill/NormalAttack.cs +++ b/Entity/Skill/NormalAttack.cs @@ -18,6 +18,11 @@ namespace Milimoe.FunGame.Core.Entity /// public string Description => $"对目标敌人造成 {(1.0 + 0.05 * (Level - 1)) * 100:0.##}% 攻击力 [ {Damage:0.##} ] 点{(IsMagic ? CharacterSet.GetMagicDamageName(MagicType) : "物理伤害")}。"; + /// + /// 普通攻击的通用说明 + /// + public string GeneralDescription => $"对目标敌人造成基于 100(+5/Lv)% 攻击力的{(IsMagic ? CharacterSet.GetMagicDamageName(MagicType) : "物理伤害")}。"; + /// /// 所属的角色 /// @@ -53,6 +58,16 @@ namespace Milimoe.FunGame.Core.Entity /// public MagicType MagicType => _MagicType; + /// + /// 是否可用 + /// + public bool Enable { get; set; } = true; + + /// + /// 是否在持续生效,为 true 时不允许再次使用。普通攻击始终为 false + /// + public bool IsInEffect => false; + /// /// 无视免疫类型 /// @@ -93,6 +108,31 @@ namespace Milimoe.FunGame.Core.Entity /// public double CanSelectTargetRange { get; set; } = 0; + /// + /// 普通攻击没有魔法消耗 + /// + public double RealMPCost => 0; + + /// + /// 普通攻击没有吟唱时间 + /// + public double RealCastTime => 0; + + /// + /// 普通攻击没有能量消耗 + /// + public double RealEPCost => 0; + + /// + /// 普通攻击没有冷却时间 + /// + public double RealCD => 0; + + /// + /// 普通攻击没有冷却时间 + /// + public double CurrentCD => 0; + /// /// 获取可选择的目标列表 /// @@ -129,6 +169,10 @@ namespace Milimoe.FunGame.Core.Entity /// public void Attack(IGamingQueue queue, Character attacker, params IEnumerable enemys) { + if (!Enable) + { + return; + } foreach (Character enemy in enemys) { if (enemy.HP > 0) diff --git a/Entity/Skill/SkillTarget.cs b/Entity/Skill/SkillTarget.cs index 8e2971c..329233e 100644 --- a/Entity/Skill/SkillTarget.cs +++ b/Entity/Skill/SkillTarget.cs @@ -1,8 +1,20 @@ namespace Milimoe.FunGame.Core.Entity { + /// + /// 技能和它的目标结构体 + /// + /// + /// public struct SkillTarget(Skill skill, List targets) { + /// + /// 技能实例 + /// public Skill Skill { get; set; } = skill; + + /// + /// 技能的目标列表 + /// public List Targets { get; set; } = targets; } } diff --git a/FunGame.Core.csproj b/FunGame.Core.csproj index 3d619d4..8f7775f 100644 --- a/FunGame.Core.csproj +++ b/FunGame.Core.csproj @@ -23,7 +23,17 @@ FunGame.Core: A C#.NET library for turn-based games. game;turn-based;server;framework;dotnet;csharp;gamedev - - Initial release candidate 1 (1.0.0-rc.1) + - Initial release candidate 1 (1.0.0-rc.1-0428) + - Abstract ActionQueue as GamingQueue, and separate the original Mix / Team modes into two queue types: MixGamingQueue and TeamGamingQueue. (1.0.0-rc.1-0502) + - In the Effect class, added ParentEffect and ForceHideInStatusBar properties for more precise control of the status bar display. (1.0.0-rc.1-0509) + - Added helper methods IsTeammate and GetIsTeammateDictionary to GamingQueue for determining if someone is a teammate, IGamingQueue also. This facilitates the skill effects to determine whether the target is a teammate. (1.0.0-rc.1-0509) + - Added more properties (such as Name, RealCD) to the ISkill interface. Both NormalAttack and Skill inherit from ISkill, thus implementing these properties, although some properties are not meaningful for NormalAttack. (1.0.0-rc.1-0509) + - Added corresponding text for EffectTypes Lifesteal and GrievousWound. (1.0.0-rc.1-0509) + - Added EffectTypes: WeakDispelling and StrongDispelling, representing DurativeWeak and DurativeStrong of DispelType. (1.0.0-rc.1-0509) + - Added underlying processing support for continuous dispelling in the TimeLapse method. (1.0.0-rc.1-0509) + - Fixed an issue where the effect's shield hook provided incorrect parameters. (1.0.0-rc.1-0509) + - Fixed an issue where the result of pre-hooks for evade and critical hit checks always deferred to the result of the last effect. It should be that if any effect prevents the check, it is skipped. (1.0.0-rc.1-0509) + - Added comments for some code. (1.0.0-rc.1-0509) https://github.com/project-redbud/FunGame-Core https://github.com/project-redbud diff --git a/Interface/Base/IGamingQueue.cs b/Interface/Base/IGamingQueue.cs index bca61f3..a21db75 100644 --- a/Interface/Base/IGamingQueue.cs +++ b/Interface/Base/IGamingQueue.cs @@ -168,6 +168,22 @@ namespace Milimoe.FunGame.Core.Interface.Base /// public Task> SelectTargetsAsync(Character character, NormalAttack attack, List enemys, List teammates); + /// + /// 判断目标对于某个角色是否是队友 + /// + /// + /// + /// + public bool IsTeammate(Character character, Character target); + + /// + /// 获取目标对于某个角色是否是队友的字典 + /// + /// + /// + /// + public Dictionary GetIsTeammateDictionary(Character character, IEnumerable targets); + /// /// 检查角色是否在 AI 控制状态 /// diff --git a/Interface/Entity/Base/IBaseEntity.cs b/Interface/Entity/Base/IBaseEntity.cs index c4288f3..dbb3a8d 100644 --- a/Interface/Entity/Base/IBaseEntity.cs +++ b/Interface/Entity/Base/IBaseEntity.cs @@ -2,10 +2,25 @@ { public interface IBaseEntity : IEquatable { + /// + /// 实体的数字标识符 + /// public long Id { get; } + + /// + /// 实体的唯一标识符 + /// public Guid Guid { get; } + + /// + /// 实体的名称 + /// public string Name { get; } + /// + /// 获取实体的 Id.Name + /// + /// public string GetIdName(); } } diff --git a/Interface/Entity/Typical/ISkill.cs b/Interface/Entity/Typical/ISkill.cs index c0dc96b..43d4fe1 100644 --- a/Interface/Entity/Typical/ISkill.cs +++ b/Interface/Entity/Typical/ISkill.cs @@ -2,8 +2,41 @@ namespace Milimoe.FunGame.Core.Interface.Entity { - public interface ISkill + /// + /// ISkill 是技能的通用接口,包含一些基本属性,实现类: + /// + public interface ISkill : IBaseEntity { + /// + /// 此技能所属的角色 + /// + public Character? Character { get; } + + /// + /// 技能描述 + /// + public string Description { get; } + + /// + /// 技能的通用描述 + /// + public string GeneralDescription { get; } + + /// + /// 技能等级,等于 0 时可以称之为尚未学习 + /// + public int Level { get; } + + /// + /// 是否可用 [ 此项为高优先级 ] + /// + public bool Enable { get; } + + /// + /// 效果持续生效中 [ 此项为高优先级 ] [ 此项设置为true后不允许再次释放,防止重复释放 ] + /// + public bool IsInEffect { get; } + /// /// 可选取自身 /// @@ -28,6 +61,36 @@ namespace Milimoe.FunGame.Core.Interface.Entity /// public double CanSelectTargetRange { get; } + /// + /// 实际魔法消耗 [ 魔法 ] + /// + public double RealMPCost { get; } + + /// + /// 实际吟唱时间 [ 魔法 ] + /// + public double RealCastTime { get; } + + /// + /// 实际能量消耗 [ 战技 ] + /// + public double RealEPCost { get; } + + /// + /// 实际冷却时间 + /// + public double RealCD { get; } + + /// + /// 剩余冷却时间 + /// + public double CurrentCD { get; } + + /// + /// 实际硬直时间 + /// + public double RealHardnessTime { get; } + /// /// 获取可选择的目标列表 /// diff --git a/Library/Constant/ConstantSet.cs b/Library/Constant/ConstantSet.cs index ac17ba3..49e53f5 100644 --- a/Library/Constant/ConstantSet.cs +++ b/Library/Constant/ConstantSet.cs @@ -682,6 +682,10 @@ namespace Milimoe.FunGame.Core.Library.Constant EffectType.SkilledImmune => "技能免疫", EffectType.AllImmune => "完全免疫", EffectType.EvadeBoost => "闪避提升", + EffectType.Lifesteal => "生命偷取", + EffectType.GrievousWound => "重伤", + EffectType.WeakDispelling => "持续性弱驱散", + EffectType.StrongDispelling => "持续性强驱散", _ => "未知效果" }; } @@ -710,6 +714,8 @@ namespace Milimoe.FunGame.Core.Library.Constant EffectType.Petrify => DispelledType.Strong, EffectType.SilenceMagic => DispelledType.Strong, EffectType.Banish => DispelledType.Strong, + EffectType.AllImmune => DispelledType.Strong, + EffectType.StrongDispelling => DispelledType.Strong, EffectType.Mark => DispelledType.Weak, EffectType.Slow => DispelledType.Weak, EffectType.Weaken => DispelledType.Weak, @@ -733,10 +739,10 @@ namespace Milimoe.FunGame.Core.Library.Constant EffectType.PhysicalImmune => DispelledType.Weak, EffectType.MagicalImmune => DispelledType.Weak, EffectType.SkilledImmune => DispelledType.Weak, - EffectType.AllImmune => DispelledType.Strong, EffectType.EvadeBoost => DispelledType.Weak, EffectType.Lifesteal => DispelledType.Weak, EffectType.GrievousWound => DispelledType.Weak, + EffectType.WeakDispelling => DispelledType.Weak, _ => DispelledType.Weak }; } diff --git a/Library/Constant/TypeEnum.cs b/Library/Constant/TypeEnum.cs index 4732a8b..6ab2361 100644 --- a/Library/Constant/TypeEnum.cs +++ b/Library/Constant/TypeEnum.cs @@ -228,6 +228,11 @@ namespace Milimoe.FunGame.Core.Library.Constant /// /// 注意:具有控制效果的特效,应该和技能本身的特效(一般此项为None)区分开来。此效果被赋值会改变一些判断的结果。 + /// 关联方法: + /// + /// + /// + /// /// public enum EffectType { @@ -464,7 +469,17 @@ namespace Milimoe.FunGame.Core.Library.Constant /// /// 重伤,目标受到的治疗效果降低 /// - GrievousWound + GrievousWound, + + /// + /// 持续性弱驱散 + /// + WeakDispelling, + + /// + /// 持续性强驱散 + /// + StrongDispelling } public enum ItemType diff --git a/Model/GamingQueue.cs b/Model/GamingQueue.cs index 0a370cf..2df2bd2 100644 --- a/Model/GamingQueue.cs +++ b/Model/GamingQueue.cs @@ -8,6 +8,7 @@ namespace Milimoe.FunGame.Core.Model { /// /// 提供一个基础的回合制游戏队列基类实现,可继承扩展 + /// 该默认实现为混战模式 /// public class GamingQueue : IGamingQueue { @@ -577,12 +578,6 @@ namespace Milimoe.FunGame.Core.Model List effects = [.. character.Effects]; foreach (Effect effect in effects) { - if (effect.IsBeingTemporaryDispelled) - { - effect.IsBeingTemporaryDispelled = false; - effect.OnEffectGained(character); - } - if (effect.Level == 0) { character.Effects.Remove(effect); @@ -595,6 +590,18 @@ namespace Milimoe.FunGame.Core.Model effect.OnTimeElapsed(character, timeToReduce); } + if (effect.IsBeingTemporaryDispelled) + { + effect.IsBeingTemporaryDispelled = false; + effect.OnEffectGained(character); + } + + // 如果特效具备临时驱散或者持续性驱散的功能 + if (effect.Source != null && (effect.EffectType == EffectType.WeakDispelling || effect.EffectType == EffectType.StrongDispelling)) + { + effect.Dispel(effect.Source, character, IsTeammate(character, effect.Source)); + } + // 自身被动不会考虑 if (effect.EffectType == EffectType.None && effect.Skill.SkillType == SkillType.Passive) { @@ -1179,10 +1186,13 @@ namespace Milimoe.FunGame.Core.Model await OnQueueUpdatedAsync(_queue, character, newHardnessTime, QueueUpdatedReason.Action, "设置角色行动后的硬直时间。"); LastRound.HardnessTime = newHardnessTime; - effects = [.. character.Effects.Where(e => e.IsInEffect)]; + effects = [.. character.Effects]; foreach (Effect effect in effects) { - effect.OnTurnEnd(character); + if (effect.IsInEffect) + { + effect.OnTurnEnd(character); + } // 自身被动不会考虑 if (effect.EffectType == EffectType.None && effect.Skill.SkillType == SkillType.Passive) @@ -1410,7 +1420,7 @@ namespace Milimoe.FunGame.Core.Model effects = [.. characters.SelectMany(c => c.Effects.Where(e => e.IsInEffect)).Distinct()]; foreach (Effect effect in effects) { - if (!effect.BeforeShieldCalculation(actor, enemy, isMagicDamage, magicType, damage, shield, ref shieldMsg)) + if (!effect.BeforeShieldCalculation(enemy, actor, isMagicDamage, magicType, damage, shield, ref shieldMsg)) { change = true; } @@ -1428,7 +1438,7 @@ namespace Milimoe.FunGame.Core.Model effects = [.. characters.SelectMany(c => c.Effects.Where(e => e.IsInEffect)).Distinct()]; foreach (Effect effect in effects) { - if (!effect.OnShieldBroken(actor, enemy, isMagicDamage, magicType, damage, shield, remain)) + if (!effect.OnShieldBroken(enemy, actor, isMagicDamage, magicType, damage, shield, remain)) { change = true; } @@ -2035,7 +2045,10 @@ namespace Milimoe.FunGame.Core.Model effects = [.. characters.SelectMany(c => c.Effects.Where(e => e.IsInEffect)).Distinct()]; foreach (Effect effect in effects) { - checkEvade = effect.BeforeEvadeCheck(actor, enemy, ref throwingBonus); + if (!effect.BeforeEvadeCheck(actor, enemy, ref throwingBonus)) + { + checkEvade = false; + } } if (checkEvade) @@ -2075,7 +2088,10 @@ namespace Milimoe.FunGame.Core.Model effects = [.. characters.SelectMany(c => c.Effects.Where(e => e.IsInEffect)).Distinct()]; foreach (Effect effect in effects) { - checkCritical = effect.BeforeCriticalCheck(actor, enemy, ref throwingBonus); + if (!effect.BeforeCriticalCheck(actor, enemy, ref throwingBonus)) + { + checkCritical = false; + } } if (checkCritical) @@ -2145,7 +2161,10 @@ namespace Milimoe.FunGame.Core.Model effects = [.. characters.SelectMany(c => c.Effects.Where(e => e.IsInEffect)).Distinct()]; foreach (Effect effect in effects) { - checkEvade = effect.BeforeEvadeCheck(actor, enemy, ref throwingBonus); + if (!effect.BeforeEvadeCheck(actor, enemy, ref throwingBonus)) + { + checkEvade = false; + } } if (checkEvade) @@ -2184,7 +2203,10 @@ namespace Milimoe.FunGame.Core.Model effects = [.. characters.SelectMany(c => c.Effects.Where(e => e.IsInEffect)).Distinct()]; foreach (Effect effect in effects) { - checkCritical = effect.BeforeCriticalCheck(actor, enemy, ref throwingBonus); + if (!effect.BeforeCriticalCheck(actor, enemy, ref throwingBonus)) + { + checkCritical = false; + } } if (checkCritical) @@ -2218,6 +2240,35 @@ namespace Milimoe.FunGame.Core.Model return Math.Min((a + Random.Shared.Next(30)) * b, max); } + /// + /// 判断目标对于某个角色是否是队友 + /// + /// + /// + /// + public bool IsTeammate(Character character, Character target) + { + List teammates = GetTeammates(character); + return teammates.Contains(target); + } + + /// + /// 获取目标对于某个角色是否是友方的字典 + /// + /// + /// + /// + public Dictionary GetIsTeammateDictionary(Character character, params IEnumerable targets) + { + Dictionary dict = []; + List teammates = GetTeammates(character); + foreach (Character target in targets) + { + dict[target] = teammates.Contains(target); + } + return dict; + } + #endregion #region 回合奖励 diff --git a/Model/MixGamingQueue.cs b/Model/MixGamingQueue.cs index e9627c0..7387886 100644 --- a/Model/MixGamingQueue.cs +++ b/Model/MixGamingQueue.cs @@ -3,6 +3,9 @@ using Milimoe.FunGame.Core.Library.Constant; namespace Milimoe.FunGame.Core.Model { + /// + /// 混战游戏队列,增强版混战模式 + /// public class MixGamingQueue : GamingQueue { /// diff --git a/Model/TeamGamingQueue.cs b/Model/TeamGamingQueue.cs index 2c9efa2..ce20487 100644 --- a/Model/TeamGamingQueue.cs +++ b/Model/TeamGamingQueue.cs @@ -3,6 +3,9 @@ using Milimoe.FunGame.Core.Library.Constant; namespace Milimoe.FunGame.Core.Model { + /// + /// 团队游戏队列,团队模式 + /// public class TeamGamingQueue : GamingQueue { /// diff --git a/README.md b/README.md index b2d48c8..961e702 100644 --- a/README.md +++ b/README.md @@ -36,6 +36,8 @@ git clone -b latest https://github.com/project-redbud/FunGame-Core.git 我们维护了一份 API 文档,如有需要请随时查阅:[FunGame 开发文档](https://project-redbud.github.io/)。 文档内容会随着本项目的更改而变化,但是我们不保证能够及时更新文档。 +也欢迎查阅由 `DeepWiki` 提供的 AI 生成的文档:[DeepWiki 文档](https://deepwiki.com/project-redbud/FunGame-Core),此 AI 工具从头到尾分析了整个项目的代码并组织为 Wiki 形式,方便开发者结合源代码来理解整个项目。 + 在使用本项目的过程中遇到任何问题,欢迎提交 [issues](https://github.com/project-redbud/FunGame-Core/issues),我们会积极解决你的问题。 ## 许可证