/* * This file is part of the TrinityCore Project. See AUTHORS file for Copyright information * * 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 2 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 . */ #include "CombatLogPackets.h" #include "PacketOperators.h" #include "Spell.h" #include "UnitDefines.h" namespace WorldPackets::CombatLog { ByteBuffer& operator<<(ByteBuffer& data, CombatWorldTextViewerInfo const& worldTextViewer) { data << worldTextViewer.ViewerGUID; data << OptionalInit(worldTextViewer.ColorType); data << OptionalInit(worldTextViewer.ScaleType); data.FlushBits(); if (worldTextViewer.ColorType) data << uint8(*worldTextViewer.ColorType); if (worldTextViewer.ScaleType) data << uint8(*worldTextViewer.ScaleType); return data; } WorldPacket const* SpellNonMeleeDamageLog::Write() { *this << Me; *this << CasterGUID; *this << CastID; *this << int32(SpellID); *this << Visual; *this << int32(Damage); *this << int32(OriginalDamage); *this << int32(Overkill); *this << uint8(SchoolMask); *this << int32(Absorbed); *this << int32(Resisted); *this << int32(ShieldBlock); *this << int32(Flags); *this << Size(WorldTextViewers); *this << Size(Supporters); for (Spells::SpellSupportInfo const& supportInfo : Supporters) *this << supportInfo; *this << Bits<1>(Periodic); *this << Bits<1>(false); // Debug info WriteLogDataBit(); *this << OptionalInit(ContentTuning); FlushBits(); for (CombatWorldTextViewerInfo const& worldTextViewer : WorldTextViewers) *this << worldTextViewer; WriteLogData(); if (ContentTuning) *this << *ContentTuning; return &_worldPacket; } WorldPacket const* EnvironmentalDamageLog::Write() { *this << Victim; *this << uint8(Type); *this << int32(Amount); *this << int32(Resisted); *this << int32(Absorbed); WriteLogDataBit(); FlushBits(); WriteLogData(); return &_worldPacket; } WorldPacket const* SpellExecuteLog::Write() { *this << Caster; *this << int32(SpellID); *this << Size(*Effects); for (SpellLogEffect const& effect : *Effects) { *this << int32(effect.Effect); *this << uint32(effect.PowerDrainTargets ? effect.PowerDrainTargets->size() : 0); *this << uint32(effect.ExtraAttacksTargets ? effect.ExtraAttacksTargets->size() : 0); *this << uint32(effect.DurabilityDamageTargets ? effect.DurabilityDamageTargets->size() : 0); *this << uint32(effect.GenericVictimTargets ? effect.GenericVictimTargets->size() : 0); *this << uint32(effect.TradeSkillTargets ? effect.TradeSkillTargets->size() : 0); *this << uint32(effect.FeedPetTargets ? effect.FeedPetTargets->size() : 0); if (effect.PowerDrainTargets) { for (SpellLogEffectPowerDrainParams const& powerDrainTarget : *effect.PowerDrainTargets) { *this << powerDrainTarget.Victim; *this << uint32(powerDrainTarget.Points); *this << int8(powerDrainTarget.PowerType); *this << float(powerDrainTarget.Amplitude); } } if (effect.ExtraAttacksTargets) { for (SpellLogEffectExtraAttacksParams const& extraAttacksTarget : *effect.ExtraAttacksTargets) { *this << extraAttacksTarget.Victim; *this << uint32(extraAttacksTarget.NumAttacks); } } if (effect.DurabilityDamageTargets) { for (SpellLogEffectDurabilityDamageParams const& durabilityDamageTarget : *effect.DurabilityDamageTargets) { *this << durabilityDamageTarget.Victim; *this << int32(durabilityDamageTarget.ItemID); *this << int32(durabilityDamageTarget.Amount); } } if (effect.GenericVictimTargets) for (SpellLogEffectGenericVictimParams const& genericVictimTarget : *effect.GenericVictimTargets) *this << genericVictimTarget.Victim; if (effect.TradeSkillTargets) for (SpellLogEffectTradeSkillItemParams const& tradeSkillTarget : *effect.TradeSkillTargets) *this << int32(tradeSkillTarget.ItemID); if (effect.FeedPetTargets) for (SpellLogEffectFeedPetParams const& feedPetTarget : *effect.FeedPetTargets) *this << int32(feedPetTarget.ItemID); } WriteLogDataBit(); FlushBits(); WriteLogData(); return &_worldPacket; } WorldPacket const* SpellHealLog::Write() { *this << TargetGUID; *this << CasterGUID; *this << int32(SpellID); *this << int32(Health); *this << int32(OriginalHeal); *this << int32(OverHeal); *this << int32(Absorbed); *this << Size(Supporters); for (Spells::SpellSupportInfo const& supportInfo : Supporters) *this << supportInfo; *this << Bits<1>(Crit); *this << OptionalInit(CritRollMade); *this << OptionalInit(CritRollNeeded); WriteLogDataBit(); *this << OptionalInit(ContentTuning); FlushBits(); WriteLogData(); if (CritRollMade) *this << *CritRollMade; if (CritRollNeeded) *this << *CritRollNeeded; if (ContentTuning) *this << *ContentTuning; return &_worldPacket; } ByteBuffer& operator<<(ByteBuffer& data, PeriodicalAuraLogEffectDebugInfo const& debugInfo) { data << float(debugInfo.CritRollMade); data << float(debugInfo.CritRollNeeded); return data; } ByteBuffer& operator<<(ByteBuffer& data, PeriodicAuraLogEffect const& effect) { data << int32(effect.Effect); data << int32(effect.Amount); data << int32(effect.OriginalDamage); data << int32(effect.OverHealOrKill); data << int32(effect.SchoolMaskOrPower); data << int32(effect.AbsorbedOrAmplitude); data << int32(effect.Resisted); data << Size(effect.Supporters); for (Spells::SpellSupportInfo const& supportInfo : effect.Supporters) data << supportInfo; data << Bits<1>(effect.Crit); data << OptionalInit(effect.DebugInfo); data << OptionalInit(effect.ContentTuning); data.FlushBits(); if (effect.ContentTuning) data << *effect.ContentTuning; if (effect.DebugInfo) data << *effect.DebugInfo; return data; } WorldPacket const* SpellPeriodicAuraLog::Write() { *this << TargetGUID; *this << CasterGUID; *this << int32(SpellID); *this << Size(Effects); WriteLogDataBit(); FlushBits(); for (PeriodicAuraLogEffect const& effect : Effects) *this << effect; WriteLogData(); return &_worldPacket; } WorldPacket const* SpellInterruptLog::Write() { _worldPacket << Caster; _worldPacket << Victim; _worldPacket << int32(InterruptedSpellID); _worldPacket << int32(SpellID); return &_worldPacket; } WorldPacket const* SpellEnergizeLog::Write() { *this << TargetGUID; *this << CasterGUID; *this << int32(SpellID); *this << int8(Type); *this << int32(Amount); *this << int32(OverEnergize); WriteLogDataBit(); FlushBits(); WriteLogData(); return &_worldPacket; } WorldPacket const* SpellInstakillLog::Write() { _worldPacket << Target; _worldPacket << Caster; _worldPacket << int32(SpellID); return &_worldPacket; } ByteBuffer& operator<<(ByteBuffer& buffer, SpellLogMissDebug const& missDebug) { buffer << float(missDebug.HitRoll); buffer << float(missDebug.HitRollNeeded); return buffer; } ByteBuffer& operator<<(ByteBuffer& buffer, SpellLogMissEntry const& missEntry) { buffer << missEntry.Victim; buffer << uint8(missEntry.MissReason); buffer << OptionalInit(missEntry.Debug); if (missEntry.Debug) buffer << *missEntry.Debug; buffer.FlushBits(); return buffer; } WorldPacket const* SpellMissLog::Write() { _worldPacket << int32(SpellID); _worldPacket << Caster; _worldPacket << Size(Entries); for (SpellLogMissEntry const& missEntry : Entries) _worldPacket << missEntry; return &_worldPacket; } WorldPacket const* ProcResist::Write() { _worldPacket << Caster; _worldPacket << Target; _worldPacket << int32(SpellID); _worldPacket << OptionalInit(Rolled); _worldPacket << OptionalInit(Needed); _worldPacket.FlushBits(); if (Rolled) _worldPacket << *Rolled; if (Needed) _worldPacket << *Needed; return &_worldPacket; } WorldPacket const* SpellOrDamageImmune::Write() { _worldPacket << CasterGUID; _worldPacket << VictimGUID; _worldPacket << uint32(SpellID); _worldPacket << Bits<1>(IsPeriodic); _worldPacket.FlushBits(); return &_worldPacket; } WorldPacket const* SpellDamageShield::Write() { *this << Attacker; *this << Defender; *this << int32(SpellID); *this << int32(TotalDamage); *this << int32(OriginalDamage); *this << int32(OverKill); *this << int32(SchoolMask); *this << int32(LogAbsorbed); WriteLogDataBit(); FlushBits(); WriteLogData(); return &_worldPacket; } WorldPacket const* AttackerStateUpdate::Write() { ByteBuffer attackRoundInfo; attackRoundInfo << uint32(HitInfo); attackRoundInfo << AttackerGUID; attackRoundInfo << VictimGUID; attackRoundInfo << int32(Damage); attackRoundInfo << int32(OriginalDamage); attackRoundInfo << int32(OverDamage); attackRoundInfo << uint8(SubDmg.has_value()); if (SubDmg) { attackRoundInfo << int32(SubDmg->SchoolMask); attackRoundInfo << float(SubDmg->FDamage); attackRoundInfo << int32(SubDmg->Damage); if (HitInfo & (HITINFO_FULL_ABSORB | HITINFO_PARTIAL_ABSORB)) attackRoundInfo << int32(SubDmg->Absorbed); if (HitInfo & (HITINFO_FULL_RESIST | HITINFO_PARTIAL_RESIST)) attackRoundInfo << int32(SubDmg->Resisted); } attackRoundInfo << uint8(VictimState); attackRoundInfo << uint32(AttackerState); attackRoundInfo << uint32(MeleeSpellID); if (HitInfo & HITINFO_BLOCK) attackRoundInfo << int32(BlockAmount); if (HitInfo & HITINFO_RAGE_GAIN) attackRoundInfo << int32(RageGained); if (HitInfo & HITINFO_UNK1) { attackRoundInfo << uint32(UnkState.State1); attackRoundInfo << float(UnkState.State2); attackRoundInfo << float(UnkState.State3); attackRoundInfo << float(UnkState.State4); attackRoundInfo << float(UnkState.State5); attackRoundInfo << float(UnkState.State6); attackRoundInfo << float(UnkState.State7); attackRoundInfo << float(UnkState.State8); attackRoundInfo << float(UnkState.State9); attackRoundInfo << float(UnkState.State10); attackRoundInfo << float(UnkState.State11); attackRoundInfo << uint32(UnkState.State12); } if (HitInfo & (HITINFO_BLOCK | HITINFO_UNK12)) attackRoundInfo << float(Unk); attackRoundInfo << ContentTuning; WriteLogDataBit(); FlushBits(); WriteLogData(); *this << Size(attackRoundInfo); _worldPacket.append(attackRoundInfo); _fullLogPacket.append(attackRoundInfo); return &_worldPacket; } ByteBuffer& operator<<(ByteBuffer& buffer, SpellDispellData const& dispellData) { buffer << int32(dispellData.SpellID); buffer << Bits<1>(dispellData.Harmful); buffer << OptionalInit(dispellData.Rolled); buffer << OptionalInit(dispellData.Needed); buffer.FlushBits(); if (dispellData.Rolled) buffer << int32(*dispellData.Rolled); if (dispellData.Needed) buffer << int32(*dispellData.Needed); return buffer; } WorldPacket const* SpellDispellLog::Write() { _worldPacket << Bits<1>(IsSteal); _worldPacket << Bits<1>(IsBreak); _worldPacket << TargetGUID; _worldPacket << CasterGUID; _worldPacket << int32(DispelledBySpellID); _worldPacket << Size(DispellData); for (SpellDispellData const& data : DispellData) _worldPacket << data; return &_worldPacket; } WorldPacket const* SpellAbsorbLog::Write() { *this << Attacker; *this << Victim; *this << int32(AbsorbedSpellID); *this << int32(AbsorbSpellID); *this << Caster; *this << int32(Absorbed); *this << int32(OriginalDamage); *this << Size(Supporters); for (Spells::SpellSupportInfo const& supportInfo : Supporters) *this << supportInfo; *this << Bits<1>(Crit); WriteLogDataBit(); FlushBits(); WriteLogData(); return &_worldPacket; } WorldPacket const* SpellHealAbsorbLog::Write() { _worldPacket << Target; _worldPacket << AbsorbCaster; _worldPacket << Healer; _worldPacket << int32(AbsorbSpellID); _worldPacket << int32(AbsorbedSpellID); _worldPacket << int32(Absorbed); _worldPacket << int32(OriginalHeal); _worldPacket << OptionalInit(ContentTuning); _worldPacket.FlushBits(); if (ContentTuning) _worldPacket << *ContentTuning; return &_worldPacket; } }