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; }
//}
}