using CommonAI.RTS;
using CommonLang.Vector;
using CommonAI.Zone.Helper;
using CommonLang;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using CommonAI.Zone.Instance.Helper;
using CommonAI.Data;
namespace CommonAI.Zone.Instance
{
public class InstancePet : InstanceUnit, ISummonedUnit
{
protected InstanceUnit mMaster;
protected StateFollowMaster mFollowMaster;
public InstanceUnit Owner { get { return this; } }
public InstancePet(InstanceZone zone, UnitInfo info, string name, int force, int level)
: base(zone, info, name, force, level)
{
s_mFollowDistance = Templates.CFG.PET_FOLLOW_DISTANCE_MIN + (Templates.CFG.PET_FOLLOW_DISTANCE_MAX - Templates.CFG.PET_FOLLOW_DISTANCE_MIN) / 2;
}
public override bool IntersectMap { get { return Info.BodySize > 0; } }
public override bool IntersectObj { get { return false; } }
public override bool IsActive { get { return false; } }
public override bool IsAttackable { get { return false; } }
///
/// 获取主人
///
public virtual InstanceUnit Master
{
get { return mMaster; }
set { this.mMaster = value; this.mFollowMaster = new StateFollowMaster(this, mMaster); }
}
public virtual InstanceUnit SummonerUnit
{
get { return Master; }
set { Master = value; }
}
///
/// IAO标记
///
public override ObjectAoiStatus AoiStatus { get { return this.Master == null ? base.AoiStatus : this.Master.AoiStatus; } }
// 跟随最大最小距离的中间值
public static float s_mFollowDistance = 0;
protected override void onUpdate(bool slowRefresh)
{
base.onUpdate(slowRefresh);
OnPetUpdate();
}
protected virtual void OnPetUpdate()
{
if (mMaster != null)
{
if (mMaster.IsDead() || !mMaster.Enable)
{
this.kill(this);
}
else if (!CMath.includeRoundPoint(X, Y, Templates.CFG.PET_FOLLOW_DISTANCE_LIMIT, mMaster.X, mMaster.Y))
{
this.transportToMaster();
}
else if (!CMath.includeRoundPoint(X, Y, Templates.CFG.PET_FOLLOW_DISTANCE_MAX, mMaster.X, mMaster.Y))
{
this.followMaster();
}
}
if (CurrentState is StateIdle)
{
doSomething2();
}
}
protected void transportToMaster()
{
float dx, dy;
CMath.RandomPosInRound(Parent.RandomN, mMaster.X, mMaster.Y, Templates.CFG.PET_FOLLOW_DISTANCE_MAX, out dx, out dy);
if (IntersectMap && Parent.TryTouchMap(this, dx, dy))
{
dx = Master.X;
dy = Master.Y;
}
this.Virtual.SetCombatState(BattleStatus.None);
this.transport(dx, dy);
this.followMaster();
}
protected void followMaster()
{
StateSkill skillState = this.CurrentState as StateSkill;
if (skillState != null && skillState.Skill != null && !skillState.IsCancelableByMove)
{
return;
}
else if(CurrentState == mFollowMaster)
{
return;
}
//float distanceTemp = MathVector.getDistance(this.X, this.Y, this.Master.X, this.Master.Y);
float speedChag = 1.01f;// (distanceTemp < s_mFollowDistance) ? 1.01f : 1.1f;
this.followMasterChangeSpeed(speedChag);
changeState(mFollowMaster);
//System.Console.WriteLine("---followMaster: " + TimeUtil.GetTimestampMS() + speedChag);
}
protected virtual void followMasterChangeSpeed(float speedChag)
{
// 随从使用主人的速度
if (this.Master != null)
{
this.SetMoveSpeed(this.Master.MoveSpeedSEC * speedChag);
}
}
protected void doSomething2()
{
if (!IsNoneSkill)
{
using (var list = ListObjectPool.AllocAutoRelease())
{
//随机找个目标施法//
Parent.getObjectsRoundRange(Collider.Object_Pos_IncludeInRound, X, Y, Info.GuardRange, list, this.AoiStatus);
DoAndRemoveCollection.UpdateAndRemove(list, (InstanceUnit u) =>
{
return !u.IsActive;
});
CUtils.RandomList(Parent.RandomN, list);
foreach (SkillState skill in SkillStatus)
{
if (skill.LaunchSkill.AutoLaunch && skill.TryLaunch())
{
foreach (InstanceUnit u in list)
{
if (Parent.IsAttackable(this, u, skill.Data.ExpectTarget, AttackReason.Look, skill.Data))
{
//检测是否有可释放技能//
if (tryAutoLaunch(skill, u))
{
return;
}
}
}
}
}
}
}
}
protected virtual bool tryAutoLaunch(SkillState st, InstanceUnit target)
{
if (st != null && st.LaunchSkill.AutoLaunch)
{
changeState(new StateFollowAndAttack(this, target, st.Data.ExpectTarget));
return true;
}
return false;
}
protected override void Disposing()
{
mMaster = null;
mFollowMaster = null;
base.Disposing();
}
//----------------------------------------------------------------------------------------------------------
protected override IUnitStatistic CreateUnitStatistic()
{
return new PetUnitStatistic(this);
//return base.CreateUnitStatistic();
}
public class PetUnitStatistic : UnitStatistic
{
private InstancePet owner;
public PetUnitStatistic(InstancePet owner) : base(owner)
{
this.owner = owner;
}
public override void onAttack(InstanceUnit target, int reduceHP)
{
//伤害统计重定向到主人//
if (owner.Master != null)
{
owner.Master.Statistic.onAttack(target, reduceHP);
}
else
{
base.onAttack(target, reduceHP);
}
}
public override void onKill(InstanceUnit target)
{
//击杀统计重定向到主人//
if (owner.Master != null)
{
owner.Master.Statistic.onKill(target);
}
else
{
base.onKill(target);
}
}
}
//----------------------------------------------------------------------------------------------------------
///
/// 移动状态
///
public class StateFollowMaster : State
{
// 被追目标
readonly private InstanceZoneObject master;
private MoveAI move;
public StateFollowMaster(InstancePet unit, InstanceZoneObject target)
: base(unit)
{
this.master = target;
this.move = new MoveAI(unit);
}
override public bool onBlock(State new_state)
{
if (new_state is StateDead)
{
return true;
}
if (new_state is StateFollowMaster)
{
return true;
}
float r = Math.Max(zone.Templates.CFG.PET_FOLLOW_DISTANCE_MIN, master.BodyBlockSize + unit.BodyBlockSize);
if (CMath.includeRoundPoint(unit.X, unit.Y, r, master.X, master.Y))
{
unit.SetActionStatus(UnitActionStatus.Idle);
return true;
}
StateSkill stateSkill = new_state as StateSkill;
if(stateSkill != null && !stateSkill.IsCancelableByMove)
{
return true;
}
return false;
}
override protected void onStart()
{
unit.SetActionStatus(UnitActionStatus.Move);
this.move.FindPath(master);
}
override protected void onUpdate()
{
float r = Math.Max(zone.Templates.CFG.PET_FOLLOW_DISTANCE_MIN, master.BodyBlockSize + unit.BodyBlockSize);
if (CMath.includeRoundPoint(unit.X, unit.Y, r, master.X, master.Y))
{
unit.SetActionStatus(UnitActionStatus.Idle);
unit.doSomething();
}
else
{
move.Update();
if (move.IsNoWay)
{
(unit as InstancePet).transportToMaster();
}
}
}
override protected void onStop()
{
unit.SetActionStatus(UnitActionStatus.Idle);
}
}
}
}