aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--sql/updates/world/2014_01_04_00_world_creature_classlevelstats.sql10
-rw-r--r--src/server/game/Entities/Creature/Creature.cpp54
-rw-r--r--src/server/game/Entities/Creature/Creature.h12
-rw-r--r--src/server/game/Entities/Creature/TemporarySummon.h2
-rw-r--r--src/server/game/Entities/Pet/Pet.h2
-rw-r--r--src/server/game/Entities/Player/Player.h3
-rw-r--r--src/server/game/Entities/Totem/Totem.h2
-rw-r--r--src/server/game/Entities/Unit/StatSystem.cpp205
-rw-r--r--src/server/game/Entities/Unit/Unit.cpp40
-rw-r--r--src/server/game/Entities/Unit/Unit.h11
-rw-r--r--src/server/game/Globals/ObjectMgr.cpp96
-rw-r--r--src/server/game/Miscellaneous/SharedDefines.h8
-rw-r--r--src/server/game/Spells/Auras/SpellAuraEffects.cpp52
-rw-r--r--src/server/game/Spells/SpellEffects.cpp6
-rw-r--r--src/server/scripts/EasternKingdoms/Karazhan/boss_prince_malchezaar.cpp20
-rw-r--r--src/server/scripts/EasternKingdoms/ZulGurub/boss_arlokk.cpp31
-rw-r--r--src/server/scripts/EasternKingdoms/ZulGurub/boss_marli.cpp17
-rw-r--r--src/server/scripts/EasternKingdoms/ZulGurub/boss_thekal.cpp8
-rw-r--r--src/server/scripts/EasternKingdoms/ZulGurub/instance_zulgurub.cpp26
-rw-r--r--src/server/scripts/Northrend/AzjolNerub/Ahnkahet/boss_elder_nadox.cpp1
-rw-r--r--src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/boss_twin_valkyr.cpp1
-rw-r--r--src/server/scripts/Pet/pet_hunter.cpp40
22 files changed, 337 insertions, 310 deletions
diff --git a/sql/updates/world/2014_01_04_00_world_creature_classlevelstats.sql b/sql/updates/world/2014_01_04_00_world_creature_classlevelstats.sql
new file mode 100644
index 00000000000..d55561bbe0e
--- /dev/null
+++ b/sql/updates/world/2014_01_04_00_world_creature_classlevelstats.sql
@@ -0,0 +1,10 @@
+ALTER TABLE `creature_classlevelstats`
+ CHANGE `level` `level` TINYINT(3) UNSIGNED NOT NULL,
+ CHANGE `class` `class` TINYINT(3) UNSIGNED NOT NULL,
+ CHANGE `basehp0` `basehp0` SMALLINT(5) UNSIGNED DEFAULT 1 NOT NULL,
+ CHANGE `basehp1` `basehp1` SMALLINT(5) UNSIGNED DEFAULT 1 NOT NULL,
+ CHANGE `basehp2` `basehp2` SMALLINT(5) UNSIGNED DEFAULT 1 NOT NULL,
+ CHANGE `basemana` `basemana` SMALLINT(5) UNSIGNED DEFAULT 0 NOT NULL,
+ CHANGE `basearmor` `basearmor` SMALLINT(5) UNSIGNED DEFAULT 1 NOT NULL,
+ CHANGE `attackpower` `attackpower` SMALLINT(5) UNSIGNED DEFAULT 0 NOT NULL,
+ CHANGE `rangedattackpower` `rangedattackpower` SMALLINT(5) UNSIGNED DEFAULT 0 NOT NULL;
diff --git a/src/server/game/Entities/Creature/Creature.cpp b/src/server/game/Entities/Creature/Creature.cpp
index d5ccaab27da..8019a14a0bd 100644
--- a/src/server/game/Entities/Creature/Creature.cpp
+++ b/src/server/game/Entities/Creature/Creature.cpp
@@ -182,8 +182,8 @@ void Creature::AddToWorld()
///- Register the creature for guid lookup
if (!IsInWorld())
{
- if (m_zoneScript)
- m_zoneScript->OnCreatureCreate(this);
+ if (GetZoneScript())
+ GetZoneScript()->OnCreatureCreate(this);
sObjectAccessor->AddObject(this);
Unit::AddToWorld();
SearchFormation();
@@ -197,8 +197,8 @@ void Creature::RemoveFromWorld()
{
if (IsInWorld())
{
- if (m_zoneScript)
- m_zoneScript->OnCreatureRemove(this);
+ if (GetZoneScript())
+ GetZoneScript()->OnCreatureRemove(this);
if (m_formation)
sFormationMgr->RemoveCreatureFromGroup(m_formation, this);
Unit::RemoveFromWorld();
@@ -312,7 +312,7 @@ bool Creature::InitEntry(uint32 entry, uint32 /*team*/, const CreatureData* data
CreatureModelInfo const* minfo = sObjectMgr->GetCreatureModelRandomGender(&displayID);
if (!minfo) // Cancel load if no model defined
{
- TC_LOG_ERROR("sql.sql", "Creature (Entry: %u) has no model defined in table `creature_template`, can't load. ", entry);
+ TC_LOG_ERROR("sql.sql", "Creature (Entry: %u) has invalid model %u defined in table `creature_template`, can't load.", entry, displayID);
return false;
}
@@ -367,7 +367,6 @@ bool Creature::UpdateEntry(uint32 Entry, uint32 team, const CreatureData* data)
if (!GetCreatureAddon())
SetSheath(SHEATH_STATE_MELEE);
- SelectLevel(GetCreatureTemplate());
if (team == HORDE)
setFaction(cInfo->faction_H);
else
@@ -381,10 +380,6 @@ bool Creature::UpdateEntry(uint32 Entry, uint32 team, const CreatureData* data)
else
SetUInt32Value(UNIT_NPC_FLAGS, npcflag);
- SetAttackTime(BASE_ATTACK, cInfo->baseattacktime);
- SetAttackTime(OFF_ATTACK, cInfo->baseattacktime);
- SetAttackTime(RANGED_ATTACK, cInfo->rangeattacktime);
-
SetUInt32Value(UNIT_FIELD_FLAGS, unit_flags);
SetUInt32Value(UNIT_FIELD_FLAGS_2, cInfo->unit_flags2);
@@ -392,6 +387,12 @@ bool Creature::UpdateEntry(uint32 Entry, uint32 team, const CreatureData* data)
RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IN_COMBAT);
+ SetAttackTime(BASE_ATTACK, cInfo->baseattacktime);
+ SetAttackTime(OFF_ATTACK, cInfo->baseattacktime);
+ SetAttackTime(RANGED_ATTACK, cInfo->rangeattacktime);
+
+ SelectLevel(GetCreatureTemplate());
+
SetMeleeDamageSchool(SpellSchools(cInfo->dmgschool));
CreatureBaseStats const* stats = sObjectMgr->GetCreatureBaseStats(getLevel(), cInfo->unit_class);
float armor = (float)stats->GenerateArmor(cInfo); /// @todo Why is this treated as uint32 when it's a float?
@@ -1073,19 +1074,24 @@ void Creature::SelectLevel(const CreatureTemplate* cinfo)
SetModifierValue(UNIT_MOD_HEALTH, BASE_VALUE, (float)health);
SetModifierValue(UNIT_MOD_MANA, BASE_VALUE, (float)mana);
- //damage
+ // damage
float basedamage = stats->GenerateBaseDamage(cinfo);
- SetBaseWeaponDamage(BASE_ATTACK, MINDAMAGE, ((basedamage + (stats->AttackPower / 14)) * cinfo->dmg_multiplier) * (cinfo->baseattacktime / 1000));
- SetBaseWeaponDamage(BASE_ATTACK, MAXDAMAGE, (((basedamage * 1.5) + (stats->AttackPower / 14)) * cinfo->dmg_multiplier) * (cinfo->baseattacktime / 1000));
- SetBaseWeaponDamage(RANGED_ATTACK, MINDAMAGE, (basedamage + (stats->RangedAttackPower / 14)) * (cinfo->rangeattacktime / 1000));
- SetBaseWeaponDamage(RANGED_ATTACK, MAXDAMAGE, ((basedamage * 1.5) + (stats->RangedAttackPower / 14)) * (cinfo->rangeattacktime / 1000));
+ float weaponBaseMinDamage = basedamage;
+ float weaponBaseMaxDamage = basedamage * 1.5;
+
+ SetBaseWeaponDamage(BASE_ATTACK, MINDAMAGE, weaponBaseMinDamage);
+ SetBaseWeaponDamage(BASE_ATTACK, MAXDAMAGE, weaponBaseMaxDamage);
- float damagemod = 1.0f;//_GetDamageMod(rank);
+ SetBaseWeaponDamage(OFF_ATTACK, MINDAMAGE, weaponBaseMinDamage);
+ SetBaseWeaponDamage(OFF_ATTACK, MAXDAMAGE, weaponBaseMaxDamage);
- SetModifierValue(UNIT_MOD_ATTACK_POWER, BASE_VALUE, stats->AttackPower * damagemod);
+ SetBaseWeaponDamage(RANGED_ATTACK, MINDAMAGE, weaponBaseMinDamage);
+ SetBaseWeaponDamage(RANGED_ATTACK, MAXDAMAGE, weaponBaseMaxDamage);
+ SetModifierValue(UNIT_MOD_ATTACK_POWER, BASE_VALUE, stats->AttackPower);
+ SetModifierValue(UNIT_MOD_ATTACK_POWER_RANGED, BASE_VALUE, stats->RangedAttackPower);
}
float Creature::_GetHealthMod(int32 Rank)
@@ -1154,9 +1160,9 @@ float Creature::GetSpellDamageMod(int32 Rank) const
bool Creature::CreateFromProto(uint32 guidlow, uint32 Entry, uint32 vehId, uint32 team, const CreatureData* data)
{
SetZoneScript();
- if (m_zoneScript && data)
+ if (GetZoneScript() && data)
{
- Entry = m_zoneScript->GetCreatureEntry(guidlow, data);
+ Entry = GetZoneScript()->GetCreatureEntry(guidlow, data);
if (!Entry)
return false;
}
@@ -1258,6 +1264,12 @@ bool Creature::LoadCreatureFromDB(uint32 guid, Map* map, bool addToMap)
return true;
}
+void Creature::SetCanDualWield(bool value)
+{
+ Unit::SetCanDualWield(value);
+ UpdateDamagePhysical(OFF_ATTACK);
+}
+
void Creature::LoadEquipment(int8 id, bool force /*= true*/)
{
if (id == 0)
@@ -1965,7 +1977,7 @@ bool Creature::CanCreatureAttack(Unit const* victim, bool /*force*/) const
if (IsAIEnabled && !AI()->CanAIAttack(victim))
return false;
- if (sMapStore.LookupEntry(GetMapId())->IsDungeon())
+ if (GetMap()->IsDungeon())
return true;
//Use AttackDistance in distance check if threat radius is lower. This prevents creature bounce in and out of combat every update tick.
@@ -2427,7 +2439,7 @@ void Creature::SetPosition(float x, float y, float z, float o)
return;
}
- GetMap()->CreatureRelocation(ToCreature(), x, y, z, o);
+ GetMap()->CreatureRelocation(this, x, y, z, o);
if (IsVehicle())
GetVehicleKit()->RelocatePassengers();
}
diff --git a/src/server/game/Entities/Creature/Creature.h b/src/server/game/Entities/Creature/Creature.h
index 2f78d29a968..e9abd7c0e0a 100644
--- a/src/server/game/Entities/Creature/Creature.h
+++ b/src/server/game/Entities/Creature/Creature.h
@@ -173,11 +173,6 @@ struct CreatureTemplate
// Benchmarked: Faster than std::map (insert/find)
typedef UNORDERED_MAP<uint32, CreatureTemplate> CreatureTemplateContainer;
-// Represents max amount of expansions.
-/// @todo: Add MAX_EXPANSION constant.
-#define MAX_CREATURE_BASE_HP 3
-#define MAX_CREATURE_BASE_DAMAGE 3
-
// GCC have alternative #pragma pack(N) syntax and old gcc version not support pack(push, N), also any gcc version not support it at some platform
#if defined(__GNUC__)
#pragma pack(1)
@@ -188,12 +183,12 @@ typedef UNORDERED_MAP<uint32, CreatureTemplate> CreatureTemplateContainer;
// Defines base stats for creatures (used to calculate HP/mana/armor/attackpower/rangedattackpower/all damage).
struct CreatureBaseStats
{
- uint32 BaseHealth[MAX_CREATURE_BASE_HP];
+ uint32 BaseHealth[MAX_EXPANSIONS];
uint32 BaseMana;
uint32 BaseArmor;
uint32 AttackPower;
uint32 RangedAttackPower;
- float BaseDamage[MAX_CREATURE_BASE_DAMAGE];
+ float BaseDamage[MAX_EXPANSIONS];
// Helpers
@@ -521,8 +516,9 @@ class Creature : public Unit, public GridObject<Creature>, public MapObject
void UpdateMaxHealth();
void UpdateMaxPower(Powers power);
void UpdateAttackPowerAndDamage(bool ranged = false);
- void UpdateDamagePhysical(WeaponAttackType attType);
+ void CalculateMinMaxDamage(WeaponAttackType attType, bool normalized, bool addTotalPct, float& minDamage, float& maxDamage) OVERRIDE;
+ void SetCanDualWield(bool value) OVERRIDE;
int8 GetOriginalEquipmentId() const { return m_originalEquipmentId; }
uint8 GetCurrentEquipmentId() { return m_equipmentId; }
void SetCurrentEquipmentId(uint8 id) { m_equipmentId = id; }
diff --git a/src/server/game/Entities/Creature/TemporarySummon.h b/src/server/game/Entities/Creature/TemporarySummon.h
index 5455bad904a..e93f66ed726 100644
--- a/src/server/game/Entities/Creature/TemporarySummon.h
+++ b/src/server/game/Entities/Creature/TemporarySummon.h
@@ -95,7 +95,7 @@ class Guardian : public Minion
void UpdateMaxHealth();
void UpdateMaxPower(Powers power);
void UpdateAttackPowerAndDamage(bool ranged = false);
- void UpdateDamagePhysical(WeaponAttackType attType);
+ void UpdateDamagePhysical(WeaponAttackType attType) OVERRIDE;
int32 GetBonusDamage() const { return m_bonusSpellDamage; }
void SetBonusDamage(int32 damage);
diff --git a/src/server/game/Entities/Pet/Pet.h b/src/server/game/Entities/Pet/Pet.h
index c375cd30ad3..ef5e792e939 100644
--- a/src/server/game/Entities/Pet/Pet.h
+++ b/src/server/game/Entities/Pet/Pet.h
@@ -95,7 +95,7 @@ class Pet : public Guardian
void UpdateMaxHealth();
void UpdateMaxPower(Powers power);
void UpdateAttackPowerAndDamage(bool ranged = false);
- void UpdateDamagePhysical(WeaponAttackType attType);
+ void UpdateDamagePhysical(WeaponAttackType attType) OVERRIDE;
*/
void ToggleAutocast(SpellInfo const* spellInfo, bool apply);
diff --git a/src/server/game/Entities/Player/Player.h b/src/server/game/Entities/Player/Player.h
index f7658f73321..457f5af8361 100644
--- a/src/server/game/Entities/Player/Player.h
+++ b/src/server/game/Entities/Player/Player.h
@@ -1747,14 +1747,13 @@ class Player : public Unit, public GridObject<Player>
void ApplyFeralAPBonus(int32 amount, bool apply);
void UpdateAttackPowerAndDamage(bool ranged = false);
void UpdateShieldBlockValue();
- void UpdateDamagePhysical(WeaponAttackType attType);
void ApplySpellPowerBonus(int32 amount, bool apply);
void UpdateSpellDamageAndHealingBonus();
void ApplyRatingMod(CombatRating cr, int32 value, bool apply);
void UpdateRating(CombatRating cr);
void UpdateAllRatings();
- void CalculateMinMaxDamage(WeaponAttackType attType, bool normalized, bool addTotalPct, float& min_damage, float& max_damage);
+ void CalculateMinMaxDamage(WeaponAttackType attType, bool normalized, bool addTotalPct, float& minDamage, float& maxDamage) OVERRIDE;
void UpdateDefenseBonusesMod();
inline void RecalculateRating(CombatRating cr) { ApplyRatingMod(cr, 0, true);}
diff --git a/src/server/game/Entities/Totem/Totem.h b/src/server/game/Entities/Totem/Totem.h
index d20a58abd01..6364157982e 100644
--- a/src/server/game/Entities/Totem/Totem.h
+++ b/src/server/game/Entities/Totem/Totem.h
@@ -53,7 +53,7 @@ class Totem : public Minion
void UpdateMaxHealth() { }
void UpdateMaxPower(Powers /*power*/) { }
void UpdateAttackPowerAndDamage(bool /*ranged*/) { }
- void UpdateDamagePhysical(WeaponAttackType /*attType*/) { }
+ void UpdateDamagePhysical(WeaponAttackType /*attType*/) OVERRIDE { }
bool IsImmunedToSpellEffect(SpellInfo const* spellInfo, uint32 index) const;
diff --git a/src/server/game/Entities/Unit/StatSystem.cpp b/src/server/game/Entities/Unit/StatSystem.cpp
index 3077b143bb0..3afa6b016d2 100644
--- a/src/server/game/Entities/Unit/StatSystem.cpp
+++ b/src/server/game/Entities/Unit/StatSystem.cpp
@@ -48,6 +48,43 @@ inline bool _ModifyUInt32(bool apply, uint32& baseValue, int32& amount)
/*#######################################
######## ########
+######## UNIT STAT SYSTEM ########
+######## ########
+#######################################*/
+
+void Unit::UpdateAllResistances()
+{
+ for (uint8 i = SPELL_SCHOOL_NORMAL; i < MAX_SPELL_SCHOOL; ++i)
+ UpdateResistances(i);
+}
+
+void Unit::UpdateDamagePhysical(WeaponAttackType attType)
+{
+ float minDamage = 0.0f;
+ float maxDamage = 0.0f;
+
+ CalculateMinMaxDamage(attType, false, true, minDamage, maxDamage);
+
+ 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;
+ }
+}
+
+/*#######################################
+######## ########
######## PLAYERS STAT SYSTEM ########
######## ########
#######################################*/
@@ -178,8 +215,7 @@ bool Player::UpdateAllStats()
UpdateExpertise(BASE_ATTACK);
UpdateExpertise(OFF_ATTACK);
RecalculateRating(CR_ARMOR_PENETRATION);
- for (int i = SPELL_SCHOOL_NORMAL; i < MAX_SPELL_SCHOOL; ++i)
- UpdateResistances(i);
+ UpdateAllResistances();
return true;
}
@@ -477,7 +513,7 @@ void Player::UpdateShieldBlockValue()
SetUInt32Value(PLAYER_SHIELD_BLOCK, GetShieldBlockValue());
}
-void Player::CalculateMinMaxDamage(WeaponAttackType attType, bool normalized, bool addTotalPct, float& min_damage, float& max_damage)
+void Player::CalculateMinMaxDamage(WeaponAttackType attType, bool normalized, bool addTotalPct, float& minDamage, float& maxDamage)
{
UnitMods unitMod;
@@ -495,70 +531,45 @@ void Player::CalculateMinMaxDamage(WeaponAttackType attType, bool normalized, bo
break;
}
- float att_speed = GetAPMultiplier(attType, normalized);
+ float attackSpeedMod = GetAPMultiplier(attType, normalized);
- float base_value = GetModifierValue(unitMod, BASE_VALUE) + GetTotalAttackPowerValue(attType)/ 14.0f * att_speed;
- float base_pct = GetModifierValue(unitMod, BASE_PCT);
- float total_value = GetModifierValue(unitMod, TOTAL_VALUE);
- float total_pct = addTotalPct ? GetModifierValue(unitMod, TOTAL_PCT) : 1.0f;
+ float baseValue = GetModifierValue(unitMod, BASE_VALUE) + GetTotalAttackPowerValue(attType) / 14.0f * attackSpeedMod;
+ float basePct = GetModifierValue(unitMod, BASE_PCT);
+ float totalValue = GetModifierValue(unitMod, TOTAL_VALUE);
+ float totalPct = addTotalPct ? GetModifierValue(unitMod, TOTAL_PCT) : 1.0f;
- float weapon_mindamage = GetWeaponDamageRange(attType, MINDAMAGE);
- float weapon_maxdamage = GetWeaponDamageRange(attType, MAXDAMAGE);
+ float weaponMinDamage = GetWeaponDamageRange(attType, MINDAMAGE);
+ float weaponMaxDamage = GetWeaponDamageRange(attType, MAXDAMAGE);
- if (IsInFeralForm()) //check if player is druid and in cat or bear forms
+ if (IsInFeralForm()) // check if player is druid and in cat or bear forms
{
uint8 lvl = getLevel();
if (lvl > 60)
lvl = 60;
- weapon_mindamage = lvl*0.85f*att_speed;
- weapon_maxdamage = lvl*1.25f*att_speed;
+ weaponMinDamage = lvl * 0.85f * attackSpeedMod;
+ weaponMaxDamage = lvl * 1.25f * attackSpeedMod;
}
- else if (!CanUseAttackType(attType)) //check if player not in form but still can't use (disarm case)
+ else if (!CanUseAttackType(attType)) // check if player not in form but still can't use (disarm case)
{
- //cannot use ranged/off attack, set values to 0
+ // cannot use ranged/off attack, set values to 0
if (attType != BASE_ATTACK)
{
- min_damage = 0;
- max_damage = 0;
+ minDamage = 0;
+ maxDamage = 0;
return;
}
- weapon_mindamage = BASE_MINDAMAGE;
- weapon_maxdamage = BASE_MAXDAMAGE;
+ weaponMinDamage = BASE_MINDAMAGE;
+ weaponMaxDamage = BASE_MAXDAMAGE;
}
- else if (attType == RANGED_ATTACK) //add ammo DPS to ranged damage
+ else if (attType == RANGED_ATTACK) // add ammo DPS to ranged damage
{
- weapon_mindamage += GetAmmoDPS() * att_speed;
- weapon_maxdamage += GetAmmoDPS() * att_speed;
+ weaponMinDamage += GetAmmoDPS() * attackSpeedMod;
+ weaponMaxDamage += GetAmmoDPS() * attackSpeedMod;
}
- min_damage = ((base_value + weapon_mindamage) * base_pct + total_value) * total_pct;
- max_damage = ((base_value + weapon_maxdamage) * base_pct + total_value) * total_pct;
-}
-
-void Player::UpdateDamagePhysical(WeaponAttackType attType)
-{
- float mindamage;
- float maxdamage;
-
- CalculateMinMaxDamage(attType, false, true, mindamage, maxdamage);
-
- 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;
- }
+ minDamage = ((weaponMinDamage + baseValue) * basePct + totalValue) * totalPct;
+ maxDamage = ((weaponMaxDamage + baseValue) * basePct + totalValue) * totalPct;
}
void Player::UpdateDefenseBonusesMod()
@@ -841,9 +852,14 @@ void Player::UpdateExpertise(WeaponAttackType attack)
switch (attack)
{
- case BASE_ATTACK: SetUInt32Value(PLAYER_EXPERTISE, expertise); break;
- case OFF_ATTACK: SetUInt32Value(PLAYER_OFFHAND_EXPERTISE, expertise); break;
- default: break;
+ case BASE_ATTACK:
+ SetUInt32Value(PLAYER_EXPERTISE, expertise);
+ break;
+ case OFF_ATTACK:
+ SetUInt32Value(PLAYER_OFFHAND_EXPERTISE, expertise);
+ break;
+ default:
+ break;
}
}
@@ -950,8 +966,7 @@ bool Creature::UpdateAllStats()
for (uint8 i = POWER_MANA; i < MAX_POWERS; ++i)
UpdateMaxPower(Powers(i));
- for (int8 i = SPELL_SCHOOL_NORMAL; i < MAX_SPELL_SCHOOL; ++i)
- UpdateResistances(i);
+ UpdateAllResistances();
return true;
}
@@ -976,7 +991,7 @@ void Creature::UpdateArmor()
void Creature::UpdateMaxHealth()
{
float value = GetTotalAuraModValue(UNIT_MOD_HEALTH);
- SetMaxHealth((uint32)value);
+ SetMaxHealth(uint32(value));
}
void Creature::UpdateMaxPower(Powers power)
@@ -992,25 +1007,25 @@ void Creature::UpdateAttackPowerAndDamage(bool ranged)
UnitMods unitMod = ranged ? UNIT_MOD_ATTACK_POWER_RANGED : UNIT_MOD_ATTACK_POWER;
uint16 index = UNIT_FIELD_ATTACK_POWER;
- uint16 index_mod = UNIT_FIELD_ATTACK_POWER_MODS;
- uint16 index_mult = UNIT_FIELD_ATTACK_POWER_MULTIPLIER;
+ uint16 indexMod = UNIT_FIELD_ATTACK_POWER_MODS;
+ uint16 indexMulti = UNIT_FIELD_ATTACK_POWER_MULTIPLIER;
if (ranged)
{
index = UNIT_FIELD_RANGED_ATTACK_POWER;
- index_mod = UNIT_FIELD_RANGED_ATTACK_POWER_MODS;
- index_mult = UNIT_FIELD_RANGED_ATTACK_POWER_MULTIPLIER;
+ indexMod = UNIT_FIELD_RANGED_ATTACK_POWER_MODS;
+ indexMulti = UNIT_FIELD_RANGED_ATTACK_POWER_MULTIPLIER;
}
- float base_attPower = GetModifierValue(unitMod, BASE_VALUE) * GetModifierValue(unitMod, BASE_PCT);
- float attPowerMod = GetModifierValue(unitMod, TOTAL_VALUE);
- float attPowerMultiplier = GetModifierValue(unitMod, TOTAL_PCT) - 1.0f;
+ float baseAttackPower = GetModifierValue(unitMod, BASE_VALUE) * GetModifierValue(unitMod, BASE_PCT);
+ float attackPowerMod = GetModifierValue(unitMod, TOTAL_VALUE);
+ float attackPowerMultiplier = GetModifierValue(unitMod, TOTAL_PCT) - 1.0f;
- SetInt32Value(index, (uint32)base_attPower); //UNIT_FIELD_(RANGED)_ATTACK_POWER field
- SetInt32Value(index_mod, (uint32)attPowerMod); //UNIT_FIELD_(RANGED)_ATTACK_POWER_MODS field
- SetFloatValue(index_mult, attPowerMultiplier); //UNIT_FIELD_(RANGED)_ATTACK_POWER_MULTIPLIER field
+ SetInt32Value(index, uint32(baseAttackPower)); // UNIT_FIELD_(RANGED)_ATTACK_POWER
+ SetInt32Value(indexMod, uint32(attackPowerMod)); // UNIT_FIELD_(RANGED)_ATTACK_POWER_MODS
+ SetFloatValue(indexMulti, attackPowerMultiplier); // UNIT_FIELD_(RANGED)_ATTACK_POWER_MULTIPLIER
- //automatically update weapon damage after attack power modification
+ // automatically update weapon damage after attack power modification
if (ranged)
UpdateDamagePhysical(RANGED_ATTACK);
else
@@ -1020,7 +1035,7 @@ void Creature::UpdateAttackPowerAndDamage(bool ranged)
}
}
-void Creature::UpdateDamagePhysical(WeaponAttackType attType)
+void Creature::CalculateMinMaxDamage(WeaponAttackType attType, bool normalized, bool addTotalPct, float& minDamage, float& maxDamage)
{
UnitMods unitMod;
switch (attType)
@@ -1037,44 +1052,32 @@ void Creature::UpdateDamagePhysical(WeaponAttackType attType)
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))
+ if (attType == OFF_ATTACK && !haveOffhandWeapon())
{
- weapon_mindamage = 0;
- weapon_maxdamage = 0;
+ minDamage = 0.0f;
+ maxDamage = 0.0f;
+ return;
}
- 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;
+ float weaponMinDamage = GetWeaponDamageRange(attType, MINDAMAGE);
+ float weaponMaxDamage = GetWeaponDamageRange(attType, MAXDAMAGE);
- switch (attType)
+ if (!CanUseAttackType(attType)) // disarm case
{
- 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;
+ weaponMinDamage = 0.0f;
+ weaponMaxDamage = 0.0f;
}
+
+ float attackPower = GetTotalAttackPowerValue(attType);
+ float attackSpeedMulti = GetAPMultiplier(attType, normalized);
+ float baseValue = GetModifierValue(unitMod, BASE_VALUE) + (attackPower / 14.0f);
+ 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()->dmg_multiplier; // = dmg_multiplier * _GetDamageMod(rank);
+
+ minDamage = ((weaponMinDamage + baseValue) * dmgMultiplier * basePct + totalValue) * totalPct;
+ maxDamage = ((weaponMaxDamage + baseValue) * dmgMultiplier * basePct + totalValue) * totalPct;
}
/*#######################################
@@ -1197,8 +1200,7 @@ bool Guardian::UpdateAllStats()
for (uint8 i = POWER_MANA; i < MAX_POWERS; ++i)
UpdateMaxPower(Powers(i));
- for (uint8 i = SPELL_SCHOOL_NORMAL; i < MAX_SPELL_SCHOOL; ++i)
- UpdateResistances(i);
+ UpdateAllResistances();
return true;
}
@@ -1436,6 +1438,7 @@ void Guardian::UpdateDamagePhysical(WeaponAttackType attType)
}
}
+ /// @todo: remove this
Unit::AuraEffectList const& mDummy = GetAuraEffectsByType(SPELL_AURA_MOD_ATTACKSPEED);
for (Unit::AuraEffectList::const_iterator itr = mDummy.begin(); itr != mDummy.end(); ++itr)
{
diff --git a/src/server/game/Entities/Unit/Unit.cpp b/src/server/game/Entities/Unit/Unit.cpp
index e5fb575d8eb..cb390cc4654 100644
--- a/src/server/game/Entities/Unit/Unit.cpp
+++ b/src/server/game/Entities/Unit/Unit.cpp
@@ -368,10 +368,10 @@ void Unit::Update(uint32 p_time)
bool Unit::haveOffhandWeapon() const
{
- if (GetTypeId() == TYPEID_PLAYER)
- return ToPlayer()->GetWeaponForAttack(OFF_ATTACK, true);
- else
- return m_canDualWield;
+ if (Player const* player = ToPlayer())
+ return player->GetWeaponForAttack(OFF_ATTACK, true);
+
+ return CanDualWield();
}
void Unit::MonsterMoveWithSpeed(float x, float y, float z, float speed, bool generatePath, bool forceDestination)
@@ -2160,41 +2160,39 @@ MeleeHitOutcome Unit::RollMeleeOutcomeAgainst (const Unit* victim, WeaponAttackT
uint32 Unit::CalculateDamage(WeaponAttackType attType, bool normalized, bool addTotalPct)
{
- float min_damage, max_damage;
+ float minDamage = 0.0f;
+ float maxDamage = 0.0f;
- if (GetTypeId() == TYPEID_PLAYER && (normalized || !addTotalPct))
- ToPlayer()->CalculateMinMaxDamage(attType, normalized, addTotalPct, min_damage, max_damage);
+ if (normalized || !addTotalPct)
+ CalculateMinMaxDamage(attType, normalized, addTotalPct, minDamage, maxDamage);
else
{
switch (attType)
{
case RANGED_ATTACK:
- min_damage = GetFloatValue(UNIT_FIELD_MINRANGEDDAMAGE);
- max_damage = GetFloatValue(UNIT_FIELD_MAXRANGEDDAMAGE);
+ minDamage = GetFloatValue(UNIT_FIELD_MINRANGEDDAMAGE);
+ maxDamage = GetFloatValue(UNIT_FIELD_MAXRANGEDDAMAGE);
break;
case BASE_ATTACK:
- min_damage = GetFloatValue(UNIT_FIELD_MINDAMAGE);
- max_damage = GetFloatValue(UNIT_FIELD_MAXDAMAGE);
+ minDamage = GetFloatValue(UNIT_FIELD_MINDAMAGE);
+ maxDamage = GetFloatValue(UNIT_FIELD_MAXDAMAGE);
break;
case OFF_ATTACK:
- min_damage = GetFloatValue(UNIT_FIELD_MINOFFHANDDAMAGE);
- max_damage = GetFloatValue(UNIT_FIELD_MAXOFFHANDDAMAGE);
+ minDamage = GetFloatValue(UNIT_FIELD_MINOFFHANDDAMAGE);
+ maxDamage = GetFloatValue(UNIT_FIELD_MAXOFFHANDDAMAGE);
break;
- // Just for good manner
default:
- min_damage = 0.0f;
- max_damage = 0.0f;
break;
}
}
- if (min_damage > max_damage)
- std::swap(min_damage, max_damage);
+ if (minDamage > maxDamage)
+ std::swap(minDamage, maxDamage);
- if (max_damage == 0.0f)
- max_damage = 5.0f;
+ if (maxDamage == 0.0f)
+ maxDamage = 5.0f;
- return urand((uint32)min_damage, (uint32)max_damage);
+ return urand(uint32(minDamage), uint32(maxDamage));
}
float Unit::CalculateLevelPenalty(SpellInfo const* spellProto) const
diff --git a/src/server/game/Entities/Unit/Unit.h b/src/server/game/Entities/Unit/Unit.h
index eb236666976..9cfdbbc77eb 100644
--- a/src/server/game/Entities/Unit/Unit.h
+++ b/src/server/game/Entities/Unit/Unit.h
@@ -1292,7 +1292,7 @@ class Unit : public WorldObject
bool isAttackReady(WeaponAttackType type = BASE_ATTACK) const { return m_attackTimer[type] == 0; }
bool haveOffhandWeapon() const;
bool CanDualWield() const { return m_canDualWield; }
- void SetCanDualWield(bool value) { m_canDualWield = value; }
+ virtual void SetCanDualWield(bool value) { m_canDualWield = value; }
float GetCombatReach() const { return m_floatValues[UNIT_FIELD_COMBATREACH]; }
float GetMeleeReach() const;
bool IsWithinCombatRange(const Unit* obj, float dist2compare) const;
@@ -1870,14 +1870,18 @@ class Unit : public WorldObject
virtual bool UpdateStats(Stats stat) = 0;
virtual bool UpdateAllStats() = 0;
virtual void UpdateResistances(uint32 school) = 0;
+ virtual void UpdateAllResistances();
virtual void UpdateArmor() = 0;
virtual void UpdateMaxHealth() = 0;
virtual void UpdateMaxPower(Powers power) = 0;
virtual void UpdateAttackPowerAndDamage(bool ranged = false) = 0;
- virtual void UpdateDamagePhysical(WeaponAttackType attType) = 0;
+ virtual void UpdateDamagePhysical(WeaponAttackType attType);
float GetTotalAttackPowerValue(WeaponAttackType attType) const;
float GetWeaponDamageRange(WeaponAttackType attType, WeaponDamageRange type) const;
void SetBaseWeaponDamage(WeaponAttackType attType, WeaponDamageRange damageRange, float value) { m_weaponDamage[attType][damageRange] = value; }
+ virtual void CalculateMinMaxDamage(WeaponAttackType attType, bool normalized, bool addTotalPct, float& minDamage, float& maxDamage) = 0;
+ uint32 CalculateDamage(WeaponAttackType attType, bool normalized, bool addTotalPct);
+ float GetAPMultiplier(WeaponAttackType attType, bool normalized);
bool isInFrontInMap(Unit const* target, float distance, float arc = M_PI) const;
bool isInBackInMap(Unit const* target, float distance, float arc = M_PI) const;
@@ -1935,8 +1939,6 @@ class Unit : public WorldObject
void RemoveGameObject(uint32 spellid, bool del);
void RemoveAllGameObjects();
- uint32 CalculateDamage(WeaponAttackType attType, bool normalized, bool addTotalPct);
- float GetAPMultiplier(WeaponAttackType attType, bool normalized);
void ModifyAuraState(AuraStateType flag, bool apply);
uint32 BuildAuraStateUpdateForTarget(Unit* target) const;
bool HasAuraState(AuraStateType flag, SpellInfo const* spellProto = NULL, Unit const* Caster = NULL) const;
@@ -1956,7 +1958,6 @@ class Unit : public WorldObject
uint32 MeleeDamageBonusDone(Unit* pVictim, uint32 damage, WeaponAttackType attType, SpellInfo const* spellProto = NULL);
uint32 MeleeDamageBonusTaken(Unit* attacker, uint32 pdamage, WeaponAttackType attType, SpellInfo const* spellProto = NULL);
-
bool isSpellBlocked(Unit* victim, SpellInfo const* spellProto, WeaponAttackType attackType = BASE_ATTACK);
bool isBlockCritical();
bool isSpellCrit(Unit* victim, SpellInfo const* spellProto, SpellSchoolMask schoolMask, WeaponAttackType attackType = BASE_ATTACK) const;
diff --git a/src/server/game/Globals/ObjectMgr.cpp b/src/server/game/Globals/ObjectMgr.cpp
index a84e2910e52..0d6990acb01 100644
--- a/src/server/game/Globals/ObjectMgr.cpp
+++ b/src/server/game/Globals/ObjectMgr.cpp
@@ -883,7 +883,7 @@ void ObjectMgr::CheckCreatureTemplate(CreatureTemplate const* cInfo)
const_cast<CreatureTemplate*>(cInfo)->scale = 1.0f;
}
- if (cInfo->expansion > (MAX_CREATURE_BASE_HP - 1))
+ if (cInfo->expansion > (MAX_EXPANSIONS - 1))
{
TC_LOG_ERROR("sql.sql", "Table `creature_template` lists creature (Entry: %u) with expansion %u. Ignored and set to 0.", cInfo->Entry, cInfo->expansion);
const_cast<CreatureTemplate*>(cInfo)->expansion = 0;
@@ -1772,7 +1772,7 @@ bool ObjectMgr::MoveCreData(uint32 guid, uint32 mapId, const Position& pos)
// We use spawn coords to spawn
if (!map->Instanceable() && map->IsGridLoaded(data.posX, data.posY))
{
- Creature* creature = new Creature;
+ Creature* creature = new Creature();
if (!creature->LoadCreatureFromDB(guid, map))
{
TC_LOG_ERROR("misc", "MoveCreData: Cannot add creature guid %u to map", guid);
@@ -1824,7 +1824,7 @@ uint32 ObjectMgr::AddCreData(uint32 entry, uint32 /*team*/, uint32 mapId, float
// We use spawn coords to spawn
if (!map->Instanceable() && !map->IsRemovalGrid(x, y))
{
- Creature* creature = new Creature;
+ Creature* creature = new Creature();
if (!creature->LoadCreatureFromDB(guid, map))
{
TC_LOG_ERROR("misc", "AddCreature: Cannot add creature entry %u to map", entry);
@@ -3044,8 +3044,8 @@ void ObjectMgr::LoadPetLevelInfo()
{
if (pInfo[level].health == 0)
{
- TC_LOG_ERROR("sql.sql", "Creature %u has no data for Level %i pet stats data, using data of Level %i.", itr->first, level+1, level);
- pInfo[level] = pInfo[level-1];
+ TC_LOG_ERROR("sql.sql", "Creature %u has no data for Level %i pet stats data, using data of Level %i.", itr->first, level + 1, level);
+ pInfo[level] = pInfo[level - 1];
}
}
}
@@ -3266,7 +3266,7 @@ void ObjectMgr::LoadPlayerInfo()
if (!result)
{
- TC_LOG_ERROR("server.loading", ">> Loaded 0 player create spells. DB table `%s` is empty.", sWorld->getBoolConfig(CONFIG_START_ALL_SPELLS) ? "playercreateinfo_spell_custom" : "playercreateinfo_spell");
+ TC_LOG_ERROR("server.loading", ">> Loaded 0 player create spells. DB table `%s` is empty.", tableName.c_str());
}
else
{
@@ -3281,13 +3281,13 @@ void ObjectMgr::LoadPlayerInfo()
if (raceMask != 0 && !(raceMask & RACEMASK_ALL_PLAYABLE))
{
- TC_LOG_ERROR("sql.sql", "Wrong race mask %u in `playercreateinfo_spell` table, ignoring.", raceMask);
+ TC_LOG_ERROR("sql.sql", "Wrong race mask %u in `%s` table, ignoring.", raceMask, tableName.c_str());
continue;
}
if (classMask != 0 && !(classMask & CLASSMASK_ALL_PLAYABLE))
{
- TC_LOG_ERROR("sql.sql", "Wrong class mask %u in `playercreateinfo_spell` table, ignoring.", classMask);
+ TC_LOG_ERROR("sql.sql", "Wrong class mask %u in `%s` table, ignoring.", classMask, tableName.c_str());
continue;
}
@@ -3307,7 +3307,7 @@ void ObjectMgr::LoadPlayerInfo()
// We need something better here, the check is not accounting for spells used by multiple races/classes but not all of them.
// Either split the masks per class, or per race, which kind of kills the point yet.
// else if (raceMask != 0 && classMask != 0)
- // TC_LOG_ERROR("sql.sql", "Racemask/classmask (%u/%u) combination was found containing an invalid race/class combination (%u/%u) in `playercreateinfo_spell` (Spell %u), ignoring.", raceMask, classMask, raceIndex, classIndex, spellId);
+ // TC_LOG_ERROR("sql.sql", "Racemask/classmask (%u/%u) combination was found containing an invalid race/class combination (%u/%u) in `%s` (Spell %u), ignoring.", raceMask, classMask, raceIndex, classIndex, tableName.c_str(), spellId);
}
}
}
@@ -3374,7 +3374,7 @@ void ObjectMgr::LoadPlayerInfo()
if (!result)
{
- TC_LOG_ERROR("server.loading", ">> Loaded 0 level health/mana definitions. DB table `game_event_condition` is empty.");
+ TC_LOG_ERROR("server.loading", ">> Loaded 0 level health/mana definitions. DB table `player_classlevelstats` is empty.");
exit(1);
}
@@ -3437,8 +3437,8 @@ void ObjectMgr::LoadPlayerInfo()
{
if (pClassInfo->levelInfo[level].basehealth == 0)
{
- TC_LOG_ERROR("sql.sql", "Class %i Level %i does not have health/mana data. Using stats data of level %i.", class_, level+1, level);
- pClassInfo->levelInfo[level] = pClassInfo->levelInfo[level-1];
+ TC_LOG_ERROR("sql.sql", "Class %i Level %i does not have health/mana data. Using stats data of level %i.", class_, level + 1, level);
+ pClassInfo->levelInfo[level] = pClassInfo->levelInfo[level - 1];
}
}
}
@@ -3498,9 +3498,9 @@ void ObjectMgr::LoadPlayerInfo()
if (!info->levelInfo)
info->levelInfo = new PlayerLevelInfo[sWorld->getIntConfig(CONFIG_MAX_PLAYER_LEVEL)];
- PlayerLevelInfo& levelInfo = info->levelInfo[current_level-1];
+ PlayerLevelInfo& levelInfo = info->levelInfo[current_level - 1];
for (int i = 0; i < MAX_STATS; i++)
- levelInfo.stats[i] = fields[i+3].GetUInt8();
+ levelInfo.stats[i] = fields[i + 3].GetUInt8();
}
++count;
@@ -3525,11 +3525,11 @@ void ObjectMgr::LoadPlayerInfo()
continue;
// skip expansion races if not playing with expansion
- if (sWorld->getIntConfig(CONFIG_EXPANSION) < 1 && (race == RACE_BLOODELF || race == RACE_DRAENEI))
+ if (sWorld->getIntConfig(CONFIG_EXPANSION) < EXPANSION_THE_BURNING_CRUSADE && (race == RACE_BLOODELF || race == RACE_DRAENEI))
continue;
// skip expansion classes if not playing with expansion
- if (sWorld->getIntConfig(CONFIG_EXPANSION) < 2 && class_ == CLASS_DEATH_KNIGHT)
+ if (sWorld->getIntConfig(CONFIG_EXPANSION) < EXPANSION_WRATH_OF_THE_LICH_KING && class_ == CLASS_DEATH_KNIGHT)
continue;
// fatal error if no level 1 data
@@ -3544,8 +3544,8 @@ void ObjectMgr::LoadPlayerInfo()
{
if (info->levelInfo[level].stats[0] == 0)
{
- TC_LOG_ERROR("sql.sql", "Race %i Class %i Level %i does not have stats data. Using stats data of level %i.", race, class_, level+1, level);
- info->levelInfo[level] = info->levelInfo[level-1];
+ TC_LOG_ERROR("sql.sql", "Race %i Class %i Level %i does not have stats data. Using stats data of level %i.", race, class_, level + 1, level);
+ info->levelInfo[level] = info->levelInfo[level - 1];
}
}
}
@@ -3603,8 +3603,8 @@ void ObjectMgr::LoadPlayerInfo()
{
if (_playerXPperLevel[level] == 0)
{
- TC_LOG_ERROR("sql.sql", "Level %i does not have XP for level data. Using data of level [%i] + 100.", level+1, level);
- _playerXPperLevel[level] = _playerXPperLevel[level-1]+100;
+ TC_LOG_ERROR("sql.sql", "Level %i does not have XP for level data. Using data of level [%i] + 100.", level + 1, level);
+ _playerXPperLevel[level] = _playerXPperLevel[level - 1] + 100;
}
}
@@ -7468,9 +7468,9 @@ void ObjectMgr::LoadGameObjectForQuests()
{
switch (itr->second.type)
{
- // scan GO chest with loot including quest items
case GAMEOBJECT_TYPE_CHEST:
{
+ // scan GO chest with loot including quest items
uint32 loot_id = (itr->second.GetLootId());
// find quest loot for GO
@@ -7486,7 +7486,7 @@ void ObjectMgr::LoadGameObjectForQuests()
if (itr->second._generic.questID > 0) //quests objects
{
_gameObjectForQuestStore.insert(itr->second.entry);
- count++;
+ ++count;
}
break;
}
@@ -7495,7 +7495,7 @@ void ObjectMgr::LoadGameObjectForQuests()
if (itr->second.goober.questId > 0) //quests objects
{
_gameObjectForQuestStore.insert(itr->second.entry);
- count++;
+ ++count;
}
break;
}
@@ -8519,13 +8519,18 @@ CreatureBaseStats const* ObjectMgr::GetCreatureBaseStats(uint8 level, uint8 unit
DefaultCreatureBaseStats()
{
BaseArmor = 1;
- for (uint8 j = 0; j < MAX_CREATURE_BASE_HP; ++j)
+ for (uint8 j = 0; j < MAX_EXPANSIONS; ++j)
+ {
BaseHealth[j] = 1;
+ BaseDamage[j] = 0.0f;
+ }
BaseMana = 0;
+ AttackPower = 0;
+ RangedAttackPower = 0;
}
};
- static const DefaultCreatureBaseStats def_stats;
- return &def_stats;
+ static const DefaultCreatureBaseStats defStats;
+ return &defStats;
}
void ObjectMgr::LoadCreatureClassLevelStats()
@@ -8545,35 +8550,38 @@ void ObjectMgr::LoadCreatureClassLevelStats()
{
Field* fields = result->Fetch();
- uint8 Level = fields[0].GetInt8();
- uint8 Class = fields[1].GetInt8();
-
- CreatureBaseStats stats;
-
- for (uint8 i = 0; i < MAX_CREATURE_BASE_HP; ++i)
- stats.BaseHealth[i] = fields[i + 2].GetInt16();
-
- stats.BaseMana = fields[5].GetInt16();
- stats.BaseArmor = fields[6].GetInt16();
-
- stats.AttackPower = fields[7].GetInt16();
- stats.RangedAttackPower = fields[8].GetInt16();
-
- for (uint8 i = 0; i < MAX_CREATURE_BASE_DAMAGE; ++i)
- stats.BaseDamage[i] = fields[i + 9].GetFloat();
+ uint8 Level = fields[0].GetUInt8();
+ uint8 Class = fields[1].GetUInt8();
if (!Class || ((1 << (Class - 1)) & CLASSMASK_ALL_CREATURES) == 0)
TC_LOG_ERROR("sql.sql", "Creature base stats for level %u has invalid class %u", Level, Class);
- for (uint8 i = 0; i < MAX_CREATURE_BASE_HP; ++i)
+ CreatureBaseStats stats;
+
+ for (uint8 i = 0; i < MAX_EXPANSIONS; ++i)
{
- if (stats.BaseHealth[i] < 1)
+ stats.BaseHealth[i] = fields[2 + i].GetUInt16();
+
+ if (stats.BaseHealth[i] == 0)
{
TC_LOG_ERROR("sql.sql", "Creature base stats for class %u, level %u has invalid zero base HP[%u] - set to 1", Class, Level, i);
stats.BaseHealth[i] = 1;
}
+
+ stats.BaseDamage[i] = fields[9 + i].GetFloat();
+ if (stats.BaseDamage[i] < 0.0f)
+ {
+ TC_LOG_ERROR("sql.sql", "Creature base stats for class %u, level %u has invalid negative base damage[%u] - set to 0.0", Class, Level, i);
+ stats.BaseDamage[i] = 0.0f;
+ }
}
+ stats.BaseMana = fields[5].GetUInt16();
+ stats.BaseArmor = fields[6].GetUInt16();
+
+ stats.AttackPower = fields[7].GetUInt16();
+ stats.RangedAttackPower = fields[8].GetUInt16();
+
_creatureBaseStatsStore[MAKE_PAIR16(Level, Class)] = stats;
++count;
diff --git a/src/server/game/Miscellaneous/SharedDefines.h b/src/server/game/Miscellaneous/SharedDefines.h
index 9d63e97a159..e5d3a5312de 100644
--- a/src/server/game/Miscellaneous/SharedDefines.h
+++ b/src/server/game/Miscellaneous/SharedDefines.h
@@ -44,6 +44,14 @@ enum LootModes
LOOT_MODE_HARD_MODE_4 = 0x10
};
+enum Expansions
+{
+ EXPANSION_CLASSIC = 0,
+ EXPANSION_THE_BURNING_CRUSADE = 1,
+ EXPANSION_WRATH_OF_THE_LICH_KING = 2,
+ MAX_EXPANSIONS = 3
+};
+
enum Gender
{
GENDER_MALE = 0,
diff --git a/src/server/game/Spells/Auras/SpellAuraEffects.cpp b/src/server/game/Spells/Auras/SpellAuraEffects.cpp
index 6a3e804eb57..4cc7e60ceaa 100644
--- a/src/server/game/Spells/Auras/SpellAuraEffects.cpp
+++ b/src/server/game/Spells/Auras/SpellAuraEffects.cpp
@@ -2214,26 +2214,26 @@ void AuraEffect::HandleAuraModDisarm(AuraApplication const* aurApp, uint8 mode,
WeaponAttackType attType;
switch (type)
{
- case SPELL_AURA_MOD_DISARM:
- field=UNIT_FIELD_FLAGS;
- flag=UNIT_FLAG_DISARMED;
- slot=EQUIPMENT_SLOT_MAINHAND;
- attType=BASE_ATTACK;
- break;
- case SPELL_AURA_MOD_DISARM_OFFHAND:
- field=UNIT_FIELD_FLAGS_2;
- flag=UNIT_FLAG2_DISARM_OFFHAND;
- slot=EQUIPMENT_SLOT_OFFHAND;
- attType=OFF_ATTACK;
- break;
- case SPELL_AURA_MOD_DISARM_RANGED:
- field=UNIT_FIELD_FLAGS_2;
- flag=UNIT_FLAG2_DISARM_RANGED;
- slot=EQUIPMENT_SLOT_RANGED;
- attType=RANGED_ATTACK;
- break;
- default:
- return;
+ case SPELL_AURA_MOD_DISARM:
+ field = UNIT_FIELD_FLAGS;
+ flag = UNIT_FLAG_DISARMED;
+ slot = EQUIPMENT_SLOT_MAINHAND;
+ attType = BASE_ATTACK;
+ break;
+ case SPELL_AURA_MOD_DISARM_OFFHAND:
+ field = UNIT_FIELD_FLAGS_2;
+ flag = UNIT_FLAG2_DISARM_OFFHAND;
+ slot = EQUIPMENT_SLOT_OFFHAND;
+ attType = OFF_ATTACK;
+ break;
+ case SPELL_AURA_MOD_DISARM_RANGED:
+ field = UNIT_FIELD_FLAGS_2;
+ flag = UNIT_FLAG2_DISARM_RANGED;
+ slot = EQUIPMENT_SLOT_RANGED;
+ attType = RANGED_ATTACK;
+ break;
+ default:
+ return;
}
// if disarm aura is to be removed, remove the flag first to reapply damage/aura mods
@@ -4112,7 +4112,7 @@ void AuraEffect::HandleModAttackSpeed(AuraApplication const* aurApp, uint8 mode,
Unit* target = aurApp->GetTarget();
- target->ApplyAttackTimePercentMod(BASE_ATTACK, (float)GetAmount(), apply);
+ target->ApplyAttackTimePercentMod(BASE_ATTACK, float(GetAmount()), apply);
target->UpdateDamagePhysical(BASE_ATTACK);
}
@@ -4123,8 +4123,8 @@ void AuraEffect::HandleModMeleeSpeedPct(AuraApplication const* aurApp, uint8 mod
Unit* target = aurApp->GetTarget();
- target->ApplyAttackTimePercentMod(BASE_ATTACK, (float)GetAmount(), apply);
- target->ApplyAttackTimePercentMod(OFF_ATTACK, (float)GetAmount(), apply);
+ target->ApplyAttackTimePercentMod(BASE_ATTACK, float(GetAmount()), apply);
+ target->ApplyAttackTimePercentMod(OFF_ATTACK, float(GetAmount()), apply);
}
void AuraEffect::HandleAuraModRangedHaste(AuraApplication const* aurApp, uint8 mode, bool apply) const
@@ -4371,9 +4371,9 @@ void AuraEffect::HandleModDamagePercentDone(AuraApplication const* aurApp, uint8
if ((GetMiscValue() & SPELL_SCHOOL_MASK_NORMAL) && (GetSpellInfo()->EquippedItemClass == -1 || target->GetTypeId() != TYPEID_PLAYER))
{
- target->HandleStatModifier(UNIT_MOD_DAMAGE_MAINHAND, TOTAL_PCT, float (GetAmount()), apply);
- target->HandleStatModifier(UNIT_MOD_DAMAGE_OFFHAND, TOTAL_PCT, float (GetAmount()), apply);
- target->HandleStatModifier(UNIT_MOD_DAMAGE_RANGED, TOTAL_PCT, float (GetAmount()), apply);
+ target->HandleStatModifier(UNIT_MOD_DAMAGE_MAINHAND, TOTAL_PCT, float(GetAmount()), apply);
+ target->HandleStatModifier(UNIT_MOD_DAMAGE_OFFHAND, TOTAL_PCT, float(GetAmount()), apply);
+ target->HandleStatModifier(UNIT_MOD_DAMAGE_RANGED, TOTAL_PCT, float(GetAmount()), apply);
if (target->GetTypeId() == TYPEID_PLAYER)
target->ToPlayer()->ApplyPercentModFloatValue(PLAYER_FIELD_MOD_DAMAGE_DONE_PCT, float (GetAmount()), apply);
diff --git a/src/server/game/Spells/SpellEffects.cpp b/src/server/game/Spells/SpellEffects.cpp
index 9a2b3815285..81eb45191bf 100644
--- a/src/server/game/Spells/SpellEffects.cpp
+++ b/src/server/game/Spells/SpellEffects.cpp
@@ -2538,8 +2538,6 @@ void Spell::EffectDualWield(SpellEffIndex /*effIndex*/)
return;
unitTarget->SetCanDualWield(true);
- if (unitTarget->GetTypeId() == TYPEID_UNIT)
- unitTarget->ToCreature()->UpdateDamagePhysical(OFF_ATTACK);
}
void Spell::EffectPull(SpellEffIndex effIndex)
@@ -5819,11 +5817,11 @@ void Spell::SummonGuardian(uint32 i, uint32 entry, SummonPropertiesEntry const*
{
if (uint32 weapon = m_caster->GetUInt32Value(PLAYER_VISIBLE_ITEM_16_ENTRYID))
{
- summon->SetDisplayId(11686);
+ summon->SetDisplayId(11686); // modelid2
summon->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID, weapon);
}
else
- summon->SetDisplayId(1126);
+ summon->SetDisplayId(1126); // modelid1
}
summon->AI()->EnterEvadeMode();
diff --git a/src/server/scripts/EasternKingdoms/Karazhan/boss_prince_malchezaar.cpp b/src/server/scripts/EasternKingdoms/Karazhan/boss_prince_malchezaar.cpp
index b82c0099ce4..bde326a5c37 100644
--- a/src/server/scripts/EasternKingdoms/Karazhan/boss_prince_malchezaar.cpp
+++ b/src/server/scripts/EasternKingdoms/Karazhan/boss_prince_malchezaar.cpp
@@ -297,12 +297,7 @@ public:
void ClearWeapons()
{
SetEquipmentSlots(false, EQUIP_UNEQUIP, EQUIP_UNEQUIP, EQUIP_NO_CHANGE);
-
- //damage
- const CreatureTemplate* cinfo = me->GetCreatureTemplate();
- me->SetBaseWeaponDamage(BASE_ATTACK, MINDAMAGE, cinfo->mindmg);
- me->SetBaseWeaponDamage(BASE_ATTACK, MAXDAMAGE, cinfo->maxdmg);
- me->UpdateDamagePhysical(BASE_ATTACK);
+ me->SetCanDualWield(false);
}
void EnfeebleHealthEffect()
@@ -419,19 +414,8 @@ public:
//models
SetEquipmentSlots(false, EQUIP_ID_AXE, EQUIP_ID_AXE, EQUIP_NO_CHANGE);
- //damage
- const CreatureTemplate* cinfo = me->GetCreatureTemplate();
- me->SetBaseWeaponDamage(BASE_ATTACK, MINDAMAGE, 2*cinfo->mindmg);
- me->SetBaseWeaponDamage(BASE_ATTACK, MAXDAMAGE, 2*cinfo->maxdmg);
- me->UpdateDamagePhysical(BASE_ATTACK);
-
- me->SetBaseWeaponDamage(OFF_ATTACK, MINDAMAGE, cinfo->mindmg);
- me->SetBaseWeaponDamage(OFF_ATTACK, MAXDAMAGE, cinfo->maxdmg);
- //Sigh, updating only works on main attack, do it manually ....
- me->SetFloatValue(UNIT_FIELD_MINOFFHANDDAMAGE, cinfo->mindmg);
- me->SetFloatValue(UNIT_FIELD_MAXOFFHANDDAMAGE, cinfo->maxdmg);
-
me->SetAttackTime(OFF_ATTACK, (me->GetAttackTime(BASE_ATTACK)*150)/100);
+ me->SetCanDualWield(true);
}
}
else if (phase == 2)
diff --git a/src/server/scripts/EasternKingdoms/ZulGurub/boss_arlokk.cpp b/src/server/scripts/EasternKingdoms/ZulGurub/boss_arlokk.cpp
index 4bf50581108..5b943fd57f2 100644
--- a/src/server/scripts/EasternKingdoms/ZulGurub/boss_arlokk.cpp
+++ b/src/server/scripts/EasternKingdoms/ZulGurub/boss_arlokk.cpp
@@ -96,24 +96,21 @@ class boss_arlokk : public CreatureScript
void Reset() OVERRIDE
{
+ if (events.IsInPhase(PHASE_TWO))
+ me->HandleStatModifier(UNIT_MOD_DAMAGE_MAINHAND, TOTAL_PCT, 35.0f, false); // hack
+ _Reset();
_summonCountA = 0;
_summonCountB = 0;
- me->RemoveAllAuras();
me->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID + 0, uint32(WEAPON_DAGGER));
me->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID + 1, uint32(WEAPON_DAGGER));
- if (GameObject* gate = me->GetMap()->GetGameObject(instance->GetData64(GO_FORCEFIELD)))
- gate->SetGoState(GO_STATE_READY);
me->SetWalk(false);
me->GetMotionMaster()->MovePoint(0, PosMoveOnSpawn[0]);
}
void JustDied(Unit* /*killer*/) OVERRIDE
{
+ _JustDied();
Talk(SAY_DEATH);
- me->RemoveAllAuras();
- if (GameObject* gate = me->GetMap()->GetGameObject(instance->GetData64(GO_FORCEFIELD)))
- gate->SetGoState(GO_STATE_ACTIVE);
- instance->SetBossState(DATA_ARLOKK, DONE);
}
void EnterCombat(Unit* /*who*/) OVERRIDE
@@ -154,11 +151,9 @@ class boss_arlokk : public CreatureScript
void EnterEvadeMode() OVERRIDE
{
- if (GameObject* object = me->GetMap()->GetGameObject(instance->GetData64(GO_FORCEFIELD)))
- object->SetGoState(GO_STATE_ACTIVE);
- if (GameObject* object = me->GetMap()->GetGameObject(instance->GetData64(GO_GONG_OF_BETHEKK)))
+ BossAI::EnterEvadeMode();
+ if (GameObject* object = ObjectAccessor::GetGameObject(*me, instance->GetData64(GO_GONG_OF_BETHEKK)))
object->RemoveFlag(GAMEOBJECT_FLAGS, GO_FLAG_NOT_SELECTABLE);
- instance->SetBossState(DATA_ARLOKK, NOT_STARTED);
me->DespawnOrUnsummon(4000);
}
@@ -194,7 +189,7 @@ class boss_arlokk : public CreatureScript
case EVENT_SUMMON_PROWLERS:
if (_summonCountA < MAX_PROWLERS_PER_SIDE)
{
- if (Unit* trigger = me->GetUnit(*me, _triggersSideAGUID[urand(0, 4)]))
+ if (Unit* trigger = ObjectAccessor::GetUnit(*me, _triggersSideAGUID[urand(0, 4)]))
{
trigger->CastSpell(trigger, SPELL_SUMMON_PROWLER);
++_summonCountA;
@@ -202,7 +197,7 @@ class boss_arlokk : public CreatureScript
}
if (_summonCountB < MAX_PROWLERS_PER_SIDE)
{
- if (Unit* trigger = me->GetUnit(*me, _triggersSideBGUID[urand(0, 4)]))
+ if (Unit* trigger = ObjectAccessor::GetUnit(*me, _triggersSideBGUID[urand(0, 4)]))
{
trigger->CastSpell(trigger, SPELL_SUMMON_PROWLER);
++_summonCountB;
@@ -225,13 +220,15 @@ class boss_arlokk : public CreatureScript
}
case EVENT_TRANSFORM:
{
- DoCast(me, SPELL_PANTHER_TRANSFORM);
+ DoCast(me, SPELL_PANTHER_TRANSFORM); // SPELL_AURA_TRANSFORM
me->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID + 0, uint32(EQUIP_UNEQUIP));
me->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID + 1, uint32(EQUIP_UNEQUIP));
+ /*
const CreatureTemplate* cinfo = me->GetCreatureTemplate();
me->SetBaseWeaponDamage(BASE_ATTACK, MINDAMAGE, (cinfo->mindmg +((cinfo->mindmg/100) * 35)));
me->SetBaseWeaponDamage(BASE_ATTACK, MAXDAMAGE, (cinfo->maxdmg +((cinfo->maxdmg/100) * 35)));
me->UpdateDamagePhysical(BASE_ATTACK);
+ */
me->AttackStop();
DoResetThreat();
me->SetReactState(REACT_PASSIVE);
@@ -262,6 +259,7 @@ class boss_arlokk : public CreatureScript
events.ScheduleEvent(EVENT_RAVAGE, urand(10000, 14000), 0, PHASE_TWO);
events.ScheduleEvent(EVENT_TRANSFORM_BACK, urand(15000, 18000), 0, PHASE_TWO);
events.SetPhase(PHASE_TWO);
+ me->HandleStatModifier(UNIT_MOD_DAMAGE_MAINHAND, TOTAL_PCT, 35.0f, true); // hack
break;
case EVENT_RAVAGE:
DoCastVictim(SPELL_RAVAGE, true);
@@ -269,14 +267,17 @@ class boss_arlokk : public CreatureScript
break;
case EVENT_TRANSFORM_BACK:
{
- me->RemoveAura(SPELL_PANTHER_TRANSFORM);
+ me->RemoveAura(SPELL_PANTHER_TRANSFORM); // SPELL_AURA_TRANSFORM
DoCast(me, SPELL_VANISH_VISUAL);
me->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID + 0, uint32(WEAPON_DAGGER));
me->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID + 1, uint32(WEAPON_DAGGER));
+ /*
const CreatureTemplate* cinfo = me->GetCreatureTemplate();
me->SetBaseWeaponDamage(BASE_ATTACK, MINDAMAGE, (cinfo->mindmg));
me->SetBaseWeaponDamage(BASE_ATTACK, MAXDAMAGE, (cinfo->maxdmg));
me->UpdateDamagePhysical(BASE_ATTACK);
+ */
+ me->HandleStatModifier(UNIT_MOD_DAMAGE_MAINHAND, TOTAL_PCT, 35.0f, false); // hack
events.ScheduleEvent(EVENT_SHADOW_WORD_PAIN, urand(4000, 7000), 0, PHASE_ONE);
events.ScheduleEvent(EVENT_GOUGE, urand(12000, 15000), 0, PHASE_ONE);
events.ScheduleEvent(EVENT_TRANSFORM, urand(16000, 20000), 0, PHASE_ONE);
diff --git a/src/server/scripts/EasternKingdoms/ZulGurub/boss_marli.cpp b/src/server/scripts/EasternKingdoms/ZulGurub/boss_marli.cpp
index 3ff18d81032..efd79d89a2b 100644
--- a/src/server/scripts/EasternKingdoms/ZulGurub/boss_marli.cpp
+++ b/src/server/scripts/EasternKingdoms/ZulGurub/boss_marli.cpp
@@ -64,11 +64,6 @@ enum Phases
PHASE_THREE = 3
};
-enum ModelId
-{
- MODEL_MARLI = 15220
-};
-
class boss_marli : public CreatureScript
{
public: boss_marli() : CreatureScript("boss_marli") { }
@@ -79,6 +74,8 @@ class boss_marli : public CreatureScript
void Reset() OVERRIDE
{
+ if (events.IsInPhase(PHASE_THREE))
+ me->HandleStatModifier(UNIT_MOD_DAMAGE_MAINHAND, TOTAL_PCT, 35.0f, false); // hack
_Reset();
}
@@ -155,11 +152,14 @@ class boss_marli : public CreatureScript
case EVENT_TRANSFORM:
{
Talk(SAY_TRANSFORM);
- DoCast(me, SPELL_SPIDER_FORM);
+ DoCast(me, SPELL_SPIDER_FORM); // SPELL_AURA_TRANSFORM
+ /*
CreatureTemplate const* cinfo = me->GetCreatureTemplate();
me->SetBaseWeaponDamage(BASE_ATTACK, MINDAMAGE, (cinfo->mindmg +((cinfo->mindmg/100) * 35)));
me->SetBaseWeaponDamage(BASE_ATTACK, MAXDAMAGE, (cinfo->maxdmg +((cinfo->maxdmg/100) * 35)));
me->UpdateDamagePhysical(BASE_ATTACK);
+ */
+ me->HandleStatModifier(UNIT_MOD_DAMAGE_MAINHAND, TOTAL_PCT, 35.0f, true); // hack
DoCastVictim(SPELL_ENVOLWINGWEB);
if (DoGetThreat(me->GetVictim()))
DoModifyThreatPercent(me->GetVictim(), -100);
@@ -188,11 +188,14 @@ class boss_marli : public CreatureScript
}
case EVENT_TRANSFORM_BACK:
{
- me->SetDisplayId(MODEL_MARLI);
+ me->RemoveAura(SPELL_SPIDER_FORM);
+ /*
CreatureTemplate const* cinfo = me->GetCreatureTemplate();
me->SetBaseWeaponDamage(BASE_ATTACK, MINDAMAGE, (cinfo->mindmg +((cinfo->mindmg/100) * 1)));
me->SetBaseWeaponDamage(BASE_ATTACK, MAXDAMAGE, (cinfo->maxdmg +((cinfo->maxdmg/100) * 1)));
me->UpdateDamagePhysical(BASE_ATTACK);
+ */
+ me->HandleStatModifier(UNIT_MOD_DAMAGE_MAINHAND, TOTAL_PCT, 35.0f, false); // hack
events.ScheduleEvent(EVENT_ASPECT_OF_MARLI, 12000, 0, PHASE_TWO);
events.ScheduleEvent(EVENT_TRANSFORM, 45000, 0, PHASE_TWO);
events.ScheduleEvent(EVENT_POISON_VOLLEY, 15000);
diff --git a/src/server/scripts/EasternKingdoms/ZulGurub/boss_thekal.cpp b/src/server/scripts/EasternKingdoms/ZulGurub/boss_thekal.cpp
index d857bff69e0..a70dd5e0a30 100644
--- a/src/server/scripts/EasternKingdoms/ZulGurub/boss_thekal.cpp
+++ b/src/server/scripts/EasternKingdoms/ZulGurub/boss_thekal.cpp
@@ -89,6 +89,8 @@ class boss_thekal : public CreatureScript
void Reset() OVERRIDE
{
+ if (events.IsInPhase(PHASE_TWO))
+ me->HandleStatModifier(UNIT_MOD_DAMAGE_MAINHAND, TOTAL_PCT, 35.0f, false); // hack
_Reset();
Enraged = false;
WasDead = false;
@@ -141,15 +143,17 @@ class boss_thekal : public CreatureScript
//Thekal will transform to Tiger if he died and was not resurrected after 10 seconds.
if (WasDead)
{
- DoCast(me, SPELL_TIGER_FORM);
+ DoCast(me, SPELL_TIGER_FORM); // SPELL_AURA_TRANSFORM
me->SetObjectScale(2.00f);
me->SetStandState(UNIT_STAND_STATE_STAND);
me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
- me->SetFullHealth();
+ /*
const CreatureTemplate* cinfo = me->GetCreatureTemplate();
me->SetBaseWeaponDamage(BASE_ATTACK, MINDAMAGE, (cinfo->mindmg +((cinfo->mindmg/100) * 40)));
me->SetBaseWeaponDamage(BASE_ATTACK, MAXDAMAGE, (cinfo->maxdmg +((cinfo->maxdmg/100) * 40)));
me->UpdateDamagePhysical(BASE_ATTACK);
+ */
+ me->HandleStatModifier(UNIT_MOD_DAMAGE_MAINHAND, TOTAL_PCT, 40.0f, true); // hack
DoResetThreat();
events.ScheduleEvent(EVENT_FRENZY, 30000, 0, PHASE_TWO); // Phase 2
events.ScheduleEvent(EVENT_FORCEPUNCH, 4000, 0, PHASE_TWO); // Phase 2
diff --git a/src/server/scripts/EasternKingdoms/ZulGurub/instance_zulgurub.cpp b/src/server/scripts/EasternKingdoms/ZulGurub/instance_zulgurub.cpp
index 673450f83d0..67d40abaea3 100644
--- a/src/server/scripts/EasternKingdoms/ZulGurub/instance_zulgurub.cpp
+++ b/src/server/scripts/EasternKingdoms/ZulGurub/instance_zulgurub.cpp
@@ -27,6 +27,12 @@ EndScriptData */
#include "InstanceScript.h"
#include "zulgurub.h"
+DoorData const doorData[] =
+{
+ { GO_FORCEFIELD, DATA_ARLOKK, DOOR_TYPE_ROOM, BOUNDARY_NONE },
+ { 0, 0, DOOR_TYPE_ROOM, BOUNDARY_NONE } // END
+};
+
class instance_zulgurub : public InstanceMapScript
{
public: instance_zulgurub(): InstanceMapScript(ZGScriptName, 309) { }
@@ -36,6 +42,7 @@ class instance_zulgurub : public InstanceMapScript
instance_zulgurub_InstanceMapScript(Map* map) : InstanceScript(map)
{
SetBossNumber(EncounterCount);
+ LoadDoorData(doorData);
}
void Initialize() OVERRIDE
@@ -46,7 +53,6 @@ class instance_zulgurub : public InstanceMapScript
_jindoTheHexxerGUID = 0;
_vilebranchSpeakerGUID = 0;
_arlokkGUID = 0;
- _goForcefieldGUID = 0;
_goGongOfBethekkGUID = 0;
}
@@ -86,7 +92,7 @@ class instance_zulgurub : public InstanceMapScript
switch (go->GetEntry())
{
case GO_FORCEFIELD:
- _goForcefieldGUID = go->GetGUID();
+ AddDoor(go, true);
break;
case GO_GONG_OF_BETHEKK:
_goGongOfBethekkGUID = go->GetGUID();
@@ -100,6 +106,18 @@ class instance_zulgurub : public InstanceMapScript
}
}
+ void OnGameObjectRemove(GameObject* go) OVERRIDE
+ {
+ switch (go->GetEntry())
+ {
+ case GO_FORCEFIELD:
+ AddDoor(go, false);
+ break;
+ default:
+ break;
+ }
+ }
+
uint64 GetData64(uint32 uiData) const OVERRIDE
{
switch (uiData)
@@ -119,9 +137,6 @@ class instance_zulgurub : public InstanceMapScript
case NPC_ARLOKK:
return _arlokkGUID;
break;
- case GO_FORCEFIELD:
- return _goForcefieldGUID;
- break;
case GO_GONG_OF_BETHEKK:
return _goGongOfBethekkGUID;
break;
@@ -181,7 +196,6 @@ class instance_zulgurub : public InstanceMapScript
uint64 _jindoTheHexxerGUID;
uint64 _vilebranchSpeakerGUID;
uint64 _arlokkGUID;
- uint64 _goForcefieldGUID;
uint64 _goGongOfBethekkGUID;
};
diff --git a/src/server/scripts/Northrend/AzjolNerub/Ahnkahet/boss_elder_nadox.cpp b/src/server/scripts/Northrend/AzjolNerub/Ahnkahet/boss_elder_nadox.cpp
index 0b281c58839..84c9181e495 100644
--- a/src/server/scripts/Northrend/AzjolNerub/Ahnkahet/boss_elder_nadox.cpp
+++ b/src/server/scripts/Northrend/AzjolNerub/Ahnkahet/boss_elder_nadox.cpp
@@ -232,7 +232,6 @@ public:
npc_nadox_eggsAI(Creature* creature) : ScriptedAI(creature)
{
creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE | UNIT_FLAG_NON_ATTACKABLE);
- creature->UpdateAllStats();
}
void Reset() OVERRIDE { }
diff --git a/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/boss_twin_valkyr.cpp b/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/boss_twin_valkyr.cpp
index d0120e4c2de..0d7dc9062ad 100644
--- a/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/boss_twin_valkyr.cpp
+++ b/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/boss_twin_valkyr.cpp
@@ -281,7 +281,6 @@ struct boss_twin_baseAI : public BossAI
{
SetEquipmentSlots(false, Weapon, mode ? Weapon : int32(EQUIP_UNEQUIP), EQUIP_UNEQUIP);
me->SetCanDualWield(mode);
- me->UpdateDamagePhysical(mode ? OFF_ATTACK : BASE_ATTACK);
}
void UpdateAI(uint32 diff) OVERRIDE
diff --git a/src/server/scripts/Pet/pet_hunter.cpp b/src/server/scripts/Pet/pet_hunter.cpp
index 0db35bf2fe6..8a0b78b5478 100644
--- a/src/server/scripts/Pet/pet_hunter.cpp
+++ b/src/server/scripts/Pet/pet_hunter.cpp
@@ -25,9 +25,9 @@
enum HunterSpells
{
- SPELL_HUNTER_CRIPPLING_POISON = 30981, // Viper
- SPELL_HUNTER_DEADLY_POISON = 34655, // Venomous Snake
- SPELL_HUNTER_MIND_NUMBING_POISON = 25810 // Viper
+ SPELL_HUNTER_CRIPPLING_POISON = 30981, // Viper
+ SPELL_HUNTER_DEADLY_POISON_PASSIVE = 34657, // Venomous Snake
+ SPELL_HUNTER_MIND_NUMBING_POISON = 25810 // Viper
};
enum HunterCreatures
@@ -57,14 +57,17 @@ class npc_pet_hunter_snake_trap : public CreatureScript
me->SetMaxHealth(uint32(107 * (me->getLevel() - 40) * 0.025f));
// Add delta to make them not all hit the same time
uint32 delta = (rand() % 7) * 100;
- me->SetStatFloatValue(UNIT_FIELD_BASEATTACKTIME, float(Info->baseattacktime + delta));
- me->SetStatFloatValue(UNIT_FIELD_RANGED_ATTACK_POWER, float(Info->attackpower));
+ me->SetAttackTime(BASE_ATTACK, Info->baseattacktime + delta);
+ //me->SetStatFloatValue(UNIT_FIELD_RANGED_ATTACK_POWER, float(Info->attackpower));
// Start attacking attacker of owner on first ai update after spawn - move in line of sight may choose better target
if (!me->GetVictim() && me->IsSummon())
if (Unit* Owner = me->ToTempSummon()->GetSummoner())
if (Owner->getAttackerForHelper())
AttackStart(Owner->getAttackerForHelper());
+
+ if (!_isViper)
+ DoCast(me, SPELL_HUNTER_DEADLY_POISON_PASSIVE, true);
}
// Redefined for random target selection:
@@ -99,32 +102,19 @@ class npc_pet_hunter_snake_trap : public CreatureScript
return;
}
- if (_spellTimer <= diff)
+ // Viper
+ if (_isViper)
{
- if (_isViper) // Viper
+ if (_spellTimer <= diff)
{
- if (urand(0, 2) == 0) //33% chance to cast
- {
- uint32 spell;
- if (urand(0, 1) == 0)
- spell = SPELL_HUNTER_MIND_NUMBING_POISON;
- else
- spell = SPELL_HUNTER_CRIPPLING_POISON;
-
- DoCastVictim(spell);
- }
+ if (urand(0, 2) == 0) // 33% chance to cast
+ DoCastVictim(RAND(SPELL_HUNTER_MIND_NUMBING_POISON, SPELL_HUNTER_CRIPPLING_POISON));
_spellTimer = 3000;
}
- else // Venomous Snake
- {
- if (urand(0, 2) == 0) // 33% chance to cast
- DoCastVictim(SPELL_HUNTER_DEADLY_POISON);
- _spellTimer = 1500 + (rand() % 5) * 100;
- }
+ else
+ _spellTimer -= diff;
}
- else
- _spellTimer -= diff;
DoMeleeAttackIfReady();
}