添加攻击受限和让施法者目标丢失的打断施法方法

This commit is contained in:
milimoe 2025-04-17 00:17:17 +08:00
parent 56d2dc6756
commit f4320e8212
Signed by: milimoe
GPG Key ID: 05D280912DA6C69E
5 changed files with 92 additions and 31 deletions

View File

@ -1778,6 +1778,7 @@ namespace Milimoe.FunGame.Core.Entity
bool isActionRestricted = false; bool isActionRestricted = false;
bool isBattleRestricted = false; bool isBattleRestricted = false;
bool isSkillRestricted = false; bool isSkillRestricted = false;
bool isAttackRestricted = false;
IEnumerable<CharacterState> states = CharacterEffectStates.Values.SelectMany(list => list); IEnumerable<CharacterState> states = CharacterEffectStates.Values.SelectMany(list => list);
// 根据持有的特效判断角色所处的状态 // 根据持有的特效判断角色所处的状态
@ -1785,12 +1786,13 @@ namespace Milimoe.FunGame.Core.Entity
isActionRestricted = states.Any(state => state == CharacterState.ActionRestricted); isActionRestricted = states.Any(state => state == CharacterState.ActionRestricted);
isBattleRestricted = states.Any(state => state == CharacterState.BattleRestricted); isBattleRestricted = states.Any(state => state == CharacterState.BattleRestricted);
isSkillRestricted = states.Any(state => state == CharacterState.SkillRestricted); isSkillRestricted = states.Any(state => state == CharacterState.SkillRestricted);
isAttackRestricted = states.Any(state => state == CharacterState.AttackRestricted);
IEnumerable<EffectType> types = CharacterEffectTypes.Values.SelectMany(list => list); IEnumerable<EffectType> types = CharacterEffectTypes.Values.SelectMany(list => list);
// 判断角色的控制效果 // 判断角色的控制效果
IsUnselectable = types.Any(type => type == EffectType.Unselectable); IsUnselectable = types.Any(type => type == EffectType.Unselectable);
bool isControl = isNotActionable || isActionRestricted || isBattleRestricted || isSkillRestricted; bool isControl = isNotActionable || isActionRestricted || isBattleRestricted || isSkillRestricted || isAttackRestricted;
bool isCasting = CharacterState == CharacterState.Casting; bool isCasting = CharacterState == CharacterState.Casting;
bool isPreCastSuperSkill = CharacterState == CharacterState.PreCastSuperSkill; bool isPreCastSuperSkill = CharacterState == CharacterState.PreCastSuperSkill;
@ -1810,6 +1812,10 @@ namespace Milimoe.FunGame.Core.Entity
{ {
CharacterState = CharacterState.SkillRestricted; CharacterState = CharacterState.SkillRestricted;
} }
else if (isAttackRestricted)
{
CharacterState = CharacterState.AttackRestricted;
}
if (!isControl && !isCasting && !isPreCastSuperSkill) if (!isControl && !isCasting && !isPreCastSuperSkill)
{ {

View File

@ -308,6 +308,7 @@ namespace Milimoe.FunGame.Core.Entity
{ {
selectable.AddRange(enemys); selectable.AddRange(enemys);
} }
if (CanSelectTeammate) if (CanSelectTeammate)
{ {
selectable.AddRange(teammates); selectable.AddRange(teammates);
@ -430,7 +431,7 @@ namespace Milimoe.FunGame.Core.Entity
builder.AppendLine("技能描述:" + (Level == 0 && GeneralDescription.Trim() != "" ? GeneralDescription : Description)); builder.AppendLine("技能描述:" + (Level == 0 && GeneralDescription.Trim() != "" ? GeneralDescription : Description));
if (CurrentCD > 0) if (CurrentCD > 0)
{ {
builder.AppendLine($"正在冷却:剩余 {CurrentCD:0.##} 时间"); builder.AppendLine($"正在冷却:剩余 {CurrentCD:0.##} {GameplayEquilibriumConstant.InGameTime}");
} }
if (!Enable) if (!Enable)
{ {

View File

@ -130,6 +130,12 @@ namespace Milimoe.FunGame.Core.Interface.Base
/// <param name="interrupter"></param> /// <param name="interrupter"></param>
public Task InterruptCastingAsync(Character caster, Character interrupter); public Task InterruptCastingAsync(Character caster, Character interrupter);
/// <summary>
/// 打断施法 [ 用于使敌人目标丢失 ]
/// </summary>
/// <param name="interrupter"></param>
public Task InterruptCastingAsync(Character interrupter);
/// <summary> /// <summary>
/// 使用物品 /// 使用物品
/// </summary> /// </summary>

View File

@ -57,6 +57,11 @@ namespace Milimoe.FunGame.Core.Library.Constant
/// 技能受限 [ 战斗相关 ] /// 技能受限 [ 战斗相关 ]
/// </summary> /// </summary>
SkillRestricted, SkillRestricted,
/// <summary>
/// 攻击受限 [ 战斗相关 ]
/// </summary>
AttackRestricted,
/// <summary> /// <summary>
/// 处于吟唱中 [ 战斗相关 ] [ 技能相关 ] /// 处于吟唱中 [ 战斗相关 ] [ 技能相关 ]

View File

@ -741,6 +741,15 @@ namespace Milimoe.FunGame.Core.Model
pCastSkill = 0; pCastSkill = 0;
} }
} }
else if (character.CharacterState == CharacterState.AttackRestricted)
{
// 攻击受限,无法普通攻击,可以使用技能,可以使用物品
pNormalAttack = 0;
if (!canUseItem)
{
pUseItem = 0;
}
}
// 模组可以通过此事件来决定角色的行动 // 模组可以通过此事件来决定角色的行动
type = await OnDecideActionAsync(character, enemys, teammates, skills, items); type = await OnDecideActionAsync(character, enemys, teammates, skills, items);
@ -779,29 +788,39 @@ namespace Milimoe.FunGame.Core.Model
if (type == CharacterActionType.NormalAttack) if (type == CharacterActionType.NormalAttack)
{ {
// 使用普通攻击逻辑 if (character.CharacterState == CharacterState.NotActionable ||
List<Character> targets = await SelectTargetsAsync(character, character.NormalAttack, enemys, teammates); character.CharacterState == CharacterState.ActionRestricted ||
if (targets.Count == 0 && _charactersInAI.Contains(character)) character.CharacterState == CharacterState.BattleRestricted ||
character.CharacterState == CharacterState.AttackRestricted)
{ {
// 如果没有选取目标,且角色在 AI 控制下,则随机选取目标 WriteLine($"角色 [ {character} ] 状态为:{CharacterSet.GetCharacterState(character.CharacterState)},无法使用普通攻击!");
if (enemys.Count > character.NormalAttack.CanSelectTargetCount)
targets = [.. enemys.OrderBy(o => Random.Shared.Next(enemys.Count)).Take(character.NormalAttack.CanSelectTargetCount)];
else
targets = [.. enemys];
} }
if (targets.Count > 0) else
{ {
LastRound.Targets = [.. targets]; // 使用普通攻击逻辑
decided = true; List<Character> targets = await SelectTargetsAsync(character, character.NormalAttack, enemys, teammates);
if (targets.Count == 0 && _charactersInAI.Contains(character))
await OnCharacterNormalAttackAsync(character, targets);
character.NormalAttack.Attack(this, character, targets);
baseTime = character.NormalAttack.HardnessTime;
effects = [.. character.Effects.Where(e => e.Level > 0)];
foreach (Effect effect in effects)
{ {
effect.AlterHardnessTimeAfterNormalAttack(character, ref baseTime, ref isCheckProtected); // 如果没有选取目标,且角色在 AI 控制下,则随机选取目标
if (enemys.Count > character.NormalAttack.CanSelectTargetCount)
targets = [.. enemys.OrderBy(o => Random.Shared.Next(enemys.Count)).Take(character.NormalAttack.CanSelectTargetCount)];
else
targets = [.. enemys];
}
if (targets.Count > 0)
{
LastRound.Targets = [.. targets];
decided = true;
await OnCharacterNormalAttackAsync(character, targets);
character.NormalAttack.Attack(this, character, targets);
baseTime = character.NormalAttack.HardnessTime;
effects = [.. character.Effects.Where(e => e.Level > 0)];
foreach (Effect effect in effects)
{
effect.AlterHardnessTimeAfterNormalAttack(character, ref baseTime, ref isCheckProtected);
}
} }
} }
} }
@ -1022,8 +1041,16 @@ namespace Milimoe.FunGame.Core.Model
// 统一在回合结束时处理角色的死亡 // 统一在回合结束时处理角色的死亡
await ProcessCharacterDeathAsync(character); await ProcessCharacterDeathAsync(character);
// 移除回合奖励
RemoveRoundRewards(TotalRound, character, rewards);
if (_isGameEnd) if (_isGameEnd)
{ {
// 回合结束事件
await OnTurnEndAsync(character);
await AfterTurnAsync(character);
return _isGameEnd; return _isGameEnd;
} }
@ -1069,9 +1096,6 @@ namespace Milimoe.FunGame.Core.Model
} }
} }
// 移除回合奖励
RemoveRoundRewards(TotalRound, character, rewards);
// 有人想要插队吗? // 有人想要插队吗?
await WillPreCastSuperSkill(); await WillPreCastSuperSkill();
@ -1895,6 +1919,7 @@ namespace Milimoe.FunGame.Core.Model
/// </summary> /// </summary>
public async Task EndGameInfo(Team winner) public async Task EndGameInfo(Team winner)
{ {
winner.IsWinner = true;
WriteLine("[ " + winner + " ] 是胜利者。"); WriteLine("[ " + winner + " ] 是胜利者。");
if (!await OnGameEndTeamAsync(winner)) if (!await OnGameEndTeamAsync(winner))
@ -2095,19 +2120,37 @@ namespace Milimoe.FunGame.Core.Model
} }
if (skill != null) if (skill != null)
{ {
WriteLine($"[ {caster} ] 的施法被 [ {interrupter} ] 打断了!!"); WriteLine($"[ {caster} ] 的{(skill.IsSuperSkill ? "" : "")}被 [ {interrupter} ] 打断了!!");
List<Effect> effects = [.. caster.Effects.Where(e => e.Level > 0)]; List<Effect> effects = [.. caster.Effects.Union(interrupter.Effects).Where(e => e.Level > 0)];
foreach (Effect effect in effects) foreach (Effect effect in effects)
{ {
effect.OnSkillCastInterrupted(caster, skill, interrupter); effect.OnSkillCastInterrupted(caster, skill, interrupter);
} }
effects = [.. interrupter.Effects.Where(e => e.Level > 0)]; await OnInterruptCastingAsync(caster, skill, interrupter);
foreach (Effect effect in effects) }
}
/// <summary>
/// 打断施法 [ 用于使敌人目标丢失 ]
/// </summary>
/// <param name="interrupter"></param>
public async Task InterruptCastingAsync(Character interrupter)
{
foreach (Character caster in _castingSkills.Keys)
{
SkillTarget skillTarget = _castingSkills[caster];
if (skillTarget.Targets.Contains(interrupter))
{ {
effect.OnSkillCastInterrupted(caster, skill, interrupter); Skill skill = skillTarget.Skill;
WriteLine($"[ {interrupter} ] 打断了 [ {caster} ] 的施法!!");
List<Effect> effects = [.. caster.Effects.Union(interrupter.Effects).Where(e => e.Level > 0)];
foreach (Effect effect in effects)
{
effect.OnSkillCastInterrupted(caster, skill, interrupter);
}
await OnInterruptCastingAsync(caster, skill, interrupter);
} }
} }
await OnInterruptCastingAsync(caster, skill, interrupter);
} }
/// <summary> /// <summary>
@ -2657,7 +2700,7 @@ namespace Milimoe.FunGame.Core.Model
/// <param name="skill"></param> /// <param name="skill"></param>
/// <param name="interrupter"></param> /// <param name="interrupter"></param>
/// <returns></returns> /// <returns></returns>
protected async Task OnInterruptCastingAsync(Character cast, Skill? skill, Character interrupter) protected async Task OnInterruptCastingAsync(Character cast, Skill skill, Character interrupter)
{ {
await (InterruptCasting?.Invoke(this, cast, skill, interrupter) ?? Task.CompletedTask); await (InterruptCasting?.Invoke(this, cast, skill, interrupter) ?? Task.CompletedTask);
} }