Files
CypherCore/Game/Network/Packets/CombatLogPackets.cs
T
hondacrx 473cea0f06 Implemented Basic Creature Scaling
Trainer followup
Misc Fixes
2017-07-31 14:18:07 -04:00

705 lines
24 KiB
C#

/*
* Copyright (C) 2012-2017 CypherCore <http://github.com/CypherCore>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
using Framework.Constants;
using Framework.Dynamic;
using Game.Entities;
using System;
using System.Collections.Generic;
namespace Game.Network.Packets
{
class CombatLogServerPacket : ServerPacket
{
public CombatLogServerPacket(ServerOpcodes opcode, ConnectionType connection = ConnectionType.Realm) : base(opcode, connection)
{
LogData = new SpellCastLogData();
}
public override void Write() { }
public void DisableAdvancedCombatLogging()
{
LogData = null;
}
public void WriteLogDataBit()
{
_worldPacket.WriteBit(LogData != null);
}
public void FlushBits()
{
_worldPacket.FlushBits();
}
public void WriteLogData()
{
if (LogData != null)
LogData.Write(_worldPacket);
}
internal SpellCastLogData LogData;
}
class SpellNonMeleeDamageLog : CombatLogServerPacket
{
public SpellNonMeleeDamageLog() : base(ServerOpcodes.SpellNonMeleeDamageLog, ConnectionType.Instance) { }
public override void Write()
{
_worldPacket.WritePackedGuid(Me);
_worldPacket.WritePackedGuid(CasterGUID);
_worldPacket.WritePackedGuid(CastID);
_worldPacket.WriteInt32(SpellID);
_worldPacket.WriteInt32(SpellXSpellVisualID);
_worldPacket.WriteInt32(Damage);
_worldPacket.WriteInt32(Overkill);
_worldPacket.WriteUInt8(SchoolMask);
_worldPacket.WriteInt32(ShieldBlock);
_worldPacket.WriteInt32(Resisted);
_worldPacket.WriteInt32(Absorbed);
_worldPacket.WriteBit(Periodic);
_worldPacket.WriteBits(Flags, 7);
_worldPacket.WriteBit(false); // Debug info
WriteLogDataBit();
_worldPacket.WriteBit(SandboxScaling.HasValue);
FlushBits();
WriteLogData();
if (SandboxScaling.HasValue)
SandboxScaling.Value.Write(_worldPacket);
}
public ObjectGuid Me;
public ObjectGuid CasterGUID;
public ObjectGuid CastID;
public int SpellID;
public int SpellXSpellVisualID;
public int Damage;
public int Overkill;
public byte SchoolMask;
public int ShieldBlock;
public int Resisted;
public bool Periodic;
public int Absorbed;
public int Flags;
// Optional<SpellNonMeleeDamageLogDebugInfo> DebugInfo;
public Optional<SandboxScalingData> SandboxScaling = new Optional<SandboxScalingData>();
}
class EnvironmentalDamageLog : CombatLogServerPacket
{
public EnvironmentalDamageLog() : base(ServerOpcodes.EnvironmentalDamageLog) { }
public override void Write()
{
_worldPacket.WritePackedGuid(Victim);
_worldPacket.WriteUInt8(Type);
_worldPacket.WriteInt32(Amount);
_worldPacket.WriteInt32(Resisted);
_worldPacket.WriteInt32(Absorbed);
WriteLogDataBit();
FlushBits();
WriteLogData();
}
public ObjectGuid Victim;
public EnviromentalDamage Type;
public int Amount;
public int Resisted;
public int Absorbed;
}
class SpellExecuteLog : CombatLogServerPacket
{
public SpellExecuteLog() : base(ServerOpcodes.SpellExecuteLog, ConnectionType.Instance) { }
public override void Write()
{
_worldPacket.WritePackedGuid(Caster);
_worldPacket.WriteUInt32(SpellID);
_worldPacket.WriteUInt32(Effects.Count);
foreach (SpellLogEffect effect in Effects)
{
_worldPacket.WriteUInt32(effect.Effect);
_worldPacket.WriteUInt32(effect.PowerDrainTargets.Count);
_worldPacket.WriteUInt32(effect.ExtraAttacksTargets.Count);
_worldPacket.WriteUInt32(effect.DurabilityDamageTargets.Count);
_worldPacket.WriteUInt32(effect.GenericVictimTargets.Count);
_worldPacket.WriteUInt32(effect.TradeSkillTargets.Count);
_worldPacket.WriteUInt32(effect.FeedPetTargets.Count);
foreach (SpellLogEffectPowerDrainParams powerDrainTarget in effect.PowerDrainTargets)
{
_worldPacket.WritePackedGuid(powerDrainTarget.Victim);
_worldPacket.WriteUInt32(powerDrainTarget.Points);
_worldPacket.WriteUInt32(powerDrainTarget.PowerType);
_worldPacket.WriteFloat(powerDrainTarget.Amplitude);
}
foreach (SpellLogEffectExtraAttacksParams extraAttacksTarget in effect.ExtraAttacksTargets)
{
_worldPacket.WritePackedGuid(extraAttacksTarget.Victim);
_worldPacket.WriteUInt32(extraAttacksTarget.NumAttacks);
}
foreach (SpellLogEffectDurabilityDamageParams durabilityDamageTarget in effect.DurabilityDamageTargets)
{
_worldPacket.WritePackedGuid(durabilityDamageTarget.Victim);
_worldPacket.WriteInt32(durabilityDamageTarget.ItemID);
_worldPacket.WriteInt32(durabilityDamageTarget.Amount);
}
foreach (SpellLogEffectGenericVictimParams genericVictimTarget in effect.GenericVictimTargets)
_worldPacket.WritePackedGuid(genericVictimTarget.Victim);
foreach (SpellLogEffectTradeSkillItemParams tradeSkillTarget in effect.TradeSkillTargets)
_worldPacket.WriteInt32(tradeSkillTarget.ItemID);
foreach (SpellLogEffectFeedPetParams feedPetTarget in effect.FeedPetTargets)
_worldPacket.WriteInt32(feedPetTarget.ItemID);
}
WriteLogDataBit();
FlushBits();
WriteLogData();
}
public ObjectGuid Caster;
public uint SpellID;
public List<SpellLogEffect> Effects = new List<SpellLogEffect>();
public class SpellLogEffect
{
public int Effect;
public List<SpellLogEffectPowerDrainParams> PowerDrainTargets = new List<SpellLogEffectPowerDrainParams>();
public List<SpellLogEffectExtraAttacksParams> ExtraAttacksTargets = new List<SpellLogEffectExtraAttacksParams>();
public List<SpellLogEffectDurabilityDamageParams> DurabilityDamageTargets = new List<SpellLogEffectDurabilityDamageParams>();
public List<SpellLogEffectGenericVictimParams> GenericVictimTargets = new List<SpellLogEffectGenericVictimParams>();
public List<SpellLogEffectTradeSkillItemParams> TradeSkillTargets = new List<SpellLogEffectTradeSkillItemParams>();
public List<SpellLogEffectFeedPetParams> FeedPetTargets = new List<SpellLogEffectFeedPetParams>();
}
}
class SpellHealLog : CombatLogServerPacket
{
public SpellHealLog() : base(ServerOpcodes.SpellHealLog, ConnectionType.Instance) { }
public override void Write()
{
_worldPacket.WritePackedGuid(TargetGUID);
_worldPacket.WritePackedGuid(CasterGUID);
_worldPacket.WriteUInt32(SpellID);
_worldPacket.WriteUInt32(Health);
_worldPacket.WriteUInt32(OverHeal);
_worldPacket.WriteUInt32(Absorbed);
_worldPacket.WriteBit(Crit);
_worldPacket.WriteBit(CritRollMade.HasValue);
_worldPacket.WriteBit(CritRollNeeded.HasValue);
WriteLogDataBit();
_worldPacket.WriteBit(SandboxScaling.HasValue);
FlushBits();
WriteLogData();
if (CritRollMade.HasValue)
_worldPacket.WriteFloat(CritRollMade.Value);
if (CritRollNeeded.HasValue)
_worldPacket.WriteFloat(CritRollNeeded.Value);
if (SandboxScaling.HasValue)
SandboxScaling.Value.Write(_worldPacket);
}
public ObjectGuid CasterGUID;
public ObjectGuid TargetGUID;
public uint SpellID;
public uint Health;
public uint OverHeal;
public uint Absorbed;
public bool Crit;
public Optional<float> CritRollMade;
public Optional<float> CritRollNeeded;
Optional<SandboxScalingData> SandboxScaling = new Optional<SandboxScalingData>();
}
class SpellPeriodicAuraLog : CombatLogServerPacket
{
public SpellPeriodicAuraLog() : base(ServerOpcodes.SpellPeriodicAuraLog, ConnectionType.Instance) { }
public override void Write()
{
_worldPacket.WritePackedGuid(TargetGUID);
_worldPacket.WritePackedGuid(CasterGUID);
_worldPacket.WriteUInt32(SpellID);
_worldPacket.WriteUInt32(Effects.Count);
WriteLogDataBit();
FlushBits();
Effects.ForEach(p => p.Write(_worldPacket));
WriteLogData();
}
public ObjectGuid TargetGUID;
public ObjectGuid CasterGUID;
public uint SpellID;
public List<SpellLogEffect> Effects = new List<SpellLogEffect>();
public struct PeriodicalAuraLogEffectDebugInfo
{
public float CritRollMade;
public float CritRollNeeded;
}
public class SpellLogEffect
{
public void Write(WorldPacket data)
{
data.WriteUInt32(Effect);
data.WriteUInt32(Amount);
data.WriteUInt32(OverHealOrKill);
data.WriteUInt32(SchoolMaskOrPower);
data.WriteUInt32(AbsorbedOrAmplitude);
data.WriteUInt32(Resisted);
data.WriteBit(Crit);
data.WriteBit(DebugInfo.HasValue);
data.WriteBit(SandboxScaling.HasValue);
data.FlushBits();
if (SandboxScaling.HasValue)
SandboxScaling.Value.Write(data);
if (DebugInfo.HasValue)
{
data.WriteFloat(DebugInfo.Value.CritRollMade);
data.WriteFloat(DebugInfo.Value.CritRollNeeded);
}
}
public uint Effect;
public uint Amount;
public uint OverHealOrKill;
public uint SchoolMaskOrPower;
public uint AbsorbedOrAmplitude;
public uint Resisted;
public bool Crit;
public Optional<PeriodicalAuraLogEffectDebugInfo> DebugInfo;
public Optional<SandboxScalingData> SandboxScaling = new Optional<SandboxScalingData>();
}
}
class SpellInterruptLog : ServerPacket
{
public SpellInterruptLog() : base(ServerOpcodes.SpellInterruptLog, ConnectionType.Instance) { }
public override void Write()
{
_worldPacket.WritePackedGuid(Caster);
_worldPacket.WritePackedGuid(Victim);
_worldPacket.WriteUInt32(InterruptedSpellID);
_worldPacket.WriteUInt32(SpellID);
}
public ObjectGuid Caster;
public ObjectGuid Victim;
public uint InterruptedSpellID;
public uint SpellID;
}
class SpellDispellLog : ServerPacket
{
public SpellDispellLog() : base(ServerOpcodes.SpellDispellLog, ConnectionType.Instance) { }
public override void Write()
{
_worldPacket.WriteBit(IsSteal);
_worldPacket.WriteBit(IsBreak);
_worldPacket.WritePackedGuid(TargetGUID);
_worldPacket.WritePackedGuid(CasterGUID);
_worldPacket.WriteUInt32(DispelledBySpellID);
_worldPacket.WriteInt32(DispellData.Count);
foreach (var data in DispellData)
{
_worldPacket.WriteUInt32(data.SpellID);
_worldPacket.WriteBit(data.Harmful);
_worldPacket.WriteBit(data.Rolled.HasValue);
_worldPacket.WriteBit(data.Needed.HasValue);
if (data.Rolled.HasValue)
_worldPacket.WriteUInt32(data.Rolled.Value);
if (data.Needed.HasValue)
_worldPacket.WriteUInt32(data.Needed.Value);
_worldPacket.FlushBits();
}
}
public List<SpellDispellData> DispellData = new List<SpellDispellData>();
public ObjectGuid CasterGUID;
public ObjectGuid TargetGUID;
public uint DispelledBySpellID;
public bool IsBreak;
public bool IsSteal;
}
class SpellEnergizeLog : CombatLogServerPacket
{
public SpellEnergizeLog() : base(ServerOpcodes.SpellEnergizeLog, ConnectionType.Instance) { }
public override void Write()
{
_worldPacket.WritePackedGuid(TargetGUID);
_worldPacket.WritePackedGuid(CasterGUID);
_worldPacket.WriteUInt32(SpellID);
_worldPacket.WriteUInt32(Type);
_worldPacket.WriteInt32(Amount);
_worldPacket.WriteInt32(OverEnergize);
WriteLogDataBit();
FlushBits();
WriteLogData();
}
public ObjectGuid TargetGUID;
public ObjectGuid CasterGUID;
public uint SpellID;
public PowerType Type;
public int Amount;
public int OverEnergize;
}
class SpellInstakillLog : ServerPacket
{
public SpellInstakillLog() : base(ServerOpcodes.SpellInstakillLog, ConnectionType.Instance) { }
public override void Write()
{
_worldPacket.WritePackedGuid(Target);
_worldPacket.WritePackedGuid(Caster);
_worldPacket.WriteUInt32(SpellID);
}
public ObjectGuid Target;
public ObjectGuid Caster;
public uint SpellID;
}
class SpellMissLog : ServerPacket
{
public SpellMissLog() : base(ServerOpcodes.SpellMissLog, ConnectionType.Instance) { }
public override void Write()
{
_worldPacket.WriteUInt32(SpellID);
_worldPacket.WritePackedGuid(Caster);
_worldPacket.WriteUInt32(Entries);
foreach (SpellLogMissEntry missEntry in Entries)
missEntry.Write(_worldPacket);
}
public uint SpellID;
public ObjectGuid Caster;
public List<SpellLogMissEntry> Entries = new List<SpellLogMissEntry>();
}
class ProcResist : ServerPacket
{
public ProcResist() : base(ServerOpcodes.ProcResist) { }
public override void Write()
{
_worldPacket.WritePackedGuid(Caster);
_worldPacket.WritePackedGuid(Target);
_worldPacket.WriteUInt32(SpellID);
_worldPacket.WriteBit(Rolled.HasValue);
_worldPacket.WriteBit(Needed.HasValue);
_worldPacket.FlushBits();
if (Rolled.HasValue)
_worldPacket.WriteFloat(Rolled.Value);
if (Needed.HasValue)
_worldPacket.WriteFloat(Needed.Value);
}
public ObjectGuid Caster;
public ObjectGuid Target;
public uint SpellID;
public Optional<float> Rolled;
public Optional<float> Needed;
}
class SpellOrDamageImmune : ServerPacket
{
public SpellOrDamageImmune() : base(ServerOpcodes.SpellOrDamageImmune, ConnectionType.Instance) { }
public override void Write()
{
_worldPacket.WritePackedGuid(CasterGUID);
_worldPacket.WritePackedGuid(VictimGUID);
_worldPacket.WriteUInt32(SpellID);
_worldPacket.WriteBit(IsPeriodic);
_worldPacket.FlushBits();
}
public ObjectGuid CasterGUID;
public ObjectGuid VictimGUID;
public uint SpellID;
public bool IsPeriodic;
}
class SpellDamageShield : CombatLogServerPacket
{
public SpellDamageShield() : base(ServerOpcodes.SpellDamageShield, ConnectionType.Instance) { }
public override void Write()
{
_worldPacket.WritePackedGuid(Attacker);
_worldPacket.WritePackedGuid(Defender);
_worldPacket.WriteUInt32(SpellID);
_worldPacket.WriteUInt32(TotalDamage);
_worldPacket.WriteUInt32(OverKill);
_worldPacket.WriteUInt32(SchoolMask);
_worldPacket.WriteUInt32(LogAbsorbed);
WriteLogDataBit();
FlushBits();
WriteLogData();
}
public ObjectGuid Attacker;
public ObjectGuid Defender;
public uint SpellID;
public uint TotalDamage;
public uint OverKill;
public uint SchoolMask;
public uint LogAbsorbed;
}
class AttackerStateUpdate : CombatLogServerPacket
{
public AttackerStateUpdate() : base(ServerOpcodes.AttackerStateUpdate, ConnectionType.Instance)
{
SubDmg = new Optional<SubDamage>();
}
public override void Write()
{
WorldPacket attackRoundInfo = new WorldPacket();
attackRoundInfo.WriteUInt32(hitInfo);
attackRoundInfo.WritePackedGuid(AttackerGUID);
attackRoundInfo.WritePackedGuid(VictimGUID);
attackRoundInfo.WriteInt32(Damage);
attackRoundInfo.WriteInt32(OverDamage);
attackRoundInfo.WriteUInt8(SubDmg.HasValue);
if (SubDmg.HasValue)
{
attackRoundInfo.WriteInt32(SubDmg.Value.SchoolMask);
attackRoundInfo.WriteFloat(SubDmg.Value.FDamage);
attackRoundInfo.WriteInt32(SubDmg.Value.Damage);
if (hitInfo.HasAnyFlag(HitInfo.FullAbsorb | HitInfo.PartialAbsorb))
attackRoundInfo.WriteInt32(SubDmg.Value.Absorbed);
if (hitInfo.HasAnyFlag(HitInfo.FullResist | HitInfo.PartialResist))
attackRoundInfo.WriteInt32(SubDmg.Value.Resisted);
}
attackRoundInfo.WriteUInt8(VictimState);
attackRoundInfo.WriteInt32(AttackerState);
attackRoundInfo.WriteInt32(MeleeSpellID);
if (hitInfo.HasAnyFlag(HitInfo.Block))
attackRoundInfo.WriteInt32(BlockAmount);
if (hitInfo.HasAnyFlag(HitInfo.RageGain))
attackRoundInfo.WriteInt32(RageGained);
if (hitInfo.HasAnyFlag(HitInfo.Unk1))
{
attackRoundInfo.WriteUInt32(UnkState.State1);
attackRoundInfo.WriteFloat(UnkState.State2);
attackRoundInfo.WriteFloat(UnkState.State3);
attackRoundInfo.WriteFloat(UnkState.State4);
attackRoundInfo.WriteFloat(UnkState.State5);
attackRoundInfo.WriteFloat(UnkState.State6);
attackRoundInfo.WriteFloat(UnkState.State7);
attackRoundInfo.WriteFloat(UnkState.State8);
attackRoundInfo.WriteFloat(UnkState.State9);
attackRoundInfo.WriteFloat(UnkState.State10);
attackRoundInfo.WriteFloat(UnkState.State11);
attackRoundInfo.WriteUInt32(UnkState.State12);
}
if (hitInfo.HasAnyFlag(HitInfo.Block | HitInfo.Unk12))
attackRoundInfo.WriteFloat(Unk);
attackRoundInfo.WriteUInt8(SandboxScaling.Type);
attackRoundInfo.WriteUInt8(SandboxScaling.TargetLevel);
attackRoundInfo.WriteUInt8(SandboxScaling.Expansion);
attackRoundInfo.WriteUInt8(SandboxScaling.Class);
attackRoundInfo.WriteUInt8(SandboxScaling.TargetMinScalingLevel);
attackRoundInfo.WriteUInt8(SandboxScaling.TargetMaxScalingLevel);
attackRoundInfo.WriteInt16(SandboxScaling.PlayerLevelDelta);
attackRoundInfo.WriteInt8(SandboxScaling.TargetScalingLevelDelta);
attackRoundInfo.WriteUInt16(SandboxScaling.PlayerItemLevel);
WriteLogDataBit();
FlushBits();
WriteLogData();
_worldPacket.WriteInt32(attackRoundInfo.GetSize());
_worldPacket.WriteBytes(attackRoundInfo);
}
public HitInfo hitInfo; // Flags
public ObjectGuid AttackerGUID;
public ObjectGuid VictimGUID;
public int Damage;
public int OverDamage = -1; // (damage - health) or -1 if unit is still alive
public Optional<SubDamage> SubDmg;
public byte VictimState;
public uint AttackerState;
public uint MeleeSpellID;
public int BlockAmount;
public int RageGained;
public UnkAttackerState UnkState;
public float Unk;
public SandboxScalingData SandboxScaling = new SandboxScalingData();
}
//Structs
struct SpellLogEffectPowerDrainParams
{
public ObjectGuid Victim;
public uint Points;
public uint PowerType;
public float Amplitude;
}
struct SpellLogEffectExtraAttacksParams
{
public ObjectGuid Victim;
public uint NumAttacks;
}
struct SpellLogEffectDurabilityDamageParams
{
public ObjectGuid Victim;
public int ItemID;
public int Amount;
}
struct SpellLogEffectGenericVictimParams
{
public ObjectGuid Victim;
}
struct SpellLogEffectTradeSkillItemParams
{
public int ItemID;
}
struct SpellLogEffectFeedPetParams
{
public int ItemID;
}
struct SpellLogMissDebug
{
public void Write(WorldPacket data)
{
data.WriteFloat(HitRoll);
data.WriteFloat(HitRollNeeded);
}
public float HitRoll;
public float HitRollNeeded;
}
public struct SpellLogMissEntry
{
public SpellLogMissEntry(ObjectGuid victim, byte missReason)
{
Victim = victim;
MissReason = missReason;
Debug = new Optional<SpellLogMissDebug>();
}
public void Write(WorldPacket data)
{
data.WritePackedGuid(Victim);
data.WriteUInt8(MissReason);
if (data.WriteBit(Debug.HasValue))
Debug.Value.Write(data);
data.FlushBits();
}
public ObjectGuid Victim;
public byte MissReason;
Optional<SpellLogMissDebug> Debug;
}
struct SpellDispellData
{
public uint SpellID;
public bool Harmful;
public Optional<int> Rolled;
public Optional<int> Needed;
}
public struct SubDamage
{
public int SchoolMask;
public float FDamage; // Float damage (Most of the time equals to Damage)
public int Damage;
public int Absorbed;
public int Resisted;
}
public struct UnkAttackerState
{
public uint State1;
public float State2;
public float State3;
public float State4;
public float State5;
public float State6;
public float State7;
public float State8;
public float State9;
public float State10;
public float State11;
public uint State12;
}
}