diff --git a/Entity/Character/Character.cs b/Entity/Character/Character.cs
index 8378251..b1e1cde 100644
--- a/Entity/Character/Character.cs
+++ b/Entity/Character/Character.cs
@@ -1415,20 +1415,7 @@ namespace Milimoe.FunGame.Core.Entity
builder.AppendLine($"魔法消耗减少:{INT * GameplayEquilibriumConstant.INTtoCastMPReduce * 100:0.##}%");
builder.AppendLine($"能量消耗减少:{INT * GameplayEquilibriumConstant.INTtoCastEPReduce * 100:0.##}%");
- if (CharacterState != CharacterState.Actionable)
- {
- builder.AppendLine(CharacterSet.GetCharacterState(CharacterState));
- }
-
- if (IsNeutral)
- {
- builder.AppendLine("角色是无敌的");
- }
-
- if (IsUnselectable)
- {
- builder.AppendLine("角色是不可选中的");
- }
+ GetStatusInfo(builder);
builder.AppendLine("== 普通攻击 ==");
builder.Append(NormalAttack.ToString());
@@ -1514,20 +1501,7 @@ namespace Milimoe.FunGame.Core.Entity
if (!showBasicOnly)
{
- if (CharacterState != CharacterState.Actionable)
- {
- builder.AppendLine(CharacterSet.GetCharacterState(CharacterState));
- }
-
- if (IsNeutral)
- {
- builder.AppendLine("角色是无敌的");
- }
-
- if (IsUnselectable)
- {
- builder.AppendLine("角色是不可选中的");
- }
+ GetStatusInfo(builder);
if (Skills.Count > 0)
{
@@ -1600,20 +1574,7 @@ namespace Milimoe.FunGame.Core.Entity
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.##}]" : ""));
- if (CharacterState != CharacterState.Actionable)
- {
- builder.AppendLine(CharacterSet.GetCharacterState(CharacterState));
- }
-
- if (IsNeutral)
- {
- builder.AppendLine("角色是中立单位,处于无敌状态");
- }
-
- if (IsUnselectable)
- {
- builder.AppendLine("角色是不可选中的");
- }
+ GetStatusInfo(builder);
builder.AppendLine($"硬直时间:{hardnessTimes:0.##}");
@@ -1674,20 +1635,7 @@ namespace Milimoe.FunGame.Core.Entity
builder.AppendLine((HP == 0 ? "[ 死亡 ] " : "") + (showUser ? ToStringWithLevel() : ToStringWithLevelWithOutUser()));
- if (CharacterState != CharacterState.Actionable)
- {
- builder.AppendLine(CharacterSet.GetCharacterState(CharacterState));
- }
-
- if (IsNeutral)
- {
- builder.AppendLine("角色是无敌的");
- }
-
- if (IsUnselectable)
- {
- builder.AppendLine("角色是不可选中的");
- }
+ GetStatusInfo(builder);
builder.AppendLine("== 普通攻击 ==");
builder.Append(NormalAttack.ToString());
@@ -1777,6 +1725,44 @@ namespace Milimoe.FunGame.Core.Entity
return builder.ToString();
}
+ private void GetStatusInfo(StringBuilder builder)
+ {
+ if (CharacterState != CharacterState.Actionable)
+ {
+ builder.AppendLine(CharacterSet.GetCharacterState(CharacterState));
+ }
+
+ if ((ImmuneType & ImmuneType.Physical) != ImmuneType.None)
+ {
+ builder.AppendLine("角色现在物理免疫");
+ }
+
+ if ((ImmuneType & ImmuneType.Magical) != ImmuneType.None)
+ {
+ builder.AppendLine("角色现在魔法免疫");
+ }
+
+ if ((ImmuneType & ImmuneType.Skilled) != ImmuneType.None)
+ {
+ builder.AppendLine("角色现在技能免疫");
+ }
+
+ if ((ImmuneType & ImmuneType.All) != ImmuneType.None)
+ {
+ builder.AppendLine("角色现在完全免疫");
+ }
+
+ if (IsNeutral)
+ {
+ builder.AppendLine("角色是无敌的");
+ }
+
+ if (IsUnselectable)
+ {
+ builder.AppendLine("角色是不可选中的");
+ }
+ }
+
///
/// 获取角色装备栏信息
///
@@ -1888,30 +1874,27 @@ namespace Milimoe.FunGame.Core.Entity
IsUnselectable = types.Any(type => type == EffectType.Unselectable);
IEnumerable immunes = CharacterImmuneTypes.Values.SelectMany(list => list);
- // 判断角色的免疫状态
+ // 判断角色的免疫状态,需要注意的是 All 不会覆盖任何其他类型,因为它是一种独立的类型
bool isAllImmune = immunes.Any(type => type == ImmuneType.All);
bool isPhysicalImmune = immunes.Any(type => type == ImmuneType.Physical);
bool isMagicalImmune = immunes.Any(type => type == ImmuneType.Magical);
bool isSkilledImmune = immunes.Any(type => type == ImmuneType.Skilled);
+ ImmuneType = ImmuneType.None;
if (isAllImmune)
{
- ImmuneType = ImmuneType.All;
+ ImmuneType |= ImmuneType.All;
}
- else if (isPhysicalImmune)
+ if (isPhysicalImmune)
{
- ImmuneType = ImmuneType.Physical;
+ ImmuneType |= ImmuneType.Physical;
}
- else if (isMagicalImmune)
+ if (isMagicalImmune)
{
- ImmuneType = ImmuneType.Magical;
+ ImmuneType |= ImmuneType.Magical;
}
- else if (isSkilledImmune)
+ if (isSkilledImmune)
{
- ImmuneType = ImmuneType.Skilled;
- }
- else
- {
- ImmuneType = ImmuneType.None;
+ ImmuneType |= ImmuneType.Skilled;
}
bool isControl = isNotActionable || isActionRestricted || isBattleRestricted || isSkillRestricted || isAttackRestricted;
diff --git a/Entity/Skill/Effect.cs b/Entity/Skill/Effect.cs
index b2df164..f5ba582 100644
--- a/Entity/Skill/Effect.cs
+++ b/Entity/Skill/Effect.cs
@@ -565,8 +565,9 @@ namespace Milimoe.FunGame.Core.Entity
///
///
///
+ ///
///
- public virtual CharacterActionType AlterActionTypeBeforeAction(Character character, CharacterState state, ref bool canUseItem, ref bool canCastSkill, ref double pUseItem, ref double pCastSkill, ref double pNormalAttack)
+ public virtual CharacterActionType AlterActionTypeBeforeAction(Character character, CharacterState state, ref bool canUseItem, ref bool canCastSkill, ref double pUseItem, ref double pCastSkill, ref double pNormalAttack, ref bool forceAction)
{
return CharacterActionType.None;
}
@@ -745,12 +746,12 @@ namespace Milimoe.FunGame.Core.Entity
///
/// 在免疫检定时
///
- ///
- ///
+ ///
+ ///
///
///
/// false:免疫检定不通过
- public virtual bool OnImmuneCheck(Character actor, Character enemy, ISkill skill, Item? item = null)
+ public virtual bool OnImmuneCheck(Character character, Character target, ISkill skill, Item? item = null)
{
return true;
}
diff --git a/Entity/Skill/NormalAttack.cs b/Entity/Skill/NormalAttack.cs
index eb3551a..f8d39c5 100644
--- a/Entity/Skill/NormalAttack.cs
+++ b/Entity/Skill/NormalAttack.cs
@@ -241,13 +241,20 @@ namespace Milimoe.FunGame.Core.Entity
selectable.Add(caster);
}
- if (CanSelectEnemy)
+ foreach (Character character in enemys)
{
- selectable.AddRange(enemys);
+ if (CanSelectEnemy && ((character.ImmuneType & ImmuneType.All) != ImmuneType.All || IgnoreImmune == ImmuneType.All))
+ {
+ selectable.Add(character);
+ }
}
- if (CanSelectTeammate)
+
+ foreach (Character character in teammates)
{
- selectable.AddRange(teammates);
+ if (CanSelectTeammate && ((character.ImmuneType & ImmuneType.All) != ImmuneType.All || IgnoreImmune == ImmuneType.All))
+ {
+ selectable.Add(character);
+ }
}
return selectable;
diff --git a/Entity/Skill/Skill.cs b/Entity/Skill/Skill.cs
index d4f9fd1..f56e688 100644
--- a/Entity/Skill/Skill.cs
+++ b/Entity/Skill/Skill.cs
@@ -208,10 +208,20 @@ namespace Milimoe.FunGame.Core.Entity
[InitRequired]
public virtual double HardnessTime { get; set; } = 0;
+ ///
+ /// 额外硬直时间 [ 技能和物品相关 ]
+ ///
+ public double ExHardnessTime { get; set; } = 0;
+
+ ///
+ /// 额外硬直时间% [ 技能和物品相关 ]
+ ///
+ public double ExHardnessTime2 { get; set; } = 0;
+
///
/// 实际硬直时间
///
- public double RealHardnessTime => Math.Max(0, HardnessTime * (1 - Calculation.PercentageCheck(Character?.ActionCoefficient ?? 0)));
+ public double RealHardnessTime => Math.Max(0, (HardnessTime + ExHardnessTime) * (1 + ExHardnessTime2) * (1 - Calculation.PercentageCheck(Character?.ActionCoefficient ?? 0)));
///
/// 效果列表
@@ -319,14 +329,30 @@ namespace Milimoe.FunGame.Core.Entity
selectable.Add(caster);
}
- if (CanSelectEnemy)
+ ImmuneType checkType = ImmuneType.Skilled | ImmuneType.All;
+ if (IsMagic)
{
- selectable.AddRange(enemys);
+ checkType |= ImmuneType.Magical;
}
- if (CanSelectTeammate)
+ foreach (Character character in enemys)
{
- selectable.AddRange(teammates);
+ IEnumerable effects = character.Effects.Where(e => e.IsInEffect);
+ if (CanSelectEnemy && ((character.ImmuneType & checkType) == ImmuneType.None ||
+ effects.Any(e => e.IgnoreImmune == ImmuneType.All || e.IgnoreImmune == ImmuneType.Skilled || (IsMagic && e.IgnoreImmune == ImmuneType.Magical))))
+ {
+ selectable.Add(character);
+ }
+ }
+
+ foreach (Character character in teammates)
+ {
+ IEnumerable effects = character.Effects.Where(e => e.IsInEffect);
+ if (CanSelectTeammate && ((character.ImmuneType & checkType) == ImmuneType.None ||
+ effects.Any(e => e.IgnoreImmune == ImmuneType.All || e.IgnoreImmune == ImmuneType.Skilled || (IsMagic && e.IgnoreImmune == ImmuneType.Magical))))
+ {
+ selectable.Add(character);
+ }
}
// 其他条件
diff --git a/Library/Common/JsonConverter/NormalAttackConverter.cs b/Library/Common/JsonConverter/NormalAttackConverter.cs
index 6e8f3c0..ed2435a 100644
--- a/Library/Common/JsonConverter/NormalAttackConverter.cs
+++ b/Library/Common/JsonConverter/NormalAttackConverter.cs
@@ -49,7 +49,10 @@ namespace Milimoe.FunGame.Core.Library.Common.JsonConverter
writer.WriteStartObject();
writer.WriteNumber(nameof(NormalAttack.Level), value.Level);
- writer.WriteNumber(nameof(NormalAttack.HardnessTime), value.HardnessTime);
+ writer.WriteNumber(nameof(NormalAttack.ExDamage), value.ExDamage);
+ writer.WriteNumber(nameof(NormalAttack.ExDamage2), value.ExDamage2);
+ writer.WriteNumber(nameof(NormalAttack.ExHardnessTime), value.ExHardnessTime);
+ writer.WriteNumber(nameof(NormalAttack.ExHardnessTime2), value.ExHardnessTime2);
writer.WriteBoolean(nameof(NormalAttack.IsMagic), value.IsMagic);
writer.WriteNumber(nameof(NormalAttack.MagicType), (int)value.MagicType);
writer.WriteNumber(nameof(NormalAttack.IgnoreImmune), (int)value.IgnoreImmune);
diff --git a/Library/Common/JsonConverter/SkillConverter.cs b/Library/Common/JsonConverter/SkillConverter.cs
index beb16ea..f1f1ae2 100644
--- a/Library/Common/JsonConverter/SkillConverter.cs
+++ b/Library/Common/JsonConverter/SkillConverter.cs
@@ -86,6 +86,12 @@ namespace Milimoe.FunGame.Core.Library.Common.JsonConverter
case nameof(Skill.HardnessTime):
result.HardnessTime = reader.GetDouble();
break;
+ case nameof(Skill.ExHardnessTime):
+ result.ExHardnessTime = reader.GetDouble();
+ break;
+ case nameof(Skill.ExHardnessTime2):
+ result.ExHardnessTime2 = reader.GetDouble();
+ break;
case nameof(Skill.Effects):
HashSet effects = NetworkUtility.JsonDeserialize>(ref reader, options) ?? [];
foreach (Effect effect in effects)
@@ -134,6 +140,8 @@ namespace Milimoe.FunGame.Core.Library.Common.JsonConverter
if (value.CD > 0) writer.WriteNumber(nameof(Skill.CD), value.CD);
if (value.CurrentCD > 0) writer.WriteNumber(nameof(Skill.CurrentCD), value.CurrentCD);
if (value.HardnessTime > 0) writer.WriteNumber(nameof(Skill.HardnessTime), value.HardnessTime);
+ if (value.ExHardnessTime != 0) writer.WriteNumber(nameof(Skill.ExHardnessTime), value.ExHardnessTime);
+ if (value.ExHardnessTime2 != 0) writer.WriteNumber(nameof(Skill.ExHardnessTime2), value.ExHardnessTime2);
writer.WritePropertyName(nameof(Skill.Effects));
JsonSerializer.Serialize(writer, value.Effects, options);
writer.WritePropertyName(nameof(Skill.Values));
diff --git a/Library/Constant/ConstantSet.cs b/Library/Constant/ConstantSet.cs
index fd18c8b..293e36e 100644
--- a/Library/Constant/ConstantSet.cs
+++ b/Library/Constant/ConstantSet.cs
@@ -465,6 +465,18 @@ namespace Milimoe.FunGame.Core.Library.Constant
_ => "物理伤害"
};
}
+
+ public static string GetImmuneTypeName(ImmuneType type)
+ {
+ return type switch
+ {
+ ImmuneType.Physical => "物理免疫",
+ ImmuneType.Magical => "魔法免疫",
+ ImmuneType.Skilled => "技能免疫",
+ ImmuneType.All => "完全免疫",
+ _ => ""
+ };
+ }
}
public class ItemSet
diff --git a/Library/Constant/TypeEnum.cs b/Library/Constant/TypeEnum.cs
index 2e9e730..d734c85 100644
--- a/Library/Constant/TypeEnum.cs
+++ b/Library/Constant/TypeEnum.cs
@@ -1021,14 +1021,15 @@ namespace Milimoe.FunGame.Core.Library.Constant
///
/// 标准实现的免疫类型
///
+ [Flags]
public enum ImmuneType
{
- None,
- Physical,
- Magical,
- Skilled,
- All,
- Special
+ None = 0,
+ Physical = 1 << 0,
+ Magical = 1 << 1,
+ Skilled = 1 << 2,
+ All = 1 << 3,
+ Special = 1 << 4
}
public enum ShieldType
diff --git a/Model/GamingQueue.cs b/Model/GamingQueue.cs
index 906dcf4..f40ace3 100644
--- a/Model/GamingQueue.cs
+++ b/Model/GamingQueue.cs
@@ -804,6 +804,7 @@ namespace Milimoe.FunGame.Core.Model
bool isAI = CharactersInAI.Contains(character);
while (!decided && (!isAI || cancelTimes > 0))
{
+ cancelTimes--;
type = CharacterActionType.None;
// 是否能使用物品和释放技能
@@ -815,7 +816,9 @@ namespace Milimoe.FunGame.Core.Model
double pCastSkill = 0.33;
double pNormalAttack = 0.34;
- cancelTimes--;
+ // 是否强制执行(跳过状态检查等)
+ bool forceAction = false;
+
// 不允许在吟唱和预释放状态下,修改角色的行动
if (character.CharacterState != CharacterState.Casting && character.CharacterState != CharacterState.PreCastSuperSkill)
{
@@ -823,7 +826,7 @@ namespace Milimoe.FunGame.Core.Model
effects = [.. character.Effects.Where(e => e.IsInEffect)];
foreach (Effect effect in effects)
{
- actionTypeTemp = effect.AlterActionTypeBeforeAction(character, character.CharacterState, ref canUseItem, ref canCastSkill, ref pUseItem, ref pCastSkill, ref pNormalAttack);
+ actionTypeTemp = effect.AlterActionTypeBeforeAction(character, character.CharacterState, ref canUseItem, ref canCastSkill, ref pUseItem, ref pCastSkill, ref pNormalAttack, ref forceAction);
}
if (actionTypeTemp != CharacterActionType.None && actionTypeTemp != CharacterActionType.CastSkill && actionTypeTemp != CharacterActionType.CastSuperSkill)
{
@@ -943,10 +946,10 @@ namespace Milimoe.FunGame.Core.Model
if (type == CharacterActionType.NormalAttack)
{
- if (character.CharacterState == CharacterState.NotActionable ||
+ if (!forceAction && (character.CharacterState == CharacterState.NotActionable ||
character.CharacterState == CharacterState.ActionRestricted ||
character.CharacterState == CharacterState.BattleRestricted ||
- character.CharacterState == CharacterState.AttackRestricted)
+ character.CharacterState == CharacterState.AttackRestricted))
{
WriteLine($"角色 [ {character} ] 状态为:{CharacterSet.GetCharacterState(character.CharacterState)},无法使用普通攻击!");
}
@@ -973,10 +976,10 @@ namespace Milimoe.FunGame.Core.Model
}
else if (type == CharacterActionType.PreCastSkill)
{
- if (character.CharacterState == CharacterState.NotActionable ||
+ if (!forceAction && (character.CharacterState == CharacterState.NotActionable ||
character.CharacterState == CharacterState.ActionRestricted ||
character.CharacterState == CharacterState.BattleRestricted ||
- character.CharacterState == CharacterState.SkillRestricted)
+ character.CharacterState == CharacterState.SkillRestricted))
{
WriteLine($"角色 [ {character} ] 状态为:{CharacterSet.GetCharacterState(character.CharacterState)},无法释放技能!");
}
@@ -1471,29 +1474,27 @@ namespace Milimoe.FunGame.Core.Model
// 此变量为是否无视免疫
bool ignore = false;
// 技能免疫无法免疫普通攻击,但是魔法免疫和物理免疫可以
- isImmune = (isNormalAttack && (enemy.ImmuneType == ImmuneType.All || enemy.ImmuneType == ImmuneType.Physical || enemy.ImmuneType == ImmuneType.Magical)) ||
- (!isNormalAttack && (enemy.ImmuneType == ImmuneType.All || enemy.ImmuneType == ImmuneType.Physical || enemy.ImmuneType == ImmuneType.Magical || enemy.ImmuneType == ImmuneType.Skilled));
+ isImmune = (enemy.ImmuneType & ImmuneType.All) == ImmuneType.All ||
+ (!isNormalAttack && (enemy.ImmuneType & ImmuneType.Skilled) == ImmuneType.Skilled) ||
+ (damageType == DamageType.Physical && (enemy.ImmuneType & ImmuneType.Physical) == ImmuneType.Physical) ||
+ (damageType == DamageType.Magical && (enemy.ImmuneType & ImmuneType.Magical) == ImmuneType.Magical);
if (isImmune)
{
+ if (isNormalAttack)
+ {
+ if (actor.NormalAttack.IgnoreImmune == ImmuneType.All ||
+ (damageType == DamageType.Physical && actor.NormalAttack.IgnoreImmune == ImmuneType.Physical) ||
+ (damageType == DamageType.Magical && actor.NormalAttack.IgnoreImmune == ImmuneType.Magical))
+ {
+ ignore = true;
+ }
+ }
effects = [.. characters.SelectMany(c => c.Effects.Where(e => e.IsInEffect)).Distinct()];
foreach (Effect effect in effects)
{
- if (isNormalAttack)
+ if (!effect.OnDamageImmuneCheck(actor, enemy, isNormalAttack, damageType, magicType, damage))
{
- if (actor.NormalAttack.IgnoreImmune == ImmuneType.All ||
- (damageType == DamageType.Physical && actor.NormalAttack.IgnoreImmune == ImmuneType.Physical) ||
- (damageType == DamageType.Magical && actor.NormalAttack.IgnoreImmune == ImmuneType.Magical) ||
- !effect.OnDamageImmuneCheck(actor, enemy, isNormalAttack, damageType, magicType, damage))
- {
- ignore = true;
- }
- }
- else
- {
- if (!effect.OnDamageImmuneCheck(actor, enemy, isNormalAttack, damageType, magicType, damage))
- {
- ignore = true;
- }
+ ignore = true;
}
}
}
@@ -1944,7 +1945,15 @@ namespace Milimoe.FunGame.Core.Model
}
_stats[death].Deaths += 1;
- string msg = $"[ {killer} ] 反补了 [ {death} ]!";
+ string msg = $"[ {killer} ] 反补了 [ {death} ]![ {killer} ] 受到了击杀队友惩罚,扣除 200 {GameplayEquilibriumConstant.InGameCurrency}并且当前连杀计数减少一次!!";
+ if (!_earnedMoney.TryAdd(killer, -200))
+ {
+ _earnedMoney[killer] -= 200;
+ }
+ if (_continuousKilling.TryGetValue(killer, out int times) && times > 0)
+ {
+ _continuousKilling[killer] -= 1;
+ }
LastRound.DeathContinuousKilling.Add(msg);
WriteLine(msg);
@@ -2987,7 +2996,8 @@ namespace Milimoe.FunGame.Core.Model
foreach (Character target in loop)
{
bool ignore = false;
- bool isImmune = target.ImmuneType == ImmuneType.Magical || target.ImmuneType == ImmuneType.Skilled || target.ImmuneType == ImmuneType.All;
+ bool isImmune = (skill.IsMagic && (target.ImmuneType & ImmuneType.Magical) == ImmuneType.Magical) ||
+ (target.ImmuneType & ImmuneType.Skilled) == ImmuneType.Skilled || (target.ImmuneType & ImmuneType.All) == ImmuneType.All;
if (isImmune)
{
Character[] characters = [character, target];
@@ -3004,11 +3014,11 @@ namespace Milimoe.FunGame.Core.Model
if (ignore)
{
isImmune = false;
- targets.Remove(target);
}
if (isImmune)
{
- WriteLine($"[ {target} ] 免疫了此技能!");
+ targets.Remove(target);
+ WriteLine($"[ {character} ] 想要对 [ {target} ] 释放技能 [ {skill.Name} ],但是被 [ {target} ] 免疫了!");
await OnCharacterImmunedAsync(character, target, skill, item);
}
}
diff --git a/Model/TeamGamingQueue.cs b/Model/TeamGamingQueue.cs
index 21c742b..ef4d197 100644
--- a/Model/TeamGamingQueue.cs
+++ b/Model/TeamGamingQueue.cs
@@ -114,10 +114,20 @@ namespace Milimoe.FunGame.Core.Model
///
protected override async Task OnDeathCalculation(Character death, Character killer)
{
+ if (killer == death)
+ {
+ return;
+ }
Team? team = GetTeam(killer);
if (team != null)
{
- team.Score++;
+ Team? team2 = GetTeam(death);
+ if (team == team2)
+ {
+ WriteLine($"[ {team} ] 受到了击杀队友惩罚!减少死亡竞赛得分!!");
+ team.Score--;
+ }
+ else team.Score++;
}
else await Task.CompletedTask;
}