using System; using System.Collections.Generic; using System.Linq; using ET.EventType; using NCalc; namespace ET { [FriendClass(typeof(Fighter))] [FriendClass(typeof(Battle))] [FriendClass(typeof(Skill))] [FriendClass(typeof(Buff))] [FriendClass(typeof(Modifier))] public static class BattleSystem { public static void EnterBattle(this Battle self, List fighterProtos, List enemyProtos) { foreach (var v in fighterProtos) { Fighter fighter = self.AddChildWithId(v.Id); fighter.FromMessage(v); fighter.Pos = v.Pos; self.FighterDic[v.Id] = fighter; self.FighterPosDic[v.Pos] = fighter; fighter.Camp = 1; self.AliveFightDic[fighter.Id] = fighter; } foreach (var v in enemyProtos) { Fighter fighter = self.AddChildWithId(v.Id); fighter.FromMessage(v); fighter.Pos = v.Pos; self.EnemyDic[v.Id] = fighter; self.EnemyPosDic[v.Pos] = fighter; fighter.Camp = 2; self.AliveFightDic[fighter.Id] = fighter; } self.BattleState = ConstBattleState.BATTLE_STATE_FIGHT; } public static void SetRandomSeed(this Battle self, int seed) { self.random.SetSeed(seed); } public static int GetRandomInt(this Battle self, int max = 100) { return self.random.RandomNumber(0, max); } public static bool GetRandomBool(this Battle self) { return self.random.RandomBool(); } public static void ResetFightList(this Battle self) { self.FightList.Clear(); foreach (var v in self.FighterPosDic.Values) { self.FightList.Add(v); } foreach (var v in self.EnemyPosDic.Values) { self.FightList.Add(v); } } private static void ResetRound(this Battle self) //重置整改回合 { self.BattleRound++; self.ResetFightList(); self.AtkIndex = 0; foreach (var fighter in self.FightList) { fighter.OnTriggerContinue(ConstContinueType.CONTINUE_ROUND); //刷新所有的BUFF fighter.UpdateAtkSpeed(); } self.FightList.Sort(((x, y) => { if (x.AtkSpeed > y.AtkSpeed) { return 1; } else if (x.AtkSpeed == y.AtkSpeed) { return 0; } return -1; })); self.OnRoundResetEvent(); //self.BattleAtk(); } private static int CompareBySpeed(this Battle self, Fighter x, Fighter y) { if (x.AtkSpeed > y.AtkSpeed) { return 1; } else if (x.AtkSpeed == y.AtkSpeed) { return 0; } return -1; } public static int UseSkill(this Battle self, long atkId, int skillId, int camp) { Fighter atker = null; if (camp == 1) { self.FighterDic.TryGetValue(atkId, out atker); } else { self.EnemyDic.TryGetValue(atkId, out atker); } if (atker != null && atker.IsAlive) { var skill = atker.GetComponent().GetSkill(skillId); if (skill != null) { var uskSkill = atker.UseSkill(skill); if (uskSkill != ErrorCode.ERR_Success) { return uskSkill; } var skillUseInfo = new SkillUseInfo() { Atker = atker, Skill = skill }; self.SkillUseQueue.Enqueue(skillUseInfo); self.BattleAtk(); } } return ErrorCode.ERR_Success; } public static void BattleAtk(this Battle self) { if (self.BattleState != ConstBattleState.BATTLE_STATE_FIGHT) { return; } self.BAtkAdd = false; self.BAtkBack = false; self.Defer = null; self.AtkAdder = null; self.AtkTrigger = true; self.DefTrigger = true; self.IsInterrupt = false; self.IsIntervene = true; self.TurnInfo = new TurnInfo(); self.TurnInfo.AtkList = new List(); if (self.SkillUseQueue.Count > 0) { var skillUseInfo = self.SkillUseQueue.Dequeue(); if (skillUseInfo.Atker.IsAlive) { self.FatherSkillAtk(skillUseInfo.Atker, skillUseInfo.Skill.ConfigId, skillUseInfo.Skill.Level); skillUseInfo.Skill.ResetCd(); } return; } if (self.FightList.Count <= self.AtkIndex) { self.ResetRound(); } var atker = self.FightList[self.AtkIndex]; self.AtkIndex++; if (!atker.IsAlive) { self.BattleAtk(); return; } self.FatherSkillAtk(atker, atker.AtkId); self.OnNomalAtkEvent(); //self.FatherSkillAtk(atker, 2); foreach (var v in self.FightList) { v.OnTriggerContinue(ConstContinueType.CONTINUE_ATK_TIMES); } } public static void FatherSkillAtk(this Battle self, Fighter atker, int skillId, int skillLv = 1) { SkillFatherConfig skillFather = SkillFatherConfigCategory.Instance.Get(skillId); self.TurnInfo.SkillFatherId = skillId; foreach (var v in skillFather.SkillSonGroup) { if (self.BattleState != ConstBattleState.BATTLE_STATE_FIGHT) { return; } //如果有打断 if (self.IsInterrupt) { break; } self.SonSkillAtk(atker, v, skillLv); } //如果有反击, if (self.BAtkBack) { skillFather = SkillFatherConfigCategory.Instance.Get(self.Defer.AtkId); self.AtkInfo = new AtkInfo(); self.AtkInfo.AtkId = self.Defer.Id; self.AtkInfo.AtkType = ConstAtkType.ATK_BACK; self.AtkInfo.TargetId = atker.Id; self.AtkInfo.HurtList = new List(); self.Effect(self.Defer, atker, 1, 1, false); self.TurnInfo.AtkList.Add(self.AtkInfo); } //如果有追击 if (self.BAtkAdd) { skillFather = SkillFatherConfigCategory.Instance.Get(self.AtkAdder.AtkId); self.AtkInfo = new AtkInfo(); self.AtkInfo.AtkId = self.AtkAdder.Id; self.AtkInfo.AtkType = ConstAtkType.ATK_HUNT; self.AtkInfo.TargetId = self.Defer.Id; self.AtkInfo.HurtList = new List(); self.Effect(self.AtkAdder, self.Defer, 1, 1, false); self.TurnInfo.AtkList.Add(self.AtkInfo); } #if !SERVER //抛出开始攻击的事件 Game.EventSystem.Publish(new EventType.AttackRound() { ZoneScene = self.ZoneScene(), TurnInfo = self.TurnInfo }); #endif } public static void SonSkillAtk(this Battle self, Fighter atker, int sonSkillId, int skillLv) { //抛出攻击的事件AtkInfo self.AtkInfo = new AtkInfo(); self.AtkInfo.AtkId = atker.Id; self.AtkInfo.AtkType = ConstAtkType.ATK_ACTIVE; self.AtkInfo.TargetId = 0; self.AtkInfo.HurtList = new List(); self.AtkInfo.SonSkillId = sonSkillId; self.InterveneFighter = null; self.IsIntervene = true; var skillSonConfig = SkillSonConfigCategory.Instance.Get(sonSkillId); var fighter = self.GetTarget(atker, skillSonConfig.ObjectType); self.Defer = fighter; self.AtkInfo.TargetId = fighter.Id; var targetList = self.GetTargetList(atker, fighter, skillSonConfig.ObjectType, skillSonConfig.ScopeType); //判断有没有暴击 self.CritValue = 1.0; self.AtkInfo.IsCrit = false; if (skillSonConfig.WhetherToCrit == ConstBool.CONST_TRUE && self.GetRandomBool()) { self.CritValue = WorldParametersConfigCategory.Instance.Get(WorldParam.CritMultiplier).Value[0] / 100.0; self.AtkInfo.IsCrit = true; } //判断援护 // self.InterveneFighter = self.GetInterveneFighter(fighter); // if (self.IsIntervene == false && self.InterveneFighter != null && skillSonConfig.CanBeSupport == 2) // { // self.IsIntervene = true; // } foreach (var v in skillSonConfig.Buff) { if (self.BattleState != ConstBattleState.BATTLE_STATE_FIGHT) { return; } foreach (var t in targetList) { if (self.InterveneFighter != null && t.Id == fighter.Id) { self.CastSkillBuff(atker, self.InterveneFighter, v, sonSkillId, skillLv); } else { self.CastSkillBuff(atker, t, v, sonSkillId, skillLv); } } } //释放次级技能 var unlockSkillList = SkillUpConfigCategory.Instance.GetUnLockedSkillsOfLevel(sonSkillId, skillLv); foreach (var v in skillSonConfig.SkillSon) { if (v == 0) { continue; } var sonSkillConfig = SkillSonConfigCategory.Instance.Get(v); if ((unlockSkillList != null && unlockSkillList.Contains(v)) || sonSkillConfig.Unlock == 2) { //触发概率 if (sonSkillConfig.TriggerParameter == 100 || self.GetRandomInt() < sonSkillConfig.TriggerParameter) { self.UnlockSkillAtk(atker, fighter, v, skillLv); } } } //判断能不能打断 // if (skillSonConfig.CanBeChase == 2 && self.GetRandomBool()) // { // self.IsInterrupt = true; // } self.TurnInfo.AtkList.Add(self.AtkInfo); } public static Fighter GetInterveneFighter(this Battle self, Fighter defer) { if (defer.Camp == 1) { foreach (var v in self.FighterPosDic.Values) { if (v.Id != defer.Id) { if (self.GetRandomInt() < 30) { return v; } } } } return null; } public static void UnlockSkillAtk(this Battle self, Fighter atker, Fighter defer, int unlockskillId, int skillLv) { var skillSonConfig = SkillSonConfigCategory.Instance.Get(unlockskillId); var targetList = self.GetTargetList(atker, defer, skillSonConfig.ObjectType, skillSonConfig.ScopeType); foreach (var v in skillSonConfig.Buff) { if (self.BattleState != ConstBattleState.BATTLE_STATE_FIGHT) { return; } foreach (var fighter in targetList) { self.CastSkillBuff(atker, fighter, v, unlockskillId, skillLv); } } } public static void CastSkillBuff(this Battle self, Fighter atker, Fighter defer, int buffId, int skillId, int skillLv) { var buffConfig = SkillBuffConfigCategory.Instance.Get(buffId); foreach (var v in buffConfig.LinkEffect) { if (self.BattleState != ConstBattleState.BATTLE_STATE_FIGHT) { return; } if (v == 0) { continue; } self.AddBuff(atker, defer, buffConfig, skillLv); } foreach (var v in buffConfig.StartTrigger) { if (v == 0) { continue; } self.Effect(atker, defer, v, skillLv, false); } } public static List GetTargetList(this Battle self, Fighter atker, Fighter defer, int targetType, int ScopeType) { var fighterPosDic = self.FighterPosDic; if (defer.Camp == 2) { fighterPosDic = self.EnemyPosDic; } List targetList = new List(); switch ((SkillSonScopeTypeEnum) ScopeType) { case 0: case SkillSonScopeTypeEnum.SINGLE: //单人 targetList.Add(defer); break; case SkillSonScopeTypeEnum.COL: //目标一列 int[] arr1 = { -6, -3, 0, 3, 6 }; foreach (var pos in arr1) { if (fighterPosDic.ContainsKey(pos + defer.Pos)) { targetList.Add(fighterPosDic[pos + defer.Pos]); } } break; case SkillSonScopeTypeEnum.COL_RID: //目标背后一列 int[] arr2 = { 3, 6 }; foreach (var pos in arr2) { if (fighterPosDic.ContainsKey(pos + defer.Pos)) { targetList.Add(fighterPosDic[pos + defer.Pos]); } } break; case SkillSonScopeTypeEnum.ROW: //目标和目标横向一排 int[] arr3 = { -2, -1, 0, 1, 2 }; foreach (var pos in arr3) { if (fighterPosDic.ContainsKey(pos + defer.Pos)) { targetList.Add(fighterPosDic[pos + defer.Pos]); } } break; case SkillSonScopeTypeEnum.ROW_RID: //目标横向一排 int[] arr4 = { -2, -1, 1, 2 }; foreach (var pos in arr4) { if (fighterPosDic.ContainsKey(pos + defer.Pos)) { targetList.Add(fighterPosDic[pos + defer.Pos]); } } break; case SkillSonScopeTypeEnum.ADJACENT_RID: //目标相连的周围,不包括目标自己 int[] arr5 = { -4, -3, -2 - 1, 1, 2, 3, 4 }; foreach (var pos in arr5) { if (fighterPosDic.ContainsKey(pos + defer.Pos)) { targetList.Add(fighterPosDic[pos + defer.Pos]); } } break; case SkillSonScopeTypeEnum.TOTAL_RID: //目标全体,不包含目标 fighterPosDic.Remove(defer.Pos); return fighterPosDic.Values.ToList(); case SkillSonScopeTypeEnum.TOTAL: return fighterPosDic.Values.ToList(); } return targetList; } public static Fighter GetTarget(this Battle self, Fighter atker, int targetType) { Fighter defer = null; switch ((SkillSonObjectTypeEnum) targetType) { case SkillSonObjectTypeEnum.MYSELF: //自己 defer = atker; break; case SkillSonObjectTypeEnum.DEFER: //敌方目标 if (atker.Camp == 1) { defer = self.GetAtkTarget(atker.Pos, self.EnemyPosDic); } else { defer = self.GetAtkTarget(atker.Pos, self.FighterPosDic); } break; case SkillSonObjectTypeEnum.RAND_FRIEND: //己全体随机 if (atker.Camp == 1) { defer = RandomHelper.RandomArray(self.FighterPosDic.Values.ToArray()); } else { defer = RandomHelper.RandomArray(self.EnemyPosDic.Values.ToArray()); } break; case SkillSonObjectTypeEnum.RAND_ENEMY: //敌方全体随机 if (atker.Camp == 2) { defer = RandomHelper.RandomArray(self.FighterPosDic.Values.ToArray()); } else { defer = RandomHelper.RandomArray(self.EnemyPosDic.Values.ToArray()); } break; case SkillSonObjectTypeEnum.HP_LOW_PERCENT: //己方血量百分比最低 if (atker.Camp == 1) { defer = self.GetHpPercentLeast(self.FighterPosDic); } else { defer = self.GetHpPercentLeast(self.EnemyPosDic); } break; case SkillSonObjectTypeEnum.ENEMY_HP_LOW_PERCENT: //敌方血量最低的 if (atker.Camp == 2) { defer = self.GetHpPercentLeast(self.FighterPosDic); } else { defer = self.GetHpPercentLeast(self.EnemyPosDic); } break; } return defer; } public static Fighter GetHpPercentLeast(this Battle self, Dictionary fightDic) { double percent = 1.0; int index = 0; foreach (var v in fightDic) { if (index == 0) { index = v.Key; } var nc = v.Value.GetComponent(); var temp = nc.GetAsInt(NumericType.HP) * 1.0 / nc.GetAsInt(NumericType.HpMax); if (temp <= percent) { percent = temp; index = v.Key; } } return fightDic[index]; } public static void AddBuff(this Battle self, Fighter atker, Fighter defer, SkillBuffConfig buffConfig, int skillLv) { var defBufCom = defer.GetOrAddComponent(); var buff = defBufCom.GetChild(buffConfig.Id); if (buff == null) { buff = defBufCom.AddChild(buffConfig.Id); buff.SkillLv = skillLv; foreach (var effectId in buffConfig.LinkEffect) { if (effectId == 0) { continue; } var modifier = buff.AddChild(effectId, defer.Id); var effectConfig = SkillEffectConfigCategory.Instance.Get(effectId); modifier.Value = self.NcalcValue(atker, defer, effectConfig.NumericExpression, skillLv); modifier.OneValue = modifier.Value; if (!defer.ModifierDic.Keys.Contains(effectConfig.EffectConfig)) { defer.ModifierDic[effectConfig.EffectConfig] = new List(); } defer.ModifierDic[effectConfig.EffectConfig].Add(modifier); } } else { foreach (var effectId in buffConfig.LinkEffect) { if (effectId == 0) { return; } var modifier = buff.GetChild(effectId); if (modifier != null) { if (buffConfig.Overlay == 2 && buffConfig.OverlayMax > buff.BuffLayer) { modifier.Value += modifier.OneValue; buff.BuffLayer += 1; } } } } buff.Duration = buffConfig.ContinuedParameter; self.OnBuffAdd(atker, defer, buffConfig, skillLv); } public static void RemoveBuff(this Battle self, Fighter fighter, int buffId, int skillLv) { var buff = fighter.GetComponent().GetChild(buffId); foreach (var v in buff.Children.Values) { var modifier = (Modifier) v; fighter.ModifierDic[modifier.Config.EffectConfig].Remove(modifier); fighter.OnModifierChange(modifier.Config.EffectConfig); } buff.Dispose(); } //生效 public static void Effect(this Battle self, Fighter atker, Fighter defer, int effectId, int skillLv, bool bTrigger = true) { var effectConfig = SkillEffectConfigCategory.Instance.Get(effectId); //判断是否要追击 //判断是否反击 //判断是否掩护 switch ((SkillEffectEffectConfigEnum) effectConfig.EffectConfig) { case SkillEffectEffectConfigEnum.HP: //伤害类型 var hurter = defer; var damage = self.NcalcValue(atker, hurter, effectConfig.NumericExpression, skillLv); damage = (int) (damage * self.CritValue); //int damage = 10; self.OnDamage(atker, hurter, damage, defer.Id); // //如果触发了援护就不触发反击和追击 // if (hurter.Id != defer.Id) // { // break; // } // // if (bTrigger) // { // if (!self.DefTrigger && !atker.IsRange() && !defer.IsRange()) // { // self.BAtkBack = self.GetRandomBool(); // if (self.BAtkBack) // { // self.DefTrigger = true; // } // } // // if (!self.AtkTrigger) // { // self.BAtkAdd = self.GetRandomBool(); // if (self.BAtkAdd) // { // self.AtkTrigger = true; // // if (atker.Camp == 1) // { // var atkPosList = self.FighterPosDic.Keys.ToList(); // atkPosList.Remove(atker.Pos); // if (atkPosList.Count == 0) // { // self.AtkTrigger = false; // self.BAtkAdd = false; // return; // } // // var pos = self.GetRandomInt(atkPosList.Count); // self.AtkAdder = self.FighterPosDic[atkPosList[pos]]; // } // else // { // var atkPosList = self.EnemyPosDic.Keys.ToList(); // atkPosList.Remove(atker.Pos); // if (atkPosList.Count == 0) // { // self.AtkTrigger = false; // self.BAtkAdd = false; // return; // } // // var pos = self.GetRandomInt(atkPosList.Count); // self.AtkAdder = self.EnemyPosDic[atkPosList[pos]]; // } // } // } // } break; case SkillEffectEffectConfigEnum.SPRIT_RESTORE: //战意恢复 break; case SkillEffectEffectConfigEnum.ARMOR: //破甲 break; } } public static void OnDamage(this Battle self, Fighter atker, Fighter defer, int damage, long targetId) { var hurtType = 1; var rate = 1.0; if (defer.Id == targetId) { (hurtType, rate) = defer.GetParry(); } else { hurtType = ConstHurtType.HURT_SHIELD; } var reallydamage = (int) (Math.Min(1 - defer.GetDef() * 0.1, 0.8) * damage * rate); var nc = defer.GetComponent(); var hp = nc.GetAsInt(NumericType.HP) + reallydamage; if (hp <= 0) { self.OnFighterDie(defer); } if (hp > nc.GetAsInt(NumericType.HpMax)) { hp = nc.GetAsInt(NumericType.HpMax); } nc.Set(NumericType.HP, hp); //收集伤害 var hurtInfo = new HurtInfo(); hurtInfo.IsAlive = defer.IsAlive; hurtInfo.TargetId = targetId; hurtInfo.HurtId = defer.Id; hurtInfo.HurtType = hurtType; hurtInfo.Damage = reallydamage; self.AtkInfo.HurtList.Add(hurtInfo); } public static Fighter GetAtkTarget(this Battle self, int pos, Dictionary FighterPosDic) { int[,] Arr = new int[3,9] { { 3, 6, 9, 2, 5, 8, 1, 4, 7 }, { 1, 4, 7, 2, 5, 8, 3, 6, 9 }, { 2, 5, 8, 1, 4, 7, 3, 6, 9 } }; var row = pos % 3; for (int i = 0; i < 9; i++) { if (FighterPosDic.ContainsKey(Arr[row, i])) { return FighterPosDic[Arr[row, i]]; } } return null; } //是否命中 public static bool IsAtkSuc(this Battle self, Fighter atker, Fighter defer) { var val = atker.GetHit() - defer.GetDodge(); var randVal = self.random.RandomNumber(0, 100); if (randVal < val) { return true; } return false; } public static Fighter GetPlayerFighter(this Battle self, long id) { if (self.FighterDic.TryGetValue(id, out Fighter fighter)) { return fighter; } return null; } public static Fighter GetEnemy(this Battle self, long id) { if (self.EnemyDic.TryGetValue(id, out Fighter fighter)) { return fighter; } return null; } public static Fighter GetFighter(this Battle self, long id) { var fighter = self.GetPlayerFighter(id); if (fighter == null) { fighter = self.GetEnemy(id); } return fighter; } public static int NcalcValue(this Battle self, Fighter atker, Fighter defer, string str, int skillLv) { Expression e = new Expression(str); e.Parameters["ATK_P"] = atker.GetAtk(); e.Parameters["DEF_E"] = defer.GetDef(); e.Parameters["LvSkill"] = skillLv; e.Parameters["HP_F"] = defer.GetHp(); e.Parameters["Strength_P"] = defer.GetHp(); var v = e.Evaluate(); return Convert.ToInt32(v); } //加到buff的时候的触发事件 public static void OnBuffAdd(this Battle self, Fighter fighter, Fighter defer, SkillBuffConfig buffConfig, int skillLv) { if (buffConfig.StartTrigger.Length > 0) { foreach (var effectId in buffConfig.StartTrigger) { if (effectId > 0) { self.Effect(fighter, defer, effectId, skillLv); } } } } //buff消失的触发事件 public static void OnBuffRemove(this Battle self, Fighter fighter, Fighter defer, int buffId, int skillLv) { var buffConfig = SkillBuffConfigCategory.Instance.Get(buffId); if (buffConfig.EndTrigger > 0) { self.Effect(fighter, defer, buffConfig.EndTrigger, skillLv); } } //普攻触发事件 public static void OnTurnEvent(this Battle self) { foreach (var v in self.AliveFightDic.Values) { v.OnTurnEvent(); } } //战斗结束 public static void OnBattleOver(this Battle self, int result) { if (result == ConstBattleState.BATTLE_STATE_WIN && self.BattleType == ConstBattleType.BATTLE_PVE) { var unit = self.GetParent(); unit.GetComponent().KillMonsterGroup(unit, self.EnemyId); //加奖励 foreach (var pair in self.DropDic) { StoreOperate.AddItem(unit,pair.Key,pair.Value); } } } //有一个战斗单位死亡 public static void OnFighterDie(this Battle self, Fighter defer) { defer.IsAlive = false; #if !SERVER Unit unit = UnitHelper.GetMyUnitFromZoneScene(self.ZoneScene()); Game.EventSystem.Publish(new EventType.BattleUnitDie() { Unit = unit, BattleUnitId = defer.Id }); #endif if (defer.Camp == 1) { self.FighterPosDic.Remove(defer.Pos); if (self.FighterPosDic.Count == 0) { self.BattleState = ConstBattleState.BATTLE_STATE_FAIL; self.OnBattleOver(self.BattleState); } } else { //产生掉落 if (self.BattleType == ConstBattleType.BATTLE_PVE) { var (itemId, itemNum) = self.GetParent().GetComponent().GetMonsterGroupById(self.EnemyId) .MonsterDrop(defer); self.Drop(itemId, itemNum); #if !SERVER Game.EventSystem.Publish(new EventType.BattleUnitDrop() { Unit = unit, BattleUnitId = defer.Id, ItemId = itemId, ItemNum = itemNum}); #endif } self.EnemyPosDic.Remove(defer.Pos); if (self.EnemyPosDic.Count == 0) { self.BattleState = ConstBattleState.BATTLE_STATE_WIN; self.OnBattleOver(self.BattleState); } } self.AliveFightDic.Remove(defer.Id); } public static void Drop(this Battle self, int itemId, int itemNum) { if (self.DropDic.Values.Contains(itemId)) { self.DropDic[itemId] += itemNum; } else { self.DropDic[itemId] = itemNum; } } //重置回合事件 public static void OnRoundResetEvent(this Battle self) { self.SkillCdEvent(SkillFatherCDTypeEnum.ROUND); } //普攻触发事件 public static void OnNomalAtkEvent(this Battle self) { self.SkillCdEvent(SkillFatherCDTypeEnum.NORMAL_ATTACK_TIMES); self.RecoverSpirit(); } public static void SkillCdEvent(this Battle self, SkillFatherCDTypeEnum cdTypeEnum) { foreach (var fighter in self.AliveFightDic.Values) { fighter.GetComponent()?.CdOneTime(cdTypeEnum); } } public static void RecoverSpirit(this Battle self) { foreach (var fighter in self.AliveFightDic.Values) { fighter.RecoverSpirit(); } } } }