You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
962 lines
33 KiB
962 lines
33 KiB
3 years ago
|
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<FighterProto> fighterProtos, List<FighterProto> enemyProtos)
|
||
|
{
|
||
|
foreach (var v in fighterProtos)
|
||
|
{
|
||
|
Fighter fighter = self.AddChildWithId<Fighter>(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<Fighter>(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<SkillComponent>().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<AtkInfo>();
|
||
|
|
||
|
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<HurtInfo>();
|
||
|
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<HurtInfo>();
|
||
|
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<HurtInfo>();
|
||
|
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<Fighter> GetTargetList(this Battle self, Fighter atker, Fighter defer, int targetType, int ScopeType)
|
||
|
{
|
||
|
var fighterPosDic = self.FighterPosDic;
|
||
|
if (defer.Camp == 2)
|
||
|
{
|
||
|
fighterPosDic = self.EnemyPosDic;
|
||
|
}
|
||
|
|
||
|
List<Fighter> targetList = new List<Fighter>();
|
||
|
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<int, Fighter> fightDic)
|
||
|
{
|
||
|
double percent = 1.0;
|
||
|
int index = 0;
|
||
|
foreach (var v in fightDic)
|
||
|
{
|
||
|
if (index == 0)
|
||
|
{
|
||
|
index = v.Key;
|
||
|
}
|
||
|
|
||
|
var nc = v.Value.GetComponent<NumericComponent>();
|
||
|
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<BuffComponent>();
|
||
|
var buff = defBufCom.GetChild<Buff>(buffConfig.Id);
|
||
|
if (buff == null)
|
||
|
{
|
||
|
buff = defBufCom.AddChild<Buff, int>(buffConfig.Id);
|
||
|
buff.SkillLv = skillLv;
|
||
|
foreach (var effectId in buffConfig.LinkEffect)
|
||
|
{
|
||
|
if (effectId == 0)
|
||
|
{
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
var modifier = buff.AddChild<Modifier, int, long>(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<Modifier>();
|
||
|
}
|
||
|
|
||
|
defer.ModifierDic[effectConfig.EffectConfig].Add(modifier);
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
foreach (var effectId in buffConfig.LinkEffect)
|
||
|
{
|
||
|
if (effectId == 0)
|
||
|
{
|
||
|
return;
|
||
|
}
|
||
|
var modifier = buff.GetChild<Modifier>(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<BuffComponent>().GetChild<Buff>(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<NumericComponent>();
|
||
|
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<int, Fighter> 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>();
|
||
|
unit.GetComponent<MonsterGroupComponent>().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<Unit>().GetComponent<MonsterGroupComponent>().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<SkillComponent>()?.CdOneTime(cdTypeEnum);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
public static void RecoverSpirit(this Battle self)
|
||
|
{
|
||
|
foreach (var fighter in self.AliveFightDic.Values)
|
||
|
{
|
||
|
fighter.RecoverSpirit();
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|