private void CheckImpact(NpcInfo npc) { DashFireSpatial.ISpatialSystem spatialSys = npc.SpatialSystem; if (null != spatialSys) { bool existNpcInAttackRange = false; ScriptRuntime.Vector3 srcPos = npc.GetMovementStateInfo().GetPosition3D(); spatialSys.VisitObjectInCircle(srcPos, npc.GetActualProperty().AttackRange, (float distSqr, ISpaceObject obj) => { if (obj.GetObjType() == SpatialObjType.kNPC && (int)obj.GetID() != npc.GetId()) { NpcInfo npcObj = obj.RealObject as NpcInfo; if (null != npcObj && npcObj.NpcType != (int)NpcTypeEnum.PvpTower) { existNpcInAttackRange = true; return(false); } } return(true); }); if (existNpcInAttackRange) { ImpactInfo impactInfo = npc.GetSkillStateInfo().GetImpactInfoById(c_ImpactForTower); if (null == impactInfo) { ServerNpcImpact(npc, c_ImpactForTower, npc); } } } }
private void GoHomeHandler(NpcInfo npc, AiCommandDispatcher aiCmdDispatcher, long deltaTime) { if (npc.IsDead()) { return; } AiData_PveNpc_Monster_CloseCombat data = GetAiData(npc); if (null != data) { if (null != npc.GetSkillStateInfo().GetImpactInfoById(data.FastMoveImpact)) { ServerNpcStopImpact(npc, data.FastMoveImpact); } if (null != npc.GetSkillStateInfo().GetImpactInfoById(data.PreAttackImpact)) { ServerNpcStopImpact(npc, data.PreAttackImpact); } } ChangeToState(npc, (int)AiStateId.Idle); }
internal NpcInfo SummonNpc(int id, int owner_id, int owner_skillid, int npc_type_id, string modelPrefab, int skillid, int ailogicid, bool followsummonerdead, float x, float y, float z, string aiparamstr) { CharacterInfo charObj = SceneContext.GetCharacterInfoById(owner_id); if (charObj == null) { return(null); } NpcInfo npc = null; SkillInfo ownerSkillInfo = charObj.GetSkillStateInfo().GetSkillInfoById(owner_skillid); if (null != ownerSkillInfo) { if (null != ownerSkillInfo.m_EnableSummonNpcs && ownerSkillInfo.m_EnableSummonNpcs.Contains(npc_type_id)) { //ownerSkillInfo.m_EnableSummonNpcs.Remove(npc_type_id); Data_Unit data = new Data_Unit(); data.m_Id = -1; data.m_LinkId = npc_type_id; data.m_CampId = charObj.GetCampId(); data.m_IsEnable = true; data.m_Pos = new Vector3(x, y, z); data.m_RotAngle = 0; data.m_AiLogic = ailogicid; if (!string.IsNullOrEmpty(aiparamstr)) { string[] strarry = aiparamstr.Split(new char[] { ',' }, 8); int i = 0; foreach (string str in strarry) { data.m_AiParam[i++] = str; } } npc = NpcManager.AddNpc(data); if (!string.IsNullOrEmpty(modelPrefab)) { npc.SetModel(modelPrefab); } npc.FollowSummonerDead = followsummonerdead; SkillInfo skillinfo = new SkillInfo(skillid); npc.GetSkillStateInfo().AddSkill(skillinfo); npc.GetMovementStateInfo().SetPosition(data.m_Pos); npc.SummonOwnerId = charObj.GetId(); charObj.GetSkillStateInfo().AddSummonObject(npc); AbstractNpcStateLogic.OnNpcSkill(npc, skillid); } } return(npc); }
private void OnNpcSkill(NpcInfo npc, int skillId) { Scene scene = npc.SceneContext.CustomData as Scene; if (null != scene) { SkillInfo skillInfo = npc.GetSkillStateInfo().GetCurSkillInfo(); if (null == skillInfo || !skillInfo.IsSkillActivated) { SkillInfo curSkillInfo = npc.GetSkillStateInfo().GetSkillInfoById(skillId); if (null != curSkillInfo) { long curTime = TimeUtility.GetServerMilliseconds(); if (!curSkillInfo.IsInCd(curTime / 1000.0f)) { curSkillInfo.StartTime = curTime / 1000.0f; curSkillInfo.BeginCD(); scene.SkillSystem.StartSkill(npc.GetId(), skillId); Msg_RC_NpcSkill skillBuilder = new Msg_RC_NpcSkill(); skillBuilder.npc_id = npc.GetId(); skillBuilder.skill_id = skillId; ArkCrossEngineMessage.Position posBuilder1 = new ArkCrossEngineMessage.Position(); posBuilder1.x = npc.GetMovementStateInfo().GetPosition3D().X; posBuilder1.z = npc.GetMovementStateInfo().GetPosition3D().Z; skillBuilder.stand_pos = posBuilder1; skillBuilder.face_direction = (float)npc.GetMovementStateInfo().GetFaceDir(); LogSystem.Debug("Send Msg_RC_NpcSkill, EntityId={0}, SkillId={1}", npc.GetId(), skillId); scene.NotifyAreaUser(npc, skillBuilder); } } } } }
private void IdleHandler(NpcInfo npc, AiCommandDispatcher aiCmdDispatcher, long deltaTime) { if (npc.IsDead()) { return; } NpcAiStateInfo info = npc.GetAiStateInfo(); AiData_PveNpc_Trap data = GetAiData(npc); if (null != data) { info.Time += deltaTime; if (info.Time > 100) { info.Time = 0; if (data.HideImpact > 0) { ImpactInfo impactInfo = npc.GetSkillStateInfo().GetImpactInfoById(data.HideImpact); if (null == impactInfo) { ServerNpcImpact(npc, data.HideImpact, npc); } } IList <ISpaceObject> objs = npc.SpatialSystem.GetObjectInCircle(npc.GetMovementStateInfo().GetPosition3D(), data.RadiusOfTrigger); foreach (ISpaceObject obj in objs) { if (obj.GetObjType() == SpatialObjType.kNPC || obj.GetObjType() == SpatialObjType.kUser) { CharacterInfo charInfo = obj.RealObject as CharacterInfo; if (null != charInfo) { if (CharacterInfo.GetRelation(npc, charInfo) == CharacterRelation.RELATION_ENEMY) { info.Time = 0; info.Target = charInfo.GetId(); ChangeToState(npc, (int)AiStateId.Combat); NotifyNpcTargetChange(npc); break; } } } } } } }
private AiData_PveNpc_Monster GetAiData(NpcInfo npc) { AiData_PveNpc_Monster data = npc.GetAiStateInfo().AiDatas.GetData <AiData_PveNpc_Monster>(); if (null == data) { NpcAiStateInfo info = npc.GetAiStateInfo(); data = new AiData_PveNpc_Monster(); SkillInfo skillInfo = npc.GetSkillStateInfo().GetSkillInfoByIndex(0); if (null != skillInfo) { data.Skill = skillInfo.SkillId; } data.ShootDistance = int.Parse(info.AiParam[0]); npc.GetAiStateInfo().AiDatas.AddData(data); } return(data); }
private void OnNpcStopSkill(NpcInfo npc) { Scene scene = npc.SceneContext.CustomData as Scene; if (null != scene) { SkillInfo skillInfo = npc.GetSkillStateInfo().GetCurSkillInfo(); if (null == skillInfo || skillInfo.IsSkillActivated) { scene.SkillSystem.StopSkill(npc.GetId()); } Msg_CRC_NpcStopSkill skillBuilder = new Msg_CRC_NpcStopSkill(); skillBuilder.npc_id = npc.GetId(); LogSystem.Debug("Send Msg_RC_NpcStopSkill, EntityId={0}", npc.GetId()); scene.NotifyAreaUser(npc, skillBuilder); } }
internal void SummonPartner(Msg_CR_SummonPartner msg) { UserInfo userInfo = UserManager.GetUserInfo(msg.obj_id); if (null != userInfo) { // summonpartner PartnerInfo partnerInfo = userInfo.GetPartnerInfo(); if (null != partnerInfo && (TimeUtility.GetServerMilliseconds() - userInfo.LastSummonPartnerTime > partnerInfo.CoolDown || userInfo.LastSummonPartnerTime == 0)) { Data_Unit data = new Data_Unit(); data.m_Id = -1; data.m_LinkId = partnerInfo.LinkId; data.m_CampId = userInfo.GetCampId(); data.m_Pos = userInfo.GetMovementStateInfo().GetPosition3D(); data.m_RotAngle = 0; data.m_AiLogic = partnerInfo.GetAiLogic(); data.m_AiParam[0] = ""; data.m_AiParam[1] = ""; data.m_AiParam[2] = partnerInfo.GetAiParam().ToString(); data.m_IsEnable = true; NpcInfo npc = NpcManager.AddNpc(data); if (null != npc) { AppendAttributeConfig aac = AppendAttributeConfigProvider.Instance.GetDataById(partnerInfo.GetAppendAttrConfigId()); float inheritAttackAttrPercent = partnerInfo.GetInheritAttackAttrPercent(); float inheritDefenceAttrPercent = partnerInfo.GetInheritDefenceAttrPercent(); if (null != aac) { // attack npc.GetBaseProperty().SetAttackBase(Operate_Type.OT_Absolute, (int)(userInfo.GetActualProperty().AttackBase *inheritAttackAttrPercent)); npc.GetBaseProperty().SetFireDamage(Operate_Type.OT_Absolute, userInfo.GetActualProperty().FireDamage *inheritAttackAttrPercent); npc.GetBaseProperty().SetIceDamage(Operate_Type.OT_Absolute, userInfo.GetActualProperty().IceDamage *inheritAttackAttrPercent); npc.GetBaseProperty().SetPoisonDamage(Operate_Type.OT_Absolute, userInfo.GetActualProperty().PoisonDamage *inheritAttackAttrPercent); // defence npc.GetBaseProperty().SetHpMax(Operate_Type.OT_Absolute, (int)(userInfo.GetActualProperty().HpMax *inheritDefenceAttrPercent)); npc.GetBaseProperty().SetEnergyMax(Operate_Type.OT_Absolute, (int)(userInfo.GetActualProperty().EnergyMax *inheritDefenceAttrPercent)); npc.GetBaseProperty().SetADefenceBase(Operate_Type.OT_Absolute, (int)(userInfo.GetActualProperty().ADefenceBase *inheritDefenceAttrPercent)); npc.GetBaseProperty().SetMDefenceBase(Operate_Type.OT_Absolute, (int)(userInfo.GetActualProperty().MDefenceBase *inheritDefenceAttrPercent)); npc.GetBaseProperty().SetFireERD(Operate_Type.OT_Absolute, userInfo.GetActualProperty().FireERD *inheritDefenceAttrPercent); npc.GetBaseProperty().SetIceERD(Operate_Type.OT_Absolute, userInfo.GetActualProperty().IceERD *inheritDefenceAttrPercent); npc.GetBaseProperty().SetPoisonERD(Operate_Type.OT_Absolute, userInfo.GetActualProperty().PoisonERD *inheritDefenceAttrPercent); // reset hp & energy npc.SetHp(Operate_Type.OT_Absolute, npc.GetBaseProperty().HpMax); npc.SetEnergy(Operate_Type.OT_Absolute, npc.GetBaseProperty().EnergyMax); } npc.SetAIEnable(true); npc.GetSkillStateInfo().RemoveAllSkill(); npc.BornTime = TimeUtility.GetServerMilliseconds(); List <int> skillList = partnerInfo.GetSkillList(); if (null != skillList) { for (int i = 0; i < skillList.Count; ++i) { SkillInfo skillInfo = new SkillInfo(skillList[i]); npc.GetSkillStateInfo().AddSkill(skillInfo); } } userInfo.LastSummonPartnerTime = TimeUtility.GetServerMilliseconds(); npc.OwnerId = userInfo.GetId(); userInfo.PartnerId = npc.GetId(); if (partnerInfo.BornSkill > 0) { SkillInfo skillInfo = new SkillInfo(partnerInfo.BornSkill); npc.GetSkillStateInfo().AddSkill(skillInfo); } ArkCrossEngineMessage.Msg_RC_CreateNpc builder = DataSyncUtility.BuildCreateNpcMessage(npc); NotifyAllUser(builder); } } } }
private void PursuitHandler(NpcInfo npc, AiCommandDispatcher aiCmdDispatcher, long deltaTime) { if (npc.IsDead() || npc.GetSkillStateInfo().IsSkillActivated()) { return; } NpcAiStateInfo info = npc.GetAiStateInfo(); bool toIdle = false; AiData_PveNpc_Monster data = GetAiData(npc); if (null != data) { CharacterInfo target = AiLogicUtility.GetSeeingLivingCharacterInfoHelper(npc, info.Target); if (null != target) { float dist = (float)npc.GetActualProperty().AttackRange; float distGoHome = (float)npc.GohomeRange; Vector3 targetPos = target.GetMovementStateInfo().GetPosition3D(); ScriptRuntime.Vector3 srcPos = npc.GetMovementStateInfo().GetPosition3D(); float powDist = Geometry.DistanceSquare(srcPos, targetPos); float powDistToHome = Geometry.DistanceSquare(srcPos, info.HomePos); if (powDist < dist * dist)//进入攻击状态 { npc.GetMovementStateInfo().IsMoving = false; NotifyNpcMove(npc); info.Time = 0; data.Time = 0; ChangeToState(npc, (int)AiStateId.Combat); } else if (powDistToHome < distGoHome * distGoHome)//追击 { info.Time += deltaTime; if (info.Time > 100) { info.Time = 0; if (AiLogicUtility.GetWalkablePosition(target, npc, ref targetPos)) { AiLogicUtility.PathToTarget(npc, data.FoundPath, targetPos, 100, true, this); } else { npc.GetMovementStateInfo().IsMoving = false; NotifyNpcMove(npc); } } } else { toIdle = true; } } else { toIdle = true; } if (toIdle) { npc.GetMovementStateInfo().IsMoving = false; NotifyNpcMove(npc); info.Time = 0; ChangeToState(npc, (int)AiStateId.Idle); } } }
private void CombatHandler(NpcInfo npc, AiCommandDispatcher aiCmdDispatcher, long deltaTime) { if (npc.IsDead()) { return; } NpcAiStateInfo info = npc.GetAiStateInfo(); info.Time += deltaTime; float rps = npc.GetActualProperty().Rps; if (rps > 0.001f && info.Time > 1000 / rps) { info.Time = 0; AiData_PveNpc_General data = GetAiData(npc); if (null != data) { bool goHome = false; CharacterInfo target = AiLogicUtility.GetSeeingLivingCharacterInfoHelper(npc, info.Target); if (null != target) { float dist = (float)npc.GetActualProperty().AttackRange; float distGoHome = (float)npc.GohomeRange; ScriptRuntime.Vector3 targetPos = target.GetMovementStateInfo().GetPosition3D(); ScriptRuntime.Vector3 srcPos = npc.GetMovementStateInfo().GetPosition3D(); float powDist = Geometry.DistanceSquare(srcPos, targetPos); float powDistToHome = Geometry.DistanceSquare(srcPos, info.HomePos); if (powDist < dist * dist) { float dir = Geometry.GetYAngle(new Vector2(srcPos.X, srcPos.Z), new Vector2(targetPos.X, targetPos.Z)); npc.GetMovementStateInfo().SetFaceDir(dir); npc.GetMovementStateInfo().SetMoveDir(dir); if (npc.CanShoot() && !npc.GetSkillStateInfo().IsSkillActivated()) { Data_NpcConfig npcConfig = NpcConfigProvider.Instance.GetNpcConfigById(npc.GetLinkId()); if (null == npcConfig) { return; } if (npcConfig.m_SkillList.Count >= 1) { ServerNpcSkill(npc, npcConfig.m_SkillList[0], target, targetPos, dir); } } } else if (powDistToHome < distGoHome * distGoHome) { npc.GetMovementStateInfo().IsMoving = false; NotifyNpcMove(npc); info.Time = 0; data.FoundPath.Clear(); ChangeToState(npc, (int)AiStateId.Pursuit); } else { goHome = true; } } else { goHome = true; } if (goHome) { npc.GetMovementStateInfo().IsMoving = false; NotifyNpcMove(npc); info.Time = 0; ChangeToState(npc, (int)AiStateId.GoHome); } } } }
private void TickNpcs() { List <NpcInfo> deletes = new List <NpcInfo>(); for (LinkedListNode <NpcInfo> linkNode = m_NpcMgr.Npcs.FirstValue; null != linkNode; linkNode = linkNode.Next) { NpcInfo info = linkNode.Value; if (info.LevelChanged || info.GetShootStateInfo().WeaponChanged || info.GetSkillStateInfo().BuffChanged || info.GetEquipmentStateInfo().EquipmentChanged) { NpcAttrCalculator.Calc(info); info.LevelChanged = false; info.GetShootStateInfo().WeaponChanged = false; info.GetSkillStateInfo().BuffChanged = false; info.GetEquipmentStateInfo().EquipmentChanged = false; } // 约定npc的高度低于140时,直接判定npc死亡。 if (140.0f > info.GetMovementStateInfo().GetPosition3D().Y) { info.SetHp(Operate_Type.OT_Absolute, 0); } if (info.NeedDelete) { deletes.Add(info); } else if (info.Hp <= 0) { if (!info.LogicDead) { GfxSystem.PublishGfxEvent("ge_on_npc_dead", "story", info.GetUnitId()); info.LogicDead = true; } if (info.DeadTime <= 0) { } else if (TimeUtility.GetServerMilliseconds() - info.DeadTime > info.ReleaseTime) { deletes.Add(info); } } if (info.IsBorning && IsNpcBornOver(info)) { info.IsBorning = false; info.SetAIEnable(true); info.SetStateFlag(Operate_Type.OT_RemoveBit, CharacterState_Type.CST_Invincible); } } if (deletes.Count > 0) { foreach (NpcInfo ni in deletes) { CharacterView view = EntityManager.Instance.GetCharacterViewById(ni.GetId()); if (null != view) { GfxSystem.SendMessage(view.Actor, "OnDead", null); } EntityManager.Instance.DestroyNpcView(ni.GetId()); WorldSystem.Instance.DestroyCharacterById(ni.GetId()); return; } } }
private void TickNpcs() { List <NpcInfo> deletes = new List <NpcInfo>(); List <NpcInfo> deletes2 = new List <NpcInfo>(); Msg_RC_NpcDead npcDeadBuilder = new Msg_RC_NpcDead(); for (LinkedListNode <NpcInfo> linkNode = NpcManager.Npcs.FirstValue; null != linkNode; linkNode = linkNode.Next) { NpcInfo info = linkNode.Value; if (info.LevelChanged || info.GetSkillStateInfo().BuffChanged || info.GetEquipmentStateInfo().EquipmentChanged || info.GetLegacyStateInfo().LegacyChanged) { NpcAttrCalculator.Calc(info); info.LevelChanged = false; info.GetSkillStateInfo().BuffChanged = false; info.GetEquipmentStateInfo().EquipmentChanged = false; info.GetLegacyStateInfo().LegacyChanged = false; } // 伙伴自动掉血 if ((int)NpcTypeEnum.Partner == info.NpcType) { UserInfo owner = UserManager.GetUserInfo(info.OwnerId); if (null != owner) { PartnerInfo pi = owner.GetPartnerInfo(); if (null != pi && TimeUtility.GetServerMilliseconds() - pi.LastTickTime > pi.TickInterval) { info.SetHp(Operate_Type.OT_Relative, (int)pi.GetHpCostPerTick(info.GetActualProperty().HpMax)); pi.LastTickTime = TimeUtility.GetServerMilliseconds(); } } } if (info.NeedDelete) { deletes2.Add(info); } else if (info.IsDead()) { if (info.DeadTime <= 0) { info.DeadTime = TimeUtility.GetServerMilliseconds(); //击杀收益计算 CalcKillIncome(info); //解除控制 ReleaseControl(info); //发送npc死亡消息 npcDeadBuilder.npc_id = info.GetId(); NotifyAllUser(npcDeadBuilder); if (info.IsCombatNpc()) { m_StorySystem.SendMessage("objkilled", info.GetId(), GetBattleNpcCount()); m_StorySystem.SendMessage(string.Format("npckilled:{0}", info.GetUnitId()), info.GetId(), GetBattleNpcCount()); if (info.GetUnitId() > 0) { if (m_IsAttemptScene) { if ((int)NpcTypeEnum.BigBoss == info.NpcType) { TryFireAllNpcKilled(); } } else { TryFireAllNpcKilled(); } } } } else if (TimeUtility.GetServerMilliseconds() - info.DeadTime > info.ReleaseTime && info.GfxDead) { deletes.Add(info); } } if (info.IsBorning && IsNpcBornOver(info)) { info.IsBorning = false; info.SetAIEnable(true); info.SetStateFlag(Operate_Type.OT_RemoveBit, CharacterState_Type.CST_Invincible); } CheckNpcOwnerId(info); } if (deletes.Count > 0) { Msg_RC_DestroyNpc destroyNpcBuilder = new Msg_RC_DestroyNpc(); foreach (NpcInfo ni in deletes) { //发送npc消失消息 destroyNpcBuilder.npc_id = ni.GetId(); destroyNpcBuilder.need_play_effect = true; NotifyAllUser(destroyNpcBuilder); //删除npc NpcManager.RemoveNpc(ni.GetId()); LogSystem.Debug("Npc {0} name {1} is deleted.", ni.GetId(), ni.GetName()); } } if (deletes2.Count > 0) { Msg_RC_DestroyNpc destroyNpcBuilder = new Msg_RC_DestroyNpc(); foreach (NpcInfo ni in deletes2) { //发送npc消失消息 destroyNpcBuilder.npc_id = ni.GetId(); destroyNpcBuilder.need_play_effect = false; NotifyAllUser(destroyNpcBuilder); //删除npc NpcManager.RemoveNpc(ni.GetId()); LogSystem.Debug("Npc {0} name {1} is deleted.", ni.GetId(), ni.GetName()); } } NpcManager.ExecuteDelayAdd(); }
private void PursuitHandler(NpcInfo npc, AiCommandDispatcher aiCmdDispatcher, long deltaTime) { if (npc.IsDead() || npc.GetSkillStateInfo().IsSkillActivated()) { return; } NpcAiStateInfo info = npc.GetAiStateInfo(); bool goHome = false; AiData_PveNpc_Monster_CloseCombat data = GetAiData(npc); if (null != data) { CharacterInfo target = AiLogicUtility.GetSeeingLivingCharacterInfoHelper(npc, info.Target); if (null != target) { float dist = (float)npc.GetActualProperty().AttackRange; float distGoHome = (float)npc.GohomeRange; Vector3 targetPos = target.GetMovementStateInfo().GetPosition3D(); ScriptRuntime.Vector3 srcPos = npc.GetMovementStateInfo().GetPosition3D(); float powDist = Geometry.DistanceSquare(srcPos, targetPos); float powDistToHome = Geometry.DistanceSquare(srcPos, info.HomePos); if (powDist < dist * dist)//进入移动攻击状态 { if (null != npc.GetSkillStateInfo().GetImpactInfoById(data.PreAttackImpact)) { ServerNpcStopImpact(npc, data.PreAttackImpact); } info.Time = 0; data.FoundPath.Clear(); data.Time = (long)(1000.0f / npc.GetActualProperty().Rps); ChangeToState(npc, (int)AiStateId.Combat); } else if (powDist < data.PreAttackDistance * data.PreAttackDistance) //预热状态 { if (null == npc.GetSkillStateInfo().GetImpactInfoById(data.FastMoveImpact)) { ServerNpcImpact(npc, data.FastMoveImpact, npc); } if (null == npc.GetSkillStateInfo().GetImpactInfoById(data.PreAttackImpact)) { ServerNpcImpact(npc, data.PreAttackImpact, npc); } info.Time += deltaTime; if (info.Time > 100) { info.Time = 0; if (AiLogicUtility.GetWalkablePosition(target, npc, ref targetPos)) { AiLogicUtility.PathToTarget(npc, data.FoundPath, targetPos, 100, true, this); } else { npc.GetMovementStateInfo().IsMoving = false; NotifyNpcMove(npc); } } } else if (powDistToHome < distGoHome * distGoHome)//追击 { if (data.TestFlag != 3) { data.TestFlag = 3; } if (null != npc.GetSkillStateInfo().GetImpactInfoById(data.FastMoveImpact)) { ServerNpcStopImpact(npc, data.FastMoveImpact); } if (null != npc.GetSkillStateInfo().GetImpactInfoById(data.PreAttackImpact)) { ServerNpcStopImpact(npc, data.PreAttackImpact); } info.Time += deltaTime; if (info.Time > 100) { info.Time = 0; if (AiLogicUtility.GetWalkablePosition(target, npc, ref targetPos)) { AiLogicUtility.PathToTarget(npc, data.FoundPath, targetPos, 100, true, this); } else { npc.GetMovementStateInfo().IsMoving = false; NotifyNpcMove(npc); } } } else { goHome = true; } } else { goHome = true; } if (goHome) { npc.GetMovementStateInfo().IsMoving = false; NotifyNpcMove(npc); info.Time = 0; ChangeToState(npc, (int)AiStateId.GoHome); } } }