using System;
using System.Collections.Generic;
using System.Text;
using CommonLang;
using CommonAI.Zone.Helper;
using CommonAI.Zone.Formula;
using CommonAI.Zone.UnitTriggers;
using CommonAI.Zone.Attributes;
using CommonLang.Property;
using CommonAI.RTS;
using CommonLang.Vector;
using CommonAI.ZoneClient;
using CommonAI.data;
using static CommonAI.Zone.LaunchSpell;
using CommonAI.Data;
namespace CommonAI.Zone.Instance
{
public delegate int ReadBuffDelegate(InstanceUnit.BuffState buffState);
///
/// 所有常态状态(Buff,技能,被动系)
///
partial class InstanceUnit
{
//--------------------------------------------------------------------------------------------------------------
#region _时效性效果_
//--------------------------------------------------------------------------------------------------------------
///
/// 是否可被发现
///
virtual public bool IsVisible { get { return !mInvisibleTimeMS.Enable;/* && !DeadHide; */} }
///
/// 是否无敌
///
virtual public bool IsInvincible { get { return mInvincibleTimeMS.Enable; } }
///
/// 此单位是否霸体
///
virtual public bool IsNoneBlock { get { return mNoneBlockTimeMS.Enable; } }
///
/// 是否为眩晕
///
virtual public bool IsStun { get { return mStunTimeMS.Enable; } }
///
/// 是否沉默
///
virtual public bool IsSilent { get { return mSilentTimeMS.Enable; } }
///
/// 是否免控
///
virtual public bool IsIgnoreControl { get { return mIgnoreControl.Enable; } }
/** 是否不允许移动 */
public bool MarkCannotMove = false;
virtual public bool IsCannotMove { get { return mCannotMoveTimeMS.Enable; } }
//死亡隐藏
private bool mDeadHide = false;
public bool DeadHide{ get { return mDeadHide; } set { mDeadHide = value; } }
public bool IsInPVP() { return this.Virtual.IsInPVP(); }
public bool IsInPVE() { return this.Virtual.IsInPVE(); }
virtual public string PlayerUUID
{
get { return ""; }
}
//--------------------------------------------------------------------------------------------------------------
private List mMultiTimeLineGroup = new List();
private UnitSyncMultiTimeLine mMultiTimeLineSync;
///
/// 注册自定义MultiTimeLine
///
///
///
public MultiTimeLine RegistMultiTimeLine(out int index)
{
index = mMultiTimeLineGroup.Count;
var timeline = new MultiTimeLine(MultiTimeLineRefresh);
mMultiTimeLineGroup.Add(timeline);
return timeline;
}
/////
///// 获取指定ID TimeLine
/////
/////
/////
//public MultiTimeLine GetTimeLine(int index)
//{
// return mMultiTimeLineGroup[index];
//}
public bool IsMoveAble()
{
return this.Info.IsMoveable && this.Info.MoveSpeedSEC > 0;
}
///
/// 指定TimeLine是否还有任务
///
///
///
public bool IsTimeLineEnable(int index)
{
return mMultiTimeLineGroup[index].Enable;
}
///
/// 获取指定 TimeLine 的 ID
///
///
///
public int GetTimeLineIndex(MultiTimeLine timeline)
{
return mMultiTimeLineGroup.IndexOf(timeline);
}
//是否跟随队长
public virtual bool IsFollowMaster() { return false; }
///
/// 添加TimeLine任务
///
///
///
///
public TimeExpire AddTimeLineTask(int index, int timeMS)
{
return mMultiTimeLineGroup[index].Add(timeMS);
}
///
/// 强制移除TimeLine任务
///
///
///
///
public bool RemoveTimeLineTask(int index, TimeExpire task)
{
return mMultiTimeLineGroup[index].Remove(task);
}
//--------------------------------------------------------------------------------------------------------------
///
/// 被击中后不会被中断(霸体),是一个叠加值
///
private MultiTimeLine mNoneBlockTimeMS;
///
/// 眩晕,移动限制状态,是一个叠加值
///
private MultiTimeLine mStunTimeMS;
///
/// 隐形,是一个叠加值
///
private MultiTimeLine mInvisibleTimeMS;
///
/// 无敌时间,是个叠加值
///
private MultiTimeLine mInvincibleTimeMS;
///
/// 沉默时间,是个叠加值
///
private MultiTimeLine mSilentTimeMS;
///
/// 沉默时间,是个叠加值
///
private MultiTimeLine mCannotMoveTimeMS;
///
/// 免控时间
///
private MultiTimeLine mIgnoreControl;
//是否刷新标记
private bool mNeedUpdate = false;
public bool IsCanLaunchSkill(int skillID)
{
if (this.IsStun || (this.IsSilent == true && skillID != this.Virtual.GetBaseSkillID()))
{
return false;
}
return true;
}
private void InitTimeLines()
{
int index;
mNoneBlockTimeMS = RegistMultiTimeLine(out index);
mStunTimeMS = RegistMultiTimeLine(out index);
mInvisibleTimeMS = RegistMultiTimeLine(out index);
mInvincibleTimeMS = RegistMultiTimeLine(out index);
mSilentTimeMS = RegistMultiTimeLine(out index);
mCannotMoveTimeMS = RegistMultiTimeLine(out index);
mIgnoreControl = RegistMultiTimeLine(out index);
mMultiTimeLineSync = new UnitSyncMultiTimeLine(this.ID);
}
private void UpdateTimeLines(int intervalMS)
{
if(mMultiTimeLineGroup == null || !mNeedUpdate)
{
return;
}
bool hasUpdate = false;
for (int i = mMultiTimeLineGroup.Count - 1; i >= 0; --i)
{
if (mMultiTimeLineGroup[i].Update(intervalMS))
{
hasUpdate = true;
}
}
// 全部timer都没有,不刷新
if (!hasUpdate)
{
mNeedUpdate = false;
}
//不能移动单独刷新,此状态需要通知客户端
if(this.MarkCannotMove && !this.IsCannotMove)
{
this.MarkCannotMove = false;
this.RemoveActionSubState(UnitActionSubStatus.CanNotMove);
}
if (mMultiTimeLineSync.Update(mMultiTimeLineGroup))
{
queueEvent(mMultiTimeLineSync);
}
}
public void MultiTimeLineRefresh(bool isAdd)
{
this.mNeedUpdate = true;
}
///
/// 设置霸体时间,如果当前已霸体,则取最大值
///
///
public TimeExpire SetNoneBlockTimeMS(int timeMS)
{
return mNoneBlockTimeMS.Add(timeMS);
}
///
/// 设置眩晕时间,如果当前已眩晕,则取最大值
///
///
public TimeExpire SetStunTimeMS(int timeMS)
{
TimeExpire ret = mStunTimeMS.Add(timeMS);
if (!IsStateDead)
{
changeState(new StateStun(this));
}
return ret;
}
///
/// 设置隐身时间,如果当前已隐身,则取最大值
///
///
public TimeExpire SetInvisibleTimeMS(int timeMS)
{
return mInvisibleTimeMS.Add(timeMS);
}
///
/// 设置无敌时间,如果当前已无敌,则取最大值
///
///
public TimeExpire SetInvincibleTimeMS(int timeMS)
{
return mInvincibleTimeMS.Add(timeMS);
}
///
/// 设置沉默时间
///
///
public TimeExpire SetSilentTimeMS(int timeMS)
{
return mSilentTimeMS.Add(timeMS);
}
/** 设置无法移动时间 */
public TimeExpire SetCannotMoveTimeMS(int timeMS)
{
this.MarkCannotMove = true;
this.AddActionSubState(UnitActionSubStatus.CanNotMove);
return mCannotMoveTimeMS.Add(timeMS);
}
///
/// 设置免控时间
///
///
public TimeExpire SetIgnoreControlTimeMS(int timeMS)
{
return mIgnoreControl.Add(timeMS);
}
public bool RemoveNoneBlock(TimeExpire task)
{
return mNoneBlockTimeMS.Remove(task);
}
public bool RemoveStun(TimeExpire task)
{
return mStunTimeMS.Remove(task);
}
public bool RemoveInvisible(TimeExpire task)
{
return mInvisibleTimeMS.Remove(task);
}
public bool RemoveInvincible(TimeExpire task)
{
return mInvincibleTimeMS.Remove(task);
}
public bool RemoveSilent(TimeExpire task)
{
return mSilentTimeMS.Remove(task);
}
public bool RemoveCannotMove(TimeExpire task)
{
return mCannotMoveTimeMS.Remove(task);
}
public bool RemoveIgnoreControl(TimeExpire task)
{
return mIgnoreControl.Remove(task);
}
public void ClearNoneBlock()
{
mNoneBlockTimeMS.Clear();
}
public void ClearStun()
{
mStunTimeMS.Clear();
}
public void ClearInvisible()
{
mInvisibleTimeMS.Clear();
}
public void ClearInvincible()
{
mInvincibleTimeMS.Clear();
}
public void ClearSilent()
{
mSilentTimeMS.Clear();
}
public void ClearCannotMove()
{
mCannotMoveTimeMS.Clear();
}
public void ClearIgnoreControl()
{
mIgnoreControl.Clear();
}
#endregion
//-----------------------------------------------------------------------------------------------------//
//-----------------------------------------------------------------------------------------------
#region _技能状态类_
public PlayerSkillChangedEvent GetSkillEvent()
{
PlayerSkillChangedEvent evt = new PlayerSkillChangedEvent(ID);
evt.unitFastCastRate = this.mFastCastRate;
if (mDefaultSkill != null)
{
evt.baseSkill = mDefaultSkill.Data;
}
foreach (SkillState sk in mSkillStatus.Skills)
{
if (sk.GetSkillType() != XmdsSkillType.cardSkill && (evt.baseSkill == null || sk.Data.TemplateID != evt.baseSkill.ID))
{
sk.Data.CurUseTimes = (short)sk.OveryLayer;
evt.skills.Add(sk.Data);
}
}
return evt;
}
public ClientStruct.UnitSkillStatus[] GetCurrentSkillStatus()
{
ClientStruct.UnitSkillStatus[] ret = new ClientStruct.UnitSkillStatus[mSkillStatus.Count];
int i = 0;
foreach (SkillState sk in mSkillStatus.Skills)
{
ret[i].SkillTemplateID = (sk.Data.TemplateID);
ret[i].PassTime = (sk.PassTime);
ret[i].useTimes = sk.OveryLayer;
i++;
}
return ret;
}
///
/// 初始化技能可用性
///
public PlayerSkillActiveChangedEvent GetSyncSkillActives()
{
PlayerSkillActiveChangedEvent mSyncSkillActives = new PlayerSkillActiveChangedEvent(this.ID, mSkillStatus.Count);
foreach (SkillState st in mSkillStatus.Skills)
{
PlayerSkillActiveChangedEvent.State sat = new PlayerSkillActiveChangedEvent.State();
sat.SkillTemplateID = st.ID;
sat.ST = st.ActiveState;
mSyncSkillActives.Skills.Add(sat);
}
return mSyncSkillActives;
}
private SkillMap mSkillStatus = new SkillMap();
private SkillState mDefaultSkill;
private List mAllSkills = new List();
private bool mSyncSkillActivesChanged = false;
private void updateSyncSkillActives()
{
if (mSyncSkillActivesChanged)
{
mSyncSkillActivesChanged = false;
queueEvent(GetSyncSkillActives());
}
}
protected bool DoTryAddSkill(ref SkillTemplate sk)
{
bool ret = true;
if (mOnTryAddSkill != null)
{
foreach (TryAddSkill tryadd in mOnTryAddSkill.GetInvocationList())
{
if (!tryadd.Invoke(this, ref sk))
{
ret = false;
}
}
}
return ret;
}
///
/// 重置当前单位技能,当前单位技能重置为单位模板指定技能
///
public void ResetSkills()
{
if (mFormula.TryResetSkill(this))
{
InitSkills(mInfo.BaseSkillID, mInfo.Skills.ToArray());
}
}
///
/// 设置当前单位技能
///
///
///
public virtual void InitSkills(LaunchSkill baseSkill, LaunchSkill[] skills)
{
List exist = new List(mSkillStatus.Skills);
mSyncSkillActivesChanged = true;
mDefaultSkill = null;
mSkillStatus.Clear();
mAllSkills.Clear();
foreach (SkillState st in exist)
{
if (mOnSkillRemoved != null) { mOnSkillRemoved.Invoke(this, st); }
}
if (baseSkill != null)
{
SkillTemplate st = Templates.getSkill(baseSkill.SkillID);
if (DoTryAddSkill(ref st))
{
if (st != null && !mSkillStatus.ContainsKey(baseSkill.SkillID))
{
mDefaultSkill = new SkillState(st, baseSkill, this);
mAllSkills.Add(st);
mSkillStatus.Add(mDefaultSkill);
if (mOnSkillAdded != null) { mOnSkillAdded.Invoke(this, mDefaultSkill); }
}
}
}
foreach (LaunchSkill lsk in skills)
{
SkillTemplate stt = Templates.getSkill(lsk.SkillID);
if (DoTryAddSkill(ref stt))
{
if (stt != null && !mSkillStatus.ContainsKey(lsk.SkillID))
{
SkillState sk = new SkillState(stt, lsk, this);
mAllSkills.Add(stt);
mSkillStatus.Add(sk);
if (mOnSkillAdded != null) { mOnSkillAdded.Invoke(this, sk); }
}
}
}
if (IsInZone)
{
Parent.queueObjectEvent(this, GetSkillEvent());
}
if (mOnSkillChanged != null)
{
mOnSkillChanged.Invoke(this, mDefaultSkill, mSkillStatus.SkillsArray);
}
}
///
/// 设置当前单位技能
///
///
///
public void InitSkills(SkillTemplate baseSkill, SkillTemplate[] skills)
{
List exist = new List(mSkillStatus.Skills);
mSyncSkillActivesChanged = true;
mDefaultSkill = null;
mSkillStatus.Clear();
mAllSkills.Clear();
foreach (SkillState st in exist)
{
if (mOnSkillRemoved != null) { mOnSkillRemoved.Invoke(this, st); }
}
if (baseSkill != null)
{
if (DoTryAddSkill(ref baseSkill))
{
if (baseSkill != null && !mSkillStatus.ContainsKey(baseSkill.ID))
{
mDefaultSkill = new SkillState(baseSkill, new LaunchSkill(baseSkill.ID), this);
mAllSkills.Add(baseSkill);
mSkillStatus.Add(mDefaultSkill);
if (mOnSkillAdded != null) { mOnSkillAdded.Invoke(this, mDefaultSkill); }
}
}
}
foreach (SkillTemplate ssk in skills)
{
SkillTemplate stt = ssk;
if (DoTryAddSkill(ref stt))
{
if (stt != null && !mSkillStatus.ContainsKey(stt.ID))
{
LaunchSkill lsk = null;
foreach(LaunchSkill _lsk in mInfo.Skills)
{
if (_lsk.SkillID == stt.ID)
{
lsk = _lsk;
break;
}
}
if (lsk == null)
lsk = new LaunchSkill(stt.ID);
SkillState state = new SkillState(stt, lsk, this);
mAllSkills.Add(stt);
mSkillStatus.Add(state);
if (mOnSkillAdded != null) { mOnSkillAdded.Invoke(this, state); }
}
}
}
if (IsInZone)
{
Parent.queueObjectEvent(this, GetSkillEvent());
}
if (mOnSkillChanged != null)
{
mOnSkillChanged.Invoke(this, mDefaultSkill, mSkillStatus.SkillsArray);
}
}
public SkillState AddSkill(SkillTemplate st, bool autoLaunch, bool is_default = false)
{
if (DoTryAddSkill(ref st))
{
if (st != null && !mSkillStatus.ContainsKey(st.ID))
{
mSyncSkillActivesChanged = true;
SkillState state = new SkillState(st, new LaunchSkill(st.ID, autoLaunch), this);
mAllSkills.Add(st);
mSkillStatus.Add(state);
if (is_default)
{
mDefaultSkill = state;
}
if (IsInZone)
{
st.CurUseTimes = (short)state.OveryLayer;
Parent.queueObjectEvent(this, new PlayerSkillAddedEvent(ID, st, is_default));
}
if (mOnSkillAdded != null) { mOnSkillAdded.Invoke(this, state); }
if (mOnSkillChanged != null) { mOnSkillChanged.Invoke(this, mDefaultSkill, mSkillStatus.SkillsArray); }
return state;
}
}
return null;
}
public SkillState RemoveSkill(int skillTemplateID)
{
SkillState state = mSkillStatus.RemoveByKey(skillTemplateID);
if (state != null)
{
mSyncSkillActivesChanged = true;
mAllSkills.RemoveAll((t) => { return (t.TemplateID == skillTemplateID); });
if (state == mDefaultSkill)
{
mDefaultSkill = null;
}
if (IsInZone) { Parent.queueObjectEvent(this, new PlayerSkillRemovedEvent(ID, skillTemplateID)); }
if (mOnSkillRemoved != null) { mOnSkillRemoved.Invoke(this, state); }
if (mOnSkillChanged != null) { mOnSkillChanged.Invoke(this, mDefaultSkill, mSkillStatus.SkillsArray); }
}
return state;
}
public SkillTemplate DefaultSkill
{
get
{
if (mDefaultSkill != null)
{
return mDefaultSkill.Data;
}
return null;
}
}
public SkillState DefaultSkillStatus()
{
return mDefaultSkill;
}
public IEnumerable SkillStatus
{
get
{
return mSkillStatus.Skills;
}
}
public SkillTemplate getSkill(int skillID)
{
SkillState st = mSkillStatus.Get(skillID);
if (st != null)
{
return st.Data;
}
return null;
}
public SkillState getSkillState(int skillID)
{
SkillState st = mSkillStatus.Get(skillID);
if (st != null)
{
return st;
}
return null;
}
public void onSkillHitTarget()
{
if (mOnSkillHitTarger != null) mOnSkillHitTarger.Invoke();
}
///
/// 获得当前随机可释放的技能
///
///
///
public virtual SkillState getRandomLaunchableExpectSkill(SkillTemplate.CastTarget expectTarget)
{
int rand = RandomN.Next(0, mAllSkills.Count);
for (int si = mAllSkills.Count - 1; si >= 0; --si)
{
SkillTemplate st = mAllSkills[CMath.cycNum(rand, si, mAllSkills.Count)];
if (st.ExpectTarget == expectTarget)
{
SkillState sst = mSkillStatus.Get(st.GetID());
if (sst.LaunchSkill.AutoLaunch && sst.TryLaunch() && sst.CanAutoLaunch())
{
return sst;
}
}
}
return null;
}
///
/// 获得当前随机可释放的技能
///
///
///
///
///
///
public virtual SkillState getRandomLaunchableExpectSkill(InstanceUnit target, SkillTemplate.CastTarget expectTarget, AttackReason reason = AttackReason.Tracing, bool checkRange = false)
{
int rand = RandomN.Next(0, mAllSkills.Count);
for (int si = mAllSkills.Count - 1; si >= 0; --si)
{
SkillTemplate st = mAllSkills[CMath.cycNum(rand, si, mAllSkills.Count)];
if (st.ExpectTarget == expectTarget)
{
SkillState sst = mSkillStatus.Get(st.GetID());
if (sst.LaunchSkill.AutoLaunch && sst.TryLaunch() && Parent.IsAttackable(this, target, expectTarget, reason, st))
{
if (!checkRange || sst.checkTargetRange(target))
{
return sst;
}
}
}
}
return null;
}
///
/// 获得当前随机可释放的技能
///
///
public virtual SkillState getRandomLaunchableSkill()
{
int rand = RandomN.Next(0, mAllSkills.Count);
for (int si = mAllSkills.Count - 1; si >= 0; --si)
{
SkillTemplate st = mAllSkills[CMath.cycNum(rand, si, mAllSkills.Count)];
SkillState sst = mSkillStatus.Get(st.GetID());
if (sst.TryLaunch())
{
return sst;
}
}
return null;
}
public void getKeepSkills(List keeps, List ret)
{
foreach (SkillState st in mSkillStatus.Skills)
{
if (keeps.Contains(st.ID))
{
ret.Add(st.LaunchSkill);
}
}
}
private void updateSkills()
{
//int intervalMS = Parent.UpdateIntervalMS;
//for (int i = 0; i < mSkillStatus.Count; i++)
//{
// SkillState st = mSkillStatus.GetAt(i);
// st.Update(intervalMS);
//}
mSkillStatus.update(Parent.UpdateIntervalMS);
}
protected virtual void clearSkills()
{
this.mSkillStatus.Clear();
}
// Skills
class SkillMap
{
private HashMap Map = new HashMap();
private List For = new List();
public int Count { get { return For.Count; } }
public IEnumerable Skills { get { return For; } }
public SkillState[] SkillsArray { get { return For.ToArray(); } }
public SkillState GetAt(int i)
{
return For[i];
}
public SkillState Get(int id)
{
return Map.Get(id);
}
public void Add(SkillState state)
{
if (!Map.ContainsKey(state.ID))
{
Map.Put(state.ID, state);
For.Add(state);
}
}
public SkillState RemoveByKey(int id)
{
SkillState ret = Map.RemoveByKey(id);
if (ret != null)
{
For.Remove(ret);
}
return ret;
}
public bool ContainsKey(int id)
{
return Map.ContainsKey(id);
}
public void Clear()
{
Map.Clear();
For.Clear();
}
public void update(int intervalMS)
{
foreach (SkillState st in this.For)
{
st.Update(intervalMS);
}
}
}
public delegate void ISkillCDStatusChange(SkillState skill, bool iscd);
public class SkillState
{
// 技能CD状态更改监听
readonly private List mSkillCDStatusChange = new List();
readonly public SkillTemplate Data;
readonly public LaunchSkill LaunchSkill;
readonly public InstanceUnit Owner;
private SkillActiveState current_state = SkillActiveState.Active;
private int total_cd_time;
private int decrease_total_timems;
private int trigger_decrease_times; //机制触发,减少CD
// 叠层
private int overLayer = -1;
///
/// 从技能开始时的逝去时间
///
private int pass_time;
///
/// 最后CD完成时间
///
private int stop_time;
///
/// 如果是多段攻击,记录段数
///
private int action_step = -1;
private int lockActionStep = -1; //锁定执行序列号
// 是否是多段式技能
private bool mCanStoreTimes = false;
///
/// 多段攻击自动下段
///
private bool auto_increase_action_step = true;
///
/// 当前是否在冷却
///
private bool is_cd = false;
///
/// 当前是否在多段攻击允许时间内
///
private bool is_in_mutil_time = true;
///
/// 当前释放技能时的状态机
///
private StateSkill state;
private float action_speed;
public int ID { get { return Data.ID; } }
///
/// 当前技能是否在转CD
///
public bool IsCD { get { return is_cd; } }
public SkillActiveState ActiveState { get { return current_state; } }
public bool IsActive { get { return current_state == SkillActiveState.Active || current_state == SkillActiveState.ActiveAndHide; } }
public bool IsPauseOnDeactive { get { return current_state == SkillActiveState.DeactiveAndPause; } }
public XmdsSkillType GetSkillType() { return this.Data.Properties.GetSkillType(); }
//是否是多段式技能
private byte mMaxMutilStep = 0;
//代码逻辑控制cd
private bool mCodeControl_HasNext;
///
/// 当前技能是否放完
///
public bool IsDone
{
get
{
if (Data.IsCoolDownWithAction)
{
if (state == null)
return true;
if (state.IsDone)
return true;
if (state.IsCancelableBySkill)
return true;
return false;
}
else if (this.IsMutilAction() && this.IsHasNext())//多段式攻击
{
if (is_in_mutil_time)
{
return true;
}
}
return !is_cd;
}
}
public bool CanAutoLaunch()
{
return this.stop_time == 0 || this.GetSkillType() == XmdsSkillType.normalAtk || this.stop_time + 2000 < this.pass_time || this.IsInMutilTime;
}
public bool IsCodeConttrolCD()
{
return this.mCodeControl_HasNext;
}
///
/// CD 需要的总时间
///
public int TotalCDTime
{
get { return total_cd_time - this.trigger_decrease_times; } set { total_cd_time = value; }
}
///
/// CD 需要的总时间
///
public bool IsInMutilTime
{
get { return is_in_mutil_time; } set { is_in_mutil_time = value; }
}
public void ResetTotalTime()
{
this.total_cd_time = Data.ToUnitSkillTotalTime(Owner.mFastCastRate) - decrease_total_timems;
this.total_cd_time = Math.Max(0, this.total_cd_time);
}
public int PassTime
{
get { return pass_time; }
}
public int OveryLayer
{
get { return this.overLayer; }
}
public void ResetPassTime()
{
this.pass_time = 0;
}
public void SetCDStates(bool cdStatus)
{
this.is_cd = cdStatus;
for (int i = 0; i < mSkillCDStatusChange.Count; i++)
{
mSkillCDStatusChange[i].Invoke(this, this.is_cd);
}
}
public void ResgistSkillCDChangeListen(ISkillCDStatusChange listen)
{
if(listen != null)
{
this.mSkillCDStatusChange.Add(listen);
}
}
public bool IsMutilAction()
{
return Data.IsSingleAction && (Data.ActionQueue.Count > 1);
}
public bool IsHasNext()
{
bool isHasNext = this.ActionIndex < this.mMaxMutilStep;
if(!isHasNext && this.Data.ActionQueue.Count > this.ActionIndex && this.Data.ActionQueue[this.ActionIndex].IsCancelBySkillNext)
{
isHasNext = true;
}
return isHasNext;
}
public byte GetMaxMutilStep()
{
return this.mMaxMutilStep;
}
public int GetMaxSteps()
{
return this.mMaxMutilStep > 0 ? Math.Min(this.mMaxMutilStep, this.Data.ActionQueue.Count-1) : (this.Data.ActionQueue.Count-1);
}
public UnitActionData GetNextAction()
{
if(this.ActionIndex + 1 >= this.Data.ActionQueue.Count)
{
return null;
}
return this.Data.ActionQueue[this.ActionIndex + 1];
}
public UnitActionData GetCurAction()
{
if (this.ActionIndex < 0 || this.ActionIndex >= this.Data.ActionQueue.Count)
{
return null;
}
return this.Data.ActionQueue[this.ActionIndex];
}
public float ActionSpeed { get { return action_speed; } }
public int ActionIndex { get { return action_step; }}
public int LockActionStep { get { return lockActionStep; } set { lockActionStep = value; } }
public object Tag { get; set; }
public bool CanStoreTimes { get { return this.mCanStoreTimes; }}
internal SkillState(SkillTemplate data, LaunchSkill skill, InstanceUnit owner)
{
this.Owner = owner;
this.Data = data;
this.mCanStoreTimes = (this.Data.Properties.GetSkillUseTimes() > 1 && this.Data.Properties.GetSkillAddTimeInterval() > 0);
//默认有最大层数
if (this.mCanStoreTimes)
{
this.overLayer = this.Data.Properties.GetSkillUseTimes();
}
this.LaunchSkill = skill;
this.total_cd_time = Data.ToUnitSkillTotalTime(Owner.mFastCastRate) - decrease_total_timems;
this.pass_time = int.MaxValue / 2;
this.action_speed = data.ActionSpeedRate + Owner.__mSkillActionSpeedRate;
// 多段式技能,但是只能释放一段
if(Data.IsSingleAction && (Data.ActionQueue.Count > 1))
{
for (int i = 0; i < Data.ActionQueue.Count; i++)
{
this.mMaxMutilStep = (byte)i;
if (Data.ActionQueue[i].SigleActionType == ActionEnum.forbidNext || Data.ActionQueue[i].SigleActionType == ActionEnum.forbidNext_lock
|| Data.ActionQueue[i].SigleActionType == ActionEnum.forbidNext_showTime)
{
break;
}
}
}
}
//设置自动释放
public void setAutoLaunch(bool AutoLaunch)
{
this.LaunchSkill.AutoLaunch = AutoLaunch;
}
public void setMaxMutilStep(int vlaue)
{
this.mMaxMutilStep = (byte)vlaue;
}
public void SetActionIndex(int index)
{
this.action_step = index;
}
// 设置机制冷却缩减时间
public void setTriggerDecreaseTime(int time, bool notify = false)
{
this.trigger_decrease_times = time;
// time==0是开始释放时的重置
if(notify)
{
PlayerCDEvent evt = new PlayerCDEvent(this.Owner.ID);
evt.is_decrease_time = true;
evt.is_all = false;
evt.decrease_timeMS = time;
evt.skill_template_id = this.LaunchSkill.SkillID;
this.Owner.Parent.queueObjectEvent(this.Owner, evt);
}
}
///
/// 检测目标距离
///
///
public bool checkTargetRange(InstanceUnit targetUnit)
{
if (Data.AttackMustBeInRange && Data.AttackAngle == 0)
{
if (targetUnit != null)
{
float rg = Owner.GetSkillAttackRange(this.Data, targetUnit);
if (Collider.Object_HitBody_TouchRound(targetUnit, Owner.X, Owner.Y, rg))
{
return true;
}
}
return false;
}
return true;
}
///
/// 检测目标距离
///
///
public bool checkTargetInAttackRange(InstanceUnit targetUnit, LaunchSkillParam param)
{
//只处理怪物的自动战斗,玩家控制不了
if (this.Owner.IsMonster && this.Data.AttackKeepRange > 0)
{
targetUnit = targetUnit == null ? this.Owner.Parent.getUnit(param.TargetUnitID) : targetUnit;
if (targetUnit != null && CMath.getDistance(targetUnit.X, targetUnit.Y, this.Owner.X, this.Owner.Y) < Data.AttackKeepRange)
{
return false;
}
}
if (this.Data.AttackRange > 0)
{
targetUnit = targetUnit == null ? this.Owner.Parent.getUnit(param.TargetUnitID) : targetUnit;
if (targetUnit != null && CMath.getDistance(targetUnit.X, targetUnit.Y, this.Owner.X, this.Owner.Y) > (Owner.GetSkillAttackRange(this.Data) + targetUnit.BodyBlockSize))
{
return false;
}
}
return true;
}
public void SetDecreaseTotalTimeMS(int timeMS)
{
this.decrease_total_timems = timeMS;
}
public void AddDecreaseTotalTimeMS(int timeMS)
{
this.decrease_total_timems += timeMS;
}
public int GetDecreaseTotalTimeMS()
{
return this.decrease_total_timems;
}
///
/// 指定技能动作
///
///
public void Reset(bool init = false)
{
this.action_step = -1;
if (!init)
{
this.IsInMutilTime = false;
}
}
///
/// 设置是否自动控制多段攻击(如果要手动指定播放技能,则设置为False)
///
///
public void SetAutoIncreaseActionIndex(bool at)
{
this.auto_increase_action_step = at;
}
internal void Launch(StateSkill s, LaunchSkillParam param)
{
this.NextAction();
this.total_cd_time = this.GetDefTotalCDTime();
this.pass_time = 0;
this.state = s;
this.SetCDStates(true);
}
private int GetDefTotalCDTime()
{
int cd_time = 0;
cd_time = Data.ToUnitSkillTotalTime(Owner.mFastCastRate) - decrease_total_timems;
if(this.GetSkillType() == XmdsSkillType.normalAtk)
{
cd_time = (int)(cd_time / (Owner.GetAttackSpeed() * 0.0001f));
}
else
{
cd_time = (int)((1.0f - Math.Min(XmdsConstConfig.SKILL_CD_REDUCE_MAX, Owner.SkillCdReduce) * 0.0001f) * cd_time);
}
cd_time = Math.Max(0, cd_time);
return cd_time;
}
public void updateOverLayer(int value)
{
this.overLayer = value;
//通知叠层
var queData = new PlayerSkillUseTimeChangedEvent(this.Owner.ID, this.Data.ID, (byte)this.overLayer);
queData.hasNext = (byte)((this.OveryLayer >= this.Data.Properties.GetSkillUseTimes()) ? 0 : 1);
this.Owner.queueEvent(queData);
}
public void StartCD(int total_time = 0)
{
if (total_time > 0)
{
this.total_cd_time = Math.Max(0, total_time - decrease_total_timems);
}
else
{
//this.total_cd_time = Data.ToUnitSkillTotalTime(Owner.mFastCastRate) - decrease_total_timems;
//this.total_cd_time = Math.Max(0, this.total_cd_time);
this.total_cd_time = this.GetDefTotalCDTime();
}
this.pass_time = 0;
this.SetCDStates(true);
Owner.queueEvent(new PlayerSkillTimeChangedEvent(Owner.ID, ID, this.pass_time, this.TotalCDTime));
}
public void LogicToCD()
{
this.mCodeControl_HasNext = true;
this.StartCD();
}
public void SetCodeControlNext()
{
this.mCodeControl_HasNext = false;
}
public void ForceIntoCD()
{
this.is_in_mutil_time = false;
this.action_step = -1;
this.StartCD();
}
internal void Stop(StateSkill s)
{
this.state = null;
// CD 依靠动作结束
if (Data.IsCoolDownWithAction)
{
this.SetCDStates(false);
this.stop_time = this.pass_time;
}
}
internal void Update(int intervalMS)
{
if (!IsActive && IsPauseOnDeactive)
{
return;
}
this.pass_time += intervalMS;
if(this.CanStoreTimes)
{
if(this.overLayer < Data.Properties.GetSkillUseTimes() && this.pass_time >= Data.Properties.GetSkillAddTimeInterval())
{
this.pass_time = 0;
this.updateOverLayer(this.overLayer + 1);
}
}
else if (is_cd && !Data.IsCoolDownWithAction)
{
// 技能 CD
if (this.pass_time >= TotalCDTime)
{
if(this.IsMutilAction() && (this.is_in_mutil_time || (this.action_step >= Data.ActionQueue.Count)))
{
if(this.action_step < Data.ActionQueue.Count && this.action_step > 0 &&
(Data.ActionQueue[this.action_step].SigleActionType == ActionEnum.chargeAtk || Data.ActionQueue[this.action_step].SigleActionType == ActionEnum.IsAutoNext))
{
pass_time = 0;
return;
}
else
{
this.Reset();
this.StartCD();
}
}
else
{
this.is_in_mutil_time = true;
this.SetCDStates(false);
this.stop_time = this.pass_time;
//Console.WriteLine("out cd : " + TimeUtil.GetTimestampMS());
}
}
}
}
public bool TryLaunch()
{
if (!IsActive)
{
return false;
}
if (!this.Owner.IsCanLaunchSkill(Data.TemplateID))
{
return false;
}
//if (Owner.__mCurrentHP.Value >= Data.CostHP)
{
return IsDone;
}
//return false;
}
public int NextAction()
{
if (Data.IsSingleAction && auto_increase_action_step)
{
int action_time = this.TotalCDTime;
// 是放技能时,处于多段攻击连击冷却时间范围
//if (pass_time - stop_time < Data.SingleActionCoolDownMS || pass_time < (action_time + Data.SingleActionCoolDownMS))
if (this.action_step < 0)
{
this.action_step = 0;
}
else
{
if (Data.IsCoolDownWithAction)
{
action_time = Data.ActionQueue[action_step % Data.ActionQueue.Count].TotalTimeMS;
}
if (this.IsMutilAction())
{
if (this.IsInMutilTime || (this.Data.IsCoolDownWithAction && this.IsDone) || (!this.IsDone && this.action_step < this.mMaxMutilStep))
{
this.action_step += 1;
this.action_step = (byte)(action_step % Data.ActionQueue.Count);
//if (this.action_step >= Data.ActionQueue.Count || !IsCanLaunchNextStepByPlayer(Data.ActionQueue[this.action_step]))
//{
// this.action_step = 0;
// this.is_in_mutil_time = false;
//}
}
}
}
}
return action_step;
}
public bool IsCanLaunchNextStepByPlayer(UnitActionData actionData)
{
// = this.Data.ActionQueue[this.ActionIndex];
if (actionData.SigleActionType == ActionEnum.forbidNext ||
actionData.SigleActionType == ActionEnum.forbidNext_lock)
{
return false;
}
return true;
}
internal void ClearCD()
{
this.pass_time = TotalCDTime;
}
internal void DecreaseSkillCD(int timeMS)
{
if (!Data.IsCoolDownWithAction)
{
this.pass_time += timeMS;
}
}
internal void DecreaseSkillCD_Pct(float percent)
{
if (!Data.IsCoolDownWithAction)
{
this.pass_time += (int)(TotalCDTime * percent);
}
}
internal void SetPassTime(int passtime)
{
if (!Data.IsCoolDownWithAction)
{
if (passtime != this.pass_time)
{
this.pass_time = passtime;
Owner.queueEvent(new PlayerSkillTimeChangedEvent(Owner.ID, ID, this.pass_time, this.total_cd_time));
if (pass_time < TotalCDTime)
{
this.SetCDStates(true);
}
}
}
}
internal bool TrySetActive(SkillActiveState state)
{
if (state != current_state)
{
this.current_state = state;
this.Owner.mSyncSkillActivesChanged = true;
return true;
}
return false;
}
}
///
/// 设置技能可用性
///
///
///
///
public void SetSkillActive(int skillTemplateID, bool active, bool pause_on_deactive = false)
{
SkillState st = getSkillState(skillTemplateID);
if (st != null)
{
if (active)
st.TrySetActive(SkillActiveState.Active);
else if (pause_on_deactive)
st.TrySetActive(SkillActiveState.DeactiveAndPause);
else
st.TrySetActive(SkillActiveState.Deactive);
}
//标记冻结
this.Virtual.SetSkillActive(skillTemplateID, active, pause_on_deactive);
}
public void SetSkillActive(int skillTemplateID, SkillActiveState state)
{
SkillState st = getSkillState(skillTemplateID);
if (st != null)
{
st.TrySetActive(state);
}
}
///
/// 清除技能CD
///
///
public void ClearSkillCD(int skillTemplateID)
{
SkillState ss = getSkillState(skillTemplateID);
if (ss != null)
{
ss.ClearCD();
PlayerCDEvent evt = new PlayerCDEvent(ID);
evt.is_clear = true;
evt.is_all = false;
evt.skill_template_id = skillTemplateID;
Parent.queueObjectEvent(this, evt);
}
}
///
/// 清除所有技能CD
///
public void ClearAllSkillCD()
{
foreach (SkillState ss in mSkillStatus.Skills)
{
ss.ClearCD();
}
PlayerCDEvent evt = new PlayerCDEvent(ID);
evt.is_clear = true;
evt.is_all = true;
Parent.queueObjectEvent(this, evt);
}
///
/// 减少当前CD固定时间
///
///
///
public void DecreaseSkillCD(int skillTemplateID, int updateTimeMS)
{
SkillState ss = getSkillState(skillTemplateID);
if (ss != null)
{
ss.DecreaseSkillCD(updateTimeMS);
PlayerCDEvent evt = new PlayerCDEvent(ID);
evt.is_decrease_time = true;
evt.is_all = false;
evt.decrease_timeMS = updateTimeMS;
evt.skill_template_id = skillTemplateID;
Parent.queueObjectEvent(this, evt);
}
}
///
/// 减少当前CD固定时间
///
///
public void DecreaseAllSkillCD(int updateTimeMS)
{
foreach (SkillState ss in mSkillStatus.Skills)
{
ss.DecreaseSkillCD(updateTimeMS);
}
PlayerCDEvent evt = new PlayerCDEvent(ID);
evt.is_decrease_time = true;
evt.is_all = true;
evt.decrease_timeMS = updateTimeMS;
Parent.queueObjectEvent(this, evt);
}
public void DecreaseSkillCD_Pct(int skillTemplateID, float percent)
{
SkillState ss = getSkillState(skillTemplateID);
if (ss != null)
{
ss.DecreaseSkillCD_Pct(percent);
PlayerCDEvent evt = new PlayerCDEvent(ID);
evt.is_decrease_pct = true;
evt.is_all = false;
evt.decrease_pct = percent;
evt.skill_template_id = skillTemplateID;
Parent.queueObjectEvent(this, evt);
}
}
public void DecreaseAllSkillCD_Pct(float percent)
{
foreach (SkillState ss in mSkillStatus.Skills)
{
ss.DecreaseSkillCD_Pct(percent);
}
PlayerCDEvent evt = new PlayerCDEvent(ID);
evt.is_decrease_pct = true;
evt.is_all = true;
evt.decrease_pct = percent;
Parent.queueObjectEvent(this, evt);
}
public void SetSkillPassTime(int skillID, int passTimeMS)
{
SkillState ss = this.getSkillState(skillID);
if (ss != null)
{
ss.SetPassTime(passTimeMS);
}
}
public void StartSkillCD(int skillID, int totalTimeMS = 0)
{
SkillState ss = this.getSkillState(skillID);
if (ss != null)
{
ss.StartCD(totalTimeMS);
}
}
#endregion
//-----------------------------------------------------------------------------------------------
#region _BUFF状态类_
public ClientStruct.UnitBuffStatus[] GetCurrentBuffStatus()
{
List ret = new List(mBuffs.Count);
mBuffs.ForEachRead((buff) =>
{
if (buff.Data.ClientVisible)
{
ClientStruct.UnitBuffStatus bf = new ClientStruct.UnitBuffStatus();
bf.BuffTemplateID = (buff.Data.TemplateID);
bf.SenderID = buff.SenderID;
bf.IsEquip = buff.IsEquip;
bf.TotalTime = buff.Data.LifeTimeMS;
bf.PassTime = (buff.PassTimeMS);
bf.OverlayLevel = buff.OverlayLevel;
bf.ext = buff.BuffExtData;
ret.Add(bf);
}
return false;
});
return ret.ToArray();
}
public bool IshasControlBuff(Predicate cb)
{
bool hasControlBuff = false;
mBuffs.ForEachReadTrueReturn((buff) =>
{
if (cb(buff.Data))
{
hasControlBuff = true;
return true;
}
return false;
});
return hasControlBuff;
}
public void GetAllBuffStatus(List ret)
{
mBuffs.ForEachRead((bf) =>
{
ret.Add(bf);
return false;
});
}
private class BuffMap
{
class BuffList : IEnumerable
{
readonly public BuffTemplate bufft;
private HashMap list;
private InstanceUnit.BuffState last;
public BuffList(BuffTemplate bufft)
{
this.bufft = bufft;
this.list = new HashMap(1);
}
public void Add(InstanceUnit.BuffState bs)
{
if (bs.Data.IsDuplicating)
{
list.Add(bs.SenderID, bs);
}
else
{
list.Add(0, bs);
}
last = bs;
}
public InstanceUnit.BuffState Remove(uint unit_id)
{
if (bufft.IsDuplicating)
{
InstanceUnit.BuffState bs = list.RemoveByKey(unit_id);
if (bs != null && bs == last)
{
if (list.Count > 0)
{
foreach (InstanceUnit.BuffState bf in list.Values)
{
last = bf;
break;
}
}
else
{
last = null;
}
}
return bs;
}
else
{
last = null;
return list.RemoveByKey(0);
}
}
public void Clear(List cleared)
{
last = null;
cleared.AddRange(list.Values);
list.Clear();
}
public InstanceUnit.BuffState Get(uint unit_id)
{
return list.Get(unit_id);
}
public int Count { get { return list.Count; } }
public InstanceUnit.BuffState Last { get { return last; } }
IEnumerator IEnumerable.GetEnumerator()
{
return list.Values.GetEnumerator();
}
System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
{
return list.Values.GetEnumerator();
}
}
private HashMap mObjects = new HashMap();
private List mObjectsList = new List();
private bool dirty = true;
public int Count { get { return mObjects.Count; } }
//-----------------------------------------------------------------------
// read
//-----------------------------------------------------------------------
public InstanceUnit.BuffState GetObject(int id)
{
BuffList list;
if (mObjects.TryGetValue(id, out list))
{
return list.Last;
}
return null;
}
public void GetObjects(int id, List ret)
{
BuffList list;
if (mObjects.TryGetValue(id, out list))
{
ret.AddRange(list);
}
}
public InstanceUnit.BuffState GetObject(int buff_id, uint unit_id)
{
BuffList list;
if (mObjects.TryGetValue(buff_id, out list))
{
return list.Get(unit_id);
}
return null;
}
//-----------------------------------------------------------------------
// write
//-----------------------------------------------------------------------
public bool RemoveObject(InstanceUnit.BuffState bs)
{
BuffList list;
if (mObjects.TryGetValue(bs.ID, out list))
{
dirty = true;
return list.Remove(bs.SenderID) != null;
}
return false;
}
public InstanceUnit.BuffState RemoveObject(int buffID, uint unit_id)
{
BuffList list;
if (mObjects.TryGetValue(buffID, out list))
{
dirty = true;
return list.Remove(unit_id);
}
return null;
}
public void RemoveObjects(int buffID, List removed)
{
BuffList list;
if (mObjects.TryGetValue(buffID, out list))
{
dirty = true;
list.Clear(removed);
}
}
public void AddObject(InstanceUnit.BuffState obj)
{
BuffList list = mObjects.Get(obj.ID);
if (list == null)
{
list = new BuffList(obj.Data);
mObjects.Add(obj.ID, list);
}
list.Add(obj);
dirty = true;
}
private IList Refresh()
{
if (dirty)
{
dirty = false;
mObjectsList.Clear();
foreach (BuffList list in mObjects.Values)
{
foreach (InstanceUnit.BuffState buff in list)
{
mObjectsList.Add(buff);
}
}
}
return mObjectsList;
}
private void ToList(List ret)
{
foreach (BuffList list in mObjects.Values)
{
foreach (InstanceUnit.BuffState buff in list)
{
ret.Add(buff);
}
}
}
//-----------------------------------------------------------------------
//
//-----------------------------------------------------------------------
///
///
///
/// 返回true终止迭代!
public void ForEachRead(Predicate action)
{
foreach (BuffList list in mObjects.Values)
{
foreach (InstanceUnit.BuffState buff in list)
{
if (action(buff))
{
return;
}
}
}
}
public bool ForEachReadTrueReturn(Predicate action)
{
foreach (BuffList list in mObjects.Values)
{
foreach (InstanceUnit.BuffState buff in list)
{
if (action(buff))
{
return true;
}
}
}
return false;
}
///
///
///
/// 返回true终止迭代!
public void ForEachWrite(Predicate action)
{
using (var list = ListObjectPool.AllocAutoRelease())
{
ToList(list);
for (int i = 0; i < list.Count; i++)
{
if (action(list[i]))
{
return;
}
}
}
}
public void Update(InstanceZone parent)
{
IList list = Refresh();
for (int i = 0; i < list.Count; i++)
{
BuffState bs = list[i];
bs.OnUpdate(parent);
if (bs.IsEnd() && !bs.MarkRemove)
{
this.RemoveObject(bs);
bs.OnEnd(BuffState.EndResult_ByTimeUp);
}
}
}
}
public class BuffState
{
public const string EndResult_ByTimeUp = "time_up";
public const string EndResult_ByReplaced = "replaced";
public const string EndResult_ByClientRemoved = "client_removed";
public const string EndResult_ByCatgoryExclusive = "catgory_exclusive";
public const string EndResult_ByCode = "code";
public const string ENDResult_HuDunBreak = "HuDunBreak";
readonly private BuffTemplate mData;
readonly private InstanceUnit mOwner;
readonly private InstanceUnit sender;
private TimeExpire st_stun;
private TimeExpire st_invisible;
private TimeExpire st_invincible;
private TimeExpire st_silent;
private TimeExpire st_canmove;
private TimeExpire st_ignoreControl;
private int mBuffExtData; //buff扩展字段
private TimeInterval interval;
private PopupKeyFrames keyframes;
private int total_time;
private int passtime;
private byte overlay_level;
public BuffTemplate Data { get { return mData; } }
public int ID { get { return mData.ID; } }
public byte OverlayLevel { get { return overlay_level; }}
public int PassTimeMS { get { return passtime; } }
public int LifeTimeMS { get { return total_time; } }
public bool IsEquip { get; private set; }
public uint SenderID { get { return sender.ID; } }
public int BuffExtData { get { return mBuffExtData; } set { mBuffExtData = value; } }
public InstanceZone Zone { get { return mOwner.Parent; } }
public InstanceUnit Owner { get { return mOwner; } }
public InstanceUnit Sender { get { return sender; } }
public object Tag { get; set; }
//释放时位置信息
private Vector2 mHitPos = new Vector2();
public bool MarkRemove { get; set; }
//set和get放在一起虽然爽,但是可读性真一般
public void SetLayerLevel(byte value)
{
this.overlay_level = value;
}
internal BuffState(BuffTemplate data, InstanceUnit unit, InstanceUnit sender, byte overlay_level, bool forever, bool isControlBuf)
{
this.mData = data;
this.mOwner = unit;
this.sender = sender;
this.IsEquip = forever;
this.overlay_level = overlay_level;
this.passtime = 0;
this.MarkRemove = false;
this.interval = new TimeInterval(data.HitIntervalMS);
this.interval.FirstTimeEnable = data.FirstTimeEnable;
this.interval.Tag = data.HitKeyFrame;
this.keyframes = new PopupKeyFrames();
this.keyframes.AddRange(data.KeyFrames);
this.total_time = data.LifeTimeMS;
//控制增幅
if (sender.__mControledTimeAdd != 0 && (mData.IsSilent || mData.MakeStun || isControlBuf))
{
this.total_time = (int)(Math.Max(0.0f, 1.0f + unit.__mControledTimeAdd * 0.0001f) * this.total_time);
}
//韧性,控制减
if (unit.ControledTimeReduce != 0 && (mData.IsSilent || mData.MakeStun || isControlBuf))
{
this.total_time = (int)(Math.Max(0.0f, 1.0f - unit.ControledTimeReduce * 0.0001f) * this.total_time);
}
}
internal void OnStart()
{
mHitPos.SetX(mOwner.X);
mHitPos.SetY(mOwner.Y);
mOwner.mFormula.OnBuffBegin(mOwner, this, sender);
if (mData.MakeStun)
{
this.st_stun = mOwner.SetStunTimeMS(total_time);
}
if (mData.IsInvisible)
{
this.st_invisible = mOwner.SetInvisibleTimeMS(total_time);
}
if (mData.IsInvincible)
{
this.st_invincible = mOwner.SetInvincibleTimeMS(total_time);
}
if (mData.IsSilent)
{
this.st_silent = mOwner.SetSilentTimeMS(total_time);
}
if(!mData.IsCanMove)
{
this.st_canmove = mOwner.SetCannotMoveTimeMS(total_time);
}
// 免疫控制
if(mData.IgnoreControl)
{
this.st_ignoreControl = mOwner.SetIgnoreControlTimeMS(total_time);
}
if (mData.UnitTrigger != null)
{
mOwner.addTrigger(mData.UnitTrigger.TriggerTemplateID);
}
if (mData.UnitChangeSkills)
{
if (mData.UnitKeepSkillsID != null && mData.UnitKeepSkillsID.Count > 0)
{
using (var keeps = ListObjectPool.AllocAutoRelease())
{
mOwner.getKeepSkills(mData.UnitKeepSkillsID, keeps);
keeps.AddRange(mData.UnitSkills);
mOwner.InitSkills(mData.UnitBaseSkillID, keeps.ToArray());
}
}
else
{
mOwner.InitSkills(mData.UnitBaseSkillID, mData.UnitSkills.ToArray());
}
}
mOwner.doGotBuff(this);
if (mData.ClientVisible)
{
//Console.WriteLine("获得剑影 - " + this.BuffExtData);
mOwner.queueEvent(new UnitLaunchBuffEvent(mOwner.ID, this.ID, this.SenderID,
this.LifeTimeMS, this.IsEquip, overlay_level, this.BuffExtData));
}
}
internal void OnEnd(string result, bool replace = false)
{
this.passtime = total_time;
this.MarkRemove = true;
mOwner.doLostBuff(this);
if (this.st_stun != null)
{
mOwner.mStunTimeMS.Remove(st_stun);
}
if (this.st_invisible != null)
{
mOwner.mInvisibleTimeMS.Remove(st_invisible);
}
if (this.st_invincible != null)
{
mOwner.mInvisibleTimeMS.Remove(st_invincible);
}
if (this.st_silent != null)
{
mOwner.mSilentTimeMS.Remove(st_silent);
}
if(this.st_canmove != null)
{
mOwner.mCannotMoveTimeMS.Remove(st_canmove);
}
if(this.st_ignoreControl != null)
{
mOwner.mIgnoreControl.Remove(st_ignoreControl);
}
if (mData.UnitTrigger != null)
{
mOwner.removeTrigger(mData.UnitTrigger.TriggerTemplateID);
}
if (mData.UnitChangeSkills)
{
mOwner.ResetSkills();
}
if (mData.EndKeyFrame != null)
{
doKeyFrame(mData.EndKeyFrame);
}
mOwner.mFormula.OnBuffEnd(mOwner, this, result, replace);
if (this.Data.ClientVisible)
{
if (!replace)
{
mOwner.queueEvent(new UnitStopBuffEvent(mOwner.ID, this.ID, SenderID));
}
}
}
internal void OnUpdate(InstanceZone zone)
{
using (var kfs = ListObjectPool.AllocAutoRelease())
{
if (keyframes.PopKeyFrames(passtime, kfs) > 0)
{
foreach (BuffTemplate.KeyFrame kf in kfs)
{
doKeyFrame(kf);
}
}
}
if (interval.Update(zone.UpdateIntervalMS))
{
doKeyFrame(mData.HitKeyFrame);
mOwner.mFormula.OnBuffUpdate(mOwner, this, interval.TotalTickCount);
}
passtime += zone.UpdateIntervalMS;
}
private void doKeyFrame(BuffTemplate.KeyFrame kf)
{
if (kf != null)
{
if (kf.Attack != null)
{
mOwner.doHitAttack(sender, new AttackSource(this, kf.Attack));
}
if (kf.Spell != null)
{
if(kf.Spell.SenderUnit == LaunchSpllSenderUnit.AttackerUnit)
{
this.sender.Parent.unitLaunchSpell(XmdsSkillType.none, sender, kf.Spell,
this.sender.X, this.sender.Y, mOwner.ID, null);
}
else
{
mOwner.Parent.unitLaunchSpell(XmdsSkillType.none, sender, kf.Spell,
mOwner.X, mOwner.Y, mOwner.ID, null);
}
}
if (kf.Item != null)
{
mOwner.UseItem(kf.Item.ItemTemplateID);
}
if(kf.addItem != null)
{
this.BuffAddItem(kf.addItem);
}
}
}
/** buff生成道具 */
private void BuffAddItem(BuffAddItem addItem)
{
var itemInfo = Zone.Templates.getItem(addItem.ItemTemplateID);
if(itemInfo == null)
{
log.Warn("BuffAddItem找不到指定道具: " + addItem.ItemTemplateID);
return;
}
if(addItem.posType == CommonAI.Zone.BuffAddItem.PosType.HitBuffPos)
{
this.mOwner.Parent.AddItem(itemInfo, null, this.mHitPos.X, this.mHitPos.Y, 0, this.mOwner.Force, null, this.Owner);
}
else if(addItem.posType == CommonAI.Zone.BuffAddItem.PosType.BindUnitPos)
{
this.mOwner.Parent.AddItem(itemInfo, null, this.Owner.X, this.Owner.Y, 0, this.mOwner.Force, null, this.Owner);
}
else if(addItem.posType == CommonAI.Zone.BuffAddItem.PosType.PointPos)
{
this.mOwner.Parent.AddItem(itemInfo, null, addItem.pointX, addItem.pointY, 0, this.mOwner.Force, null, this.Owner);
}
}
public bool IsEnd()
{
if (Data.IsRemoveOnSenderRemoved)
{
if (!sender.Enable || sender.IsDead())
{
return true;
}
}
if(Data.IsRemoveOnDead && this.mOwner.IsDead())
{
return true;
}
if (IsEquip) return false;
return (passtime >= total_time);
}
public void AddLifeTimeMS(int timeMS)
{
this.total_time += timeMS;
}
//public void RefrushToMaxOverlayer()
//{
// this.overlay_level = this.mData.MaxOverlay;
//}
}
private BuffMap mBuffs = new BuffMap();
///
/// 是否存在技能变身BUFF
///
public bool IsBuffChangeSkills
{
get
{
return GetChangeSkillBuff() != null;
}
}
///
/// 获得技能变身BUFF
///
public BuffState GetChangeSkillBuff()
{
BuffState ret = null;
mBuffs.ForEachRead((bs) =>
{
if (bs.Data.UnitChangeSkills && !bs.IsEnd())
{
ret = bs;
return true;
}
return false;
});
return ret;
}
public BuffState GetBuffByID(int buffTemplateID)
{
return mBuffs.GetObject(buffTemplateID);
}
public BuffState GetBuffByIDAndSender(int buffTemplateID, uint senderUnitID)
{
return mBuffs.GetObject(buffTemplateID, senderUnitID);
}
public BuffState AddBuff(int buffID, int pointMaxOverLayer = 0, bool forever = false, bool bMaxOverlayer = false, bool bMaxReset = false)
{
BuffTemplate buff = Templates.getBuff(buffID);
if (buff != null)
{
return this.AddBuff(buff, this, pointMaxOverLayer, forever, bMaxOverlayer, 0, false, bMaxReset);
}
return null;
}
public BuffState AddBuff(int buffID, InstanceUnit sender, int pointMaxOverLayer = 0, bool forever = false,
bool bMaxOverlayer = false, bool bMaxReset = false, int buffExt = 0, int addLyers = 0)
{
BuffTemplate buff = Templates.getBuff(buffID);
if (buff != null)
{
return this.AddBuff(buff, sender, pointMaxOverLayer, forever, bMaxOverlayer, buffExt, false, bMaxReset, addLyers);
}
return null;
}
/** 编辑器直接编写增加buff接口 */
public BuffState AddBuff(LaunchBuff buff, InstanceUnit sender, bool forever = false)
{
//如果绑定了事件id,就表示去触发事件
if (buff.BuffID == 0 && buff.BindEventID > 0)
{
BattleFunction.GetInstance().TriggrBattleFunction(buff.BindEventID, this.Virtual, sender == null ? null : sender.Virtual);
return null;
}
return this.AddBuff(buff.BuffID, sender, 0, forever);
}
///
/// 增加Buff
///
/// 如果为True,则表示Buff不受时间CD控制
public virtual BuffState AddBuff(BuffTemplate buff, InstanceUnit sender, int pointMaxOverLayer = 0, bool forever = false,
bool bMaxOverlayer = false, int buffExt = 0, bool isControlBuf = false, bool maxReset = false, int addLayers = 0)
{
object tag = null;
if (mFormula.TryAddBuff(this, sender, ref buff, out tag))
{
if (!forever && buff.LifeTimeMS <= 0)
{
return null;
}
//凌驾于一切之上的免控
if(isControlBuf && this.IsIgnoreControl)
{
return null;
}
if (!removeBuffByCatgory(buff.ID, buff.ExclusiveCatgory, buff.ExclusivePriority))
{
return null;
}
int finalMaxOverLay = (pointMaxOverLayer <= 0) ? buff.MaxOverlay : pointMaxOverLayer;
int overlay_level = bMaxOverlayer ? (finalMaxOverLay - 1) : 0;
BuffState bs = mBuffs.RemoveObject(buff.ID, sender.ID);
if (bs != null)
{
if (buff.IsOverlay)
{
int finalAddLayer = Math.Max(1, addLayers);
if(bs.OverlayLevel + finalAddLayer >= finalMaxOverLay && maxReset)
{
overlay_level = 0;
}
else
{
overlay_level = bMaxOverlayer ? (finalMaxOverLay - 1) : (Math.Min(bs.OverlayLevel + finalAddLayer, finalMaxOverLay - 1));
}
}
bs.OnEnd(BuffState.EndResult_ByReplaced, true);
}
else if(addLayers > 0 && buff.MaxOverlay > 0)
{
overlay_level = Math.Max(0, Math.Min(buff.MaxOverlay - 1, addLayers-1));
}
BuffState newbs = new BuffState(buff, this, sender, (byte)overlay_level, forever, isControlBuf);
newbs.Tag = tag;
newbs.BuffExtData = (bs == null) ? buffExt : bs.BuffExtData;
mBuffs.AddObject(newbs);
newbs.OnStart();
//System.Console.WriteLine("AddBuf - " + newbs.Data.ID + ", " + newbs.OverlayLevel);
mFormula.SendAddBuffEvent(this, sender, buff);
return newbs;
}
return null;
}
///
/// 移除互斥技能,根据优先级
///
///
///
///
private bool removeBuffByCatgory(int buffID, int catgory, int priority)
{
if (catgory != 0)
{
// 检测当时有更高优先级 //
{
BuffState greater_buff = null;
mBuffs.ForEachRead((bs) =>
{
if ((bs.ID != buffID) && (bs.Data.ExclusiveCatgory == catgory) && (bs.Data.ExclusivePriority > priority))
{
greater_buff = bs;
return true;
}
return false;
});
if (greater_buff != null)
{
return false;
}
}
// 移除低优先级 //
mBuffs.ForEachWrite((bs) =>
{
if ((bs.ID != buffID) && (bs.Data.ExclusiveCatgory == catgory))
{
mBuffs.RemoveObject(bs);
bs.OnEnd(BuffState.EndResult_ByCatgoryExclusive);
}
return false;
});
}
return true;
}
public void removeBuff(int buffID, string result = BuffState.EndResult_ByCode)
{
using (var bss = ListObjectPool.AllocAutoRelease())
{
mBuffs.RemoveObjects(buffID, bss);
if (bss.Count > 0)
{
foreach (BuffState bs in bss)
{
bs.OnEnd(result);
}
}
}
}
public void removeBuffBySender(int buffID, uint senderUnitID, string result = BuffState.EndResult_ByCode)
{
BuffState bs = mBuffs.RemoveObject(buffID, senderUnitID);
if (bs != null)
{
bs.OnEnd(result);
}
}
public void clearBuffs(string result = BuffState.EndResult_ByCode)
{
mBuffs.ForEachWrite((bs) =>
{
if (!bs.Data.IsPassive && !bs.IsEquip)
{
mBuffs.RemoveObject(bs);
bs.OnEnd(result);
}
return false;
});
}
private void updateBuffs()
{
mBuffs.Update(Parent);
}
#endregion
//---------------------------------------------------------------------------------------------------------------
#region _被动系触发类_
private readonly List mTriggerStatus = new List();
private readonly UnitTriggerHelper mTriggerHelper;
///
/// 保存被动状态
///
public class TriggerState
{
readonly internal UnitTriggerTemplate mData;
readonly internal InstanceUnit mOwner;
public bool IsDamageTrigger { get; private set; }
public bool IsAttackTrigger { get; private set; }
public UnitTriggerTemplate Data { get { return mData; } }
public object Tag { get; set; }
private long launch_time;
internal TriggerState(UnitTriggerTemplate data, InstanceUnit unit)
{
this.mData = data;
this.mOwner = unit;
this.IsDamageTrigger = false;
this.IsAttackTrigger = false;
this.launch_time = -mData.CoolDownTimeMS;
foreach (BaseTriggerEvent evt in data.Triggers)
{
UnitTriggerEventTypeAttribute ut = PropertyUtil.GetAttribute(evt.GetType());
foreach (Type dtype in ut.DelegateTypes)
{
if (dtype == typeof(DamageHandler))
{
this.IsDamageTrigger = true;
}
else if (dtype == typeof(AttackHandler))
{
this.IsAttackTrigger = true;
}
}
}
}
internal void Start(InstanceUnit target)
{
if (IsActive)
{
this.launch_time = mOwner.Parent.PassTimeMS;
uint targetID = 0;
Vector2 targetPos = new Vector2(mOwner.X, mOwner.Y);
if (target != null)
{
targetPos.SetX(target.X);
targetPos.SetY(target.Y);
targetID = target.ID;
}
// 如果关键帧绑定特效
if (mData.DoEffect != null)
{
mOwner.queueEvent(new UnitEffectEvent(mOwner.ID, mData.DoEffect));
}
// 如果关键帧绑定释放法术
if (mData.DoSpell != null)
{
mOwner.Parent.unitLaunchSpell(XmdsSkillType.none, mOwner, mData.DoSpell, mOwner.X, mOwner.Y, 0, targetPos);
}
// 如果关键帧绑定自己释放BUFF
if (mData.DoBuff != null)
{
mOwner.AddBuff(mData.DoBuff, mOwner);
}
// 如果关键帧绑定单位位移
if (mData.DoSkill != null)
{
mOwner.launchSkill(mData.DoSkill.SkillID, new InstanceUnit.LaunchSkillParam(targetID, targetPos));
}
//召唤
if (mData.DoSummon != null)
{
mOwner.Parent.unitSummonUnit(mOwner, mData.DoSummon);
}
mOwner.mFormula.OnTriggerStart(mOwner, this, target);
}
}
public bool Test(AttackSource source)
{
if (IsActive)
{
foreach (BaseTriggerEvent evt in mData.Triggers)
{
if (!mOwner.mFormula.TryLaunchTrigger(mOwner, mData, evt, source) || !evt.Test(mOwner, source))
{
return false;
}
}
return true;
}
return false;
}
///
/// 是否处于冷却状态
///
public bool IsActive
{
get { return (launch_time + mData.CoolDownTimeMS) < mOwner.Parent.PassTimeMS; }
}
}
private void updateTriggers(bool slowRefresh)
{
this.mFormula.OnUpdateTriggerSkill(this, Parent.UpdateIntervalMS, slowRefresh);
}
public void addTriggers(ICollection triggers)
{
foreach (LaunchTrigger launch in triggers)
{
addTrigger(launch.TriggerTemplateID);
}
}
public bool containsTrigger(int tgID)
{
for (int i = mTriggerStatus.Count - 1; i >= 0; --i)
{
if (mTriggerStatus[i].mData.ID == tgID)
{
return true;
}
}
return false;
}
public TriggerState findTrigger(int tgID)
{
for (int i = mTriggerStatus.Count - 1; i >= 0; --i)
{
if (mTriggerStatus[i].mData.ID == tgID)
{
return mTriggerStatus[i];
}
}
return null;
}
public bool addTrigger(UnitTriggerTemplate trigger)
{
if (!containsTrigger(trigger.ID))
{
TriggerState ts = new TriggerState(trigger, this);
mTriggerStatus.Add(ts);
}
return false;
}
public bool addTrigger(int triggerID)
{
if (!containsTrigger(triggerID))
{
UnitTriggerTemplate tg = Templates.getUnitTrigger(triggerID);
if (tg != null)
{
TriggerState ts = new TriggerState(tg, this);
mTriggerStatus.Add(ts);
}
}
return false;
}
public void removeTrigger(int tgID)
{
TriggerState bs = findTrigger(tgID);
if (bs != null)
{
mTriggerStatus.Remove(bs);
}
}
public bool startTrigger(int tgID, InstanceUnit target)
{
TriggerState bs = findTrigger(tgID);
if (bs != null && bs.IsActive)
{
bs.Start(target);
return true;
}
return false;
}
public void clearTriggers()
{
mTriggerStatus.Clear();
}
///
/// 如果被攻击,尝试启动单位触发器
///
///
///
public void TryStartDamageTriggers(InstanceUnit attacker, AttackSource source)
{
foreach (TriggerState ts in this.mTriggerStatus)
{
if (ts.IsDamageTrigger && ts.Test(source))
{
ts.Start(attacker);
}
}
}
///
/// 如果攻击别人,尝试启动触发器
///
///
///
public void TryStartAttackTriggers(InstanceUnit target, AttackSource source)
{
foreach (TriggerState ts in this.mTriggerStatus)
{
if (ts.IsAttackTrigger && ts.Test(source))
{
ts.Start(target);
}
}
}
public class UnitTriggerHelper
{
private readonly InstanceUnit unit;
public UnitTriggerHelper(InstanceUnit unit)
{
this.unit = unit;
unit.OnDamage += this.onUnitDamage;
unit.OnAttack += this.onUnitAttack;
}
public void onUnitDamage(InstanceUnit obj, InstanceUnit attacker, int hp, AttackSource source)
{
unit.TryStartDamageTriggers(attacker, source);
}
public void onUnitAttack(InstanceUnit obj, InstanceUnit target, int hp, AttackSource source)
{
unit.TryStartAttackTriggers(target, source);
}
}
#endregion
//---------------------------------------------------------------------------------------------------------------
#region _背包和道具_
public ClientStruct.UnitItemStatus[] GetCurrentItemStatus()
{
ClientStruct.UnitItemStatus[] ret = new ClientStruct.UnitItemStatus[mInventorySlots.Count];
int i = 0;
foreach (InventorySlot item in mInventorySlots)
{
ret[i].ItemTemplateID = item.ItemTemplateID;
ret[i].Count = item.Count;
i++;
}
return ret;
}
public class InventorySlot
{
readonly public int Index;
readonly public InstanceUnit Owner;
public InventorySlot(int index, InstanceUnit owner)
{
this.Index = index;
this.Owner = owner;
}
public bool IsEmpty
{
get
{
return (Item == null);
}
}
public int ItemTemplateID
{
get
{
if (Item != null)
return Item.TemplateID;
return 0;
}
}
public ItemTemplate Item { get; private set; }
public int Count { get; private set; }
internal int AddItem(ItemTemplate item, int count)
{
if (item == null) return 0;
if (count <= 0) return 0;
if (this.IsEmpty)
{
// 背包为空 //
this.Item = item;
this.Count = Math.Min(this.Item.MaxStackCount, count);
this.Owner.doGotInventoryItem(this, item, Index, count);
return this.Count;
}
else if (item.TemplateID == this.ItemTemplateID)
{
int oldcount = this.Count;
// 道具类型一致, 堆叠 //
this.Count = Math.Min(this.Item.MaxStackCount, this.Count + count);
if (oldcount != this.Count)
{
this.Owner.doGotInventoryItem(this, item, Index, count);
return this.Count - oldcount;
}
return 0;
}
return 0;
}
internal int TryUse(int count)
{
if (IsEmpty) return 0;
if (!Item.IsInventoryUseable) return 0;
if (Owner.tryUseItem(Item, Owner))
{
return Math.Min(count, this.Count);
}
return 0;
}
internal int Use(int count)
{
if (IsEmpty) return 0;
if (!Item.IsInventoryUseable) return 0;
if (Owner.tryUseItem(Item, Owner))
{
int used = 0;
count = Math.Min(count, this.Count);
for (int i = 0; i < count; i++)
{
Owner.UseItem(Item);
this.Count--;
used++;
if (Count == 0)
{
break;
}
}
this.Owner.doLostInventoryItem(this, Item, Index, count);
if (Count == 0)
{
this.Item = null;
}
return used;
}
return 0;
}
internal int Drop(int count)
{
if (IsEmpty) return 0;
count = Math.Min(count, this.Count);
this.Count -= count;
if (this.Count <= 0)
{
this.Count = 0;
}
this.Owner.doLostInventoryItem(this, Item, Index, count);
if (this.Count == 0)
{
this.Item = null;
}
return count;
}
internal int Clean()
{
return Drop(this.Count);
}
}
private List mInventorySlots = new List();
private HashMap> mCoolDownItems = new HashMap>();
private List> mRemoved = new List>();
private void InitBagSlots()
{
for (int i = 0; i < mInfo.InventorySize; i++)
{
mInventorySlots.Add(new InventorySlot(i, this));
}
}
private bool tryUseItem(ItemTemplate item, InstanceUnit item_creater)
{
if (mFormula.TryUseItem(this, item, item_creater))
{
if (item.UseCoolDownTimeMS > 0)
{
if (IsItemCoolDown(item.ID))
{
return false;
}
return true;
}
return true;
}
return false;
}
private void beginUseItem(ItemTemplate item)
{
if (item.UseCoolDownTimeMS > 0)
{
mCoolDownItems.Put(item.ID, new TimeExpire(item, item.UseCoolDownTimeMS));
}
}
private void updateItems()
{
int intervalMS = Parent.UpdateIntervalMS;
/*
using (var removed = ListObjectPool>.AllocAutoRelease())
{
foreach (TimeExpire expire in mCoolDownItems.Values)
{
if (expire.Update(intervalMS))
{
removed.Add(expire);
}
}
if (removed.Count > 0)
{
foreach (TimeExpire expire in removed)
{
if (expire.IsEnd)
{
mCoolDownItems.RemoveByKey(expire.Tag.ID);
}
}
}
}*/
if(mCoolDownItems.Count <= 0)
{
return;
}
//换一个写法
mRemoved.Clear();
foreach (TimeExpire expire in mCoolDownItems.Values)
{
if (expire.Update(intervalMS))
{
mRemoved.Add(expire);
}
}
if (mRemoved.Count > 0)
{
foreach (TimeExpire expire in mRemoved)
{
if (expire.IsEnd)
{
mCoolDownItems.RemoveByKey(expire.Tag.ID);
}
}
mRemoved.Clear();
}
}
protected virtual void clearItemSlots()
{
foreach (var slot in mInventorySlots)
{
slot.Clean();
}
mInventorySlots.Clear();
mCoolDownItems.Clear();
}
///
/// 检测此道具是否在CD
///
///
///
public bool IsItemCoolDown(int itemTemplateID)
{
if (mCoolDownItems.ContainsKey(itemTemplateID))
{
return true;
}
return false;
}
///
/// 添加道具到白空的背包
///
///
///
///
public int AddItemToEmptyInventory(ItemTemplate item, int count = 1)
{
if (item == null) return 0;
if (count <= 0) return 0;
if (!item.IsDuplicateInventory || item.HoldingLimit > 0)
{
int holding = GetItemCountInInventory(item.ID);
if (!item.IsDuplicateInventory)
{
if (holding > 0)
{
return 0;
}
count = 1;
}
if (item.HoldingLimit > 0)
{
if (holding >= item.HoldingLimit)
{
return 0;
}
if (holding + count > item.HoldingLimit)
{
count = item.HoldingLimit - holding;
}
if (count <= 0) return 0;
}
}
int added = 0;
//优先堆叠//
for (int i = 0; i < mInventorySlots.Count; i++)
{
InventorySlot slot = mInventorySlots[i];
if (slot.ItemTemplateID == item.ID)
{
added += slot.AddItem(item, count - added);
if (added >= count)
{
break;
}
}
}
//使用空闲格子//
for (int i = 0; i < mInventorySlots.Count; i++)
{
InventorySlot slot = mInventorySlots[i];
added += slot.AddItem(item, count - added);
if (added >= count)
{
break;
}
}
return added;
}
///
/// 添加道具到指定背包
///
///
///
///
///
public int AddItemToInventory(ItemTemplate item, int index, int count = 1)
{
if (item == null) return 0;
if (count <= 0) return 0;
if (!item.IsDuplicateInventory || item.HoldingLimit > 0)
{
int holding = GetItemCountInInventory(item.ID);
if (!item.IsDuplicateInventory)
{
if (holding > 0)
{
return 0;
}
count = 1;
}
if (item.HoldingLimit > 0)
{
if (holding >= item.HoldingLimit)
{
return 0;
}
if (holding + count > item.HoldingLimit)
{
count = item.HoldingLimit - holding;
}
if (count <= 0) return 0;
}
}
if (index >= 0 && index < mInventorySlots.Count)
{
InventorySlot slot = mInventorySlots[index];
return slot.AddItem(item, count);
}
return 0;
}
///
/// 添加道具到指定背包
///
///
///
///
///
public int AddItemToInventory(int itemTemplateID, int index, int count = 1)
{
if (count <= 0) return 0;
return AddItemToInventory(Templates.getItem(itemTemplateID), index, count);
}
private int UseItemInternal(InventorySlot slot, int count)
{
if (slot.Item != null)
{
if (slot.Item.UseInProgressTimeMS > 0)
{
count = slot.TryUse(count);
if (count > 0)
{
this.startPickProgressSelf(slot.Item.UseInProgressTimeMS, (s, p) =>
{
slot.Use(count);
});
}
return count;
}
else
{
return slot.Use(count);
}
}
return 0;
}
///
/// 使用背包的道具
///
///
///
///
public int UseInventoryItem(int index, int count = 1)
{
if (count <= 0) return 0;
if (index >= 0 && index < mInventorySlots.Count)
{
InventorySlot slot = mInventorySlots[index];
return UseItemInternal(slot, count);
}
return 0;
}
public int UseInventoryItemByType(int itemTemplateID, int count = 1)
{
if (count <= 0) return 0;
for (int i = 0; i < mInventorySlots.Count; i++)
{
InventorySlot slot = mInventorySlots[i];
if (slot.ItemTemplateID == itemTemplateID)
{
return UseItemInternal(slot, count);
}
}
return 0;
}
public int DropInventoryItemByIndex(int index, int count = 1)
{
if (count <= 0) return 0;
if (index >= 0 && index < mInventorySlots.Count)
{
InventorySlot slot = mInventorySlots[index];
return slot.Drop(count);
}
return 0;
}
public int DropInventoryItemByType(int itemTemplateID, int count = 1)
{
if (count <= 0) return 0;
int droped = 0;
for (int i = 0; i < mInventorySlots.Count; i++)
{
InventorySlot slot = mInventorySlots[i];
if (slot.ItemTemplateID == itemTemplateID)
{
droped += slot.Drop(count);
if (droped >= count)
{
break;
}
}
}
return droped;
}
public int ClearInventoryItemByIndex(int index)
{
if (index >= 0 && index < mInventorySlots.Count)
{
InventorySlot slot = mInventorySlots[index];
return slot.Clean();
}
return 0;
}
public int ClearInventoryItemByType(int itemTemplateID)
{
int droped = 0;
for (int i = 0; i < mInventorySlots.Count; i++)
{
InventorySlot slot = mInventorySlots[i];
if (slot.ItemTemplateID == itemTemplateID)
{
droped += slot.Clean();
}
}
return droped;
}
///
/// 背包内是否有此道具
///
///
///
public bool ContainsItemInInventory(int itemTemplateID)
{
for (int i = 0; i < mInventorySlots.Count; i++)
{
InventorySlot slot = mInventorySlots[i];
if (slot.ItemTemplateID == itemTemplateID)
{
return true;
}
}
return false;
}
public int GetItemCountInInventory(int itemTemplateID)
{
int ret = 0;
for (int i = 0; i < mInventorySlots.Count; i++)
{
InventorySlot slot = mInventorySlots[i];
if (slot.ItemTemplateID == itemTemplateID)
{
ret += slot.Count;
}
}
return ret;
}
#endregion
//---------------------------------------------------------------------------------------------------------------
#region _物理运动_
public bool IsFallingDown
{
get
{
if (mCurrentFallingDown != null)
return !mCurrentFallingDown.IsEnd;
return false;
}
}
public bool IsDamageFallingDown
{
get
{
StateDamage damage = (this.CurrentState as StateDamage);
if (damage != null)
{
return damage.IsFallingDown;
}
return false;
}
}
public bool IsPhysicalMove
{
get
{
if (mCurrentStartMove != null)
return !mCurrentStartMove.IsEnd;
return false;
}
}
private FallingDown mCurrentFallingDown;
private HitMoveSpeed mCurrentStartMove;
private void updatePhysical()
{
if (mCurrentFallingDown != null && mCurrentFallingDown.Update(Parent.UpdateIntervalMS))
{
mCurrentFallingDown = null;
}
if (mCurrentStartMove != null && mCurrentStartMove.Update(Parent.UpdateIntervalMS))
{
mCurrentStartMove = null;
}
}
///
/// 开始自由落体
///
///
///
///
///
///
public virtual FallingDown StartFly(object launcher, float speedZ, float gravity, float zlimit)
{
mCurrentFallingDown = new FallingDown(this, speedZ, gravity, zlimit);
return mCurrentFallingDown;
}
///
/// 开始复杂移动
///
///
///
///
///
///
///
///
///
public virtual HitMoveSpeed StartHitMove(
object launcher,
float direction,
float rotateSpeedSEC,
int expectlTimeMS,
float moveSpeedSEC,
float moveSpeedAdd,
float moveSpeedAcc,
bool isNoneTouch)
{
if (mCurrentStartMove != null)
{
mCurrentStartMove.Stop();
}
HitMoveSpeed move = new HitMoveSpeed(
this,
direction,
rotateSpeedSEC,
expectlTimeMS,
moveSpeedSEC,
moveSpeedAdd,
moveSpeedAcc,
isNoneTouch);
mCurrentStartMove = move;
return move;
}
///
/// 落体运动
///
public class FallingDown
{
private readonly InstanceUnit unit;
private readonly float gravity;
private readonly float z_limit;
private float z_speed;
public FallingDown(InstanceUnit unit, float zspeed, float zgravity, float zlimit)
{
this.unit = unit;
this.z_limit = zlimit;
this.z_speed = zspeed;
this.gravity = zgravity == 0 ? unit.Templates.CFG.GLOBAL_GRAVITY : zgravity;
this.ExpectTimeMS = MoveHelper.CalculateFlyTimeMS(unit.Z, zspeed, zlimit, gravity, 10);
this.IsEnd = false;
}
public bool Update(int intervalMS)
{
//向上受到ZLimit限制//
unit.Z += MoveHelper.GetDistance(intervalMS, z_speed);
unit.Z = Math.Max(0, unit.Z);
this.IsEnd = unit.Z <= 0;
//骤停//
if (z_limit != 0 && z_speed > 0 && unit.Z > z_limit)
{
z_speed = 0;
}
this.z_speed -= MoveHelper.GetDistance(intervalMS, gravity);
return IsEnd;
}
public bool IsEnd { get; private set; }
public int ExpectTimeMS { get; private set; }
public float ZSpeedSEC { get { return z_speed; } }
public float ZLimit { get { return z_limit; } }
}
public class HitMoveSpeed
{
private readonly InstanceUnit mOwner;
private readonly float mStartDirection;
private readonly float mMoveSpeedAdd;
private readonly float mMoveSpeedAcc;
private readonly float mRotateSpeedSEC;
private float moveSpeedSEC;
private TimeExpire hitMoveTime;
private FallingDown hasFly;
private IPositionObject moveTarget;
private bool moveTargetBody;
private bool isNoneTouch = false;
public HitMoveSpeed(
InstanceUnit owner,
float direction,
float rotateSpeedSEC,
int expectlTimeMS,
float moveSpeedSEC,
float moveSpeedAdd,
float moveSpeedAccPct,
bool isNoneTouch)
{
this.mOwner = owner;
this.mStartDirection = direction;
this.moveSpeedSEC = moveSpeedSEC;
this.mMoveSpeedAdd = moveSpeedAdd;
this.mMoveSpeedAcc = moveSpeedAccPct / 100f;
this.mRotateSpeedSEC = rotateSpeedSEC;
this.isNoneTouch = isNoneTouch;
this.TotalTimeMS = expectlTimeMS;
this.hitMoveTime = new TimeExpire(TotalTimeMS);
this.IsEnd = false;
this.PrevX = owner.X;
this.PrevY = owner.Y;
}
public void SetFly(object launcher, float moveZSpeed, float gravity, float zlimit)
{
if (moveZSpeed != 0)
{
this.hasFly = mOwner.StartFly(launcher, moveZSpeed, gravity, zlimit);
this.TotalTimeMS = hasFly.ExpectTimeMS;
this.hitMoveTime = new TimeExpire(TotalTimeMS);
}
}
public void SetMoveTarget(IPositionObject target, bool targetBodyBlock)
{
moveTarget = target;
moveTargetBody = targetBodyBlock;
}
public void Stop()
{
this.IsEnd = true;
}
public bool Update(int intervalMS)
{
int intervalMS_move = intervalMS;
if (hitMoveTime.PassTimeMS + intervalMS >= hitMoveTime.TotalTimeMS)
{
intervalMS_move = hitMoveTime.TotalTimeMS - hitMoveTime.PassTimeMS;
}
if (mRotateSpeedSEC != 0)
{
mOwner.turn(MoveHelper.GetDistance(intervalMS_move, mRotateSpeedSEC));
}
this.PrevX = mOwner.X;
this.PrevY = mOwner.Y;
// 移动 //
if (moveTarget != null)
{
move(intervalMS_move, moveTarget);
}
else
{
move(intervalMS_move, mStartDirection);
}
// 递增 //
{
//每秒递减速度绝对值//
MoveHelper.UpdateSpeed(intervalMS_move, ref moveSpeedSEC, mMoveSpeedAdd, mMoveSpeedAcc);
}
if (hitMoveTime.PassTimeMS + intervalMS >= hitMoveTime.TotalTimeMS || hitMoveTime.Update(intervalMS))
{
IsEnd = true;
}
return IsEnd;
}
private void move(int intervalMS, IPositionObject target)
{
if (moveTargetBody)
{
float distance = MoveHelper.GetDistance(intervalMS, moveSpeedSEC);
if (CMath.includeRoundPoint(mOwner.X, mOwner.Y, target.RadiusSize + mOwner.RadiusSize + distance, target.X, target.Y))
{
return;
}
}
if (hasFly != null)
{
mOwner.jumpToTarget(target.X, target.Y, moveSpeedSEC, intervalMS, IsNoneTouch);
}
else
{
if (IsNoneTouch)
{
mOwner.jumpToTarget(target.X, target.Y, moveSpeedSEC, intervalMS, IsNoneTouch);
}
else if (mMoveSpeedAdd != 0 || mMoveSpeedAcc != 0)
{
mOwner.moveImpactTo(target.X, target.Y, moveSpeedSEC, intervalMS);
}
else
{
mOwner.moveBlockTo(target.X, target.Y, moveSpeedSEC, intervalMS);
}
}
}
private void move(int intervalMS, float direction)
{
if (hasFly != null)
{
mOwner.jumpTo(direction, moveSpeedSEC, intervalMS, IsNoneTouch);
}
else
{
if (IsNoneTouch)
{
mOwner.jumpTo(direction, moveSpeedSEC, intervalMS, IsNoneTouch);
}
else if (mMoveSpeedAdd != 0 || mMoveSpeedAcc != 0)
{
mOwner.moveImpact(direction, moveSpeedSEC, intervalMS);
}
else
{
mOwner.moveBlockTo(direction, moveSpeedSEC, intervalMS);
}
}
}
public float PrevX { get; private set; }
public float PrevY { get; private set; }
public bool IsFly { get { return hasFly != null; } }
public int TotalTimeMS { get; private set; }
public bool IsEnd { get; private set; }
public bool IsNoneTouch
{
get { return isNoneTouch; }
set { this.isNoneTouch = value; }
}
public float ZSpeedSEC
{
get
{
if (hasFly != null)
return hasFly.ZSpeedSEC;
return 0;
}
}
}
#endregion
//---------------------------------------------------------------------------------------------------------------
}
}