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; bool toIdle = false; CharacterInfo target = AiLogicUtility.GetSeeingLivingCharacterInfoHelper(npc, info.Target); if (null != target && npc.SpatialSystem.CanShoot(npc.SpaceObject, target.GetMovementStateInfo().GetPosition3D())) { ScriptRuntime.Vector3 targetPos = target.GetMovementStateInfo().GetPosition3D(); ScriptRuntime.Vector3 srcPos = npc.GetMovementStateInfo().GetPosition3D(); float powDist = Geometry.DistanceSquare(srcPos, targetPos); float dist = (float)npc.GetActualProperty().AttackRange; float distView = (float)npc.ViewRange; if (powDist < dist * dist) { npc.GetMovementStateInfo().IsMoving = false; } else if (powDist < distView * distView) { npc.GetMovementStateInfo().IsMoving = false; } else { toIdle = true; } } else { toIdle = true; } if (toIdle) { info.Time = 0; npc.GetMovementStateInfo().IsMoving = false; ChangeToState(npc, (int)AiStateId.Idle); } } }
private static void MoveToNext(NpcInfo npc, AiData_ForMoveCommand data) { if (++data.Index >= data.WayPoints.Count) { data.IsFinish = true; return; } var move_info = npc.GetMovementStateInfo(); Vector3 from = move_info.GetPosition3D(); Vector3 to = data.WayPoints[data.Index]; float move_dir = MoveDirection(from, to); float now = TimeUtility.GetServerMilliseconds(); float distance = Geometry.Distance(from, to); float speed = npc.GetActualProperty().MoveSpeed; data.EstimateFinishTime = now + 1000 * (distance / speed); DLog._("ai_move", "[{0}]: now({1}), from({2}), to({3}), distance({4}), speed({5}), move_time({6}), estimate({7})", npc.GetId(), now, from.ToString(), to.ToString(), distance, speed, 1000 * (distance / speed), data.EstimateFinishTime); move_info.IsMoving = true; move_info.SetMoveDir(move_dir); move_info.SetFaceDir(move_dir); }
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); } } } }
internal static Msg_RC_NpcMove BuildNpcMoveMessage(NpcInfo npc) { Msg_RC_NpcMove npcMoveBuilder = new Msg_RC_NpcMove(); if (npc.GetMovementStateInfo().IsMoving) { npcMoveBuilder.npc_id = npc.GetId(); npcMoveBuilder.is_moving = true; npcMoveBuilder.move_direction = (float)npc.GetMovementStateInfo().GetMoveDir(); npcMoveBuilder.face_direction = (float)npc.GetMovementStateInfo().GetFaceDir(); npcMoveBuilder.cur_pos_x = npc.GetMovementStateInfo().GetPosition3D().X; npcMoveBuilder.cur_pos_z = npc.GetMovementStateInfo().GetPosition3D().Z; NpcAiStateInfo data = npc.GetAiStateInfo(); npcMoveBuilder.target_pos_x = npc.GetMovementStateInfo().TargetPosition.X; npcMoveBuilder.target_pos_z = npc.GetMovementStateInfo().TargetPosition.Z; npcMoveBuilder.velocity_coefficient = (float)npc.VelocityCoefficient; npcMoveBuilder.velocity = npc.GetActualProperty().MoveSpeed; npcMoveBuilder.move_mode = (int)npc.GetMovementStateInfo().MovementMode; } else { npcMoveBuilder.npc_id = npc.GetId(); npcMoveBuilder.is_moving = false; npcMoveBuilder.cur_pos_x = npc.GetMovementStateInfo().GetPosition3D().X; npcMoveBuilder.cur_pos_z = npc.GetMovementStateInfo().GetPosition3D().Z; } return(npcMoveBuilder); }
private void PursuitHandler(NpcInfo npc, AiCommandDispatcher aiCmdDispatcher, long deltaTime) { if (npc.IsDead()) { return; } NpcAiStateInfo info = npc.GetAiStateInfo(); bool goHome = false; AiData_PveNpc_General data = GetAiData(npc); if (null != data) { CharacterInfo target = AiLogicUtility.GetLivingCharacterInfoHelper(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; info.Time = 0; data.Time = 0; ChangeToState(npc, (int)AiStateId.Combat); NotifyNpcMove(npc); } else if (true) // 目标存活的情况下屏蔽掉gohome。 { info.Time += deltaTime; if (info.Time > m_IntervalTime) { info.Time = 0; AiLogicUtility.PathToTargetWithoutObstacle(npc, data.FoundPath, targetPos, m_IntervalTime, true, this); } } else { goHome = true; } } else { goHome = true; } if (goHome) { npc.GetMovementStateInfo().IsMoving = false; NotifyNpcMove(npc); info.Time = 0; data.Time = 0; ChangeToState(npc, (int)AiStateId.GoHome); } } }
protected override void OnStateLogicInit(NpcInfo npc, AiCommandDispatcher aiCmdDispatcher, long deltaTime) { NpcAiStateInfo info = npc.GetAiStateInfo(); info.Time = 0; npc.GetMovementStateInfo().IsMoving = false; info.HomePos = npc.GetMovementStateInfo().GetPosition3D(); info.Target = 0; if (!string.IsNullOrEmpty(info.AiParam[0])) { if (int.Parse(info.AiParam[0]) == 0) { InitPatrolData(npc); } else if (int.Parse(info.AiParam[0]) == 1) { InitIdleAnim(npc); } } npc.GetActualProperty().SetMoveSpeed(Operate_Type.OT_Absolute, GetWalkSpeed(npc)); npc.GetMovementStateInfo().MovementMode = MovementMode.LowSpeed; }
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 CombatHandler(NpcInfo npc, AiCommandDispatcher aiCmdDispatcher, long deltaTime) { if (npc.IsDead()) { return; } NpcAiStateInfo info = npc.GetAiStateInfo(); info.Time += deltaTime; if (info.Time > 100) { AiData_PveNpc_Monster data = GetAiData(npc); if (null != data) { data.Time += info.Time; info.Time = 0; 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); float dir = Geometry.GetYAngle(new Vector2(srcPos.X, srcPos.Z), new Vector2(targetPos.X, targetPos.Z)); npc.GetMovementStateInfo().SetFaceDir(dir); if (powDist < data.ShootDistance * data.ShootDistance) { float rps = npc.GetActualProperty().Rps; if (rps > 0.001f && data.Time > 1000 / rps) { data.Time = 0; } npc.GetMovementStateInfo().IsMoving = false; NotifyNpcMove(npc); goHome = true; } else if (powDist < dist * dist /*&& SkillSystem.Instance.CanStartSkill(npc, data.Skill)*/) { ServerNpcSkill(npc, data.Skill, target, targetPos, dir); npc.GetMovementStateInfo().IsMoving = false; NotifyNpcMove(npc); goHome = true; } 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 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; CheckImpact(npc); bool toIdle = false; //修改确定攻击目标的逻辑 CharacterInfo target = AiLogicUtility.GetSeeingLivingCharacterInfoHelper(npc, info.Target); if (null != target && npc.SpatialSystem.CanShoot(npc.SpaceObject, target.GetMovementStateInfo().GetPosition3D())) { ScriptRuntime.Vector3 targetPos = target.GetMovementStateInfo().GetPosition3D(); ScriptRuntime.Vector3 srcPos = npc.GetMovementStateInfo().GetPosition3D(); float powDist = Geometry.DistanceSquare(srcPos, targetPos); //npc与目标距离 float dist = (float)npc.GetActualProperty().AttackRange; //攻击范围 //float distView = (float)npc.ViewRange; //视野范围 if (powDist < dist * dist) { //在攻击范围内 float dir = Geometry.GetYAngle(new Vector2(srcPos.X, srcPos.Z), new Vector2(targetPos.X, targetPos.Z)); npc.GetMovementStateInfo().IsMoving = false; npc.GetMovementStateInfo().SetFaceDir(dir); npc.GetMovementStateInfo().SetMoveDir(dir); if (npc.CanShoot()) { aiCmdDispatcher.NpcFace(npc, this); } } else { //如果原目标已经超出了攻击范围,防御塔应当重新进行探测,而不是跳转到Idle状态 CharacterInfo newTarget = GetNewTarget(npc); if (null != newTarget) { npc.GetMovementStateInfo().IsMoving = false; info.Time = 0; info.Target = newTarget.GetId(); } else { toIdle = true; } } } else { //如果原目标死亡或不可攻击,防御塔应当首先重新进行探测,而不是跳转到Idle状态 //若找到新目标,则进行攻击 //若没有心目标。则进入Idle状态 CharacterInfo newTarget = GetNewTarget(npc); if (null != newTarget) { npc.GetMovementStateInfo().IsMoving = false; info.Time = 0; info.Target = newTarget.GetId(); } else { toIdle = true; } } if (toIdle) { info.Time = 0; npc.GetMovementStateInfo().IsMoving = false; 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; if (info.Time > 100) { AiData_PvpNpc_General data = GetAiData(npc); if (null != data) { data.Time += info.Time; data.ThinkingTime += info.Time; //ai配置参数 小兵思考时间 long thinkingTime = int.Parse(info.AiParam[2]); //大于思考时间 重新选择新的目标 if (data.ThinkingTime > thinkingTime) { CharacterInfo interestestTarget = GetInterestestTargetHelper(npc, CharacterRelation.RELATION_ENEMY); if (null != interestestTarget && info.Target != interestestTarget.GetId()) { npc.GetMovementStateInfo().IsMoving = false; NotifyNpcMove(npc); info.Time = 0; data.Time = 0; data.ThinkingTime = 0; info.Target = interestestTarget.GetId(); return; } } info.Time = 0; bool changeTarget = false; CharacterInfo target = AiLogicUtility.GetSeeingLivingCharacterInfoHelper(npc, info.Target); if (null != target) { float dist = (float)(npc.GetActualProperty().AttackRange *npc.AttackRangeCoefficient); 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 && npc.SpatialSystem.CanShoot(npc.SpaceObject, target.GetMovementStateInfo().GetPosition3D())) { float rps = npc.GetActualProperty().Rps; if (rps > 0.001f && data.Time > 1000 / rps) { data.Time = 0; 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()) { aiCmdDispatcher.NpcFace(npc, this); } } } else if (powDistToHome < distGoHome * distGoHome) { npc.GetMovementStateInfo().IsMoving = false; NotifyNpcMove(npc); info.Time = 0; data.FoundPath.Clear(); ChangeToState(npc, (int)AiStateId.Pursuit); } else { changeTarget = true; } } else { changeTarget = true; } if (changeTarget) { data.FoundPath.Clear(); target = GetInterestestTargetHelper(npc, CharacterRelation.RELATION_ENEMY); if (null != target) { npc.GetMovementStateInfo().IsMoving = false; NotifyNpcMove(npc); info.Time = 0; info.Target = target.GetId(); ChangeToState(npc, (int)AiStateId.Pursuit); } else { npc.GetMovementStateInfo().IsMoving = false; NotifyNpcMove(npc); info.Time = 0; info.HomePos = GetHomePosition(npc, data); ChangeToState(npc, (int)AiStateId.GoHome); } } } else { info.Time = 0; } } }
private void TickRecover() { float hp_coefficient = 1.0f; float mp_coefficient = 1.0f; Data_SceneConfig scene_data = SceneConfigProvider.Instance.GetSceneConfigById(m_SceneResId); if (null != scene_data) { hp_coefficient = scene_data.m_RecoverHpCoefficient; mp_coefficient = scene_data.m_RecoverMpCoefficient; } for (LinkedListNode <UserInfo> linkNode = UserManager.Users.FirstValue; null != linkNode; linkNode = linkNode.Next) { UserInfo info = linkNode.Value; if (!info.IsDead()) { float hpRecover = info.GetActualProperty().HpRecover *hp_coefficient; float epRecover = info.GetActualProperty().EnergyRecover *mp_coefficient; if (hpRecover > 0.0001) { if (info.Hp + (int)hpRecover >= info.GetActualProperty().HpMax) { info.SetHp(Operate_Type.OT_Absolute, (int)info.GetActualProperty().HpMax); } else { info.SetHp(Operate_Type.OT_Relative, (int)hpRecover); } } if (epRecover > 0.0001) { if (info.Energy + (int)epRecover >= info.GetActualProperty().EnergyMax) { info.SetEnergy(Operate_Type.OT_Absolute, (int)info.GetActualProperty().EnergyMax); } else { info.SetEnergy(Operate_Type.OT_Relative, (int)epRecover); } } if (hpRecover > 0.0001 || epRecover > 0.0001) { Msg_RC_SyncProperty builder = DataSyncUtility.BuildSyncPropertyMessage(info); NotifyAreaUser(info, builder, false); } } } for (LinkedListNode <NpcInfo> linkNode = NpcManager.Npcs.FirstValue; null != linkNode; linkNode = linkNode.Next) { NpcInfo info = linkNode.Value; if (!info.IsDead()) { float hpRecover = info.GetActualProperty().HpRecover; float npRecover = info.GetActualProperty().EnergyRecover; if (hpRecover > 0.0001) { if (info.Hp + (int)hpRecover >= info.GetActualProperty().HpMax) { info.SetHp(Operate_Type.OT_Absolute, (int)info.GetActualProperty().HpMax); } else { info.SetHp(Operate_Type.OT_Relative, (int)hpRecover); } } if (npRecover > 0.0001) { if (info.Energy + (int)npRecover >= info.GetActualProperty().EnergyMax) { info.SetEnergy(Operate_Type.OT_Absolute, (int)info.GetActualProperty().EnergyMax); } else { info.SetEnergy(Operate_Type.OT_Relative, (int)npRecover); } } if (hpRecover > 0.0001 || npRecover > 0.0001) { Msg_RC_SyncProperty builder = DataSyncUtility.BuildSyncPropertyMessage(info); NotifyAreaUser(info, builder, false); } } } }
private void PathToTargetWithoutObstacle(NpcInfo npc, AiPathData data, Vector3 pathTargetPos, long deltaTime) { NpcAiStateInfo info = npc.GetAiStateInfo(); if (null != data) { data.UpdateTime += deltaTime; ScriptRuntime.Vector3 srcPos = npc.GetMovementStateInfo().GetPosition3D(); float dir = npc.GetMovementStateInfo().GetMoveDir(); bool findObstacle = false; bool havePathPoint = data.HavePathPoint; if (havePathPoint)//沿路点列表移动的逻辑 { Vector3 targetPos = data.CurPathPoint; if (!data.IsReached(srcPos))//向指定路点移动(避让移动过程) { float angle = Geometry.GetYAngle(new Vector2(srcPos.X, srcPos.Z), new Vector2(targetPos.X, targetPos.Z)); Vector3 prefVelocity = (float)npc.GetActualProperty().MoveSpeed *new Vector3((float)Math.Sin(angle), 0, (float)Math.Cos(angle)); Vector3 v = new Vector3(targetPos.X - srcPos.X, 0, targetPos.Z - srcPos.Z); v.Normalize(); Vector3 velocity = npc.SpaceObject.GetVelocity(); float speedSquare = (float)npc.GetActualProperty().MoveSpeed *(float)npc.GetActualProperty().MoveSpeed; long stTime = TimeUtility.GetElapsedTimeUs(); Vector3 newVelocity = npc.SpatialSystem.ComputeVelocity(npc.SpaceObject, v, (float)deltaTime / 1000, (float)npc.GetActualProperty().MoveSpeed, (float)npc.GetRadius(), data.IsUsingAvoidanceVelocity); long endTime = TimeUtility.GetElapsedTimeUs(); long calcTime = endTime - stTime; if (calcTime > 10000) { LogSystem.Warn("*** pvp ComputeVelocity consume {0} us,npc:{1} velocity:{2} newVelocity:{3} deltaTime:{4} speed:{5} pos:{6}", calcTime, npc.GetId(), velocity.ToString(), newVelocity.ToString(), deltaTime, npc.GetActualProperty().MoveSpeed, npc.GetMovementStateInfo().GetPosition3D().ToString()); for (LinkedListNode <UserInfo> node = npc.UserManager.Users.FirstValue; null != node; node = node.Next) { UserInfo userInfo = node.Value; if (null != userInfo) { LogSystem.Warn("===>User:{0} Pos:{1}", userInfo.GetId(), userInfo.GetMovementStateInfo().GetPosition3D().ToString()); } } for (LinkedListNode <NpcInfo> node = npc.NpcManager.Npcs.FirstValue; null != node; node = node.Next) { NpcInfo npcInfo = node.Value; if (null != npcInfo) { LogSystem.Warn("===>Npc:{0} Pos:{1}", npcInfo.GetId(), npcInfo.GetMovementStateInfo().GetPosition3D().ToString()); } } } if (findObstacle)//当前移动方向遇到阻挡,停止移动,触发寻路 { npc.GetMovementStateInfo().IsMoving = false; NotifyNpcMove(npc); data.IsUsingAvoidanceVelocity = false; } else if (!npc.GetMovementStateInfo().IsMoving&& velocity.LengthSquared() > speedSquare * 0.25f)//正常移动过程,继续移动 { velocity.Normalize(); npc.GetMovementStateInfo().TargetPosition = srcPos + velocity * Geometry.Distance(srcPos, targetPos); npc.GetMovementStateInfo().IsMoving = true; NotifyNpcMove(npc); data.IsUsingAvoidanceVelocity = false; } } else//改变路点或结束沿路点移动 { data.UseNextPathPoint(); if (data.HavePathPoint) { targetPos = data.CurPathPoint; npc.GetMovementStateInfo().TargetPosition = targetPos; float angle = Geometry.GetYAngle(new Vector2(srcPos.X, srcPos.Z), new Vector2(targetPos.X, targetPos.Z)); npc.GetMovementStateInfo().SetFaceDir(angle); npc.GetMovementStateInfo().SetMoveDir(angle); npc.GetMovementStateInfo().IsMoving = true; NotifyNpcMove(npc); data.IsUsingAvoidanceVelocity = false; } else { data.Clear(); } } } if (!havePathPoint || findObstacle)//获得路点过程(寻路) { data.Clear(); Vector3 targetPos = pathTargetPos; bool canGo = true; if (canGo) { List <Vector3> posList = null; bool canPass = npc.SpatialSystem.CanPass(npc.SpaceObject, targetPos); if (canPass) { posList = new List <Vector3>(); posList.Add(srcPos); posList.Add(targetPos); } else { long stTime = TimeUtility.GetElapsedTimeUs(); posList = npc.SpatialSystem.FindPath(srcPos, targetPos, npc.AvoidanceRadius); long endTime = TimeUtility.GetElapsedTimeUs(); long calcTime = endTime - stTime; if (calcTime > 10000) { LogSystem.Warn("*** pvp FindPath consume {0} us,npc:{1} from:{2} to:{3} radius:{4} pos:{5}", calcTime, npc.GetId(), srcPos.ToString(), targetPos.ToString(), npc.AvoidanceRadius, npc.GetMovementStateInfo().GetPosition3D().ToString()); } } if (posList.Count >= 2) { data.SetPathPoints(posList[0], posList, 1); targetPos = data.CurPathPoint; npc.GetMovementStateInfo().TargetPosition = targetPos; float angle = Geometry.GetYAngle(new Vector2(srcPos.X, srcPos.Z), new Vector2(targetPos.X, targetPos.Z)); npc.GetMovementStateInfo().SetFaceDir(angle); npc.GetMovementStateInfo().SetMoveDir(angle); npc.GetMovementStateInfo().IsMoving = true; NotifyNpcMove(npc); data.IsUsingAvoidanceVelocity = false; } else { npc.GetMovementStateInfo().IsMoving = false; NotifyNpcMove(npc); data.IsUsingAvoidanceVelocity = false; } } else { npc.GetMovementStateInfo().IsMoving = false; NotifyNpcMove(npc); data.IsUsingAvoidanceVelocity = false; } } } }
private void CombatHandler(NpcInfo npc, AiCommandDispatcher aiCmdDispatcher, long deltaTime) { if (npc.IsDead()) { return; } NpcAiStateInfo info = npc.GetAiStateInfo(); info.Time += deltaTime; if (info.Time > m_IntervalTime) { AiData_Demo_Melee data = GetAiData(npc); if (null != data) { data.Time += info.Time; info.Time = 0; bool goHome = false; CharacterInfo target = AiLogicUtility.GetLivingCharacterInfoHelper(npc, info.Target); //CharacterInfo target = AiLogicUtility.GetInterestestTargetHelper(npc, CharacterRelation.RELATION_ENEMY, AiTargetType.USER); 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 rps = npc.GetActualProperty().Rps; if (rps > 0.001f && data.Time > 1000 / rps) { data.Time = 0; float dir = Geometry.GetYAngle(new Vector2(srcPos.X, srcPos.Z), new Vector2(targetPos.X, targetPos.Z)); NotifyNpcFace(npc, dir); //npc.GetMovementStateInfo().SetMoveDir(dir); if (powDist < (npc.ViewRange - 1.0f) * (npc.ViewRange - 1.0f)) { if (0 == data.SkillToCast) { data.SkillToCast = GetNextSkill(); } if (null != OnNpcSkill) { float angle = Geometry.GetYAngle(new Vector2(srcPos.X, srcPos.Z), new Vector2(targetPos.X, targetPos.Z)); if (Geometry.IsSameDouble(angle, npc.GetMovementStateInfo().GetFaceDir())) { OnNpcSkill(npc, data.SkillToCast, target); data.SkillToCast = 0; } } } } } else { npc.GetMovementStateInfo().IsMoving = false; NotifyNpcMove(npc); info.Time = 0; data.FoundPath.Clear(); data.SkillToCast = 0; ChangeToState(npc, (int)AiStateId.Pursuit); } } else { goHome = true; } if (goHome) { npc.GetMovementStateInfo().IsMoving = false; NotifyNpcMove(npc); info.Time = 0; ChangeToState(npc, (int)AiStateId.GoHome); } } else { info.Time = 0; } } }
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()) { return; } NpcAiStateInfo info = npc.GetAiStateInfo(); //ai配置参数 long maxPursuitTime = int.Parse(info.AiParam[0]); long minPursuitTime = int.Parse(info.AiParam[1]); // bool goHome = false; info.Time += deltaTime; CharacterInfo target = AiLogicUtility.GetSeeingLivingCharacterInfoHelper(npc, info.Target); AiData_PvpNpc_General data = GetAiData(npc); if (null != target && info.Time <= maxPursuitTime && null != data) { if (info.Time >= minPursuitTime) { //超过最小追击时间,尝试换攻击目标 CharacterInfo interestestTarget = GetInterestestTargetHelper(npc, CharacterRelation.RELATION_ENEMY); if (null != interestestTarget && interestestTarget != target) { info.Time = 0; info.Target = interestestTarget.GetId(); data.FoundPath.Clear(); target = interestestTarget; } } float dist = (float)(npc.GetActualProperty().AttackRange *npc.AttackRangeCoefficient); 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.SpatialSystem.CanShoot(npc.SpaceObject, target.GetMovementStateInfo().GetPosition3D())) { npc.GetMovementStateInfo().IsMoving = false; info.Time = 0; ChangeToState(npc, (int)AiStateId.Combat); NotifyNpcMove(npc); } else if (powDistToHome < distGoHome * distGoHome) { if (AiLogicUtility.GetWalkablePosition(target, npc, ref targetPos)) { PathToTargetWithoutObstacle(npc, data.FoundPath, targetPos, deltaTime); } else { npc.GetMovementStateInfo().IsMoving = false; NotifyNpcMove(npc); } } else { goHome = true; } } else { goHome = true; } if (goHome) { npc.GetMovementStateInfo().IsMoving = false; NotifyNpcMove(npc); info.Time = 0; info.HomePos = GetHomePosition(npc, data); data.FoundPath.Clear(); ChangeToState(npc, (int)AiStateId.GoHome); } }
private void PursuitHandler(NpcInfo npc, AiCommandDispatcher aiCmdDispatcher, long deltaTime) { if (npc.IsDead()) { return; } NpcAiStateInfo info = npc.GetAiStateInfo(); bool goHome = false; AiData_Demo_Melee data = GetAiData(npc); if (null != data) { CharacterInfo target = AiLogicUtility.GetLivingCharacterInfoHelper(npc, info.Target); if (null != target) { if (data.WaitTime <= m_ResponseTime) { if (!data.HasMeetEnemy) { if (null != OnNpcMeetEnemy) { OnNpcMeetEnemy(npc, data.MeetEnemyAnim); } data.HasMeetEnemy = true; } float angle = Geometry.GetYAngle(npc.GetMovementStateInfo().GetPosition2D(), target.GetMovementStateInfo().GetPosition2D()); NotifyNpcFace(npc, angle); data.WaitTime += deltaTime; return; } data.WalkTime += deltaTime; if (data.WalkTime < 4000) { npc.GetActualProperty().SetMoveSpeed(Operate_Type.OT_Absolute, GetWalkSpeed(npc)); npc.GetMovementStateInfo().MovementMode = MovementMode.LowSpeed; } else { npc.GetActualProperty().SetMoveSpeed(Operate_Type.OT_Absolute, GetRunSpeed(npc)); npc.GetMovementStateInfo().MovementMode = MovementMode.HighSpeed; } 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); if (0 == data.SkillToCast) { data.SkillToCast = GetNextSkill(); } if (powDist < (npc.ViewRange - m_TauntDis) * (npc.ViewRange - m_TauntDis)) { if (m_Taunt == data.SkillToCast) { float angle = Geometry.GetYAngle(new Vector2(srcPos.X, srcPos.Z), new Vector2(targetPos.X, targetPos.Z)); if (Geometry.IsSameDouble(angle, npc.GetMovementStateInfo().GetFaceDir())) { OnNpcSkill(npc, data.SkillToCast, target); data.SkillToCast = 0; } } } float powDistToHome = Geometry.DistanceSquare(srcPos, info.HomePos); if (powDist < dist * dist) { npc.GetMovementStateInfo().IsMoving = false; info.Time = 0; data.Time = 0; npc.GetActualProperty().SetMoveSpeed(Operate_Type.OT_Absolute, GetRunSpeed(npc)); npc.GetMovementStateInfo().MovementMode = MovementMode.HighSpeed; ChangeToState(npc, (int)AiStateId.Combat); NotifyNpcMove(npc); } else { info.Time += deltaTime; if (info.Time > m_IntervalTime) { info.Time = 0; AiLogicUtility.PathToTargetWithoutObstacle(npc, data.FoundPath, targetPos, m_IntervalTime, true, this); } } } else { goHome = true; } if (goHome) { npc.GetMovementStateInfo().IsMoving = false; NotifyNpcMove(npc); info.Time = 0; data.Time = 0; npc.GetActualProperty().SetMoveSpeed(Operate_Type.OT_Absolute, 3.5f); ChangeToState(npc, (int)AiStateId.Combat); ChangeToState(npc, (int)AiStateId.GoHome); } } }
public static void PathToTargetWithoutObstacle(NpcInfo npc, AiPathData data, Vector3 pathTargetPos, long deltaTime, bool faceIsMoveFir, AbstractNpcStateLogic logic) { NpcAiStateInfo info = npc.GetAiStateInfo(); Vector3 srcPos = npc.GetMovementStateInfo().GetPosition3D(); if (null != data) { data.Clear(); data.UpdateTime += deltaTime; Vector3 targetPos = pathTargetPos; List <Vector3> posList = null; bool canPass = npc.SpatialSystem.CanPass(npc.SpaceObject, targetPos); if (canPass) { posList = new List <Vector3>(); posList.Add(srcPos); posList.Add(targetPos); } else { long stTime = TimeUtility.GetElapsedTimeUs(); posList = npc.SpatialSystem.FindPath(srcPos, targetPos, npc.AvoidanceRadius); long endTime = TimeUtility.GetElapsedTimeUs(); long calcTime = endTime - stTime; if (calcTime > 10000) { LogSystem.Warn("*** pve FindPath consume {0} us,npc:{1} from:{2} to:{3} radius:{4} pos:{5}", calcTime, npc.GetId(), srcPos.ToString(), targetPos.ToString(), npc.AvoidanceRadius, npc.GetMovementStateInfo().GetPosition3D().ToString()); } } if (posList.Count >= 2) { data.SetPathPoints(posList[0], posList, 1); } else { npc.GetMovementStateInfo().IsMoving = false; logic.NotifyNpcMove(npc); data.IsUsingAvoidanceVelocity = false; } bool havePathPoint = data.HavePathPoint; if (havePathPoint)//沿路点列表移动的逻辑 { targetPos = data.CurPathPoint; if (!data.IsReached(srcPos))//向指定路点移动(避让移动过程) { float angle = Geometry.GetYAngle(new Vector2(srcPos.X, srcPos.Z), new Vector2(targetPos.X, targetPos.Z)); Vector3 prefVelocity = (float)npc.GetActualProperty().MoveSpeed *new Vector3((float)Math.Sin(angle), 0, (float)Math.Cos(angle)); Vector3 v = new Vector3(targetPos.X - srcPos.X, 0, targetPos.Z - srcPos.Z); v.Normalize(); Vector3 velocity = npc.SpaceObject.GetVelocity(); float speedSquare = (float)npc.GetActualProperty().MoveSpeed *(float)npc.GetActualProperty().MoveSpeed; long stTime = TimeUtility.GetElapsedTimeUs(); Vector3 newVelocity = npc.SpatialSystem.ComputeVelocity(npc.SpaceObject, v, (float)deltaTime / 1000, (float)npc.GetActualProperty().MoveSpeed, (float)npc.GetRadius(), data.IsUsingAvoidanceVelocity); long endTime = TimeUtility.GetElapsedTimeUs(); long calcTime = endTime - stTime; if (calcTime > 10000) { LogSystem.Warn("*** pve ComputeVelocity consume {0} us,npc:{1} velocity:{2} newVelocity:{3} deltaTime:{4} speed:{5} pos:{6}", calcTime, npc.GetId(), velocity.ToString(), newVelocity.ToString(), deltaTime, npc.GetActualProperty().MoveSpeed, npc.GetMovementStateInfo().GetPosition3D().ToString()); } if (data.UpdateTime > 500) { data.UpdateTime = 0; float newAngle = Geometry.GetYAngle(new Vector2(0, 0), new Vector2(newVelocity.X, newVelocity.Z)); npc.GetMovementStateInfo().SetMoveDir(newAngle); if (faceIsMoveFir) { logic.NotifyNpcFace(npc, newAngle); } newVelocity.Normalize(); npc.GetMovementStateInfo().TargetPosition = srcPos + newVelocity * Geometry.Distance(srcPos, targetPos); npc.GetMovementStateInfo().IsMoving = true; logic.NotifyNpcMove(npc); } else { data.UpdateTime += deltaTime; } } else//改变路点或结束沿路点移动 { data.UseNextPathPoint(); if (data.HavePathPoint) { targetPos = data.CurPathPoint; npc.GetMovementStateInfo().TargetPosition = targetPos; float angle = Geometry.GetYAngle(new Vector2(srcPos.X, srcPos.Z), new Vector2(targetPos.X, targetPos.Z)); npc.GetMovementStateInfo().SetMoveDir(angle); if (faceIsMoveFir) { logic.NotifyNpcFace(npc, angle); } npc.GetMovementStateInfo().IsMoving = true; logic.NotifyNpcMove(npc); data.IsUsingAvoidanceVelocity = false; } else { npc.GetMovementStateInfo().IsMoving = false; data.Clear(); } } } } }
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); } } }
public static void PathToTarget(NpcInfo npc, AiPathData data, Vector3 pathTargetPos, long deltaTime, bool faceIsMoveFir, AbstractNpcStateLogic logic) { NpcAiStateInfo info = npc.GetAiStateInfo(); if (null != data) { data.UpdateTime += deltaTime; ScriptRuntime.Vector3 srcPos = npc.GetMovementStateInfo().GetPosition3D(); float dir = npc.GetMovementStateInfo().GetMoveDir(); bool findObstacle = false; bool havePathPoint = data.HavePathPoint; if (havePathPoint)//沿路点列表移动的逻辑 { Vector3 targetPos = data.CurPathPoint; if (!data.IsReached(srcPos))//向指定路点移动(避让移动过程) { float angle = Geometry.GetYAngle(new Vector2(srcPos.X, srcPos.Z), new Vector2(targetPos.X, targetPos.Z)); Vector3 prefVelocity = (float)npc.GetActualProperty().MoveSpeed *new Vector3((float)Math.Sin(angle), 0, (float)Math.Cos(angle)); Vector3 v = new Vector3(targetPos.X - srcPos.X, 0, targetPos.Z - srcPos.Z); v.Normalize(); Vector3 velocity = npc.SpaceObject.GetVelocity(); float speedSquare = (float)npc.GetActualProperty().MoveSpeed *(float)npc.GetActualProperty().MoveSpeed; long stTime = TimeUtility.GetElapsedTimeUs(); Vector3 newVelocity = npc.SpatialSystem.ComputeVelocity(npc.SpaceObject, v, (float)deltaTime / 1000, (float)npc.GetActualProperty().MoveSpeed, (float)npc.GetRadius(), data.IsUsingAvoidanceVelocity); findObstacle = !AiLogicUtility.IsWalkable(npc.SpatialSystem.GetCellMapView(npc.AvoidanceRadius), srcPos, newVelocity); long endTime = TimeUtility.GetElapsedTimeUs(); long calcTime = endTime - stTime; if (calcTime > 10000) { LogSystem.Warn("*** pve ComputeVelocity consume {0} us,npc:{1} velocity:{2} newVelocity:{3} deltaTime:{4} speed:{5} pos:{6}", calcTime, npc.GetId(), velocity.ToString(), newVelocity.ToString(), deltaTime, npc.GetActualProperty().MoveSpeed, npc.GetMovementStateInfo().GetPosition3D().ToString()); } if (Geometry.DistanceSquare(newVelocity, new Vector3()) <= speedSquare * 0.25f)//避让计算的移动速度变小(说明没有更好的保持原速的选择,停止) { npc.GetMovementStateInfo().IsMoving = false; logic.NotifyNpcMove(npc); data.IsUsingAvoidanceVelocity = false; } else if (findObstacle)//当前移动方向遇到阻挡,停止移动,触发寻路 { npc.GetMovementStateInfo().IsMoving = false; logic.NotifyNpcMove(npc); data.IsUsingAvoidanceVelocity = false; } else if (data.UpdateTime > 1000)//避让速度改变每秒一次(表现上更像人类一些) { data.UpdateTime = 0; float newAngle = Geometry.GetYAngle(new Vector2(0, 0), new Vector2(newVelocity.X, newVelocity.Z)); npc.GetMovementStateInfo().SetMoveDir(newAngle); if (faceIsMoveFir) { npc.GetMovementStateInfo().SetFaceDir(newAngle); } newVelocity.Normalize(); npc.GetMovementStateInfo().TargetPosition = srcPos + newVelocity * Geometry.Distance(srcPos, targetPos); npc.GetMovementStateInfo().IsMoving = true; logic.NotifyNpcMove(npc); data.IsUsingAvoidanceVelocity = true; } else if (Geometry.DistanceSquare(velocity, newVelocity) > 9.0f) //没有到速度改变周期,但避让方向需要大幅调整 { if (Geometry.Dot(newVelocity, prefVelocity) > 0) //如果是调整为与目标方向一致,则进行调整 { float newAngle = Geometry.GetYAngle(new Vector2(0, 0), new Vector2(newVelocity.X, newVelocity.Z)); npc.GetMovementStateInfo().SetMoveDir(newAngle); if (faceIsMoveFir) { npc.GetMovementStateInfo().SetFaceDir(newAngle); } newVelocity.Normalize(); npc.GetMovementStateInfo().TargetPosition = srcPos + newVelocity * Geometry.Distance(srcPos, targetPos); npc.GetMovementStateInfo().IsMoving = true; logic.NotifyNpcMove(npc); data.IsUsingAvoidanceVelocity = true; } else//如果调整为远离目标方向,则停止 { npc.GetMovementStateInfo().IsMoving = false; logic.NotifyNpcMove(npc); data.IsUsingAvoidanceVelocity = false; } } else if (!npc.GetMovementStateInfo().IsMoving&& velocity.LengthSquared() > speedSquare * 0.25f)//正常移动过程,继续移动 { velocity.Normalize(); npc.GetMovementStateInfo().TargetPosition = srcPos + velocity * Geometry.Distance(srcPos, targetPos); npc.GetMovementStateInfo().IsMoving = true; logic.NotifyNpcMove(npc); data.IsUsingAvoidanceVelocity = false; } } else//改变路点或结束沿路点移动 { data.UseNextPathPoint(); if (data.HavePathPoint) { targetPos = data.CurPathPoint; npc.GetMovementStateInfo().TargetPosition = targetPos; float angle = Geometry.GetYAngle(new Vector2(srcPos.X, srcPos.Z), new Vector2(targetPos.X, targetPos.Z)); npc.GetMovementStateInfo().SetMoveDir(angle); if (faceIsMoveFir) { npc.GetMovementStateInfo().SetFaceDir(angle); } npc.GetMovementStateInfo().IsMoving = true; logic.NotifyNpcMove(npc); data.IsUsingAvoidanceVelocity = false; } else { data.Clear(); } } } if (!havePathPoint || findObstacle)//获得路点过程(寻路) { data.Clear(); Vector3 targetPos = pathTargetPos; bool canGo = true; if (!npc.SpatialSystem.GetCellMapView(npc.AvoidanceRadius).CanPass(targetPos)) { if (!AiLogicUtility.GetWalkablePosition(npc.SpatialSystem.GetCellMapView(npc.AvoidanceRadius), targetPos, srcPos, ref targetPos)) { canGo = false; } } if (canGo) { List <Vector3> posList = null; bool canPass = npc.SpatialSystem.CanPass(npc.SpaceObject, targetPos); if (canPass) { posList = new List <Vector3>(); posList.Add(srcPos); posList.Add(targetPos); } else { long stTime = TimeUtility.GetElapsedTimeUs(); posList = npc.SpatialSystem.FindPath(srcPos, targetPos, npc.AvoidanceRadius); long endTime = TimeUtility.GetElapsedTimeUs(); long calcTime = endTime - stTime; if (calcTime > 10000) { LogSystem.Warn("*** pve FindPath consume {0} us,npc:{1} from:{2} to:{3} radius:{4} pos:{5}", calcTime, npc.GetId(), srcPos.ToString(), targetPos.ToString(), npc.AvoidanceRadius, npc.GetMovementStateInfo().GetPosition3D().ToString()); } } if (posList.Count >= 2) { data.SetPathPoints(posList[0], posList, 1); targetPos = data.CurPathPoint; npc.GetMovementStateInfo().TargetPosition = targetPos; float angle = Geometry.GetYAngle(new Vector2(srcPos.X, srcPos.Z), new Vector2(targetPos.X, targetPos.Z)); npc.GetMovementStateInfo().SetMoveDir(angle); if (faceIsMoveFir) { npc.GetMovementStateInfo().SetFaceDir(angle); } npc.GetMovementStateInfo().IsMoving = true; logic.NotifyNpcMove(npc); data.IsUsingAvoidanceVelocity = false; } else { npc.GetMovementStateInfo().IsMoving = false; logic.NotifyNpcMove(npc); data.IsUsingAvoidanceVelocity = false; } } else { npc.GetMovementStateInfo().IsMoving = false; logic.NotifyNpcMove(npc); data.IsUsingAvoidanceVelocity = false; } } } }