mirror of
https://bitbucket.org/Ioncannon/project-meteor-server.git
synced 2025-08-06 01:25:05 +02:00
initial navmesh stuff
This commit is contained in:
parent
44a76c94af
commit
d72a2af641
19 changed files with 831 additions and 33 deletions
|
@ -40,6 +40,13 @@ namespace FFXIVClassic_Map_Server.Actors
|
|||
public string className;
|
||||
public List<LuaParam> classParams;
|
||||
|
||||
public List<utils.Vector3> positionUpdates = new List<utils.Vector3>();
|
||||
public DateTime lastAiUpdate;
|
||||
public DateTime lastMoveUpdate;
|
||||
public Actor target;
|
||||
|
||||
public bool hasMoved = false;
|
||||
public bool isAtSpawn = true;
|
||||
public EventList eventConditions;
|
||||
|
||||
public Actor(uint actorId)
|
||||
|
@ -126,7 +133,30 @@ namespace FFXIVClassic_Map_Server.Actors
|
|||
|
||||
public SubPacket CreatePositionUpdatePacket(uint playerActorId)
|
||||
{
|
||||
return MoveActorToPositionPacket.BuildPacket(actorId, playerActorId, positionX, positionY, positionZ, rotation, moveState);
|
||||
int updateMs = 300;
|
||||
var diffTime = (DateTime.Now - lastMoveUpdate);
|
||||
|
||||
if (this.target != null)
|
||||
{
|
||||
updateMs = 150;
|
||||
}
|
||||
if (diffTime.Milliseconds >= updateMs && hasMoved)
|
||||
{
|
||||
hasMoved = (this.positionUpdates != null && this.positionUpdates.Count > 0);
|
||||
if (hasMoved)
|
||||
{
|
||||
var pos = positionUpdates[0];
|
||||
positionUpdates.Remove(pos);
|
||||
|
||||
positionX = pos.X;
|
||||
positionY = pos.Y;
|
||||
positionZ = pos.Z;
|
||||
//Program.Server.GetInstance().mLuaEngine.OnPath(actor, position, positionUpdates)
|
||||
}
|
||||
lastMoveUpdate = DateTime.Now;
|
||||
return MoveActorToPositionPacket.BuildPacket(actorId, playerActorId, positionX, positionY, positionZ, rotation, moveState);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public SubPacket CreateStatePacket(uint playerActorID)
|
||||
|
@ -323,7 +353,78 @@ namespace FFXIVClassic_Map_Server.Actors
|
|||
}
|
||||
|
||||
public void Update(double deltaTime)
|
||||
{
|
||||
{
|
||||
// todo: this is retarded
|
||||
if (this is Zone || this is Area || this is Player)
|
||||
return;
|
||||
|
||||
var diffTime = (DateTime.Now - lastAiUpdate);
|
||||
|
||||
// todo: this too
|
||||
if (diffTime.Milliseconds >= deltaTime)
|
||||
{
|
||||
bool foundActor = false;
|
||||
foreach (var actor in ((Area)zone).GetActorsAroundActor(this, 50))
|
||||
{
|
||||
if (actor is Player && actor != this)
|
||||
{
|
||||
var player = actor as Player;
|
||||
|
||||
var distance = Utils.Distance(positionX, positionY, positionZ, player.positionX, player.positionY, player.positionZ);
|
||||
|
||||
int maxDistance = player == target ? 25 : 15;
|
||||
|
||||
if (distance <= maxDistance)
|
||||
{
|
||||
foundActor = true;
|
||||
|
||||
if (!hasMoved)
|
||||
{
|
||||
if (distance >= 3)
|
||||
{
|
||||
FollowTarget(player, 2.0f);
|
||||
}
|
||||
// too close, spread out
|
||||
else if (distance <= 0.64f)
|
||||
{
|
||||
var minRadius = 0.65f;
|
||||
var maxRadius = 0.85f;
|
||||
|
||||
var angle = Program.Random.NextDouble() * Math.PI * 2;
|
||||
var radius = Math.Sqrt(Program.Random.NextDouble() * (maxRadius - minRadius)) + minRadius;
|
||||
|
||||
float x = (float)(radius * Math.Cos(angle));
|
||||
float z = (float)(radius * Math.Sin(angle));
|
||||
|
||||
positionUpdates.Add(new utils.Vector3(positionX + x, positionY, positionZ + z));
|
||||
|
||||
hasMoved = true;
|
||||
}
|
||||
else if (target != null)
|
||||
{
|
||||
// todo: actually make IsFacing work
|
||||
if(!IsFacing(target.positionX, target.positionY))
|
||||
LookAt(target);
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
// 5 seconds before back to spawn
|
||||
if ((DateTime.Now - lastMoveUpdate).Seconds >= 5 && !foundActor)
|
||||
{
|
||||
// 10 yalms spawn radius just because
|
||||
this.isAtSpawn = Utils.Distance(positionX, positionY, positionZ, oldPositionX, oldPositionY, oldPositionZ) <= 18.0f;
|
||||
|
||||
if (this.isAtSpawn != true && this.target == null && oldPositionX != 0.0f && oldPositionY != 0.0f && oldPositionZ != 0.0f)
|
||||
PathTo(oldPositionX, oldPositionY, oldPositionZ, 3.0f);
|
||||
|
||||
lastMoveUpdate = DateTime.Now;
|
||||
this.target = null;
|
||||
}
|
||||
lastAiUpdate = DateTime.Now;
|
||||
}
|
||||
}
|
||||
|
||||
public void GenerateActorName(int actorNumber)
|
||||
|
@ -492,6 +593,110 @@ namespace FFXIVClassic_Map_Server.Actors
|
|||
{
|
||||
return zoneId;
|
||||
}
|
||||
|
||||
public bool IsFacing(float x, float y, byte checkAngle = 45)
|
||||
{
|
||||
var rot1 = this.rotation;
|
||||
|
||||
var dX = this.positionX - x;
|
||||
var dY = this.positionY - y;
|
||||
|
||||
var rot2 = Math.Atan2(dY, dX);
|
||||
|
||||
var dRot = Math.PI - rot2 + Math.PI / 2;
|
||||
|
||||
Program.Log.Error("IsFacing Rotation {0} Rotation2 {1}", rot1, rot2);
|
||||
return rot1 == rot2;
|
||||
}
|
||||
|
||||
public void LookAt(Actor actor)
|
||||
{
|
||||
if (actor != null)
|
||||
{
|
||||
LookAt(actor.positionX, actor.positionY);
|
||||
}
|
||||
else
|
||||
{
|
||||
Program.Log.Error("Actor.LookAt() unable to find actor!");
|
||||
}
|
||||
}
|
||||
|
||||
public void LookAt(float x, float y)
|
||||
{
|
||||
var rot1 = this.rotation;
|
||||
|
||||
var dX = this.positionX - x;
|
||||
var dY = this.positionY - y;
|
||||
|
||||
var rot2 = Math.Atan2(dY, dX);
|
||||
|
||||
var dRot = Math.PI - rot2 + Math.PI / 2;
|
||||
|
||||
Program.Log.Error("LookAt Rotation {0} Rotation2 {1}", rot1, rot2);
|
||||
|
||||
this.hasMoved = rot2 != rot1;
|
||||
this.rotation = (float)dRot;
|
||||
}
|
||||
|
||||
public void PathTo(float x, float y, float z, float stepSize = 0.70f, int maxPath = 40)
|
||||
{
|
||||
var pos = new utils.Vector3(positionX, positionY, positionZ);
|
||||
var dest = new utils.Vector3(x, y, z);
|
||||
|
||||
var sw = new System.Diagnostics.Stopwatch();
|
||||
sw.Start();
|
||||
|
||||
var path = utils.NavmeshUtils.GetPath(((Zone)GetZone()), pos, dest, stepSize, maxPath);
|
||||
|
||||
if (path != null)
|
||||
{
|
||||
if (oldPositionX == 0.0f && oldPositionY == 0.0f && oldPositionZ == 0.0f)
|
||||
{
|
||||
oldPositionX = positionX;
|
||||
oldPositionY = positionY;
|
||||
oldPositionZ = positionZ;
|
||||
}
|
||||
|
||||
// todo: something went wrong
|
||||
if (path.Count == 0)
|
||||
{
|
||||
positionX = oldPositionX;
|
||||
positionY = oldPositionY;
|
||||
positionZ = oldPositionZ;
|
||||
}
|
||||
|
||||
positionUpdates = path;
|
||||
|
||||
this.hasMoved = true;
|
||||
this.isAtSpawn = false;
|
||||
|
||||
sw.Stop();
|
||||
((Zone)zone).pathCalls++;
|
||||
((Zone)zone).pathCallTime += sw.ElapsedMilliseconds;
|
||||
Program.Log.Error("[{0}][{1}] Created {2} points in {3} milliseconds", actorId, actorName, path.Count, sw.ElapsedMilliseconds);
|
||||
}
|
||||
}
|
||||
|
||||
public void FollowTarget(Actor target, float stepSize = 1.2f, int maxPath = 25)
|
||||
{
|
||||
if (target != null)
|
||||
{
|
||||
var player = target as Player;
|
||||
|
||||
if (this.target != target)
|
||||
this.target = target;
|
||||
|
||||
this.moveState = player.moveState;
|
||||
this.moveSpeeds = player.moveSpeeds;
|
||||
|
||||
PathTo(player.positionX, player.positionY, player.positionZ, stepSize, maxPath);
|
||||
}
|
||||
}
|
||||
|
||||
public void OnPath()
|
||||
{
|
||||
// todo: lua function onPath in mob script
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -10,6 +10,8 @@ using System.Collections.Generic;
|
|||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.IO;
|
||||
|
||||
using FFXIVClassic_Map_Server.actors.director;
|
||||
|
||||
namespace FFXIVClassic_Map_Server.actors.area
|
||||
|
@ -20,10 +22,31 @@ namespace FFXIVClassic_Map_Server.actors.area
|
|||
Dictionary<string, List<PrivateAreaContent>> contentAreas = new Dictionary<string, List<PrivateAreaContent>>();
|
||||
Object contentAreasLock = new Object();
|
||||
|
||||
public Detour.dtNavMesh navMesh;
|
||||
public SharpNav.TiledNavMesh tiledNavMesh;
|
||||
public SharpNav.NavMeshQuery navMeshQuery;
|
||||
public Int64 pathCalls;
|
||||
public Int64 pathCallTime;
|
||||
|
||||
public Zone(uint id, string zoneName, ushort regionId, string classPath, ushort bgmDay, ushort bgmNight, ushort bgmBattle, bool isIsolated, bool isInn, bool canRideChocobo, bool canStealth, bool isInstanceRaid)
|
||||
: base(id, zoneName, regionId, classPath, bgmDay, bgmNight, bgmBattle, isIsolated, isInn, canRideChocobo, canStealth, isInstanceRaid)
|
||||
{
|
||||
|
||||
// central thanalan navmesh
|
||||
if (id == 170)
|
||||
{
|
||||
try
|
||||
{
|
||||
//navMesh = utils.NavmeshUtils.LoadNavmesh("wil_w0_fld01.bin");
|
||||
tiledNavMesh = utils.NavmeshUtils.LoadNavmesh(tiledNavMesh, "wil_w0_fld01.snb");
|
||||
navMeshQuery = new SharpNav.NavMeshQuery(tiledNavMesh, 100);
|
||||
GC.Collect(2);
|
||||
}
|
||||
catch(Exception e)
|
||||
{
|
||||
Program.Log.Error(e.Message);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
public void AddPrivateArea(PrivateArea pa)
|
||||
|
|
|
@ -151,8 +151,8 @@ namespace FFXIVClassic_Map_Server.Actors
|
|||
isStatic = true;
|
||||
else
|
||||
{
|
||||
// charaWork.property[2] = 1;
|
||||
// npcWork.hateType = 1;
|
||||
charaWork.property[2] = 1;
|
||||
npcWork.hateType = 1;
|
||||
}
|
||||
|
||||
if (lParams == null)
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue