using Games.GlobeDefine; using GCGame.Table; using Module.Log; using System.Collections.Generic; using UnityEngine; namespace Games.SkillModle { public enum SKILLSELLOGIC { SELLOGIC_INVALID = -1, SELLOGIC_SINGLE = 0, SELLOGIC_MULTI = 1, SELLOGIC_ALL = 2 } public enum SKILLUSEFAILTYPE { CE_ERROR_ELSE = -1, //其他错误 CE_OK = 0, //技能释放成功 CE_TARGET_ERROR = 1, //技能释放目标错误 CE_NO_SKILLEX_CONFIG = 2, //SkillEx未配置 CE_NO_SKILLBASE_CONFIG = 3, //SkillBase未配置 CE_IN_ESCORT_SKILL_LIMIT = 4, //跑商不能使用位移技能 CE_IN_BUFF_LIMIT_SKILL = 5, //有buff限制技能BuffLimitSkill.txt CE_SCENE_INVALID = 6, //场景无效 CE_MOUNT_FREEZE = 7, //上下马冻结期不能使用技能 CE_SKILL_CONDI_CHECK_FAILED = 8, //技能释放条件检测未通过 CE_IN_DEATH = 9, //死亡状态不能释放技能 CE_ROLE_NOT_ACTIVE = 10, //角色未激活 CE_IS_PASSIVITY = 11, //被动技能不能主动释放 CE_IN_MAINSCENE = 12, //主城不能释放技能 CE_SCENE_NOT_ALLOWED_XP_SKILL = 13, //当前场景不能使用xp技能 CE_CUR_SKILL_CANNOT_BREAK = 14, //正在使用的技能不能被打断 CE_NOT_HAVE_THIS_SKILL = 15, //没有学习该技能 CE_IMPACT_SKILL_DISABLED = 16, //有禁止使用该技能的buff CE_TARGET_IN_HIDING = 17, //不能对隐身目标使用技能 CE_DISTANCE_NOT_ENOUGH = 18, //距离不够 CE_SCENE_NOT_ALLOWED_PK = 19, //当前场景不能PK CE_SCENE_NOT_ALLOWED_ATK_NEW_ROLE = 20, //新手保护 CE_TARGET_ROLE_CANNOT_PK = 21, //目标角色不满足PK条件 CE_PUBLIC_CD_NOT_COOL = 22, //公共CD未冷却 CE_SKILL_CD_NOT_COOL = 23, //技能CD未冷却 CE_BACKSWINGCD1_NOT_COOL = 24, //后摇CD1未冷却 CE_BACKSWINGCD2_NOT_COOL = 25, //后摇CD2未冷却 CE_SKILL_DES_POS_CHECK_FAILED = 26, //技能释放点检测失败 CE_DEPLETE_CHECK_FAILED = 27, //技能消耗检测失败 CE_IS_NOT_WANTED_UNIT = 28, // 非技能预期目标 CE_SKILL_STAGE_CHECK_FAILED = 29, // 连段技能判断失败 CE_SKILL_HAS_TYPE_SKILL_LIMIT = 30 // 技能使用时,角色状态不对 } public enum SKILLFINISHREASON { BREAK = 1, FINISH = 2 } public enum SKILLUSETYPE { SHUNFA = 0, //瞬发 YINCHANG = 1, //吟唱 BEIDONG = 2 //被动 } public enum SKILLBASEID { XFZBASEID = 104, //摩诃无量的的baseID YTWJID = 307, //以退为进baseID YGSDID = 204, //阳关三叠baseID HDWLID = 306, //画地为牢 ZLZ = 404 //祝融掌 } public enum SKILLDEFINE { MAX_SKILLNUM = 20, //主角最大技能数 MAX_PET_SKILLNUM = 2, //宠物最大技能数 PUBLICCDID = 14 //公共冷却ID } //每个int位表示一种类别 符合两种及以上的累加 public enum SKILLCLASS { ACTIVE = 1, //主动技 PASSIVITY = 2, //被动技 AUTOREPEAT = 4, //自动连续技 XP = 8, //XP技 CHONGFENG = 16, //冲锋技 DUTIAO = 32, //读条 MASTERSKILL = 64, //师门技能 GAINSKILL = 128, //加持技能 SIMPLEATTACK = 256, //普攻技能 SPECIALSKILL = 512 //玄女锁链连续技 } //技能范围特效 类别 public enum SKILLRANGEEFFECTTYPE { INVALID = -1, RING = 0, //环 CIRCLE = 1, //圆 RECT = 2, //矩形 ARROWS = 3 //箭头 } public enum SKILLRANGEEFFECTTAR { INVAILD = -1, SELF = 0, //自身 SELECTTARGET = 1 //选中目标 } public enum SKILLRANGEEFFECTID { INVALID = -1, RINGEFFECTID = 100, //环 CIRCLEEFFECTID = 101, //圆 RECTEFFECTID = 102, //矩形 ARROWSEFFECTID = 103 //箭头 } public class OwnSkillData { /// /// 总技能释放间隔时间 /// public float Cooldown { get; private set; } /// /// 当前技能释放间隔时间 /// public float CurrentCooldown { get { return Mathf.Max(0f, _currentCooldown); } } /// /// 真实的cd残余时间,可能小于0 - 以允许部分需要cd结束再延迟的检查正常使用 /// private float _currentCooldown; // ******** 连段技能的记录 ******** // 注:连段技能由客户端实行数据预测,不等服务器返回再更新 /// /// 当前连段开始时间 /// private float _comboStartTime = float.NegativeInfinity; /// /// 连段到下一段所需时间 /// public float ComboTime { get; private set; } /// /// 连读残余允许时间 /// public float ComboRemain { get { UpdateCombo(); // 注:如果Combo超时,UpdateCombo后_comboStartTime会重置 if (_comboStartTime < 0f) return float.NegativeInfinity; else return _comboStartTime + ComboTime - Time.time; } } /// /// 技能cd流逝速度校正值列表 /// private List> _cooldownModifiers; /// /// 当前cd时间流逝速度 /// public float CooldownModifier { get; private set; } /// /// 当前最后一次连段是否已经执行 /// public bool FullCombo { get; private set; } public int exSkillLevel { get; private set; } public int SkillId { get; private set; } public void SetSkillId(int newExId, int newExLevel) { // SkillBase是否更新为其他技能 var newSkill = false; if (SkillId != newExId) { var inCombo = ComboExTable != SkillExTable; SkillExTable = newExId < 0 ? null : TableManager.GetSkillExByID(newExId, 0); if (SkillExTable != null) { if (SkillBaseTable == null || SkillBaseTable.Id != SkillExTable.BaseId) { newSkill = true; SkillBaseTable = TableManager.GetSkillBaseByID(SkillExTable.BaseId, 0); } if (inCombo) { ComboExTable = TableManager.GetSkillExByID(SkillExTable.MultiNextSkillId, 0); if (ComboExTable != null) ComboBaseTable = TableManager.GetSkillBaseByID(ComboExTable.BaseId, 0); else { ComboExTable = SkillExTable; ComboBaseTable = SkillBaseTable; LogModule.ErrorLog(string.Format("技能Ex{0}无法正确获得连段技能!", SkillExTable.SkillExID)); } } else { ComboExTable = SkillExTable; ComboBaseTable = SkillBaseTable; } } else { SkillBaseTable = null; ComboExTable = null; ComboBaseTable = null; } } // 试图更新当前的Ex等级 if (SkillId != newExId || exSkillLevel != newExLevel) { if (SkillExTable == null) { ComboExTableFinal = null; BaseExTableFinal = null; SkillLevelTable = null; Cooldown = default(float); } else { if (newExLevel > 0) { BaseExTableFinal = TableManager.GetSkillExByID(SkillExTable.SkillExID + newExLevel, 0) ?? CommonUtility.GetSkillMaxLevelByBaseId(SkillExTable.BaseId); ComboExTableFinal = SkillExTable == ComboExTable ? BaseExTableFinal : TableManager.GetSkillExByID(BaseExTableFinal.MultiNextSkillId, 0); } else { ComboExTableFinal = ComboExTable; BaseExTableFinal = SkillExTable; } SkillLevelTable = TableManager.GetSkillLevelUpByID(BaseExTableFinal.SkillExID, 0); var cdTable = TableManager.GetCoolDownTimeByID(BaseExTableFinal.CDTimeId, 0); Cooldown = cdTable.CDTime.ToClientTime(); } } if (newSkill) { _currentCooldown = float.NegativeInfinity; _cooldownModifiers = new List>(); SetCooldownRate(); CleanComboState(); } SkillId = SkillExTable == null ? GlobeVar.INVALID_ID : SkillExTable.SkillExID; exSkillLevel = newExLevel; } // 连段技能的第一段数据表 - 不会受到ExSkillLevel校正 public Tab_SkillEx SkillExTable { get; private set; } public Tab_SkillBase SkillBaseTable { get; private set; } // 当前连段技能Base数据表 // 注:连段现在不可支持两段以上连段的情况,支持两段以上需要很多特殊处理 public Tab_SkillEx _comboextable; public Tab_SkillEx ComboExTable { get; private set; } public Tab_SkillBase ComboBaseTable { get; private set; } // 受到加成修正之后的数据表 public Tab_SkillEx BaseExTableFinal { get; private set; } public Tab_SkillEx ComboExTableFinal { get; private set; } public Tab_SkillLevelUp SkillLevelTable { get; private set; } public int PriorityAutoCombat { get { return ComboBaseTable == null ? 0 : ComboBaseTable.PriorityAutoFight; } } public bool IsValid() { return SkillId > -1; } /// /// 该技能是否为连段技能 /// public bool IsComboSkill() { return SkillExTable.HasNextCombo(); } /// /// 是否Cd结束,允许添加额外等待时间 /// public bool IsCooldownFinish(float extraTime = 0f) { return _currentCooldown + extraTime <= 0f; } /// /// 设置技能当前释放间隔时间 /// public void SetCooldown(float currentCooldown) { // 若技能进入cd(由于服务器同步信息或其他原因),技能连段重置 if (currentCooldown > 0) CleanComboState(); _currentCooldown = currentCooldown; } /// /// 设置技能刚刚被释放 /// public void ResetCooldown() { _currentCooldown = Cooldown; //if (SkillBaseTable != ComboBaseTable) CleanComboState(); } /// /// 更新技能冷却时间 /// public void UpdateCooldown() { if (IsValid()) _currentCooldown -= Time.unscaledDeltaTime * CooldownModifier; } private void SetCooldownRate() { CooldownModifier = 1f; for (var i = 0; i < _cooldownModifiers.Count; i++) CooldownModifier *= _cooldownModifiers[i].second; } /// /// 增加一个技能冷却校正 /// public void AddCooldownModifier(int handle, float value) { if (IsValid()) { _cooldownModifiers.Add(new MyTuple(handle, value)); SetCooldownRate(); } } /// /// 移除一个技能冷却校正 /// public void RemoveCooldownModifier(int handle) { if (IsValid()) { var index = _cooldownModifiers.FindIndex(a => a.first == handle); if (index >= 0) { _cooldownModifiers.RemoveAt(index); SetCooldownRate(); } } } /// /// 立刻减少cd时间 /// public void SubstractCooldown(float time) { if (IsValid()) _currentCooldown -= time * CooldownModifier; } /// /// 清除当前技能 /// public void CleanUp() { SkillId = -1; _currentCooldown = float.NegativeInfinity; CleanComboState(); } // 注:一般调用这个技能前,应该已经进行过一次UpdateCombo操作,因此不判定连段跌落的情况 public void AddCombo() { if (!SkillBaseTable.SkillClass.ContainFlag((int)SKILLCLASS.SIMPLEATTACK)) { // 如果当前技能仍然可以连段 if (ComboExTable.HasNextCombo()) { //var cdTable = TableManager.GetCoolDownTimeByID(ComboExTable.NextSkillCDTimeId, 0); //ComboTime = 3.0f;//cdTable.CDTime.ToClientTime(); //int use_multi_id = 0; var base_id = ComboExTable.NextStageSkillId; if (base_id > 0) { var ownSkill = GameManager.gameManager.PlayerDataPool.GetOwnSkillInfo(base_id); //use_multi_id = ownSkill.SkillId; if (ownSkill != null) { ownSkill.ComboTime = 3.0f; ownSkill._comboStartTime = Time.time; } } //ComboExTable = TableManager.GetSkillExByID(use_multi_id, 0); //ComboExTableFinal = TableManager.GetSkillExByID(use_multi_id, 0); ////ComboExTable = TableManager.GetSkillExByID(ComboExTable.MultiNextSkillId, 0); ////ComboExTableFinal = TableManager.GetSkillExByID(ComboExTableFinal.MultiNextSkillId, 0); //ComboBaseTable = TableManager.GetSkillBaseByID(ComboExTable.BaseId, 0); //_comboStartTime = Time.time; _currentCooldown = Cooldown; } else FullCombo = true; //{ // // 如果技能是连段技能回滚到第一段,增加一次假cd时间 // if (ComboExTable != SkillExTable) // CleanComboState(); //} } } public OwnSkillData GetComboSkill() { if (!SkillBaseTable.SkillClass.ContainFlag((int)SKILLCLASS.SIMPLEATTACK)) { if (ComboExTable.HasNextCombo()) { var base_id = ComboExTable.NextStageSkillId; if (base_id > 0) { return GameManager.gameManager.PlayerDataPool.GetOwnSkillInfo(base_id); } } } return null; } /// /// 更新连段状态 /// public void UpdateCombo() { // 普攻不使用Combo逻辑 // 非连段不使用Combo逻辑 if (!SkillBaseTable.SkillClass.ContainFlag((int)SKILLCLASS.SIMPLEATTACK) )// && IsComboSkill() { // Combo衔接超时的情况,特殊预测当前连段 // 注:客户端会先走预测Cooldown,然后等待服务器返回的真实Cooldown if (ComboExTable != SkillExTable && (_comboStartTime < 0f || _comboStartTime + ComboTime < Time.time)) { ResetCooldown(); //CleanComboState(); } } } public void CleanComboState() { ComboTime = 0f; ComboExTable = SkillExTable; ComboExTableFinal = BaseExTableFinal; ComboBaseTable = SkillBaseTable; _comboStartTime = float.NegativeInfinity; FullCombo = false; } } public struct ShowDamageInfo { public int showValue; public int showTime; public float interval; public Tab_DamageBoardType damageType; public float nextShowTime; } /// /// 用于GC_SYN_SKILLINFO的临时数据 /// // 注:由于协议是动态生成的,因此暂时 public struct SyncSkillData { public int index; public int skillId; public int skillBaseId; public float cooldown; } //public struct MultiShowDamageBoard //多次显示 //{ // public void CleanUp() // { // ShowValue = 0; // ShowTimes = -1; // ShowInter = -1.0f; // DamageType = GameDefine_Globe.DAMAGEBOARD_TYPE.PLAYER_TYPE_INVALID; // NextShowTime = 0; // } // // public int ShowValue { get; set; } // // public int ShowTimes { get; set; } // // public float ShowInter { get; set; } // // public GameDefine_Globe.DAMAGEBOARD_TYPE DamageType { get; set; } // // public float NextShowTime { get; set; } //} }