diff --git a/FFXIVClassic Map Server/FFXIVClassic Map Server.csproj b/FFXIVClassic Map Server/FFXIVClassic Map Server.csproj
index a24629b3..a1c0bde5 100644
--- a/FFXIVClassic Map Server/FFXIVClassic Map Server.csproj
+++ b/FFXIVClassic Map Server/FFXIVClassic Map Server.csproj
@@ -85,14 +85,18 @@
+
+
+
+
diff --git a/FFXIVClassic Map Server/WorldManager.cs b/FFXIVClassic Map Server/WorldManager.cs
index e61e4221..271a22c9 100644
--- a/FFXIVClassic Map Server/WorldManager.cs
+++ b/FFXIVClassic Map Server/WorldManager.cs
@@ -956,8 +956,8 @@ namespace FFXIVClassic_Map_Server
{
lock (zoneList)
{
- foreach (Area area in zoneList.Values)
- area.Update(MILIS_LOOPTIME);
+ foreach (Zone zone in zoneList.Values)
+ zone.Update(MILIS_LOOPTIME);
}
}
diff --git a/FFXIVClassic Map Server/actors/Actor.cs b/FFXIVClassic Map Server/actors/Actor.cs
index 8e642e82..97e8b34e 100644
--- a/FFXIVClassic Map Server/actors/Actor.cs
+++ b/FFXIVClassic Map Server/actors/Actor.cs
@@ -152,7 +152,7 @@ namespace FFXIVClassic_Map_Server.Actors
{
updateMs = 150;
}
- if (diffTime.Milliseconds >= updateMs && hasMoved)
+ if (hasMoved && diffTime.Milliseconds >= updateMs)
{
hasMoved = (this.positionUpdates != null && this.positionUpdates.Count > 0);
if (hasMoved)
diff --git a/FFXIVClassic Map Server/actors/area/Zone.cs b/FFXIVClassic Map Server/actors/area/Zone.cs
index cb75cbd2..a45b5fd4 100644
--- a/FFXIVClassic Map Server/actors/area/Zone.cs
+++ b/FFXIVClassic Map Server/actors/area/Zone.cs
@@ -167,6 +167,7 @@ namespace FFXIVClassic_Map_Server.actors.area
{
// todo: again, this is retarded but debug stuff
var diffTime = DateTime.Now - lastUpdate;
+ base.Update(deltaTime);
// arbitrary cap
if (diffTime.Milliseconds >= 33)
diff --git a/FFXIVClassic Map Server/actors/chara/Character.cs b/FFXIVClassic Map Server/actors/chara/Character.cs
index 92262271..755ab6f4 100644
--- a/FFXIVClassic Map Server/actors/chara/Character.cs
+++ b/FFXIVClassic Map Server/actors/chara/Character.cs
@@ -228,6 +228,13 @@ namespace FFXIVClassic_Map_Server.Actors
// todo: other ai helpers
// time elapsed since last ai update
+
+ if (aiContainer != null)
+ {
+ this.aiContainer.Update(DateTime.Now);
+ }
+
+ /*
var diffTime = (DateTime.Now - lastAiUpdate);
if (this is Player)
@@ -386,7 +393,9 @@ namespace FFXIVClassic_Map_Server.Actors
lastAiUpdate = DateTime.Now;
}
}
+ */
}
+
}
}
diff --git a/FFXIVClassic Map Server/actors/chara/ai/AIContainer.cs b/FFXIVClassic Map Server/actors/chara/ai/AIContainer.cs
index f0217a6c..f5d0bcf3 100644
--- a/FFXIVClassic Map Server/actors/chara/ai/AIContainer.cs
+++ b/FFXIVClassic Map Server/actors/chara/ai/AIContainer.cs
@@ -6,27 +6,118 @@ using System.Threading.Tasks;
using FFXIVClassic_Map_Server.Actors;
using FFXIVClassic_Map_Server.actors.chara.ai.state;
using FFXIVClassic_Map_Server.actors.chara.ai.controllers;
+using FFXIVClassic_Map_Server.packets.send.actor;
// port of ai code in dsp by kjLotus
namespace FFXIVClassic_Map_Server.actors.chara.ai
{
// todo: actually implement stuff
+ // todo: use spell/ability/ws/mobskill objects instead of looking up ids
class AIContainer
{
private Character owner;
private Controller controller;
- private List states;
+ private Stack states;
private DateTime latestUpdate;
private DateTime prevUpdate;
+ private PathFind pathFind;
+ private TargetFind targetFind;
- public AIContainer(Actors.Character actor)
+ public AIContainer(Character actor, Controller controller, PathFind pathFind, TargetFind targetFind)
{
this.owner = actor;
+ this.states = new Stack();
+ this.controller = controller;
+ this.pathFind = pathFind;
+ this.targetFind = targetFind;
+ latestUpdate = DateTime.Now;
+ prevUpdate = latestUpdate;
+ }
+
+ public void Update(DateTime tick)
+ {
+ prevUpdate = latestUpdate;
+ latestUpdate = tick;
+
+ // todo: trigger listeners
+
+ // todo: action queues
+
+
+ }
+
+ public void Engage(Character target)
+ {
+ if (controller != null)
+ controller.Engage(target);
+ else
+ InternalEngage(target);
+ }
+
+ public bool IsEngaged()
+ {
+ // todo: check this is legit
+ return owner.currentMainState == SetActorStatePacket.MAIN_STATE_ACTIVE;
+ }
+
+ public void Disengage()
+ {
+ if (controller != null)
+ controller.Disengage();
+ else
+ InternalDisengage();
+ }
+
+ public void Cast(Character target, uint spellId)
+ {
+
}
public void ChangeController(Controller controller)
{
this.controller = controller;
}
+
+ public bool CanChangeState()
+ {
+ return states.Count == 0 || states.First().CanInterrupt();
+ }
+
+ public void ChangeState(State state)
+ {
+ if (states.Count < 10)
+ {
+ states.Push(state);
+ }
+ else
+ {
+ throw new Exception("shit");
+ }
+ }
+
+ public void InternalEngage(Character target)
+ {
+
+ }
+
+ public void InternalDisengage()
+ {
+
+ }
+
+ public void InternalCast(Character target, uint spellId)
+ {
+
+ }
+
+ public void InternalWeaponSkill(Character target, uint weaponSkillId)
+ {
+
+ }
+
+ public void InternalMobSkill(Character target, uint mobSkillId)
+ {
+
+ }
}
}
diff --git a/FFXIVClassic Map Server/actors/chara/ai/ActionQueue.cs b/FFXIVClassic Map Server/actors/chara/ai/ActionQueue.cs
new file mode 100644
index 00000000..b69caed8
--- /dev/null
+++ b/FFXIVClassic Map Server/actors/chara/ai/ActionQueue.cs
@@ -0,0 +1,49 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using FFXIVClassic_Map_Server.Actors;
+using MoonSharp;
+using MoonSharp.Interpreter;
+
+namespace FFXIVClassic_Map_Server.actors.chara.ai
+{
+ class Action
+ {
+ public DateTime startTime;
+ public uint durationMs;
+ public bool checkState;
+ // todo: lua function
+ Script script;
+ }
+ class ActionQueue
+ {
+ private Character owner;
+ private Queue actionQueue;
+ private Queue timerQueue;
+
+ public bool IsEmpty { get { return actionQueue.Count > 0 || timerQueue.Count > 0; } }
+
+ public ActionQueue(Character owner)
+ {
+
+ }
+
+ public void PushAction(Action action)
+ {
+
+ }
+
+ public void Update(DateTime tick)
+ {
+
+ }
+
+ public void HandleAction(Action action)
+ {
+
+ }
+
+ }
+}
diff --git a/FFXIVClassic Map Server/actors/chara/ai/PathFind.cs b/FFXIVClassic Map Server/actors/chara/ai/PathFind.cs
new file mode 100644
index 00000000..80a6a41c
--- /dev/null
+++ b/FFXIVClassic Map Server/actors/chara/ai/PathFind.cs
@@ -0,0 +1,19 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using FFXIVClassic_Map_Server.Actors;
+
+namespace FFXIVClassic_Map_Server.actors.chara.ai
+{
+ class PathFind
+ {
+ private Character owner;
+
+ public PathFind(Character owner)
+ {
+ this.owner = owner;
+ }
+ }
+}
diff --git a/FFXIVClassic Map Server/actors/chara/ai/TargetFind.cs b/FFXIVClassic Map Server/actors/chara/ai/TargetFind.cs
new file mode 100644
index 00000000..7a53177d
--- /dev/null
+++ b/FFXIVClassic Map Server/actors/chara/ai/TargetFind.cs
@@ -0,0 +1,19 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using FFXIVClassic_Map_Server.Actors;
+
+namespace FFXIVClassic_Map_Server.actors.chara.ai
+{
+ class TargetFind
+ {
+ private Character owner;
+
+ public TargetFind(Character owner)
+ {
+ this.owner = owner;
+ }
+ }
+}
diff --git a/FFXIVClassic Map Server/actors/chara/ai/controllers/Controller.cs b/FFXIVClassic Map Server/actors/chara/ai/controllers/Controller.cs
index 87bc3391..3f237d9e 100644
--- a/FFXIVClassic Map Server/actors/chara/ai/controllers/Controller.cs
+++ b/FFXIVClassic Map Server/actors/chara/ai/controllers/Controller.cs
@@ -3,10 +3,67 @@ using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
+using FFXIVClassic_Map_Server.Actors;
namespace FFXIVClassic_Map_Server.actors.chara.ai.controllers
{
- class Controller
+ abstract class Controller
{
+ protected Character owner;
+
+ protected DateTime lastUpdate;
+ protected bool canUpdate = true;
+ protected bool autoAttackEnabled = true;
+ protected bool castingEnabled = true;
+ protected bool weaponSkillEnabled = true;
+ protected PathFind pathFind;
+ protected TargetFind targetFind;
+
+ public abstract void Update(DateTime tick);
+ public abstract bool Engage(Character target);
+ public abstract bool Disengage();
+ public abstract void Cast(Character target, uint spellId);
+ public virtual void WeaponSkill(Character target, uint weaponSkillId) { }
+ public virtual void MobSkill(Character target, uint mobSkillId) { }
+ public abstract void Ability(Character target, uint abilityId);
+ public abstract void RangedAttack(Character target);
+ public virtual void Spawn() { }
+ public virtual void Despawn() { }
+
+
+ public virtual void ChangeTarget(Character target)
+ {
+ owner.aiContainer.InternalEngage(target);
+ }
+
+ public bool IsAutoAttackEnabled()
+ {
+ return autoAttackEnabled;
+ }
+
+ public void SetAutoAttackEnabled(bool isEnabled)
+ {
+ autoAttackEnabled = isEnabled;
+ }
+
+ public bool IsCastingEnabled()
+ {
+ return castingEnabled;
+ }
+
+ public void SetCastingEnabled(bool isEnabled)
+ {
+ castingEnabled = isEnabled;
+ }
+
+ public bool IsWeaponSkillEnabled()
+ {
+ return weaponSkillEnabled;
+ }
+
+ public void SetWeaponSkillEnabled(bool isEnabled)
+ {
+ weaponSkillEnabled = isEnabled;
+ }
}
}
diff --git a/FFXIVClassic Map Server/actors/chara/ai/controllers/MobController.cs b/FFXIVClassic Map Server/actors/chara/ai/controllers/MobController.cs
index c8a1ba6c..b6da397f 100644
--- a/FFXIVClassic Map Server/actors/chara/ai/controllers/MobController.cs
+++ b/FFXIVClassic Map Server/actors/chara/ai/controllers/MobController.cs
@@ -3,10 +3,59 @@ using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
+using FFXIVClassic_Map_Server.Actors;
namespace FFXIVClassic_Map_Server.actors.chara.ai.controllers
{
class MobController : Controller
{
+ public MobController(Character owner)
+ {
+ this.owner = owner;
+ this.lastUpdate = DateTime.Now;
+ }
+
+ public override void Update(DateTime tick)
+ {
+
+ }
+
+ public override bool Engage(Character target)
+ {
+ // todo: check distance, last swing time, status effects
+ return true;
+ }
+
+ private bool TryEngage(Character target)
+ {
+ // todo:
+ return true;
+ }
+
+ public override bool Disengage()
+ {
+ // todo:
+ return true;
+ }
+
+ public override void Cast(Character target, uint spellId)
+ {
+
+ }
+
+ public override void Ability(Character target, uint abilityId)
+ {
+
+ }
+
+ public override void RangedAttack(Character target)
+ {
+
+ }
+
+ public override void MobSkill(Character target, uint mobSkillId)
+ {
+
+ }
}
}
diff --git a/FFXIVClassic Map Server/actors/chara/ai/controllers/PlayerController.cs b/FFXIVClassic Map Server/actors/chara/ai/controllers/PlayerController.cs
index b067dc58..b920c690 100644
--- a/FFXIVClassic Map Server/actors/chara/ai/controllers/PlayerController.cs
+++ b/FFXIVClassic Map Server/actors/chara/ai/controllers/PlayerController.cs
@@ -3,10 +3,53 @@ using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
+using FFXIVClassic_Map_Server.Actors;
namespace FFXIVClassic_Map_Server.actors.chara.ai.controllers
{
class PlayerController : Controller
{
+ public PlayerController(Character owner)
+ {
+ this.owner = owner;
+ this.lastUpdate = DateTime.Now;
+ }
+
+ public override void Update(DateTime tick)
+ {
+
+ }
+
+ public override void ChangeTarget(Character target)
+ {
+ base.ChangeTarget(target);
+ }
+
+ public override bool Engage(Character target)
+ {
+ // todo: check distance, last swing time, status effects
+ return true;
+ }
+
+ public override bool Disengage()
+ {
+ // todo:
+ return true;
+ }
+
+ public override void Cast(Character target, uint spellId)
+ {
+
+ }
+
+ public override void Ability(Character target, uint abilityId)
+ {
+
+ }
+
+ public override void RangedAttack(Character target)
+ {
+
+ }
}
}
diff --git a/FFXIVClassic Map Server/actors/chara/npc/Mob.cs b/FFXIVClassic Map Server/actors/chara/npc/Mob.cs
new file mode 100644
index 00000000..a24ba397
--- /dev/null
+++ b/FFXIVClassic Map Server/actors/chara/npc/Mob.cs
@@ -0,0 +1,24 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using FFXIVClassic_Map_Server.Actors;
+using FFXIVClassic_Map_Server.actors.chara.npc;
+using FFXIVClassic_Map_Server.actors;
+using FFXIVClassic_Map_Server.actors.chara;
+using FFXIVClassic_Map_Server.actors.chara.ai;
+using FFXIVClassic_Map_Server.actors.chara.ai.controllers;
+
+namespace FFXIVClassic_Map_Server.Actors
+{
+ class Mob : Npc
+ {
+ public Mob(int actorNumber, ActorClass actorClass, string uniqueId, Area spawnedArea, float posX, float posY, float posZ, float rot,
+ ushort actorState, uint animationId, string customDisplayName)
+ : base(actorNumber, actorClass, uniqueId, spawnedArea, posX, posY, posZ, rot, actorState, animationId, customDisplayName)
+ {
+ this.aiContainer = new AIContainer(this, new MobController(this), new PathFind(this), new TargetFind(this));
+ }
+ }
+}
diff --git a/FFXIVClassic Map Server/actors/chara/npc/Npc.cs b/FFXIVClassic Map Server/actors/chara/npc/Npc.cs
index d7a94eee..94f37af2 100644
--- a/FFXIVClassic Map Server/actors/chara/npc/Npc.cs
+++ b/FFXIVClassic Map Server/actors/chara/npc/Npc.cs
@@ -17,6 +17,7 @@ using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
+using FFXIVClassic_Map_Server.actors.chara.ai;
namespace FFXIVClassic_Map_Server.Actors
{
@@ -84,8 +85,7 @@ namespace FFXIVClassic_Map_Server.Actors
isStatic = true;
}
}
-
- GenerateActorName((int)actorNumber);
+ this.aiContainer = new AIContainer(this, null, new PathFind(this), new TargetFind(this));
}
public Npc(int actorNumber, ActorClass actorClass, string uniqueId, Area spawnedArea, float posX, float posY, float posZ, float rot, uint layout, uint instance)
diff --git a/FFXIVClassic Map Server/actors/chara/player/Player.cs b/FFXIVClassic Map Server/actors/chara/player/Player.cs
index 3e700d63..a63dc7cc 100644
--- a/FFXIVClassic Map Server/actors/chara/player/Player.cs
+++ b/FFXIVClassic Map Server/actors/chara/player/Player.cs
@@ -18,6 +18,8 @@ using FFXIVClassic_Map_Server.packets.send.actor.inventory;
using FFXIVClassic_Map_Server.actors.group;
using FFXIVClassic_Map_Server.packets.send.group;
using FFXIVClassic_Map_Server.packets.WorldPackets.Send.Group;
+using FFXIVClassic_Map_Server.actors.chara.ai;
+using FFXIVClassic_Map_Server.actors.chara.ai.controllers;
namespace FFXIVClassic_Map_Server.Actors
{
@@ -247,6 +249,7 @@ namespace FFXIVClassic_Map_Server.Actors
Database.LoadPlayerCharacter(this);
lastPlayTimeUpdate = Utils.UnixTimeStampUTC();
+ this.aiContainer = new AIContainer(this, new PlayerController(this), null, new TargetFind(this));
}
public List Create0x132Packets(uint playerActorId)