using System;
using System.Collections.Generic;
using System.Text;
using CommonAI.RTS;
using CommonLang.Vector;
using CommonLang;
using CommonAI.Zone.Helper;
using CommonAI.RTS.Manhattan;
using CommonAI.Zone.ZoneEditor;
namespace CommonAI.Zone.Instance
{
public abstract class InstanceFlag : GameEntity, IPositionObject
{
public abstract float Direction { get; }
public abstract float RadiusSize { get; }
public InstanceZone Parent { get { return mParent; } }
public string Name { get { return mName; } }
public string Alias { get { return mAlias; } }
public Vector2 Pos { get { return mPos; } }
public float X { get { return mPos.X; } }
public float Y { get { return mPos.Y; } }
private Vector2 mPos = new Vector2();
private readonly string mName;
private readonly string mAlias;
private readonly string mSrcTag = null;
private bool mEnableTriggerd = false;
private bool mEnable = true;
private InstanceZone mParent;
private string mTag;
public bool Enable
{
get { return mEnable; }
set
{
if (!mEnableTriggerd || mEnable != value)
{
mEnableTriggerd = true;
mEnable = value;
if (mEnable)
{
if (mOnFlagEnabled != null)
mOnFlagEnabled.Invoke(this);
}
else
{
if (mOnFlagDisabled != null)
mOnFlagDisabled.Invoke(this);
}
}
}
}
public string Tag
{
get { return mTag; }
set
{
if (mTag != value)
{
mTag = value;
Parent.queueEvent(new FlagTagChangedEvent(this.mName, this.mTag));
}
}
}
public string SrcTag
{
get { return mSrcTag; }
}
public InstanceFlag(InstanceZone zone, ZoneEditor.SceneObjectData data)
{
this.mParent = zone;
this.mName = data.Name;
this.mAlias = data.Alias;
this.mPos = new Vector2(data.X, data.Y);
this.mTag = data.Tag;
}
protected override void Disposing()
{
base.Disposing();
this.clearEvents();
}
virtual internal void onAdded()
{
if (mOnInit != null)
{
mOnInit.Invoke(this);
}
}
protected internal virtual void OnStart()
{
}
virtual internal void update()
{
}
abstract public TVector2 getRandomPos(Random random);
//----------------------------------------------------------------------------
#region IFlagAPI
public bool get_enable()
{
return Enable;
}
public bool set_enable(bool e)
{
Enable = e;
return e;
}
public string get_name()
{
return Name;
}
public float get_x()
{
return X;
}
public float get_y()
{
return Y;
}
///
/// Show Check Point
///
///
public void look_at_target(string target)
{
mParent.queueEvent(new LookAtEvent(target, 0, 0));
}
#endregion
//----------------------------------------------------------------------------
#region Delegate
///
/// 触发器开始
///
///
public delegate void InitHandler(InstanceFlag flag);
///
/// 触发器被开启
///
///
public delegate void FlagEnabledHandler(InstanceFlag flag);
///
/// 触发器被关闭
///
///
public delegate void FlagDisabledHandler(InstanceFlag flag);
private InitHandler mOnInit;
private FlagEnabledHandler mOnFlagEnabled;
private FlagDisabledHandler mOnFlagDisabled;
public event InitHandler OnInit { add { mOnInit += value; } remove { mOnInit -= value; } }
public event FlagEnabledHandler OnFlagEnabled { add { mOnFlagEnabled += value; } remove { mOnFlagEnabled -= value; } }
public event FlagDisabledHandler OnFlagDisabled { add { mOnFlagDisabled += value; } remove { mOnFlagDisabled -= value; } }
protected virtual void clearEvents()
{
mOnInit = null;
mOnFlagEnabled = null;
mOnFlagDisabled = null;
}
#endregion
//----------------------------------------------------------------------------
}
public class ZoneRegion : InstanceFlag, ViewTrigger.ViewTriggerListener
{
public ZoneEditor.RegionData.Shape RegionType { get { return mShape; } }
///
/// Center of the position
///
public override float RadiusSize { get { return R; } }
public override float Direction { get { return 0; } }
public float Width { get { return W; } }
public float Height { get { return H; } }
public float Radius { get { return R; } }
readonly private ZoneEditor.RegionData.Shape mShape;
private float W;
private float H;
private float R;
private ViewTrigger mViewTrigger;
private bool mAllTriggerOver = false;
private bool mAllTriggerNoneAlive = false;
private List mSpawnTriggers = new List();
public ZoneRegion(InstanceZone zone, ZoneEditor.RegionData data)
: base(zone, data)
{
this.mShape = data.RegionType;
this.W = data.W;
this.H = data.H;
this.R = data.Radius;
switch (mShape)
{
case ZoneEditor.RegionData.Shape.RECTANGLE:
this.mViewTrigger = new ViewTriggerRectCenter(Parent, W, H);
break;
case ZoneEditor.RegionData.Shape.STRIP:
this.mViewTrigger = new ViewTriggerStripCenter(Parent, W, H, data.StripDirection);
break;
case ZoneEditor.RegionData.Shape.ROUND:
default:
this.mViewTrigger = new ViewTriggerRoundCenter(Parent, R);
break;
}
this.mViewTrigger.setListener(this);
}
public override TVector2 getRandomPos(Random random)
{
if (mShape == ZoneEditor.RegionData.Shape.ROUND)
{
float angle = (float)(random.NextDouble() * CMath.PI_MUL_2);
float len = (float)(random.NextDouble() * R);
float x = X + (float)(Math.Cos(angle) * len);
float y = Y + (float)(Math.Sin(angle) * len);
return new TVector2(x, y);
}
else
{
float x = X + (float)((-W / 2f) + random.NextDouble() * W);
float y = Y + (float)((-H / 2f) + random.NextDouble() * H);
return new TVector2(x, y);
}
}
public bool IsUnitInRegion(InstanceZoneObject unit)
{
return Collider.Object_BlockBody_TouchRound(unit, this.get_x(), this.get_y(), this.RadiusSize); ;
}
public void keepInRegion(ref float x, ref float y)
{
switch (mShape)
{
case ZoneEditor.RegionData.Shape.RECTANGLE:
x = CMath.getInRange(x, this.X - this.W / 2, this.X + this.W / 2);
y = CMath.getInRange(y, this.Y - this.H / 2, this.Y + this.H / 2);
break;
case ZoneEditor.RegionData.Shape.ROUND:
float d = MathVector.getDistance(x, y, this.X, this.Y);
if (d > this.R)
{
float a = MathVector.getDegree(x, y, this.X, this.Y);
MathVector.movePolar(ref x, ref y, a, d - this.R);
}
break;
}
}
protected override void Disposing()
{
base.Disposing();
mViewTrigger.Dispose();
foreach (var e in mSpawnTriggers)
{
e.OnLastObjectRemoved -= onTriggerLastObjectRemoved;
e.Dispose();
}
mSpawnTriggers.Clear();
mOnUnitEnter = null;
mOnUnitLeave = null;
mOnZoneUpdate = null;
mOnSpawnOver = null;
}
internal void AddSpawnTrigger(AbstractSpawnTrigger trigger)
{
trigger.OnLastObjectRemoved += onTriggerLastObjectRemoved;
mSpawnTriggers.Add(trigger);
mAllTriggerOver = false;
}
private void onTriggerLastObjectRemoved(ZoneRegion region, AbstractSpawnTrigger trigger, InstanceZoneObject unit)
{
if (mOnSpawnOver != null && IsSpawnOver)
{
mOnSpawnOver.Invoke(this);
}
}
///
/// 获取此区域绑定的怪物刷新点
///
///
public IEnumerable GetSpawnTriggers()
{
return mSpawnTriggers;
}
///
/// 获取此区域绑定的怪物刷新点
///
///
///
public AbstractSpawnTrigger GetSpawnTrigger(string name)
{
for (int i = mSpawnTriggers.Count - 1; i >= 0; --i)
{
AbstractSpawnTrigger tg = mSpawnTriggers[i];
if (string.Equals(tg.Name, name))
{
return tg;
}
}
return null;
}
///
/// 检测是否所有刷怪点都结束
///
public bool IsSpawnOver
{
get
{
if (!mAllTriggerOver)
{
for (int i = mSpawnTriggers.Count - 1; i >= 0; --i)
{
AbstractSpawnTrigger tg = mSpawnTriggers[i];
if (!tg.IsSpawnOver)
{
return false;
}
}
mAllTriggerOver = true;
}
return true;
}
}
///
/// 检测是否所有刷怪点都无存活
///
public bool IsSpawnNoneAlive
{
get
{
if (!mAllTriggerNoneAlive)
{
for (int i = mSpawnTriggers.Count - 1; i >= 0; --i)
{
AbstractSpawnTrigger tg = mSpawnTriggers[i];
if (!tg.IsSpawnOver)
{
return false;
}
if (tg.AliveCount > 0)
{
return false;
}
}
mAllTriggerNoneAlive = true;
}
return true;
}
}
internal override void update()
{
base.update();
if (Enable && (mOnUnitEnter != null || mOnUnitLeave != null || mEnterOnceList.Count > 0 || mLeaveOnceList.Count > 0))
{
mViewTrigger.Enable = true;
mViewTrigger.onLookUpdate(X, Y);
}
else
{
mViewTrigger.Enable = false;
}
if (Enable && mOnZoneUpdate != null)
{
mOnZoneUpdate.Invoke(this);
}
}
void ViewTrigger.ViewTriggerListener.onObjectEnterView(ViewTrigger src, InstanceZoneObject obj)
{
if (mOnUnitEnter != null)
{
mOnUnitEnter.Invoke(this, obj as InstanceUnit);
}
mEnterOnceList.Invoke(this, obj as InstanceUnit);
}
void ViewTrigger.ViewTriggerListener.onObjectLeaveView(ViewTrigger src, InstanceZoneObject obj)
{
if (mOnUnitLeave != null)
{
mOnUnitLeave.Invoke(this, obj as InstanceUnit);
}
mLeaveOnceList.Invoke(this, obj as InstanceUnit);
}
bool ViewTrigger.ViewTriggerListener.select(ViewTrigger src, InstanceZoneObject obj)
{
return obj is InstanceUnit;
}
public void addInRegionViewed(InstanceUnit unit)
{
if (mViewTrigger != null)
{
mViewTrigger.addViewed(unit);
}
}
///
/// 获得所有由此刷新点产生的单位
///
///
///
public void getSpawnedObjectsInRegion(List list) where T : InstanceZoneObject
{
foreach (var spawn in mSpawnTriggers)
{
spawn.getSpawnedObjects(list);
}
}
//[Obsolete]
//private List getObjectsInRegion(ObjectAoiStatus aoi) where T : InstanceZoneObject
//{
// if (this.RegionType == ZoneEditor.RegionData.Shape.RECTANGLE)
// {
// return Parent.getObjectsRectRange(
// Collider.Object_Pos_IncludeInRect,
// this.X, this.Y, this.Width, this.Height , aoi);
// }
// else
// {
// return Parent.getObjectsRoundRange(
// Collider.Object_Pos_IncludeInRound,
// this.X, this.Y, this.Radius, aoi);
// }
//}
public void getObjectsInRegion(List list, ObjectAoiStatus aoi = null) where T : InstanceZoneObject
{
if (this.RegionType == ZoneEditor.RegionData.Shape.RECTANGLE)
{
Parent.getObjectsRectRange(
Collider.Object_Pos_IncludeInRect,
this.X - this.Width/2, this.Y- this.Height/2, this.X + this.Width/2, this.Y + this.Height/2,
list, aoi);
}
else
{
Parent.getObjectsRoundRange(
Collider.Object_Pos_IncludeInRound,
this.X, this.Y, this.Radius,
list, aoi);
}
}
public int getObjectsCountInRegion(ObjectAoiStatus aoi = null) where T : InstanceZoneObject
{
if (this.RegionType == ZoneEditor.RegionData.Shape.RECTANGLE)
{
return Parent.getObjectsCountRectRange(Collider.Object_Pos_IncludeInRect,
this.X - this.Width / 2, this.Y - this.Height / 2, this.X + this.Width / 2, this.Y + this.Height / 2, aoi);
}
else
{
return Parent.getObjectsCountRoundRange(
Collider.Object_Pos_IncludeInRound,
this.X, this.Y, this.Radius, aoi);
}
}
//[Obsolete]
//private List getObjectsInRegion(Select select, ObjectAoiStatus aoi) where T : InstanceZoneObject
//{
// List list = getObjectsInRegion();
// for (int i = list.Count - 1; i >= 0; --i)
// {
// if (!select.Invoke(list[i]))
// {
// list.RemoveAt(i);
// }
// }
// return list;
//}
public int getObjectsCountInRegion(Select select , ObjectAoiStatus aoi = null) where T : InstanceZoneObject
{
int ret = 0;
using (var list = ListObjectPool.AllocAutoRelease())
{
getObjectsInRegion(list , aoi);
for (int i = list.Count - 1; i >= 0; --i)
{
if (select.Invoke(list[i]))
{
ret++;
}
}
}
return ret;
}
//--------------------------------------------------------------------------------------------------------------
#region Delegate
///
/// 某单位进入此区域
///
///
///
public delegate void UnitEnterHandler(ZoneRegion region, InstanceUnit obj);
///
/// 某单位离开此区域
///
///
///
public delegate void UnitLeaveHandler(ZoneRegion region, InstanceUnit obj);
///
/// 区域更新
///
///
public delegate void ZoneUpdateHandler(ZoneRegion region);
///
/// 刷新点刷新完毕
///
///
public delegate void SpawnOverHandler(ZoneRegion region);
private UnitEnterHandler mOnUnitEnter;
private UnitLeaveHandler mOnUnitLeave;
private ZoneUpdateHandler mOnZoneUpdate;
private SpawnOverHandler mOnSpawnOver;
public event UnitEnterHandler OnUnitEnter { add { mOnUnitEnter += value; } remove { mOnUnitEnter -= value; } }
public event UnitLeaveHandler OnUnitLeave { add { mOnUnitLeave += value; } remove { mOnUnitLeave -= value; } }
public event ZoneUpdateHandler OnZoneUpdate { add { mOnZoneUpdate += value; } remove { mOnZoneUpdate -= value; } }
public event SpawnOverHandler OnSpawnOver { add { mOnSpawnOver += value; } remove { mOnSpawnOver -= value; } }
//--------------------------------------------------------------------------------------------------------------
private struct OnceEvent : IOnceInvoke
{
public InstanceUnit unit { get; private set; }
public bool IsDone { get { return done || !unit.Enable; } }
private UnitEnterHandler enter_handler;
private UnitLeaveHandler leave_handler;
private bool done;
public OnceEvent(InstanceUnit unit, UnitEnterHandler enter, UnitLeaveHandler leave)
{
this.unit = unit;
this.enter_handler = enter;
this.leave_handler = leave;
this.done = false;
}
public void Invoke(ZoneRegion region)
{
if (enter_handler != null) this.enter_handler.Invoke(region, unit);
if (leave_handler != null) this.leave_handler.Invoke(region, unit);
this.enter_handler = null;
this.leave_handler = null;
this.done = true;
}
}
private class OnceInvokeList : OnceInvokeList
{
public void Invoke(ZoneRegion region, InstanceUnit unit)
{
base.Invoke((e) =>
{
if (e.unit == unit)
{
e.Invoke(region);
}
});
}
}
private OnceInvokeList mEnterOnceList = new OnceInvokeList();
private OnceInvokeList mLeaveOnceList = new OnceInvokeList();
///
/// 监听单位进入一次,触发器只触发一次
///
///
///
public void ListenUnitEnterOnce(InstanceUnit unit, UnitEnterHandler handler)
{
mEnterOnceList.Add(new OnceEvent(unit, handler, null));
}
///
/// 监听单位离开一次,触发器只触发一次
///
///
///
public void ListenUnitLeaveOnce(InstanceUnit unit, UnitLeaveHandler handler)
{
mLeaveOnceList.Add(new OnceEvent(unit, null, handler));
}
//--------------------------------------------------------------------------------------------------------------
protected override void clearEvents()
{
base.clearEvents();
mEnterOnceList.Clear();
mLeaveOnceList.Clear();
mOnUnitEnter = null;
mOnUnitLeave = null;
mOnZoneUpdate = null;
mOnSpawnOver = null;
}
#endregion
}
public class ZoneWayPoint : InstanceFlag
{
public override float RadiusSize { get { return 1; } }
public override float Direction { get { return 0; } }
private IList mNexts = new List();
public ZoneWayPoint(InstanceZone zone, ZoneEditor.PointData data)
: base(zone, data)
{
}
public override TVector2 getRandomPos(Random random)
{
return new TVector2(X, Y);
}
internal override void update()
{
base.update();
}
internal void AddNext(ZoneWayPoint next)
{
mNexts.Add(next);
}
public ZoneWayPoint GetRandomNext(ZoneWayPoint prev = null)
{
if (mNexts.Count > 0)
{
if (mNexts.Count == 1)
{
return mNexts[0];
}
int nexti = Parent.RandomN.Next(0, mNexts.Count);
for (int i = 0; i < mNexts.Count; i++)
{
int idx = CMath.cycNum(nexti, i, mNexts.Count);
if (mNexts[idx] != prev)
{
return mNexts[idx];
}
}
return mNexts[nexti];
}
return null;
}
public ZoneWayPoint GetNext()
{
if (mNexts.Count > 0)
{
return mNexts[0];
}
return null;
}
public ZoneWayPoint GetTail()
{
if (mNexts.Count == 0)
{
return this;
}
ZoneWayPoint wp = GetNext();
while (true)
{
ZoneWayPoint next = wp.GetNext();
if (next != null)
{
wp = next;
}
else
{
break;
}
}
return wp;
}
}
public class ZoneDecoration : InstanceFlag
{
public override float RadiusSize { get { return this.R; } }
public override float Direction { get { return this.StripDirection; } }
readonly private ZoneEditor.DecorationData.Shape mShape;
private float W;
private float H;
private float R;
private float StripDirection;
private bool Blockable;
private int BlockValue;
public ZoneDecoration(InstanceZone zone, ZoneEditor.DecorationData data)
: base(zone, data)
{
this.mShape = data.RegionType;
this.W = data.W;
this.H = data.H;
this.R = data.Radius;
this.StripDirection = data.StripDirection;
this.Blockable = data.Blockable;
this.BlockValue = data.BlockValue;
this.OnFlagEnabled += this.OnEnabled;
this.OnFlagDisabled += this.OnDisabled;
if (Blockable)
{
this.OnFlagEnabled += this.OnTerrainEnabled;
this.OnFlagDisabled += this.OnTerrainDisabled;
}
}
internal override void update()
{
base.update();
}
public override TVector2 getRandomPos(Random random)
{
if (mShape == ZoneEditor.DecorationData.Shape.ROUND)
{
float angle = (float)(random.NextDouble() * CMath.PI_MUL_2);
float len = (float)(random.NextDouble() * R);
float x = X + (float)(Math.Cos(angle) * len);
float y = Y + (float)(Math.Sin(angle) * len);
return new TVector2(x, y);
}
else
{
float x = X + (float)((-W / 2f) + random.NextDouble() * W);
float y = Y + (float)((-H / 2f) + random.NextDouble() * H);
return new TVector2(x, y);
}
}
private void OnEnabled(InstanceFlag flag)
{
Parent.queueEvent(new DecorationChangedEvent(Name, true));
}
private void OnDisabled(InstanceFlag flag)
{
Parent.queueEvent(new DecorationChangedEvent(Name, false));
}
#region FillTerrain
private void OnTerrainEnabled(InstanceFlag flag)
{
this.FillTerrain(fill_Terrain_value);
}
private void OnTerrainDisabled(InstanceFlag flag)
{
this.FillTerrain(fill_Terrain_reset);
}
private void fill_Terrain_value(int bx, int by)
{
Parent.PathFinder.TryFillTerrain(bx, by, BlockValue);
}
private void fill_Terrain_reset(int bx, int by)
{
Parent.PathFinder.TryFillTerrain(bx, by, Parent.TerrainSrc.TerrainMatrix[bx, by]);
}
protected void FillTerrain(AstarManhattan.ForEachTerrainAction fillAction)
{
var mmap = Parent.PathFinder.MMap;
switch (this.mShape)
{
case ZoneEditor.DecorationData.Shape.RECTANGLE:
AstarManhattan.ForEachTerrainRect(mmap, X - W / 2, Y - H / 2, W, H, fillAction);
break;
case ZoneEditor.DecorationData.Shape.ROUND:
AstarManhattan.ForEachTerrainEllipse(mmap, X - W / 2, Y - H / 2, W, H, fillAction);
break;
case ZoneEditor.DecorationData.Shape.STRIP:
TLine2 line = new TLine2(X, Y, X, Y);
MathVector.movePolarExt(ref line.p, StripDirection, -H / 2);
MathVector.movePolarExt(ref line.q, StripDirection, +H / 2);
AstarManhattan.ForEachTerrainStripWidth(mmap, line.p.X, line.p.Y, line.q.X, line.q.Y, W / 2, fillAction);
break;
}
Parent.PathFinder.BeginFindPath();
}
public bool TouchBlock(float x, float y)
{
if (Blockable && Enable && Parent.PathFinder.MMap.TestBlockValue(this.BlockValue))
{
int bx = (((int)x) / Parent.TerrainSrc.GridCellW);
int by = (((int)y) / Parent.TerrainSrc.GridCellH);
var mmap = Parent.PathFinder.MMap;
switch (this.mShape)
{
case ZoneEditor.DecorationData.Shape.RECTANGLE:
return AstarManhattan.ForEachTerrainRect(mmap, X - W / 2, Y - H / 2, W, H,
(cx, cy) => { return cx == bx && cy == by; });
case ZoneEditor.DecorationData.Shape.ROUND:
return AstarManhattan.ForEachTerrainEllipse(mmap, X - W / 2, Y - H / 2, W, H,
(cx, cy) => { return cx == bx && cy == by; });
case ZoneEditor.DecorationData.Shape.STRIP:
TLine2 line = new TLine2(X, Y, X, Y);
MathVector.movePolarExt(ref line.p, StripDirection, -H / 2);
MathVector.movePolarExt(ref line.q, StripDirection, +H / 2);
return AstarManhattan.ForEachTerrainStripWidth(mmap, line.p.X, line.p.Y, line.q.X, line.q.Y, W / 2,
(cx, cy) => { return cx == bx && cy == by; });
}
}
return false;
}
#endregion
}
public class ZoneArea : InstanceFlag
{
public override float RadiusSize { get { return this.R; } }
public override float Direction { get { return 0; } }
public int CurrentMapNodeValue { get; private set; }
private float W;
private float H;
private float R;
public ZoneArea(InstanceZone zone, ZoneEditor.AreaData data)
: base(zone, data)
{
this.W = data.W;
this.H = data.H;
this.R = data.W / 2;
}
internal void BindMapBlock(AreaData data)
{
//var current_node = Parent.PathFinder.GetMapNodeByPos(X, Y);
//if (current_node != null)
{
this.CurrentMapNodeValue = data.Color;
var list = Parent.TerrainAreaGenerator.GetContinuousMapNode(X, Y, W / 2, H / 2);
foreach (var index in list)
{
var node = Parent.PathFinder.GetMapNode(index.BX, index.BY) as ZoneMapNode;
if (node != null)
{
node.SetServerArea(this);
}
}
}
}
public override TVector2 getRandomPos(Random random)
{
return new TVector2(X, Y);
}
internal void do_onUnitEnter(InstanceZoneObject obj)
{
if (obj is InstanceUnit)
{
if (mOnUnitEnter != null) mOnUnitEnter.Invoke(this, obj as InstanceUnit);
if (mEnterOnceList.Count > 0) mEnterOnceList.Invoke(this, obj as InstanceUnit);
}
}
internal void do_onUnitLeave(InstanceZoneObject obj)
{
if (obj is InstanceUnit)
{
if (mOnUnitLeave != null) mOnUnitLeave.Invoke(this, obj as InstanceUnit);
if (mLeaveOnceList.Count > 0) mLeaveOnceList.Invoke(this, obj as InstanceUnit);
}
}
//----------------------------------------------------------------------------
#region Delegate
///
/// 某单位进入此区域
///
///
///
public delegate void UnitEnterHandler(ZoneArea area, InstanceUnit obj);
///
/// 某单位离开此区域
///
///
///
public delegate void UnitLeaveHandler(ZoneArea area, InstanceUnit obj);
private UnitEnterHandler mOnUnitEnter;
private UnitLeaveHandler mOnUnitLeave;
public event UnitEnterHandler OnUnitEnter { add { mOnUnitEnter += value; } remove { mOnUnitEnter -= value; } }
public event UnitLeaveHandler OnUnitLeave { add { mOnUnitLeave += value; } remove { mOnUnitLeave -= value; } }
//----------------------------------------------------------------------------
private struct OnceEvent : IOnceInvoke
{
public InstanceUnit unit { get; private set; }
public bool IsDone { get { return done || !unit.Enable; } }
private UnitEnterHandler enter_handler;
private UnitLeaveHandler leave_handler;
private bool done;
public OnceEvent(InstanceUnit unit, UnitEnterHandler enter, UnitLeaveHandler leave)
{
this.unit = unit;
this.enter_handler = enter;
this.leave_handler = leave;
this.done = false;
}
public void Invoke(ZoneArea area)
{
if (enter_handler != null) this.enter_handler.Invoke(area, unit);
if (leave_handler != null) this.leave_handler.Invoke(area, unit);
this.enter_handler = null;
this.leave_handler = null;
this.done = true;
}
}
private class OnceInvokeList : OnceInvokeList
{
public void Invoke(ZoneArea area, InstanceUnit unit)
{
base.Invoke((e) =>
{
if (e.unit == unit)
{
e.Invoke(area);
}
});
}
}
private OnceInvokeList mEnterOnceList = new OnceInvokeList();
private OnceInvokeList mLeaveOnceList = new OnceInvokeList();
///
/// 监听单位进入一次,触发器只触发一次
///
///
///
public void ListenUnitEnterOnce(InstanceUnit unit, UnitEnterHandler handler)
{
mEnterOnceList.Add(new OnceEvent(unit, handler, null));
}
///
/// 监听单位离开一次,触发器只触发一次
///
///
///
public void ListenUnitLeaveOnce(InstanceUnit unit, UnitLeaveHandler handler)
{
mLeaveOnceList.Add(new OnceEvent(unit, null, handler));
}
//----------------------------------------------------------------------------
protected override void clearEvents()
{
base.clearEvents();
mEnterOnceList.Clear();
mLeaveOnceList.Clear();
mOnUnitEnter = null;
mOnUnitLeave = null;
}
#endregion
//----------------------------------------------------------------------------
}
}