public static void CombatAction(CombatActionPack pack)
{
var attackerPos = pack.Attacker.GetPosition();
var packet = new Packet(Op.CombatActionPack, MabiId.Broadcast);
packet.PutInt(pack.Id);
packet.PutInt(pack.PrevId);
packet.PutByte(pack.Hit);
packet.PutByte((byte)pack.Type);
packet.PutByte(pack.Flags);
if ((pack.Flags & 1) == 1)
{
packet.PutInt(pack.BlockedByShieldPosX);
packet.PutInt(pack.BlockedByShieldPosY);
packet.PutLong(pack.ShieldCasterId);
}
// Actions
packet.PutInt(pack.Actions.Count);
Packet actionPacket = null;
foreach (var action in pack.Actions)
{
var pos = action.Creature.GetPosition();
if (actionPacket == null)
actionPacket = new Packet(Op.CombatAction, action.Creature.EntityId);
else
actionPacket.Clear(Op.CombatAction, action.Creature.EntityId);
actionPacket.PutInt(pack.Id);
actionPacket.PutLong(action.Creature.EntityId);
actionPacket.PutByte((byte)action.Flags);
actionPacket.PutShort(action.Stun);
actionPacket.PutUShort((ushort)action.SkillId);
actionPacket.PutUShort((ushort)action.SecondarySkillId);
// Official name for CombatAction is CombatScene, and both Actions are Combatant.
// Official client distinguish between Attacker and Defender simply by checking Flags. tachiorz
// AttackerAction
//if ((action.Flags & CombatActionFlags.Attacker) != 0)
if (action.Category == CombatActionCategory.Attack)
{
var aAction = action as AttackerAction;
actionPacket.PutLong(aAction.TargetId);
actionPacket.PutUInt((uint)aAction.Options);
actionPacket.PutByte(aAction.UsedWeaponSet);
actionPacket.PutByte(aAction.WeaponParameterType); // !aAction.Has(AttackerOptions.KnockBackHit2) ? 2 : 1)); // ?
actionPacket.PutInt(0); // [200200, NA233 (2016-08-12)] ?
actionPacket.PutInt(pos.X);
actionPacket.PutInt(pos.Y);
if ((aAction.Options & AttackerOptions.Dashed) != 0)
{
actionPacket.PutFloat(0); // DashedPosX
actionPacket.PutFloat(0); // DashedPosY
actionPacket.PutUInt(0); // DashDelay
}
if ((aAction.Options & AttackerOptions.PhaseAttack) != 0)
actionPacket.PutByte(aAction.Phase);
if ((aAction.Options & AttackerOptions.UseEffect) != 0)
actionPacket.PutLong(aAction.PropId);
}
// TargetAction
//if ((action.Flags & CombatActionFlags.TakeHit) != 0)
else if (action.Category == CombatActionCategory.Target && !action.Is(CombatActionType.None))
{
var tAction = action as TargetAction;
// Target used Defense or Counter
if ((action.Flags & CombatActionType.Attacker) != 0)
{
actionPacket.PutLong(tAction.Attacker.EntityId);
actionPacket.PutInt(0); // attacker Options
actionPacket.PutByte(tAction.UsedWeaponSet);
actionPacket.PutByte(tAction.WeaponParameterType);
actionPacket.PutInt(0); // [200200, NA233 (2016-08-12)] ?
actionPacket.PutInt(pos.X);
actionPacket.PutInt(pos.Y);
}
actionPacket.PutUInt((uint)tAction.Options);
actionPacket.PutFloat(tAction.Damage);
actionPacket.PutFloat(tAction.Wound);
actionPacket.PutInt((int)tAction.ManaDamage);
actionPacket.PutFloat(attackerPos.X - pos.X);
actionPacket.PutFloat(attackerPos.Y - pos.Y);
if (tAction.IsKnockBack)
{
actionPacket.PutFloat(pos.X);
actionPacket.PutFloat(pos.Y);
// [190200, NA203 (22.04.2015)]
{
actionPacket.PutInt(0);
}
}
if ((tAction.Options & TargetOptions.MultiHit) != 0)
{
actionPacket.PutUInt(0); // MultiHitDamageCount
actionPacket.PutUInt(0); // MultiHitDamageShowTime
}
actionPacket.PutByte((byte)tAction.EffectFlags);
actionPacket.PutInt(tAction.Delay);
actionPacket.PutLong(tAction.Attacker.EntityId);
}
packet.PutBin(actionPacket);
}
pack.Attacker.Region.Broadcast(packet, pack.Attacker);
}