/* * 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 "CombatLogPacketsCommon.h" #include "Creature.h" #include "DB2Stores.h" #include "Map.h" #include "PacketOperators.h" #include "Player.h" #include "Spell.h" #include "SpellInfo.h" #include "Unit.h" namespace WorldPackets::Spells { void SpellCastLogData::Initialize(Unit const* unit) { Health = unit->GetHealth(); AttackPower = unit->GetTotalAttackPowerValue(unit->GetClass() == CLASS_HUNTER ? RANGED_ATTACK : BASE_ATTACK); SpellPower = unit->SpellBaseDamageBonusDone(SPELL_SCHOOL_MASK_SPELL); Armor = unit->GetArmor(); PowerData.emplace_back(int32(unit->GetPowerType()), unit->GetPower(unit->GetPowerType()), int32(0)); } void SpellCastLogData::Initialize(Spell const* spell) { if (Unit const* unitCaster = spell->GetCaster()->ToUnit()) { Health = unitCaster->GetHealth(); AttackPower = unitCaster->GetTotalAttackPowerValue(unitCaster->GetClass() == CLASS_HUNTER ? RANGED_ATTACK : BASE_ATTACK); SpellPower = unitCaster->SpellBaseDamageBonusDone(SPELL_SCHOOL_MASK_SPELL); Armor = unitCaster->GetArmor(); Powers primaryPowerType = unitCaster->GetPowerType(); bool primaryPowerAdded = false; for (SpellPowerCost const& cost : spell->GetPowerCost()) { PowerData.emplace_back(int8(cost.Power), unitCaster->GetPower(Powers(cost.Power)), int32(cost.Amount)); if (cost.Power == primaryPowerType) primaryPowerAdded = true; } if (!primaryPowerAdded) PowerData.emplace(PowerData.begin(), int8(primaryPowerType), unitCaster->GetPower(primaryPowerType), 0); } } template bool ContentTuningParams::GenerateDataForUnits(T* /*attacker*/, U* /*target*/) { return false; } template<> bool ContentTuningParams::GenerateDataForUnits(Creature* attacker, Player* target) { CreatureTemplate const* creatureTemplate = attacker->GetCreatureTemplate(); CreatureDifficulty const* creatureDifficulty = creatureTemplate->GetDifficulty(attacker->GetMap()->GetDifficultyID()); Type = TYPE_CREATURE_TO_PLAYER_DAMAGE; PlayerLevelDelta = target->m_activePlayerData->ScalingPlayerLevelDelta; PlayerItemLevel = target->GetAverageItemLevel(); TargetItemLevel = 0; if (ContentTuningEntry const* contentTuning = sContentTuningStore.LookupEntry(creatureDifficulty->ContentTuningID)) { ScalingHealthItemLevelCurveID = contentTuning->HealthItemLevelCurveID; ScalingHealthPrimaryStatCurveID = contentTuning->HealthPrimaryStatCurveID; TargetContentTuningID = contentTuning->ID; } TargetLevel = target->GetLevel(); Expansion = creatureDifficulty->HealthScalingExpansion; TargetScalingLevelDelta = int8(attacker->m_unitData->ScalingLevelDelta); return true; } template<> bool ContentTuningParams::GenerateDataForUnits(Player* attacker, Creature* target) { CreatureTemplate const* creatureTemplate = target->GetCreatureTemplate(); CreatureDifficulty const* creatureDifficulty = creatureTemplate->GetDifficulty(target->GetMap()->GetDifficultyID()); Type = TYPE_PLAYER_TO_CREATURE_DAMAGE; PlayerLevelDelta = attacker->m_activePlayerData->ScalingPlayerLevelDelta; PlayerItemLevel = attacker->GetAverageItemLevel(); TargetItemLevel = 0; if (ContentTuningEntry const* contentTuning = sContentTuningStore.LookupEntry(creatureDifficulty->ContentTuningID)) { ScalingHealthItemLevelCurveID = contentTuning->HealthItemLevelCurveID; ScalingHealthPrimaryStatCurveID = contentTuning->HealthPrimaryStatCurveID; TargetContentTuningID = contentTuning->ID; } TargetLevel = target->GetLevel(); Expansion = creatureDifficulty->HealthScalingExpansion; TargetScalingLevelDelta = int8(target->m_unitData->ScalingLevelDelta); return true; } template<> bool ContentTuningParams::GenerateDataForUnits(Creature* attacker, Creature* target) { Creature* accessor = target->HasScalableLevels() ? target : attacker; CreatureTemplate const* creatureTemplate = accessor->GetCreatureTemplate(); CreatureDifficulty const* creatureDifficulty = creatureTemplate->GetDifficulty(accessor->GetMap()->GetDifficultyID()); Type = TYPE_CREATURE_TO_CREATURE_DAMAGE; PlayerLevelDelta = 0; PlayerItemLevel = 0; TargetLevel = target->GetLevel(); Expansion = creatureDifficulty->HealthScalingExpansion; TargetScalingLevelDelta = int8(accessor->m_unitData->ScalingLevelDelta); TargetContentTuningID = creatureDifficulty->ContentTuningID; return true; } template<> bool ContentTuningParams::GenerateDataForUnits(Unit* attacker, Unit* target) { if (Player* playerAttacker = Object::ToPlayer(attacker)) { if (Player* playerTarget = Object::ToPlayer(target)) return GenerateDataForUnits(playerAttacker, playerTarget); else if (Creature* creatureTarget = Object::ToCreature(target)) { if (creatureTarget->HasScalableLevels()) return GenerateDataForUnits(playerAttacker, creatureTarget); } } else if (Creature* creatureAttacker = Object::ToCreature(attacker)) { if (Player* playerTarget = Object::ToPlayer(target)) { if (creatureAttacker->HasScalableLevels()) return GenerateDataForUnits(creatureAttacker, playerTarget); } else if (Creature* creatureTarget = Object::ToCreature(target)) { if (creatureAttacker->HasScalableLevels() || creatureTarget->HasScalableLevels()) return GenerateDataForUnits(creatureAttacker, creatureTarget); } } return false; } ByteBuffer& operator<<(ByteBuffer& data, SpellCastLogData const& spellCastLogData) { data << int64(spellCastLogData.Health); data << int32(spellCastLogData.AttackPower); data << int32(spellCastLogData.SpellPower); data << int32(spellCastLogData.Armor); data << int32(spellCastLogData.Unknown_1105_1); data << int32(spellCastLogData.Unknown_1105_2); data << BitsSize<9>(spellCastLogData.PowerData); data.FlushBits(); for (SpellLogPowerData const& powerData : spellCastLogData.PowerData) { data << int8(powerData.PowerType); data << int32(powerData.Amount); data << int32(powerData.Cost); } return data; } ByteBuffer& operator<<(ByteBuffer& data, ContentTuningParams const& contentTuningParams) { data << float(contentTuningParams.PlayerItemLevel); data << float(contentTuningParams.TargetItemLevel); data << int16(contentTuningParams.PlayerLevelDelta); data << int32(contentTuningParams.ScalingHealthItemLevelCurveID); data << int32(contentTuningParams.Unused1117); data << int32(contentTuningParams.ScalingHealthPrimaryStatCurveID); data << uint8(contentTuningParams.TargetLevel); data << uint8(contentTuningParams.Expansion); data << int8(contentTuningParams.TargetScalingLevelDelta); data << uint32(contentTuningParams.Flags); data << int32(contentTuningParams.PlayerContentTuningID); data << int32(contentTuningParams.TargetContentTuningID); data << int32(contentTuningParams.TargetHealingContentTuningID); data << float(contentTuningParams.PlayerPrimaryStatToExpectedRatio); data << Bits<4>(contentTuningParams.Type); data.FlushBits(); return data; } ByteBuffer& operator>>(ByteBuffer& data, SpellCastVisual& visual) { data >> visual.SpellXSpellVisualID; data >> visual.ScriptVisualID; return data; } ByteBuffer& operator<<(ByteBuffer& data, SpellCastVisual const& visual) { data << int32(visual.SpellXSpellVisualID); data << int32(visual.ScriptVisualID); return data; } ByteBuffer& operator<<(ByteBuffer& data, SpellSupportInfo const& supportInfo) { data << supportInfo.Supporter; data << int32(supportInfo.SupportSpellID); data << int32(supportInfo.AmountRaw); data << float(supportInfo.AmountPortion); return data; } } namespace WorldPackets::CombatLog { ByteBuffer& CombatLogServerPacket::WriteLogData() { return _fullLogPacket << LogData; } }