diff --git a/Entity/Character/Character.cs b/Entity/Character/Character.cs index 4f17db5..0399065 100644 --- a/Entity/Character/Character.cs +++ b/Entity/Character/Character.cs @@ -125,13 +125,14 @@ namespace Milimoe.FunGame.Core.Entity { get { - return field >= 1 ? field : 1; + return Math.Max(1, field + ExLevel); } set { int past = field; field = Math.Min(Math.Max(1, value), GameplayEquilibriumConstant.MaxLevel); - if (past != field) + int level = field + ExLevel; + if (past != level) { OnAttributeChanged(); Recovery(); @@ -139,6 +140,11 @@ namespace Milimoe.FunGame.Core.Entity } } + /// + /// 额外等级 + /// + public int ExLevel { get; set; } = 0; + /// /// 经验值 /// @@ -2003,6 +2009,7 @@ namespace Milimoe.FunGame.Core.Entity Promotion = Promotion, PrimaryAttribute = PrimaryAttribute, Level = Level, + ExLevel = ExLevel, LevelBreak = LevelBreak, EXP = EXP, InitialHP = InitialHP, @@ -2116,6 +2123,7 @@ namespace Milimoe.FunGame.Core.Entity Promotion = c.Promotion; PrimaryAttribute = c.PrimaryAttribute; Level = c.Level; + ExLevel = c.ExLevel; LevelBreak = c.LevelBreak; EXP = c.EXP; CharacterState = c.CharacterState; diff --git a/Entity/Skill/Skill.cs b/Entity/Skill/Skill.cs index 5f306f4..4408b2e 100644 --- a/Entity/Skill/Skill.cs +++ b/Entity/Skill/Skill.cs @@ -56,7 +56,7 @@ namespace Milimoe.FunGame.Core.Entity { get { - return Math.Max(0, field); + return Math.Max(0, field + ExLevel); } set { @@ -66,6 +66,11 @@ namespace Milimoe.FunGame.Core.Entity } } + /// + /// 额外等级 + /// + public int ExLevel { get; set; } = 0; + /// /// 技能类型 [ 此项为最高优先级 ] /// diff --git a/Library/Common/JsonConverter/CharacterConverter.cs b/Library/Common/JsonConverter/CharacterConverter.cs index ff6beff..3310ac5 100644 --- a/Library/Common/JsonConverter/CharacterConverter.cs +++ b/Library/Common/JsonConverter/CharacterConverter.cs @@ -59,6 +59,9 @@ namespace Milimoe.FunGame.Core.Library.Common.JsonConverter case nameof(Character.Level): result.Level = reader.GetInt32(); break; + case nameof(Character.ExLevel): + result.ExLevel = reader.GetInt32(); + break; case nameof(Character.LevelBreak): result.LevelBreak = reader.GetInt32(); break; @@ -267,6 +270,7 @@ namespace Milimoe.FunGame.Core.Library.Common.JsonConverter writer.WriteNumber(nameof(Character.Promotion), value.Promotion); writer.WriteNumber(nameof(Character.PrimaryAttribute), (int)value.PrimaryAttribute); writer.WriteNumber(nameof(Character.Level), value.Level); + writer.WriteNumber(nameof(Character.ExLevel), value.ExLevel); writer.WriteNumber(nameof(Character.LevelBreak), value.LevelBreak); writer.WriteNumber(nameof(Character.EXP), value.EXP); writer.WriteBoolean(nameof(Character.IsNeutral), value.IsNeutral); diff --git a/Library/Common/JsonConverter/SkillConverter.cs b/Library/Common/JsonConverter/SkillConverter.cs index 3aa325f..2e3f89f 100644 --- a/Library/Common/JsonConverter/SkillConverter.cs +++ b/Library/Common/JsonConverter/SkillConverter.cs @@ -41,6 +41,9 @@ namespace Milimoe.FunGame.Core.Library.Common.JsonConverter case nameof(Skill.Level): result.Level = reader.GetInt32(); break; + case nameof(Skill.ExLevel): + result.ExLevel = reader.GetInt32(); + break; case nameof(Skill.CastAnywhere): result.CastAnywhere = reader.GetBoolean(); break; @@ -143,6 +146,7 @@ namespace Milimoe.FunGame.Core.Library.Common.JsonConverter if (value.GeneralDescription.Length > 0) writer.WriteString(nameof(Skill.GeneralDescription), value.GeneralDescription); if (value.Slogan.Length > 0) writer.WriteString(nameof(Skill.Slogan), value.Slogan); if (value.Level > 0) writer.WriteNumber(nameof(Skill.Level), value.Level); + if (value.ExLevel > 0) writer.WriteNumber(nameof(Skill.ExLevel), value.ExLevel); writer.WriteBoolean(nameof(Skill.CastAnywhere), value.CastAnywhere); writer.WriteNumber(nameof(Skill.CastRange), value.CastRange); if (value.CanSelectSelf) writer.WriteBoolean(nameof(Skill.CanSelectSelf), value.CanSelectSelf); diff --git a/Model/DecisionPoints.cs b/Model/DecisionPoints.cs index 25c112e..583d05e 100644 --- a/Model/DecisionPoints.cs +++ b/Model/DecisionPoints.cs @@ -1,4 +1,5 @@ -using System.Text.Json.Serialization; +using System.Text; +using System.Text.Json.Serialization; using Milimoe.FunGame.Core.Entity; using Milimoe.FunGame.Core.Library.Constant; @@ -52,15 +53,51 @@ namespace Milimoe.FunGame.Core.Model /// public int ActionsTaken { get; set; } = 0; - // 回合内的临时决策点配额加成 - private int _tempActionQuotaNormalAttack = 0; - private int _tempActionQuotaSuperSkill = 0; - private int _tempActionQuotaSkill = 0; - private int _tempActionQuotaItem = 0; - private int _tempActionQuotaOther = 0; + /// + /// 本回合已使用的决策点 + /// + public int DecisionPointsCost { get; set; } = 0; /// - /// 获取当前决策点配额 + /// 临时全能决策点配额加成 + /// + public int TempActionQuotaAllRound => _tempActionQuotaAllRound.Values.Sum(); + + /// + /// 临时普通攻击决策点配额加成 + /// + public int TempActionQuotaNormalAttack => _tempActionQuotaNormalAttack.Values.Sum(); + + /// + /// 临时爆发技决策点配额加成 + /// + public int TempActionQuotaSuperSkill => _tempActionQuotaSuperSkill.Values.Sum(); + + /// + /// 临时战技决策点配额加成 + /// + public int TempActionQuotaSkill => _tempActionQuotaSkill.Values.Sum(); + + /// + /// 临时使用物品决策点配额加成 + /// + public int TempActionQuotaItem => _tempActionQuotaItem.Values.Sum(); + + /// + /// 临时其他决策点配额加成 + /// + public int TempActionQuotaOther => _tempActionQuotaOther.Values.Sum(); + + // 回合内的临时决策点配额加成 + private readonly Dictionary _tempActionQuotaAllRound = []; + private readonly Dictionary _tempActionQuotaNormalAttack = []; + private readonly Dictionary _tempActionQuotaSuperSkill = []; + private readonly Dictionary _tempActionQuotaSkill = []; + private readonly Dictionary _tempActionQuotaItem = []; + private readonly Dictionary _tempActionQuotaOther = []; + + /// + /// 获取决策点配额 /// /// /// @@ -70,12 +107,12 @@ namespace Milimoe.FunGame.Core.Model { return type switch { - CharacterActionType.NormalAttack => GameplayEquilibriumConstant.ActionQuotaNormalAttack + _tempActionQuotaNormalAttack, - CharacterActionType.CastSuperSkill => GameplayEquilibriumConstant.ActionQuotaSuperSkill + _tempActionQuotaSuperSkill, - CharacterActionType.CastSkill => GameplayEquilibriumConstant.ActionQuotaSkill + _tempActionQuotaSkill, + CharacterActionType.NormalAttack => GameplayEquilibriumConstant.ActionQuotaNormalAttack + TempActionQuotaNormalAttack + TempActionQuotaAllRound, + CharacterActionType.CastSuperSkill => GameplayEquilibriumConstant.ActionQuotaSuperSkill + TempActionQuotaSuperSkill + TempActionQuotaAllRound, + CharacterActionType.CastSkill => GameplayEquilibriumConstant.ActionQuotaSkill + TempActionQuotaSkill + TempActionQuotaAllRound, CharacterActionType.PreCastSkill => GameplayEquilibriumConstant.ActionQuotaMagic, - CharacterActionType.UseItem => GameplayEquilibriumConstant.ActionQuotaItem + _tempActionQuotaItem, - _ => GameplayEquilibriumConstant.ActionQuotaOther + _tempActionQuotaOther, + CharacterActionType.UseItem => GameplayEquilibriumConstant.ActionQuotaItem + TempActionQuotaItem + TempActionQuotaAllRound, + _ => GameplayEquilibriumConstant.ActionQuotaOther + TempActionQuotaOther + TempActionQuotaAllRound, }; } } @@ -83,28 +120,21 @@ namespace Milimoe.FunGame.Core.Model /// /// 添加临时决策点配额 [ 回合结束时清除 ] /// + /// /// /// - public void AddTempActionQuota(CharacterActionType type, int add = 1) + public void AddTempActionQuota(Effect effect, CharacterActionType? type = null, int add = 1) { - switch (type) + Dictionary dict = type switch { - case CharacterActionType.NormalAttack: - _tempActionQuotaNormalAttack += add; - break; - case CharacterActionType.CastSkill: - _tempActionQuotaSkill += add; - break; - case CharacterActionType.CastSuperSkill: - _tempActionQuotaSuperSkill += add; - break; - case CharacterActionType.UseItem: - _tempActionQuotaItem += add; - break; - default: - _tempActionQuotaOther += add; - break; - } + null => _tempActionQuotaAllRound, + CharacterActionType.NormalAttack => _tempActionQuotaNormalAttack, + CharacterActionType.CastSkill => _tempActionQuotaSkill, + CharacterActionType.CastSuperSkill => _tempActionQuotaSuperSkill, + CharacterActionType.UseItem => _tempActionQuotaItem, + _ => _tempActionQuotaOther + }; + dict[effect] = dict.GetValueOrDefault(effect) + add; } /// @@ -112,25 +142,28 @@ namespace Milimoe.FunGame.Core.Model /// public void ClearTempActionQuota() { - _tempActionQuotaNormalAttack = 0; - _tempActionQuotaSuperSkill = 0; - _tempActionQuotaSkill = 0; - _tempActionQuotaItem = 0; - _tempActionQuotaOther = 0; + _tempActionQuotaAllRound.Clear(); + _tempActionQuotaNormalAttack.Clear(); + _tempActionQuotaSuperSkill.Clear(); + _tempActionQuotaSkill.Clear(); + _tempActionQuotaItem.Clear(); + _tempActionQuotaOther.Clear(); } /// /// 累计行动类型和次数 /// /// + /// /// - public void AddActionType(CharacterActionType type, bool addActionTaken = true) + public void AddActionType(CharacterActionType type, Skill? skill = null, bool addActionTaken = true) { if (addActionTaken) ActionsTaken++; if (!ActionTypes.TryAdd(type, 1)) { ActionTypes[type]++; } + DecisionPointsCost += GetActionPointCost(type, skill); } /// @@ -165,5 +198,30 @@ namespace Milimoe.FunGame.Core.Model _ => GameplayEquilibriumConstant.DecisionPointsCostOther }; } + + /// + /// 获取当前决策点信息 + /// + /// + public string GetDecisionPointsInfo() + { + StringBuilder builder = new(); + + builder.AppendLine($"===[ 决策点信息 ]==="); + builder.AppendLine($"当前决策点:{CurrentDecisionPoints} / {MaxDecisionPoints}"); + builder.AppendLine($"普通攻击决策点配额:{this[CharacterActionType.NormalAttack] - ActionTypes.GetValueOrDefault(CharacterActionType.NormalAttack)} / {this[CharacterActionType.NormalAttack]}"); + builder.AppendLine($"战技决策点配额:{this[CharacterActionType.CastSkill] - ActionTypes.GetValueOrDefault(CharacterActionType.CastSkill)} / {this[CharacterActionType.CastSkill]}"); + builder.AppendLine($"魔法决策点配额:{this[CharacterActionType.PreCastSkill] - ActionTypes.GetValueOrDefault(CharacterActionType.PreCastSkill)} / {this[CharacterActionType.PreCastSkill]}"); + builder.AppendLine($"爆发技决策点配额:{this[CharacterActionType.CastSuperSkill] - ActionTypes.GetValueOrDefault(CharacterActionType.CastSuperSkill)} / {this[CharacterActionType.CastSuperSkill]}"); + builder.AppendLine($"使用物品决策点配额:{this[CharacterActionType.UseItem] - ActionTypes.GetValueOrDefault(CharacterActionType.UseItem)} / {this[CharacterActionType.UseItem]}"); + + if (_tempActionQuotaAllRound.Count > 0) + { + builder.AppendLine($"全能决策点配额:你拥有以下全能决策点配额加成并已自动计入每个行动决策所需的配额中。"); + builder.AppendLine(string.Join("\r\n", _tempActionQuotaAllRound.Select(kv => $"{kv.Key.Name}:{kv.Value}"))); + } + + return builder.ToString(); + } } } diff --git a/Model/GamingQueue.cs b/Model/GamingQueue.cs index 1000854..7a10169 100644 --- a/Model/GamingQueue.cs +++ b/Model/GamingQueue.cs @@ -909,6 +909,7 @@ namespace Milimoe.FunGame.Core.Model effect.RemainDuration = 0; character.Effects.Remove(effect); effect.OnEffectLost(character); + WriteLine($"[ {character} ] 失去了 [ {effect.Name} ] 效果。"); } else { @@ -1346,15 +1347,15 @@ namespace Milimoe.FunGame.Core.Model character.CharacterState == CharacterState.BattleRestricted || character.CharacterState == CharacterState.AttackRestricted)) { - if (IsDebug) WriteLine($"角色 [ {character} ] 状态为:{CharacterSet.GetCharacterState(character.CharacterState)},无法使用普通攻击!"); + if (IsDebug) WriteLine($"[ {character} ] 的状态为:{CharacterSet.GetCharacterState(character.CharacterState)},无法使用普通攻击!"); } else if (dp.CurrentDecisionPoints < costDP) { - if (IsDebug) WriteLine($"角色 [ {character} ] 决策点不足,无法使用普通攻击!"); + if (IsDebug) WriteLine($"[ {character} ] 想要发起普通攻击,但决策点不足,无法使用普通攻击!"); } else if (!dp.CheckActionTypeQuota(CharacterActionType.NormalAttack)) { - if (IsDebug) WriteLine($"角色 [ {character} ] 该回合使用普通攻击的次数已超过决策点配额,无法再次使用普通攻击!"); + if (IsDebug) WriteLine($"[ {character} ] 想要发起普通攻击,但该回合使用普通攻击的次数已超过决策点配额,无法再次使用普通攻击!"); } else { @@ -1418,7 +1419,7 @@ namespace Milimoe.FunGame.Core.Model character.CharacterState == CharacterState.BattleRestricted || character.CharacterState == CharacterState.SkillRestricted)) { - if (IsDebug) WriteLine($"角色 [ {character} ] 状态为:{CharacterSet.GetCharacterState(character.CharacterState)},无法释放技能!"); + if (IsDebug) WriteLine($"[ {character} ] 的状态为:{CharacterSet.GetCharacterState(character.CharacterState)},无法释放技能!"); } else { @@ -1444,7 +1445,7 @@ namespace Milimoe.FunGame.Core.Model costDP = dp.GetActionPointCost(type, skill); if (dp.CurrentDecisionPoints < costDP) { - if (IsDebug) WriteLine($"角色 [ {character} ] 决策点不足,无法释放技能!"); + if (IsDebug) WriteLine($"[ {character} ] 想要释放 [ {skill.Name} ],但决策点不足,无法释放技能!"); } else if (skill.SkillType == SkillType.Magic) { @@ -1479,7 +1480,7 @@ namespace Milimoe.FunGame.Core.Model LastRound.ActionTypes.Add(CharacterActionType.PreCastSkill); _stats[statsCharacter].UseDecisionPoints += costDP; _stats[statsCharacter].TurnDecisions++; - dp.AddActionType(CharacterActionType.PreCastSkill); + dp.AddActionType(CharacterActionType.PreCastSkill, skill); dp.CurrentDecisionPoints -= costDP; decided = true; endTurn = true; @@ -1507,15 +1508,15 @@ namespace Milimoe.FunGame.Core.Model } else if (skill is CourageCommandSkill && dp.CourageCommandSkill) { - if (IsDebug) WriteLine($"角色 [ {character} ] 该回合已经使用过勇气指令,无法再次使用勇气指令!"); + if (IsDebug) WriteLine($"[ {character} ] 想要释放 [ {skill.Name} ],但该回合已经使用过勇气指令,无法再次使用勇气指令!"); } else if (skill is not CourageCommandSkill && !skill.IsSuperSkill && !dp.CheckActionTypeQuota(CharacterActionType.CastSkill)) { - if (IsDebug) WriteLine($"角色 [ {character} ] 该回合使用战技的次数已超过决策点配额,无法再次使用战技!"); + if (IsDebug) WriteLine($"[ {character} ] 想要释放 [ {skill.Name} ],但该回合使用战技的次数已超过决策点配额,无法再次使用战技!"); } else if (skill is not CourageCommandSkill && skill.IsSuperSkill && !dp.CheckActionTypeQuota(CharacterActionType.CastSuperSkill)) { - if (IsDebug) WriteLine($"角色 [ {character} ] 该回合使用爆发技的次数已超过决策点配额,无法再次使用爆发技!"); + if (IsDebug) WriteLine($"[ {character} ] 想要释放 [ {skill.Name} ],但该回合使用爆发技的次数已超过决策点配额,无法再次使用爆发技!"); } else { @@ -1553,7 +1554,7 @@ namespace Milimoe.FunGame.Core.Model { _stats[statsCharacter].UseDecisionPoints += costDP; _stats[statsCharacter].TurnDecisions++; - dp.AddActionType(skillType); + dp.AddActionType(skillType, skill); dp.CurrentDecisionPoints -= costDP; } else @@ -1799,11 +1800,11 @@ namespace Milimoe.FunGame.Core.Model } if (dp.CurrentDecisionPoints < costDP) { - if (IsDebug) WriteLine($"角色 [ {character} ] 决策点不足,无法使用物品!"); + if (IsDebug) WriteLine($"[ {character} ] 想要使用物品 [ {item.Name} ],但决策点不足,无法使用物品!"); } else if (!dp.CheckActionTypeQuota(CharacterActionType.UseItem)) { - if (IsDebug) WriteLine($"角色 [ {character} ] 该回合使用物品的次数已超过决策点配额,无法再使用物品!"); + if (IsDebug) WriteLine($"[ {character} ] 想要使用物品 [ {item.Name} ],但该回合使用物品的次数已超过决策点配额,无法再使用物品!"); } else if (UseItem(item, character, dp, enemys, teammates, castRange, allEnemys, allTeammates, aiDecision)) { @@ -1834,7 +1835,7 @@ namespace Milimoe.FunGame.Core.Model } else { - if (baseTime == 0) baseTime += 8; + if (baseTime == 0) baseTime += 7; decided = true; endTurn = true; WriteLine($"[ {character} ] 完全行动不能!"); @@ -1849,7 +1850,7 @@ namespace Milimoe.FunGame.Core.Model if (!decided && (isAI || cancelTimes == 0)) { endTurn = true; - baseTime += 5; + baseTime += 4; type = CharacterActionType.EndTurn; } @@ -1878,7 +1879,7 @@ namespace Milimoe.FunGame.Core.Model if (character.CharacterState != CharacterState.Casting && dp.ActionsHardnessTime.Count > 0) { - baseTime = dp.ActionsTaken > 1 ? (dp.ActionsHardnessTime.Max() + dp.ActionsTaken) : dp.ActionsHardnessTime.Max(); + baseTime = dp.ActionsTaken > 1 ? (dp.ActionsHardnessTime.Max() + dp.DecisionPointsCost) : dp.ActionsHardnessTime.Max(); } if (character.Master is null) @@ -1952,6 +1953,7 @@ namespace Milimoe.FunGame.Core.Model effect.RemainDurationTurn = 0; character.Effects.Remove(effect); effect.OnEffectLost(character); + WriteLine($"[ {character} ] 失去了 [ {effect.Name} ] 效果。"); } } } @@ -2778,7 +2780,7 @@ namespace Milimoe.FunGame.Core.Model bool isDead = target.HP <= 0; List healStrings = []; - healStrings.Add($"{heal:0.##}(基础)"); + healStrings.Add($"{heal:0.##}({(skill is null ? $"生命偷取:{actor.Lifesteal * 100:0.##}%" : skill.Name)})"); if (triggerEffects) { @@ -3742,7 +3744,7 @@ namespace Milimoe.FunGame.Core.Model character.CharacterState == CharacterState.ActionRestricted || character.CharacterState == CharacterState.BattleRestricted) { - baseTime += 3; + baseTime += 2; WriteLine($"[ {character} ] {CharacterSet.GetCharacterState(character.CharacterState)},放弃行动将额外获得 3 {GameplayEquilibriumConstant.InGameTime}硬直时间!"); } } @@ -3771,6 +3773,7 @@ namespace Milimoe.FunGame.Core.Model dp.ActionsHardnessTime.Clear(); dp.ActionTypes.Clear(); dp.ActionsTaken = 0; + dp.DecisionPointsCost = 0; // 根据角色状态补充决策点 int pointsToAdd;