375 lines
13 KiB
C#
375 lines
13 KiB
C#
using Cal;
|
|
using Cal.DataTable;
|
|
using System;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
|
|
namespace ET
|
|
{
|
|
public class PlayerSkillAIAwakeSystem: AwakeSystem<SkillAI>
|
|
{
|
|
public override void Awake(SkillAI self)
|
|
{
|
|
}
|
|
}
|
|
|
|
public class SkillAIDestroySystem: DestroySystem<SkillAI>
|
|
{
|
|
public override void Destroy(SkillAI self)
|
|
{
|
|
self.CurrSkillNode = null;
|
|
self.AutoSkillList.Clear();
|
|
self.canSkill = false;
|
|
}
|
|
}
|
|
|
|
public static class PlayerSkillAISystem
|
|
{
|
|
public static bool CheckCD(this SkillAI self, long now)
|
|
{
|
|
if (self == null)
|
|
{
|
|
Log.Error($"skillAI = null");
|
|
return false;
|
|
}
|
|
|
|
if (now - self.lastSkillTime >= self.roundCD)
|
|
{
|
|
self.lastSkillTime = now;
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
public static void PlayAutoSkill(this SkillAI self, long now)
|
|
{
|
|
if (!self.canSkill) return;
|
|
self.canSkill = false;
|
|
LinkedList<int> skills = self.AutoSkillList;
|
|
if (skills.Count == 0) return;
|
|
PlaySkill(self, skills, now);
|
|
}
|
|
|
|
private static void PlaySkill(this SkillAI self, LinkedList<int> list, long now)
|
|
{
|
|
try
|
|
{
|
|
Unit unit = self.GetParent<Unit>();
|
|
int skillCount = list.Count;
|
|
for (int i = 0; i < skillCount; i++)
|
|
{
|
|
int skillId = self.GetCurrSkillId(list);
|
|
if (skillId == 0) continue;
|
|
string ret = self.PlaySkill(skillId, now, true);
|
|
if (ret == null)
|
|
{
|
|
SkillMgrComponent skillMgr = unit.GetComponent<SkillMgrComponent>();
|
|
SkillLogic skillLogic = skillMgr.GetSkill(skillId);
|
|
if (skillLogic == null)
|
|
{
|
|
Log.Error($"skillLogic == null where skillid = {skillId}");
|
|
return;
|
|
}
|
|
|
|
SetMainUICD(unit, skillId, skillLogic.skillConfig.CD);
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
catch (Exception e)
|
|
{
|
|
Log.Error(e);
|
|
}
|
|
}
|
|
|
|
private static void SetMainUICD(Unit unit, int id, int skillCD)
|
|
{
|
|
UserSetting userSetting = unit.GetComponent<UserSetting>();
|
|
userSetting.StartCD(MainUIType.SkillSlot, id, skillCD);
|
|
}
|
|
|
|
public static string PlaySkill(this SkillAI self, int skillId, long now, bool isAuto = false)
|
|
{
|
|
try
|
|
{
|
|
Unit unit = self.GetParent<Unit>();
|
|
if (skillId == 0)
|
|
{
|
|
Log.Error($"skillId == 0");
|
|
return "系统错误";
|
|
}
|
|
|
|
UnitSkill skill = unit.GetComponent<UnitSkillComponent>().GetLearnedSkill(skillId);
|
|
if (skill == UnitSkill.Null)
|
|
{
|
|
Log.Error($"【{UserComponent.Instance.Get(unit.Id)?.NickName} ({unit.Id})】使用了没学会的技能,技能id={skillId}");
|
|
return "系统错误";
|
|
}
|
|
|
|
int level = skill.Level;
|
|
//!+暂时
|
|
|
|
var skillLogic = GetSkillLogic(unit, skillId, level);
|
|
if (skillLogic == null)
|
|
{
|
|
Log.Error($"{unit.Id.GetPlayerFormatName()} has not the skill where skillId = {skillId} level = {level}");
|
|
return "系统错误,没有技能";
|
|
}
|
|
//!判断状态
|
|
if (CheckUnActionState(unit))
|
|
{
|
|
return "禁足";
|
|
}
|
|
|
|
return CheckSkillConditionAndSpell(now, unit, skillLogic, isAuto);
|
|
}
|
|
catch (Exception e)
|
|
{
|
|
Log.Error(e);
|
|
return "系统错误";
|
|
}
|
|
}
|
|
|
|
private static SkillLogic GetSkillLogic(Unit unit, int skillId, int level)
|
|
{
|
|
SkillMgrComponent skillMgr = unit.GetComponent<SkillMgrComponent>();
|
|
SkillLogic skillLogic = skillMgr.GetSkill(skillId);
|
|
if (skillLogic == null)
|
|
{
|
|
Log.Error($"skillLogic == null where skillid = {skillId}");
|
|
return null;
|
|
}
|
|
|
|
skillLogic.skillLevel = level;
|
|
return skillLogic;
|
|
}
|
|
|
|
private static string CheckSkillConditionAndSpell(long now, Unit unit, SkillLogic skillLogic, bool isAuto)
|
|
{
|
|
SkillLogicConfig skillConfig = skillLogic.skillLogicConfig;
|
|
if (now - skillLogic.lastCDTime < skillConfig.CD)
|
|
{
|
|
return "冷却中!";
|
|
}
|
|
|
|
string canCast = null;
|
|
SkillCastType skillCastType = skillConfig.cast.skillCastType;
|
|
switch (skillCastType)
|
|
{
|
|
case SkillCastType.无消耗:
|
|
break;
|
|
case SkillCastType.消耗精力:
|
|
if (!CastMp(unit, skillConfig.cast))
|
|
canCast = "精力不足!";
|
|
break;
|
|
case SkillCastType.消耗血量:
|
|
if (!CastHp(unit, skillConfig.cast))
|
|
canCast = "血量不足!";
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
|
|
if (isAuto)
|
|
{
|
|
if (canCast != null)
|
|
{
|
|
skillLogic = GetSkillLogic(unit, SkillHotfixHelper.GetNomalSkillId(unit), 1);
|
|
if (skillLogic == null)
|
|
{
|
|
Log.Error($"{unit.Id.GetPlayerFormatName()} has not the skill where skillId = {SkillHotfixHelper.GetNomalSkillId(unit)}");
|
|
}
|
|
skillConfig = skillLogic.skillLogicConfig;
|
|
if (now - skillLogic.lastCDTime < skillConfig.CD)
|
|
{
|
|
return "冷却中!";
|
|
}
|
|
return canCast;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (canCast != null) return canCast;
|
|
}
|
|
|
|
//!选择目标
|
|
TargetableUnitComponent targetComponent = unit.GetComponent<TargetableUnitComponent>();
|
|
if (!targetComponent)
|
|
{
|
|
Log.Error($"targetComponent == null where id = {unit.Id}");
|
|
return "系统错误";
|
|
}
|
|
|
|
targetComponent.SelectTarget(skillLogic.skillLogicConfig);
|
|
long time = skillLogic.lastCDTime;
|
|
skillLogic.lastCDTime = now;
|
|
//!执行技能逻辑
|
|
bool ret = unit.GetComponent<AttackComponent>().StartSpellSkill(skillLogic);
|
|
if (!ret)
|
|
{
|
|
skillLogic.lastCDTime = time;
|
|
return "特别原因";
|
|
}
|
|
|
|
return null;
|
|
}
|
|
|
|
private static bool CastHp(Unit unit, CastParam cast)
|
|
{
|
|
NumericComponent num = unit.GetComponent<NumericComponent>();
|
|
float hp = num.Get(NumericType.Hp);
|
|
float value = 0;
|
|
switch (cast.castBaseType)
|
|
{
|
|
case CastBaseType.Level:
|
|
float level = num.Get(NumericType.Level);
|
|
value = level * cast.skillCast;
|
|
break;
|
|
case CastBaseType.Curr:
|
|
float currHp = num.Get(NumericType.Hp);
|
|
value = currHp * cast.skillCast;
|
|
break;
|
|
case CastBaseType.Max:
|
|
float maxHp = num.Get(NumericType.MaxHp);
|
|
value = maxHp * cast.skillCast;
|
|
break;
|
|
case CastBaseType.Other:
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
|
|
if (hp < value)
|
|
return false;
|
|
num.ReduceSet(NumericType.Hp, value);
|
|
return true;
|
|
}
|
|
|
|
private static bool CastMp(Unit unit, CastParam cast)
|
|
{
|
|
NumericComponent num = unit.GetComponent<NumericComponent>();
|
|
float mp = num.Get(NumericType.Mp);
|
|
float value = 0;
|
|
switch (cast.castBaseType)
|
|
{
|
|
case CastBaseType.Level:
|
|
float level = num.Get(NumericType.Level);
|
|
value = level * cast.skillCast;
|
|
break;
|
|
case CastBaseType.Curr:
|
|
float currHp = num.Get(NumericType.Mp);
|
|
value = currHp * cast.skillCast;
|
|
break;
|
|
case CastBaseType.Max:
|
|
float maxHp = num.Get(NumericType.MaxMp);
|
|
value = maxHp * cast.skillCast;
|
|
break;
|
|
case CastBaseType.Other:
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
|
|
if (mp < value)
|
|
return false;
|
|
num.ReduceSet(NumericType.Mp, value);
|
|
return true;
|
|
}
|
|
|
|
/// <summary>
|
|
/// 怪物释放逻辑
|
|
/// </summary>
|
|
/// <param name="self"></param>
|
|
public static void PlaySkill(this SkillAI self)
|
|
{
|
|
try
|
|
{
|
|
Unit unit = self.GetParent<Unit>();
|
|
if (!unit) return;
|
|
LinkedList<int> list = self.AutoSkillList;
|
|
int skillId = self.GetCurrSkillId(list);
|
|
if (skillId == 0) return;
|
|
|
|
UnitSkillComponent skillConponent = unit.GetComponent<UnitSkillComponent>();
|
|
UnitSkill skill = skillConponent.GetLearnedSkill(skillId);
|
|
if (skill == UnitSkill.Null)
|
|
{
|
|
Log.Error($"skill == null where skillid = {skillId}");
|
|
return;
|
|
}
|
|
|
|
int level = skill.Level;
|
|
|
|
AttackComponent attacker = unit.GetComponent<AttackComponent>();
|
|
SkillMgrComponent skillMgr = unit.GetComponent<SkillMgrComponent>();
|
|
SkillLogic skillLogic = skillMgr.GetSkill(skillId);
|
|
if (skillLogic == null)
|
|
{
|
|
Log.Error($"skillLogic == null where skillid = {skillId}");
|
|
return;
|
|
}
|
|
|
|
skillLogic.skillLevel = level;
|
|
//!判断状态
|
|
if (CheckUnActionState(unit))
|
|
{
|
|
return;
|
|
}
|
|
|
|
//!选择目标
|
|
TargetableUnitComponent targetComponent = unit.GetComponent<TargetableUnitComponent>();
|
|
if (!targetComponent)
|
|
Log.Error($"targetComponent == null where id = {unit.Id}");
|
|
else
|
|
targetComponent.SelectTarget(skillLogic.skillLogicConfig);
|
|
attacker.StartSpellSkill(skillLogic);
|
|
}
|
|
catch (Exception e)
|
|
{
|
|
Log.Error(e);
|
|
}
|
|
}
|
|
|
|
public static void UpdateAutoSkill(this SkillAI self)
|
|
{
|
|
LinkedList<int> list = self.Parent.GetComponent<UserSetting>().GetAutoSkills();
|
|
self.AutoSkillList.Clear();
|
|
foreach (int item in list)
|
|
{
|
|
self.AutoSkillList.AddLast(item);
|
|
}
|
|
}
|
|
|
|
private static bool CheckUnActionState(Unit unit)
|
|
{
|
|
ModifierContainerComponent modifierContainer = unit.GetComponent<ModifierContainerComponent>();
|
|
return Check(modifierContainer, ModifierStateType.眩晕) ||
|
|
Check(modifierContainer, ModifierStateType.石化) ||
|
|
Check(modifierContainer, ModifierStateType.冰冻) ||
|
|
Check(modifierContainer, ModifierStateType.沉默);
|
|
|
|
static bool Check(ModifierContainerComponent modifierContainer, ModifierStateType modifierStateType) =>
|
|
modifierContainer.HasState(modifierStateType);
|
|
}
|
|
|
|
private static int GetCurrSkillId(this SkillAI self, LinkedList<int> list)
|
|
{
|
|
try
|
|
{
|
|
LinkedListNode<int> curr = self.CurrSkillNode ?? list.First;
|
|
if (curr == list.Last)
|
|
self.CurrSkillNode = null;
|
|
else
|
|
self.CurrSkillNode = curr.Next;
|
|
return curr.Value;
|
|
}
|
|
catch (Exception e)
|
|
{
|
|
Log.Error(e);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
}
|
|
} |