mirror of
https://bitbucket.org/Ioncannon/project-meteor-server.git
synced 2025-05-20 08:26:59 -04:00
fixed auto attack messing up cast anim
- fixed auto attack anim for mobs (<3 u ion) - added hotbar timer updates (<3 u azia) - fixed actor block bug - cleaned up substate retardation - fixed some targetfind issues - added despawn state - added messages for in progress commands - added fields for aoe target, range, battleAnimation to server_battle_commands table
This commit is contained in:
@@ -20,7 +20,7 @@ namespace FFXIVClassic_Map_Server.actors.chara.ai.state
|
||||
this.startTime = DateTime.Now;
|
||||
|
||||
owner.ChangeState(SetActorStatePacket.MAIN_STATE_ACTIVE);
|
||||
owner.aiContainer.ChangeTarget(target);
|
||||
ChangeTarget(target);
|
||||
attackTime = startTime;
|
||||
owner.aiContainer.pathFind?.Clear();
|
||||
// todo: should handle everything here instead of on next tick..
|
||||
@@ -42,12 +42,13 @@ namespace FFXIVClassic_Map_Server.actors.chara.ai.state
|
||||
return true;
|
||||
}
|
||||
*/
|
||||
if (target == null || owner.target != target || owner.target?.actorId != owner.currentLockedTarget)
|
||||
owner.aiContainer.ChangeTarget(target = owner.zone.FindActorInArea(owner.currentLockedTarget == 0xC0000000 ? owner.currentTarget : owner.currentLockedTarget) as Character);
|
||||
|
||||
if ((target == null || owner.target != target || owner.target?.actorId != owner.currentLockedTarget) && owner.isAutoAttackEnabled)
|
||||
owner.aiContainer.ChangeTarget(target = owner.zone.FindActorInArea<Character>(owner.currentLockedTarget));
|
||||
|
||||
if (target == null || target.IsDead())
|
||||
{
|
||||
if (owner.currentSubState == SetActorStatePacket.SUB_STATE_MONSTER)
|
||||
if (owner is BattleNpc)
|
||||
target = ((BattleNpc)owner).hateContainer.GetMostHatedTarget();
|
||||
}
|
||||
else
|
||||
@@ -110,7 +111,7 @@ namespace FFXIVClassic_Map_Server.actors.chara.ai.state
|
||||
|
||||
owner.OnAttack(this, action, ref errorResult);
|
||||
// handle paralyze/intimidate/sleep/whatever in character thing
|
||||
owner.DoBattleAction((ushort)BattleActionX01PacketCommand.Attack, 0x19001000, errorResult == null ? action : errorResult);
|
||||
owner.DoBattleAction((ushort)BattleActionX01PacketCommand.Attack, action.animation, errorResult == null ? action : errorResult);
|
||||
|
||||
//this.errorPacket = BattleActionX01Packet.BuildPacket(target.actorId, owner.actorId, target.actorId, 0, effectId, 0, (ushort)BattleActionX01PacketCommand.Attack, (ushort)damage, 0);
|
||||
}
|
||||
@@ -140,11 +141,17 @@ namespace FFXIVClassic_Map_Server.actors.chara.ai.state
|
||||
|
||||
private bool IsAttackReady()
|
||||
{
|
||||
return Program.Tick >= attackTime;
|
||||
// todo: this enforced delay should really be changed if it's not retail..
|
||||
return Program.Tick >= attackTime && Program.Tick >= owner.aiContainer.GetLastActionTime().AddSeconds(1);
|
||||
}
|
||||
|
||||
private bool CanAttack()
|
||||
{
|
||||
if (!owner.isAutoAttackEnabled)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (target == null)
|
||||
{
|
||||
return false;
|
||||
@@ -162,7 +169,7 @@ namespace FFXIVClassic_Map_Server.actors.chara.ai.state
|
||||
// todo: use a mod for melee range
|
||||
else if (Utils.Distance(owner.positionX, owner.positionY, owner.positionZ, target.positionX, target.positionY, target.positionZ) > owner.GetAttackRange())
|
||||
{
|
||||
if (owner.currentSubState == SetActorStatePacket.SUB_STATE_PLAYER)
|
||||
if (owner is Player)
|
||||
{
|
||||
((Player)owner).SendGameMessage(Server.GetWorldManager().GetActor(), 32539, 0x20);
|
||||
}
|
||||
|
@@ -15,6 +15,7 @@ namespace FFXIVClassic_Map_Server.actors.chara.ai.state
|
||||
: base(owner, null)
|
||||
{
|
||||
owner.ChangeState(SetActorStatePacket.MAIN_STATE_DEAD);
|
||||
owner.Disengage();
|
||||
canInterrupt = false;
|
||||
startTime = tick;
|
||||
despawnTime = startTime.AddSeconds(timeToFadeOut);
|
||||
@@ -25,7 +26,14 @@ namespace FFXIVClassic_Map_Server.actors.chara.ai.state
|
||||
// todo: handle raise etc
|
||||
if (tick >= despawnTime)
|
||||
{
|
||||
owner.Spawn(Program.Tick);
|
||||
if (owner is BattleNpc)
|
||||
{
|
||||
owner.Despawn(tick);
|
||||
}
|
||||
else
|
||||
{
|
||||
// todo: queue a warp for the player
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
@@ -0,0 +1,34 @@
|
||||
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.packets.send.actor;
|
||||
|
||||
namespace FFXIVClassic_Map_Server.actors.chara.ai.state
|
||||
{
|
||||
class DespawnState : State
|
||||
{
|
||||
private DateTime endTime;
|
||||
public DespawnState(Character owner, Character target, uint despawnTimeSeconds) :
|
||||
base(owner, null)
|
||||
{
|
||||
startTime = Program.Tick;
|
||||
endTime = startTime.AddSeconds(despawnTimeSeconds);
|
||||
}
|
||||
|
||||
public override bool Update(DateTime tick)
|
||||
{
|
||||
if (tick >= endTime)
|
||||
{
|
||||
// todo: send packet to despawn the npc, set it so npc is despawned when requesting spawn packets
|
||||
owner.zone.BroadcastPacketAroundActor(owner, RemoveActorPacket.BuildPacket(owner.actorId));
|
||||
owner.QueuePositionUpdate(owner.spawnX, owner.spawnY, owner.spawnZ);
|
||||
lua.LuaEngine.CallLuaBattleAction(owner, "onDespawn", owner);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
@@ -57,14 +57,13 @@ namespace FFXIVClassic_Map_Server.actors.chara.ai.state
|
||||
float spellSpeed = spell.castTimeSeconds;
|
||||
|
||||
// command casting duration
|
||||
if (owner.currentSubState == SetActorStatePacket.SUB_STATE_PLAYER)
|
||||
if (owner is Player)
|
||||
{
|
||||
// todo: modify spellSpeed based on modifiers and stuff
|
||||
((Player)owner).SendStartCastbar(spell.id, Utils.UnixTimeStampUTC(DateTime.Now.AddSeconds(spellSpeed)));
|
||||
owner.SendChant(0xF, 0x0);
|
||||
owner.DoBattleAction(spell.id, 0x6F000002, new BattleAction(target.actorId, 30128, 1, 0, 1)); //You begin casting (6F000002: BLM, 6F000003: WHM)
|
||||
((Player)owner).SendStartCastbar(spell.id, Utils.UnixTimeStampUTC(DateTime.Now.AddSeconds(spellSpeed)));
|
||||
}
|
||||
|
||||
owner.SendChant(0xF, 0x0);
|
||||
owner.DoBattleAction(spell.id, 0x6F000002, new BattleAction(target.actorId, 30128, 1, 0, 1)); //You begin casting (6F000002: BLM, 6F000003: WHM)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -106,7 +105,7 @@ namespace FFXIVClassic_Map_Server.actors.chara.ai.state
|
||||
|
||||
public override void OnComplete()
|
||||
{
|
||||
spell.targetFind.FindWithinArea(target, spell.validTarget);
|
||||
spell.targetFind.FindWithinArea(target, spell.validTarget, spell.aoeTarget);
|
||||
isCompleted = true;
|
||||
|
||||
var targets = spell.targetFind.GetTargets();
|
||||
@@ -119,7 +118,10 @@ namespace FFXIVClassic_Map_Server.actors.chara.ai.state
|
||||
actions[i++] = action;
|
||||
}
|
||||
|
||||
owner.SendChant(0, 0);
|
||||
// todo: this is fuckin stupid, probably only need *one* error packet, not an error for each action
|
||||
var errors = (BattleAction[])actions.Clone();
|
||||
|
||||
owner.OnCast(this, actions, ref errors);
|
||||
owner.DoBattleAction(spell.id, spell.battleAnimation, actions);
|
||||
}
|
||||
|
||||
@@ -138,10 +140,6 @@ namespace FFXIVClassic_Map_Server.actors.chara.ai.state
|
||||
// todo: actually check proc rate/random chance of whatever effect
|
||||
effectId = list[0].GetStatusEffectId();
|
||||
}
|
||||
// todo: which is actually the swing packet
|
||||
//this.errorPacket = BattleActionX01Packet.BuildPacket(target.actorId, owner.actorId, target.actorId, 0, effectId, 0, (ushort)BattleActionX01PacketCommand.Attack, (ushort)damage, 0);
|
||||
//owner.zone.BroadcastPacketAroundActor(owner, errorPacket);
|
||||
//errorPacket = null;
|
||||
interrupt = true;
|
||||
return;
|
||||
}
|
||||
@@ -159,7 +157,7 @@ namespace FFXIVClassic_Map_Server.actors.chara.ai.state
|
||||
|
||||
private bool CanCast()
|
||||
{
|
||||
return owner.CanCast(target, spell) && !HasMoved();
|
||||
return owner.CanCast(target, spell) && spell.IsValidTarget(owner, target) && !HasMoved();
|
||||
}
|
||||
|
||||
private bool HasMoved()
|
||||
@@ -169,13 +167,13 @@ namespace FFXIVClassic_Map_Server.actors.chara.ai.state
|
||||
|
||||
public override void Cleanup()
|
||||
{
|
||||
if (owner.currentSubState == SetActorStatePacket.SUB_STATE_PLAYER)
|
||||
{
|
||||
owner.SendChant(0, 0);
|
||||
|
||||
if (owner is Player)
|
||||
{
|
||||
((Player)owner).SendEndCastbar();
|
||||
}
|
||||
// command casting duration
|
||||
//var packets = new List<SubPacket>();
|
||||
//owner.zone.BroadcastPacketsAroundActor(owner, packets);
|
||||
owner.aiContainer.UpdateLastActionTime();
|
||||
}
|
||||
|
||||
public BattleCommand GetSpell()
|
||||
|
@@ -90,7 +90,7 @@ namespace FFXIVClassic_Map_Server.actors.chara.ai.state
|
||||
|
||||
public override void OnComplete()
|
||||
{
|
||||
skill.targetFind.FindWithinArea(target, skill.validTarget);
|
||||
skill.targetFind.FindWithinArea(target, skill.validTarget, skill.aoeTarget);
|
||||
isCompleted = true;
|
||||
|
||||
var targets = skill.targetFind.GetTargets();
|
||||
@@ -104,10 +104,12 @@ namespace FFXIVClassic_Map_Server.actors.chara.ai.state
|
||||
// evasion, miss, dodge, etc to be handled in script, calling helpers from scripts/weaponskills.lua
|
||||
action.amount = (ushort)lua.LuaEngine.CallLuaBattleCommandFunction(owner, skill, "weaponskill", "onSkillFinish", owner, target, skill, action);
|
||||
actions[i++] = action;
|
||||
|
||||
//packets.Add(BattleActionX01Packet.BuildPacket(chara.actorId, owner.actorId, action.targetId, skill.battleAnimation, action.effectId, action.worldMasterTextId, skill.id, action.amount, action.param));
|
||||
}
|
||||
|
||||
// todo: this is fuckin stupid, probably only need *one* error packet, not an error for each action
|
||||
var errors = (BattleAction[])actions.Clone();
|
||||
|
||||
owner.OnWeaponSkill(this, actions, ref errors);
|
||||
owner.DoBattleAction(skill.id, 0, actions);
|
||||
}
|
||||
|
||||
@@ -126,10 +128,6 @@ namespace FFXIVClassic_Map_Server.actors.chara.ai.state
|
||||
// todo: actually check proc rate/random chance of whatever effect
|
||||
effectId = list[0].GetStatusEffectId();
|
||||
}
|
||||
// todo: which is actually the swing packet
|
||||
//this.errorPacket = BattleActionX01Packet.BuildPacket(target.actorId, owner.actorId, target.actorId, 0, effectId, 0, (ushort)BattleActionX01PacketCommand.Attack, (ushort)damage, 0);
|
||||
//owner.zone.BroadcastPacketAroundActor(owner, errorPacket);
|
||||
//errorPacket = null;
|
||||
interrupt = true;
|
||||
return;
|
||||
}
|
||||
@@ -139,12 +137,17 @@ namespace FFXIVClassic_Map_Server.actors.chara.ai.state
|
||||
|
||||
private bool CanUse()
|
||||
{
|
||||
return owner.CanWeaponSkill(target, skill);
|
||||
return owner.CanWeaponSkill(target, skill) && skill.IsValidTarget(owner, target);
|
||||
}
|
||||
|
||||
public BattleCommand GetWeaponSkill()
|
||||
{
|
||||
return skill;
|
||||
}
|
||||
|
||||
public override void Cleanup()
|
||||
{
|
||||
owner.aiContainer.UpdateLastActionTime();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user