void Creature::UpdateDamagePhysical(WeaponAttackType attType) { UnitMods unitMod; switch (attType) { case BASE_ATTACK: default: unitMod = UNIT_MOD_DAMAGE_MAINHAND; break; case OFF_ATTACK: unitMod = UNIT_MOD_DAMAGE_OFFHAND; break; case RANGED_ATTACK: unitMod = UNIT_MOD_DAMAGE_RANGED; break; } //float att_speed = float(GetAttackTime(attType))/1000.0f; float weapon_mindamage = GetWeaponDamageRange(attType, MINDAMAGE); float weapon_maxdamage = GetWeaponDamageRange(attType, MAXDAMAGE); /* difference in AP between current attack power and base value from DB */ // creature's damage in battleground is calculated in Creature::SelectLevel // so don't change it with ap and dmg multipliers float att_pwr_change = GetTotalAttackPowerValue(attType) - GetCreatureTemplate()->attackpower; float base_value = ((GetMap()->IsBattleground()) ? GetModifierValue(unitMod, BASE_VALUE) : (GetModifierValue(unitMod, BASE_VALUE) + (att_pwr_change * GetAPMultiplier(attType, false) / 14.0f))); float base_pct = GetModifierValue(unitMod, BASE_PCT); float total_value = GetModifierValue(unitMod, TOTAL_VALUE); float total_pct = GetModifierValue(unitMod, TOTAL_PCT); float dmg_multiplier = ((GetMap()->IsBattleground()) ? 1.0f : GetCreatureTemplate()->dmg_multiplier); if (!CanUseAttackType(attType)) { weapon_mindamage = 0; weapon_maxdamage = 0; } float mindamage = ((base_value + weapon_mindamage) * dmg_multiplier * base_pct + total_value) * total_pct; float maxdamage = ((base_value + weapon_maxdamage) * dmg_multiplier * base_pct + total_value) * total_pct; switch (attType) { case BASE_ATTACK: default: SetStatFloatValue(UNIT_FIELD_MINDAMAGE, mindamage); SetStatFloatValue(UNIT_FIELD_MAXDAMAGE, maxdamage); break; case OFF_ATTACK: SetStatFloatValue(UNIT_FIELD_MINOFFHANDDAMAGE, mindamage); SetStatFloatValue(UNIT_FIELD_MAXOFFHANDDAMAGE, maxdamage); break; case RANGED_ATTACK: SetStatFloatValue(UNIT_FIELD_MINRANGEDDAMAGE, mindamage); SetStatFloatValue(UNIT_FIELD_MAXRANGEDDAMAGE, maxdamage); break; } }
void Creature::UpdateDamagePhysical(WeaponAttackType attType) { UnitMods unitMod; switch (attType) { case BASE_ATTACK: default: unitMod = UNIT_MOD_DAMAGE_MAINHAND; break; case OFF_ATTACK: unitMod = UNIT_MOD_DAMAGE_OFFHAND; break; case RANGED_ATTACK: unitMod = UNIT_MOD_DAMAGE_RANGED; break; } //float att_speed = float(GetAttackTime(attType))/1000.0f; float weapon_mindamage = GetWeaponDamageRange(attType, MINDAMAGE); float weapon_maxdamage = GetWeaponDamageRange(attType, MAXDAMAGE); /* difference in AP between current attack power and base value from DB */ float att_pwr_change = GetTotalAttackPowerValue(attType) - GetCreatureTemplate()->attackpower; float base_value = GetModifierValue(unitMod, BASE_VALUE) + (att_pwr_change * GetAPMultiplier(attType, false) / 14.0f); float base_pct = GetModifierValue(unitMod, BASE_PCT); float total_value = GetModifierValue(unitMod, TOTAL_VALUE); float total_pct = GetModifierValue(unitMod, TOTAL_PCT); float dmg_multiplier = GetCreatureTemplate()->dmg_multiplier; if (!CanUseAttackType(attType)) { weapon_mindamage = 0; weapon_maxdamage = 0; } float mindamage = ((base_value + weapon_mindamage) * dmg_multiplier * base_pct + total_value) * total_pct; float maxdamage = ((base_value + weapon_maxdamage) * dmg_multiplier * base_pct + total_value) * total_pct; switch (attType) { case BASE_ATTACK: default: SetStatFloatValue(UNIT_FIELD_MIN_DAMAGE, mindamage); SetStatFloatValue(UNIT_FIELD_MAX_DAMAGE, maxdamage); break; case OFF_ATTACK: SetStatFloatValue(UNIT_FIELD_MIN_OFF_HAND_DAMAGE, mindamage); SetStatFloatValue(UNIT_FIELD_MAX_OFF_HAND_DAMAGE, maxdamage); break; case RANGED_ATTACK: SetStatFloatValue(UNIT_FIELD_MIN_RANGED_DAMAGE, mindamage); SetStatFloatValue(UNIT_FIELD_MAX_RANGED_DAMAGE, maxdamage); break; } }
void Creature::CalculateMinMaxDamage(WeaponAttackType attType, bool normalized, bool addTotalPct, float& minDamage, float& maxDamage) { float variance = 1.0f; UnitMods unitMod; switch (attType) { case BASE_ATTACK: default: variance = GetCreatureTemplate()->BaseVariance; unitMod = UNIT_MOD_DAMAGE_MAINHAND; break; case OFF_ATTACK: variance = GetCreatureTemplate()->BaseVariance; unitMod = UNIT_MOD_DAMAGE_OFFHAND; break; case RANGED_ATTACK: variance = GetCreatureTemplate()->RangeVariance; unitMod = UNIT_MOD_DAMAGE_RANGED; break; } if (attType == OFF_ATTACK && !haveOffhandWeapon()) { minDamage = 0.0f; maxDamage = 0.0f; return; } float weaponMinDamage = GetWeaponDamageRange(attType, MINDAMAGE); float weaponMaxDamage = GetWeaponDamageRange(attType, MAXDAMAGE); if (!CanUseAttackType(attType)) // disarm case { weaponMinDamage = 0.0f; weaponMaxDamage = 0.0f; } float attackPower = GetTotalAttackPowerValue(attType); float attackSpeedMulti = GetAPMultiplier(attType, normalized); float baseValue = GetModifierValue(unitMod, BASE_VALUE) + (attackPower / 14.0f) * variance; float basePct = GetModifierValue(unitMod, BASE_PCT) * attackSpeedMulti; float totalValue = GetModifierValue(unitMod, TOTAL_VALUE); float totalPct = addTotalPct ? GetModifierValue(unitMod, TOTAL_PCT) : 1.0f; float dmgMultiplier = GetCreatureTemplate()->ModDamage; // = ModDamage * _GetDamageMod(rank); minDamage = ((weaponMinDamage + baseValue) * dmgMultiplier * basePct + totalValue) * totalPct; maxDamage = ((weaponMaxDamage + baseValue) * dmgMultiplier * basePct + totalValue) * totalPct; }
void Totem::InitStats(uint32 duration) { // client requires SMSG_TOTEM_CREATED to be sent before adding to world and before removing old totem if (GetOwner()->GetTypeId() == TYPEID_PLAYER && m_Properties->Slot >= SUMMON_SLOT_TOTEM && m_Properties->Slot < MAX_TOTEM_SLOT) { WorldPacket data(SMSG_TOTEM_CREATED, 1 + 8 + 4 + 4); data << uint8(m_Properties->Slot - 1); data << GetGUID128(); data << uint32(duration); data << uint32(GetUInt32Value(UNIT_FIELD_CREATED_BY_SPELL)); GetOwner()->ToPlayer()->SendDirectMessage(&data); // set display id depending on caster's race CreatureTemplate const* creatureTemplate = GetCreatureTemplate(); if (creatureTemplate) SetDisplayId(GetOwner()->GetModelForTotem(PlayerTotemType(creatureTemplate->Modelid1))); } Minion::InitStats(duration); // Get spell cast by totem if (SpellInfo const* totemSpell = sSpellMgr->GetSpellInfo(GetSpell())) if (totemSpell->CalcCastTime(getLevel())) // If spell has cast time -> its an active totem m_type = TOTEM_ACTIVE; m_duration = duration; SetLevel(GetOwner()->getLevel()); }
void Totem::InitStats(uint32 duration) { if (m_owner->GetTypeId() == TYPEID_PLAYER && m_Properties->Slot >= SUMMON_SLOT_TOTEM && m_Properties->Slot < MAX_TOTEM_SLOT) { WorldPacket data(SMSG_TOTEM_CREATED, 1 + 8 + 4 + 4); data << uint8(m_Properties->Slot - 1); data << uint64(GetGUID()); data << uint32(duration); data << uint32(GetUInt32Value(UNIT_CREATED_BY_SPELL)); m_owner->ToPlayer()->SendDirectMessage(&data); CreatureInfo const* cinfo = GetCreatureTemplate(); if (cinfo) { uint32 modelid = 0; if (m_owner->ToPlayer()->GetTeam() == HORDE) { if (cinfo->modelid3) modelid = cinfo->modelid3; else if (cinfo->modelid4) modelid = cinfo->modelid4; } else { if (cinfo->modelid1) modelid = cinfo->modelid1; else if (cinfo->modelid2) modelid = cinfo->modelid2; } if (modelid) SetDisplayId(modelid); else sLog.outErrorDb("Totem::Summon: Missing modelid information for entry %u, team %u, totem will use default values.", GetEntry(), m_owner->ToPlayer()->GetTeam()); } } Minion::InitStats(duration); // Get spell casted by totem SpellEntry const* totemSpell = sSpellStore.LookupEntry(GetSpell()); if (totemSpell) { // If spell have cast time -> so its active totem if (GetSpellCastTime(totemSpell)) m_type = TOTEM_ACTIVE; } if (GetEntry() == SENTRY_TOTEM_ENTRY) SetReactState(REACT_AGGRESSIVE); m_duration = duration; SetLevel(m_owner->getLevel()); }
void Creature::CalculateMinMaxDamage(WeaponAttackType attType, bool normalized, bool addTotalPct, float& minDamage, float& maxDamage) { UnitMods unitMod; switch (attType) { case BASE_ATTACK: default: unitMod = UNIT_MOD_DAMAGE_MAINHAND; break; case OFF_ATTACK: unitMod = UNIT_MOD_DAMAGE_OFFHAND; break; case RANGED_ATTACK: unitMod = UNIT_MOD_DAMAGE_RANGED; break; } if (attType == OFF_ATTACK && !haveOffhandWeapon()) { minDamage = 0.0f; maxDamage = 0.0f; return; } float weaponMinDamage = GetWeaponDamageRange(attType, MINDAMAGE); float weaponMaxDamage = GetWeaponDamageRange(attType, MAXDAMAGE); if (!CanUseAttackType(attType)) // disarm case { weaponMinDamage = 0.0f; weaponMaxDamage = 0.0f; } // pussywizard: subtract value from database till its fixed (the way it worked before creature_levelstats damage implementation) float attackPower = GetTotalAttackPowerValue(attType) - (attType == RANGED_ATTACK ? GetCreatureTemplate()->rangedattackpower : GetCreatureTemplate()->attackpower); float baseValue = GetModifierValue(unitMod, BASE_VALUE) + (attackPower * GetAPMultiplier(attType, normalized) / 14.0f); float basePct = GetModifierValue(unitMod, BASE_PCT); float totalValue = GetModifierValue(unitMod, TOTAL_VALUE); float totalPct = addTotalPct ? GetModifierValue(unitMod, TOTAL_PCT) : 1.0f; float dmgMultiplier = GetCreatureTemplate()->dmg_multiplier; // = dmg_multiplier * _GetDamageMod(rank); minDamage = ((weaponMinDamage + baseValue) * dmgMultiplier * basePct + totalValue) * totalPct; maxDamage = ((weaponMaxDamage + baseValue) * dmgMultiplier * basePct + totalValue) * totalPct; // pussywizard: crashfix (casting negative to uint => min > max => assertion in urand) if (minDamage < 0.0f || minDamage > 1000000000.0f) minDamage = 0.0f; if (maxDamage < 0.0f || maxDamage > 1000000000.0f) maxDamage = 0.0f; if (minDamage > maxDamage) minDamage = maxDamage; }
void Totem::InitStats(uint32 duration) { Minion::InitStats(duration); CreatureTemplate const *cinfo = GetCreatureTemplate(); if (m_owner->GetTypeId() == TYPEID_PLAYER && cinfo) { uint32 modelid = 0; if (m_owner->ToPlayer()->GetTeam() == HORDE) { if (cinfo->Modelid_H1) modelid = cinfo->Modelid_H1; else if (cinfo->Modelid_H2) modelid = cinfo->Modelid_H2; } else { if (cinfo->Modelid_A1) modelid = cinfo->Modelid_A1; else if (cinfo->Modelid_A2) modelid = cinfo->Modelid_A2; } if (modelid) SetDisplayId(modelid); else sLog->outErrorDb("Totem::Summon: Missing modelid information for entry %u, team %u, totem will use default values.", GetEntry(), m_owner->ToPlayer()->GetTeam()); } // Get spell casted by totem SpellEntry const * totemSpell = sSpellStore.LookupEntry(GetSpell()); if (totemSpell) { // If spell have cast time -> so its active totem if (GetSpellCastTime(totemSpell)) m_type = TOTEM_ACTIVE; } if (GetEntry() == SENTRY_TOTEM_ENTRY) SetReactState(REACT_AGGRESSIVE); m_duration = duration; SetLevel(m_owner->getLevel()); }
bool Guardian::UpdateStats(Stats stat) { if (stat >= MAX_STATS) return false; // value = ((base_value * base_pct) + total_value) * total_pct float value = GetTotalStatValue(stat); ApplyStatBuffMod(stat, m_statFromOwner[stat], false); float ownersBonus = 0.0f; Unit* owner = GetOwner(); // Handle Death Knight Glyphs and Talents float mod = 0.75f; if (IsPetGhoul() && (stat == STAT_STAMINA || stat == STAT_STRENGTH)) { switch (stat) { case STAT_STAMINA: mod = 0.9f; break; // Default is 0.48 case STAT_STRENGTH: mod = 0.7f; break; // Default Owner's Strength scale default: break; } // Check just if owner has Ravenous Dead since it's effect is not an aura AuraEffect const* aurEff = owner->GetAuraEffect(SPELL_AURA_MOD_TOTAL_STAT_PERCENTAGE, SPELLFAMILY_DEATHKNIGHT, 3010, 0); if (aurEff) { SpellInfo const* spellInfo = aurEff->GetSpellInfo(); // Then get the SpellProto and add the dummy effect value AddPct(mod, spellInfo->Effects[EFFECT_1].CalcValue(owner)); // Ravenous Dead edits the original scale } // Glyph of the Ghoul aurEff = owner->GetAuraEffect(58686, 0); if (aurEff) mod += CalculatePct(1.0f, aurEff->GetAmount()); // Glyph of the Ghoul adds a flat value to the scale mod ownersBonus = float(owner->GetStat(stat)) * mod; value += ownersBonus; } else if (stat == STAT_STAMINA) { int pct = 30; switch(owner->getClass()) { case CLASS_WARLOCK: pct = 75; break; case CLASS_DEATH_KNIGHT: // Ebon Gargoyle if(GetEntry() == 27829) { pct = 80; } break; case CLASS_MAGE: pct = 78; break; case CLASS_SHAMAN: pct = 78; break; case CLASS_HUNTER: pct = 67; // Looks for creature template if(CreatureTemplate const* cinfo = GetCreatureTemplate()) { // Checks the pet talent type CreatureFamilyEntry const* pet_family = sCreatureFamilyStore.LookupEntry(cinfo->family); if (pet_family) { switch(pet_family->petTalentType) { // Ferocity case 0: pct = 67; break; // Tenacity case 1: pct = 78; break; // Cunning case 2: pct = 73; break; } } } break; } ownersBonus = CalculatePct(owner->GetStat(STAT_STAMINA) - owner->GetCreateStat(STAT_STAMINA), pct); value += ownersBonus; } //warlock's and mage's pets gain 30% of owner's intellect else if (stat == STAT_INTELLECT) { if (owner->getClass() == CLASS_WARLOCK || owner->getClass() == CLASS_MAGE) { ownersBonus = CalculatePct(owner->GetStat(stat), 30); value += ownersBonus; } } /* else if (stat == STAT_STRENGTH) { if (IsPetGhoul()) value += float(owner->GetStat(stat)) * 0.3f; } */ SetStat(stat, int32(value)); m_statFromOwner[stat] = ownersBonus; ApplyStatBuffMod(stat, m_statFromOwner[stat], true); switch (stat) { case STAT_STRENGTH: UpdateAttackPowerAndDamage(); break; case STAT_AGILITY: UpdateArmor(); break; case STAT_STAMINA: UpdateMaxHealth(); break; case STAT_INTELLECT: UpdateMaxPower(POWER_MANA); break; case STAT_SPIRIT: default: break; } return true; }
void Guardian::UpdateArmor() { float value = 0.0f; float bonus_armor = 0.0f; UnitMods unitMod = UNIT_MOD_ARMOR; // hunter pets gain 35% of owner's armor value, warlock pets gain 100% of owner's armor if (isHunterPet()) { int pct = 50; // Looks for creature template if(CreatureTemplate const* cinfo = GetCreatureTemplate()) { // Checks the pet talent type CreatureFamilyEntry const* pet_family = sCreatureFamilyStore.LookupEntry(cinfo->family); if (pet_family) { switch(pet_family->petTalentType) { // Ferocity case 0: pct = 50; break; // Tenacity case 1: pct = 70; break; // Cunning case 2: pct = 60; break; } } } bonus_armor = float(CalculatePct(m_owner->GetArmor(), pct)); } else if (isPet() && !IsPetGhoul()) { bonus_armor = m_owner->GetArmor(); switch(m_owner->getClass()) { case CLASS_SHAMAN: case CLASS_MAGE: case CLASS_WARLOCK: bonus_armor = CalculatePct(m_owner->GetArmor(), 35); break; } } else { if(m_owner) { switch(m_owner->getClass()) { case CLASS_SHAMAN: bonus_armor = CalculatePct(m_owner->GetArmor(), 35); break; } } } value = GetModifierValue(unitMod, BASE_VALUE); value *= GetModifierValue(unitMod, BASE_PCT); value += GetModifierValue(unitMod, TOTAL_VALUE) + bonus_armor; value *= GetModifierValue(unitMod, TOTAL_PCT); SetArmor(int32(value)); }