mirror of
https://bitbucket.org/Ioncannon/project-meteor-server.git
synced 2025-04-20 11:47:48 +00:00
moved getpath crap to pathfinding (or should i keep it in actor?)
- stubbed some more crap
This commit is contained in:
parent
100f3ae156
commit
cc1929a9fb
9 changed files with 149 additions and 25 deletions
|
@ -64,12 +64,15 @@ namespace FFXIVClassic_Map_Server.Actors
|
||||||
public DateTime lastAiUpdate;
|
public DateTime lastAiUpdate;
|
||||||
|
|
||||||
public AIContainer aiContainer;
|
public AIContainer aiContainer;
|
||||||
|
public StatusEffects statusEffects;
|
||||||
|
|
||||||
public Character(uint actorID) : base(actorID)
|
public Character(uint actorID) : base(actorID)
|
||||||
{
|
{
|
||||||
//Init timer array to "notimer"
|
//Init timer array to "notimer"
|
||||||
for (int i = 0; i < charaWork.statusShownTime.Length; i++)
|
for (int i = 0; i < charaWork.statusShownTime.Length; i++)
|
||||||
charaWork.statusShownTime[i] = 0xFFFFFFFF;
|
charaWork.statusShownTime[i] = 0xFFFFFFFF;
|
||||||
|
|
||||||
|
this.statusEffects = new StatusEffects(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
public SubPacket CreateAppearancePacket(uint playerActorId)
|
public SubPacket CreateAppearancePacket(uint playerActorId)
|
||||||
|
|
|
@ -45,6 +45,14 @@ namespace FFXIVClassic_Map_Server.actors.chara.ai
|
||||||
|
|
||||||
// todo: action queues
|
// todo: action queues
|
||||||
controller?.Update(tick);
|
controller?.Update(tick);
|
||||||
|
State currState;
|
||||||
|
while (states.Count > 0 && (currState = states.Peek()).Update(tick))
|
||||||
|
{
|
||||||
|
if (currState == GetCurrentState())
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void CheckCompletedStates()
|
public void CheckCompletedStates()
|
||||||
|
|
|
@ -4,6 +4,10 @@ using System.Linq;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using FFXIVClassic_Map_Server.Actors;
|
using FFXIVClassic_Map_Server.Actors;
|
||||||
|
using FFXIVClassic_Map_Server;
|
||||||
|
using FFXIVClassic_Map_Server.utils;
|
||||||
|
using FFXIVClassic.Common;
|
||||||
|
using FFXIVClassic_Map_Server.actors.area;
|
||||||
|
|
||||||
namespace FFXIVClassic_Map_Server.actors.chara.ai
|
namespace FFXIVClassic_Map_Server.actors.chara.ai
|
||||||
{
|
{
|
||||||
|
@ -15,5 +19,49 @@ namespace FFXIVClassic_Map_Server.actors.chara.ai
|
||||||
{
|
{
|
||||||
this.owner = owner;
|
this.owner = owner;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// todo: is this class even needed?
|
||||||
|
public void PathTo(float x, float y, float z, float stepSize = 0.70f, int maxPath = 40, float polyRadius = 0.0f)
|
||||||
|
{
|
||||||
|
var pos = new Vector3(owner.positionX, owner.positionY, owner.positionZ);
|
||||||
|
var dest = new Vector3(x, y, z);
|
||||||
|
var zone = (Zone)owner.GetZone();
|
||||||
|
var sw = new System.Diagnostics.Stopwatch();
|
||||||
|
sw.Start();
|
||||||
|
|
||||||
|
var path = NavmeshUtils.GetPath(zone, pos, dest, stepSize, maxPath, polyRadius);
|
||||||
|
|
||||||
|
if (path != null)
|
||||||
|
{
|
||||||
|
if (owner.oldPositionX == 0.0f && owner.oldPositionY == 0.0f && owner.oldPositionZ == 0.0f)
|
||||||
|
{
|
||||||
|
owner.oldPositionX = owner.positionX;
|
||||||
|
owner.oldPositionY = owner.positionY;
|
||||||
|
owner.oldPositionZ = owner.positionZ;
|
||||||
|
}
|
||||||
|
|
||||||
|
// todo: something went wrong
|
||||||
|
if (path.Count == 0)
|
||||||
|
{
|
||||||
|
owner.positionX = owner.oldPositionX;
|
||||||
|
owner.positionY = owner.oldPositionY;
|
||||||
|
owner.positionZ = owner.oldPositionZ;
|
||||||
|
}
|
||||||
|
|
||||||
|
owner.positionUpdates = path;
|
||||||
|
|
||||||
|
owner.hasMoved = true;
|
||||||
|
owner.isAtSpawn = false;
|
||||||
|
|
||||||
|
sw.Stop();
|
||||||
|
zone.pathCalls++;
|
||||||
|
zone.pathCallTime += sw.ElapsedMilliseconds;
|
||||||
|
|
||||||
|
if (path.Count == 1)
|
||||||
|
Program.Log.Info($"mypos: {owner.positionX} {owner.positionY} {owner.positionZ} | targetPos: {x} {y} {z} | step {stepSize} | maxPath {maxPath} | polyRadius {polyRadius}");
|
||||||
|
|
||||||
|
Program.Log.Error("[{0}][{1}] Created {2} points in {3} milliseconds", owner.actorId, owner.actorName, path.Count, sw.ElapsedMilliseconds);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,7 +4,8 @@ using System.Linq;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using FFXIVClassic_Map_Server.Actors;
|
using FFXIVClassic_Map_Server.Actors;
|
||||||
|
using FFXIVClassic_Map_Server.packets.send.actor;
|
||||||
|
using FFXIVClassic_Map_Server.packets.send.actor.battle;
|
||||||
namespace FFXIVClassic_Map_Server.actors.chara.ai.state
|
namespace FFXIVClassic_Map_Server.actors.chara.ai.state
|
||||||
{
|
{
|
||||||
class AttackState : State
|
class AttackState : State
|
||||||
|
@ -21,24 +22,84 @@ namespace FFXIVClassic_Map_Server.actors.chara.ai.state
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void Update(DateTime time)
|
public override bool Update(DateTime tick)
|
||||||
{
|
{
|
||||||
|
TryInterrupt();
|
||||||
|
|
||||||
|
if (interrupt)
|
||||||
|
{
|
||||||
|
OnInterrupt();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// todo: check weapon delay/haste etc and use that
|
||||||
|
if ((tick - startTime).Milliseconds >= 0)
|
||||||
|
{
|
||||||
|
OnComplete();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void OnInterrupt()
|
public override void OnInterrupt()
|
||||||
{
|
{
|
||||||
|
// todo: send paralyzed/sleep message etc.
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void OnComplete()
|
public override void OnComplete()
|
||||||
{
|
{
|
||||||
|
var damage = FFXIVClassic_Map_Server.actors.chara.ai.utils.AttackUtils.CalculateDamage(owner, target);
|
||||||
|
|
||||||
|
lua.LuaEngine.GetInstance().CallLuaFunction(owner, target, "onAttack", false, damage);
|
||||||
|
|
||||||
|
//var packet = BattleAction1Packet.BuildPacket(owner.actorId, target.actorId);
|
||||||
|
|
||||||
|
// todo: find a better place to put this?
|
||||||
|
if (owner.GetState() != SetActorStatePacket.MAIN_STATE_ACTIVE)
|
||||||
|
owner.ChangeState(SetActorStatePacket.MAIN_STATE_ACTIVE);
|
||||||
|
|
||||||
isCompleted = true;
|
isCompleted = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void TryInterrupt()
|
public override void TryInterrupt()
|
||||||
{
|
{
|
||||||
|
if (owner.statusEffects.HasStatusEffectsByFlag((uint)StatusEffectFlags.PreventAction))
|
||||||
|
{
|
||||||
|
// todo: sometimes paralyze can let you attack, get random percentage of actually letting you attack
|
||||||
|
var list = owner.statusEffects.GetStatusEffectsByFlag((uint)StatusEffectFlags.PreventAction);
|
||||||
|
uint effectId = 0;
|
||||||
|
if (list.Count > 0)
|
||||||
|
{
|
||||||
|
// todo: actually check proc rate/random chance of whatever effect
|
||||||
|
effectId = list[0].GetEffectId();
|
||||||
|
}
|
||||||
|
this.errorPacket = BattleActionX01Packet.BuildPacket(target.actorId, owner.actorId, target.actorId, 0, effectId, 0, 0, 0, 0);
|
||||||
|
owner.zone.BroadcastPacketAroundActor(owner, errorPacket);
|
||||||
|
errorPacket = null;
|
||||||
|
interrupt = true;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
else if (target.zone != owner.zone)
|
||||||
|
{
|
||||||
|
interrupt = true;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
else if (owner.aiContainer.IsDead())
|
||||||
|
{
|
||||||
|
// todo: this really shouldnt ever hit since we'd be clearing states on death
|
||||||
|
interrupt = true;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
interrupt = CanAttack();
|
||||||
|
}
|
||||||
|
|
||||||
|
private bool CanAttack()
|
||||||
|
{
|
||||||
|
if (target.aiContainer.IsDead())
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -30,7 +30,7 @@ namespace FFXIVClassic_Map_Server.actors.chara.ai.state
|
||||||
this.interrupt = false;
|
this.interrupt = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public virtual void Update(DateTime tick) { }
|
public virtual bool Update(DateTime tick) { return true; }
|
||||||
public virtual void OnStart() { }
|
public virtual void OnStart() { }
|
||||||
public virtual void OnInterrupt() { }
|
public virtual void OnInterrupt() { }
|
||||||
public virtual void OnComplete() { isCompleted = true; }
|
public virtual void OnComplete() { isCompleted = true; }
|
||||||
|
@ -54,5 +54,10 @@ namespace FFXIVClassic_Map_Server.actors.chara.ai.state
|
||||||
return isCompleted;
|
return isCompleted;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void ChangeTarget(Character target)
|
||||||
|
{
|
||||||
|
this.target = target;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,7 +16,8 @@ namespace FFXIVClassic_Map_Server.actors.chara.ai.utils
|
||||||
}
|
}
|
||||||
public static int CalculateBaseDamage(Character attacker, Character defender)
|
public static int CalculateBaseDamage(Character attacker, Character defender)
|
||||||
{
|
{
|
||||||
return 0;
|
// todo: actually calculate damage
|
||||||
|
return Program.Random.Next(10) * 10;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -16,7 +16,6 @@ namespace FFXIVClassic_Map_Server.Actors
|
||||||
class Mob : Npc
|
class Mob : Npc
|
||||||
{
|
{
|
||||||
public HateContainer hateContainer;
|
public HateContainer hateContainer;
|
||||||
public StatusEffects statusEffects;
|
|
||||||
|
|
||||||
public Mob(int actorNumber, ActorClass actorClass, string uniqueId, Area spawnedArea, float posX, float posY, float posZ, float rot,
|
public Mob(int actorNumber, ActorClass actorClass, string uniqueId, Area spawnedArea, float posX, float posY, float posZ, float rot,
|
||||||
ushort actorState, uint animationId, string customDisplayName)
|
ushort actorState, uint animationId, string customDisplayName)
|
||||||
|
@ -25,7 +24,6 @@ namespace FFXIVClassic_Map_Server.Actors
|
||||||
this.aiContainer = new AIContainer(this, new MobController(this), new PathFind(this), new TargetFind(this));
|
this.aiContainer = new AIContainer(this, new MobController(this), new PathFind(this), new TargetFind(this));
|
||||||
this.currentSubState = SetActorStatePacket.SUB_STATE_MONSTER;
|
this.currentSubState = SetActorStatePacket.SUB_STATE_MONSTER;
|
||||||
this.hateContainer = new HateContainer(this);
|
this.hateContainer = new HateContainer(this);
|
||||||
this.statusEffects = new StatusEffects(this);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -141,8 +141,6 @@ namespace FFXIVClassic_Map_Server.Actors
|
||||||
|
|
||||||
public Session playerSession;
|
public Session playerSession;
|
||||||
|
|
||||||
public StatusEffects statusEffects;
|
|
||||||
|
|
||||||
public Player(Session cp, uint actorID) : base(actorID)
|
public Player(Session cp, uint actorID) : base(actorID)
|
||||||
{
|
{
|
||||||
playerSession = cp;
|
playerSession = cp;
|
||||||
|
@ -253,7 +251,6 @@ namespace FFXIVClassic_Map_Server.Actors
|
||||||
lastPlayTimeUpdate = Utils.UnixTimeStampUTC();
|
lastPlayTimeUpdate = Utils.UnixTimeStampUTC();
|
||||||
|
|
||||||
this.aiContainer = new AIContainer(this, new PlayerController(this), null, new TargetFind(this));
|
this.aiContainer = new AIContainer(this, new PlayerController(this), null, new TargetFind(this));
|
||||||
this.statusEffects = new StatusEffects(this);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<SubPacket> Create0x132Packets(uint playerActorId)
|
public List<SubPacket> Create0x132Packets(uint playerActorId)
|
||||||
|
|
|
@ -320,40 +320,41 @@ namespace FFXIVClassic_Map_Server.lua
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void CallLuaFunction(Player player, Actor target, string funcName, bool optional, params object[] args)
|
public void CallLuaFunction(Actor actor, Actor target, string funcName, bool optional, params object[] args)
|
||||||
{
|
{
|
||||||
|
bool isPlayer = actor is Player;
|
||||||
//Need a seperate case for NPCs cause that child/parent thing.
|
//Need a seperate case for NPCs cause that child/parent thing.
|
||||||
if (target is Npc)
|
if (target is Npc && isPlayer)
|
||||||
{
|
{
|
||||||
CallLuaFunctionNpc(player, (Npc)target, funcName, optional, args);
|
CallLuaFunctionNpc((Player)actor, (Npc)target, funcName, optional, args);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
object[] args2 = new object[args.Length + 2];
|
object[] args2 = new object[args.Length + 2];
|
||||||
Array.Copy(args, 0, args2, 2, args.Length);
|
Array.Copy(args, 0, args2, 2, args.Length);
|
||||||
args2[0] = player;
|
args2[0] = actor;
|
||||||
args2[1] = target;
|
args2[1] = target;
|
||||||
|
|
||||||
string luaPath = GetScriptPath(target);
|
string luaPath = GetScriptPath(target);
|
||||||
LuaScript script = LoadScript(luaPath);
|
LuaScript script = LoadScript(luaPath);
|
||||||
if (script != null)
|
if (script != null)
|
||||||
{
|
{
|
||||||
if (!script.Globals.Get(funcName).IsNil())
|
if (!script.Globals.Get(funcName).IsNil() && isPlayer)
|
||||||
{
|
{
|
||||||
Coroutine coroutine = script.CreateCoroutine(script.Globals[funcName]).Coroutine;
|
Coroutine coroutine = script.CreateCoroutine(script.Globals[funcName]).Coroutine;
|
||||||
DynValue value = coroutine.Resume(args2);
|
DynValue value = coroutine.Resume(args2);
|
||||||
ResolveResume(player, coroutine, value);
|
ResolveResume((Player)actor, coroutine, value);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (!optional)
|
if (!optional)
|
||||||
SendError(player, String.Format("Could not find function '{0}' for actor {1}.", funcName, target.GetName()));
|
SendError((Player)actor, String.Format("Could not find function '{0}' for actor {1}.", funcName, target.GetName()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (!(target is Area) && !optional)
|
if (!(target is Area) && !optional && isPlayer)
|
||||||
SendError(player, String.Format("Could not find script for actor {0}.", target.GetName()));
|
SendError((Player)actor, String.Format("Could not find script for actor {0}.", target.GetName()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -372,16 +373,18 @@ namespace FFXIVClassic_Map_Server.lua
|
||||||
CallLuaFunction(player, target, "onEventStarted", false, LuaUtils.CreateLuaParamObjectList(lparams));
|
CallLuaFunction(player, target, "onEventStarted", false, LuaUtils.CreateLuaParamObjectList(lparams));
|
||||||
}
|
}
|
||||||
|
|
||||||
private DynValue ResolveResume(Player player, Coroutine coroutine, DynValue value)
|
private DynValue ResolveResume(Actor actor, Coroutine coroutine, DynValue value)
|
||||||
{
|
{
|
||||||
|
var isPlayer = actor is Player;
|
||||||
|
|
||||||
if (value == null || value.IsVoid())
|
if (value == null || value.IsVoid())
|
||||||
return value;
|
return value;
|
||||||
|
|
||||||
if (value.String != null && value.String.Equals("_WAIT_EVENT"))
|
if (isPlayer && value.String != null && value.String.Equals("_WAIT_EVENT"))
|
||||||
{
|
{
|
||||||
GetInstance().AddWaitEventCoroutine(player, coroutine);
|
GetInstance().AddWaitEventCoroutine((Player)actor, coroutine);
|
||||||
}
|
}
|
||||||
else if (value.Tuple != null && value.Tuple.Length >= 1 && value.Tuple[0].String != null)
|
else if (isPlayer && value.Tuple != null && value.Tuple.Length >= 1 && value.Tuple[0].String != null)
|
||||||
{
|
{
|
||||||
switch (value.Tuple[0].String)
|
switch (value.Tuple[0].String)
|
||||||
{
|
{
|
||||||
|
|
Loading…
Add table
Reference in a new issue