1
Fork 0
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:
Tahir Akhlaq 2017-07-02 20:01:24 +01:00
parent 100f3ae156
commit cc1929a9fb
9 changed files with 149 additions and 25 deletions

View file

@ -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)

View file

@ -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()

View file

@ -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);
}
}
} }
} }

View file

@ -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;
} }
} }
} }

View file

@ -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;
}
} }
} }

View file

@ -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;
} }
} }
} }

View file

@ -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);
} }
} }
} }

View file

@ -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)

View file

@ -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)
{ {