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:
Tahir Akhlaq 2017-08-31 05:56:43 +01:00
parent 4c7928da78
commit c5cc7c2f00
24 changed files with 550 additions and 330 deletions

View File

@ -88,6 +88,9 @@ namespace FFXIVClassic.Common
public static float GetAngle(float x, float z, float x2, float z2) public static float GetAngle(float x, float z, float x2, float z2)
{ {
if (x == x2)
return 0.0f;
var angle = (float)(Math.Atan((z2 - z) / (x2 - x))); var angle = (float)(Math.Atan((z2 - z) / (x2 - x)));
return (float)(x > x2 ? angle + Math.PI : angle); return (float)(x > x2 ? angle + Math.PI : angle);
} }
@ -104,6 +107,9 @@ namespace FFXIVClassic.Common
public bool IsWithinCircle(Vector3 centre, float radius) public bool IsWithinCircle(Vector3 centre, float radius)
{ {
if (this.X == centre.X && this.Z == centre.Z)
return true;
float diffX = centre.X - this.X; float diffX = centre.X - this.X;
float diffZ = centre.Z - this.Z; float diffZ = centre.Z - this.Z;

View File

@ -2154,8 +2154,8 @@ namespace FFXIVClassic_Map_Server
{ {
conn.Open(); conn.Open();
var query = ("SELECT `id`, name, classJob, lvl, requirements, validTarget, aoeType, numHits, positionBonus, procRequirement, `range`, buffDuration, debuffDuration, " + var query = ("SELECT `id`, name, classJob, lvl, requirements, validTarget, aoeType, aoeRange, aoeTarget, numHits, positionBonus, procRequirement, `range`, buffDuration, debuffDuration, " +
"castType, castTime, recastTime, mpCost, tpCost, animationType, effectAnimation, modelAnimation, animationDuration, aoeRange FROM server_battle_commands;"); "castType, castTime, recastTime, mpCost, tpCost, animationType, effectAnimation, modelAnimation, animationDuration, battleAnimation FROM server_battle_commands;");
MySqlCommand cmd = new MySqlCommand(query, conn); MySqlCommand cmd = new MySqlCommand(query, conn);
@ -2188,7 +2188,9 @@ namespace FFXIVClassic_Map_Server
battleCommand.modelAnimation = reader.GetUInt16("modelAnimation"); battleCommand.modelAnimation = reader.GetUInt16("modelAnimation");
battleCommand.animationDurationSeconds = reader.GetUInt16("animationDuration"); battleCommand.animationDurationSeconds = reader.GetUInt16("animationDuration");
battleCommand.aoeRange = reader.GetInt32("aoeRange"); battleCommand.aoeRange = reader.GetInt32("aoeRange");
battleCommand.battleAnimation = (uint)((battleCommand.animationType << 24) | (battleCommand.modelAnimation << 12) | (battleCommand.effectAnimation)); battleCommand.aoeTarget = (TargetFindAOETarget)reader.GetByte("aoeTarget");
battleCommand.battleAnimation = reader.GetUInt32("battleAnimation");
battleCommands.Add(id, battleCommand); battleCommands.Add(id, battleCommand);
} }

View File

@ -96,6 +96,7 @@
<Compile Include="actors\chara\ai\BattleCommand.cs" /> <Compile Include="actors\chara\ai\BattleCommand.cs" />
<Compile Include="actors\chara\ai\state\AttackState.cs" /> <Compile Include="actors\chara\ai\state\AttackState.cs" />
<Compile Include="actors\chara\ai\state\DeathState.cs" /> <Compile Include="actors\chara\ai\state\DeathState.cs" />
<Compile Include="actors\chara\ai\state\DespawnState.cs" />
<Compile Include="actors\chara\ai\state\MagicState.cs" /> <Compile Include="actors\chara\ai\state\MagicState.cs" />
<Compile Include="actors\chara\ai\state\State.cs" /> <Compile Include="actors\chara\ai\state\State.cs" />
<Compile Include="actors\chara\ai\state\WeaponSkillState.cs" /> <Compile Include="actors\chara\ai\state\WeaponSkillState.cs" />

View File

@ -154,6 +154,8 @@ namespace FFXIVClassic_Map_Server
case 0x00CC: case 0x00CC:
LockTargetPacket lockTarget = new LockTargetPacket(subpacket.data); LockTargetPacket lockTarget = new LockTargetPacket(subpacket.data);
session.GetActor().currentLockedTarget = lockTarget.actorID; session.GetActor().currentLockedTarget = lockTarget.actorID;
session.GetActor().isAutoAttackEnabled = lockTarget.otherVal == 0x00000040;
break; break;
//Start Event //Start Event
case 0x012D: case 0x012D:

View File

@ -365,10 +365,10 @@ namespace FFXIVClassic_Map_Server.Actors
public void ChangeState(ushort newState) public void ChangeState(ushort newState)
{ {
if (newState != currentMainState) //if (newState != currentMainState)
{ {
currentMainState = newState; currentMainState = newState;
updateFlags |= ActorUpdateFlags.State; updateFlags |= (ActorUpdateFlags.State | ActorUpdateFlags.Position);
} }
} }
@ -402,7 +402,7 @@ namespace FFXIVClassic_Map_Server.Actors
if (positionUpdates != null && positionUpdates.Count > 0) if (positionUpdates != null && positionUpdates.Count > 0)
{ {
// push latest for player // push latest for player
var pos = positionUpdates[currentSubState == SetActorStatePacket.SUB_STATE_PLAYER ? positionUpdates.Count - 1 : 0]; var pos = positionUpdates[0];
oldPositionX = positionX; oldPositionX = positionX;
oldPositionY = positionY; oldPositionY = positionY;
oldPositionZ = positionZ; oldPositionZ = positionZ;
@ -417,8 +417,8 @@ namespace FFXIVClassic_Map_Server.Actors
//Program.Server.GetInstance().mLuaEngine.OnPath(actor, position, positionUpdates) //Program.Server.GetInstance().mLuaEngine.OnPath(actor, position, positionUpdates)
positionUpdates.Remove(pos); positionUpdates.Remove(pos);
packets.Add(CreatePositionUpdatePacket());
} }
packets.Add(CreatePositionUpdatePacket());
} }
if ((updateFlags & ActorUpdateFlags.Speed) != 0) if ((updateFlags & ActorUpdateFlags.Speed) != 0)
@ -434,8 +434,6 @@ namespace FFXIVClassic_Map_Server.Actors
if ((updateFlags & ActorUpdateFlags.State) != 0) if ((updateFlags & ActorUpdateFlags.State) != 0)
{ {
packets.Add(SetActorStatePacket.BuildPacket(actorId, currentMainState, currentSubState)); packets.Add(SetActorStatePacket.BuildPacket(actorId, currentMainState, currentSubState));
if (this is Character)
((Character)this).DoBattleAction(21001, 0x7C000062, new BattleAction(this.actorId, 0, 1, 0, 0, 1)); //Attack Mode
} }
updateFlags = ActorUpdateFlags.None; updateFlags = ActorUpdateFlags.None;

View File

@ -321,6 +321,11 @@ namespace FFXIVClassic_Map_Server.Actors
} }
} }
public T FindActorInArea<T>(uint id) where T : Actor
{
return FindActorInArea(id) as T;
}
public Actor FindActorInZoneByUniqueID(string uniqueId) public Actor FindActorInZoneByUniqueID(string uniqueId)
{ {
lock (mActorList) lock (mActorList)

View File

@ -67,6 +67,7 @@ namespace FFXIVClassic_Map_Server.Actors
public bool isStatic = false; public bool isStatic = false;
public bool isMovingToSpawn = false; public bool isMovingToSpawn = false;
public bool isAutoAttackEnabled = true;
public uint modelId; public uint modelId;
public uint[] appearanceIds = new uint[28]; public uint[] appearanceIds = new uint[28];
@ -98,6 +99,8 @@ namespace FFXIVClassic_Map_Server.Actors
protected ushort hpBase, hpMaxBase, mpBase, mpMaxBase, tpBase; protected ushort hpBase, hpMaxBase, mpBase, mpMaxBase, tpBase;
protected BattleTemp baseStats = new BattleTemp(); protected BattleTemp baseStats = new BattleTemp();
public ushort currentJob; public ushort currentJob;
public ushort newMainState;
public float spawnX, spawnY, spawnZ;
public Character(uint actorID) : base(actorID) public Character(uint actorID) : base(actorID)
{ {
@ -112,6 +115,10 @@ namespace FFXIVClassic_Map_Server.Actors
// todo: base this on equip and shit // todo: base this on equip and shit
SetMod((uint)Modifier.AttackRange, 3); SetMod((uint)Modifier.AttackRange, 3);
SetMod((uint)Modifier.AttackDelay, (Program.Random.Next(30, 60) * 100)); SetMod((uint)Modifier.AttackDelay, (Program.Random.Next(30, 60) * 100));
spawnX = positionX;
spawnY = positionY;
spawnZ = positionZ;
} }
public SubPacket CreateAppearancePacket() public SubPacket CreateAppearancePacket()
@ -305,7 +312,13 @@ namespace FFXIVClassic_Map_Server.Actors
if ((updateFlags & ActorUpdateFlags.State) != 0) if ((updateFlags & ActorUpdateFlags.State) != 0)
{ {
packets.Add(SetActorStatePacket.BuildPacket(actorId, currentMainState, currentSubState));
packets.Add(BattleActionX00Packet.BuildPacket(actorId, 0x72000062, 0)); packets.Add(BattleActionX00Packet.BuildPacket(actorId, 0x72000062, 0));
packets.Add(BattleActionX01Packet.BuildPacket(actorId, 0x7C000062, 21001, new BattleAction(actorId, 0, 1)));
// this is silly, but looks like state change goes full retard unless theyre sent in order
updateFlags &= ~ActorUpdateFlags.State;
//DoBattleAction(21001, 0x7C000062, new BattleAction(this.actorId, 0, 1, 0, 0, 1)); //Attack Mode
} }
// todo: should probably add another flag for battleTemp since all this uses reflection // todo: should probably add another flag for battleTemp since all this uses reflection
@ -357,26 +370,37 @@ namespace FFXIVClassic_Map_Server.Actors
return (uint)GetMod((uint)Modifier.AttackRange); return (uint)GetMod((uint)Modifier.AttackRange);
} }
public bool Engage(uint targid = 0) public virtual bool Engage(uint targid = 0, ushort newMainState = 0xFFFF)
{ {
// todo: attack the things // todo: attack the things
if (targid == 0) if (newMainState != 0xFFFF)
{ {
if (currentTarget != 0xC0000000) this.newMainState = newMainState;
targid = currentTarget;
else if (currentLockedTarget != 0xC0000000)
targid = currentLockedTarget;
} }
if (targid != 0) else if (aiContainer.CanChangeState())
{ {
aiContainer.Engage(Server.GetWorldManager().GetActorInWorld(targid) as Character); if (targid == 0)
{
if (currentTarget != 0xC0000000)
targid = currentTarget;
else if (currentLockedTarget != 0xC0000000)
targid = currentLockedTarget;
}
//if (targid != 0)
{
aiContainer.Engage(zone.FindActorInArea<Character>(targid));
}
} }
return false; return false;
} }
public bool Disengage() public virtual bool Disengage(ushort newMainState = 0xFFFF)
{ {
if (aiContainer != null) if (newMainState != 0xFFFF)
{
this.newMainState = newMainState;
}
else
{ {
aiContainer.Disengage(); aiContainer.Disengage();
return true; return true;
@ -384,19 +408,22 @@ namespace FFXIVClassic_Map_Server.Actors
return false; return false;
} }
public void Cast(uint spellId, uint targetId = 0) public virtual void Cast(uint spellId, uint targetId = 0)
{ {
aiContainer.Cast(Server.GetWorldManager().GetActorInWorld(targetId == 0 ? currentTarget : targetId) as Character, spellId); if (aiContainer.CanChangeState())
aiContainer.Cast(zone.FindActorInArea<Character>(targetId == 0 ? currentTarget : targetId), spellId);
} }
public void Ability(uint abilityId, uint targetId = 0) public virtual void Ability(uint abilityId, uint targetId = 0)
{ {
aiContainer.Ability(Server.GetWorldManager().GetActorInWorld(targetId == 0 ? currentTarget : targetId) as Character, abilityId); if (aiContainer.CanChangeState())
aiContainer.Ability(zone.FindActorInArea<Character>(targetId == 0 ? currentTarget : targetId), abilityId);
} }
public void WeaponSkill(uint skillId) public virtual void WeaponSkill(uint skillId, uint targetId = 0)
{ {
aiContainer.WeaponSkill(Server.GetWorldManager().GetActorInWorld(currentTarget) as Character, skillId); if (aiContainer.CanChangeState())
aiContainer.WeaponSkill(zone.FindActorInArea<Character>(targetId == 0 ? currentTarget : targetId), skillId);
} }
public virtual void Spawn(DateTime tick) public virtual void Spawn(DateTime tick)
@ -414,9 +441,9 @@ namespace FFXIVClassic_Map_Server.Actors
aiContainer.InternalDie(tick, 10); aiContainer.InternalDie(tick, 10);
} }
protected virtual void Despawn(DateTime tick) public virtual void Despawn(DateTime tick)
{ {
} }
public bool IsDead() public bool IsDead()
@ -551,20 +578,23 @@ namespace FFXIVClassic_Map_Server.Actors
//var packet = BattleActionX01Packet.BuildPacket(owner.actorId, owner.actorId, target.actorId, (uint)0x19001000, (uint)0x8000604, (ushort)0x765D, (ushort)BattleActionX01PacketCommand.Attack, (ushort)damage, (byte)0x1); //var packet = BattleActionX01Packet.BuildPacket(owner.actorId, owner.actorId, target.actorId, (uint)0x19001000, (uint)0x8000604, (ushort)0x765D, (ushort)BattleActionX01PacketCommand.Attack, (ushort)damage, (byte)0x1);
} }
// todo: call onAttack/onDamageTaken
target.DelHP(action.amount); target.DelHP(action.amount);
} }
public virtual void OnCast(State state, BattleAction action, ref SubPacket errorPacket) public virtual void OnCast(State state, BattleAction[] actions, ref BattleAction[] errors)
{ {
var spell = ((MagicState)state).GetSpell();
this.DelMP(spell.mpCost); // mpCost can be set in script e.g. if caster has something for free spells
} }
public virtual void OnWeaponSkill(State state, BattleAction action, ref SubPacket errorPacket) public virtual void OnWeaponSkill(State state, BattleAction[] actions, ref BattleAction[] errors)
{ {
var skill = ((WeaponSkillState)state).GetWeaponSkill();
this.DelTP(skill.tpCost);
} }
public virtual void OnAbility(State state, BattleAction action, ref SubPacket errorPacket) public virtual void OnAbility(State state, BattleAction[] actions, ref BattleAction[] errors)
{ {
} }

View File

@ -23,6 +23,7 @@ namespace FFXIVClassic_Map_Server.actors.chara.ai
public readonly PathFind pathFind; public readonly PathFind pathFind;
private TargetFind targetFind; private TargetFind targetFind;
private ActionQueue actionQueue; private ActionQueue actionQueue;
private DateTime lastActionTime;
public AIContainer(Character actor, Controller controller, PathFind pathFind, TargetFind targetFind) public AIContainer(Character actor, Controller controller, PathFind pathFind, TargetFind targetFind)
{ {
@ -36,6 +37,16 @@ namespace FFXIVClassic_Map_Server.actors.chara.ai
actionQueue = new ActionQueue(owner); actionQueue = new ActionQueue(owner);
} }
public void UpdateLastActionTime()
{
lastActionTime = DateTime.Now;
}
public DateTime GetLastActionTime()
{
return lastActionTime;
}
public void Update(DateTime tick) public void Update(DateTime tick)
{ {
prevUpdate = latestUpdate; prevUpdate = latestUpdate;
@ -186,13 +197,13 @@ namespace FFXIVClassic_Map_Server.actors.chara.ai
public bool IsEngaged() public bool IsEngaged()
{ {
// todo: check this is legit // todo: check this is legit
return owner.currentMainState == SetActorStatePacket.MAIN_STATE_ACTIVE && owner.target != null; return owner.currentMainState == SetActorStatePacket.MAIN_STATE_ACTIVE;
} }
public bool IsDead() public bool IsDead()
{ {
return owner.currentMainState == SetActorStatePacket.MAIN_STATE_DEAD || return owner.currentMainState == SetActorStatePacket.MAIN_STATE_DEAD ||
owner.currentMainState == SetActorStatePacket.MAIN_STATE_DEAD2; owner.currentMainState == SetActorStatePacket.MAIN_STATE_DEAD2 || owner.GetHP() == 0;
} }
public bool IsRoaming() public bool IsRoaming()
@ -253,10 +264,6 @@ namespace FFXIVClassic_Map_Server.actors.chara.ai
{ {
// todo: use invalid target id // todo: use invalid target id
// todo: this is retarded, call entity's changetarget function // todo: this is retarded, call entity's changetarget function
owner.target = target;
owner.currentLockedTarget = target != null ? target.actorId : 0xC0000000;
owner.currentTarget = target != null ? target.actorId : 0xC0000000;
if (IsEngaged() || target == null) if (IsEngaged() || target == null)
{ {
@ -293,8 +300,8 @@ namespace FFXIVClassic_Map_Server.actors.chara.ai
GetTargetFind()?.Reset(); GetTargetFind()?.Reset();
owner.updateFlags |= ActorUpdateFlags.HpTpMp; owner.updateFlags |= ActorUpdateFlags.HpTpMp;
ChangeTarget(null); ChangeTarget(null);
owner.ChangeState(SetActorStatePacket.MAIN_STATE_PASSIVE);
ClearStates(); ClearStates();
} }

View File

@ -53,6 +53,7 @@ namespace FFXIVClassic_Map_Server.actors.chara.ai
public BattleCommandRequirements requirements; public BattleCommandRequirements requirements;
public ValidTarget validTarget; public ValidTarget validTarget;
public TargetFindAOEType aoeType; public TargetFindAOEType aoeType;
public TargetFindAOETarget aoeTarget;
public byte numHits; public byte numHits;
public BattleCommandPositionBonus positionBonus; public BattleCommandPositionBonus positionBonus;
public BattleCommandProcRequirement procRequirement; public BattleCommandProcRequirement procRequirement;
@ -105,11 +106,11 @@ namespace FFXIVClassic_Map_Server.actors.chara.ai
if (aoeType == TargetFindAOEType.Box) if (aoeType == TargetFindAOEType.Box)
{ {
// todo: read box width from sql // todo: read box width from sql
targetFind.SetAOEBox(validTarget, range, aoeRange); targetFind.SetAOEBox(validTarget, aoeTarget, range, aoeRange);
} }
else else
{ {
targetFind.SetAOEType(validTarget, aoeType, range, aoeRange); targetFind.SetAOEType(validTarget, aoeType, aoeTarget, range, aoeRange);
} }
@ -183,8 +184,7 @@ namespace FFXIVClassic_Map_Server.actors.chara.ai
if ((validTarget & ValidTarget.Enemy) != 0) if ((validTarget & ValidTarget.Enemy) != 0)
{ {
if (target == user || target != null && if (target == user || target != null &&
target.currentSubState != (user.currentSubState == SetActorStatePacket.SUB_STATE_MONSTER ? user.allegiance == target.allegiance)
SetActorStatePacket.SUB_STATE_PLAYER : SetActorStatePacket.SUB_STATE_MONSTER))
{ {
if (user is Player) if (user is Player)
((Player)user).SendGameMessage(Server.GetWorldManager().GetActor(), 32519, 0x20, (uint)id); ((Player)user).SendGameMessage(Server.GetWorldManager().GetActor(), 32519, 0x20, (uint)id);
@ -194,14 +194,14 @@ namespace FFXIVClassic_Map_Server.actors.chara.ai
if ((validTarget & (ValidTarget.PartyMember | ValidTarget.Player | ValidTarget.Ally)) != 0) if ((validTarget & (ValidTarget.PartyMember | ValidTarget.Player | ValidTarget.Ally)) != 0)
{ {
if (target == null || target.currentSubState != user.currentSubState ) if (target == null || target.allegiance != user.allegiance)
{ {
if (user is Player) if (user is Player)
((Player)user).SendGameMessage(Server.GetWorldManager().GetActor(), 32516, 0x20, (uint)id); ((Player)user).SendGameMessage(Server.GetWorldManager().GetActor(), 32516, 0x20, (uint)id);
return false; return false;
} }
} }
return targetFind.CanTarget(target, true, true); return targetFind.CanTarget(target, true, true, true);
} }
public ushort CalculateCost(uint level) public ushort CalculateCost(uint level)

View File

@ -195,13 +195,13 @@ namespace FFXIVClassic_Map_Server.actors.chara.ai
float baseSpeed = owner.GetSpeed(); float baseSpeed = owner.GetSpeed();
// todo: get actual speed crap // todo: get actual speed crap
if (owner.currentSubState != SetActorStatePacket.SUB_STATE_NONE) if (!(owner is Player))
{ {
if (owner.currentSubState == SetActorStatePacket.SUB_STATE_MONSTER) if (owner is BattleNpc)
{ {
//owner.ChangeSpeed(0.0f, SetActorSpeedPacket.DEFAULT_WALK - 2.0f, SetActorSpeedPacket.DEFAULT_RUN - 2.0f, SetActorSpeedPacket.DEFAULT_ACTIVE - 2.0f); //owner.ChangeSpeed(0.0f, SetActorSpeedPacket.DEFAULT_WALK - 2.0f, SetActorSpeedPacket.DEFAULT_RUN - 2.0f, SetActorSpeedPacket.DEFAULT_ACTIVE - 2.0f);
} }
// baseSpeed += ConfigConstants.SPEED_MOD; // baseSpeed += ConfigConstants.NPC_SPEED_MOD;
} }
return baseSpeed; return baseSpeed;
} }

View File

@ -7,6 +7,7 @@ using FFXIVClassic_Map_Server.Actors;
using FFXIVClassic.Common; using FFXIVClassic.Common;
using FFXIVClassic_Map_Server.actors.chara.ai; using FFXIVClassic_Map_Server.actors.chara.ai;
using FFXIVClassic_Map_Server.actors.chara.ai.controllers; using FFXIVClassic_Map_Server.actors.chara.ai.controllers;
using FFXIVClassic_Map_Server.actors.group;
using FFXIVClassic_Map_Server.packets.send.actor; using FFXIVClassic_Map_Server.packets.send.actor;
// port of dsp's ai code https://github.com/DarkstarProject/darkstar/blob/master/src/map/ai/ // port of dsp's ai code https://github.com/DarkstarProject/darkstar/blob/master/src/map/ai/
@ -48,9 +49,9 @@ namespace FFXIVClassic_Map_Server.actors.chara.ai
enum TargetFindAOEType : byte enum TargetFindAOEType : byte
{ {
None, None,
/// <summary> Really a cylinder, uses extents parameter in SetAOEType </summary> /// <summary> Really a cylinder, uses maxDistance parameter in SetAOEType </summary>
Circle, Circle,
/// <summary> Create a cone with angle in radians </summary> /// <summary> Create a cone with param in radians </summary>
Cone, Cone,
/// <summary> Box using self/target coords and </summary> /// <summary> Box using self/target coords and </summary>
Box Box
@ -69,14 +70,14 @@ namespace FFXIVClassic_Map_Server.actors.chara.ai
class TargetFind class TargetFind
{ {
private Character owner; private Character owner;
private Character target;
private Character masterTarget; // if target is a pet, this is the owner private Character masterTarget; // if target is a pet, this is the owner
private TargetFindCharacterType findType; private TargetFindCharacterType findType;
private ValidTarget validTarget; private ValidTarget validTarget;
private TargetFindAOETarget aoeTarget;
private TargetFindAOEType aoeType; private TargetFindAOEType aoeType;
private Vector3 targetPosition; private Vector3 targetPosition;
private float extents; private float maxDistance;
private float angle; private float param;
private List<Character> targets; private List<Character> targets;
public TargetFind(Character owner) public TargetFind(Character owner)
@ -87,13 +88,13 @@ namespace FFXIVClassic_Map_Server.actors.chara.ai
public void Reset() public void Reset()
{ {
this.target = null;
this.findType = TargetFindCharacterType.None; this.findType = TargetFindCharacterType.None;
this.validTarget = ValidTarget.Enemy; this.validTarget = ValidTarget.Enemy;
this.aoeType = TargetFindAOEType.None; this.aoeType = TargetFindAOEType.None;
this.aoeTarget = TargetFindAOETarget.Target;
this.targetPosition = null; this.targetPosition = null;
this.extents = 0.0f; this.maxDistance = 0.0f;
this.angle = 0.0f; this.param = 0.0f;
this.targets = new List<Character>(); this.targets = new List<Character>();
} }
@ -110,28 +111,29 @@ namespace FFXIVClassic_Map_Server.actors.chara.ai
/// <summary> /// <summary>
/// Call this before <see cref="FindWithinArea"/> <para/> /// Call this before <see cref="FindWithinArea"/> <para/>
/// </summary> /// </summary>
/// <param name="extents"> /// <param name="maxDistance">
/// <see cref="TargetFindAOEType.Circle"/> - radius of circle <para/> /// <see cref="TargetFindAOEType.Circle"/> - radius of circle <para/>
/// <see cref="TargetFindAOEType.Cone"/> - height of cone <para/> /// <see cref="TargetFindAOEType.Cone"/> - height of cone <para/>
/// <see cref="TargetFindAOEType.Box"/> - width of box / 2 (todo: set box length not just between user and target) /// <see cref="TargetFindAOEType.Box"/> - width of box / 2 (todo: set box length not just between user and target)
/// </param> /// </param>
/// <param name="angle"> Angle in radians of cone </param> /// <param name="param"> param in degrees of cone (todo: probably use radians and forget converting at runtime) </param>
public void SetAOEType(ValidTarget validTarget, TargetFindAOEType aoeType, float extents = -1.0f, float angle = -1.0f) public void SetAOEType(ValidTarget validTarget, TargetFindAOEType aoeType, TargetFindAOETarget aoeTarget, float maxDistance = -1.0f, float param = -1.0f)
{ {
this.validTarget = validTarget; this.validTarget = validTarget;
this.aoeType = aoeType; this.aoeType = aoeType;
this.extents = extents != -1.0f ? extents : 0.0f; this.maxDistance = maxDistance != -1.0f ? maxDistance : 0.0f;
this.angle = angle != -1.0f ? angle : 0.0f; this.param = param != -1.0f ? param : 0.0f;
} }
public void SetAOEBox(ValidTarget validTarget, float length, float width) public void SetAOEBox(ValidTarget validTarget, TargetFindAOETarget aoeTarget, float length, float width)
{ {
this.validTarget = validTarget; this.validTarget = validTarget;
this.aoeType = TargetFindAOEType.Box; this.aoeType = TargetFindAOEType.Box;
this.aoeTarget = aoeTarget;
float x = owner.positionX - (float)Math.Cos(owner.rotation + (float)(Math.PI / 2)) * (length); float x = owner.positionX - (float)Math.Cos(owner.rotation + (float)(Math.PI / 2)) * (length);
float z = owner.positionZ + (float)Math.Sin(owner.rotation + (float)(Math.PI / 2)) * (length); float z = owner.positionZ + (float)Math.Sin(owner.rotation + (float)(Math.PI / 2)) * (length);
this.targetPosition = new Vector3(x, owner.positionY, z); this.targetPosition = new Vector3(x, owner.positionY, z);
this.extents = width; this.maxDistance = width;
} }
/// <summary> /// <summary>
@ -140,7 +142,6 @@ namespace FFXIVClassic_Map_Server.actors.chara.ai
public void FindTarget(Character target, ValidTarget flags) public void FindTarget(Character target, ValidTarget flags)
{ {
validTarget = flags; validTarget = flags;
this.target = null;
// todo: maybe this should only be set if successfully added? // todo: maybe this should only be set if successfully added?
this.targetPosition = target.GetPosAsVector3(); this.targetPosition = target.GetPosAsVector3();
AddTarget(target, false); AddTarget(target, false);
@ -150,21 +151,18 @@ namespace FFXIVClassic_Map_Server.actors.chara.ai
/// <para> Call SetAOEType before calling this </para> /// <para> Call SetAOEType before calling this </para>
/// Find targets within area set by <see cref="SetAOEType"/> /// Find targets within area set by <see cref="SetAOEType"/>
/// </summary> /// </summary>
public void FindWithinArea(Character target, ValidTarget flags) public void FindWithinArea(Character target, ValidTarget flags, TargetFindAOETarget aoeTarget)
{ {
validTarget = flags; validTarget = flags;
// todo: maybe we should keep a snapshot which is only updated on each tick for consistency // todo: maybe we should keep a snapshot which is only updated on each tick for consistency
// are we creating aoe circles around target or self // are we creating aoe circles around target or self
if ((aoeType & TargetFindAOEType.Circle) != 0 && validTarget != ValidTarget.Self) if (aoeTarget == TargetFindAOETarget.Self)
this.targetPosition = owner.GetPosAsVector3(); this.targetPosition = owner.GetPosAsVector3();
else else
this.targetPosition = target.GetPosAsVector3(); this.targetPosition = target.GetPosAsVector3();
masterTarget = TryGetMasterTarget(target) ?? target; masterTarget = TryGetMasterTarget(target) ?? target;
// todo: should i set this yet or wait til checked if valid target
this.target = target;
// todo: this is stupid // todo: this is stupid
bool withPet = (flags & ValidTarget.Ally) != 0 || masterTarget.allegiance != owner.allegiance; bool withPet = (flags & ValidTarget.Ally) != 0 || masterTarget.allegiance != owner.allegiance;
@ -180,7 +178,7 @@ namespace FFXIVClassic_Map_Server.actors.chara.ai
// todo: handle player parties // todo: handle player parties
if (masterTarget.currentParty != null) if (masterTarget.currentParty != null)
{ {
if ((validTarget & ValidTarget.Ally) != 0) if ((validTarget & (ValidTarget.Ally | ValidTarget.PartyMember)) != 0)
AddAllInAlliance(masterTarget, withPet); AddAllInAlliance(masterTarget, withPet);
else else
AddAllInParty(masterTarget, withPet); AddAllInParty(masterTarget, withPet);
@ -229,19 +227,24 @@ namespace FFXIVClassic_Map_Server.actors.chara.ai
/// <summary> /// <summary>
/// Find targets within a box using owner's coordinates and target's coordinates as length /// Find targets within a box using owner's coordinates and target's coordinates as length
/// with corners being `extents` yalms to either side of self and target /// with corners being `maxDistance` yalms to either side of self and target
/// </summary> /// </summary>
private bool IsWithinBox(Character target, bool withPet) private bool IsWithinBox(Character target, bool withPet)
{ {
if (aoeTarget == TargetFindAOETarget.Self)
targetPosition = owner.GetPosAsVector3();
else
targetPosition = target.GetPosAsVector3();
var myPos = owner.GetPosAsVector3(); var myPos = owner.GetPosAsVector3();
var angle = Vector3.GetAngle(myPos, targetPosition); var angle = Vector3.GetAngle(myPos, targetPosition);
// todo: actually check this works.. // todo: actually check this works..
var myCorner = myPos.NewHorizontalVector(angle, extents); var myCorner = myPos.NewHorizontalVector(angle, maxDistance);
var myCorner2 = myPos.NewHorizontalVector(angle, -extents); var myCorner2 = myPos.NewHorizontalVector(angle, -maxDistance);
var targetCorner = targetPosition.NewHorizontalVector(angle, extents); var targetCorner = targetPosition.NewHorizontalVector(angle, maxDistance);
var targetCorner2 = targetPosition.NewHorizontalVector(angle, -extents); var targetCorner2 = targetPosition.NewHorizontalVector(angle, -maxDistance);
return target.GetPosAsVector3().IsWithinBox(targetCorner2, myCorner); return target.GetPosAsVector3().IsWithinBox(targetCorner2, myCorner);
} }
@ -249,7 +252,7 @@ namespace FFXIVClassic_Map_Server.actors.chara.ai
private bool IsWithinCone(Character target, bool withPet) private bool IsWithinCone(Character target, bool withPet)
{ {
// todo: make this actual cone // todo: make this actual cone
return owner.IsFacing(target, angle) && Utils.Distance(owner.positionX, owner.positionY, owner.positionZ, target.positionX, target.positionY, target.positionZ) < extents; return owner.IsFacing(target, param) && Utils.Distance(owner.positionX, owner.positionY, owner.positionZ, target.positionX, target.positionY, target.positionZ) < maxDistance;
} }
private void AddTarget(Character target, bool withPet) private void AddTarget(Character target, bool withPet)
@ -264,25 +267,20 @@ namespace FFXIVClassic_Map_Server.actors.chara.ai
private void AddAllInParty(Character target, bool withPet) private void AddAllInParty(Character target, bool withPet)
{ {
// todo: // todo:
/* var party = target.currentParty as Party;
* foreach (var actor in target.currentParty.GetMembers()) if (party != null)
* { {
* AddTarget(actor, withPet); foreach (var actorId in party.members)
* } {
*/ AddTarget(owner.zone.FindActorInArea(actorId) as Character, withPet);
AddTarget(target, withPet); }
}
} }
private void AddAllInAlliance(Character target, bool withPet) private void AddAllInAlliance(Character target, bool withPet)
{ {
// todo: // todo:
/* AddAllInParty(target, withPet);
* foreach (var actor in target.currentParty.GetAllianceMembers())
* {
* AddTarget(actor, withPet);
* }
*/
AddTarget(target, withPet);
} }
private void AddAllBattleNpcs(Character target, bool withPet) private void AddAllBattleNpcs(Character target, bool withPet)
@ -321,7 +319,7 @@ namespace FFXIVClassic_Map_Server.actors.chara.ai
} }
} }
public bool CanTarget(Character target, bool withPet = false, bool retarget = false) public bool CanTarget(Character target, bool withPet = false, bool retarget = false, bool ignoreAOE = false)
{ {
// already targeted, dont target again // already targeted, dont target again
if (target == null || !retarget && targets.Contains(target)) if (target == null || !retarget && targets.Contains(target))
@ -331,21 +329,18 @@ namespace FFXIVClassic_Map_Server.actors.chara.ai
if ((validTarget & ValidTarget.Corpse) == 0 && target.IsDead()) if ((validTarget & ValidTarget.Corpse) == 0 && target.IsDead())
return false; return false;
bool targetingPlayer = target.currentSubState == SetActorStatePacket.SUB_STATE_PLAYER; if ((validTarget & ValidTarget.Ally) != 0 && target.allegiance != owner.allegiance)
if ((validTarget & ValidTarget.Ally) != 0 && target.currentSubState != owner.currentSubState)
return false; return false;
if ((validTarget & ValidTarget.Enemy) != 0 && target.currentSubState != (owner.currentSubState == SetActorStatePacket.SUB_STATE_MONSTER ? if ((validTarget & ValidTarget.Enemy) != 0 && target.allegiance == owner.allegiance)
SetActorStatePacket.SUB_STATE_PLAYER : SetActorStatePacket.SUB_STATE_MONSTER))
return false; return false;
if ((validTarget & ValidTarget.NPC) != 0 && target.currentSubState != SetActorStatePacket.SUB_STATE_NONE) if ((validTarget & ValidTarget.NPC) != 0 && target.isStatic)
return false; return false;
// todo: why is player always zoning? // todo: why is player always zoning?
// cant target if zoning // cant target if zoning
if (targetingPlayer && ((Player)target).playerSession.isUpdatesLocked) if (target is Player && ((Player)target).playerSession.isUpdatesLocked)
{ {
owner.aiContainer.ChangeTarget(null); owner.aiContainer.ChangeTarget(null);
return false; return false;
@ -354,25 +349,36 @@ namespace FFXIVClassic_Map_Server.actors.chara.ai
if (/*target.isZoning || owner.isZoning || */target.zone != owner.zone) if (/*target.isZoning || owner.isZoning || */target.zone != owner.zone)
return false; return false;
if (validTarget == ValidTarget.Self && aoeType != TargetFindAOEType.None && owner != target) if (validTarget == ValidTarget.Self && aoeType == TargetFindAOEType.None && owner != target)
return false; return false;
// hit everything within zone or within aoe region // this is fuckin retarded, think of a better way l8r
if (extents == 255.0f || aoeType == TargetFindAOEType.Circle && target.GetPosAsVector3().IsWithinCircle(targetPosition ?? target.GetPosAsVector3(), extents)) if (!ignoreAOE)
return true; {
// hit everything within zone or within aoe region
if (maxDistance == -1.0f || aoeType == TargetFindAOEType.Circle && !IsWithinCircle(target, maxDistance))
return false;
if (aoeType == TargetFindAOEType.Cone && IsWithinCone(target, withPet)) if (aoeType == TargetFindAOEType.Cone && !IsWithinCone(target, withPet))
return true; return false;
if (aoeType == TargetFindAOEType.Box && IsWithinBox(target, withPet)) if (aoeType == TargetFindAOEType.Box && !IsWithinBox(target, withPet))
return true; return false;
if (aoeType == TargetFindAOEType.None && targets.Count != 0)
return false;
if (aoeType == TargetFindAOEType.None && targets.Count != 0)
return false;
}
return true; return true;
} }
private bool IsWithinCircle(Character target, float maxDistance)
{
if (this.targetPosition == null)
this.targetPosition = aoeTarget == TargetFindAOETarget.Self ? owner.GetPosAsVector3() : masterTarget.GetPosAsVector3();
return target.GetPosAsVector3().IsWithinCircle(targetPosition, param);
}
private bool IsPlayer(Character target) private bool IsPlayer(Character target)
{ {
if (target is Player) if (target is Player)
@ -397,11 +403,11 @@ namespace FFXIVClassic_Map_Server.actors.chara.ai
private bool IsBattleNpcOwner(Character target) private bool IsBattleNpcOwner(Character target)
{ {
// i know i copied this from dsp but what even // i know i copied this from dsp but what even
if (owner.currentSubState != SetActorStatePacket.SUB_STATE_PLAYER || target.currentSubState == SetActorStatePacket.SUB_STATE_PLAYER) if (!(owner is Player) || target is Player)
return true; return true;
// todo: check hate list // todo: check hate list
if (owner.currentSubState == SetActorStatePacket.SUB_STATE_MONSTER && ((BattleNpc)owner).hateContainer.GetMostHatedTarget() != target) if (owner is BattleNpc && ((BattleNpc)owner).hateContainer.GetMostHatedTarget() != target)
{ {
return false; return false;
} }
@ -410,7 +416,7 @@ namespace FFXIVClassic_Map_Server.actors.chara.ai
public Character GetValidTarget(Character target, ValidTarget findFlags) public Character GetValidTarget(Character target, ValidTarget findFlags)
{ {
if (target == null || target.currentSubState == SetActorStatePacket.SUB_STATE_PLAYER && ((Player)target).playerSession.isUpdatesLocked) if (target == null || target is Player && ((Player)target).playerSession.isUpdatesLocked)
return null; return null;
if ((findFlags & ValidTarget.Ally) != 0) if ((findFlags & ValidTarget.Ally) != 0)

View File

@ -23,6 +23,7 @@ namespace FFXIVClassic_Map_Server.actors.chara.ai.controllers
private bool firstSpell = true; private bool firstSpell = true;
private DateTime lastRoamUpdate; private DateTime lastRoamUpdate;
private DateTime battleStartTime;
private new BattleNpc owner; private new BattleNpc owner;
public BattleNpcController(BattleNpc owner) : public BattleNpcController(BattleNpc owner) :
@ -65,6 +66,8 @@ namespace FFXIVClassic_Map_Server.actors.chara.ai.controllers
var canEngage = this.owner.aiContainer.InternalEngage(target); var canEngage = this.owner.aiContainer.InternalEngage(target);
if (canEngage) if (canEngage)
{ {
//owner.ChangeState(SetActorStatePacket.MAIN_STATE_ACTIVE);
// reset casting // reset casting
firstSpell = true; firstSpell = true;
// todo: find a better place to put this? // todo: find a better place to put this?
@ -77,6 +80,7 @@ namespace FFXIVClassic_Map_Server.actors.chara.ai.controllers
// owner.ResetMoveSpeeds(); // owner.ResetMoveSpeeds();
owner.moveState = 2; owner.moveState = 2;
lastActionTime = DateTime.Now; lastActionTime = DateTime.Now;
battleStartTime = lastActionTime;
// todo: adjust cooldowns with modifiers // todo: adjust cooldowns with modifiers
} }
return canEngage; return canEngage;
@ -100,7 +104,7 @@ namespace FFXIVClassic_Map_Server.actors.chara.ai.controllers
neutralTime = lastActionTime; neutralTime = lastActionTime;
owner.hateContainer.ClearHate(); owner.hateContainer.ClearHate();
owner.moveState = 1; owner.moveState = 1;
lua.LuaEngine.CallLuaBattleAction(owner, "onDisengage", owner, target); lua.LuaEngine.CallLuaBattleAction(owner, "onDisengage", owner, target, Utils.UnixTimeStampUTC(battleStartTime));
} }
public override void Cast(Character target, uint spellId) public override void Cast(Character target, uint spellId)
@ -199,6 +203,7 @@ namespace FFXIVClassic_Map_Server.actors.chara.ai.controllers
} }
Move(); Move();
lua.LuaEngine.CallLuaBattleAction(owner, "onCombatTick", owner, owner.target, Utils.UnixTimeStampUTC());
} }
private void Move() private void Move()
@ -230,7 +235,7 @@ namespace FFXIVClassic_Map_Server.actors.chara.ai.controllers
owner.aiContainer.pathFind.FollowPath(); owner.aiContainer.pathFind.FollowPath();
if (!owner.aiContainer.pathFind.IsFollowingPath()) if (!owner.aiContainer.pathFind.IsFollowingPath())
{ {
if (owner.target.currentSubState == SetActorStatePacket.SUB_STATE_PLAYER) if (owner.target is Player)
{ {
foreach (var chara in owner.zone.GetActorsAroundActor<Character>(owner, 1)) foreach (var chara in owner.zone.GetActorsAroundActor<Character>(owner, 1))
{ {
@ -355,5 +360,13 @@ namespace FFXIVClassic_Map_Server.actors.chara.ai.controllers
{ {
ChangeTarget(owner.hateContainer.GetMostHatedTarget()); ChangeTarget(owner.hateContainer.GetMostHatedTarget());
} }
public override void ChangeTarget(Character target)
{
owner.target = target;
owner.currentLockedTarget = target != null ? target.actorId : 0xC0000000;
owner.currentTarget = target != null ? target.actorId : 0xC0000000;
base.ChangeTarget(target);
}
} }
} }

View File

@ -11,19 +11,35 @@ namespace FFXIVClassic_Map_Server.actors.chara.ai.controllers
{ {
class PlayerController : Controller class PlayerController : Controller
{ {
public PlayerController(Character owner) : private new Player owner;
public PlayerController(Player owner) :
base(owner) base(owner)
{ {
this.owner = owner;
this.lastUpdate = DateTime.Now; this.lastUpdate = DateTime.Now;
} }
public override void Update(DateTime tick) public override void Update(DateTime tick)
{ {
// todo: handle player stuff on tick // todo: handle player stuff on tick
if (owner.newMainState != owner.currentMainState)
{
//owner.updateFlags = ActorUpdateFlags.Combat;
if (owner.newMainState == SetActorStatePacket.MAIN_STATE_ACTIVE)
{
owner.Engage();
}
else
{
owner.Disengage();
}
owner.currentMainState = (ushort)owner.newMainState;
}
} }
public override void ChangeTarget(Character target) public override void ChangeTarget(Character target)
{ {
owner.target = target;
base.ChangeTarget(target); base.ChangeTarget(target);
} }
@ -32,21 +48,12 @@ namespace FFXIVClassic_Map_Server.actors.chara.ai.controllers
var canEngage = this.owner.aiContainer.InternalEngage(target); var canEngage = this.owner.aiContainer.InternalEngage(target);
if (canEngage) if (canEngage)
{ {
// todo: find a better place to put this?
if (owner.GetState() != SetActorStatePacket.MAIN_STATE_ACTIVE)
owner.ChangeState(SetActorStatePacket.MAIN_STATE_ACTIVE);
// todo: check speed/is able to move // todo: check speed/is able to move
// todo: too far, path to player if mob, message if player // todo: too far, path to player if mob, message if player
if (owner.statusEffects.HasStatusEffect(StatusEffectId.Sleep))
// todo: actual stat based range
if (Utils.Distance(owner.positionX, owner.positionY, owner.positionZ, target.positionX, target.positionY, target.positionZ) > 10)
{ {
{ // That command cannot be performed.
// todo: out of range error owner.SendGameMessage(Server.GetWorldManager().GetActor(), 32553, 0x20);
}
ChangeTarget(target);
return false; return false;
} }
// todo: adjust cooldowns with modifiers // todo: adjust cooldowns with modifiers

View File

@ -20,7 +20,7 @@ namespace FFXIVClassic_Map_Server.actors.chara.ai.state
this.startTime = DateTime.Now; this.startTime = DateTime.Now;
owner.ChangeState(SetActorStatePacket.MAIN_STATE_ACTIVE); owner.ChangeState(SetActorStatePacket.MAIN_STATE_ACTIVE);
owner.aiContainer.ChangeTarget(target); ChangeTarget(target);
attackTime = startTime; attackTime = startTime;
owner.aiContainer.pathFind?.Clear(); owner.aiContainer.pathFind?.Clear();
// todo: should handle everything here instead of on next tick.. // todo: should handle everything here instead of on next tick..
@ -42,12 +42,13 @@ namespace FFXIVClassic_Map_Server.actors.chara.ai.state
return true; 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 (target == null || target.IsDead())
{ {
if (owner.currentSubState == SetActorStatePacket.SUB_STATE_MONSTER) if (owner is BattleNpc)
target = ((BattleNpc)owner).hateContainer.GetMostHatedTarget(); target = ((BattleNpc)owner).hateContainer.GetMostHatedTarget();
} }
else else
@ -110,7 +111,7 @@ namespace FFXIVClassic_Map_Server.actors.chara.ai.state
owner.OnAttack(this, action, ref errorResult); owner.OnAttack(this, action, ref errorResult);
// handle paralyze/intimidate/sleep/whatever in character thing // 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); //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() 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() private bool CanAttack()
{ {
if (!owner.isAutoAttackEnabled)
{
return false;
}
if (target == null) if (target == null)
{ {
return false; return false;
@ -162,7 +169,7 @@ namespace FFXIVClassic_Map_Server.actors.chara.ai.state
// todo: use a mod for melee range // 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()) 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); ((Player)owner).SendGameMessage(Server.GetWorldManager().GetActor(), 32539, 0x20);
} }

View File

@ -15,6 +15,7 @@ namespace FFXIVClassic_Map_Server.actors.chara.ai.state
: base(owner, null) : base(owner, null)
{ {
owner.ChangeState(SetActorStatePacket.MAIN_STATE_DEAD); owner.ChangeState(SetActorStatePacket.MAIN_STATE_DEAD);
owner.Disengage();
canInterrupt = false; canInterrupt = false;
startTime = tick; startTime = tick;
despawnTime = startTime.AddSeconds(timeToFadeOut); despawnTime = startTime.AddSeconds(timeToFadeOut);
@ -25,7 +26,14 @@ namespace FFXIVClassic_Map_Server.actors.chara.ai.state
// todo: handle raise etc // todo: handle raise etc
if (tick >= despawnTime) 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 true;
} }
return false; return false;

View File

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

View File

@ -57,14 +57,13 @@ namespace FFXIVClassic_Map_Server.actors.chara.ai.state
float spellSpeed = spell.castTimeSeconds; float spellSpeed = spell.castTimeSeconds;
// command casting duration // command casting duration
if (owner.currentSubState == SetActorStatePacket.SUB_STATE_PLAYER) if (owner is Player)
{ {
// todo: modify spellSpeed based on modifiers and stuff // todo: modify spellSpeed based on modifiers and stuff
((Player)owner).SendStartCastbar(spell.id, Utils.UnixTimeStampUTC(DateTime.Now.AddSeconds(spellSpeed))); ((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)
} }
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() public override void OnComplete()
{ {
spell.targetFind.FindWithinArea(target, spell.validTarget); spell.targetFind.FindWithinArea(target, spell.validTarget, spell.aoeTarget);
isCompleted = true; isCompleted = true;
var targets = spell.targetFind.GetTargets(); var targets = spell.targetFind.GetTargets();
@ -119,7 +118,10 @@ namespace FFXIVClassic_Map_Server.actors.chara.ai.state
actions[i++] = action; 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); 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 // todo: actually check proc rate/random chance of whatever effect
effectId = list[0].GetStatusEffectId(); 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; interrupt = true;
return; return;
} }
@ -159,7 +157,7 @@ namespace FFXIVClassic_Map_Server.actors.chara.ai.state
private bool CanCast() private bool CanCast()
{ {
return owner.CanCast(target, spell) && !HasMoved(); return owner.CanCast(target, spell) && spell.IsValidTarget(owner, target) && !HasMoved();
} }
private bool HasMoved() private bool HasMoved()
@ -169,13 +167,13 @@ namespace FFXIVClassic_Map_Server.actors.chara.ai.state
public override void Cleanup() public override void Cleanup()
{ {
if (owner.currentSubState == SetActorStatePacket.SUB_STATE_PLAYER) owner.SendChant(0, 0);
{
if (owner is Player)
{
((Player)owner).SendEndCastbar(); ((Player)owner).SendEndCastbar();
} }
// command casting duration owner.aiContainer.UpdateLastActionTime();
//var packets = new List<SubPacket>();
//owner.zone.BroadcastPacketsAroundActor(owner, packets);
} }
public BattleCommand GetSpell() public BattleCommand GetSpell()

View File

@ -90,7 +90,7 @@ namespace FFXIVClassic_Map_Server.actors.chara.ai.state
public override void OnComplete() public override void OnComplete()
{ {
skill.targetFind.FindWithinArea(target, skill.validTarget); skill.targetFind.FindWithinArea(target, skill.validTarget, skill.aoeTarget);
isCompleted = true; isCompleted = true;
var targets = skill.targetFind.GetTargets(); 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 // 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); action.amount = (ushort)lua.LuaEngine.CallLuaBattleCommandFunction(owner, skill, "weaponskill", "onSkillFinish", owner, target, skill, action);
actions[i++] = 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); 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 // todo: actually check proc rate/random chance of whatever effect
effectId = list[0].GetStatusEffectId(); 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; interrupt = true;
return; return;
} }
@ -139,12 +137,17 @@ namespace FFXIVClassic_Map_Server.actors.chara.ai.state
private bool CanUse() private bool CanUse()
{ {
return owner.CanWeaponSkill(target, skill); return owner.CanWeaponSkill(target, skill) && skill.IsValidTarget(owner, target);
} }
public BattleCommand GetWeaponSkill() public BattleCommand GetWeaponSkill()
{ {
return skill; return skill;
} }
public override void Cleanup()
{
owner.aiContainer.UpdateLastActionTime();
}
} }
} }

View File

@ -101,7 +101,7 @@ namespace FFXIVClassic_Map_Server.actors.chara.ai.utils
var scaledCost = spell.CalculateCost((uint)caster.charaWork.parameterSave.state_mainSkillLevel); var scaledCost = spell.CalculateCost((uint)caster.charaWork.parameterSave.state_mainSkillLevel);
// todo: calculate cost for mob/player // todo: calculate cost for mob/player
if (caster.currentSubState == SetActorStatePacket.SUB_STATE_MONSTER) if (caster is BattleNpc)
{ {
} }

View File

@ -36,7 +36,7 @@ namespace FFXIVClassic_Map_Server.Actors
private uint despawnTime; private uint despawnTime;
private uint spawnDistance; private uint spawnDistance;
public float spawnX, spawnY, spawnZ;
public BattleNpc(int actorNumber, ActorClass actorClass, string uniqueId, Area spawnedArea, float posX, float posY, float posZ, float rot, public BattleNpc(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)
: base(actorNumber, actorClass, uniqueId, spawnedArea, posX, posY, posZ, rot, actorState, animationId, customDisplayName) : base(actorNumber, actorClass, uniqueId, spawnedArea, posX, posY, posZ, rot, actorState, animationId, customDisplayName)
@ -174,6 +174,13 @@ namespace FFXIVClassic_Map_Server.Actors
} }
} }
public override void Despawn(DateTime tick)
{
aiContainer.ClearStates();
// todo: probably didnt need to make a new state...
aiContainer.ForceChangeState(new DespawnState(this, null, 0));
}
public void OnRoam(DateTime tick) public void OnRoam(DateTime tick)
{ {
// todo: move this to battlenpccontroller.. // todo: move this to battlenpccontroller..
@ -207,6 +214,8 @@ namespace FFXIVClassic_Map_Server.Actors
public override void OnAttack(State state, BattleAction action, ref BattleAction error) public override void OnAttack(State state, BattleAction action, ref BattleAction error)
{ {
base.OnAttack(state, action, ref error); base.OnAttack(state, action, ref error);
// todo: move this somewhere else prolly and change based on model/appearance (so maybe in Character.cs instead)
action.animation = 0x11001000; // (temporary) wolf anim
} }
} }
} }

View File

@ -1757,13 +1757,23 @@ namespace FFXIVClassic_Map_Server.Actors
{ {
// todo: should probably add another flag for battleTemp since all this uses reflection // todo: should probably add another flag for battleTemp since all this uses reflection
packets = new List<SubPacket>(); packets = new List<SubPacket>();
// we only want the latest update for the player
if ((updateFlags & ActorUpdateFlags.Position) != 0)
{
if (positionUpdates.Count > 1)
positionUpdates.RemoveRange(1, positionUpdates.Count - 1);
}
if ((updateFlags & ActorUpdateFlags.HpTpMp) != 0) if ((updateFlags & ActorUpdateFlags.HpTpMp) != 0)
{ {
var propPacketUtil = new ActorPropertyPacketUtil("charaWork.parameterSave", this); var propPacketUtil = new ActorPropertyPacketUtil("charaWork.parameterSave", this);
propPacketUtil.AddProperty($"charaWork.parameterSave.hp[{currentJob}]"); // todo: should this be using job as index?
propPacketUtil.AddProperty($"charaWork.parameterSave.hpMax[{currentJob}]"); propPacketUtil.AddProperty($"charaWork.parameterSave.hp[{0}]");
propPacketUtil.AddProperty($"charaWork.parameterSave.state_mainSkill[{currentJob}]"); propPacketUtil.AddProperty($"charaWork.parameterSave.hpMax[{0}]");
propPacketUtil.AddProperty($"charaWork.parameterSave.state_mainSkill[{0}]");
propPacketUtil.AddProperty($"charaWork.parameterSave.state_mainSkillLevel");
packets.AddRange(propPacketUtil.Done()); packets.AddRange(propPacketUtil.Done());
} }
@ -1937,6 +1947,7 @@ namespace FFXIVClassic_Map_Server.Actors
//If the returned value is outside the hotbar, it indicates it wasn't found. //If the returned value is outside the hotbar, it indicates it wasn't found.
private ushort FindFirstCommandSlotById(uint commandId) private ushort FindFirstCommandSlotById(uint commandId)
{ {
commandId |= 0xA0F00000;
ushort firstSlot = (ushort)(charaWork.commandBorder + 30); ushort firstSlot = (ushort)(charaWork.commandBorder + 30);
for (ushort i = charaWork.commandBorder; i < charaWork.commandBorder + 30; i++) for (ushort i = charaWork.commandBorder; i < charaWork.commandBorder + 30; i++)
@ -1950,13 +1961,51 @@ namespace FFXIVClassic_Map_Server.Actors
return firstSlot; return firstSlot;
} }
/* private void UpdateHotbarTimer(uint commandId, uint recastTimeSeconds)
public void SendBattleActionX01Packet(uint anim, uint effect, uint text = 0x756D, uint command = 27260, uint param = 0x01, uint idek = 0x01)
{ {
var packet = BattleActionX01Packet.BuildPacket(actorId, actorId, currentTarget != 0xC0000000 ? currentTarget : currentLockedTarget, (uint)anim, (uint)effect, (ushort)text, (ushort)command, (ushort)param, (byte)idek); ushort slot = FindFirstCommandSlotById(commandId);
QueuePacket(packet); charaWork.parameterSave.commandSlot_recastTime[slot - charaWork.commandBorder] = Utils.UnixTimeStampUTC(DateTime.Now.AddSeconds(recastTimeSeconds));
}*/ var slots = new List<ushort>();
slots.Add(slot);
UpdateRecastTimers(slots);
}
private uint GetHotbarTimer(uint commandId)
{
ushort slot = FindFirstCommandSlotById(commandId);
return charaWork.parameterSave.commandSlot_recastTime[slot - charaWork.commandBorder];
}
public override void Cast(uint spellId, uint targetId = 0)
{
if (aiContainer.CanChangeState())
aiContainer.Cast(zone.FindActorInArea<Character>(targetId == 0 ? currentTarget : targetId), spellId);
else if (aiContainer.GetCurrentState() is MagicState)
// You are already casting.
SendGameMessage(Server.GetWorldManager().GetActor(), 32536, 0x20);
else
// Please wait a moment and try again.
SendGameMessage(Server.GetWorldManager().GetActor(), 32535, 0x20);
}
public override void Ability(uint abilityId, uint targetId = 0)
{
if (aiContainer.CanChangeState())
aiContainer.Ability(zone.FindActorInArea<Character>(targetId == 0 ? currentTarget : targetId), abilityId);
else
// Please wait a moment and try again.
SendGameMessage(Server.GetWorldManager().GetActor(), 32535, 0x20);
}
public override void WeaponSkill(uint skillId, uint targetId = 0)
{
if (aiContainer.CanChangeState())
aiContainer.WeaponSkill(zone.FindActorInArea<Character>(targetId == 0 ? currentTarget : targetId), skillId);
else
// Please wait a moment and try again.
SendGameMessage(Server.GetWorldManager().GetActor(), 32535, 0x20);
}
public override bool IsValidTarget(Character target, ValidTarget validTarget) public override bool IsValidTarget(Character target, ValidTarget validTarget)
{ {
@ -1977,7 +2026,8 @@ namespace FFXIVClassic_Map_Server.Actors
// enemy only // enemy only
if ((validTarget & ValidTarget.Enemy) != 0) if ((validTarget & ValidTarget.Enemy) != 0)
{ {
if (target.currentSubState == SetActorStatePacket.SUB_STATE_NONE) // todo: this seems ambiguous
if (target.isStatic)
{ {
// That command cannot be performed on the current target. // That command cannot be performed on the current target.
SendGameMessage(Server.GetWorldManager().GetActor(), 32547, 0x20); SendGameMessage(Server.GetWorldManager().GetActor(), 32547, 0x20);
@ -1990,7 +2040,7 @@ namespace FFXIVClassic_Map_Server.Actors
return false; return false;
} }
// todo: pvp? // todo: pvp?
if (target.currentSubState == currentSubState) if (target.allegiance == allegiance)
{ {
// That command cannot be performed on an ally. // That command cannot be performed on an ally.
SendGameMessage(Server.GetWorldManager().GetActor(), 32549, 0x20); SendGameMessage(Server.GetWorldManager().GetActor(), 32549, 0x20);
@ -1998,14 +2048,15 @@ namespace FFXIVClassic_Map_Server.Actors
} }
} }
if ((validTarget & ValidTarget.Ally) != 0 && target.currentSubState != currentSubState) if ((validTarget & ValidTarget.Ally) != 0 && target.allegiance != allegiance)
{ {
// That command cannot be performed on the current target. // That command cannot be performed on the current target.
SendGameMessage(Server.GetWorldManager().GetActor(), 32547, 0x20); SendGameMessage(Server.GetWorldManager().GetActor(), 32547, 0x20);
return false; return false;
} }
if ((validTarget & ValidTarget.NPC) != 0 && target.currentSubState == SetActorStatePacket.SUB_STATE_NONE) // todo: isStatic seems ambiguous?
if ((validTarget & ValidTarget.NPC) != 0 && target.isStatic)
return true; return true;
// todo: why is player always zoning? // todo: why is player always zoning?
@ -2022,7 +2073,13 @@ namespace FFXIVClassic_Map_Server.Actors
public override bool CanCast(Character target, BattleCommand spell) public override bool CanCast(Character target, BattleCommand spell)
{ {
// todo: move the ability specific stuff to ability.cs if (GetHotbarTimer(spell.id) > Utils.UnixTimeStampUTC())
{
// todo: this needs confirming
// Please wait a moment and try again.
SendGameMessage(Server.GetWorldManager().GetActor(), 32535, 0x20, (uint)spell.id);
return false;
}
if (target == null) if (target == null)
{ {
// Target does not exist. // Target does not exist.
@ -2046,6 +2103,13 @@ namespace FFXIVClassic_Map_Server.Actors
public override bool CanWeaponSkill(Character target, BattleCommand skill) public override bool CanWeaponSkill(Character target, BattleCommand skill)
{ {
// todo: see worldmaster ids 32558~32557 for proper ko message and stuff // todo: see worldmaster ids 32558~32557 for proper ko message and stuff
if (GetHotbarTimer(skill.id) > Utils.UnixTimeStampUTC())
{
// todo: this needs confirming
// Please wait a moment and try again.
SendGameMessage(Server.GetWorldManager().GetActor(), 32535, 0x20, (uint)skill.id);
return false;
}
if (target == null) if (target == null)
{ {
// Target does not exist. // Target does not exist.
@ -2069,7 +2133,8 @@ namespace FFXIVClassic_Map_Server.Actors
public override void OnAttack(State state, BattleAction action, ref BattleAction error) public override void OnAttack(State state, BattleAction action, ref BattleAction error)
{ {
base.OnAttack(state, action, ref error); base.OnAttack(state, action, ref error);
// todo: switch based on main weap (also probably move this anim assignment somewhere else)
action.animation = 0x19001000;
if (error == null) if (error == null)
{ {
// melee attack animation // melee attack animation
@ -2081,5 +2146,24 @@ namespace FFXIVClassic_Map_Server.Actors
((BattleNpc)target).hateContainer.UpdateHate(this, action.amount); ((BattleNpc)target).hateContainer.UpdateHate(this, action.amount);
} }
} }
public override void OnCast(State state, BattleAction[] actions, ref BattleAction[] errors)
{
// todo: update hotbar timers to skill's recast time (also needs to be done on class change or equip crap)
base.OnCast(state, actions, ref errors);
var spell = ((MagicState)state).GetSpell();
// todo: should just make a thing that updates the one slot cause this is dumb as hell
UpdateHotbarTimer(spell.id, spell.recastTimeSeconds);
}
public override void OnWeaponSkill(State state, BattleAction[] actions, ref BattleAction[] errors)
{
// todo: update hotbar timers to skill's recast time (also needs to be done on class change or equip crap)
base.OnWeaponSkill(state, actions, ref errors);
var skill = ((WeaponSkillState)state).GetWeaponSkill();
// todo: should just make a thing that updates the one slot cause this is dumb as hell
UpdateHotbarTimer(skill.id, skill.recastTimeSeconds);
}
} }
} }

View File

@ -86,7 +86,7 @@ namespace FFXIVClassic_Map_Server.dataobjects
playerActor.rotation = rot; playerActor.rotation = rot;
playerActor.moveState = moveState; playerActor.moveState = moveState;
GetActor().GetZone().UpdateActorPosition(GetActor()); //GetActor().GetZone().UpdateActorPosition(GetActor());
playerActor.QueuePositionUpdate(new Vector3(x,y,z)); playerActor.QueuePositionUpdate(new Vector3(x,y,z));
} }

View File

@ -8,14 +8,12 @@ Switches between active and passive mode states
--]] --]]
function onEventStarted(player, command, triggerName) function onEventStarted(player, command, triggerName)
if (player:GetState() == 0) then if (player.newMainState == 0x0000) then
player.ChangeState(2); player.Engage(0, 0x0002);
player.Engage(); elseif (player.newMainState == 0x0002) then
elseif (player:GetState() == 2) then player.Disengage(0x0000);
player:ChangeState(0);
player.Disengage();
end end
player:endEvent(); player:endEvent();
sendSignal("playerActive"); sendSignal("playerActive");

View File

@ -30,6 +30,8 @@ CREATE TABLE `server_battle_commands` (
`requirements` smallint(5) unsigned NOT NULL, `requirements` smallint(5) unsigned NOT NULL,
`validTarget` tinyint(3) unsigned NOT NULL, `validTarget` tinyint(3) unsigned NOT NULL,
`aoeType` tinyint(3) unsigned NOT NULL, `aoeType` tinyint(3) unsigned NOT NULL,
`aoeRange` int(10) NOT NULL DEFAULT '0',
`aoeTarget` tinyint(3) NOT NULL,
`numHits` tinyint(3) unsigned NOT NULL, `numHits` tinyint(3) unsigned NOT NULL,
`positionBonus` tinyint(3) unsigned NOT NULL, `positionBonus` tinyint(3) unsigned NOT NULL,
`procRequirement` tinyint(3) unsigned NOT NULL, `procRequirement` tinyint(3) unsigned NOT NULL,
@ -45,7 +47,7 @@ CREATE TABLE `server_battle_commands` (
`effectAnimation` smallint(5) unsigned NOT NULL, `effectAnimation` smallint(5) unsigned NOT NULL,
`modelAnimation` smallint(5) unsigned NOT NULL, `modelAnimation` smallint(5) unsigned NOT NULL,
`animationDuration` smallint(5) unsigned NOT NULL, `animationDuration` smallint(5) unsigned NOT NULL,
`aoeRange` int(10) NOT NULL DEFAULT '0', `battleAnimation` int(10) unsigned NOT NULL DEFAULT '0',
PRIMARY KEY (`id`) PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8; ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
/*!40101 SET character_set_client = @saved_cs_client */; /*!40101 SET character_set_client = @saved_cs_client */;
@ -57,148 +59,148 @@ CREATE TABLE `server_battle_commands` (
LOCK TABLES `server_battle_commands` WRITE; LOCK TABLES `server_battle_commands` WRITE;
/*!40000 ALTER TABLE `server_battle_commands` DISABLE KEYS */; /*!40000 ALTER TABLE `server_battle_commands` DISABLE KEYS */;
set autocommit=0; set autocommit=0;
INSERT INTO `server_battle_commands` VALUES (27100,'second_wind',2,6,3,1,0,1,0,0,5,0,0,0,0,45,0,0,14,519,2,2,0); INSERT INTO `server_battle_commands` VALUES (27100,'second_wind',2,6,3,1,0,0,0,1,0,0,5,0,0,0,0,45,0,0,14,519,2,2,234889735);
INSERT INTO `server_battle_commands` VALUES (27101,'blindside',2,14,3,1,0,1,0,0,5,0,60,0,0,60,0,0,14,635,2,2,0); INSERT INTO `server_battle_commands` VALUES (27101,'blindside',2,14,3,1,0,0,0,1,0,0,5,0,60,0,0,60,0,0,14,635,2,2,234889851);
INSERT INTO `server_battle_commands` VALUES (27102,'taunt',2,42,4,32,0,1,0,0,5,5,0,0,0,60,0,0,14,517,2,2,0); INSERT INTO `server_battle_commands` VALUES (27102,'taunt',2,42,4,32,0,0,0,1,0,0,5,5,0,0,0,60,0,0,14,517,2,2,234889733);
INSERT INTO `server_battle_commands` VALUES (27103,'featherfoot',2,2,3,1,0,1,0,0,5,0,30,0,0,60,0,0,14,535,2,2,0); INSERT INTO `server_battle_commands` VALUES (27103,'featherfoot',2,2,3,1,0,0,0,1,0,0,5,0,30,0,0,60,0,0,14,535,2,2,234889751);
INSERT INTO `server_battle_commands` VALUES (27104,'fists_of_fire',2,34,4,1,0,1,0,0,5,0,0,0,0,10,0,0,14,684,2,2,0); INSERT INTO `server_battle_commands` VALUES (27104,'fists_of_fire',2,34,4,1,0,0,0,1,0,0,5,0,0,0,0,10,0,0,14,684,2,2,234889900);
INSERT INTO `server_battle_commands` VALUES (27105,'fists_of_earth',2,22,4,1,0,1,0,0,5,0,0,0,0,10,0,0,14,685,2,2,0); INSERT INTO `server_battle_commands` VALUES (27105,'fists_of_earth',2,22,4,1,0,0,0,1,0,0,5,0,0,0,0,10,0,0,14,685,2,2,234889901);
INSERT INTO `server_battle_commands` VALUES (27106,'hundred_fists',15,50,0,0,0,1,0,0,5,0,0,0,0,900,0,0,14,712,2,2,0); INSERT INTO `server_battle_commands` VALUES (27106,'hundred_fists',15,50,0,0,0,0,0,1,0,0,5,0,0,0,0,900,0,0,14,712,2,2,234889928);
INSERT INTO `server_battle_commands` VALUES (27107,'spinning_heel',15,35,0,0,0,1,0,0,5,0,0,0,0,120,0,0,14,718,2,2,0); INSERT INTO `server_battle_commands` VALUES (27107,'spinning_heel',15,35,0,0,0,0,0,1,0,0,5,0,0,0,0,120,0,0,14,718,2,2,234889934);
INSERT INTO `server_battle_commands` VALUES (27108,'shoulder_tackle',15,30,0,0,0,1,0,0,5,0,0,0,0,60,0,0,18,1048,205,2,0); INSERT INTO `server_battle_commands` VALUES (27108,'shoulder_tackle',15,30,0,0,0,0,0,1,0,0,5,0,0,0,0,60,0,0,18,1048,205,2,302830616);
INSERT INTO `server_battle_commands` VALUES (27109,'fists_of_wind',15,40,0,0,0,1,0,0,5,0,0,0,0,10,0,0,14,720,2,2,0); INSERT INTO `server_battle_commands` VALUES (27109,'fists_of_wind',15,40,0,0,0,0,0,1,0,0,5,0,0,0,0,10,0,0,14,720,2,2,234889936);
INSERT INTO `server_battle_commands` VALUES (27110,'pummel',2,1,1,32,0,1,1,0,5,0,0,0,0,10,0,1000,18,1027,1,2,0); INSERT INTO `server_battle_commands` VALUES (27110,'pummel',2,1,1,32,0,0,0,1,1,0,5,0,0,0,0,10,0,1000,18,1027,1,2,301995011);
INSERT INTO `server_battle_commands` VALUES (27111,'concussive_blow',2,10,1,32,0,1,4,0,5,30,0,0,0,30,0,1500,18,20,3,2,0); INSERT INTO `server_battle_commands` VALUES (27111,'concussive_blow',2,10,1,32,0,0,0,1,4,0,5,30,0,0,0,30,0,1500,18,20,3,2,302002196);
INSERT INTO `server_battle_commands` VALUES (27112,'simian_thrash',2,50,4,32,0,1,0,0,5,0,0,0,0,80,0,2000,18,1003,202,2,0); INSERT INTO `server_battle_commands` VALUES (27112,'simian_thrash',2,50,4,32,0,0,0,1,0,0,5,0,0,0,0,80,0,2000,18,1003,202,2,302818283);
INSERT INTO `server_battle_commands` VALUES (27113,'aura_pulse',2,38,4,32,1,1,0,0,5,30,0,0,0,40,0,1500,18,66,203,2,0); INSERT INTO `server_battle_commands` VALUES (27113,'aura_pulse',2,38,4,32,1,0,0,1,0,0,5,30,0,0,0,40,0,1500,18,66,203,2,302821442);
INSERT INTO `server_battle_commands` VALUES (27114,'pounce',2,4,4,32,0,1,2,0,5,10,0,0,0,20,0,1500,18,8,3,2,0); INSERT INTO `server_battle_commands` VALUES (27114,'pounce',2,4,4,32,0,0,0,1,2,0,5,10,0,0,0,20,0,1500,18,8,3,2,302002184);
INSERT INTO `server_battle_commands` VALUES (27115,'demolish',2,30,1,32,0,1,0,0,5,0,0,0,0,30,0,1500,18,1028,2,2,0); INSERT INTO `server_battle_commands` VALUES (27115,'demolish',2,30,1,32,0,0,0,1,0,0,5,0,0,0,0,30,0,1500,18,1028,2,2,301999108);
INSERT INTO `server_battle_commands` VALUES (27116,'howling_fist',2,46,4,32,0,1,4,0,5,0,0,0,0,80,0,3000,18,1029,2,2,0); INSERT INTO `server_battle_commands` VALUES (27116,'howling_fist',2,46,4,32,0,0,0,1,4,0,5,0,0,0,0,80,0,3000,18,1029,2,2,301999109);
INSERT INTO `server_battle_commands` VALUES (27117,'sucker_punch',2,26,1,32,0,1,4,0,5,0,0,0,0,15,0,1000,18,73,3,2,0); INSERT INTO `server_battle_commands` VALUES (27117,'sucker_punch',2,26,1,32,0,0,0,1,4,0,5,0,0,0,0,15,0,1000,18,73,3,2,302002249);
INSERT INTO `server_battle_commands` VALUES (27118,'dragon_kick',15,45,0,0,0,1,0,0,5,0,0,0,0,60,0,2000,18,1041,204,2,0); INSERT INTO `server_battle_commands` VALUES (27118,'dragon_kick',15,45,0,0,0,0,0,1,0,0,5,0,0,0,0,60,0,2000,18,1041,204,2,302826513);
INSERT INTO `server_battle_commands` VALUES (27119,'haymaker',2,18,4,32,0,1,0,1,5,0,0,0,0,5,0,250,18,23,201,2,0); INSERT INTO `server_battle_commands` VALUES (27119,'haymaker',2,18,4,32,0,0,0,1,0,1,5,0,0,0,0,5,0,250,18,23,201,2,302813207);
INSERT INTO `server_battle_commands` VALUES (27140,'sentinel',3,22,3,1,0,1,0,0,5,0,15,0,0,90,0,0,14,526,2,2,0); INSERT INTO `server_battle_commands` VALUES (27140,'sentinel',3,22,3,1,0,0,0,1,0,0,5,0,15,0,0,90,0,0,14,526,2,2,234889742);
INSERT INTO `server_battle_commands` VALUES (27141,'aegis_boon',3,6,8,1,0,1,0,0,5,0,30,0,0,60,0,0,14,583,21,2,0); INSERT INTO `server_battle_commands` VALUES (27141,'aegis_boon',3,6,8,1,0,0,0,1,0,0,5,0,30,0,0,60,0,0,14,583,21,2,234967623);
INSERT INTO `server_battle_commands` VALUES (27142,'rampart',3,2,3,1,0,1,0,2,5,0,60,0,0,120,0,0,14,536,2,2,0); INSERT INTO `server_battle_commands` VALUES (27142,'rampart',3,2,3,1,0,0,0,1,0,2,5,0,60,0,0,120,0,0,14,536,2,2,234889752);
INSERT INTO `server_battle_commands` VALUES (27143,'tempered_will',3,42,8,1,0,1,0,0,5,0,20,0,0,180,0,0,14,515,2,2,0); INSERT INTO `server_battle_commands` VALUES (27143,'tempered_will',3,42,8,1,0,0,0,1,0,0,5,0,20,0,0,180,0,0,14,515,2,2,234889731);
INSERT INTO `server_battle_commands` VALUES (27144,'outmaneuver',3,34,8,1,0,1,0,0,5,0,30,0,0,90,0,0,14,512,21,2,0); INSERT INTO `server_battle_commands` VALUES (27144,'outmaneuver',3,34,8,1,0,0,0,1,0,0,5,0,30,0,0,90,0,0,14,512,21,2,234967552);
INSERT INTO `server_battle_commands` VALUES (27145,'flash',3,14,3,32,0,1,0,0,5,0,0,0,0,30,0,0,14,696,2,2,0); INSERT INTO `server_battle_commands` VALUES (27145,'flash',3,14,3,32,0,0,0,1,0,0,5,0,0,0,0,30,0,0,14,696,2,2,234889912);
INSERT INTO `server_battle_commands` VALUES (27146,'cover',16,30,0,0,0,1,0,0,5,0,15,0,0,60,0,0,14,725,2,2,0); INSERT INTO `server_battle_commands` VALUES (27146,'cover',16,30,0,0,0,0,0,1,0,0,5,0,15,0,0,60,0,0,14,725,2,2,234889941);
INSERT INTO `server_battle_commands` VALUES (27147,'divine_veil',16,35,0,0,0,1,0,0,5,0,20,0,0,60,0,0,14,713,2,2,0); INSERT INTO `server_battle_commands` VALUES (27147,'divine_veil',16,35,0,0,0,0,0,1,0,0,5,0,20,0,0,60,0,0,14,713,2,2,234889929);
INSERT INTO `server_battle_commands` VALUES (27148,'hallowed_ground',16,50,0,0,0,1,0,0,5,0,0,0,0,900,0,0,14,709,2,2,0); INSERT INTO `server_battle_commands` VALUES (27148,'hallowed_ground',16,50,0,0,0,0,0,1,0,0,5,0,0,0,0,900,0,0,14,709,2,2,234889925);
INSERT INTO `server_battle_commands` VALUES (27149,'holy_succor',16,40,0,0,0,1,0,0,15,0,0,0,2,10,100,0,1,701,1,2,0); INSERT INTO `server_battle_commands` VALUES (27149,'holy_succor',16,40,0,0,0,0,0,1,0,0,15,0,0,0,2,10,100,0,1,701,1,2,16782013);
INSERT INTO `server_battle_commands` VALUES (27150,'fast_blade',3,1,1,32,0,1,1,0,5,0,0,0,0,10,0,1000,18,1023,1,2,0); INSERT INTO `server_battle_commands` VALUES (27150,'fast_blade',3,1,1,32,0,0,0,1,1,0,5,0,0,0,0,10,0,1000,18,1023,1,2,301995007);
INSERT INTO `server_battle_commands` VALUES (27151,'flat_blade',3,26,1,32,0,1,0,0,5,0,0,0,0,10,0,1500,18,1024,2,2,0); INSERT INTO `server_battle_commands` VALUES (27151,'flat_blade',3,26,1,32,0,0,0,1,0,0,5,0,0,0,0,10,0,1500,18,1024,2,2,301999104);
INSERT INTO `server_battle_commands` VALUES (27152,'savage_blade',3,10,1,32,0,1,0,0,5,0,0,0,0,30,0,1000,18,1025,1,2,0); INSERT INTO `server_battle_commands` VALUES (27152,'savage_blade',3,10,1,32,0,0,0,1,0,0,5,0,0,0,0,30,0,1000,18,1025,1,2,301995009);
INSERT INTO `server_battle_commands` VALUES (27153,'goring_blade',3,50,8,32,0,1,2,0,5,30,0,0,0,60,0,3000,18,1026,301,2,0); INSERT INTO `server_battle_commands` VALUES (27153,'goring_blade',3,50,8,32,0,0,0,1,2,0,5,30,0,0,0,60,0,3000,18,1026,301,2,303223810);
INSERT INTO `server_battle_commands` VALUES (27154,'riot_blade',3,30,8,32,0,1,2,0,5,30,0,0,0,80,0,2000,18,75,2,2,0); INSERT INTO `server_battle_commands` VALUES (27154,'riot_blade',3,30,8,32,0,0,0,1,2,0,5,30,0,0,0,80,0,2000,18,75,2,2,301998155);
INSERT INTO `server_battle_commands` VALUES (27155,'rage_of_halone',3,46,8,32,0,1,0,0,5,0,0,0,0,20,0,1500,18,1008,302,2,0); INSERT INTO `server_battle_commands` VALUES (27155,'rage_of_halone',3,46,8,32,0,0,0,1,0,0,5,0,0,0,0,20,0,1500,18,1008,302,2,303227888);
INSERT INTO `server_battle_commands` VALUES (27156,'shield_bash',3,18,17,32,0,1,0,0,5,5,0,0,0,30,0,250,18,5,26,2,0); INSERT INTO `server_battle_commands` VALUES (27156,'shield_bash',3,18,17,32,0,0,0,1,0,0,5,5,0,0,0,30,0,250,18,5,26,2,302096389);
INSERT INTO `server_battle_commands` VALUES (27157,'war_drum',3,38,24,32,1,1,0,2,5,0,0,0,0,60,0,500,14,502,21,2,0); INSERT INTO `server_battle_commands` VALUES (27157,'war_drum',3,38,24,32,1,0,0,1,0,2,5,0,0,0,0,60,0,500,14,502,21,2,234967542);
INSERT INTO `server_battle_commands` VALUES (27158,'phalanx',3,4,8,1,0,1,0,0,5,0,0,0,0,5,0,250,18,32,1,2,0); INSERT INTO `server_battle_commands` VALUES (27158,'phalanx',3,4,8,1,0,0,0,1,0,0,5,0,0,0,0,5,0,250,18,32,1,2,301994016);
INSERT INTO `server_battle_commands` VALUES (27159,'spirits_within',16,45,0,0,0,1,0,0,5,0,0,0,0,60,0,3000,18,1044,304,2,0); INSERT INTO `server_battle_commands` VALUES (27159,'spirits_within',16,45,0,0,0,0,0,1,0,0,5,0,0,0,0,60,0,3000,18,1044,304,2,303236116);
INSERT INTO `server_battle_commands` VALUES (27180,'provoke',4,14,3,32,0,1,0,0,5,0,0,0,0,30,0,0,14,600,2,2,0); INSERT INTO `server_battle_commands` VALUES (27180,'provoke',4,14,3,32,0,0,0,1,0,0,5,0,0,0,0,30,0,0,14,600,2,2,234889816);
INSERT INTO `server_battle_commands` VALUES (27181,'foresight',4,2,3,1,0,1,0,0,5,0,30,0,0,60,0,0,14,545,2,2,0); INSERT INTO `server_battle_commands` VALUES (27181,'foresight',4,2,3,1,0,0,0,1,0,0,5,0,30,0,0,60,0,0,14,545,2,2,234889761);
INSERT INTO `server_battle_commands` VALUES (27182,'bloodbath',4,6,3,1,0,1,0,0,5,0,30,0,0,60,0,0,14,581,2,2,0); INSERT INTO `server_battle_commands` VALUES (27182,'bloodbath',4,6,3,1,0,0,0,1,0,0,5,0,30,0,0,60,0,0,14,581,2,2,234889797);
INSERT INTO `server_battle_commands` VALUES (27183,'berserk',4,22,32,1,0,1,0,0,5,0,0,0,0,10,0,0,14,682,2,2,0); INSERT INTO `server_battle_commands` VALUES (27183,'berserk',4,22,32,1,0,0,0,1,0,0,5,0,0,0,0,10,0,0,14,682,2,2,234889898);
INSERT INTO `server_battle_commands` VALUES (27184,'rampage',4,34,32,1,0,1,0,0,5,0,0,0,0,10,0,0,14,546,2,2,0); INSERT INTO `server_battle_commands` VALUES (27184,'rampage',4,34,32,1,0,0,0,1,0,0,5,0,0,0,0,10,0,0,14,546,2,2,234889762);
INSERT INTO `server_battle_commands` VALUES (27185,'enduring_march',4,42,32,1,0,1,0,0,5,0,20,0,0,180,0,0,14,539,2,2,0); INSERT INTO `server_battle_commands` VALUES (27185,'enduring_march',4,42,32,1,0,0,0,1,0,0,5,0,20,0,0,180,0,0,14,539,2,2,234889755);
INSERT INTO `server_battle_commands` VALUES (27186,'vengeance',17,30,0,1,0,1,0,0,5,0,0,0,0,150,0,0,14,714,2,2,0); INSERT INTO `server_battle_commands` VALUES (27186,'vengeance',17,30,0,1,0,0,0,1,0,0,5,0,0,0,0,150,0,0,14,714,2,2,234889930);
INSERT INTO `server_battle_commands` VALUES (27187,'antagonize',17,35,0,1,0,1,0,0,5,0,0,0,0,120,0,0,14,715,2,2,0); INSERT INTO `server_battle_commands` VALUES (27187,'antagonize',17,35,0,1,0,0,0,1,0,0,5,0,0,0,0,120,0,0,14,715,2,2,234889931);
INSERT INTO `server_battle_commands` VALUES (27188,'collusion',17,40,0,4,0,1,0,0,5,0,0,0,0,90,0,0,14,711,2,2,0); INSERT INTO `server_battle_commands` VALUES (27188,'collusion',17,40,0,4,0,0,0,1,0,0,5,0,0,0,0,90,0,0,14,711,2,2,234889927);
INSERT INTO `server_battle_commands` VALUES (27189,'mighty_strikes',17,50,0,1,0,1,0,0,5,0,0,0,0,900,0,0,14,716,2,2,0); INSERT INTO `server_battle_commands` VALUES (27189,'mighty_strikes',17,50,0,1,0,0,0,1,0,0,5,0,0,0,0,900,0,0,14,716,2,2,234889932);
INSERT INTO `server_battle_commands` VALUES (27190,'heavy_swing',4,1,1,32,0,1,1,0,5,0,0,0,0,10,0,1000,18,14,1,2,0); INSERT INTO `server_battle_commands` VALUES (27190,'heavy_swing',4,1,1,32,0,0,0,1,1,0,5,0,0,0,0,10,0,1000,18,14,1,2,301993998);
INSERT INTO `server_battle_commands` VALUES (27191,'skull_sunder',4,10,1,32,0,1,0,0,5,0,0,0,0,30,0,1500,18,43,1,2,0); INSERT INTO `server_battle_commands` VALUES (27191,'skull_sunder',4,10,1,32,0,0,0,1,0,0,5,0,0,0,0,30,0,1500,18,43,1,2,301994027);
INSERT INTO `server_battle_commands` VALUES (27192,'steel_cyclone',17,45,0,32,1,1,0,0,5,0,0,0,0,30,0,2000,18,1040,404,2,0); INSERT INTO `server_battle_commands` VALUES (27192,'steel_cyclone',17,45,0,32,1,0,0,1,0,0,5,0,0,0,0,30,0,2000,18,1040,404,2,303645712);
INSERT INTO `server_battle_commands` VALUES (27193,'brutal_swing',4,4,1,32,0,1,4,0,5,0,0,0,0,20,0,1500,18,15,3,2,0); INSERT INTO `server_battle_commands` VALUES (27193,'brutal_swing',4,4,1,32,0,0,0,1,4,0,5,0,0,0,0,20,0,1500,18,15,3,2,302002191);
INSERT INTO `server_battle_commands` VALUES (27194,'maim',4,26,1,32,0,1,0,0,5,0,0,0,0,30,0,1500,18,88,1,2,0); INSERT INTO `server_battle_commands` VALUES (27194,'maim',4,26,1,32,0,0,0,1,0,0,5,0,0,0,0,30,0,1500,18,88,1,2,301994072);
INSERT INTO `server_battle_commands` VALUES (27195,'godsbane',4,50,32,32,0,1,0,0,5,0,0,0,0,60,0,3000,18,1014,402,2,0); INSERT INTO `server_battle_commands` VALUES (27195,'godsbane',4,50,32,32,0,0,0,1,0,0,5,0,0,0,0,60,0,3000,18,1014,402,2,303637494);
INSERT INTO `server_battle_commands` VALUES (27196,'path_of_the_storm',4,38,32,32,0,1,2,0,5,0,0,0,0,30,0,1500,18,44,401,2,0); INSERT INTO `server_battle_commands` VALUES (27196,'path_of_the_storm',4,38,32,32,0,0,0,1,2,0,5,0,0,0,0,30,0,1500,18,44,401,2,303632428);
INSERT INTO `server_battle_commands` VALUES (27197,'whirlwind',4,46,32,32,1,1,0,0,5,0,0,0,0,80,0,3000,18,1015,403,2,0); INSERT INTO `server_battle_commands` VALUES (27197,'whirlwind',4,46,32,32,1,0,0,1,0,0,5,0,0,0,0,80,0,3000,18,1015,403,2,303641591);
INSERT INTO `server_battle_commands` VALUES (27198,'fracture',4,18,32,32,0,1,0,4,5,8,0,0,0,40,0,500,18,42,3,2,0); INSERT INTO `server_battle_commands` VALUES (27198,'fracture',4,18,32,32,0,0,0,1,0,4,5,8,0,0,0,40,0,500,18,42,3,2,302002218);
INSERT INTO `server_battle_commands` VALUES (27199,'overpower',4,30,1,32,2,1,0,4,5,0,0,0,0,5,0,250,18,89,1,2,0); INSERT INTO `server_battle_commands` VALUES (27199,'overpower',4,30,1,32,2,0,0,1,0,4,5,0,0,0,0,5,0,250,18,89,1,2,301994073);
INSERT INTO `server_battle_commands` VALUES (27220,'hawks_eye',7,6,3,1,0,1,0,0,5,0,15,0,0,90,0,0,14,516,2,2,0); INSERT INTO `server_battle_commands` VALUES (27220,'hawks_eye',7,6,3,1,0,0,0,1,0,0,5,0,15,0,0,90,0,0,14,516,2,2,234889732);
INSERT INTO `server_battle_commands` VALUES (27221,'quelling_strikes',7,22,3,1,0,1,0,0,5,30,0,0,0,60,0,0,14,614,2,2,0); INSERT INTO `server_battle_commands` VALUES (27221,'quelling_strikes',7,22,3,1,0,0,0,1,0,0,5,30,0,0,0,60,0,0,14,614,2,2,234889830);
INSERT INTO `server_battle_commands` VALUES (27222,'decoy',7,2,3,1,0,1,0,0,15,0,60,0,0,90,100,0,14,565,2,2,0); INSERT INTO `server_battle_commands` VALUES (27222,'decoy',7,2,3,1,0,0,0,1,0,0,15,0,60,0,0,90,100,0,14,565,2,2,234889781);
INSERT INTO `server_battle_commands` VALUES (27223,'chameleon',7,42,3,1,0,1,0,0,5,0,0,0,0,180,0,0,14,504,2,2,0); INSERT INTO `server_battle_commands` VALUES (27223,'chameleon',7,42,3,1,0,0,0,1,0,0,5,0,0,0,0,180,0,0,14,504,2,2,234889720);
INSERT INTO `server_battle_commands` VALUES (27224,'barrage',7,34,64,1,0,1,0,0,5,0,60,0,0,90,0,0,14,683,2,2,0); INSERT INTO `server_battle_commands` VALUES (27224,'barrage',7,34,64,1,0,0,0,1,0,0,5,0,60,0,0,90,0,0,14,683,2,2,234889899);
INSERT INTO `server_battle_commands` VALUES (27225,'raging_strikes',7,14,64,1,0,1,0,0,5,0,0,0,0,10,0,0,14,632,2,2,0); INSERT INTO `server_battle_commands` VALUES (27225,'raging_strikes',7,14,64,1,0,0,0,1,0,0,5,0,0,0,0,10,0,0,14,632,2,2,234889848);
INSERT INTO `server_battle_commands` VALUES (27226,'swiftsong',7,26,64,1,1,1,0,0,15,0,180,0,0,10,100,0,1,150,1,2,0); INSERT INTO `server_battle_commands` VALUES (27226,'swiftsong',7,26,64,1,1,0,0,1,0,0,15,0,180,0,0,10,100,0,1,150,1,2,16781462);
INSERT INTO `server_battle_commands` VALUES (27227,'battle_voice',18,50,0,1,1,1,0,0,5,0,0,0,0,900,0,0,14,721,2,2,0); INSERT INTO `server_battle_commands` VALUES (27227,'battle_voice',18,50,0,1,1,0,0,1,0,0,5,0,0,0,0,900,0,0,14,721,2,2,234889937);
INSERT INTO `server_battle_commands` VALUES (27228,'heavy_shot',7,1,1,32,0,1,0,0,5,0,0,0,0,10,0,1000,18,1036,4,2,0); INSERT INTO `server_battle_commands` VALUES (27228,'heavy_shot',7,1,1,32,0,0,0,1,0,0,5,0,0,0,0,10,0,1000,18,1036,4,2,302007308);
INSERT INTO `server_battle_commands` VALUES (27229,'leaden_arrow',7,10,1,32,0,1,0,0,5,30,0,0,0,30,0,1500,18,1035,4,2,0); INSERT INTO `server_battle_commands` VALUES (27229,'leaden_arrow',7,10,1,32,0,0,0,1,0,0,5,30,0,0,0,30,0,1500,18,1035,4,2,302007307);
INSERT INTO `server_battle_commands` VALUES (27230,'wide_volley',7,50,64,32,1,1,0,0,5,0,0,0,0,80,0,2000,18,18,703,2,0); INSERT INTO `server_battle_commands` VALUES (27230,'wide_volley',7,50,64,32,1,0,0,1,0,0,5,0,0,0,0,80,0,2000,18,18,703,2,304869394);
INSERT INTO `server_battle_commands` VALUES (27231,'quick_nock',7,38,64,32,2,1,0,0,5,0,0,0,0,180,0,1000,18,1017,702,2,0); INSERT INTO `server_battle_commands` VALUES (27231,'quick_nock',7,38,64,32,2,0,0,1,0,0,5,0,0,0,0,180,0,1000,18,1017,702,2,304866297);
INSERT INTO `server_battle_commands` VALUES (27232,'rain_of_death',18,45,0,32,1,1,0,0,5,0,0,0,0,30,0,3000,18,1037,704,2,0); INSERT INTO `server_battle_commands` VALUES (27232,'rain_of_death',18,45,0,32,1,0,0,1,0,0,5,0,0,0,0,30,0,3000,18,1037,704,2,304874509);
INSERT INTO `server_battle_commands` VALUES (27233,'piercing_arrow',7,4,1,32,0,1,0,0,5,0,0,0,0,20,0,1000,18,1038,1,2,0); INSERT INTO `server_battle_commands` VALUES (27233,'piercing_arrow',7,4,1,32,0,0,0,1,0,0,5,0,0,0,0,20,0,1000,18,1038,1,2,301995022);
INSERT INTO `server_battle_commands` VALUES (27234,'gloom_arrow',7,30,1,32,0,1,0,0,5,30,0,0,0,10,0,1000,18,1039,4,2,0); INSERT INTO `server_battle_commands` VALUES (27234,'gloom_arrow',7,30,1,32,0,0,0,1,0,0,5,30,0,0,0,10,0,1000,18,1039,4,2,302007311);
INSERT INTO `server_battle_commands` VALUES (27235,'bloodletter',7,46,64,32,0,1,0,0,5,30,0,0,0,80,0,1500,18,53,701,2,0); INSERT INTO `server_battle_commands` VALUES (27235,'bloodletter',7,46,64,32,0,0,0,1,0,0,5,30,0,0,0,80,0,1500,18,53,701,2,304861237);
INSERT INTO `server_battle_commands` VALUES (27236,'shadowbind',7,18,64,32,0,1,0,0,5,30,0,0,0,40,0,250,18,17,4,2,0); INSERT INTO `server_battle_commands` VALUES (27236,'shadowbind',7,18,64,32,0,0,0,1,0,0,5,30,0,0,0,40,0,250,18,17,4,2,302006289);
INSERT INTO `server_battle_commands` VALUES (27237,'ballad_of_magi',18,30,0,1,1,1,0,0,15,0,0,0,3,10,100,0,1,709,1,2,0); INSERT INTO `server_battle_commands` VALUES (27237,'ballad_of_magi',18,30,0,1,1,0,0,1,0,0,15,0,0,0,3,10,100,0,1,709,1,2,16782021);
INSERT INTO `server_battle_commands` VALUES (27238,'paeon_of_war',18,40,0,1,1,1,0,0,15,0,0,0,3,10,50,1000,1,710,1,2,0); INSERT INTO `server_battle_commands` VALUES (27238,'paeon_of_war',18,40,0,1,1,0,0,1,0,0,15,0,0,0,3,10,50,1000,1,710,1,2,16782022);
INSERT INTO `server_battle_commands` VALUES (27239,'minuet_of_rigor',18,35,0,1,1,1,0,0,15,0,0,0,3,10,100,0,1,711,1,2,0); INSERT INTO `server_battle_commands` VALUES (27239,'minuet_of_rigor',18,35,0,1,1,0,0,1,0,0,15,0,0,0,3,10,100,0,1,711,1,2,16782023);
INSERT INTO `server_battle_commands` VALUES (27258,'refill',7,1,0,1,0,1,0,0,5,0,0,0,0,0,0,0,0,0,0,2,0); INSERT INTO `server_battle_commands` VALUES (27258,'refill',7,1,0,1,0,0,0,1,0,0,5,0,0,0,0,0,0,0,0,0,0,2,0);
INSERT INTO `server_battle_commands` VALUES (27259,'light_shot',7,1,0,32,0,1,0,0,5,0,0,0,0,0,0,0,0,0,0,2,0); INSERT INTO `server_battle_commands` VALUES (27259,'light_shot',7,1,0,32,0,0,0,1,0,0,5,0,0,0,0,0,0,0,0,0,0,2,0);
INSERT INTO `server_battle_commands` VALUES (27260,'invigorate',8,14,3,1,0,1,0,0,5,0,30,0,0,90,0,0,14,575,2,2,0); INSERT INTO `server_battle_commands` VALUES (27260,'invigorate',8,14,3,1,0,0,0,1,0,0,5,0,30,0,0,90,0,0,14,575,2,2,234889791);
INSERT INTO `server_battle_commands` VALUES (27261,'power_surge',8,34,128,1,0,1,0,0,5,0,0,0,0,10,0,0,14,686,2,2,0); INSERT INTO `server_battle_commands` VALUES (27261,'power_surge',8,34,128,1,0,0,0,1,0,0,5,0,0,0,0,10,0,0,14,686,2,2,234889902);
INSERT INTO `server_battle_commands` VALUES (27262,'life_surge',8,22,128,1,0,1,0,0,5,0,0,0,0,15,0,250,14,687,2,2,0); INSERT INTO `server_battle_commands` VALUES (27262,'life_surge',8,22,128,1,0,0,0,1,0,0,5,0,0,0,0,15,0,250,14,687,2,2,234889903);
INSERT INTO `server_battle_commands` VALUES (27263,'dread_spike',8,42,128,1,0,1,0,0,5,0,0,0,0,120,0,0,14,686,2,2,0); INSERT INTO `server_battle_commands` VALUES (27263,'dread_spike',8,42,128,1,0,0,0,1,0,0,5,0,0,0,0,120,0,0,14,686,2,2,234889902);
INSERT INTO `server_battle_commands` VALUES (27264,'blood_for_blood',8,6,3,1,0,1,0,0,5,0,0,0,0,60,0,0,14,689,2,2,0); INSERT INTO `server_battle_commands` VALUES (27264,'blood_for_blood',8,6,3,1,0,0,0,1,0,0,5,0,0,0,0,60,0,0,14,689,2,2,234889905);
INSERT INTO `server_battle_commands` VALUES (27265,'keen_flurry',8,26,3,1,0,1,0,0,5,0,0,0,0,90,0,0,14,569,2,2,0); INSERT INTO `server_battle_commands` VALUES (27265,'keen_flurry',8,26,3,1,0,0,0,1,0,0,5,0,0,0,0,90,0,0,14,569,2,2,234889785);
INSERT INTO `server_battle_commands` VALUES (27266,'jump',19,30,0,32,0,1,0,0,5,0,0,0,0,60,0,0,18,1045,804,2,0); INSERT INTO `server_battle_commands` VALUES (27266,'jump',19,30,0,32,0,0,0,1,0,0,5,0,0,0,0,60,0,0,18,1045,804,2,305284117);
INSERT INTO `server_battle_commands` VALUES (27267,'elusive_jump',19,40,0,1,0,1,0,0,5,0,0,0,0,180,0,0,18,1046,806,2,0); INSERT INTO `server_battle_commands` VALUES (27267,'elusive_jump',19,40,0,1,0,0,0,1,0,0,5,0,0,0,0,180,0,0,18,1046,806,2,305292310);
INSERT INTO `server_battle_commands` VALUES (27268,'dragonfire_dive',19,50,0,32,1,1,0,0,5,0,0,0,0,900,0,0,18,1045,804,2,0); INSERT INTO `server_battle_commands` VALUES (27268,'dragonfire_dive',19,50,0,32,1,0,0,1,0,0,5,0,0,0,0,900,0,0,18,1045,804,2,305284117);
INSERT INTO `server_battle_commands` VALUES (27269,'true_thrust',8,1,1,32,0,1,1,0,5,0,0,0,0,10,0,1000,18,1030,2,2,0); INSERT INTO `server_battle_commands` VALUES (27269,'true_thrust',8,1,1,32,0,0,0,1,1,0,5,0,0,0,0,10,0,1000,18,1030,2,2,301999110);
INSERT INTO `server_battle_commands` VALUES (27270,'leg_sweep',8,30,1,32,1,1,0,0,5,8,0,0,0,30,0,1000,18,37,1,2,0); INSERT INTO `server_battle_commands` VALUES (27270,'leg_sweep',8,30,1,32,1,0,0,1,0,0,5,8,0,0,0,30,0,1000,18,37,1,2,301994021);
INSERT INTO `server_battle_commands` VALUES (27271,'doom_spike',8,46,128,32,3,1,0,0,5,0,0,0,0,60,0,3000,18,83,801,2,0); INSERT INTO `server_battle_commands` VALUES (27271,'doom_spike',8,46,128,32,3,0,0,1,0,0,5,0,0,0,0,60,0,3000,18,83,801,2,305270867);
INSERT INTO `server_battle_commands` VALUES (27272,'disembowel',19,35,0,32,0,1,0,0,5,0,0,0,0,30,0,750,18,1042,2,2,0); INSERT INTO `server_battle_commands` VALUES (27272,'disembowel',19,35,0,32,0,0,0,1,0,0,5,0,0,0,0,30,0,750,18,1042,2,2,301999122);
INSERT INTO `server_battle_commands` VALUES (27273,'heavy_thrust',8,10,1,32,0,1,0,0,5,4,0,0,0,20,0,1500,18,1031,1,2,0); INSERT INTO `server_battle_commands` VALUES (27273,'heavy_thrust',8,10,1,32,0,0,0,1,0,0,5,4,0,0,0,20,0,1500,18,1031,1,2,301995015);
INSERT INTO `server_battle_commands` VALUES (27274,'vorpal_thrust',8,2,1,32,0,1,2,0,5,0,0,0,0,20,0,1500,18,1032,2,2,0); INSERT INTO `server_battle_commands` VALUES (27274,'vorpal_thrust',8,2,1,32,0,0,0,1,2,0,5,0,0,0,0,20,0,1500,18,1032,2,2,301999112);
INSERT INTO `server_battle_commands` VALUES (27275,'impulse_drive',8,18,1,32,0,1,4,0,5,0,0,0,0,30,0,1500,18,1033,2,2,0); INSERT INTO `server_battle_commands` VALUES (27275,'impulse_drive',8,18,1,32,0,0,0,1,4,0,5,0,0,0,0,30,0,1500,18,1033,2,2,301999113);
INSERT INTO `server_battle_commands` VALUES (27276,'chaos_thrust',8,50,128,32,0,1,0,0,5,0,0,0,0,80,0,3000,18,40,802,2,0); INSERT INTO `server_battle_commands` VALUES (27276,'chaos_thrust',8,50,128,32,0,0,0,1,0,0,5,0,0,0,0,80,0,3000,18,40,802,2,305274920);
INSERT INTO `server_battle_commands` VALUES (27277,'ring_of_talons',19,45,0,32,1,1,0,0,5,0,0,0,0,60,0,2000,18,1009,803,2,0); INSERT INTO `server_battle_commands` VALUES (27277,'ring_of_talons',19,45,0,32,1,0,0,1,0,0,5,0,0,0,0,60,0,2000,18,1009,803,2,305279985);
INSERT INTO `server_battle_commands` VALUES (27278,'feint',8,4,1,32,0,1,0,8,5,0,0,0,0,10,0,250,18,39,2,2,0); INSERT INTO `server_battle_commands` VALUES (27278,'feint',8,4,1,32,0,0,0,1,0,8,5,0,0,0,0,10,0,250,18,39,2,2,301998119);
INSERT INTO `server_battle_commands` VALUES (27279,'full_thrust',8,38,128,32,0,1,0,8,5,0,0,0,0,30,0,250,18,1034,801,2,0); INSERT INTO `server_battle_commands` VALUES (27279,'full_thrust',8,38,128,32,0,0,0,1,0,8,5,0,0,0,0,30,0,250,18,1034,801,2,305271818);
INSERT INTO `server_battle_commands` VALUES (27300,'dark_seal',22,14,3,1,0,1,0,0,5,0,30,0,0,90,0,0,14,518,2,2,0); INSERT INTO `server_battle_commands` VALUES (27300,'dark_seal',22,14,3,1,0,0,0,1,0,0,5,0,30,0,0,90,0,0,14,518,2,2,234889734);
INSERT INTO `server_battle_commands` VALUES (27301,'resonance',22,22,3,1,0,1,0,0,5,0,30,0,0,90,0,0,14,669,2,2,0); INSERT INTO `server_battle_commands` VALUES (27301,'resonance',22,22,3,1,0,0,0,1,0,0,5,0,30,0,0,90,0,0,14,669,2,2,234889885);
INSERT INTO `server_battle_commands` VALUES (27302,'excruciate',22,38,256,1,0,1,0,0,5,0,30,0,0,90,0,0,14,694,2,2,0); INSERT INTO `server_battle_commands` VALUES (27302,'excruciate',22,38,256,1,0,0,0,1,0,0,5,0,30,0,0,90,0,0,14,694,2,2,234889910);
INSERT INTO `server_battle_commands` VALUES (27303,'necrogenesis',22,6,3,1,0,1,0,0,5,0,30,0,0,90,0,0,14,695,2,2,0); INSERT INTO `server_battle_commands` VALUES (27303,'necrogenesis',22,6,3,1,0,0,0,1,0,0,5,0,30,0,0,90,0,0,14,695,2,2,234889911);
INSERT INTO `server_battle_commands` VALUES (27304,'parsimony',22,2,256,1,0,1,0,0,5,0,30,0,0,90,0,0,14,568,2,2,0); INSERT INTO `server_battle_commands` VALUES (27304,'parsimony',22,2,256,1,0,0,0,1,0,0,5,0,30,0,0,90,0,0,14,568,2,2,234889784);
INSERT INTO `server_battle_commands` VALUES (27305,'convert',26,30,0,1,0,1,0,0,5,0,0,0,0,450,0,0,14,724,2,2,0); INSERT INTO `server_battle_commands` VALUES (27305,'convert',26,30,0,1,0,0,0,1,0,0,5,0,0,0,0,450,0,0,14,724,2,2,234889940);
INSERT INTO `server_battle_commands` VALUES (27306,'sleep',22,42,256,32,0,1,0,0,15,60,0,0,3,0,75,0,1,651,1,2,0); INSERT INTO `server_battle_commands` VALUES (27306,'sleep',22,42,256,32,0,0,0,1,0,0,15,60,0,0,3,0,75,0,1,651,1,2,16781963);
INSERT INTO `server_battle_commands` VALUES (27307,'sanguine_rite',22,30,3,1,0,1,0,0,15,0,20,0,0,60,120,0,1,152,1,2,0); INSERT INTO `server_battle_commands` VALUES (27307,'sanguine_rite',22,30,3,1,0,0,0,1,0,0,15,0,20,0,0,60,120,0,1,152,1,2,16781464);
INSERT INTO `server_battle_commands` VALUES (27308,'blizzard',22,4,256,32,0,1,0,0,15,30,0,0,3,10,90,0,1,502,1,2,0); INSERT INTO `server_battle_commands` VALUES (27308,'blizzard',22,4,256,32,0,0,0,1,0,0,15,30,0,0,3,10,90,0,1,502,1,2,16781814);
INSERT INTO `server_battle_commands` VALUES (27309,'blizzara',22,26,256,32,1,1,0,0,15,30,0,0,0,40,150,0,1,506,1,2,0); INSERT INTO `server_battle_commands` VALUES (27309,'blizzara',22,26,256,32,1,0,0,1,0,0,15,30,0,0,0,40,150,0,1,506,1,2,16781818);
INSERT INTO `server_battle_commands` VALUES (27310,'fire',22,10,3,32,1,1,0,0,15,0,0,0,3,8,105,0,1,501,1,2,0); INSERT INTO `server_battle_commands` VALUES (27310,'fire',22,10,3,32,1,0,0,1,0,0,15,0,0,0,3,8,105,0,1,501,1,2,16781813);
INSERT INTO `server_battle_commands` VALUES (27311,'fira',22,34,3,32,1,1,0,0,15,0,0,0,5,16,180,0,1,504,1,2,0); INSERT INTO `server_battle_commands` VALUES (27311,'fira',22,34,3,32,1,0,0,1,0,0,15,0,0,0,5,16,180,0,1,504,1,2,16781816);
INSERT INTO `server_battle_commands` VALUES (27312,'firaga',22,50,256,32,1,1,0,0,15,0,0,0,8,7,255,0,1,700,1,2,0); INSERT INTO `server_battle_commands` VALUES (27312,'firaga',22,50,256,32,1,0,0,1,0,0,15,0,0,0,8,7,255,0,1,700,1,2,16782012);
INSERT INTO `server_battle_commands` VALUES (27313,'thunder',22,1,3,32,0,1,0,0,15,0,0,0,2,6,75,0,1,503,1,2,0); INSERT INTO `server_battle_commands` VALUES (27313,'thunder',22,1,3,32,0,0,0,1,0,0,15,0,0,0,2,6,75,0,1,503,1,2,16781815);
INSERT INTO `server_battle_commands` VALUES (27314,'thundara',22,18,256,32,0,1,0,0,15,4,0,0,0,30,135,0,1,508,1,2,0); INSERT INTO `server_battle_commands` VALUES (27314,'thundara',22,18,256,32,0,0,0,1,0,0,15,4,0,0,0,30,135,0,1,508,1,2,16781820);
INSERT INTO `server_battle_commands` VALUES (27315,'thundaga',22,46,256,32,0,1,0,0,15,0,0,0,5,45,195,0,1,509,1,2,0); INSERT INTO `server_battle_commands` VALUES (27315,'thundaga',22,46,256,32,0,0,0,1,0,0,15,0,0,0,5,45,195,0,1,509,1,2,16781821);
INSERT INTO `server_battle_commands` VALUES (27316,'burst',26,50,0,32,0,1,0,0,15,0,0,0,4,900,90,0,1,705,1,2,0); INSERT INTO `server_battle_commands` VALUES (27316,'burst',26,50,0,32,0,0,0,1,0,0,15,0,0,0,4,900,90,0,1,705,1,2,16782017);
INSERT INTO `server_battle_commands` VALUES (27317,'sleepga',26,45,0,32,1,1,0,0,15,0,0,0,4,0,100,0,1,704,1,2,0); INSERT INTO `server_battle_commands` VALUES (27317,'sleepga',26,45,0,32,1,0,0,1,0,0,15,0,0,0,4,0,100,0,1,704,1,2,16782016);
INSERT INTO `server_battle_commands` VALUES (27318,'flare',26,40,0,32,1,1,0,0,15,0,0,0,8,120,200,0,1,706,1,2,0); INSERT INTO `server_battle_commands` VALUES (27318,'flare',26,40,0,32,1,0,0,1,0,0,15,0,0,0,8,120,200,0,1,706,1,2,16782018);
INSERT INTO `server_battle_commands` VALUES (27319,'freeze',26,35,0,32,0,1,0,0,15,0,0,0,5,120,120,0,1,707,1,2,0); INSERT INTO `server_battle_commands` VALUES (27319,'freeze',26,35,0,32,0,0,0,1,0,0,15,0,0,0,5,120,120,0,1,707,1,2,16782019);
INSERT INTO `server_battle_commands` VALUES (27340,'sacred_prism',23,34,3,1,0,1,0,0,5,0,60,0,0,90,0,0,14,690,2,2,0); INSERT INTO `server_battle_commands` VALUES (27340,'sacred_prism',23,34,3,1,0,0,0,1,0,0,5,0,60,0,0,90,0,0,14,690,2,2,234889906);
INSERT INTO `server_battle_commands` VALUES (27341,'shroud_of_saints',23,38,512,1,0,1,0,0,5,0,20,0,0,180,0,0,14,691,2,2,0); INSERT INTO `server_battle_commands` VALUES (27341,'shroud_of_saints',23,38,512,1,0,0,0,1,0,0,5,0,20,0,0,180,0,0,14,691,2,2,234889907);
INSERT INTO `server_battle_commands` VALUES (27342,'cleric_stance',23,10,512,1,0,1,0,0,5,0,0,0,0,30,0,0,14,692,2,2,0); INSERT INTO `server_battle_commands` VALUES (27342,'cleric_stance',23,10,512,1,0,0,0,1,0,0,5,0,0,0,0,30,0,0,14,692,2,2,234889908);
INSERT INTO `server_battle_commands` VALUES (27343,'blissful_mind',23,14,512,1,0,1,0,0,5,0,0,0,0,30,0,0,14,693,2,2,0); INSERT INTO `server_battle_commands` VALUES (27343,'blissful_mind',23,14,512,1,0,0,0,1,0,0,5,0,0,0,0,30,0,0,14,693,2,2,234889909);
INSERT INTO `server_battle_commands` VALUES (27344,'presence_of_mind',27,30,0,1,0,1,0,0,5,0,0,0,0,300,0,0,14,722,2,2,0); INSERT INTO `server_battle_commands` VALUES (27344,'presence_of_mind',27,30,0,1,0,0,0,1,0,0,5,0,0,0,0,300,0,0,14,722,2,2,234889938);
INSERT INTO `server_battle_commands` VALUES (27345,'benediction',27,50,0,1,1,1,0,0,5,0,0,0,0,900,0,0,14,723,2,2,0); INSERT INTO `server_battle_commands` VALUES (27345,'benediction',27,50,0,1,1,0,0,1,0,0,5,0,0,0,0,900,0,0,14,723,2,2,234889939);
INSERT INTO `server_battle_commands` VALUES (27346,'cure',23,2,3,2,0,1,0,0,15,0,0,0,2,5,40,0,1,101,1,2,0); INSERT INTO `server_battle_commands` VALUES (27346,'cure',23,2,3,2,0,0,0,1,0,0,15,0,0,0,2,5,40,0,1,101,1,2,16781413);
INSERT INTO `server_battle_commands` VALUES (27347,'cura',23,30,512,2,0,1,0,0,15,0,0,0,2,5,100,0,1,103,1,2,0); INSERT INTO `server_battle_commands` VALUES (27347,'cura',23,30,512,2,0,0,0,1,0,0,15,0,0,0,2,5,100,0,1,103,1,2,16781415);
INSERT INTO `server_battle_commands` VALUES (27348,'curaga',23,46,512,4,1,1,0,0,15,0,0,0,3,10,150,0,1,146,1,2,0); INSERT INTO `server_battle_commands` VALUES (27348,'curaga',23,46,512,4,1,0,0,1,0,0,15,0,0,0,3,10,150,0,1,146,1,2,16781458);
INSERT INTO `server_battle_commands` VALUES (27349,'raise',23,18,512,2,0,1,0,0,15,0,0,0,10,300,150,0,1,148,1,2,0); INSERT INTO `server_battle_commands` VALUES (27349,'raise',23,18,512,2,0,0,0,1,0,0,15,0,0,0,10,300,150,0,1,148,1,2,16781460);
INSERT INTO `server_battle_commands` VALUES (27350,'stoneskin',23,26,3,2,0,1,0,0,15,0,300,0,3,30,50,0,1,133,1,2,0); INSERT INTO `server_battle_commands` VALUES (27350,'stoneskin',23,26,3,2,0,0,0,1,0,0,15,0,300,0,3,30,50,0,1,133,1,2,16781445);
INSERT INTO `server_battle_commands` VALUES (27351,'protect',23,6,3,4,1,1,0,0,15,0,300,0,3,30,80,0,1,1085,1,2,0); INSERT INTO `server_battle_commands` VALUES (27351,'protect',23,6,3,4,1,0,0,1,0,0,15,0,300,0,3,30,80,0,1,1085,1,2,16782397);
INSERT INTO `server_battle_commands` VALUES (27352,'repose',23,50,0,32,0,1,0,0,15,0,0,0,3,0,80,0,1,151,1,2,0); INSERT INTO `server_battle_commands` VALUES (27352,'repose',23,50,0,32,0,0,0,1,0,0,15,0,0,0,3,0,80,0,1,151,1,2,16781463);
INSERT INTO `server_battle_commands` VALUES (27353,'aero',23,4,3,32,0,1,0,0,15,0,0,0,3,6,75,0,1,510,1,2,0); INSERT INTO `server_battle_commands` VALUES (27353,'aero',23,4,3,32,0,0,0,1,0,0,15,0,0,0,3,6,75,0,1,510,1,2,16781822);
INSERT INTO `server_battle_commands` VALUES (27354,'aerora',23,42,512,32,1,1,0,0,15,0,0,0,4,20,150,0,1,511,1,2,0); INSERT INTO `server_battle_commands` VALUES (27354,'aerora',23,42,512,32,1,0,0,1,0,0,15,0,0,0,4,20,150,0,1,511,1,2,16781823);
INSERT INTO `server_battle_commands` VALUES (27355,'stone',23,1,3,32,0,1,0,0,15,0,0,0,2,6,75,0,1,513,1,2,0); INSERT INTO `server_battle_commands` VALUES (27355,'stone',23,1,3,32,0,0,0,1,0,0,15,0,0,0,2,6,75,0,1,513,1,2,16781825);
INSERT INTO `server_battle_commands` VALUES (27356,'stonera',23,22,512,32,1,1,0,0,15,0,0,0,3,30,150,0,1,514,1,2,0); INSERT INTO `server_battle_commands` VALUES (27356,'stonera',23,22,512,32,1,0,0,1,0,0,15,0,0,0,3,30,150,0,1,514,1,2,16781826);
INSERT INTO `server_battle_commands` VALUES (27357,'esuna',27,40,0,2,0,1,0,0,15,0,0,0,2,10,40,0,1,702,1,2,0); INSERT INTO `server_battle_commands` VALUES (27357,'esuna',27,40,0,2,0,0,0,1,0,0,15,0,0,0,2,10,40,0,1,702,1,2,16782014);
INSERT INTO `server_battle_commands` VALUES (27358,'regen',27,35,0,2,0,1,0,0,15,0,0,0,2,5,20,0,1,703,1,2,0); INSERT INTO `server_battle_commands` VALUES (27358,'regen',27,35,0,2,0,0,0,1,0,0,15,0,0,0,2,5,20,0,1,703,1,2,16782015);
INSERT INTO `server_battle_commands` VALUES (27359,'holy',27,45,0,32,1,1,0,0,15,0,0,0,0,300,100,0,1,708,1,2,0); INSERT INTO `server_battle_commands` VALUES (27359,'holy',27,45,0,32,1,0,0,1,0,0,15,0,0,0,0,300,100,0,1,708,1,2,16782020);
/*!40000 ALTER TABLE `server_battle_commands` ENABLE KEYS */; /*!40000 ALTER TABLE `server_battle_commands` ENABLE KEYS */;
UNLOCK TABLES; UNLOCK TABLES;
commit; commit;
@ -212,4 +214,4 @@ commit;
/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */; /*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */;
/*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */; /*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */;
-- Dump completed on 2017-08-28 1:38:36 -- Dump completed on 2017-08-31 5:52:52