diff --git a/Controller/AIController.cs b/Controller/AIController.cs
index 6f3236b..266b659 100644
--- a/Controller/AIController.cs
+++ b/Controller/AIController.cs
@@ -24,11 +24,29 @@ namespace Milimoe.FunGame.Core.Controller
/// 场上所有队友
/// 场上能够选取的敌人
/// 场上能够选取的队友
+ /// 使用物品的概率
+ /// 释放技能的概率
+ /// 普通攻击的概率
/// 包含最佳行动的AIDecision对象
public AIDecision DecideAIAction(Character character, DecisionPoints dp, Grid startGrid, List allPossibleMoveGrids,
List availableSkills, List- availableItems, List allEnemysInGame, List allTeammatesInGame,
- List selectableEnemys, List selectableTeammates)
+ List selectableEnemys, List selectableTeammates, double pUseItem, double pCastSkill, double pNormalAttack)
{
+ // 动态调整概率
+ double dynamicPUseItem = pUseItem;
+ double dynamicPCastSkill = pCastSkill;
+ double dynamicPNormalAttack = pNormalAttack;
+ AdjustProbabilitiesBasedOnContext(ref dynamicPUseItem, ref dynamicPCastSkill, ref dynamicPNormalAttack, character, allEnemysInGame, allTeammatesInGame);
+
+ // 归一化概率
+ double[] normalizedProbs = NormalizeProbabilities(dynamicPUseItem, dynamicPCastSkill, dynamicPNormalAttack);
+ double normalizedPUseItem = normalizedProbs[0];
+ double normalizedPCastSkill = normalizedProbs[1];
+ double normalizedPNormalAttack = normalizedProbs[2];
+
+ // 获取偏好行动类型
+ CharacterActionType? preferredAction = GetPreferredActionType(pUseItem, pCastSkill, pNormalAttack);
+
// 初始化一个默认的“结束回合”决策作为基准
AIDecision bestDecision = new()
{
@@ -38,6 +56,9 @@ namespace Milimoe.FunGame.Core.Controller
Score = -1000.0
};
+ // 候选决策
+ List candidateDecisions = [];
+
// 遍历所有可能的移动目标格子 (包括起始格子本身)
foreach (Grid potentialMoveGrid in allPossibleMoveGrids)
{
@@ -45,75 +66,79 @@ namespace Milimoe.FunGame.Core.Controller
int moveDistance = GameMap.CalculateManhattanDistance(startGrid, potentialMoveGrid);
double movePenalty = moveDistance * 0.5; // 每移动一步扣0.5分
- if (CanCharacterNormalAttack(character, dp))
+ if (pNormalAttack > 0)
{
- // 计算普通攻击的可达格子
- List normalAttackReachableGrids = _map.GetGridsByRange(potentialMoveGrid, character.ATR, true);
-
- List normalAttackReachableEnemys = [.. allEnemysInGame.Where(c => normalAttackReachableGrids.SelectMany(g => g.Characters).Contains(c) && !c.IsUnselectable && selectableEnemys.Contains(c)).Distinct()];
- List normalAttackReachableTeammates = [.. allTeammatesInGame.Where(c => normalAttackReachableGrids.SelectMany(g => g.Characters).Contains(c) && selectableTeammates.Contains(c)).Distinct()];
-
- if (normalAttackReachableEnemys.Count > 0)
+ if (CanCharacterNormalAttack(character, dp))
{
- // 将筛选后的目标列表传递给 SelectTargets
- List targets = SelectTargets(character, character.NormalAttack, normalAttackReachableEnemys, normalAttackReachableTeammates);
- if (targets.Count > 0)
+ // 计算普通攻击的可达格子
+ List normalAttackReachableGrids = _map.GetGridsByRange(potentialMoveGrid, character.ATR, true);
+
+ List normalAttackReachableEnemys = [.. allEnemysInGame.Where(c => normalAttackReachableGrids.SelectMany(g => g.Characters).Contains(c) && !c.IsUnselectable && selectableEnemys.Contains(c)).Distinct()];
+ List normalAttackReachableTeammates = [.. allTeammatesInGame.Where(c => normalAttackReachableGrids.SelectMany(g => g.Characters).Contains(c) && selectableTeammates.Contains(c)).Distinct()];
+
+ if (normalAttackReachableEnemys.Count > 0)
{
- double currentScore = EvaluateNormalAttack(character, targets) - movePenalty;
- if (currentScore > bestDecision.Score)
+ // 将筛选后的目标列表传递给 SelectTargets
+ List targets = SelectTargets(character, character.NormalAttack, normalAttackReachableEnemys, normalAttackReachableTeammates);
+ if (targets.Count > 0)
{
- bestDecision = new AIDecision
+ double currentScore = EvaluateNormalAttack(character, targets) - movePenalty;
+ double probabilityWeight = 1.0 + (normalizedPNormalAttack * 0.3);
+ candidateDecisions.Add(new AIDecision
{
ActionType = CharacterActionType.NormalAttack,
TargetMoveGrid = potentialMoveGrid,
SkillToUse = character.NormalAttack,
Targets = targets,
- Score = currentScore
- };
+ Score = currentScore,
+ ProbabilityWeight = probabilityWeight
+ });
}
}
}
}
- foreach (Skill skill in availableSkills)
+ if (pCastSkill > 0)
{
- if (CanCharacterUseSkill(character, skill, dp) && _queue.CheckCanCast(character, skill, out double cost))
+ foreach (Skill skill in availableSkills)
{
- // 计算当前技能的可达格子
- List skillReachableGrids = _map.GetGridsByRange(potentialMoveGrid, skill.CastRange, true);
-
- if (skill.IsNonDirectional)
+ if (CanCharacterUseSkill(character, skill, dp) && _queue.CheckCanCast(character, skill, out double cost))
{
- AIDecision? nonDirDecision = EvaluateNonDirectionalSkill(character, skill, potentialMoveGrid, skillReachableGrids, allEnemysInGame, allTeammatesInGame, cost);
+ // 计算当前技能的可达格子
+ List skillReachableGrids = _map.GetGridsByRange(potentialMoveGrid, skill.CastRange, true);
- if (nonDirDecision != null && nonDirDecision.Score > bestDecision.Score)
+ if (skill.IsNonDirectional)
{
- bestDecision = nonDirDecision;
- }
- }
- else
- {
- List skillReachableEnemys = [.. allEnemysInGame.Where(c => skillReachableGrids.SelectMany(g => g.Characters).Contains(c) && !c.IsUnselectable && selectableEnemys.Contains(c)).Distinct()];
- List skillReachableTeammates = [.. allTeammatesInGame.Where(c => skillReachableGrids.SelectMany(g => g.Characters).Contains(c) && selectableTeammates.Contains(c)).Distinct()];
+ AIDecision? nonDirDecision = EvaluateNonDirectionalSkill(character, skill, potentialMoveGrid, skillReachableGrids, allEnemysInGame, allTeammatesInGame, cost);
- // 检查是否有可用的目标(敌人或队友,取决于技能类型)
- if (skillReachableEnemys.Count > 0 || skillReachableTeammates.Count > 0)
- {
- // 将筛选后的目标列表传递给 SelectTargets
- List targets = SelectTargets(character, skill, skillReachableEnemys, skillReachableTeammates);
- if (targets.Count > 0)
+ if (nonDirDecision != null && nonDirDecision.Score > bestDecision.Score)
{
- double currentScore = EvaluateSkill(character, skill, targets, cost) - movePenalty;
- if (currentScore > bestDecision.Score)
+ bestDecision = nonDirDecision;
+ }
+ }
+ else
+ {
+ List skillReachableEnemys = [.. allEnemysInGame.Where(c => skillReachableGrids.SelectMany(g => g.Characters).Contains(c) && !c.IsUnselectable && selectableEnemys.Contains(c)).Distinct()];
+ List skillReachableTeammates = [.. allTeammatesInGame.Where(c => skillReachableGrids.SelectMany(g => g.Characters).Contains(c) && selectableTeammates.Contains(c)).Distinct()];
+
+ // 检查是否有可用的目标(敌人或队友,取决于技能类型)
+ if (skillReachableEnemys.Count > 0 || skillReachableTeammates.Count > 0)
+ {
+ // 将筛选后的目标列表传递给 SelectTargets
+ List targets = SelectTargets(character, skill, skillReachableEnemys, skillReachableTeammates);
+ if (targets.Count > 0)
{
- bestDecision = new AIDecision
+ double currentScore = EvaluateSkill(character, skill, targets, cost) - movePenalty;
+ double probabilityWeight = 1.0 + (normalizedPCastSkill * 0.3);
+ candidateDecisions.Add(new AIDecision
{
ActionType = CharacterActionType.PreCastSkill,
TargetMoveGrid = potentialMoveGrid,
SkillToUse = skill,
Targets = targets,
- Score = currentScore
- };
+ Score = currentScore,
+ ProbabilityWeight = probabilityWeight
+ });
}
}
}
@@ -121,48 +146,50 @@ namespace Milimoe.FunGame.Core.Controller
}
}
- foreach (Item item in availableItems)
+ if (pUseItem > 0)
{
- if (item.Skills.Active != null && CanCharacterUseItem(character, item, dp) && _queue.CheckCanCast(character, item.Skills.Active, out double cost))
+ foreach (Item item in availableItems)
{
- Skill itemSkill = item.Skills.Active;
-
- // 计算当前物品技能的可达格子
- List itemSkillReachableGrids = _map.GetGridsByRange(potentialMoveGrid, itemSkill.CastRange, true);
-
- if (itemSkill.IsNonDirectional)
+ if (item.Skills.Active != null && CanCharacterUseItem(character, item, dp) && _queue.CheckCanCast(character, item.Skills.Active, out double cost))
{
- AIDecision? nonDirDecision = EvaluateNonDirectionalSkill(character, itemSkill, potentialMoveGrid, itemSkillReachableGrids, allEnemysInGame, allTeammatesInGame, cost);
+ Skill itemSkill = item.Skills.Active;
- if (nonDirDecision != null && nonDirDecision.Score > bestDecision.Score)
- {
- bestDecision = nonDirDecision;
- }
- }
- else
- {
- List itemSkillReachableEnemys = [.. allEnemysInGame.Where(c => itemSkillReachableGrids.SelectMany(g => g.Characters).Contains(c) && !c.IsUnselectable && selectableEnemys.Contains(c)).Distinct()];
- List itemSkillReachableTeammates = [.. allTeammatesInGame.Where(c => itemSkillReachableGrids.SelectMany(g => g.Characters).Contains(c) && selectableTeammates.Contains(c)).Distinct()];
+ // 计算当前物品技能的可达格子
+ List itemSkillReachableGrids = _map.GetGridsByRange(potentialMoveGrid, itemSkill.CastRange, true);
- // 检查是否有可用的目标
- if (itemSkillReachableEnemys.Count > 0 || itemSkillReachableTeammates.Count > 0)
+ if (itemSkill.IsNonDirectional)
{
- // 将筛选后的目标列表传递给 SelectTargets
- List targetsForItem = SelectTargets(character, itemSkill, itemSkillReachableEnemys, itemSkillReachableTeammates);
- if (targetsForItem.Count > 0)
+ AIDecision? nonDirDecision = EvaluateNonDirectionalSkill(character, itemSkill, potentialMoveGrid, itemSkillReachableGrids, allEnemysInGame, allTeammatesInGame, cost);
+
+ if (nonDirDecision != null && nonDirDecision.Score > bestDecision.Score)
{
- double currentScore = EvaluateItem(character, item, targetsForItem, cost) - movePenalty;
- if (currentScore > bestDecision.Score)
+ bestDecision = nonDirDecision;
+ }
+ }
+ else
+ {
+ List itemSkillReachableEnemys = [.. allEnemysInGame.Where(c => itemSkillReachableGrids.SelectMany(g => g.Characters).Contains(c) && !c.IsUnselectable && selectableEnemys.Contains(c)).Distinct()];
+ List itemSkillReachableTeammates = [.. allTeammatesInGame.Where(c => itemSkillReachableGrids.SelectMany(g => g.Characters).Contains(c) && selectableTeammates.Contains(c)).Distinct()];
+
+ // 检查是否有可用的目标
+ if (itemSkillReachableEnemys.Count > 0 || itemSkillReachableTeammates.Count > 0)
+ {
+ // 将筛选后的目标列表传递给 SelectTargets
+ List targetsForItem = SelectTargets(character, itemSkill, itemSkillReachableEnemys, itemSkillReachableTeammates);
+ if (targetsForItem.Count > 0)
{
- bestDecision = new AIDecision
+ double currentScore = EvaluateItem(character, item, targetsForItem, cost) - movePenalty;
+ double probabilityWeight = 1.0 + (normalizedPUseItem * 0.3);
+ candidateDecisions.Add(new AIDecision
{
ActionType = CharacterActionType.UseItem,
TargetMoveGrid = potentialMoveGrid,
ItemToUse = item,
SkillToUse = itemSkill,
Targets = targetsForItem,
- Score = currentScore
- };
+ Score = currentScore,
+ ProbabilityWeight = probabilityWeight
+ });
}
}
}
@@ -209,19 +236,30 @@ namespace Milimoe.FunGame.Core.Controller
}
}
- // 如果纯粹移动比当前最佳(什么都不做)更好
- if (pureMoveScore > bestDecision.Score)
+ candidateDecisions.Add(new AIDecision
{
- bestDecision = new AIDecision
+ ActionType = CharacterActionType.Move,
+ TargetMoveGrid = potentialMoveGrid,
+ Targets = [],
+ Score = pureMoveScore,
+ IsPureMove = true
+ });
+ }
+
+ // 偏好类型额外加分
+ if (preferredAction.HasValue)
+ {
+ foreach (var decision in candidateDecisions)
+ {
+ if (decision.ActionType == preferredAction.Value)
{
- ActionType = CharacterActionType.Move,
- TargetMoveGrid = potentialMoveGrid,
- Targets = [],
- Score = pureMoveScore,
- IsPureMove = true
- };
+ decision.Score *= 1.2;
+ }
}
}
+
+ // 最终决策
+ bestDecision = candidateDecisions.OrderByDescending(d => d.Score * d.ProbabilityWeight).FirstOrDefault() ?? bestDecision;
}
return bestDecision;
@@ -229,6 +267,79 @@ namespace Milimoe.FunGame.Core.Controller
// --- AI 决策辅助方法 ---
+ // 获取偏好行动类型
+ private static CharacterActionType? GetPreferredActionType(double pItem, double pSkill, double pAttack)
+ {
+ // 找出最高概率的行动类型
+ Dictionary probabilities = new()
+ {
+ { CharacterActionType.UseItem, pItem },
+ { CharacterActionType.PreCastSkill, pSkill },
+ { CharacterActionType.NormalAttack, pAttack }
+ };
+
+ double maxProb = probabilities.Values.Max();
+ if (maxProb > 0)
+ {
+ CharacterActionType preferredType = probabilities.FirstOrDefault(kvp => kvp.Value == maxProb).Key;
+
+ // 如果最高概率超过阈值,优先考虑该类型
+ if (maxProb > 0.7)
+ {
+ return preferredType;
+ }
+ }
+
+ return null;
+ }
+
+ // 动态调整概率
+ private static void AdjustProbabilitiesBasedOnContext(ref double pUseItem, ref double pCastSkill, ref double pNormalAttack, Character character, List allEnemysInGame, List allTeammatesInGame)
+ {
+ // 基于角色状态调整
+ if (character.HP / character.MaxHP < 0.3 || allTeammatesInGame.Any(c => c.HP / c.MaxHP < 0.3))
+ {
+ // 低生命值时增加使用物品概率
+ if (pUseItem > 0) pUseItem *= 1.5;
+ if (pCastSkill > 0) pCastSkill *= 0.7;
+ }
+
+ // 基于敌人数量调整
+ int enemyCount = allEnemysInGame.Count;
+ if (enemyCount > 3)
+ {
+ // 敌人多时倾向于范围技能
+ if (pCastSkill > 0) pCastSkill *= 1.3;
+ }
+ else if (enemyCount == 1)
+ {
+ // 单个敌人时倾向于普通攻击
+ if (pNormalAttack > 0) pNormalAttack *= 1.2;
+ }
+
+ if (pUseItem > 0) pUseItem = Math.Max(0, pUseItem);
+ if (pCastSkill > 0) pCastSkill = Math.Max(0, pCastSkill);
+ if (pNormalAttack > 0) pNormalAttack = Math.Max(0, pNormalAttack);
+ }
+
+ // / 归一化概率分布
+ private static double[] NormalizeProbabilities(double pUseItem, double pCastSkill, double pNormalAttack)
+ {
+ if (pUseItem <= 0 && pCastSkill <= 0 && pNormalAttack <= 0)
+ {
+ return [0, 0, 0];
+ }
+
+ double sum = pUseItem + pCastSkill + pNormalAttack;
+ if (sum <= 0) return [0.33, 0.33, 0.34];
+
+ return [
+ pUseItem / sum,
+ pCastSkill / sum,
+ pNormalAttack / sum
+ ];
+ }
+
// 检查角色是否能进行普通攻击(基于状态)
private static bool CanCharacterNormalAttack(Character character, DecisionPoints dp)
{
diff --git a/Entity/Character/Character.cs b/Entity/Character/Character.cs
index 225ed4e..4f17db5 100644
--- a/Entity/Character/Character.cs
+++ b/Entity/Character/Character.cs
@@ -1283,7 +1283,7 @@ namespace Milimoe.FunGame.Core.Entity
}
if (isUp)
{
- Effect[] effects = [.. Effects.Where(e => e.IsInEffect)];
+ Effect[] effects = [.. Effects.Where(e => e.IsInEffect).OrderByDescending(e => e.Priority)];
foreach (Effect e in effects)
{
e.OnOwnerLevelUp(this, Level);
@@ -1312,7 +1312,7 @@ namespace Milimoe.FunGame.Core.Entity
///
public void OnAttributeChanged()
{
- List effects = [.. Effects.Where(e => e.IsInEffect)];
+ List effects = [.. Effects.Where(e => e.IsInEffect).OrderByDescending(e => e.Priority)];
foreach (Effect effect in effects)
{
effect.OnAttributeChanged(this);
@@ -1447,41 +1447,8 @@ namespace Milimoe.FunGame.Core.Entity
builder.AppendLine($"等级:{Level} / {GameplayEquilibriumConstant.MaxLevel}(突破进度:{LevelBreak + 1} / {GameplayEquilibriumConstant.LevelBreakList.Count})");
builder.AppendLine($"经验值:{EXP:0.##}{(Level != GameplayEquilibriumConstant.MaxLevel && GameplayEquilibriumConstant.EXPUpperLimit.TryGetValue(Level, out double need) ? " / " + need : "")}");
}
- double exHP = ExHP + ExHP2 + ExHP3;
- List shield = [];
- if (Shield.TotalPhysical > 0) shield.Add($"物理:{Shield.TotalPhysical:0.##}");
- if (Shield.TotalMagical > 0) shield.Add($"魔法:{Shield.TotalMagical:0.##}");
- if (Shield.TotalMix > 0) shield.Add($"混合:{Shield.TotalMix:0.##}");
- builder.AppendLine($"生命值:{HP:0.##} / {MaxHP:0.##}" + (exHP != 0 ? $" [{BaseHP:0.##} {(exHP >= 0 ? "+" : "-")} {Math.Abs(exHP):0.##}]" : "") + (shield.Count > 0 ? $"({string.Join(",", shield)})" : ""));
- double exMP = ExMP + ExMP2 + ExMP3;
- builder.AppendLine($"魔法值:{MP:0.##} / {MaxMP:0.##}" + (exMP != 0 ? $" [{BaseMP:0.##} {(exMP >= 0 ? "+" : "-")} {Math.Abs(exMP):0.##}]" : ""));
- builder.AppendLine($"能量值:{EP:0.##} / {GameplayEquilibriumConstant.MaxEP:0.##}");
- double exATK = ExATK + ExATK2 + ExATK3;
- builder.AppendLine($"攻击力:{ATK:0.##}" + (exATK != 0 ? $" [{BaseATK:0.##} {(exATK >= 0 ? "+" : "-")} {Math.Abs(exATK):0.##}]" : ""));
- double exDEF = ExDEF + ExDEF2 + ExDEF3;
- builder.AppendLine($"物理护甲:{DEF:0.##}" + (exDEF != 0 ? $" [{BaseDEF:0.##} {(exDEF >= 0 ? "+" : "-")} {Math.Abs(exDEF):0.##}]" : "") + $" ({PDR * 100:0.##}%)");
- builder.AppendLine(GetMagicResistanceInfo().Trim());
- double exSPD = AGI * GameplayEquilibriumConstant.AGItoSPDMultiplier + ExSPD;
- builder.AppendLine($"行动速度:{SPD:0.##}" + (exSPD != 0 ? $" [{InitialSPD:0.##} {(exSPD >= 0 ? "+" : "-")} {Math.Abs(exSPD):0.##}]" : "") + $" ({ActionCoefficient * 100:0.##}%)");
- builder.AppendLine($"核心属性:{CharacterSet.GetPrimaryAttributeName(PrimaryAttribute)}");
- double exSTR = ExSTR + ExSTR2;
- builder.AppendLine($"力量:{STR:0.##}" + (exSTR != 0 ? $" [{BaseSTR:0.##} {(exSTR >= 0 ? "+" : "-")} {Math.Abs(exSTR):0.##}]" : "") + (showGrowth ? $"({(STRGrowth >= 0 ? "+" : "-")}{Math.Abs(STRGrowth)}/Lv)" : "") + $"({STRExemption * 100:0.##}%)");
- double exAGI = ExAGI + ExAGI2;
- builder.AppendLine($"敏捷:{AGI:0.##}" + (exAGI != 0 ? $" [{BaseAGI:0.##} {(exAGI >= 0 ? "+" : "-")} {Math.Abs(exAGI):0.##}]" : "") + (showGrowth ? $"({(AGIGrowth >= 0 ? "+" : "-")}{Math.Abs(AGIGrowth)}/Lv)" : "") + $"({AGIExemption * 100:0.##}%)");
- double exINT = ExINT + ExINT2;
- builder.AppendLine($"智力:{INT:0.##}" + (exINT != 0 ? $" [{BaseINT:0.##} {(exINT >= 0 ? "+" : "-")} {Math.Abs(exINT):0.##}]" : "") + (showGrowth ? $"({(INTGrowth >= 0 ? "+" : "-")}{Math.Abs(INTGrowth)}/Lv)" : "") + $"({INTExemption * 100:0.##}%)");
- builder.AppendLine($"生命回复:{HR:0.##}" + (ExHR != 0 ? $" [{InitialHR + STR * GameplayEquilibriumConstant.STRtoHRFactor:0.##} {(ExHR >= 0 ? "+" : "-")} {Math.Abs(ExHR):0.##}]" : ""));
- builder.AppendLine($"魔法回复:{MR:0.##}" + (ExMR != 0 ? $" [{InitialMR + INT * GameplayEquilibriumConstant.INTtoMRFactor:0.##} {(ExMR >= 0 ? "+" : "-")} {Math.Abs(ExMR):0.##}]" : ""));
- builder.AppendLine($"暴击率:{CritRate * 100:0.##}%");
- builder.AppendLine($"暴击伤害:{CritDMG * 100:0.##}%");
- builder.AppendLine($"闪避率:{EvadeRate * 100:0.##}%");
- builder.AppendLine($"生命偷取:{Lifesteal * 100:0.##}%");
- builder.AppendLine($"冷却缩减:{CDR * 100:0.##}%");
- builder.AppendLine($"加速系数:{AccelerationCoefficient * 100:0.##}%");
- builder.AppendLine($"物理穿透:{PhysicalPenetration * 100:0.##}%");
- builder.AppendLine($"魔法穿透:{MagicalPenetration * 100:0.##}%");
- builder.AppendLine($"魔法消耗减少:{INT * GameplayEquilibriumConstant.INTtoCastMPReduce * 100:0.##}%");
- builder.AppendLine($"能量消耗减少:{INT * GameplayEquilibriumConstant.INTtoCastEPReduce * 100:0.##}%");
+
+ builder.AppendLine(GetAttributeInfo(showGrowth).Trim());
if (showMapRelated)
{
@@ -1489,7 +1456,7 @@ namespace Milimoe.FunGame.Core.Entity
builder.AppendLine($"攻击距离:{ATR}");
}
- GetStatusInfo(builder);
+ builder.AppendLine(GetStatusInfo().Trim());
builder.AppendLine("== 普通攻击 ==");
builder.Append(NormalAttack.ToString());
@@ -1541,38 +1508,8 @@ namespace Milimoe.FunGame.Core.Entity
builder.AppendLine($"等级:{Level} / {GameplayEquilibriumConstant.MaxLevel}(突破进度:{LevelBreak + 1} / {GameplayEquilibriumConstant.LevelBreakList.Count})");
builder.AppendLine($"经验值:{EXP:0.##}{(Level != GameplayEquilibriumConstant.MaxLevel && GameplayEquilibriumConstant.EXPUpperLimit.TryGetValue(Level, out double need) ? " / " + need : "")}");
}
- double exHP = ExHP + ExHP2 + ExHP3;
- List shield = [];
- if (Shield.TotalPhysical > 0) shield.Add($"物理:{Shield.TotalPhysical:0.##}");
- if (Shield.TotalMagical > 0) shield.Add($"魔法:{Shield.TotalMagical:0.##}");
- if (Shield.TotalMix > 0) shield.Add($"混合:{Shield.TotalMix:0.##}");
- builder.AppendLine($"生命值:{HP:0.##} / {MaxHP:0.##}" + (exHP != 0 ? $" [{BaseHP:0.##} {(exHP >= 0 ? "+" : "-")} {Math.Abs(exHP):0.##}]" : "") + (shield.Count > 0 ? $"({string.Join(",", shield)})" : ""));
- double exMP = ExMP + ExMP2 + ExMP3;
- builder.AppendLine($"魔法值:{MP:0.##} / {MaxMP:0.##}" + (exMP != 0 ? $" [{BaseMP:0.##} {(exMP >= 0 ? "+" : "-")} {Math.Abs(exMP):0.##}]" : ""));
- builder.AppendLine($"能量值:{EP:0.##} / {GameplayEquilibriumConstant.MaxEP:0.##}");
- double exATK = ExATK + ExATK2 + ExATK3;
- builder.AppendLine($"攻击力:{ATK:0.##}" + (exATK != 0 ? $" [{BaseATK:0.##} {(exATK >= 0 ? "+" : "-")} {Math.Abs(exATK):0.##}]" : ""));
- double exDEF = ExDEF + ExDEF2 + ExDEF3;
- builder.AppendLine($"物理护甲:{DEF:0.##}" + (exDEF != 0 ? $" [{BaseDEF:0.##} {(exDEF >= 0 ? "+" : "-")} {Math.Abs(exDEF):0.##}]" : "") + $" ({PDR * 100:0.##}%)");
- builder.AppendLine(GetMagicResistanceInfo().Trim());
- if (showBasicOnly)
- {
- builder.AppendLine($"核心属性:{PrimaryAttributeValue:0.##}({CharacterSet.GetPrimaryAttributeName(PrimaryAttribute)})");
- }
- else
- {
- double exSPD = AGI * GameplayEquilibriumConstant.AGItoSPDMultiplier + ExSPD;
- builder.AppendLine($"行动速度:{SPD:0.##}" + (exSPD != 0 ? $" [{InitialSPD:0.##} {(exSPD >= 0 ? "+" : "-")} {Math.Abs(exSPD):0.##}]" : "") + $" ({ActionCoefficient * 100:0.##}%)");
- builder.AppendLine($"核心属性:{CharacterSet.GetPrimaryAttributeName(PrimaryAttribute)}");
- double exSTR = ExSTR + ExSTR2;
- builder.AppendLine($"力量:{STR:0.##}" + (exSTR != 0 ? $" [{BaseSTR:0.##} {(exSTR >= 0 ? "+" : "-")} {Math.Abs(exSTR):0.##}]" : "") + (showGrowth ? $"({(STRGrowth >= 0 ? "+" : "-")}{Math.Abs(STRGrowth)}/Lv)" : "") + $"({STRExemption * 100:0.##}%)");
- double exAGI = ExAGI + ExAGI2;
- builder.AppendLine($"敏捷:{AGI:0.##}" + (exAGI != 0 ? $" [{BaseAGI:0.##} {(exAGI >= 0 ? "+" : "-")} {Math.Abs(exAGI):0.##}]" : "") + (showGrowth ? $"({(AGIGrowth >= 0 ? "+" : "-")}{Math.Abs(AGIGrowth)}/Lv)" : "") + $"({AGIExemption * 100:0.##}%)");
- double exINT = ExINT + ExINT2;
- builder.AppendLine($"智力:{INT:0.##}" + (exINT != 0 ? $" [{BaseINT:0.##} {(exINT >= 0 ? "+" : "-")} {Math.Abs(exINT):0.##}]" : "") + (showGrowth ? $"({(INTGrowth >= 0 ? "+" : "-")}{Math.Abs(INTGrowth)}/Lv)" : "") + $"({INTExemption * 100:0.##}%)");
- }
- builder.AppendLine($"生命回复:{HR:0.##}" + (ExHR != 0 ? $" [{InitialHR + STR * GameplayEquilibriumConstant.STRtoHRFactor:0.##} {(ExHR >= 0 ? "+" : "-")} {Math.Abs(ExHR):0.##}]" : ""));
- builder.AppendLine($"魔法回复:{MR:0.##}" + (ExMR != 0 ? $" [{InitialMR + INT * GameplayEquilibriumConstant.INTtoMRFactor:0.##} {(ExMR >= 0 ? "+" : "-")} {Math.Abs(ExMR):0.##}]" : ""));
+
+ builder.AppendLine(GetSimpleAttributeInfo(showGrowth, showBasicOnly).Trim());
if (showMapRelated)
{
@@ -1582,7 +1519,7 @@ namespace Milimoe.FunGame.Core.Entity
if (!showBasicOnly)
{
- GetStatusInfo(builder);
+ builder.AppendLine(GetStatusInfo().Trim());
if (Skills.Count > 0)
{
@@ -1636,26 +1573,16 @@ namespace Milimoe.FunGame.Core.Entity
/// 获取战斗状态的信息
///
///
+ ///
///
- public string GetInBattleInfo(double hardnessTimes)
+ public string GetInBattleInfo(double hardnessTimes, bool simpleStatusBar = false)
{
StringBuilder builder = new();
builder.AppendLine((HP == 0 ? "[ 死亡 ] " : "") + ToStringWithLevel());
- double exHP = ExHP + ExHP2 + ExHP3;
- List shield = [];
- if (Shield.TotalPhysical > 0) shield.Add($"物理:{Shield.TotalPhysical:0.##}");
- if (Shield.TotalMagical > 0) shield.Add($"魔法:{Shield.TotalMagical:0.##}");
- if (Shield.TotalMix > 0) shield.Add($"混合:{Shield.TotalMix:0.##}");
- builder.AppendLine($"生命值:{HP:0.##} / {MaxHP:0.##}" + (exHP != 0 ? $" [{BaseHP:0.##} {(exHP >= 0 ? "+" : "-")} {Math.Abs(exHP):0.##}]" : "") + (shield.Count > 0 ? $"({string.Join(",", shield)})" : ""));
- double exMP = ExMP + ExMP2 + ExMP3;
- builder.AppendLine($"魔法值:{MP:0.##} / {MaxMP:0.##}" + (exMP != 0 ? $" [{BaseMP:0.##} {(exMP >= 0 ? "+" : "-")} {Math.Abs(exMP):0.##}]" : ""));
- builder.AppendLine($"能量值:{EP:0.##} / {GameplayEquilibriumConstant.MaxEP:0.##}");
- double exATK = ExATK + ExATK2 + ExATK3;
- builder.AppendLine($"攻击力:{ATK:0.##}" + (exATK != 0 ? $" [{BaseATK:0.##} {(exATK >= 0 ? "+" : "-")} {Math.Abs(exATK):0.##}]" : ""));
- builder.AppendLine($"核心属性:{PrimaryAttributeValue:0.##}" + (ExPrimaryAttributeValue != 0 ? $" [{BasePrimaryAttributeValue:0.##} {(ExPrimaryAttributeValue >= 0 ? "+" : "-")} {Math.Abs(ExPrimaryAttributeValue):0.##}]" : ""));
- GetStatusInfo(builder);
+ builder.AppendLine(GetSimpleAttributeInfo(false, true).Trim());
+ builder.AppendLine(GetStatusInfo().Trim());
builder.AppendLine($"硬直时间:{hardnessTimes:0.##}");
@@ -1663,49 +1590,22 @@ namespace Milimoe.FunGame.Core.Entity
if (effects.Length > 0)
{
builder.AppendLine("== 状态栏 ==");
- foreach (Effect effect in effects)
+ if (simpleStatusBar)
{
- builder.AppendLine(effect.ToString());
+ builder.Append(string.Join(",", effects.Select(e => e.Name)));
+ }
+ else
+ {
+ foreach (Effect effect in effects)
+ {
+ builder.AppendLine(effect.ToString());
+ }
}
}
return builder.ToString().Trim();
}
- ///
- /// 获取战斗状态的信息(简略版)
- ///
- ///
- ///
- public string GetSimpleInBattleInfo(double hardnessTimes)
- {
- StringBuilder builder = new();
-
- builder.AppendLine((HP == 0 ? "[ 死亡 ] " : "") + ToStringWithLevel());
- double exHP = ExHP + ExHP2 + ExHP3;
- List shield = [];
- if (Shield.TotalPhysical > 0) shield.Add($"物理:{Shield.TotalPhysical:0.##}");
- if (Shield.TotalMagical > 0) shield.Add($"魔法:{Shield.TotalMagical:0.##}");
- if (Shield.TotalMix > 0) shield.Add($"混合:{Shield.TotalMix:0.##}");
- builder.AppendLine($"生命值:{HP:0.##} / {MaxHP:0.##}" + (exHP != 0 ? $" [{BaseHP:0.##} {(exHP >= 0 ? "+" : "-")} {Math.Abs(exHP):0.##}]" : "") + (shield.Count > 0 ? $"({string.Join(",", shield)})" : ""));
- double exMP = ExMP + ExMP2 + ExMP3;
- builder.AppendLine($"魔法值:{MP:0.##} / {MaxMP:0.##}" + (exMP != 0 ? $" [{BaseMP:0.##} {(exMP >= 0 ? "+" : "-")} {Math.Abs(exMP):0.##}]" : ""));
- builder.AppendLine($"能量值:{EP:0.##} / {GameplayEquilibriumConstant.MaxEP:0.##}");
- double exATK = ExATK + ExATK2 + ExATK3;
- builder.AppendLine($"攻击力:{ATK:0.##}" + (exATK != 0 ? $" [{BaseATK:0.##} {(exATK >= 0 ? "+" : "-")} {Math.Abs(exATK):0.##}]" : ""));
- builder.AppendLine($"核心属性:{PrimaryAttributeValue:0.##}" + (ExPrimaryAttributeValue != 0 ? $" [{BasePrimaryAttributeValue:0.##} {(ExPrimaryAttributeValue >= 0 ? "+" : "-")} {Math.Abs(ExPrimaryAttributeValue):0.##}]" : ""));
- builder.AppendLine($"硬直时间:{hardnessTimes:0.##}");
-
- Effect[] effects = [.. Effects.Where(e => e.ShowInStatusBar)];
- if (effects.Length > 0)
- {
- builder.AppendLine("== 状态栏 ==");
- builder.Append(string.Join(",", effects.Select(e => e.Name)));
- }
-
- return builder.ToString();
- }
-
///
/// 获取角色的技能信息
///
@@ -1716,7 +1616,7 @@ namespace Milimoe.FunGame.Core.Entity
builder.AppendLine((HP == 0 ? "[ 死亡 ] " : "") + (showUser ? ToStringWithLevel() : ToStringWithLevelWithOutUser()));
- GetStatusInfo(builder);
+ builder.AppendLine(GetStatusInfo().Trim());
builder.AppendLine("== 普通攻击 ==");
builder.Append(NormalAttack.ToString());
@@ -1757,6 +1657,35 @@ namespace Milimoe.FunGame.Core.Entity
builder.AppendLine($"等级:{Level} / {GameplayEquilibriumConstant.MaxLevel}(突破进度:{LevelBreak + 1} / {GameplayEquilibriumConstant.LevelBreakList.Count})");
builder.AppendLine($"经验值:{EXP:0.##}{(Level != GameplayEquilibriumConstant.MaxLevel && GameplayEquilibriumConstant.EXPUpperLimit.TryGetValue(Level, out double need) ? " / " + need : "")}");
}
+
+ builder.AppendLine(GetAttributeInfo(showGrowth).Trim());
+
+ if (showMapRelated)
+ {
+ builder.AppendLine($"移动距离:{MOV}");
+ builder.AppendLine($"攻击距离:{ATR}");
+ }
+
+ if (EquipSlot.Any())
+ {
+ builder.AppendLine(GetEquipSlotInfo().Trim());
+ }
+
+ if (Items.Count > 0)
+ {
+ builder.AppendLine(GetBackpackItemsInfo().Trim());
+ }
+
+ return builder.ToString();
+ }
+
+ ///
+ /// 获取角色属性和能力值信息
+ ///
+ ///
+ public string GetAttributeInfo(bool showGrowth = true)
+ {
+ StringBuilder builder = new();
double exHP = ExHP + ExHP2 + ExHP3;
List shield = [];
if (Shield.TotalPhysical > 0) shield.Add($"物理:{Shield.TotalPhysical:0.##}");
@@ -1792,28 +1721,58 @@ namespace Milimoe.FunGame.Core.Entity
builder.AppendLine($"魔法穿透:{MagicalPenetration * 100:0.##}%");
builder.AppendLine($"魔法消耗减少:{INT * GameplayEquilibriumConstant.INTtoCastMPReduce * 100:0.##}%");
builder.AppendLine($"能量消耗减少:{INT * GameplayEquilibriumConstant.INTtoCastEPReduce * 100:0.##}%");
-
- if (showMapRelated)
- {
- builder.AppendLine($"移动距离:{MOV}");
- builder.AppendLine($"攻击距离:{ATR}");
- }
-
- if (EquipSlot.Any())
- {
- builder.AppendLine(GetEquipSlotInfo().Trim());
- }
-
- if (Items.Count > 0)
- {
- builder.AppendLine(GetBackpackItemsInfo().Trim());
- }
-
return builder.ToString();
}
- private void GetStatusInfo(StringBuilder builder)
+ ///
+ /// 获取角色属性和能力值的简略版信息
+ ///
+ ///
+ public string GetSimpleAttributeInfo(bool showGrowth = true, bool showBasicOnly = false)
{
+ StringBuilder builder = new();
+ double exHP = ExHP + ExHP2 + ExHP3;
+ List shield = [];
+ if (Shield.TotalPhysical > 0) shield.Add($"物理:{Shield.TotalPhysical:0.##}");
+ if (Shield.TotalMagical > 0) shield.Add($"魔法:{Shield.TotalMagical:0.##}");
+ if (Shield.TotalMix > 0) shield.Add($"混合:{Shield.TotalMix:0.##}");
+ builder.AppendLine($"生命值:{HP:0.##} / {MaxHP:0.##}" + (exHP != 0 ? $" [{BaseHP:0.##} {(exHP >= 0 ? "+" : "-")} {Math.Abs(exHP):0.##}]" : "") + (shield.Count > 0 ? $"({string.Join(",", shield)})" : ""));
+ double exMP = ExMP + ExMP2 + ExMP3;
+ builder.AppendLine($"魔法值:{MP:0.##} / {MaxMP:0.##}" + (exMP != 0 ? $" [{BaseMP:0.##} {(exMP >= 0 ? "+" : "-")} {Math.Abs(exMP):0.##}]" : ""));
+ builder.AppendLine($"能量值:{EP:0.##} / {GameplayEquilibriumConstant.MaxEP:0.##}");
+ double exATK = ExATK + ExATK2 + ExATK3;
+ builder.AppendLine($"攻击力:{ATK:0.##}" + (exATK != 0 ? $" [{BaseATK:0.##} {(exATK >= 0 ? "+" : "-")} {Math.Abs(exATK):0.##}]" : ""));
+ double exDEF = ExDEF + ExDEF2 + ExDEF3;
+ builder.AppendLine($"物理护甲:{DEF:0.##}" + (exDEF != 0 ? $" [{BaseDEF:0.##} {(exDEF >= 0 ? "+" : "-")} {Math.Abs(exDEF):0.##}]" : "") + $" ({PDR * 100:0.##}%)");
+ builder.AppendLine(GetMagicResistanceInfo().Trim());
+ if (showBasicOnly)
+ {
+ builder.AppendLine($"核心属性:{PrimaryAttributeValue:0.##}({CharacterSet.GetPrimaryAttributeName(PrimaryAttribute)})");
+ }
+ else
+ {
+ double exSPD = AGI * GameplayEquilibriumConstant.AGItoSPDMultiplier + ExSPD;
+ builder.AppendLine($"行动速度:{SPD:0.##}" + (exSPD != 0 ? $" [{InitialSPD:0.##} {(exSPD >= 0 ? "+" : "-")} {Math.Abs(exSPD):0.##}]" : "") + $" ({ActionCoefficient * 100:0.##}%)");
+ builder.AppendLine($"核心属性:{CharacterSet.GetPrimaryAttributeName(PrimaryAttribute)}");
+ double exSTR = ExSTR + ExSTR2;
+ builder.AppendLine($"力量:{STR:0.##}" + (exSTR != 0 ? $" [{BaseSTR:0.##} {(exSTR >= 0 ? "+" : "-")} {Math.Abs(exSTR):0.##}]" : "") + (showGrowth ? $"({(STRGrowth >= 0 ? "+" : "-")}{Math.Abs(STRGrowth)}/Lv)" : "") + $"({STRExemption * 100:0.##}%)");
+ double exAGI = ExAGI + ExAGI2;
+ builder.AppendLine($"敏捷:{AGI:0.##}" + (exAGI != 0 ? $" [{BaseAGI:0.##} {(exAGI >= 0 ? "+" : "-")} {Math.Abs(exAGI):0.##}]" : "") + (showGrowth ? $"({(AGIGrowth >= 0 ? "+" : "-")}{Math.Abs(AGIGrowth)}/Lv)" : "") + $"({AGIExemption * 100:0.##}%)");
+ double exINT = ExINT + ExINT2;
+ builder.AppendLine($"智力:{INT:0.##}" + (exINT != 0 ? $" [{BaseINT:0.##} {(exINT >= 0 ? "+" : "-")} {Math.Abs(exINT):0.##}]" : "") + (showGrowth ? $"({(INTGrowth >= 0 ? "+" : "-")}{Math.Abs(INTGrowth)}/Lv)" : "") + $"({INTExemption * 100:0.##}%)");
+ }
+ builder.AppendLine($"生命回复:{HR:0.##}" + (ExHR != 0 ? $" [{InitialHR + STR * GameplayEquilibriumConstant.STRtoHRFactor:0.##} {(ExHR >= 0 ? "+" : "-")} {Math.Abs(ExHR):0.##}]" : ""));
+ builder.AppendLine($"魔法回复:{MR:0.##}" + (ExMR != 0 ? $" [{InitialMR + INT * GameplayEquilibriumConstant.INTtoMRFactor:0.##} {(ExMR >= 0 ? "+" : "-")} {Math.Abs(ExMR):0.##}]" : ""));
+ return builder.ToString();
+ }
+
+ ///
+ /// 获取角色状态信息
+ ///
+ public string GetStatusInfo()
+ {
+ StringBuilder builder = new();
+
if (CharacterState != CharacterState.Actionable)
{
builder.AppendLine(CharacterSet.GetCharacterState(CharacterState));
@@ -1848,6 +1807,8 @@ namespace Milimoe.FunGame.Core.Entity
{
builder.AppendLine("角色是不可选中的");
}
+
+ return builder.ToString();
}
///
@@ -2134,7 +2095,7 @@ namespace Milimoe.FunGame.Core.Entity
List skills = [.. Skills];
List
- items = [.. Items];
Character c = original.Copy();
- List effects = [.. Effects];
+ List effects = [.. Effects.OrderByDescending(e => e.Priority)];
foreach (Effect e in effects)
{
e.OnEffectLost(this);
diff --git a/Entity/Character/Unit.cs b/Entity/Character/Unit.cs
index 071c163..8456d7b 100644
--- a/Entity/Character/Unit.cs
+++ b/Entity/Character/Unit.cs
@@ -292,8 +292,9 @@ namespace Milimoe.FunGame.Core.Entity
/// 获取战斗状态的信息
///
///
+ ///
///
- public new string GetInBattleInfo(double hardnessTimes)
+ public new string GetInBattleInfo(double hardnessTimes, bool simpleStatusBar = false)
{
StringBuilder builder = new();
@@ -339,38 +340,6 @@ namespace Milimoe.FunGame.Core.Entity
return builder.ToString();
}
- ///
- /// 获取战斗状态的信息(简略版)
- ///
- ///
- ///
- public new string GetSimpleInBattleInfo(double hardnessTimes)
- {
- StringBuilder builder = new();
-
- builder.AppendLine(ToStringWithLevel());
- double exHP = ExHP + ExHP2 + ExHP3;
- List shield = [];
- if (Shield.TotalPhysical > 0) shield.Add($"物理:{Shield.TotalPhysical:0.##}");
- if (Shield.TotalMagical > 0) shield.Add($"魔法:{Shield.TotalMagical:0.##}");
- if (Shield.Mix > 0) shield.Add($"混合:{Shield.Mix:0.##}");
- builder.AppendLine($"生命值:{HP:0.##} / {MaxHP:0.##}" + (exHP != 0 ? $" [{BaseHP:0.##} {(exHP >= 0 ? "+" : "-")} {Math.Abs(exHP):0.##}]" : "") + (shield.Count > 0 ? $"({string.Join(",", shield)})" : ""));
- double exMP = ExMP + ExMP2 + ExMP3;
- builder.AppendLine($"魔法值:{MP:0.##} / {MaxMP:0.##}" + (exMP != 0 ? $" [{BaseMP:0.##} {(exMP >= 0 ? "+" : "-")} {Math.Abs(exMP):0.##}]" : ""));
- double exATK = ExATK + ExATK2 + ExATK3;
- builder.AppendLine($"攻击力:{ATK:0.##}" + (exATK != 0 ? $" [{BaseATK:0.##} {(exATK >= 0 ? "+" : "-")} {Math.Abs(exATK):0.##}]" : ""));
- builder.AppendLine($"硬直时间:{hardnessTimes:0.##}");
-
- Effect[] effects = [.. Effects.Where(e => e.ShowInStatusBar)];
- if (effects.Length > 0)
- {
- builder.AppendLine("== 状态栏 ==");
- builder.Append(string.Join(",", effects.Select(e => e.Name)));
- }
-
- return builder.ToString();
- }
-
///
/// 获取单位的技能信息
///
diff --git a/Entity/Item/Item.cs b/Entity/Item/Item.cs
index 0b59c15..5b69611 100644
--- a/Entity/Item/Item.cs
+++ b/Entity/Item/Item.cs
@@ -252,7 +252,7 @@ namespace Milimoe.FunGame.Core.Entity
{
foreach (Skill skill in Skills.Passives)
{
- List effects = [.. Character.Effects.Where(e => e.Skill == skill && e.IsInEffect)];
+ List effects = [.. Character.Effects.Where(e => e.Skill == skill && e.IsInEffect).OrderByDescending(e => e.Priority)];
foreach (Effect e in effects)
{
Character.Effects.Remove(e);
diff --git a/Entity/Skill/Effect.cs b/Entity/Skill/Effect.cs
index 5ecaf53..0cda70c 100644
--- a/Entity/Skill/Effect.cs
+++ b/Entity/Skill/Effect.cs
@@ -18,6 +18,12 @@ namespace Milimoe.FunGame.Core.Entity
///
public Skill Skill { get; }
+ ///
+ /// 特效触发优先级
+ /// 越大优先级越高;默认值为 0,在状态栏()中使用默认哈希排序。
+ ///
+ public int Priority { get; set; } = 0;
+
///
/// 特殊效果类型
/// 注意:如果技能特效没有原生施加控制效果,请始终保持此属性为 。
@@ -1267,7 +1273,7 @@ namespace Milimoe.FunGame.Core.Entity
{
return;
}
- Effect[] effects = [.. target.Effects.Where(e => e.ShowInStatusBar)];
+ Effect[] effects = [.. target.Effects.Where(e => e.ShowInStatusBar).OrderByDescending(e => e.Priority)];
foreach (Effect effect in effects)
{
if (effect.OnEffectIsBeingDispelled(dispeller, target, this, isEnemy))
diff --git a/Entity/Skill/Skill.cs b/Entity/Skill/Skill.cs
index c4cb1d4..5f306f4 100644
--- a/Entity/Skill/Skill.cs
+++ b/Entity/Skill/Skill.cs
@@ -408,7 +408,7 @@ namespace Milimoe.FunGame.Core.Entity
}
if (Level > 0 && Character != null)
{
- Effect[] effects = [.. Character.Effects.Where(e => e.IsInEffect)];
+ Effect[] effects = [.. Character.Effects.Where(e => e.IsInEffect).OrderByDescending(e => e.Priority)];
foreach (Effect e in effects)
{
e.OnSkillLevelUp(Character, Level);
@@ -474,7 +474,7 @@ namespace Milimoe.FunGame.Core.Entity
foreach (Character character in enemys)
{
- IEnumerable effects = Effects.Where(e => e.IsInEffect);
+ IEnumerable effects = Effects.Where(e => e.IsInEffect).OrderByDescending(e => e.Priority);
if (CanSelectEnemy && ((character.ImmuneType & checkType) == ImmuneType.None ||
effects.Any(e => e.IgnoreImmune == ImmuneType.All || e.IgnoreImmune == ImmuneType.Skilled || (IsMagic && e.IgnoreImmune == ImmuneType.Magical))))
{
@@ -609,7 +609,7 @@ namespace Milimoe.FunGame.Core.Entity
if (allEnemys.Contains(character))
{
- IEnumerable effects = Effects.Where(e => e.IsInEffect);
+ IEnumerable effects = Effects.Where(e => e.IsInEffect).OrderByDescending(e => e.Priority);
if (CanSelectEnemy && ((AllowSelectDead && character.HP == 0) || (!AllowSelectDead && character.HP > 0)) &&
((character.ImmuneType & checkType) == ImmuneType.None || effects.Any(e => e.IgnoreImmune == ImmuneType.All || e.IgnoreImmune == ImmuneType.Skilled || (IsMagic && e.IgnoreImmune == ImmuneType.Magical))))
{
@@ -725,7 +725,7 @@ namespace Milimoe.FunGame.Core.Entity
Character[] characters = [caster, .. targets];
foreach (Character target in characters)
{
- Effect[] effects = [.. target.Effects.Where(e => e.IsInEffect)];
+ Effect[] effects = [.. target.Effects.Where(e => e.IsInEffect).OrderByDescending(e => e.Priority)];
foreach (Effect e in effects)
{
e.GamingQueue = GamingQueue;
diff --git a/Library/Common/Addon/GameMap.cs b/Library/Common/Addon/GameMap.cs
index 6e95626..81bb5d2 100644
--- a/Library/Common/Addon/GameMap.cs
+++ b/Library/Common/Addon/GameMap.cs
@@ -979,7 +979,7 @@ namespace Milimoe.FunGame.Core.Library.Common.Addon
foreach (Grid grid in Grids.Values)
{
- List effects = [.. grid.Effects];
+ List effects = [.. grid.Effects.OrderByDescending(e => e.Priority)];
foreach (Effect effect in effects)
{
if (effect.Durative)
diff --git a/Model/AIDecision.cs b/Model/AIDecision.cs
index 2046e0a..884cb6e 100644
--- a/Model/AIDecision.cs
+++ b/Model/AIDecision.cs
@@ -14,6 +14,7 @@ namespace Milimoe.FunGame.Core.Model
public List Targets { get; set; } = [];
public List TargetGrids { get; set; } = [];
public double Score { get; set; } = 0;
+ public double ProbabilityWeight { get; set; } = 0;
public bool IsPureMove { get; set; } = false;
}
}
diff --git a/Model/GamingQueue.cs b/Model/GamingQueue.cs
index d444c89..1000854 100644
--- a/Model/GamingQueue.cs
+++ b/Model/GamingQueue.cs
@@ -712,7 +712,7 @@ namespace Milimoe.FunGame.Core.Model
{
// 触发游戏开始事件
OnGameStartEvent();
- Effect[] effects = [.. _queue.SelectMany(c => c.Effects).Where(e => e.IsInEffect)];
+ Effect[] effects = [.. _queue.SelectMany(c => c.Effects).Where(e => e.IsInEffect).OrderByDescending(e => e.Priority)];
foreach (Effect effect in effects)
{
effect.OnGameStart();
@@ -795,7 +795,7 @@ namespace Milimoe.FunGame.Core.Model
double reallyReHP = needHP >= recoveryHP ? recoveryHP : needHP;
double reallyReMP = needMP >= recoveryMP ? recoveryMP : needMP;
bool allowRecovery = true;
- Effect[] effects = [.. character.Effects];
+ Effect[] effects = [.. character.Effects.OrderByDescending(e => e.Priority)];
foreach (Effect effect in effects)
{
if (!effect.BeforeApplyRecoveryAtTimeLapsing(character, ref reallyReHP, ref reallyReMP))
@@ -847,7 +847,7 @@ namespace Milimoe.FunGame.Core.Model
_map?.OnTimeElapsed(timeToReduce);
// 移除到时间的特效
- effects = [.. character.Effects];
+ effects = [.. character.Effects.OrderByDescending(e => e.Priority)];
foreach (Effect effect in effects)
{
if (!character.Shield.ShieldOfEffects.ContainsKey(effect))
@@ -919,7 +919,7 @@ namespace Milimoe.FunGame.Core.Model
}
// 如果特效具备临时驱散或者持续性驱散的功能
- effects = [.. character.Effects.Where(e => e.Source != null && (e.EffectType == EffectType.WeakDispelling || e.EffectType == EffectType.StrongDispelling))];
+ effects = [.. character.Effects.Where(e => e.Source != null && (e.EffectType == EffectType.WeakDispelling || e.EffectType == EffectType.StrongDispelling)).OrderByDescending(e => e.Priority)];
foreach (Effect effect in effects)
{
if (effect.Source is null) continue;
@@ -1025,7 +1025,7 @@ namespace Milimoe.FunGame.Core.Model
skillTurnStart.OnTurnStart(character, selectableEnemys, selectableTeammates, skills, items);
}
- List effects = [.. character.Effects.Where(e => e.IsInEffect)];
+ List effects = [.. character.Effects.Where(e => e.IsInEffect).OrderByDescending(e => e.Priority)];
foreach (Effect effect in effects)
{
effect.OnTurnStart(character, selectableEnemys, selectableTeammates, skills, items);
@@ -1128,7 +1128,7 @@ namespace Milimoe.FunGame.Core.Model
// 行动开始前,可以修改可选取的角色列表
Dictionary continuousKillingTemp = new(_continuousKilling);
Dictionary earnedMoneyTemp = new(_earnedMoney);
- effects = [.. character.Effects.Where(e => e.IsInEffect)];
+ effects = [.. character.Effects.Where(e => e.IsInEffect).OrderByDescending(e => e.Priority)];
foreach (Effect effect in effects)
{
effect.AlterSelectListBeforeAction(character, enemys, teammates, skills, continuousKillingTemp, earnedMoneyTemp);
@@ -1159,7 +1159,7 @@ namespace Milimoe.FunGame.Core.Model
if (character.CharacterState != CharacterState.Casting && character.CharacterState != CharacterState.PreCastSuperSkill)
{
CharacterActionType actionTypeTemp = CharacterActionType.None;
- effects = [.. character.Effects.Where(e => e.IsInEffect)];
+ effects = [.. character.Effects.Where(e => e.IsInEffect).OrderByDescending(e => e.Priority)];
foreach (Effect effect in effects)
{
bool force = false;
@@ -1268,7 +1268,7 @@ namespace Milimoe.FunGame.Core.Model
List allEnemysInGame = [.. allEnemys.Where(canAttackGridsByStartGrid.Union(canCastGridsByStartGrid).SelectMany(g => g.Characters).Contains)];
List allTeammatesInGame = [.. allTeammates.Where(canAttackGridsByStartGrid.Union(canCastGridsByStartGrid).SelectMany(g => g.Characters).Contains)];
- aiDecision = ai.DecideAIAction(character, dp, startGrid, canMoveGrids, skills, items, allEnemys, allTeammates, enemys, teammates);
+ aiDecision = ai.DecideAIAction(character, dp, startGrid, canMoveGrids, skills, items, allEnemys, allTeammates, enemys, teammates, pUseItem, pCastSkill, pNormalAttack);
type = aiDecision.ActionType;
}
else
@@ -1307,7 +1307,7 @@ namespace Milimoe.FunGame.Core.Model
int costDP = dp.GetActionPointCost(type);
- effects = [.. character.Effects.Where(e => e.IsInEffect)];
+ effects = [.. character.Effects.Where(e => e.IsInEffect).OrderByDescending(e => e.Priority)];
foreach (Effect effect in effects)
{
effect.OnCharacterActionStart(character, dp, type);
@@ -1396,14 +1396,14 @@ namespace Milimoe.FunGame.Core.Model
character.NormalAttack.Attack(this, character, null, targets);
- effects = [.. character.Effects.Where(e => e.IsInEffect)];
+ effects = [.. character.Effects.Where(e => e.IsInEffect).OrderByDescending(e => e.Priority)];
foreach (Effect effect in effects)
{
effect.AfterCharacterNormalAttack(character, character.NormalAttack, targets);
}
baseTime += character.NormalAttack.RealHardnessTime;
- effects = [.. character.Effects.Where(e => e.IsInEffect)];
+ effects = [.. character.Effects.Where(e => e.IsInEffect).OrderByDescending(e => e.Priority)];
foreach (Effect effect in effects)
{
effect.AlterHardnessTimeAfterNormalAttack(character, ref baseTime, ref isCheckProtected);
@@ -1493,7 +1493,7 @@ namespace Milimoe.FunGame.Core.Model
isCheckProtected = false;
skill.OnSkillCasting(this, character, targets, grids);
- effects = [.. character.Effects.Where(e => e.IsInEffect)];
+ effects = [.. character.Effects.Where(e => e.IsInEffect).OrderByDescending(e => e.Priority)];
foreach (Effect effect in effects)
{
effect.AfterCharacterStartCasting(character, skill, targets);
@@ -1568,7 +1568,7 @@ namespace Milimoe.FunGame.Core.Model
skill.OnSkillCasting(this, character, targets, grids);
- effects = [.. character.Effects.Where(e => e.IsInEffect)];
+ effects = [.. character.Effects.Where(e => e.IsInEffect).OrderByDescending(e => e.Priority)];
foreach (Effect effect in effects)
{
effect.AfterCharacterStartCasting(character, skill, targets);
@@ -1587,13 +1587,13 @@ namespace Milimoe.FunGame.Core.Model
skill.OnSkillCasted(this, character, targets, grids);
- effects = [.. character.Effects.Where(e => e.IsInEffect)];
+ effects = [.. character.Effects.Where(e => e.IsInEffect).OrderByDescending(e => e.Priority)];
foreach (Effect effect in effects)
{
effect.AfterCharacterCastSkill(character, skill, targets);
}
- effects = [.. character.Effects.Where(e => e.IsInEffect)];
+ effects = [.. character.Effects.Where(e => e.IsInEffect).OrderByDescending(e => e.Priority)];
foreach (Effect effect in effects)
{
effect.AlterHardnessTimeAfterCastSkill(character, skill, ref baseTime, ref isCheckProtected);
@@ -1663,13 +1663,13 @@ namespace Milimoe.FunGame.Core.Model
skill.OnSkillCasted(this, character, targets, grids);
- effects = [.. character.Effects.Where(e => e.IsInEffect)];
+ effects = [.. character.Effects.Where(e => e.IsInEffect).OrderByDescending(e => e.Priority)];
foreach (Effect effect in effects)
{
effect.AfterCharacterCastSkill(character, skill, targets);
}
- effects = [.. character.Effects.Where(e => e.IsInEffect)];
+ effects = [.. character.Effects.Where(e => e.IsInEffect).OrderByDescending(e => e.Priority)];
foreach (Effect effect in effects)
{
effect.AlterHardnessTimeAfterCastSkill(character, skill, ref baseTime, ref isCheckProtected);
@@ -1735,13 +1735,13 @@ namespace Milimoe.FunGame.Core.Model
skill.OnSkillCasted(this, character, targets, grids);
- effects = [.. character.Effects.Where(e => e.IsInEffect)];
+ effects = [.. character.Effects.Where(e => e.IsInEffect).OrderByDescending(e => e.Priority)];
foreach (Effect effect in effects)
{
effect.AfterCharacterCastSkill(character, skill, targets);
}
- effects = [.. character.Effects.Where(e => e.IsInEffect)];
+ effects = [.. character.Effects.Where(e => e.IsInEffect).OrderByDescending(e => e.Priority)];
foreach (Effect effect in effects)
{
effect.AlterHardnessTimeAfterCastSkill(character, skill, ref baseTime, ref isCheckProtected);
@@ -1815,7 +1815,7 @@ namespace Milimoe.FunGame.Core.Model
LastRound.Items[CharacterActionType.UseItem] = item;
decided = true;
baseTime += skill.RealHardnessTime > 0 ? skill.RealHardnessTime : 5;
- effects = [.. character.Effects.Where(e => e.IsInEffect)];
+ effects = [.. character.Effects.Where(e => e.IsInEffect).OrderByDescending(e => e.Priority)];
foreach (Effect effect in effects)
{
effect.AlterHardnessTimeAfterCastSkill(character, skill, ref baseTime, ref isCheckProtected);
@@ -1864,7 +1864,7 @@ namespace Milimoe.FunGame.Core.Model
OnCharacterActionTakenEvent(character, dp, type, LastRound);
- effects = [.. _queue.Union([character]).SelectMany(c => c.Effects).Where(e => e.IsInEffect).Distinct()];
+ effects = [.. _queue.Union([character]).SelectMany(c => c.Effects).Where(e => e.IsInEffect).OrderByDescending(e => e.Priority).Distinct()];
foreach (Effect effect in effects)
{
effect.OnCharacterActionTaken(character, dp, type);
@@ -1888,7 +1888,7 @@ namespace Milimoe.FunGame.Core.Model
AfterCharacterDecision(character, dp);
OnCharacterDecisionCompletedEvent(character, dp, LastRound);
- effects = [.. character.Effects.Where(e => e.IsInEffect)];
+ effects = [.. character.Effects.Where(e => e.IsInEffect).OrderByDescending(e => e.Priority)];
foreach (Effect effect in effects)
{
effect.OnCharacterDecisionCompleted(character, dp);
@@ -1928,7 +1928,7 @@ namespace Milimoe.FunGame.Core.Model
LastRound.HardnessTime = newHardnessTime;
OnQueueUpdatedEvent(_queue, character, dp, newHardnessTime, QueueUpdatedReason.Action, "设置角色行动后的硬直时间。");
- effects = [.. character.Effects];
+ effects = [.. character.Effects.OrderByDescending(e => e.Priority)];
foreach (Effect effect in effects)
{
if (effect.IsInEffect)
@@ -1959,9 +1959,6 @@ namespace Milimoe.FunGame.Core.Model
// 清空临时决策点
dp.ClearTempActionQuota();
- // 有人想要插队吗?
- WillPreCastSuperSkill();
-
// 回合结束事件
OnTurnEndEvent(character, dp);
@@ -1969,6 +1966,10 @@ namespace Milimoe.FunGame.Core.Model
WriteLine("");
_isInRound = false;
+
+ // 有人想要插队吗?
+ WillPreCastSuperSkill();
+
return _isGameEnd;
}
@@ -2126,7 +2127,7 @@ namespace Milimoe.FunGame.Core.Model
// 真实伤害跳过伤害加成区间
if (damageType != DamageType.True)
{
- effects = [.. characters.SelectMany(c => c.Effects.Where(e => e.IsInEffect)).Distinct()];
+ effects = [.. characters.SelectMany(c => c.Effects.Where(e => e.IsInEffect)).OrderByDescending(e => e.Priority).Distinct()];
foreach (Effect effect in effects)
{
double damageBonus = effect.AlterActualDamageAfterCalculation(actor, enemy, damage, isNormalAttack, damageType, magicType, damageResult, ref isEvaded, totalDamageBonus);
@@ -2140,7 +2141,7 @@ namespace Milimoe.FunGame.Core.Model
}
else
{
- effects = [.. characters.SelectMany(c => c.Effects.Where(e => e.IsInEffect)).Distinct()];
+ effects = [.. characters.SelectMany(c => c.Effects.Where(e => e.IsInEffect)).OrderByDescending(e => e.Priority).Distinct()];
foreach (Effect effect in effects)
{
if (effect.BeforeApplyTrueDamage(actor, enemy, damage, isNormalAttack, damageResult))
@@ -2188,7 +2189,7 @@ namespace Milimoe.FunGame.Core.Model
ignore = true;
}
}
- effects = [.. characters.SelectMany(c => c.Effects.Where(e => e.IsInEffect)).Distinct()];
+ effects = [.. characters.SelectMany(c => c.Effects.Where(e => e.IsInEffect)).OrderByDescending(e => e.Priority).Distinct()];
foreach (Effect effect in effects)
{
if (!effect.OnDamageImmuneCheck(actor, enemy, isNormalAttack, damageType, magicType, damage))
@@ -2227,7 +2228,7 @@ namespace Milimoe.FunGame.Core.Model
{
// 在护盾结算前,特效可以有自己的逻辑
bool change = false;
- effects = [.. characters.SelectMany(c => c.Effects.Where(e => e.IsInEffect)).Distinct()];
+ effects = [.. characters.SelectMany(c => c.Effects.Where(e => e.IsInEffect)).OrderByDescending(e => e.Priority).Distinct()];
foreach (Effect effect in effects)
{
double damageReduce = 0;
@@ -2248,7 +2249,7 @@ namespace Milimoe.FunGame.Core.Model
double remain = actualDamage;
// 检查特效护盾
- effects = [.. enemy.Shield.ShieldOfEffects.Keys];
+ effects = [.. enemy.Shield.ShieldOfEffects.Keys.OrderByDescending(e => e.Priority)];
foreach (Effect effect in effects)
{
ShieldOfEffect soe = enemy.Shield.ShieldOfEffects[effect];
@@ -2277,7 +2278,7 @@ namespace Milimoe.FunGame.Core.Model
{
WriteLine($"[ {enemy} ] 发动了 [ {effect.Skill.Name} ] 的护盾效果,抵消了 {effectShield:0.##} 点{damageTypeString},护盾已破碎!");
remain -= effectShield;
- Effect[] effects2 = [.. characters.SelectMany(c => c.Effects.Where(e => e.IsInEffect)).Distinct()];
+ Effect[] effects2 = [.. characters.SelectMany(c => c.Effects.Where(e => e.IsInEffect)).OrderByDescending(e => e.Priority).Distinct()];
foreach (Effect effect2 in effects2)
{
if (!effect2.OnShieldBroken(enemy, actor, effect, remain))
@@ -2289,7 +2290,7 @@ namespace Milimoe.FunGame.Core.Model
}
if (remain <= 0)
{
- Effect[] effects2 = [.. characters.SelectMany(c => c.Effects.Where(e => e.IsInEffect)).Distinct()];
+ Effect[] effects2 = [.. characters.SelectMany(c => c.Effects.Where(e => e.IsInEffect)).OrderByDescending(e => e.Priority).Distinct()];
foreach (Effect effect2 in effects2)
{
effect2.OnShieldNeutralizeDamage(enemy, actor, damageType, magicType, damage, ShieldType.Effect);
@@ -2315,7 +2316,7 @@ namespace Milimoe.FunGame.Core.Model
WriteLine($"[ {enemy} ] 的{shieldTypeString}护盾抵消了 {remain:0.##} 点{damageTypeString}!");
enemy.Shield[isMagicDamage, magicType] -= remain;
remain = 0;
- effects = [.. characters.SelectMany(c => c.Effects.Where(e => e.IsInEffect)).Distinct()];
+ effects = [.. characters.SelectMany(c => c.Effects.Where(e => e.IsInEffect)).OrderByDescending(e => e.Priority).Distinct()];
foreach (Effect effect in effects)
{
effect.OnShieldNeutralizeDamage(enemy, actor, damageType, magicType, damage, shieldType);
@@ -2328,7 +2329,7 @@ namespace Milimoe.FunGame.Core.Model
enemy.Shield[isMagicDamage, magicType] = 0;
if (isMagicDamage && enemy.Shield.TotalMagical <= 0 || !isMagicDamage && enemy.Shield.TotalPhysical <= 0)
{
- effects = [.. characters.SelectMany(c => c.Effects.Where(e => e.IsInEffect)).Distinct()];
+ effects = [.. characters.SelectMany(c => c.Effects.Where(e => e.IsInEffect)).OrderByDescending(e => e.Priority).Distinct()];
foreach (Effect effect in effects)
{
if (!effect.OnShieldBroken(enemy, actor, shieldType, remain))
@@ -2351,7 +2352,7 @@ namespace Milimoe.FunGame.Core.Model
WriteLine($"[ {enemy} ] 的混合护盾抵消了 {remain:0.##} 点{damageTypeString}!");
enemy.Shield.Mix -= remain;
remain = 0;
- effects = [.. characters.SelectMany(c => c.Effects.Where(e => e.IsInEffect)).Distinct()];
+ effects = [.. characters.SelectMany(c => c.Effects.Where(e => e.IsInEffect)).OrderByDescending(e => e.Priority).Distinct()];
foreach (Effect effect in effects)
{
effect.OnShieldNeutralizeDamage(enemy, actor, damageType, magicType, damage, ShieldType.Mix);
@@ -2362,7 +2363,7 @@ namespace Milimoe.FunGame.Core.Model
WriteLine($"[ {enemy} ] 的混合护盾抵消了 {enemy.Shield.TotalMix:0.##} 点{damageTypeString}并破碎!");
remain -= enemy.Shield.TotalMix;
enemy.Shield.Mix = 0;
- effects = [.. characters.SelectMany(c => c.Effects.Where(e => e.IsInEffect)).Distinct()];
+ effects = [.. characters.SelectMany(c => c.Effects.Where(e => e.IsInEffect)).OrderByDescending(e => e.Priority).Distinct()];
foreach (Effect effect in effects)
{
if (!effect.OnShieldBroken(enemy, actor, ShieldType.Mix, remain))
@@ -2397,7 +2398,7 @@ namespace Milimoe.FunGame.Core.Model
options.ActualDamage = actualDamage;
enemy.HP -= actualDamage;
string strDamageMessage = $"[ {enemy} ] 受到了 {actualDamage:0.##} 点{damageTypeString}!{shieldMsg}";
- effects = [.. characters.SelectMany(c => c.Effects.Where(e => e.IsInEffect)).Distinct()];
+ effects = [.. characters.SelectMany(c => c.Effects.Where(e => e.IsInEffect)).OrderByDescending(e => e.Priority).Distinct()];
foreach (Effect effect in effects)
{
effect.OnApplyDamage(enemy, actor, damage, actualDamage, isNormalAttack, damageType, magicType, damageResult, shieldMsg, ref strDamageMessage);
@@ -2425,7 +2426,7 @@ namespace Milimoe.FunGame.Core.Model
// 生命偷取
double steal = actualDamage * actor.Lifesteal;
bool allowSteal = true;
- effects = [.. characters.SelectMany(c => c.Effects.Where(e => e.IsInEffect)).Distinct()];
+ effects = [.. characters.SelectMany(c => c.Effects.Where(e => e.IsInEffect)).OrderByDescending(e => e.Priority).Distinct()];
foreach (Effect effect in effects)
{
if (!effect.BeforeLifesteal(actor, enemy, damage, steal))
@@ -2436,7 +2437,7 @@ namespace Milimoe.FunGame.Core.Model
if (allowSteal)
{
HealToTarget(actor, actor, steal, false, true);
- effects = [.. characters.SelectMany(c => c.Effects.Where(e => e.IsInEffect)).Distinct()];
+ effects = [.. characters.SelectMany(c => c.Effects.Where(e => e.IsInEffect)).OrderByDescending(e => e.Priority).Distinct()];
foreach (Effect effect in effects)
{
effect.AfterLifesteal(actor, enemy, damage, steal);
@@ -2447,7 +2448,7 @@ namespace Milimoe.FunGame.Core.Model
double ep = GetEP(actualDamage, GameplayEquilibriumConstant.DamageGetEPFactor, GameplayEquilibriumConstant.DamageGetEPMax);
if (ep > 0)
{
- effects = [.. actor.Effects.Where(e => e.IsInEffect)];
+ effects = [.. actor.Effects.Where(e => e.IsInEffect).OrderByDescending(e => e.Priority)];
foreach (Effect effect in effects)
{
effect.AlterEPAfterDamage(actor, ref ep);
@@ -2457,7 +2458,7 @@ namespace Milimoe.FunGame.Core.Model
ep = GetEP(actualDamage, GameplayEquilibriumConstant.TakenDamageGetEPFactor, GameplayEquilibriumConstant.TakenDamageGetEPMax);
if (ep > 0)
{
- effects = [.. enemy.Effects.Where(e => e.IsInEffect)];
+ effects = [.. enemy.Effects.Where(e => e.IsInEffect).OrderByDescending(e => e.Priority)];
foreach (Effect effect in effects)
{
effect.AlterEPAfterGetDamage(enemy, ref ep);
@@ -2497,7 +2498,7 @@ namespace Milimoe.FunGame.Core.Model
if (options.TriggerEffects)
{
- effects = [.. characters.SelectMany(c => c.Effects.Where(e => e.IsInEffect)).Distinct()];
+ effects = [.. characters.SelectMany(c => c.Effects.Where(e => e.IsInEffect)).OrderByDescending(e => e.Priority).Distinct()];
foreach (Effect effect in effects)
{
effect.AfterDamageCalculation(actor, enemy, damage, actualDamage, isNormalAttack, damageType, magicType, damageResult);
@@ -2761,7 +2762,7 @@ namespace Milimoe.FunGame.Core.Model
}
bool allowHealing = true;
- List effects = [.. actor.Effects.Union(target.Effects).Distinct().Where(e => e.IsInEffect)];
+ List effects = [.. actor.Effects.Union(target.Effects).Distinct().Where(e => e.IsInEffect).OrderByDescending(e => e.Priority)];
foreach (Effect effect in effects)
{
if (!effect.BeforeHealToTarget(actor, target, heal, canRespawn))
@@ -2782,7 +2783,7 @@ namespace Milimoe.FunGame.Core.Model
if (triggerEffects)
{
Dictionary totalHealBonus = [];
- effects = [.. actor.Effects.Union(target.Effects).Distinct().Where(e => e.IsInEffect)];
+ effects = [.. actor.Effects.Union(target.Effects).Distinct().Where(e => e.IsInEffect).OrderByDescending(e => e.Priority)];
foreach (Effect effect in effects)
{
bool changeCanRespawn = false;
@@ -2971,7 +2972,7 @@ namespace Milimoe.FunGame.Core.Model
public void DealWithCharacterDied(Character killer, Character death, Character[] assists)
{
// 给所有角色的特效广播角色死亡结算
- List effects = [.. _queue.SelectMany(c => c.Effects.Where(e => e.IsInEffect)).Union(killer.Effects).Distinct()];
+ List effects = [.. _queue.SelectMany(c => c.Effects.Where(e => e.IsInEffect)).Union(killer.Effects).Distinct().OrderByDescending(e => e.Priority)];
foreach (Effect effect in effects)
{
effect.AfterDeathCalculation(death, death.Master != null, killer, _continuousKilling, _earnedMoney, assists);
@@ -3084,7 +3085,7 @@ namespace Milimoe.FunGame.Core.Model
skill.OnSkillCasting(this, character, targets, grids);
- Effect[] effects = [.. character.Effects.Where(e => e.IsInEffect)];
+ Effect[] effects = [.. character.Effects.Where(e => e.IsInEffect).OrderByDescending(e => e.Priority)];
foreach (Effect effect in effects)
{
effect.AfterCharacterStartCasting(character, skill, targets);
@@ -3119,13 +3120,13 @@ namespace Milimoe.FunGame.Core.Model
skill.OnSkillCasted(this, character, targets, grids);
- effects = [.. character.Effects.Where(e => e.IsInEffect)];
+ effects = [.. character.Effects.Where(e => e.IsInEffect).OrderByDescending(e => e.Priority)];
foreach (Effect effect in effects)
{
effect.AfterCharacterCastSkill(character, skill, targets);
}
- effects = [.. character.Effects.Where(e => e.IsInEffect)];
+ effects = [.. character.Effects.Where(e => e.IsInEffect).OrderByDescending(e => e.Priority)];
foreach (Effect effect in effects)
{
effect.AfterCharacterUseItem(character, item, skill, targets);
@@ -3234,7 +3235,7 @@ namespace Milimoe.FunGame.Core.Model
///
public Grid SelectTargetGrid(Character character, List enemys, List teammates, GameMap map, List moveRange)
{
- List effects = [.. character.Effects.Where(e => e.IsInEffect)];
+ List effects = [.. character.Effects.Where(e => e.IsInEffect).OrderByDescending(e => e.Priority)];
foreach (Effect effect in effects)
{
effect.BeforeSelectTargetGrid(character, enemys, teammates, map, moveRange);
@@ -3265,7 +3266,7 @@ namespace Milimoe.FunGame.Core.Model
///
public List SelectTargets(Character caster, Skill skill, List enemys, List teammates, List castRange)
{
- List effects = [.. caster.Effects.Where(e => e.IsInEffect)];
+ List effects = [.. caster.Effects.Where(e => e.IsInEffect).OrderByDescending(e => e.Priority)];
foreach (Effect effect in effects)
{
effect.AlterSelectListBeforeSelection(caster, skill, enemys, teammates);
@@ -3308,7 +3309,7 @@ namespace Milimoe.FunGame.Core.Model
///
public List SelectTargets(Character character, NormalAttack attack, List enemys, List teammates, List attackRange)
{
- List effects = [.. character.Effects.Where(e => e.IsInEffect)];
+ List effects = [.. character.Effects.Where(e => e.IsInEffect).OrderByDescending(e => e.Priority)];
foreach (Effect effect in effects)
{
effect.AlterSelectListBeforeSelection(character, attack, enemys, teammates);
@@ -3416,7 +3417,7 @@ namespace Milimoe.FunGame.Core.Model
List characters = [actor, enemy];
DamageType damageType = DamageType.Physical;
MagicType magicType = MagicType.None;
- List effects = [.. characters.SelectMany(c => c.Effects.Where(e => e.IsInEffect)).Distinct()];
+ List effects = [.. characters.SelectMany(c => c.Effects.Where(e => e.IsInEffect)).OrderByDescending(e => e.Priority).Distinct()];
Dictionary totalDamageBonus = [];
if (options.TriggerEffects)
{
@@ -3433,7 +3434,7 @@ namespace Milimoe.FunGame.Core.Model
}
}
- effects = [.. actor.Effects.Union(enemy.Effects).Distinct().Where(e => e.IsInEffect)];
+ effects = [.. actor.Effects.Union(enemy.Effects).Distinct().Where(e => e.IsInEffect).OrderByDescending(e => e.Priority)];
foreach (Effect effect in effects)
{
double damageBonus = effect.AlterExpectedDamageBeforeCalculation(actor, enemy, expectedDamage, isNormalAttack, DamageType.Physical, MagicType.None, totalDamageBonus);
@@ -3449,7 +3450,7 @@ namespace Milimoe.FunGame.Core.Model
bool checkCritical = true;
if (isNormalAttack && options.CalculateEvade)
{
- effects = [.. characters.SelectMany(c => c.Effects.Where(e => e.IsInEffect)).Distinct()];
+ effects = [.. characters.SelectMany(c => c.Effects.Where(e => e.IsInEffect)).OrderByDescending(e => e.Priority).Distinct()];
foreach (Effect effect in effects)
{
if (!effect.BeforeEvadeCheck(actor, enemy, ref throwingBonus))
@@ -3464,7 +3465,7 @@ namespace Milimoe.FunGame.Core.Model
if (dice < (enemy.EvadeRate + throwingBonus))
{
bool isAlterEvaded = false;
- effects = [.. characters.SelectMany(c => c.Effects.Where(e => e.IsInEffect)).Distinct()];
+ effects = [.. characters.SelectMany(c => c.Effects.Where(e => e.IsInEffect)).OrderByDescending(e => e.Priority).Distinct()];
foreach (Effect effect in effects)
{
if (effect.OnEvadedTriggered(actor, enemy, dice))
@@ -3500,7 +3501,7 @@ namespace Milimoe.FunGame.Core.Model
if (options.CalculateCritical)
{
// 暴击检定
- effects = [.. characters.SelectMany(c => c.Effects.Where(e => e.IsInEffect)).Distinct()];
+ effects = [.. characters.SelectMany(c => c.Effects.Where(e => e.IsInEffect)).OrderByDescending(e => e.Priority).Distinct()];
foreach (Effect effect in effects)
{
if (!effect.BeforeCriticalCheck(actor, enemy, isNormalAttack, ref throwingBonus))
@@ -3517,7 +3518,7 @@ namespace Milimoe.FunGame.Core.Model
options.CriticalDamage = finalDamage * (actor.CritDMG - 1);
finalDamage *= actor.CritDMG; // 暴击伤害倍率加成
WriteLine("暴击生效!!");
- effects = [.. characters.SelectMany(c => c.Effects.Where(e => e.IsInEffect)).Distinct()];
+ effects = [.. characters.SelectMany(c => c.Effects.Where(e => e.IsInEffect)).OrderByDescending(e => e.Priority).Distinct()];
foreach (Effect effect in effects)
{
effect.OnCriticalDamageTriggered(actor, enemy, dice);
@@ -3549,7 +3550,7 @@ namespace Milimoe.FunGame.Core.Model
if (options.ExpectedDamage == 0) options.ExpectedDamage = expectedDamage;
List characters = [actor, enemy];
DamageType damageType = DamageType.Magical;
- List effects = [.. characters.SelectMany(c => c.Effects.Where(e => e.IsInEffect)).Distinct()];
+ List effects = [.. characters.SelectMany(c => c.Effects.Where(e => e.IsInEffect)).OrderByDescending(e => e.Priority).Distinct()];
Dictionary totalDamageBonus = [];
if (options.TriggerEffects)
{
@@ -3566,7 +3567,7 @@ namespace Milimoe.FunGame.Core.Model
}
}
- effects = [.. characters.SelectMany(c => c.Effects.Where(e => e.IsInEffect)).Distinct()];
+ effects = [.. characters.SelectMany(c => c.Effects.Where(e => e.IsInEffect)).OrderByDescending(e => e.Priority).Distinct()];
foreach (Effect effect in effects)
{
double damageBonus = effect.AlterExpectedDamageBeforeCalculation(actor, enemy, expectedDamage, isNormalAttack, DamageType.Magical, magicType, totalDamageBonus);
@@ -3582,7 +3583,7 @@ namespace Milimoe.FunGame.Core.Model
bool checkCritical = true;
if (isNormalAttack && options.CalculateEvade)
{
- effects = [.. characters.SelectMany(c => c.Effects.Where(e => e.IsInEffect)).Distinct()];
+ effects = [.. characters.SelectMany(c => c.Effects.Where(e => e.IsInEffect)).OrderByDescending(e => e.Priority).Distinct()];
foreach (Effect effect in effects)
{
if (!effect.BeforeEvadeCheck(actor, enemy, ref throwingBonus))
@@ -3597,7 +3598,7 @@ namespace Milimoe.FunGame.Core.Model
if (dice < (enemy.EvadeRate + throwingBonus))
{
bool isAlterEvaded = false;
- effects = [.. characters.SelectMany(c => c.Effects.Where(e => e.IsInEffect)).Distinct()];
+ effects = [.. characters.SelectMany(c => c.Effects.Where(e => e.IsInEffect)).OrderByDescending(e => e.Priority).Distinct()];
foreach (Effect effect in effects)
{
if (effect.OnEvadedTriggered(actor, enemy, dice))
@@ -3633,7 +3634,7 @@ namespace Milimoe.FunGame.Core.Model
if (options.CalculateCritical)
{
// 暴击检定
- effects = [.. characters.SelectMany(c => c.Effects.Where(e => e.IsInEffect)).Distinct()];
+ effects = [.. characters.SelectMany(c => c.Effects.Where(e => e.IsInEffect)).OrderByDescending(e => e.Priority).Distinct()];
foreach (Effect effect in effects)
{
if (!effect.BeforeCriticalCheck(actor, enemy, isNormalAttack, ref throwingBonus))
@@ -3650,7 +3651,7 @@ namespace Milimoe.FunGame.Core.Model
options.CriticalDamage = finalDamage * (actor.CritDMG - 1);
finalDamage *= actor.CritDMG; // 暴击伤害倍率加成
WriteLine("暴击生效!!");
- effects = [.. characters.SelectMany(c => c.Effects.Where(e => e.IsInEffect)).Distinct()];
+ effects = [.. characters.SelectMany(c => c.Effects.Where(e => e.IsInEffect)).OrderByDescending(e => e.Priority).Distinct()];
foreach (Effect effect in effects)
{
effect.OnCriticalDamageTriggered(actor, enemy, dice);
@@ -3959,7 +3960,7 @@ namespace Milimoe.FunGame.Core.Model
if (skill != null)
{
bool interruption = true;
- List effects = [.. caster.Effects.Union(interrupter.Effects).Distinct().Where(e => e.IsInEffect)];
+ List effects = [.. caster.Effects.Union(interrupter.Effects).Distinct().Where(e => e.IsInEffect).OrderByDescending(e => e.Priority)];
foreach (Effect e in effects)
{
if (!e.BeforeSkillCastWillBeInterrupted(caster, skill, interrupter))
@@ -3971,7 +3972,7 @@ namespace Milimoe.FunGame.Core.Model
{
_castingSkills.Remove(caster);
WriteLine($"[ {caster} ] 的施法被 [ {interrupter} ] 打断了!!");
- effects = [.. caster.Effects.Union(interrupter.Effects).Distinct().Where(e => e.IsInEffect)];
+ effects = [.. caster.Effects.Union(interrupter.Effects).Distinct().Where(e => e.IsInEffect).OrderByDescending(e => e.Priority)];
foreach (Effect e in effects)
{
e.OnSkillCastInterrupted(caster, skill, interrupter);
@@ -3995,7 +3996,7 @@ namespace Milimoe.FunGame.Core.Model
{
Skill skill = skillTarget.Skill;
WriteLine($"[ {caster} ] 丢失了施法目标!!");
- List effects = [.. caster.Effects.Union(interrupter.Effects).Distinct().Where(e => e.IsInEffect)];
+ List effects = [.. caster.Effects.Union(interrupter.Effects).Distinct().Where(e => e.IsInEffect).OrderByDescending(e => e.Priority)];
foreach (Effect effect in effects)
{
effect.OnSkillCastInterrupted(caster, skill, interrupter);
@@ -4040,6 +4041,10 @@ namespace Milimoe.FunGame.Core.Model
///
public void SetCharacterPreCastSuperSkill(Character character, Skill skill)
{
+ if (LastRound.Actor == character && _isInRound)
+ {
+ return;
+ }
if (_decisionPoints.TryGetValue(character, out DecisionPoints? dp) && dp != null)
{
if (dp.CurrentDecisionPoints < GameplayEquilibriumConstant.DecisionPointsCostSuperSkillOutOfTurn)
@@ -4104,7 +4109,7 @@ namespace Milimoe.FunGame.Core.Model
AddCharacter(character, newHardnessTime, false);
skill.OnSkillCasting(this, character, [], []);
- Effect[] effects = [.. character.Effects.Where(e => e.IsInEffect)];
+ Effect[] effects = [.. character.Effects.Where(e => e.IsInEffect).OrderByDescending(e => e.Priority)];
foreach (Effect effect in effects)
{
effect.AfterCharacterStartCasting(character, skill, []);
@@ -4289,7 +4294,7 @@ namespace Milimoe.FunGame.Core.Model
(target.ImmuneType & ImmuneType.Skilled) == ImmuneType.Skilled || (target.ImmuneType & ImmuneType.All) == ImmuneType.All;
if (isImmune)
{
- Effect[] effects = [.. skill.Effects.Where(e => e.IsInEffect)];
+ Effect[] effects = [.. skill.Effects.Where(e => e.IsInEffect).OrderByDescending(e => e.Priority)];
foreach (Effect effect in effects)
{
// 自带无视免疫
@@ -4301,7 +4306,7 @@ namespace Milimoe.FunGame.Core.Model
if (!ignore)
{
Character[] characters = [character, target];
- effects = [.. characters.SelectMany(c => c.Effects.Where(e => e.IsInEffect)).Distinct()];
+ effects = [.. characters.SelectMany(c => c.Effects.Where(e => e.IsInEffect)).OrderByDescending(e => e.Priority).Distinct()];
foreach (Effect effect in effects)
{
// 特效免疫检定不通过可无视免疫
@@ -4345,7 +4350,7 @@ namespace Milimoe.FunGame.Core.Model
bool checkExempted = true;
double throwingBonus = 0;
Character[] characters = source != null ? [character, source] : [character];
- Effect[] effects = [.. characters.SelectMany(c => c.Effects.Where(e => e.IsInEffect)).Distinct()];
+ Effect[] effects = [.. characters.SelectMany(c => c.Effects.Where(e => e.IsInEffect)).OrderByDescending(e => e.Priority).Distinct()];
foreach (Effect e in effects)
{
if (!e.OnExemptionCheck(character, source, effect, isEvade, ref throwingBonus))
@@ -4520,7 +4525,7 @@ namespace Milimoe.FunGame.Core.Model
_decisionPoints[character] = dp;
}
InquiryResponse response = OnCharacterInquiryEvent(character, dp, options);
- Effect[] effects = [.. character.Effects.Where(e => e.IsInEffect)];
+ Effect[] effects = [.. character.Effects.Where(e => e.IsInEffect).OrderByDescending(e => e.Priority)];
foreach (Effect effect in effects)
{
effect.OnCharacterInquiry(character, options, response);
diff --git a/Model/InquiryOptions.cs b/Model/InquiryOptions.cs
index b5784e4..2a765b5 100644
--- a/Model/InquiryOptions.cs
+++ b/Model/InquiryOptions.cs
@@ -12,6 +12,7 @@ namespace Milimoe.FunGame.Core.Model
public double MinNumberValue { get; set; } = 0;
public double MaxNumberValue { get; set; } = 0;
public double DefaultNumberValue { get; set; } = 0;
+ public bool CanCancel { get; set; } = true;
public Dictionary CustomArgs { get; set; } = [];
public InquiryOptions(InquiryType type, string topic)
diff --git a/Model/InquiryResponse.cs b/Model/InquiryResponse.cs
index dbba58e..59aaabc 100644
--- a/Model/InquiryResponse.cs
+++ b/Model/InquiryResponse.cs
@@ -9,6 +9,7 @@ namespace Milimoe.FunGame.Core.Model
public List Choices { get; set; } = [];
public string TextResult { get; set; } = "";
public double NumberResult { get; set; } = 0;
+ public bool Cancel { get; set; } = false;
public Dictionary CustomResponse { get; set; } = [];
public InquiryResponse(InquiryType type, string topic)