1
Fork 0
mirror of https://bitbucket.org/Ioncannon/project-meteor-server.git synced 2025-04-26 06:37:45 +00:00

initial navmesh stuff

This commit is contained in:
Tahir Akhlaq 2017-05-27 02:17:25 +01:00
parent 44a76c94af
commit d72a2af641
19 changed files with 831 additions and 33 deletions

3
.gitmodules vendored Normal file
View file

@ -0,0 +1,3 @@
[submodule "FFXIVClassic Map Server/navmesh/rcdtcs"]
path = FFXIVClassic Map Server/navmesh/rcdtcs
url = https://github.com/jlalleve/rcdtcs

View file

@ -36,6 +36,7 @@
<ErrorReport>prompt</ErrorReport> <ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel> <WarningLevel>4</WarningLevel>
<Prefer32Bit>false</Prefer32Bit> <Prefer32Bit>false</Prefer32Bit>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<Reference Include="DotNetZip"> <Reference Include="DotNetZip">
@ -51,6 +52,7 @@
</Reference> </Reference>
<Reference Include="System" /> <Reference Include="System" />
<Reference Include="System.Core" /> <Reference Include="System.Core" />
<Reference Include="System.Numerics" />
<Reference Include="System.Xml.Linq" /> <Reference Include="System.Xml.Linq" />
<Reference Include="System.Data.DataSetExtensions" /> <Reference Include="System.Data.DataSetExtensions" />
<Reference Include="Microsoft.CSharp" /> <Reference Include="Microsoft.CSharp" />

View file

@ -351,5 +351,32 @@ namespace FFXIVClassic.Common
{ {
return (value >> bits) | (value << (16 - bits)); return (value >> bits) | (value << (16 - bits));
} }
public static float Clamp(float val, float min, float max)
{
return Math.Max(Math.Min(max, val), min);
}
public static float Distance(float x, float y, float z, float x2, float y2, float z2)
{
if (x == x2 && y == y2 && z == z2)
return 0.0f;
return (float)Math.Sqrt(DistanceSquared(x, y, z, x2, y2, z2));
}
public static float DistanceSquared(float x, float y, float z, float x2, float y2, float z2)
{
if (x == x2 && y == y2 && z == z2)
return 0.0f;
// todo: my maths is shit
var dx = x - x2;
var dy = y - y2;
var dz = z - z2;
return dx * dx + dy * dy + dz * dz;
}
} }
} }

View file

@ -1,11 +1,20 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<configuration> <configuration>
<startup> <startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5" /> <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5.1" />
</startup> </startup>
<system.data> <system.data>
<DbProviderFactories> <DbProviderFactories>
<remove invariant="MySql.Data.MySqlClient" /> <remove invariant="MySql.Data.MySqlClient" />
<add name="MySQL Data Provider" invariant="MySql.Data.MySqlClient" description=".Net Framework Data Provider for MySQL" type="MySql.Data.MySqlClient.MySqlClientFactory, MySql.Data, Version=6.9.8.0, Culture=neutral, PublicKeyToken=c5687fc88969c44d" /> <add name="MySQL Data Provider" invariant="MySql.Data.MySqlClient" description=".Net Framework Data Provider for MySQL" type="MySql.Data.MySqlClient.MySqlClientFactory, MySql.Data, Version=6.9.8.0, Culture=neutral, PublicKeyToken=c5687fc88969c44d" />
</DbProviderFactories> </DbProviderFactories>
</system.data></configuration> </system.data>
<runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="Newtonsoft.Json" publicKeyToken="30ad4fe6b2a6aeed" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-10.0.0.0" newVersion="10.0.0.0" />
</dependentAssembly>
</assemblyBinding>
</runtime>
</configuration>

View file

@ -10,9 +10,10 @@
<AppDesignerFolder>Properties</AppDesignerFolder> <AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>FFXIVClassic_Map_Server</RootNamespace> <RootNamespace>FFXIVClassic_Map_Server</RootNamespace>
<AssemblyName>FFXIVClassic Map Server</AssemblyName> <AssemblyName>FFXIVClassic Map Server</AssemblyName>
<TargetFrameworkVersion>v4.5</TargetFrameworkVersion> <TargetFrameworkVersion>v4.5.1</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment> <FileAlignment>512</FileAlignment>
<NuGetPackageImportStamp>1d22ec4a</NuGetPackageImportStamp> <NuGetPackageImportStamp>1d22ec4a</NuGetPackageImportStamp>
<TargetFrameworkProfile />
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' "> <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<PlatformTarget>AnyCPU</PlatformTarget> <PlatformTarget>AnyCPU</PlatformTarget>
@ -24,6 +25,7 @@
<ErrorReport>prompt</ErrorReport> <ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel> <WarningLevel>4</WarningLevel>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks> <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<Prefer32Bit>true</Prefer32Bit>
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' "> <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<PlatformTarget>AnyCPU</PlatformTarget> <PlatformTarget>AnyCPU</PlatformTarget>
@ -58,16 +60,20 @@
<HintPath>..\packages\MySql.Data.6.9.8\lib\net45\MySql.Data.dll</HintPath> <HintPath>..\packages\MySql.Data.6.9.8\lib\net45\MySql.Data.dll</HintPath>
<Private>True</Private> <Private>True</Private>
</Reference> </Reference>
<Reference Include="Newtonsoft.Json, Version=8.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL"> <Reference Include="Newtonsoft.Json, Version=10.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
<HintPath>..\packages\Newtonsoft.Json.8.0.3\lib\net45\Newtonsoft.Json.dll</HintPath> <HintPath>..\packages\Newtonsoft.Json.10.0.2\lib\net45\Newtonsoft.Json.dll</HintPath>
<Private>True</Private>
</Reference> </Reference>
<Reference Include="NLog, Version=4.0.0.0, Culture=neutral, PublicKeyToken=5120e14c03d0593c, processorArchitecture=MSIL"> <Reference Include="NLog, Version=4.0.0.0, Culture=neutral, PublicKeyToken=5120e14c03d0593c, processorArchitecture=MSIL">
<HintPath>..\packages\NLog.4.3.5\lib\net45\NLog.dll</HintPath> <HintPath>..\packages\NLog.4.3.5\lib\net45\NLog.dll</HintPath>
<Private>True</Private> <Private>True</Private>
</Reference> </Reference>
<Reference Include="SharpNav, Version=1.0.0.1, Culture=neutral, PublicKeyToken=b467138d8cacd85b, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>.\SharpNav.dll</HintPath>
</Reference>
<Reference Include="System" /> <Reference Include="System" />
<Reference Include="System.Core" /> <Reference Include="System.Core" />
<Reference Include="System.Numerics" />
<Reference Include="System.Xml.Linq" /> <Reference Include="System.Xml.Linq" />
<Reference Include="System.Data.DataSetExtensions" /> <Reference Include="System.Data.DataSetExtensions" />
<Reference Include="Microsoft.CSharp" /> <Reference Include="Microsoft.CSharp" />
@ -131,6 +137,21 @@
<Compile Include="lua\LuaParam.cs" /> <Compile Include="lua\LuaParam.cs" />
<Compile Include="lua\LuaScript.cs" /> <Compile Include="lua\LuaScript.cs" />
<Compile Include="lua\LuaUtils.cs" /> <Compile Include="lua\LuaUtils.cs" />
<Compile Include="navmesh\rcdtcs\Assets\Rcdtcs\Detour\DetourCommon.cs" />
<Compile Include="navmesh\rcdtcs\Assets\Rcdtcs\Detour\DetourNavMesh.cs" />
<Compile Include="navmesh\rcdtcs\Assets\Rcdtcs\Detour\DetourNavMeshBuilder.cs" />
<Compile Include="navmesh\rcdtcs\Assets\Rcdtcs\Detour\DetourNavMeshQuery.cs" />
<Compile Include="navmesh\rcdtcs\Assets\Rcdtcs\Detour\DetourNode.cs" />
<Compile Include="navmesh\rcdtcs\Assets\Rcdtcs\Detour\DetourStatus.cs" />
<Compile Include="navmesh\rcdtcs\Assets\Rcdtcs\Recast\Recast.cs" />
<Compile Include="navmesh\rcdtcs\Assets\Rcdtcs\Recast\RecastArea.cs" />
<Compile Include="navmesh\rcdtcs\Assets\Rcdtcs\Recast\RecastContour.cs" />
<Compile Include="navmesh\rcdtcs\Assets\Rcdtcs\Recast\RecastFilter.cs" />
<Compile Include="navmesh\rcdtcs\Assets\Rcdtcs\Recast\RecastLayers.cs" />
<Compile Include="navmesh\rcdtcs\Assets\Rcdtcs\Recast\RecastMesh.cs" />
<Compile Include="navmesh\rcdtcs\Assets\Rcdtcs\Recast\RecastMeshDetail.cs" />
<Compile Include="navmesh\rcdtcs\Assets\Rcdtcs\Recast\RecastRasterization.cs" />
<Compile Include="navmesh\rcdtcs\Assets\Rcdtcs\Recast\RecastRegion.cs" />
<Compile Include="PacketProcessor.cs" /> <Compile Include="PacketProcessor.cs" />
<Compile Include="packets\receive\ChatMessagePacket.cs" /> <Compile Include="packets\receive\ChatMessagePacket.cs" />
<Compile Include="packets\receive\events\EventUpdatePacket.cs" /> <Compile Include="packets\receive\events\EventUpdatePacket.cs" />
@ -310,6 +331,7 @@
<Compile Include="Server.cs" /> <Compile Include="Server.cs" />
<Compile Include="utils\ActorPropertyPacketUtil.cs" /> <Compile Include="utils\ActorPropertyPacketUtil.cs" />
<Compile Include="utils\CharacterUtils.cs" /> <Compile Include="utils\CharacterUtils.cs" />
<Compile Include="utils\NavmeshUtils.cs" />
<Compile Include="utils\SQLGeneration.cs" /> <Compile Include="utils\SQLGeneration.cs" />
<Compile Include="actors\area\Area.cs" /> <Compile Include="actors\area\Area.cs" />
<Compile Include="WorldManager.cs" /> <Compile Include="WorldManager.cs" />
@ -332,6 +354,7 @@
<LastGenOutput>Resources.Designer.cs</LastGenOutput> <LastGenOutput>Resources.Designer.cs</LastGenOutput>
</EmbeddedResource> </EmbeddedResource>
</ItemGroup> </ItemGroup>
<ItemGroup />
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" /> <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<PropertyGroup> <PropertyGroup>
<PostBuildEvent>xcopy "$(SolutionDir)data\map_config.ini" "$(SolutionDir)$(ProjectName)\$(OutDir)" /d <PostBuildEvent>xcopy "$(SolutionDir)data\map_config.ini" "$(SolutionDir)$(ProjectName)\$(OutDir)" /d

View file

@ -16,6 +16,8 @@ namespace FFXIVClassic_Map_Server
class Program class Program
{ {
public static Logger Log; public static Logger Log;
public static Server Server;
public static Random Random;
static void Main(string[] args) static void Main(string[] args)
{ {
@ -55,9 +57,10 @@ namespace FFXIVClassic_Map_Server
//Start server if A-OK //Start server if A-OK
if (startServer) if (startServer)
{ {
Server server = new Server(); Random = new Random();
Server = new Server();
server.StartServer(); Server.StartServer();
while (startServer) while (startServer)
{ {

View file

@ -17,7 +17,7 @@ namespace FFXIVClassic_Map_Server.Properties {
/// </summary> /// </summary>
// This class was auto-generated by the StronglyTypedResourceBuilder // This class was auto-generated by the StronglyTypedResourceBuilder
// class via a tool like ResGen or Visual Studio. // class via a tool like ResGen or Visual Studio.
// To add or Remove a member, edit your .ResX file then rerun ResGen // To add or remove a member, edit your .ResX file then rerun ResGen
// with the /str option, or rebuild your VS project. // with the /str option, or rebuild your VS project.
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")] [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()] [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
@ -105,7 +105,7 @@ namespace FFXIVClassic_Map_Server.Properties {
/// ///
///Available commands: ///Available commands:
///Standard: mypos, music, warp ///Standard: mypos, music, warp
///Server Administration: givecurrency, giveitem, givekeyitem, Removecurrency, Removekeyitem, reloaditems, reloadzones ///Server Administration: givecurrency, giveitem, givekeyitem, removecurrency, removekeyitem, reloaditems, reloadzones
///Test: test weather. ///Test: test weather.
/// </summary> /// </summary>
public static string CPhelp { public static string CPhelp {
@ -176,38 +176,38 @@ namespace FFXIVClassic_Map_Server.Properties {
/// <summary> /// <summary>
/// Looks up a localized string similar to Removes the specified currency from the current player&apos;s inventory /// Looks up a localized string similar to Removes the specified currency from the current player&apos;s inventory
/// ///
///*Syntax: Removecurrency &lt;quantity&gt; ///*Syntax: removecurrency &lt;quantity&gt;
/// Removecurrency &lt;type&gt; &lt;quantity&gt; /// removecurrency &lt;type&gt; &lt;quantity&gt;
///&lt;type&gt; is the specific type of currency desired, defaults to gil if no type specified. ///&lt;type&gt; is the specific type of currency desired, defaults to gil if no type specified.
/// </summary> /// </summary>
public static string CPRemovecurrency { public static string CPremovecurrency {
get { get {
return ResourceManager.GetString("CPRemovecurrency", resourceCulture); return ResourceManager.GetString("CPremovecurrency", resourceCulture);
} }
} }
/// <summary> /// <summary>
/// Looks up a localized string similar to Removes the specified items to the current player&apos;s inventory /// Looks up a localized string similar to Removes the specified items to the current player&apos;s inventory
/// ///
///*Syntax: Removeitem &lt;itemid&gt; ///*Syntax: removeitem &lt;itemid&gt;
/// Removeitem &lt;itemid&gt; &lt;quantity&gt; /// removeitem &lt;itemid&gt; &lt;quantity&gt;
///&lt;item id&gt; is the item&apos;s specific id as defined in the server database. ///&lt;item id&gt; is the item&apos;s specific id as defined in the server database.
/// </summary> /// </summary>
public static string CPRemoveitem { public static string CPremoveitem {
get { get {
return ResourceManager.GetString("CPRemoveitem", resourceCulture); return ResourceManager.GetString("CPremoveitem", resourceCulture);
} }
} }
/// <summary> /// <summary>
/// Looks up a localized string similar to Removes the specified key item to the current player&apos;s inventory /// Looks up a localized string similar to Removes the specified key item to the current player&apos;s inventory
/// ///
///*Syntax: Removekeyitem &lt;itemid&gt; ///*Syntax: removekeyitem &lt;itemid&gt;
///&lt;item id&gt; is the key item&apos;s specific id as defined in the server database. ///&lt;item id&gt; is the key item&apos;s specific id as defined in the server database.
/// </summary> /// </summary>
public static string CPRemovekeyitem { public static string CPremovekeyitem {
get { get {
return ResourceManager.GetString("CPRemovekeyitem", resourceCulture); return ResourceManager.GetString("CPremovekeyitem", resourceCulture);
} }
} }

Binary file not shown.

View file

@ -40,6 +40,13 @@ namespace FFXIVClassic_Map_Server.Actors
public string className; public string className;
public List<LuaParam> classParams; 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 EventList eventConditions;
public Actor(uint actorId) public Actor(uint actorId)
@ -126,8 +133,31 @@ namespace FFXIVClassic_Map_Server.Actors
public SubPacket CreatePositionUpdatePacket(uint playerActorId) public SubPacket CreatePositionUpdatePacket(uint playerActorId)
{ {
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 MoveActorToPositionPacket.BuildPacket(actorId, playerActorId, positionX, positionY, positionZ, rotation, moveState);
} }
return null;
}
public SubPacket CreateStatePacket(uint playerActorID) public SubPacket CreateStatePacket(uint playerActorID)
{ {
@ -324,6 +354,77 @@ namespace FFXIVClassic_Map_Server.Actors
public void Update(double deltaTime) 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) public void GenerateActorName(int actorNumber)
@ -492,6 +593,110 @@ namespace FFXIVClassic_Map_Server.Actors
{ {
return zoneId; 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
}
} }
} }

View file

@ -10,6 +10,8 @@ using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Text; using System.Text;
using System.Threading.Tasks; using System.Threading.Tasks;
using System.IO;
using FFXIVClassic_Map_Server.actors.director; using FFXIVClassic_Map_Server.actors.director;
namespace FFXIVClassic_Map_Server.actors.area namespace FFXIVClassic_Map_Server.actors.area
@ -20,11 +22,32 @@ namespace FFXIVClassic_Map_Server.actors.area
Dictionary<string, List<PrivateAreaContent>> contentAreas = new Dictionary<string, List<PrivateAreaContent>>(); Dictionary<string, List<PrivateAreaContent>> contentAreas = new Dictionary<string, List<PrivateAreaContent>>();
Object contentAreasLock = new Object(); 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) 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) : 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) public void AddPrivateArea(PrivateArea pa)
{ {

View file

@ -151,8 +151,8 @@ namespace FFXIVClassic_Map_Server.Actors
isStatic = true; isStatic = true;
else else
{ {
// charaWork.property[2] = 1; charaWork.property[2] = 1;
// npcWork.hateType = 1; npcWork.hateType = 1;
} }
if (lParams == null) if (lParams == null)

View file

@ -0,0 +1,169 @@
require("global");
properties = {
permissions = 0,
parameters = "ssss",
description =
[[
yolo
]],
}
local quests =
{
[111807] = { level = 25, weight = 4, rewardexp = 1080 },
[110868] = { level = 50, weight = 4, rewardexp = 4400 },
[111603] = { level = 22, weight = 5, rewardexp = 1100 },
[111602] = { level = 22, weight = 5, rewardexp = 1100 },
[111420] = { level = 45, weight = 5, rewardexp = 4450 },
[110811] = { level = 18, weight = 6, rewardexp = 780 },
[110814] = { level = 18, weight = 6, rewardexp = 780 },
[110707] = { level = 25, weight = 6, rewardexp = 1620 },
[110682] = { level = 34, weight = 6, rewardexp = 3180 },
[111202] = { level = 35, weight = 6, rewardexp = 3360 },
[111222] = { level = 35, weight = 6, rewardexp = 3360 },
[111302] = { level = 35, weight = 6, rewardexp = 3360 },
[111223] = { level = 40, weight = 6, rewardexp = 4260 },
[110819] = { level = 45, weight = 6, rewardexp = 5340 },
[111224] = { level = 45, weight = 6, rewardexp = 5340 },
[111225] = { level = 45, weight = 6, rewardexp = 5340 },
[110867] = { level = 45, weight = 6, rewardexp = 5340 },
[110869] = { level = 45, weight = 6, rewardexp = 5340 },
[110708] = { level = 45, weight = 6, rewardexp = 5340 },
[110627] = { level = 45, weight = 6, rewardexp = 5340 },
[111434] = { level = 50, weight = 6, rewardexp = 6600 },
[110850] = { level = 1, weight = 7, rewardexp = 40 },
[110851] = { level = 1, weight = 7, rewardexp = 40 },
[110841] = { level = 20, weight = 7, rewardexp = 1120 },
[110642] = { level = 20, weight = 7, rewardexp = 1120 },
[110840] = { level = 20, weight = 7, rewardexp = 1120 },
[110727] = { level = 21, weight = 7, rewardexp = 1401 },
[111221] = { level = 30, weight = 7, rewardexp = 2661 },
[111241] = { level = 30, weight = 7, rewardexp = 2661 },
[110687] = { level = 28, weight = 9, rewardexp = 2970 },
[110016] = { level = 34, weight = 50, rewardexp = 26500 },
[110017] = { level = 38, weight = 50, rewardexp = 32500 },
[110019] = { level = 46, weight = 50, rewardexp = 46000 }
};
local expTable = {
570, -- 1
700,
880,
1100,
1500,
1800,
2300,
3200,
4300,
5000, -- 10
5900,
6800,
7700,
8700,
9700,
11000,
12000,
13000,
15000,
16000, -- 20
20000,
22000,
23000,
25000,
27000,
29000,
31000,
33000,
35000,
38000, -- 30
45000,
47000,
50000,
53000,
56000,
59000,
62000,
65000,
68000,
71000, -- 40
74000,
78000,
81000,
85000,
89000,
92000,
96000,
100000,
100000,
110000 -- 50
};
local commandCost = {
["raise"] = 150,
["cure"] = 40,
["cura"] = 100,
["curaga"] = 150,
};
-- stone: (1, 9) (5, 12) (10, )
-- cure: (1, 5) (5, 6) (10, )
-- aero: (1, 9) (5, 12) (10, )
-- protect: (1, 9) (5, 12) (10, )
--[[
function onTrigger(player, argc, id, level, weight)
id = tonumber(id) or 111807;
level = tonumber(level) or quests[id].level;
weight = tonumber(weight) or quests[id].weight;
local messageId = MESSAGE_TYPE_SYSTEM_ERROR;
local sender = "yolo";
if id == 1 then
return
end
local message = calcSkillPoint(player, level, weight);
if player then
player.SendMessage(messageId, sender, string.format("calculated %s | expected %s", message, quests[id].rewardexp));
end;
printf("calculated %s | expected %s", message, quests[id].rewardexp);
end;
]]
function onTrigger(player, argc, skillName, level)
local messageId = MESSAGE_TYPE_SYSTEM_ERROR;
local sender = "yolo";
if player then
local pos = player:GetPos();
local x = tonumber(pos[0]);
local y = tonumber(pos[1]);
local z = tonumber(pos[2]);
local rot = tonumber(pos[3]);
local zone = pos[4];
printf("%f %f %f", x, y, z);
--local x, y, z = player.GetPos();
for i = 1, 1 do
local actor = player.GetZone().SpawnActor(1000070, 'ass', x-(13 + 2*i), y, z);
actor.FollowTarget(player, 3.2);
end;
return;
end
level = tonumber(level) or 1;
if player then
player.SendMessage(messageId, sender, string.format("name %s | cost %d | level %u", skillName, calculateCommandCost(player, skillName, level), level));
end;
end;
function calculateCommandCost(player, skillName, level)
if skillName and level and commandCost[skillName] then
return math.ceil((8000 + (level - 70) * 500) * (commandCost[skillName] * 0.001));
end;
return 1;
end
function calcSkillPoint(player, lvl, weight)
weight = weight / 100
return math.ceil(expTable[lvl] * weight)
end

View file

@ -120,6 +120,7 @@ namespace FFXIVClassic_Map_Server.dataobjects
} }
bool checkedThisTick = false;
//Add new actors or move //Add new actors or move
for (int i = 0; i < list.Count; i++) for (int i = 0; i < list.Count; i++)
{ {
@ -131,10 +132,25 @@ namespace FFXIVClassic_Map_Server.dataobjects
if (actorInstanceList.Contains(actor)) if (actorInstanceList.Contains(actor))
{ {
//Don't send for static characters (npcs) //Don't send for static characters (npcs)
if (actor is Character && ((Character)actor).isStatic) // todo: this is retarded, need actual mob class
if (actor is Character && !actor.hasMoved && ((Character)actor).isStatic)
continue; continue;
GetActor().QueuePacket(actor.CreatePositionUpdatePacket(playerActor.actorId)); // todo: again, this is retarded but debug stuff
var zone = (actors.area.Zone)actor.zone;
if(zone != null && !checkedThisTick)
{
if (zone.pathCalls > 0)
{
checkedThisTick = true;
Program.Log.Error("Number of pathfinding calls {0} average time {1}", zone.pathCalls, zone.pathCallTime / zone.pathCalls);
}
}
var packet = actor.CreatePositionUpdatePacket(playerActor.actorId);
if (packet != null)
GetActor().QueuePacket(packet);
} }
else else
{ {

View file

@ -533,11 +533,11 @@ namespace FFXIVClassic_Map_Server.lua
LuaParam.Insert(1, i - (playerNull ? 2 : 0)); LuaParam.Insert(1, i - (playerNull ? 2 : 0));
// run the script // run the script
//script.Call(script.Globals["onTrigger"], LuaParam.ToArray()); script.Call(script.Globals["onTrigger"], LuaParam.ToArray());
Coroutine coroutine = script.CreateCoroutine(script.Globals["onTrigger"]).Coroutine; //Coroutine coroutine = script.CreateCoroutine(script.Globals["onTrigger"]).Coroutine;
DynValue value = coroutine.Resume(LuaParam.ToArray()); //DynValue value = coroutine.Resume(LuaParam.ToArray());
GetInstance().ResolveResume(player, coroutine, value); //GetInstance().ResolveResume(player, coroutine, value);
return; return;
} }
} }

@ -0,0 +1 @@
Subproject commit 8eea27727df5132c5f0e6732d1bd36238ce300ea

View file

@ -5,7 +5,7 @@
<package id="Microsoft.Net.Compilers" version="2.0.0-beta3" targetFramework="net45" developmentDependency="true" /> <package id="Microsoft.Net.Compilers" version="2.0.0-beta3" targetFramework="net45" developmentDependency="true" />
<package id="MoonSharp" version="1.2.1.0" targetFramework="net45" /> <package id="MoonSharp" version="1.2.1.0" targetFramework="net45" />
<package id="MySql.Data" version="6.9.8" targetFramework="net45" /> <package id="MySql.Data" version="6.9.8" targetFramework="net45" />
<package id="Newtonsoft.Json" version="8.0.3" targetFramework="net45" /> <package id="Newtonsoft.Json" version="10.0.2" targetFramework="net451" />
<package id="NLog" version="4.3.5" targetFramework="net45" /> <package id="NLog" version="4.3.5" targetFramework="net45" />
<package id="NLog.Config" version="4.3.5" targetFramework="net45" /> <package id="NLog.Config" version="4.3.5" targetFramework="net45" />
<package id="NLog.Schema" version="4.3.4" targetFramework="net45" /> <package id="NLog.Schema" version="4.3.4" targetFramework="net45" />

View file

@ -0,0 +1,313 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.IO;
using SharpNav;
using SharpNav.Pathfinding;
using SharpNav.Crowds;
using SharpNav.IO;
namespace FFXIVClassic_Map_Server.utils
{
public class Vector3
{
public float X;
public float Y;
public float Z;
public static Vector3 Zero = new Vector3();
public Vector3(float x, float y, float z)
{
X = x;
Y = y;
Z = z;
}
public Vector3()
{
X = 0.0f;
Y = 0.0f;
Z = 0.0f;
}
public Vector3(SharpNav.Geometry.Vector3 vec)
{
X = vec.X;
Y = vec.Y;
Z = vec.Z;
}
public static Vector3 operator +(Vector3 lhs, Vector3 rhs)
{
Vector3 newVec = new Vector3(lhs.X, lhs.Y, lhs.Z);
newVec.X += rhs.X;
newVec.Y += rhs.Y;
newVec.Z += rhs.Z;
return newVec;
}
public static Vector3 operator -(Vector3 lhs, Vector3 rhs)
{
return new Vector3(lhs.X - rhs.X, lhs.Y - rhs.Y, lhs.Z - rhs.Z);
}
public static Vector3 operator *(Vector3 lhs, Vector3 rhs)
{
return new Vector3(lhs.X * rhs.X, lhs.Y * rhs.Y, lhs.Z * rhs.Z);
}
public static Vector3 operator *(float scalar, Vector3 rhs)
{
return new Vector3(scalar * rhs.X, scalar * rhs.Y, scalar * rhs.Z);
}
public static Vector3 operator /(Vector3 lhs, Vector3 rhs)
{
return new Vector3(lhs.X - rhs.X, lhs.Y - rhs.Y, lhs.Z - rhs.Z);
}
public float Length()
{
return (float)Math.Sqrt(this.LengthSquared());
}
public float LengthSquared()
{
return (this.X * this.X) + (this.Y * this.Y) + (this.Z * this.Z);
}
public static float Dot(Vector3 lhs, Vector3 rhs)
{
return (lhs.X * rhs.X) + (lhs.Y * rhs.Y) + (lhs.Z * rhs.Z);
}
}
class NavmeshUtils
{
// navmesh
public static bool CanSee(float x1, float y1, float z1, float x2, float y2, float z2)
{
return false;
}
public static Detour.dtNavMesh LoadNavmesh(string path)
{
var bytes = File.ReadAllBytes(path);
var start = 0;
var navmesh = Detour.NavMeshSetBuild.FromBytes(bytes, ref start);
return navmesh;
}
public static SharpNav.TiledNavMesh LoadNavmesh(TiledNavMesh navmesh, string filePath)
{
var serialiser = new SharpNav.IO.Json.NavMeshJsonSerializer();
return serialiser.Deserialize(filePath);
//return navmesh = new SharpNav.IO.Json.NavMeshJsonSerializer().Deserialize(filePath);
}
public static List<Vector3> GetPath(Detour.dtNavMesh navmesh, Vector3 start, Vector3 end)
{
var path = new Vector3[] { };
return path.ToList();
}
#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 = 2048)
{
var navMesh = zone.tiledNavMesh;
var navMeshQuery = zone.navMeshQuery;
if (navMesh == null || (startVec.X == endVec.X && startVec.Y == endVec.Y && startVec.Z == endVec.Z))
{
return null;
}
float distanceSquared = FFXIVClassic.Common.Utils.DistanceSquared(startVec.X, startVec.Y, startVec.Z, endVec.X, endVec.Y, endVec.Z);
// no point pathing if in range
if (distanceSquared < 4 && Math.Abs(startVec.Y - endVec.Y) < 1.1f)
{
return null;
}
var smoothPath = new List<Vector3>(pathSize) { };
NavQueryFilter filter = new NavQueryFilter();
NavPoint startPt, endPt;
RaycastHit hit;
PathCorridor corridor = new PathCorridor();
try
{
SharpNav.Geometry.Vector3 c = new SharpNav.Geometry.Vector3(startVec.X, startVec.Y, startVec.Z);
SharpNav.Geometry.Vector3 ep = new SharpNav.Geometry.Vector3(endVec.X, endVec.Y, endVec.Z);
SharpNav.Geometry.Vector3 e = new SharpNav.Geometry.Vector3(5, 5, 5);
navMeshQuery.FindNearestPoly(ref c, ref e, out startPt);
navMeshQuery.FindNearestPoly(ref ep, ref e, out endPt);
//calculate the overall path, which contains an array of polygon references
int MAX_POLYS = 256;
var path = new SharpNav.Pathfinding.Path();
navMeshQuery.FindPath(ref startPt, ref endPt, filter, path);
//find a smooth path over the mesh surface
int npolys = path.Count;
SharpNav.Geometry.Vector3 iterPos = new SharpNav.Geometry.Vector3();
SharpNav.Geometry.Vector3 targetPos = new SharpNav.Geometry.Vector3();
navMeshQuery.ClosestPointOnPoly(startPt.Polygon, startPt.Position, ref iterPos);
navMeshQuery.ClosestPointOnPoly(path[npolys - 1], endPt.Position, ref targetPos);
smoothPath.Add(new Vector3(iterPos));
//float STEP_SIZE = 0.70f;
float SLOP = 0.15f;
while (npolys > 0 && smoothPath.Count < smoothPath.Capacity)
{
//find location to steer towards
SharpNav.Geometry.Vector3 steerPos = new SharpNav.Geometry.Vector3();
StraightPathFlags steerPosFlag = 0;
NavPolyId steerPosRef = NavPolyId.Null;
if (!GetSteerTarget(navMeshQuery, iterPos, targetPos, SLOP, path, ref steerPos, ref steerPosFlag, ref steerPosRef))
break;
bool endOfPath = (steerPosFlag & StraightPathFlags.End) != 0 ? true : false;
bool offMeshConnection = (steerPosFlag & StraightPathFlags.OffMeshConnection) != 0 ? true : false;
//find movement delta
SharpNav.Geometry.Vector3 delta = steerPos - iterPos;
float len = (float)Math.Sqrt(SharpNav.Geometry.Vector3.Dot(delta, delta));
//if steer target is at end of path or off-mesh link
//don't move past location
if ((endOfPath || offMeshConnection) && len < stepSize)
len = 1;
else
len = stepSize / len;
SharpNav.Geometry.Vector3 moveTgt = new SharpNav.Geometry.Vector3();
VMad(ref moveTgt, iterPos, delta, len);
//move
SharpNav.Geometry.Vector3 result = new SharpNav.Geometry.Vector3();
List<NavPolyId> visited = new List<NavPolyId>(pathSize);
NavPoint startPoint = new NavPoint(path[0], iterPos);
navMeshQuery.MoveAlongSurface(ref startPoint, ref moveTgt, out result, visited);
path.FixupCorridor(visited);
npolys = path.Count;
float h = 0;
navMeshQuery.GetPolyHeight(path[0], result, ref h);
result.Y = h;
iterPos = result;
//handle end of path when close enough
if (endOfPath && InRange(iterPos, steerPos, SLOP, 1000.0f))
{
//reached end of path
iterPos = targetPos;
if (smoothPath.Count < smoothPath.Capacity)
{
smoothPath.Add(new Vector3(iterPos));
}
break;
}
//store results
if (smoothPath.Count < smoothPath.Capacity)
{
smoothPath.Add(new Vector3(iterPos));
}
}
}
catch(Exception e)
{
Program.Log.Error(e.Message);
Program.Log.Error("Start pos {0} {1} {2} end pos {3} {4} {5}", startVec.X, startVec.Y, startVec.Z, endVec.X, endVec.Y, endVec.Z);
// todo: probably log this
return new List<Vector3>() { };
}
return smoothPath;
}
/// <summary>
/// Scaled vector addition
/// </summary>
/// <param name="dest">Result</param>
/// <param name="v1">Vector 1</param>
/// <param name="v2">Vector 2</param>
/// <param name="s">Scalar</param>
private static void VMad(ref SharpNav.Geometry.Vector3 dest, SharpNav.Geometry.Vector3 v1, SharpNav.Geometry.Vector3 v2, float s)
{
dest.X = v1.X + v2.X * s;
dest.Y = v1.Y + v2.Y * s;
dest.Z = v1.Z + v2.Z * s;
}
private static bool GetSteerTarget(NavMeshQuery navMeshQuery, SharpNav.Geometry.Vector3 startPos, SharpNav.Geometry.Vector3 endPos, float minTargetDist, SharpNav.Pathfinding.Path path,
ref SharpNav.Geometry.Vector3 steerPos, ref StraightPathFlags steerPosFlag, ref NavPolyId steerPosRef)
{
StraightPath steerPath = new StraightPath();
navMeshQuery.FindStraightPath(startPos, endPos, path, steerPath, 0);
int nsteerPath = steerPath.Count;
if (nsteerPath == 0)
return false;
//find vertex far enough to steer to
int ns = 0;
while (ns < nsteerPath)
{
if ((steerPath[ns].Flags & StraightPathFlags.OffMeshConnection) != 0 ||
!InRange(steerPath[ns].Point.Position, startPos, minTargetDist, 1000.0f))
break;
ns++;
}
//failed to find good point to steer to
if (ns >= nsteerPath)
return false;
steerPos = steerPath[ns].Point.Position;
steerPos.Y = startPos.Y;
steerPosFlag = steerPath[ns].Flags;
if (steerPosFlag == StraightPathFlags.None && ns == (nsteerPath - 1))
steerPosFlag = StraightPathFlags.End; // otherwise seeks path infinitely!!!
steerPosRef = steerPath[ns].Point.Polygon;
return true;
}
private static bool InRange(SharpNav.Geometry.Vector3 v1, SharpNav.Geometry.Vector3 v2, float r, float h)
{
float dx = v2.X - v1.X;
float dy = v2.Y - v1.Y;
float dz = v2.Z - v1.Z;
return (dx * dx + dz * dz) < (r * r) && Math.Abs(dy) < h;
}
#endregion
public static Vector3 GamePosToNavmeshPos(float x, float y, float z)
{
return new Vector3(x, -z, y);
}
public static Vector3 NavmeshPosToGamePos(float x, float y, float z)
{
return new Vector3(x, z, -y);
}
}
}

View file

@ -8,6 +8,7 @@ Date: 6/19/2017 10:23:48 PM
*/ */
SET FOREIGN_KEY_CHECKS=0; SET FOREIGN_KEY_CHECKS=0;
SET autocommit=0;
-- ---------------------------- -- ----------------------------
-- Table structure for gamedata_actor_class -- Table structure for gamedata_actor_class
-- ---------------------------- -- ----------------------------
@ -8007,3 +8008,5 @@ INSERT INTO `gamedata_actor_class` VALUES ('9220405', '', '2', '0', null);
INSERT INTO `gamedata_actor_class` VALUES ('9220406', '', '2', '0', null); INSERT INTO `gamedata_actor_class` VALUES ('9220406', '', '2', '0', null);
INSERT INTO `gamedata_actor_class` VALUES ('9220407', '', '2', '0', null); INSERT INTO `gamedata_actor_class` VALUES ('9220407', '', '2', '0', null);
INSERT INTO `gamedata_actor_class` VALUES ('9220408', '', '2', '0', null); INSERT INTO `gamedata_actor_class` VALUES ('9220408', '', '2', '0', null);
COMMIT;

View file

@ -6,6 +6,7 @@ Target Host: localhost
Target Database: ffxiv_server Target Database: ffxiv_server
Date: 6/19/2017 10:24:01 PM Date: 6/19/2017 10:24:01 PM
*/ */
DROP TABLE IF EXISTS `server_spawn_locations`;
SET FOREIGN_KEY_CHECKS=0; SET FOREIGN_KEY_CHECKS=0;
-- ---------------------------- -- ----------------------------