(badly) ported dsp's pathfind code

- added distance for vectors
- todo: why does it go retard
This commit is contained in:
Tahir Akhlaq 2017-08-16 17:25:32 +01:00
parent 68657e1edc
commit 1856cc0634
9 changed files with 98 additions and 29 deletions

View File

@ -379,6 +379,16 @@ namespace FFXIVClassic.Common
return value;
}
public static float DistanceSquared(Vector3 lhs, Vector3 rhs)
{
return DistanceSquared(lhs.X, lhs.Y, lhs.Z, rhs.X, rhs.Y, rhs.Z);
}
public static float Distance(Vector3 lhs, Vector3 rhs)
{
return Distance(lhs.X, lhs.Y, lhs.Z, rhs.X, rhs.Y, rhs.Z);
}
public static float Distance(float x, float y, float z, float x2, float y2, float z2)
{
if (x == x2 && y == y2 && z == z2)

View File

@ -404,9 +404,14 @@ namespace FFXIVClassic_Map_Server.Actors
// push latest for player
var pos = positionUpdates?[currentSubState == SetActorStatePacket.SUB_STATE_PLAYER ? positionUpdates.Count - 1 : 0];
oldPositionX = positionX;
oldPositionY = positionY;
oldPositionZ = positionZ;
positionX = pos.X;
positionY = pos.Y;
positionZ = pos.Z;
//Program.Server.GetInstance().mLuaEngine.OnPath(actor, position, positionUpdates)
positionUpdates.RemoveAt(0);

View File

@ -10,6 +10,8 @@ using FFXIVClassic.Common;
using FFXIVClassic_Map_Server.actors.area;
using FFXIVClassic_Map_Server.packets.send.actor;
// port of https://github.com/DarkstarProject/darkstar/blob/master/src/map/ai/helpers/pathfind.h
namespace FFXIVClassic_Map_Server.actors.chara.ai
{
// todo: path flags, check for obstacles etc
@ -24,6 +26,7 @@ namespace FFXIVClassic_Map_Server.actors.chara.ai
private Character owner;
private List<Vector3> path;
private bool canFollowPath;
float distanceFromPoint;
private PathFindFlags pathFlags;
@ -87,6 +90,8 @@ namespace FFXIVClassic_Map_Server.actors.chara.ai
public void PathInRange(float x, float y, float z, float minRange, float maxRange = 5.0f)
{
var dest = owner.FindRandomPoint(x, y, z, minRange, maxRange);
// todo: this is dumb..
distanceFromPoint = owner.meleeRange;
PreparePath(dest.X, dest.Y, dest.Z);
}
@ -98,7 +103,7 @@ namespace FFXIVClassic_Map_Server.actors.chara.ai
public bool IsFollowingPath()
{
return path.Count > 0;
return path?.Count > 0;
}
public bool IsFollowingScriptedPath()
@ -112,12 +117,53 @@ namespace FFXIVClassic_Map_Server.actors.chara.ai
{
var point = path[0];
owner.OnPath(point);
owner.QueuePositionUpdate(point);
path.Remove(point);
StepTo(point);
if (path.Count == 0)
owner.LookAt(point.X, point.Y);
if (AtPoint(point))
{
path.Remove(point);
owner.OnPath(point);
}
}
}
public bool AtPoint(Vector3 point)
{
if (distanceFromPoint == 0)
return owner.positionX == point.X && owner.positionZ == point.Z;
else
return Utils.Distance(owner.positionX, owner.positionY, owner.positionZ, point.X, point.Y, point.Z) <= (distanceFromPoint + 1.5f);
}
public void StepTo(Vector3 point, bool run = false)
{
float speed = GetSpeed();
float stepDistance = (speed / 10) / 2;
float distanceTo = Utils.Distance(owner.positionX, owner.positionY, owner.positionZ, point.X, point.Y, point.Z);
owner.LookAt(point.X, point.Y);
if (distanceTo <= distanceFromPoint + stepDistance + 1.5f)
{
if (distanceFromPoint == 0)
{
owner.QueuePositionUpdate(point);
}
else
{
float x = owner.positionX - (float)Math.Cos(owner.rotation + (float)(Math.PI / 2)) * (distanceTo - distanceFromPoint);
float z = owner.positionZ + (float)Math.Sin(owner.rotation + (float)(Math.PI / 2)) * (distanceTo - distanceFromPoint);
owner.QueuePositionUpdate(x, owner.positionY, z);
}
}
else
{
float x = owner.positionX - (float)Math.Cos(owner.rotation + (float)(Math.PI / 2)) * (distanceTo - distanceFromPoint);
float z = owner.positionZ + (float)Math.Sin(owner.rotation + (float)(Math.PI / 2)) * (distanceTo - distanceFromPoint);
owner.QueuePositionUpdate(x, owner.positionY, z);
}
}
@ -126,6 +172,8 @@ namespace FFXIVClassic_Map_Server.actors.chara.ai
// todo:
path?.Clear();
pathFlags = PathFindFlags.None;
distanceFromPoint = 0.0f;
}
private float GetSpeed()
@ -137,7 +185,7 @@ namespace FFXIVClassic_Map_Server.actors.chara.ai
{
if (owner.currentSubState == SetActorStatePacket.SUB_STATE_MONSTER)
{
owner.ChangeSpeed(0.0f, SetActorSpeedPacket.DEFAULT_WALK - 2.0f, SetActorSpeedPacket.DEFAULT_RUN - 2.0f, SetActorSpeedPacket.DEFAULT_ACTIVE - 2.0f);
//owner.ChangeSpeed(0.0f, SetActorSpeedPacket.DEFAULT_WALK - 2.0f, SetActorSpeedPacket.DEFAULT_RUN - 2.0f, SetActorSpeedPacket.DEFAULT_ACTIVE - 2.0f);
}
// baseSpeed += ConfigConstants.SPEED_MOD;
}

View File

@ -82,7 +82,7 @@ namespace FFXIVClassic_Map_Server.actors.chara.ai.controllers
if (Utils.Distance(owner.positionX, owner.positionY, owner.positionZ, target.positionX, target.positionY, target.positionZ) > 10)
{
owner.aiContainer.pathFind.SetPathFlags(PathFindFlags.None);
owner.aiContainer.pathFind.PreparePath(target.positionX, target.positionY, target.positionZ);
owner.aiContainer.pathFind.PathInRange(target.positionX, target.positionY, target.positionZ, 1.5f, owner.meleeRange);
ChangeTarget(target);
return false;
}
@ -193,18 +193,19 @@ namespace FFXIVClassic_Map_Server.actors.chara.ai.controllers
return;
}
var targetPos = owner.target.GetPosAsVector3();
var targetPos = new Vector3(owner.target.positionX, owner.target.positionY, owner.target.positionZ);
var distance = Utils.Distance(owner.positionX, owner.positionY, owner.positionZ, targetPos.X, targetPos.Y, targetPos.Z);
if (distance > owner.meleeRange - 0.2f || owner.aiContainer.CanFollowPath())
{
if (CanMoveForward(distance))
{
owner.LookAt(targetPos.X, targetPos.Y);
if (!owner.aiContainer.pathFind.IsFollowingPath() && distance > 3)
{
// pathfind if too far otherwise jump to target
owner.aiContainer.pathFind.SetPathFlags(distance > 3 ? PathFindFlags.None : PathFindFlags.IgnoreNav );
owner.aiContainer.pathFind.PreparePath(targetPos, 0.7f, 5);
owner.aiContainer.pathFind.SetPathFlags(distance > 5 ? PathFindFlags.None : PathFindFlags.IgnoreNav );
owner.aiContainer.pathFind.PreparePath(targetPos, 0.5f, 5);
}
owner.aiContainer.pathFind.FollowPath();
if (!owner.aiContainer.pathFind.IsFollowingPath())
@ -213,7 +214,11 @@ namespace FFXIVClassic_Map_Server.actors.chara.ai.controllers
{
foreach (var battlenpc in owner.zone.GetActorsAroundActor<BattleNpc>(owner, 1))
{
battlenpc.aiContainer.pathFind.PathInRange(targetPos, 1.5f, 1.5f);
if (battlenpc == owner)
continue;
float mobDistance = Utils.Distance(owner.positionX, owner.positionY, owner.positionZ, battlenpc.positionX, battlenpc.positionY, battlenpc.positionZ);
if (mobDistance < 0.3f && (battlenpc.updateFlags & ActorUpdateFlags.Position) == 0)
battlenpc.aiContainer.pathFind.PathInRange(targetPos, 1.5f, 1.5f);
}
}
}
@ -277,7 +282,7 @@ namespace FFXIVClassic_Map_Server.actors.chara.ai.controllers
if (verticalDistance > 8)
return false;
var distance = Utils.Distance(owner.positionX, owner.positionY, owner.positionZ, target.positionX, target.positionY, target.positionZ);
var distance = Utils.Distance(owner.positionX, owner.positionY, owner.positionZ, target.oldPositionX, target.oldPositionY, target.oldPositionZ);
bool detectSight = forceSight || (owner.aggroType & AggroType.Sight) != 0;
bool hasSneak = false;

View File

@ -43,7 +43,9 @@ namespace FFXIVClassic_Map_Server.actors.chara.ai.controllers
// todo: actual stat based range
if (Utils.Distance(owner.positionX, owner.positionY, owner.positionZ, target.positionX, target.positionY, target.positionZ) > 10)
{
owner.aiContainer.pathFind.PreparePath(target.positionX, target.positionY, target.positionZ);
{
// todo: out of range error
}
ChangeTarget(target);
return false;
}

View File

@ -87,12 +87,13 @@ namespace FFXIVClassic_Map_Server.actors.chara.ai.state
lua.LuaEngine.CallLuaBattleAction(owner, "onAttack", false, owner, target, damage);
foreach (var player in owner.zone.GetActorsAroundActor<Player>(owner, 50))
player.QueuePacket(BattleActionX01Packet.BuildPacket(player.actorId, owner.actorId, target.actorId, 223001, 18, 0, (ushort)BattleActionX01PacketCommand.Attack, (ushort)damage, 0));
if (target is Player)
((Player)target).SendPacket("139.bin");
player.QueuePacket(BattleActionX01Packet.BuildPacket(player.actorId, owner.actorId, target.actorId, 0, 537094006, 0, 27260, (ushort)damage, 0));
//if (target is Player)
// ((Player)target).SendPacket("139.bin");
target.AddHP((short)damage);
attackTime = attackTime.AddMilliseconds(owner.GetAttackDelayMs());
owner.LookAt(target);
//this.errorPacket = BattleActionX01Packet.BuildPacket(target.actorId, owner.actorId, target.actorId, 0, effectId, 0, (ushort)BattleActionX01PacketCommand.Attack, (ushort)damage, 0);
}

View File

@ -72,14 +72,16 @@ namespace FFXIVClassic_Map_Server.dataobjects
if (playerActor.positionX == x && playerActor.positionY == y && playerActor.positionZ == z && playerActor.rotation == rot)
return;
/*
playerActor.oldPositionX = playerActor.positionX;
playerActor.oldPositionY = playerActor.positionY;
playerActor.oldPositionZ = playerActor.positionZ;
playerActor.oldRotation = playerActor.rotation;
playerActor.positionX = x;
playerActor.positionY = y;
playerActor.positionZ = z;
*/
playerActor.rotation = rot;
playerActor.moveState = moveState;

View File

@ -31,7 +31,7 @@ namespace FFXIVClassic_Map_Server.packets.send.actor.battle
binWriter.Seek(0x20, SeekOrigin.Begin);
binWriter.Write((UInt32)1); //Num actions (always 1 for this)
binWriter.Write((UInt16)commandId);
binWriter.Write((UInt16)810); //?
binWriter.Write((UInt16)0x810); //?
binWriter.Write((UInt32)targetActorId);

View File

@ -58,11 +58,16 @@ namespace FFXIVClassic_Map_Server.utils
//return navmesh = new SharpNav.IO.Json.NavMeshJsonSerializer().Deserialize(filePath);
}
public static List<Vector3> GetPath(actors.area.Zone zone, float x, float y, float z, float targetX, float targetY, float targetZ, float stepSize = 0.70f, int pathSize = 45, float polyRadius = 0.0f, bool skipToTarget = false)
{
return GetPath(zone, new Vector3(x, y, z), new Vector3(targetX, targetY, targetZ), stepSize, pathSize, polyRadius, skipToTarget);
}
#region sharpnav stuff
// Copyright (c) 2013-2016 Robert Rouhani <robert.rouhani@gmail.com> and other contributors (see CONTRIBUTORS file).
// Licensed under the MIT License - https://raw.github.com/Robmaister/SharpNav/master/LICENSE
public static List<Vector3> GetPath(FFXIVClassic_Map_Server.actors.area.Zone zone, Vector3 startVec, Vector3 endVec, float stepSize = 0.70f, int pathSize = 45, float polyRadius = 0.0f, bool skipToTarget = false)
public static List<Vector3> GetPath(actors.area.Zone zone, Vector3 startVec, Vector3 endVec, float stepSize = 0.70f, int pathSize = 45, float polyRadius = 0.0f, bool skipToTarget = false)
{
var navMesh = zone.tiledNavMesh;
var navMeshQuery = zone.navMeshQuery;
@ -79,15 +84,6 @@ namespace FFXIVClassic_Map_Server.utils
return null;
}
// we dont care about distance if picking random point
float distanceSquared = polyRadius == 0.0f ? FFXIVClassic.Common.Utils.DistanceSquared(startVec.X, startVec.Y, startVec.Z, endVec.X, endVec.Y, endVec.Z) : 100;
// no point pathing if in range
if (distanceSquared < 4 && Math.Abs(startVec.Y - endVec.Y) < 1.1f)
{
return new List<Vector3>() { endVec };
}
var smoothPath = new List<Vector3>(pathSize) { };
NavQueryFilter filter = new NavQueryFilter();