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 AIContainer aiContainer;
public StatusEffects statusEffects;
public Character(uint actorID) : base(actorID)
{
//Init timer array to "notimer"
for (int i = 0; i < charaWork.statusShownTime.Length; i++)
charaWork.statusShownTime[i] = 0xFFFFFFFF;
this.statusEffects = new StatusEffects(this);
}
public SubPacket CreateAppearancePacket(uint playerActorId)

View file

@ -45,6 +45,14 @@ namespace FFXIVClassic_Map_Server.actors.chara.ai
// todo: action queues
controller?.Update(tick);
State currState;
while (states.Count > 0 && (currState = states.Peek()).Update(tick))
{
if (currState == GetCurrentState())
{
}
}
}
public void CheckCompletedStates()

View file

@ -4,6 +4,10 @@ using System.Linq;
using System.Text;
using System.Threading.Tasks;
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
{
@ -15,5 +19,49 @@ namespace FFXIVClassic_Map_Server.actors.chara.ai
{
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.Threading.Tasks;
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
{
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()
{
// todo: send paralyzed/sleep message etc.
}
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;
}
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;
}
public virtual void Update(DateTime tick) { }
public virtual bool Update(DateTime tick) { return true; }
public virtual void OnStart() { }
public virtual void OnInterrupt() { }
public virtual void OnComplete() { isCompleted = true; }
@ -54,5 +54,10 @@ namespace FFXIVClassic_Map_Server.actors.chara.ai.state
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)
{
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
{
public HateContainer hateContainer;
public StatusEffects statusEffects;
public Mob(int actorNumber, ActorClass actorClass, string uniqueId, Area spawnedArea, float posX, float posY, float posZ, float rot,
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.currentSubState = SetActorStatePacket.SUB_STATE_MONSTER;
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 StatusEffects statusEffects;
public Player(Session cp, uint actorID) : base(actorID)
{
playerSession = cp;
@ -253,7 +251,6 @@ namespace FFXIVClassic_Map_Server.Actors
lastPlayTimeUpdate = Utils.UnixTimeStampUTC();
this.aiContainer = new AIContainer(this, new PlayerController(this), null, new TargetFind(this));
this.statusEffects = new StatusEffects(this);
}
public List<SubPacket> Create0x132Packets(uint playerActorId)

View file

@ -320,40 +320,41 @@ namespace FFXIVClassic_Map_Server.lua
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.
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;
}
object[] args2 = new object[args.Length + 2];
Array.Copy(args, 0, args2, 2, args.Length);
args2[0] = player;
args2[0] = actor;
args2[1] = target;
string luaPath = GetScriptPath(target);
LuaScript script = LoadScript(luaPath);
if (script != null)
{
if (!script.Globals.Get(funcName).IsNil())
if (!script.Globals.Get(funcName).IsNil() && isPlayer)
{
Coroutine coroutine = script.CreateCoroutine(script.Globals[funcName]).Coroutine;
DynValue value = coroutine.Resume(args2);
ResolveResume(player, coroutine, value);
ResolveResume((Player)actor, coroutine, value);
}
else
{
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
{
if (!(target is Area) && !optional)
SendError(player, String.Format("Could not find script for actor {0}.", target.GetName()));
if (!(target is Area) && !optional && isPlayer)
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));
}
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())
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)
{