mirror of
https://github.com/mangosfour/server.git
synced 2025-12-14 07:37:01 +00:00
Lots of cmangos commirs applied
This commit is contained in:
parent
8431568536
commit
18dd18780d
44 changed files with 677 additions and 323 deletions
|
|
@ -130,7 +130,6 @@ class BattleGroundQueue
|
||||||
bool AddGroup(GroupQueueInfo* ginfo, uint32 desiredCount);
|
bool AddGroup(GroupQueueInfo* ginfo, uint32 desiredCount);
|
||||||
bool KickGroup(uint32 size);
|
bool KickGroup(uint32 size);
|
||||||
uint32 GetPlayerCount() const {return PlayerCount;}
|
uint32 GetPlayerCount() const {return PlayerCount;}
|
||||||
public:
|
|
||||||
GroupsQueueType SelectedGroups;
|
GroupsQueueType SelectedGroups;
|
||||||
private:
|
private:
|
||||||
uint32 PlayerCount;
|
uint32 PlayerCount;
|
||||||
|
|
|
||||||
|
|
@ -235,8 +235,6 @@ bool ChatHandler::HandleTriggerCommand(char* args)
|
||||||
|
|
||||||
float dist2 = MAP_SIZE * MAP_SIZE;
|
float dist2 = MAP_SIZE * MAP_SIZE;
|
||||||
|
|
||||||
Player* pl = m_session->GetPlayer();
|
|
||||||
|
|
||||||
// Search triggers
|
// Search triggers
|
||||||
for (uint32 id = 0; id < sAreaTriggerStore.GetNumRows(); ++id)
|
for (uint32 id = 0; id < sAreaTriggerStore.GetNumRows(); ++id)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -734,17 +734,17 @@ dtStatus PathFinder::findSmoothPath(const float* startPos, const float* endPos,
|
||||||
npolys -= npos;
|
npolys -= npos;
|
||||||
|
|
||||||
// Handle the connection.
|
// Handle the connection.
|
||||||
float startPos[VERTEX_SIZE], endPos[VERTEX_SIZE];
|
float newStartPos[VERTEX_SIZE], newEndPos[VERTEX_SIZE];
|
||||||
dtResult = m_navMesh->getOffMeshConnectionPolyEndPoints(prevRef, polyRef, startPos, endPos);
|
dtResult = m_navMesh->getOffMeshConnectionPolyEndPoints(prevRef, polyRef, newStartPos, newEndPos);
|
||||||
if (dtStatusSucceed(dtResult))
|
if (dtStatusSucceed(dtResult))
|
||||||
{
|
{
|
||||||
if (nsmoothPath < maxSmoothPathSize)
|
if (nsmoothPath < maxSmoothPathSize)
|
||||||
{
|
{
|
||||||
dtVcopy(&smoothPath[nsmoothPath * VERTEX_SIZE], startPos);
|
dtVcopy(&smoothPath[nsmoothPath * VERTEX_SIZE], newStartPos);
|
||||||
++nsmoothPath;
|
++nsmoothPath;
|
||||||
}
|
}
|
||||||
// Move position at the other side of the off-mesh link.
|
// Move position at the other side of the off-mesh link.
|
||||||
dtVcopy(iterPos, endPos);
|
dtVcopy(iterPos, newEndPos);
|
||||||
|
|
||||||
m_navMeshQuery->getPolyHeight(polys[0], iterPos, &iterPos[1]);
|
m_navMeshQuery->getPolyHeight(polys[0], iterPos, &iterPos[1]);
|
||||||
iterPos[1] += 0.5f;
|
iterPos[1] += 0.5f;
|
||||||
|
|
|
||||||
|
|
@ -419,6 +419,7 @@ void FlightPathMovementGenerator::Reset(Player& player)
|
||||||
player.getHostileRefManager().setOnlineOfflineState(false);
|
player.getHostileRefManager().setOnlineOfflineState(false);
|
||||||
player.addUnitState(UNIT_STAT_TAXI_FLIGHT);
|
player.addUnitState(UNIT_STAT_TAXI_FLIGHT);
|
||||||
player.SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_DISABLE_MOVE | UNIT_FLAG_TAXI_FLIGHT);
|
player.SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_DISABLE_MOVE | UNIT_FLAG_TAXI_FLIGHT);
|
||||||
|
player.SetClientControl(&player, 0);
|
||||||
|
|
||||||
Movement::MoveSplineInit init(player);
|
Movement::MoveSplineInit init(player);
|
||||||
uint32 end = GetPathAtMapEnd();
|
uint32 end = GetPathAtMapEnd();
|
||||||
|
|
|
||||||
|
|
@ -411,7 +411,14 @@ bool Creature::UpdateEntry(uint32 Entry, Team team, const CreatureData* data /*=
|
||||||
// creatures always have melee weapon ready if any
|
// creatures always have melee weapon ready if any
|
||||||
SetSheath(SHEATH_STATE_MELEE);
|
SetSheath(SHEATH_STATE_MELEE);
|
||||||
|
|
||||||
SelectLevel(GetCreatureInfo(), preserveHPAndPower ? GetHealthPercent() : 100.0f);
|
if (preserveHPAndPower)
|
||||||
|
{
|
||||||
|
uint32 healthPercent = GetHealthPercent();
|
||||||
|
SelectLevel();
|
||||||
|
SetHealthPercent(healthPercent);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
SelectLevel();
|
||||||
|
|
||||||
if (team == HORDE)
|
if (team == HORDE)
|
||||||
setFaction(GetCreatureInfo()->FactionHorde);
|
setFaction(GetCreatureInfo()->FactionHorde);
|
||||||
|
|
@ -830,6 +837,9 @@ bool Creature::AIM_Initialize()
|
||||||
i_motionMaster.Initialize();
|
i_motionMaster.Initialize();
|
||||||
i_AI = FactorySelector::selectAI(this);
|
i_AI = FactorySelector::selectAI(this);
|
||||||
delete oldAI;
|
delete oldAI;
|
||||||
|
|
||||||
|
// Handle Spawned Events, also calls Reset()
|
||||||
|
i_AI->JustRespawned();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1241,6 +1251,126 @@ void Creature::SaveToDB(uint32 mapid, uint8 spawnMask, uint32 phaseMask)
|
||||||
WorldDatabase.CommitTransaction();
|
WorldDatabase.CommitTransaction();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Creature::SelectLevel(uint32 forcedLevel /*= USE_DEFAULT_DATABASE_LEVEL*/)
|
||||||
|
{
|
||||||
|
CreatureInfo const* cinfo = GetCreatureInfo();
|
||||||
|
if (!cinfo)
|
||||||
|
return;
|
||||||
|
|
||||||
|
uint32 rank = IsPet() ? 0 : cinfo->Rank; // TODO :: IsPet probably not needed here
|
||||||
|
|
||||||
|
// level
|
||||||
|
uint32 level = forcedLevel;
|
||||||
|
uint32 const minlevel = cinfo->MinLevel;
|
||||||
|
uint32 const maxlevel = cinfo->MaxLevel;
|
||||||
|
|
||||||
|
if (level == USE_DEFAULT_DATABASE_LEVEL)
|
||||||
|
level = minlevel == maxlevel ? minlevel : urand(minlevel, maxlevel);
|
||||||
|
|
||||||
|
SetLevel(level);
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
// Calculate level dependent stats
|
||||||
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
uint32 health;
|
||||||
|
uint32 mana;
|
||||||
|
|
||||||
|
if (CreatureClassLvlStats const* cCLS = sObjectMgr.GetCreatureClassLvlStats(level, cinfo->UnitClass, cinfo->Expansion))
|
||||||
|
{
|
||||||
|
// Use Creature Stats to calculate stat values
|
||||||
|
|
||||||
|
// health
|
||||||
|
health = cCLS->BaseHealth * cinfo->HealthMultiplier;
|
||||||
|
|
||||||
|
// mana
|
||||||
|
mana = cCLS->BaseMana * cinfo->PowerMultiplier;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (forcedLevel == USE_DEFAULT_DATABASE_LEVEL || (forcedLevel >= minlevel && forcedLevel <= maxlevel))
|
||||||
|
{
|
||||||
|
// Use old style to calculate stat values
|
||||||
|
float rellevel = maxlevel == minlevel ? 0 : (float(level - minlevel)) / (maxlevel - minlevel);
|
||||||
|
|
||||||
|
// health
|
||||||
|
uint32 minhealth = std::min(cinfo->MaxLevelHealth, cinfo->MinLevelHealth);
|
||||||
|
uint32 maxhealth = std::max(cinfo->MaxLevelHealth, cinfo->MinLevelHealth);
|
||||||
|
health = uint32(minhealth + uint32(rellevel * (maxhealth - minhealth)));
|
||||||
|
|
||||||
|
// mana
|
||||||
|
uint32 minmana = std::min(cinfo->MaxLevelMana, cinfo->MinLevelMana);
|
||||||
|
uint32 maxmana = std::max(cinfo->MaxLevelMana, cinfo->MinLevelMana);
|
||||||
|
mana = minmana + uint32(rellevel * (maxmana - minmana));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
sLog.outError("Creature::SelectLevel> Error trying to set level(%u) for creature %s without enough data to do it!", level, GetGuidStr().c_str());
|
||||||
|
// probably wrong
|
||||||
|
health = (cinfo->MaxLevelHealth / cinfo->MaxLevel) * level;
|
||||||
|
mana = (cinfo->MaxLevelMana / cinfo->MaxLevel) * level;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
health *= _GetHealthMod(rank); // Apply custom config settting
|
||||||
|
if (health < 1)
|
||||||
|
health = 1;
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
// Set values
|
||||||
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
// health
|
||||||
|
SetCreateHealth(health);
|
||||||
|
SetMaxHealth(health);
|
||||||
|
SetHealth(health);
|
||||||
|
|
||||||
|
SetModifierValue(UNIT_MOD_HEALTH, BASE_VALUE, float(health));
|
||||||
|
|
||||||
|
// all power types
|
||||||
|
for (int i = POWER_MANA; i <= POWER_RUNIC_POWER; ++i)
|
||||||
|
{
|
||||||
|
uint32 maxValue = 0;
|
||||||
|
|
||||||
|
switch (i)
|
||||||
|
{
|
||||||
|
case POWER_MANA: maxValue = mana; break;
|
||||||
|
case POWER_RAGE: maxValue = 0; break;
|
||||||
|
case POWER_FOCUS: maxValue = POWER_FOCUS_DEFAULT; break;
|
||||||
|
case POWER_ENERGY: maxValue = POWER_ENERGY_DEFAULT * cinfo->PowerMultiplier; break;
|
||||||
|
case POWER_RUNE: maxValue = 0; break;
|
||||||
|
case POWER_RUNIC_POWER: maxValue = 0; break;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32 value = maxValue;
|
||||||
|
|
||||||
|
// For non regenerating powers set 0
|
||||||
|
if ((i == POWER_ENERGY || i == POWER_MANA) && !IsRegeneratingPower())
|
||||||
|
value = 0;
|
||||||
|
|
||||||
|
// Mana requires an extra field to be set
|
||||||
|
if (i == POWER_MANA)
|
||||||
|
SetCreateMana(value);
|
||||||
|
|
||||||
|
SetMaxPower(Powers(i), maxValue);
|
||||||
|
SetPower(Powers(i), value);
|
||||||
|
SetModifierValue(UnitMods(UNIT_MOD_POWER_START + i), BASE_VALUE, float(value));
|
||||||
|
}
|
||||||
|
|
||||||
|
// damage
|
||||||
|
float damagemod = _GetDamageMod(rank);
|
||||||
|
|
||||||
|
SetBaseWeaponDamage(BASE_ATTACK, MINDAMAGE, cinfo->MinMeleeDmg * damagemod);
|
||||||
|
SetBaseWeaponDamage(BASE_ATTACK, MAXDAMAGE, cinfo->MaxMeleeDmg * damagemod);
|
||||||
|
|
||||||
|
SetBaseWeaponDamage(OFF_ATTACK, MINDAMAGE, cinfo->MinMeleeDmg * damagemod);
|
||||||
|
SetBaseWeaponDamage(OFF_ATTACK, MAXDAMAGE, cinfo->MaxMeleeDmg * damagemod);
|
||||||
|
|
||||||
|
SetFloatValue(UNIT_FIELD_MINRANGEDDAMAGE, cinfo->MinRangedDmg * damagemod);
|
||||||
|
SetFloatValue(UNIT_FIELD_MAXRANGEDDAMAGE, cinfo->MaxRangedDmg * damagemod);
|
||||||
|
|
||||||
|
SetModifierValue(UNIT_MOD_ATTACK_POWER, BASE_VALUE, cinfo->MeleeAttackPower * damagemod);
|
||||||
|
}
|
||||||
|
|
||||||
void Creature::SelectLevel(const CreatureInfo* cinfo, float percentHealth /*= 100.0f*/)
|
void Creature::SelectLevel(const CreatureInfo* cinfo, float percentHealth /*= 100.0f*/)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -78,7 +78,7 @@ enum CreatureFlagsExtra
|
||||||
|
|
||||||
#define MAX_KILL_CREDIT 2
|
#define MAX_KILL_CREDIT 2
|
||||||
#define MAX_CREATURE_MODEL 4
|
#define MAX_CREATURE_MODEL 4
|
||||||
|
#define USE_DEFAULT_DATABASE_LEVEL 0 // just used to show we don't want to force the new creature level and use the level stored in db
|
||||||
|
|
||||||
// from `creature_template` table
|
// from `creature_template` table
|
||||||
struct CreatureInfo
|
struct CreatureInfo
|
||||||
|
|
@ -522,6 +522,7 @@ class Creature : public Unit
|
||||||
bool Create(uint32 guidlow, CreatureCreatePos& cPos, CreatureInfo const* cinfo, Team team = TEAM_NONE, const CreatureData* data = NULL, GameEventCreatureData const* eventData = NULL);
|
bool Create(uint32 guidlow, CreatureCreatePos& cPos, CreatureInfo const* cinfo, Team team = TEAM_NONE, const CreatureData* data = NULL, GameEventCreatureData const* eventData = NULL);
|
||||||
bool LoadCreatureAddon(bool reload);
|
bool LoadCreatureAddon(bool reload);
|
||||||
void SelectLevel(const CreatureInfo* cinfo, float percentHealth = 100.0f);
|
void SelectLevel(const CreatureInfo* cinfo, float percentHealth = 100.0f);
|
||||||
|
void SelectLevel(uint32 forcedLevel = USE_DEFAULT_DATABASE_LEVEL);
|
||||||
void LoadEquipment(uint32 equip_entry, bool force = false);
|
void LoadEquipment(uint32 equip_entry, bool force = false);
|
||||||
|
|
||||||
bool HasStaticDBSpawnData() const; // listed in `creature` table and have fixed in DB guid
|
bool HasStaticDBSpawnData() const; // listed in `creature` table and have fixed in DB guid
|
||||||
|
|
|
||||||
|
|
@ -59,9 +59,12 @@ namespace FactorySelector
|
||||||
// select by NPC flags _first_ - otherwise EventAI might be choosen for pets/totems
|
// select by NPC flags _first_ - otherwise EventAI might be choosen for pets/totems
|
||||||
// excplicit check for isControlled() and owner type to allow guardian, mini-pets and pets controlled by NPCs to be scripted by EventAI
|
// excplicit check for isControlled() and owner type to allow guardian, mini-pets and pets controlled by NPCs to be scripted by EventAI
|
||||||
Unit* owner = NULL;
|
Unit* owner = NULL;
|
||||||
if ((creature->IsPet() && ((Pet*)creature)->isControlled() &&
|
if (creature->IsPet() && ((Pet*)creature)->isControlled())
|
||||||
((owner = creature->GetOwner()) && owner->GetTypeId() == TYPEID_PLAYER)) || creature->IsCharmed())
|
{
|
||||||
ai_factory = ai_registry.GetRegistryItem("PetAI");
|
Unit* controler = creature->GetOwner() ? creature->GetOwner() : creature->GetCharmer();
|
||||||
|
if (controler && controler->GetTypeId() == TYPEID_PLAYER && controler->IsAlive())
|
||||||
|
ai_factory = ai_registry.GetRegistryItem("PetAI");
|
||||||
|
}
|
||||||
else if (creature->IsTotem())
|
else if (creature->IsTotem())
|
||||||
ai_factory = ai_registry.GetRegistryItem("TotemAI");
|
ai_factory = ai_registry.GetRegistryItem("TotemAI");
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -156,9 +156,6 @@ CreatureEventAI::CreatureEventAI(Creature* c) : CreatureAI(c),
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
sLog.outErrorEventAI("EventMap for Creature %u is empty but creature is using CreatureEventAI.", m_creature->GetEntry());
|
sLog.outErrorEventAI("EventMap for Creature %u is empty but creature is using CreatureEventAI.", m_creature->GetEntry());
|
||||||
|
|
||||||
// Handle Spawned Events, also calls Reset()
|
|
||||||
JustRespawned();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#define LOG_PROCESS_EVENT \
|
#define LOG_PROCESS_EVENT \
|
||||||
|
|
|
||||||
|
|
@ -214,6 +214,7 @@ bool DynamicObject::isVisibleForInState(Player const* u, WorldObject const* view
|
||||||
return IsWithinDistInMap(viewPoint, GetMap()->GetVisibilityDistance() + (inVisibleList ? World::GetVisibleObjectGreyDistance() : 0.0f), false);
|
return IsWithinDistInMap(viewPoint, GetMap()->GetVisibilityDistance() + (inVisibleList ? World::GetVisibleObjectGreyDistance() : 0.0f), false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool DynamicObject::IsHostileTo(Unit const* unit) const
|
bool DynamicObject::IsHostileTo(Unit const* unit) const
|
||||||
{
|
{
|
||||||
if (Unit* owner = GetCaster())
|
if (Unit* owner = GetCaster())
|
||||||
|
|
|
||||||
|
|
@ -764,6 +764,76 @@ void GameObject::SaveRespawnTime()
|
||||||
{ GetMap()->GetPersistentState()->SaveGORespawnTime(GetGUIDLow(), m_respawnTime); }
|
{ GetMap()->GetPersistentState()->SaveGORespawnTime(GetGUIDLow(), m_respawnTime); }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool GameObject::isVisibleForInState(Player const* u, WorldObject const* viewPoint, bool inVisibleList) const
|
||||||
|
{
|
||||||
|
// Not in world
|
||||||
|
if (!IsInWorld() || !u->IsInWorld())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// invisible at client always
|
||||||
|
if (!GetGOInfo()->displayId)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// Transport always visible at this step implementation
|
||||||
|
if (IsTransport() && IsInMap(u))
|
||||||
|
return true;
|
||||||
|
|
||||||
|
// quick check visibility false cases for non-GM-mode
|
||||||
|
if (!u->isGameMaster())
|
||||||
|
{
|
||||||
|
// despawned and then not visible for non-GM in GM-mode
|
||||||
|
if (!isSpawned())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// special invisibility cases
|
||||||
|
if (GetGOInfo()->type == GAMEOBJECT_TYPE_TRAP && GetGOInfo()->trap.stealthed)
|
||||||
|
{
|
||||||
|
bool trapNotVisible = false;
|
||||||
|
|
||||||
|
// handle summoned traps, usually by players
|
||||||
|
if (Unit* owner = GetOwner())
|
||||||
|
{
|
||||||
|
if (owner->GetTypeId() == TYPEID_PLAYER)
|
||||||
|
{
|
||||||
|
Player* ownerPlayer = (Player*)owner;
|
||||||
|
if ((GetMap()->IsBattleGroundOrArena() && ownerPlayer->GetBGTeam() != u->GetBGTeam()) ||
|
||||||
|
(ownerPlayer->IsInDuelWith(u)) ||
|
||||||
|
(ownerPlayer->GetTeam() != u->GetTeam()))
|
||||||
|
trapNotVisible = true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (u->IsFriendlyTo(owner))
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// handle environment traps (spawned by DB)
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (this->IsFriendlyTo(u))
|
||||||
|
return true;
|
||||||
|
else
|
||||||
|
trapNotVisible = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// only rogue have skill for traps detection
|
||||||
|
if (Aura* aura = ((Player*)u)->GetAura(2836, EFFECT_INDEX_0))
|
||||||
|
{
|
||||||
|
if (roll_chance_i(aura->GetModifier()->m_amount) && u->isInFront(this, 15.0f))
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (trapNotVisible)
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// check distance
|
||||||
|
return IsWithinDistInMap(viewPoint, GetMap()->GetVisibilityDistance() +
|
||||||
|
(inVisibleList ? World::GetVisibleObjectGreyDistance() : 0.0f), false);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
bool GameObject::isVisibleForInState(Player const* u, WorldObject const* viewPoint, bool inVisibleList) const
|
bool GameObject::isVisibleForInState(Player const* u, WorldObject const* viewPoint, bool inVisibleList) const
|
||||||
{
|
{
|
||||||
// Not in world
|
// Not in world
|
||||||
|
|
@ -784,6 +854,7 @@ bool GameObject::isVisibleForInState(Player const* u, WorldObject const* viewPoi
|
||||||
// despawned and then not visible for non-GM in GM-mode
|
// despawned and then not visible for non-GM in GM-mode
|
||||||
if (!isSpawned())
|
if (!isSpawned())
|
||||||
{ return false; }
|
{ return false; }
|
||||||
|
*/
|
||||||
|
|
||||||
// special invisibility cases
|
// special invisibility cases
|
||||||
/* TODO: implement trap stealth, take look at spell 2836
|
/* TODO: implement trap stealth, take look at spell 2836
|
||||||
|
|
@ -792,12 +863,14 @@ bool GameObject::isVisibleForInState(Player const* u, WorldObject const* viewPoi
|
||||||
if(check stuff here)
|
if(check stuff here)
|
||||||
return false;
|
return false;
|
||||||
}*/
|
}*/
|
||||||
|
/*
|
||||||
}
|
}
|
||||||
|
|
||||||
// check distance
|
// check distance
|
||||||
|
|
||||||
return IsWithinDistInMap(viewPoint, GetMap()->GetVisibilityDistance() +
|
return IsWithinDistInMap(viewPoint, GetMap()->GetVisibilityDistance() +
|
||||||
(inVisibleList ? World::GetVisibleObjectGreyDistance() : 0.0f), false);
|
(inVisibleList ? World::GetVisibleObjectGreyDistance() : 0.0f), false);
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
void GameObject::Respawn()
|
void GameObject::Respawn()
|
||||||
{
|
{
|
||||||
|
|
@ -1669,7 +1742,7 @@ void GameObject::Use(Unit* user)
|
||||||
SpellCastTargets targets;
|
SpellCastTargets targets;
|
||||||
targets.setUnitTarget(user);
|
targets.setUnitTarget(user);
|
||||||
|
|
||||||
spell->prepare(&targets);
|
spell->SpellStart(&targets);
|
||||||
}
|
}
|
||||||
|
|
||||||
// overwrite WorldObject function for proper name localization
|
// overwrite WorldObject function for proper name localization
|
||||||
|
|
|
||||||
|
|
@ -259,16 +259,19 @@ bool LootStoreItem::Roll(bool rate) const
|
||||||
if (mincountOrRef < 0) // reference case
|
if (mincountOrRef < 0) // reference case
|
||||||
return roll_chance_f(chance * (rate ? sWorld.getConfig(CONFIG_FLOAT_RATE_DROP_ITEM_REFERENCED) : 1.0f));
|
return roll_chance_f(chance * (rate ? sWorld.getConfig(CONFIG_FLOAT_RATE_DROP_ITEM_REFERENCED) : 1.0f));
|
||||||
|
|
||||||
if (type == LOOT_ITEM_TYPE_ITEM)
|
if (type == LOOTITEM_TYPE_CURRENCY)
|
||||||
|
return roll_chance_f(chance * (rate ? sWorld.getConfig(CONFIG_FLOAT_RATE_DROP_CURRENCY) : 1.0f));
|
||||||
|
else
|
||||||
{
|
{
|
||||||
|
if (needs_quest)
|
||||||
|
return roll_chance_f(chance * (rate ? sWorld.getConfig(CONFIG_FLOAT_RATE_DROP_ITEM_QUEST) : 1.0f));
|
||||||
|
|
||||||
ItemPrototype const* pProto = ObjectMgr::GetItemPrototype(itemid);
|
ItemPrototype const* pProto = ObjectMgr::GetItemPrototype(itemid);
|
||||||
|
|
||||||
float qualityModifier = pProto && rate ? sWorld.getConfig(qualityToRate[pProto->Quality]) : 1.0f;
|
float qualityModifier = pProto && rate ? sWorld.getConfig(qualityToRate[pProto->Quality]) : 1.0f;
|
||||||
|
|
||||||
return roll_chance_f(chance * qualityModifier);
|
return roll_chance_f(chance * qualityModifier);
|
||||||
}
|
}
|
||||||
else if (type == LOOT_ITEM_TYPE_CURRENCY)
|
|
||||||
return roll_chance_f(chance * (rate ? sWorld.getConfig(CONFIG_FLOAT_RATE_DROP_CURRENCY) : 1.0f));
|
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -53,8 +53,10 @@ enum PermissionTypes
|
||||||
|
|
||||||
enum LootItemType
|
enum LootItemType
|
||||||
{
|
{
|
||||||
LOOT_ITEM_TYPE_ITEM = 0,
|
LOOT_ITEM_TYPE_ITEM = 0,
|
||||||
LOOT_ITEM_TYPE_CURRENCY = 1,
|
LOOT_ITEM_TYPE_CURRENCY = 1,
|
||||||
|
LOOTITEM_TYPE_CONDITIONNAL = 3,
|
||||||
|
LOOTITEM_TYPE_CURRENCY = 4,
|
||||||
};
|
};
|
||||||
|
|
||||||
enum LootType
|
enum LootType
|
||||||
|
|
|
||||||
|
|
@ -133,63 +133,37 @@ void Object::SendForcedObjectUpdate()
|
||||||
void Object::BuildCreateUpdateBlockForPlayer(UpdateData* data, Player* target) const
|
void Object::BuildCreateUpdateBlockForPlayer(UpdateData* data, Player* target) const
|
||||||
{
|
{
|
||||||
if (!target)
|
if (!target)
|
||||||
{ return; }
|
return;
|
||||||
|
|
||||||
uint8 updatetype = UPDATETYPE_CREATE_OBJECT;
|
uint8 updatetype = UPDATETYPE_CREATE_OBJECT;
|
||||||
uint16 updateFlags = m_updateFlag;
|
uint16 updateFlags = m_updateFlag;
|
||||||
|
|
||||||
/** lower flag1 **/
|
/** lower flag1 **/
|
||||||
if (target == this) // building packet for yourself
|
if (target == this) // building packet for yourself
|
||||||
{ updateFlags |= UPDATEFLAG_SELF; }
|
updateFlags |= UPDATEFLAG_SELF;
|
||||||
|
|
||||||
switch (GetObjectGuid().GetHigh())
|
if (m_itsNewObject)
|
||||||
{
|
{
|
||||||
case HIGHGUID_PLAYER:
|
switch (GetObjectGuid().GetHigh())
|
||||||
case HIGHGUID_PET:
|
|
||||||
case HIGHGUID_CORPSE:
|
|
||||||
case HIGHGUID_DYNAMICOBJECT:
|
|
||||||
updatetype = UPDATETYPE_CREATE_OBJECT2;
|
|
||||||
break;
|
|
||||||
case HIGHGUID_UNIT:
|
|
||||||
{
|
{
|
||||||
Creature* creature = (Creature*)this;
|
case HighGuid::HIGHGUID_DYNAMICOBJECT:
|
||||||
if (creature->IsTemporarySummon() && ((TemporarySummon*)this)->GetSummonerGuid().IsPlayer())
|
case HighGuid::HIGHGUID_CORPSE:
|
||||||
|
case HighGuid::HIGHGUID_PLAYER:
|
||||||
|
case HighGuid::HIGHGUID_UNIT:
|
||||||
|
case HighGuid::HIGHGUID_VEHICLE:
|
||||||
|
case HighGuid::HIGHGUID_GAMEOBJECT:
|
||||||
updatetype = UPDATETYPE_CREATE_OBJECT2;
|
updatetype = UPDATETYPE_CREATE_OBJECT2;
|
||||||
break;
|
break;
|
||||||
}
|
|
||||||
case HIGHGUID_GAMEOBJECT:
|
default:
|
||||||
{
|
break;
|
||||||
if (((GameObject*)this)->GetOwnerGuid().IsPlayer())
|
|
||||||
updatetype = UPDATETYPE_CREATE_OBJECT2;
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (updateFlags & UPDATEFLAG_HAS_POSITION)
|
|
||||||
{
|
|
||||||
// UPDATETYPE_CREATE_OBJECT2 for some gameobject types...
|
|
||||||
if (isType(TYPEMASK_GAMEOBJECT))
|
|
||||||
{
|
|
||||||
switch (((GameObject*)this)->GetGoType())
|
|
||||||
{
|
|
||||||
case GAMEOBJECT_TYPE_TRAP:
|
|
||||||
case GAMEOBJECT_TYPE_DUEL_ARBITER:
|
|
||||||
case GAMEOBJECT_CreatureTypeFlagsTAND:
|
|
||||||
case GAMEOBJECT_TYPE_FLAGDROP:
|
|
||||||
updatetype = UPDATETYPE_CREATE_OBJECT2;
|
|
||||||
break;
|
|
||||||
case GAMEOBJECT_TYPE_TRANSPORT:
|
|
||||||
updateFlags |= UPDATEFLAG_TRANSPORT;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (isType(TYPEMASK_UNIT))
|
if (isType(TYPEMASK_UNIT))
|
||||||
{
|
{
|
||||||
if (((Unit*)this)->getVictim())
|
if (((Unit*)this)->getVictim())
|
||||||
updateFlags |= UPDATEFLAG_HAS_ATTACKING_TARGET;
|
updateFlags |= UPDATEFLAG_HAS_ATTACKING_TARGET;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// DEBUG_LOG("BuildCreateUpdate: update-type: %u, object-type: %u got updateFlags: %X", updatetype, m_objectTypeId, updateFlags);
|
// DEBUG_LOG("BuildCreateUpdate: update-type: %u, object-type: %u got updateFlags: %X", updatetype, m_objectTypeId, updateFlags);
|
||||||
|
|
|
||||||
|
|
@ -400,6 +400,7 @@ class Object
|
||||||
|
|
||||||
virtual bool HasQuest(uint32 /* quest_id */) const { return false; }
|
virtual bool HasQuest(uint32 /* quest_id */) const { return false; }
|
||||||
virtual bool HasInvolvedQuest(uint32 /* quest_id */) const { return false; }
|
virtual bool HasInvolvedQuest(uint32 /* quest_id */) const { return false; }
|
||||||
|
void SetItsNewObject(bool enable) { m_itsNewObject = enable; }
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
Object();
|
Object();
|
||||||
|
|
@ -435,6 +436,7 @@ class Object
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool m_inWorld;
|
bool m_inWorld;
|
||||||
|
bool m_itsNewObject;
|
||||||
|
|
||||||
PackedGuid m_PackGUID;
|
PackedGuid m_PackGUID;
|
||||||
|
|
||||||
|
|
@ -567,7 +569,7 @@ class WorldObject : public Object
|
||||||
float GetDistanceZ(const WorldObject* obj) const;
|
float GetDistanceZ(const WorldObject* obj) const;
|
||||||
bool IsInMap(const WorldObject* obj) const
|
bool IsInMap(const WorldObject* obj) const
|
||||||
{
|
{
|
||||||
return IsInWorld() && obj->IsInWorld() && (GetMap() == obj->GetMap()) && InSamePhase(obj);
|
return obj && IsInWorld() && obj->IsInWorld() && (GetMap() == obj->GetMap()) && InSamePhase(obj);
|
||||||
}
|
}
|
||||||
bool IsWithinDist3d(float x, float y, float z, float dist2compare) const;
|
bool IsWithinDist3d(float x, float y, float z, float dist2compare) const;
|
||||||
bool IsWithinDist2d(float x, float y, float dist2compare) const;
|
bool IsWithinDist2d(float x, float y, float dist2compare) const;
|
||||||
|
|
|
||||||
|
|
@ -8227,9 +8227,9 @@ bool PlayerCondition::Meets(Player const* player, Map const* map, WorldObject co
|
||||||
case CONDITION_TEAM:
|
case CONDITION_TEAM:
|
||||||
{
|
{
|
||||||
if (conditionSourceType == CONDITION_FROM_REFERING_LOOT && sWorld.getConfig(CONFIG_BOOL_ALLOW_TWO_SIDE_INTERACTION_AUCTION))
|
if (conditionSourceType == CONDITION_FROM_REFERING_LOOT && sWorld.getConfig(CONFIG_BOOL_ALLOW_TWO_SIDE_INTERACTION_AUCTION))
|
||||||
{ return true; }
|
return true;
|
||||||
else
|
else
|
||||||
{ return uint32(player->GetTeam()) == m_value1; }
|
return uint32(player->GetTeam()) == m_value1;
|
||||||
}
|
}
|
||||||
case CONDITION_SKILL:
|
case CONDITION_SKILL:
|
||||||
return player->HasSkill(m_value1) && player->GetBaseSkillValue(m_value1) >= m_value2;
|
return player->HasSkill(m_value1) && player->GetBaseSkillValue(m_value1) >= m_value2;
|
||||||
|
|
|
||||||
|
|
@ -197,6 +197,9 @@ bool Pet::LoadPetFromDB(Player* owner, uint32 petentry, uint32 petnumber, bool c
|
||||||
SetUInt32Value(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_NONE);
|
SetUInt32Value(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_NONE);
|
||||||
SetName(fields[8].GetString());
|
SetName(fields[8].GetString());
|
||||||
|
|
||||||
|
SetByteValue(UNIT_FIELD_BYTES_2, 1, UNIT_BYTE2_FLAG_SUPPORTABLE | UNIT_BYTE2_FLAG_AURAS);
|
||||||
|
SetUInt32Value(UNIT_FIELD_FLAGS, UNIT_FLAG_PVP_ATTACKABLE);
|
||||||
|
|
||||||
switch (getPetType())
|
switch (getPetType())
|
||||||
{
|
{
|
||||||
case SUMMON_PET:
|
case SUMMON_PET:
|
||||||
|
|
|
||||||
|
|
@ -129,7 +129,7 @@ typedef std::vector<uint32> AutoSpellList;
|
||||||
#define ACTIVE_SPELLS_MAX 4
|
#define ACTIVE_SPELLS_MAX 4
|
||||||
|
|
||||||
#define PET_FOLLOW_DIST 1.0f
|
#define PET_FOLLOW_DIST 1.0f
|
||||||
#define PET_FOLLOW_ANGLE (M_PI_F/2.0f)
|
#define PET_FOLLOW_ANGLE (M_PI_F / 4.00f) * 3.50f
|
||||||
|
|
||||||
class Player;
|
class Player;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -48,28 +48,24 @@ PetAI::PetAI(Creature* c) : CreatureAI(c), i_tracker(TIME_INTERVAL_LOOK), inComb
|
||||||
UpdateAllies();
|
UpdateAllies();
|
||||||
}
|
}
|
||||||
|
|
||||||
void PetAI::MoveInLineOfSight(Unit* u)
|
void PetAI::MoveInLineOfSight(Unit* pWho)
|
||||||
{
|
{
|
||||||
if (m_creature->getVictim())
|
if (m_creature->getVictim())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (m_creature->IsPet() && ((Pet*)m_creature)->GetModeFlags() & PET_MODE_DISABLE_ACTIONS)
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (!m_creature->GetCharmInfo() || !m_creature->GetCharmInfo()->HasReactState(REACT_AGGRESSIVE))
|
if (!m_creature->GetCharmInfo() || !m_creature->GetCharmInfo()->HasReactState(REACT_AGGRESSIVE))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (u->IsTargetableForAttack() && m_creature->IsHostileTo(u) &&
|
if (m_creature->CanInitiateAttack() && pWho->IsTargetableForAttack() &&
|
||||||
u->isInAccessablePlaceFor(m_creature))
|
m_creature->IsHostileTo(pWho) && pWho->isInAccessablePlaceFor(m_creature))
|
||||||
{
|
{
|
||||||
float attackRadius = m_creature->GetAttackDistance(u);
|
if (!m_creature->CanFly() && m_creature->GetDistanceZ(pWho) > CREATURE_Z_ATTACK_RANGE)
|
||||||
if (m_creature->IsWithinDistInMap(u, attackRadius) && m_creature->GetDistanceZ(u) <= CREATURE_Z_ATTACK_RANGE)
|
return;
|
||||||
|
|
||||||
|
if (m_creature->IsWithinDistInMap(pWho, m_creature->GetAttackDistance(pWho)) && m_creature->IsWithinLOSInMap(pWho))
|
||||||
{
|
{
|
||||||
if (m_creature->IsWithinLOSInMap(u))
|
pWho->RemoveSpellsCausingAura(SPELL_AURA_MOD_STEALTH);
|
||||||
{
|
AttackStart(pWho);
|
||||||
AttackStart(u);
|
|
||||||
u->RemoveSpellsCausingAura(SPELL_AURA_MOD_STEALTH);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -298,7 +294,7 @@ void PetAI::UpdateAI(const uint32 diff)
|
||||||
|
|
||||||
m_creature->AddCreatureSpellCooldown(spell->m_spellInfo->Id);
|
m_creature->AddCreatureSpellCooldown(spell->m_spellInfo->Id);
|
||||||
|
|
||||||
spell->prepare(&targets);
|
spell->SpellStart(&targets);
|
||||||
}
|
}
|
||||||
|
|
||||||
// deleted cached Spell objects
|
// deleted cached Spell objects
|
||||||
|
|
|
||||||
|
|
@ -3629,17 +3629,18 @@ void Player::removeSpell(uint32 spell_id, bool disabled, bool learn_low_rank, bo
|
||||||
PlayerSpellMap::iterator prev_itr = m_spells.find(prev_id);
|
PlayerSpellMap::iterator prev_itr = m_spells.find(prev_id);
|
||||||
if (prev_itr != m_spells.end())
|
if (prev_itr != m_spells.end())
|
||||||
{
|
{
|
||||||
if (prev_itr->second.dependent != cur_dependent)
|
PlayerSpell& spell = prev_itr->second;
|
||||||
|
if (spell.dependent != cur_dependent)
|
||||||
{
|
{
|
||||||
prev_itr->second.dependent = cur_dependent;
|
spell.dependent = cur_dependent;
|
||||||
if (prev_itr->second.state != PLAYERSPELL_NEW)
|
if (spell.state != PLAYERSPELL_NEW)
|
||||||
prev_itr->second.state = PLAYERSPELL_CHANGED;
|
spell.state = PLAYERSPELL_CHANGED;
|
||||||
}
|
}
|
||||||
|
|
||||||
// now re-learn if need re-activate
|
// now re-learn if need re-activate
|
||||||
if (cur_active && !prev_itr->second.active && learn_low_rank)
|
if (cur_active && !spell.active && learn_low_rank)
|
||||||
{
|
{
|
||||||
if (addSpell(prev_id, true, false, prev_itr->second.dependent, prev_itr->second.disabled))
|
if (addSpell(prev_id, true, false, spell.dependent, spell.disabled))
|
||||||
{
|
{
|
||||||
// downgrade spell ranks in spellbook and action bar
|
// downgrade spell ranks in spellbook and action bar
|
||||||
WorldPacket data(SMSG_SUPERCEDED_SPELL, 4 + 4);
|
WorldPacket data(SMSG_SUPERCEDED_SPELL, 4 + 4);
|
||||||
|
|
@ -6306,7 +6307,12 @@ void Player::CheckAreaExploreAndOutdoor()
|
||||||
SpellEntry const* spellInfo = sSpellStore.LookupEntry(itr->first);
|
SpellEntry const* spellInfo = sSpellStore.LookupEntry(itr->first);
|
||||||
if (!spellInfo || !IsNeedCastSpellAtOutdoor(spellInfo) || HasAura(itr->first))
|
if (!spellInfo || !IsNeedCastSpellAtOutdoor(spellInfo) || HasAura(itr->first))
|
||||||
continue;
|
continue;
|
||||||
CastSpell(this, itr->first, true, NULL);
|
|
||||||
|
SpellShapeshiftEntry const* shapeShift = spellInfo->GetSpellShapeshift();
|
||||||
|
|
||||||
|
if (!shapeShift || (shapeShift->Stances || shapeShift->StancesNot) && !IsNeedCastSpellAtFormApply(spellInfo, GetShapeshiftForm()))
|
||||||
|
continue;
|
||||||
|
CastSpell(this, itr->first, true, nullptr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (sWorld.getConfig(CONFIG_BOOL_VMAP_INDOOR_CHECK) && !isGameMaster())
|
else if (sWorld.getConfig(CONFIG_BOOL_VMAP_INDOOR_CHECK) && !isGameMaster())
|
||||||
|
|
@ -6980,13 +6986,13 @@ void Player::UpdateZone(uint32 newZone, uint32 newArea)
|
||||||
|
|
||||||
if (zone->flags & AREA_FLAG_SANCTUARY) // in sanctuary
|
if (zone->flags & AREA_FLAG_SANCTUARY) // in sanctuary
|
||||||
{
|
{
|
||||||
SetByteFlag(UNIT_FIELD_BYTES_2, 1, UNIT_BYTE2_FLAG_SUPPORTABLE);
|
SetFlag(PLAYER_FLAGS, PLAYER_FLAGS_SANCTUARY);
|
||||||
if (sWorld.IsFFAPvPRealm())
|
if (sWorld.IsFFAPvPRealm())
|
||||||
SetFFAPvP(false);
|
SetFFAPvP(false);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
RemoveByteFlag(UNIT_FIELD_BYTES_2, 1, UNIT_BYTE2_FLAG_SUPPORTABLE);
|
RemoveFlag(PLAYER_FLAGS, PLAYER_FLAGS_SANCTUARY);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (zone->flags & AREA_FLAG_CAPITAL) // in capital city
|
if (zone->flags & AREA_FLAG_CAPITAL) // in capital city
|
||||||
|
|
@ -7812,7 +7818,7 @@ void Player::CastItemUseSpell(Item* item, SpellCastTargets const& targets, uint8
|
||||||
spell->m_CastItem = item;
|
spell->m_CastItem = item;
|
||||||
spell->m_cast_count = cast_count; // set count of casts
|
spell->m_cast_count = cast_count; // set count of casts
|
||||||
spell->m_currentBasePoints[EFFECT_INDEX_0] = learning_spell_id;
|
spell->m_currentBasePoints[EFFECT_INDEX_0] = learning_spell_id;
|
||||||
spell->prepare(&targets);
|
spell->SpellStart(&targets);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -7843,7 +7849,7 @@ void Player::CastItemUseSpell(Item* item, SpellCastTargets const& targets, uint8
|
||||||
spell->m_CastItem = item;
|
spell->m_CastItem = item;
|
||||||
spell->m_cast_count = cast_count; // set count of casts
|
spell->m_cast_count = cast_count; // set count of casts
|
||||||
spell->m_glyphIndex = glyphIndex; // glyph index
|
spell->m_glyphIndex = glyphIndex; // glyph index
|
||||||
spell->prepare(&targets);
|
spell->SpellStart(&targets);
|
||||||
|
|
||||||
++count;
|
++count;
|
||||||
}
|
}
|
||||||
|
|
@ -7875,7 +7881,7 @@ void Player::CastItemUseSpell(Item* item, SpellCastTargets const& targets, uint8
|
||||||
spell->m_CastItem = item;
|
spell->m_CastItem = item;
|
||||||
spell->m_cast_count = cast_count; // set count of casts
|
spell->m_cast_count = cast_count; // set count of casts
|
||||||
spell->m_glyphIndex = glyphIndex; // glyph index
|
spell->m_glyphIndex = glyphIndex; // glyph index
|
||||||
spell->prepare(&targets);
|
spell->SpellStart(&targets);
|
||||||
|
|
||||||
++count;
|
++count;
|
||||||
}
|
}
|
||||||
|
|
@ -18354,6 +18360,10 @@ void Player::Whisper(const std::string& text, uint32 language, ObjectGuid receiv
|
||||||
ChatHandler::BuildChatPacket(data, CHAT_MSG_WHISPER, text.c_str(), Language(language), GetChatTag(), GetObjectGuid(), GetName());
|
ChatHandler::BuildChatPacket(data, CHAT_MSG_WHISPER, text.c_str(), Language(language), GetChatTag(), GetObjectGuid(), GetName());
|
||||||
rPlayer->GetSession()->SendPacket(&data);
|
rPlayer->GetSession()->SendPacket(&data);
|
||||||
|
|
||||||
|
// do not send confirmations, afk, dnd or system notifications for addon messages
|
||||||
|
if (language == LANG_ADDON)
|
||||||
|
return;
|
||||||
|
|
||||||
data.clear();
|
data.clear();
|
||||||
ChatHandler::BuildChatPacket(data, CHAT_MSG_WHISPER_INFORM, text.c_str(), Language(language), CHAT_TAG_NONE, rPlayer->GetObjectGuid());
|
ChatHandler::BuildChatPacket(data, CHAT_MSG_WHISPER_INFORM, text.c_str(), Language(language), CHAT_TAG_NONE, rPlayer->GetObjectGuid());
|
||||||
GetSession()->SendPacket(&data);
|
GetSession()->SendPacket(&data);
|
||||||
|
|
@ -18365,10 +18375,13 @@ void Player::Whisper(const std::string& text, uint32 language, ObjectGuid receiv
|
||||||
}
|
}
|
||||||
|
|
||||||
// announce afk or dnd message
|
// announce afk or dnd message
|
||||||
if (rPlayer->isAFK())
|
if (rPlayer->isAFK() || rPlayer->isDND())
|
||||||
ChatHandler(this).PSendSysMessage(LANG_PLAYER_AFK, rPlayer->GetName(), rPlayer->autoReplyMsg.c_str());
|
{
|
||||||
else if (rPlayer->isDND())
|
const ChatMsg msgtype = rPlayer->isAFK() ? CHAT_MSG_AFK : CHAT_MSG_DND;
|
||||||
ChatHandler(this).PSendSysMessage(LANG_PLAYER_DND, rPlayer->GetName(), rPlayer->autoReplyMsg.c_str());
|
data.clear();
|
||||||
|
ChatHandler::BuildChatPacket(data, msgtype, rPlayer->autoReplyMsg.c_str(), LANG_UNIVERSAL, CHAT_TAG_NONE, rPlayer->GetObjectGuid());
|
||||||
|
GetSession()->SendPacket(&data);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Player::PetSpellInitialize()
|
void Player::PetSpellInitialize()
|
||||||
|
|
@ -20780,8 +20793,8 @@ bool Player::IsSpellFitByClassAndRace(uint32 spell_id, uint32* pReqlevel /*= NUL
|
||||||
if (abilityEntry->classmask && (abilityEntry->classmask & classmask) == 0)
|
if (abilityEntry->classmask && (abilityEntry->classmask & classmask) == 0)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
SkillRaceClassInfoMapBounds bounds = sSpellMgr.GetSkillRaceClassInfoMapBounds(abilityEntry->skillId);
|
SkillRaceClassInfoMapBounds raceBounds = sSpellMgr.GetSkillRaceClassInfoMapBounds(abilityEntry->skillId);
|
||||||
for (SkillRaceClassInfoMap::const_iterator itr = bounds.first; itr != bounds.second; ++itr)
|
for (SkillRaceClassInfoMap::const_iterator itr = raceBounds.first; itr != raceBounds.second; ++itr)
|
||||||
{
|
{
|
||||||
SkillRaceClassInfoEntry const* skillRCEntry = itr->second;
|
SkillRaceClassInfoEntry const* skillRCEntry = itr->second;
|
||||||
if ((skillRCEntry->raceMask & racemask) && (skillRCEntry->classMask & classmask))
|
if ((skillRCEntry->raceMask & racemask) && (skillRCEntry->classMask & classmask))
|
||||||
|
|
|
||||||
|
|
@ -452,7 +452,7 @@ enum PlayerFlags
|
||||||
PLAYER_FLAGS_GM = 0x00000008,
|
PLAYER_FLAGS_GM = 0x00000008,
|
||||||
PLAYER_FLAGS_GHOST = 0x00000010,
|
PLAYER_FLAGS_GHOST = 0x00000010,
|
||||||
PLAYER_FLAGS_RESTING = 0x00000020,
|
PLAYER_FLAGS_RESTING = 0x00000020,
|
||||||
PLAYER_FLAGS_UNK7 = 0x00000040, // admin?
|
PLAYER_FLAGS_SANCTUARY = 0x00000040,
|
||||||
PLAYER_FLAGS_UNK8 = 0x00000080, // pre-3.0.3 PLAYER_FLAGS_FFA_PVP flag for FFA PVP state
|
PLAYER_FLAGS_UNK8 = 0x00000080, // pre-3.0.3 PLAYER_FLAGS_FFA_PVP flag for FFA PVP state
|
||||||
PLAYER_FLAGS_CONTESTED_PVP = 0x00000100, // Player has been involved in a PvP combat and will be attacked by contested guards
|
PLAYER_FLAGS_CONTESTED_PVP = 0x00000100, // Player has been involved in a PvP combat and will be attacked by contested guards
|
||||||
PLAYER_FLAGS_IN_PVP = 0x00000200,
|
PLAYER_FLAGS_IN_PVP = 0x00000200,
|
||||||
|
|
@ -2574,6 +2574,10 @@ class Player : public Unit
|
||||||
void SetTitle(CharTitlesEntry const* title, bool lost = false);
|
void SetTitle(CharTitlesEntry const* title, bool lost = false);
|
||||||
|
|
||||||
bool canSeeSpellClickOn(Creature const* creature) const;
|
bool canSeeSpellClickOn(Creature const* creature) const;
|
||||||
|
|
||||||
|
// function used for raise ally spell
|
||||||
|
bool IsGhouled() const { return m_isGhouled; }
|
||||||
|
void SetGhouled(bool enable) { m_isGhouled = enable; }
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
uint32 m_contestedPvPTimer;
|
uint32 m_contestedPvPTimer;
|
||||||
|
|
@ -2899,6 +2903,8 @@ class Player : public Unit
|
||||||
uint32 m_timeSyncServer;
|
uint32 m_timeSyncServer;
|
||||||
|
|
||||||
uint32 m_cachedGS;
|
uint32 m_cachedGS;
|
||||||
|
|
||||||
|
bool m_isGhouled;
|
||||||
};
|
};
|
||||||
|
|
||||||
void AddItemsSetItem(Player* player, Item* item);
|
void AddItemsSetItem(Player* player, Item* item);
|
||||||
|
|
|
||||||
|
|
@ -809,7 +809,9 @@ bool IsPositiveEffect(SpellEntry const* spellproto, SpellEffectIndex effIndex)
|
||||||
switch (spellproto->Id)
|
switch (spellproto->Id)
|
||||||
{
|
{
|
||||||
case 13139: // net-o-matic special effect
|
case 13139: // net-o-matic special effect
|
||||||
|
case 23182: // Mark of Frost
|
||||||
case 23445: // evil twin
|
case 23445: // evil twin
|
||||||
|
case 25040: // Mark of Nature
|
||||||
case 35679: // Protectorate Demolitionist
|
case 35679: // Protectorate Demolitionist
|
||||||
case 37695: // Stanky
|
case 37695: // Stanky
|
||||||
case 38637: // Nether Exhaustion (red)
|
case 38637: // Nether Exhaustion (red)
|
||||||
|
|
@ -931,6 +933,7 @@ bool IsPositiveEffect(SpellEntry const* spellproto, SpellEffectIndex effIndex)
|
||||||
{
|
{
|
||||||
case 36897: // Transporter Malfunction (race mutation to horde)
|
case 36897: // Transporter Malfunction (race mutation to horde)
|
||||||
case 36899: // Transporter Malfunction (race mutation to alliance)
|
case 36899: // Transporter Malfunction (race mutation to alliance)
|
||||||
|
case 37097: // Crate Disguise
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
@ -940,6 +943,7 @@ bool IsPositiveEffect(SpellEntry const* spellproto, SpellEffectIndex effIndex)
|
||||||
{
|
{
|
||||||
case 802: // Mutate Bug, wrongly negative by target modes
|
case 802: // Mutate Bug, wrongly negative by target modes
|
||||||
case 38449: // Blessing of the Tides
|
case 38449: // Blessing of the Tides
|
||||||
|
case 50312: // Unholy Frenzy
|
||||||
return true;
|
return true;
|
||||||
case 36900: // Soul Split: Evil!
|
case 36900: // Soul Split: Evil!
|
||||||
case 36901: // Soul Split: Good
|
case 36901: // Soul Split: Good
|
||||||
|
|
@ -1058,16 +1062,6 @@ bool IsSingleTargetSpell(SpellEntry const* spellInfo)
|
||||||
{
|
{
|
||||||
// all other single target spells have if it has AttributesEx5
|
// all other single target spells have if it has AttributesEx5
|
||||||
if (spellInfo->HasAttribute(SPELL_ATTR_EX5_SINGLE_TARGET_SPELL))
|
if (spellInfo->HasAttribute(SPELL_ATTR_EX5_SINGLE_TARGET_SPELL))
|
||||||
return true;
|
|
||||||
|
|
||||||
// TODO - need found Judgements rule
|
|
||||||
switch (GetSpellSpecific(spellInfo->Id))
|
|
||||||
{
|
|
||||||
case SPELL_JUDGEMENT:
|
|
||||||
return true;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
// single target triggered spell.
|
// single target triggered spell.
|
||||||
// Not real client side single target spell, but it' not triggered until prev. aura expired.
|
// Not real client side single target spell, but it' not triggered until prev. aura expired.
|
||||||
|
|
@ -1086,12 +1080,10 @@ bool IsSingleTargetSpells(SpellEntry const* spellInfo1, SpellEntry const* spellI
|
||||||
spellInfo1->SpellIconID == spellInfo2->SpellIconID )
|
spellInfo1->SpellIconID == spellInfo2->SpellIconID )
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
// TODO - need found Judgements rule
|
|
||||||
SpellSpecific spec1 = GetSpellSpecific(spellInfo1->Id);
|
SpellSpecific spec1 = GetSpellSpecific(spellInfo1->Id);
|
||||||
// spell with single target specific types
|
// spell with single target specific types
|
||||||
switch (spec1)
|
switch (spec1)
|
||||||
{
|
{
|
||||||
case SPELL_JUDGEMENT:
|
|
||||||
case SPELL_MAGE_POLYMORPH:
|
case SPELL_MAGE_POLYMORPH:
|
||||||
if (GetSpellSpecific(spellInfo2->Id) == spec1)
|
if (GetSpellSpecific(spellInfo2->Id) == spec1)
|
||||||
return true;
|
return true;
|
||||||
|
|
|
||||||
|
|
@ -669,9 +669,13 @@ void Unit::Update(uint32 update_diff, uint32 p_time)
|
||||||
// update abilities available only for fraction of time
|
// update abilities available only for fraction of time
|
||||||
UpdateReactives(update_diff);
|
UpdateReactives(update_diff);
|
||||||
|
|
||||||
ModifyAuraState(AURA_STATE_HEALTHLESS_20_PERCENT, GetHealth() < GetMaxHealth() * 0.20f);
|
if (IsAlive())
|
||||||
ModifyAuraState(AURA_STATE_HEALTHLESS_35_PERCENT, GetHealth() < GetMaxHealth() * 0.35f);
|
{
|
||||||
ModifyAuraState(AURA_STATE_HEALTH_ABOVE_75_PERCENT, GetHealth() > GetMaxHealth() * 0.75f);
|
ModifyAuraState(AURA_STATE_HEALTHLESS_20_PERCENT, GetHealth() < GetMaxHealth() * 0.20f);
|
||||||
|
ModifyAuraState(AURA_STATE_HEALTHLESS_35_PERCENT, GetHealth() < GetMaxHealth() * 0.35f);
|
||||||
|
ModifyAuraState(AURA_STATE_HEALTH_ABOVE_75_PERCENT, GetHealth() > GetMaxHealth() * 0.75f);
|
||||||
|
}
|
||||||
|
|
||||||
UpdateSplineMovement(p_time);
|
UpdateSplineMovement(p_time);
|
||||||
i_motionMaster.UpdateMotion(p_time);
|
i_motionMaster.UpdateMotion(p_time);
|
||||||
}
|
}
|
||||||
|
|
@ -734,7 +738,7 @@ bool Unit::UpdateMeleeAttackingState()
|
||||||
player->SwingErrorMsg(swingError);
|
player->SwingErrorMsg(swingError);
|
||||||
}
|
}
|
||||||
|
|
||||||
return swingError == 0;
|
return swingError;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Unit::haveOffhandWeapon() const
|
bool Unit::haveOffhandWeapon() const
|
||||||
|
|
@ -1089,6 +1093,8 @@ uint32 Unit::DealDamage(Unit* pVictim, uint32 damage, CleanDamage const* cleanDa
|
||||||
|
|
||||||
player_tap->SendDirectMessage(&data);
|
player_tap->SendDirectMessage(&data);
|
||||||
}
|
}
|
||||||
|
else if (GetTypeId() == TYPEID_UNIT && this != pVictim)
|
||||||
|
ProcDamageAndSpell(pVictim, PROC_FLAG_KILL, PROC_FLAG_KILLED, PROC_EX_NONE, 0);
|
||||||
|
|
||||||
// Reward player, his pets, and group/raid members
|
// Reward player, his pets, and group/raid members
|
||||||
if (player_tap != pVictim)
|
if (player_tap != pVictim)
|
||||||
|
|
@ -1538,7 +1544,7 @@ void Unit::CastSpell(Unit* Victim, SpellEntry const* spellInfo, bool triggered,
|
||||||
targets.setSource(caster->GetPositionX(), caster->GetPositionY(), caster->GetPositionZ());
|
targets.setSource(caster->GetPositionX(), caster->GetPositionY(), caster->GetPositionZ());
|
||||||
|
|
||||||
spell->m_CastItem = castItem;
|
spell->m_CastItem = castItem;
|
||||||
spell->prepare(&targets, triggeredByAura);
|
spell->SpellStart(&targets, triggeredByAura);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Unit::CastCustomSpell(Unit* Victim, uint32 spellId, int32 const* bp0, int32 const* bp1, int32 const* bp2, bool triggered, Item* castItem, Aura* triggeredByAura, ObjectGuid originalCaster, SpellEntry const* triggeredBy)
|
void Unit::CastCustomSpell(Unit* Victim, uint32 spellId, int32 const* bp0, int32 const* bp1, int32 const* bp2, bool triggered, Item* castItem, Aura* triggeredByAura, ObjectGuid originalCaster, SpellEntry const* triggeredBy)
|
||||||
|
|
@ -1600,7 +1606,7 @@ void Unit::CastCustomSpell(Unit* Victim, SpellEntry const* spellInfo, int32 cons
|
||||||
if (WorldObject* caster = spell->GetCastingObject())
|
if (WorldObject* caster = spell->GetCastingObject())
|
||||||
{ targets.setSource(caster->GetPositionX(), caster->GetPositionY(), caster->GetPositionZ()); }
|
{ targets.setSource(caster->GetPositionX(), caster->GetPositionY(), caster->GetPositionZ()); }
|
||||||
|
|
||||||
spell->prepare(&targets, triggeredByAura);
|
spell->SpellStart(&targets, triggeredByAura);
|
||||||
}
|
}
|
||||||
|
|
||||||
// used for scripting
|
// used for scripting
|
||||||
|
|
@ -1657,7 +1663,7 @@ void Unit::CastSpell(float x, float y, float z, SpellEntry const* spellInfo, boo
|
||||||
{ targets.setDestination(x, y, z); }
|
{ targets.setDestination(x, y, z); }
|
||||||
|
|
||||||
spell->m_CastItem = castItem;
|
spell->m_CastItem = castItem;
|
||||||
spell->prepare(&targets, triggeredByAura);
|
spell->SpellStart(&targets, triggeredByAura);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Obsolete func need remove, here only for comotability vs another patches
|
// Obsolete func need remove, here only for comotability vs another patches
|
||||||
|
|
@ -1897,6 +1903,11 @@ void Unit::CalculateMeleeDamage(Unit* pVictim, CalcDamageInfo* damageInfo, Weapo
|
||||||
damageInfo->procEx |= PROC_EX_CRITICAL_HIT;
|
damageInfo->procEx |= PROC_EX_CRITICAL_HIT;
|
||||||
// Crit bonus calc
|
// Crit bonus calc
|
||||||
damageInfo->damage += damageInfo->damage;
|
damageInfo->damage += damageInfo->damage;
|
||||||
|
|
||||||
|
// Apply SPELL_AURA_MOD_CRIT_DAMAGE_BONUS modifier first
|
||||||
|
const int32 bonus = GetTotalAuraModifierByMiscMask(SPELL_AURA_MOD_CRIT_DAMAGE_BONUS, SPELL_SCHOOL_MASK_NORMAL);
|
||||||
|
damageInfo->damage += int32((damageInfo->damage) * float(bonus / 100.0f));
|
||||||
|
|
||||||
int32 mod = 0;
|
int32 mod = 0;
|
||||||
// Apply SPELL_AURA_MOD_ATTACKER_RANGED_CRIT_DAMAGE or SPELL_AURA_MOD_ATTACKER_MELEE_CRIT_DAMAGE
|
// Apply SPELL_AURA_MOD_ATTACKER_RANGED_CRIT_DAMAGE or SPELL_AURA_MOD_ATTACKER_MELEE_CRIT_DAMAGE
|
||||||
if (damageInfo->attackType == RANGED_ATTACK)
|
if (damageInfo->attackType == RANGED_ATTACK)
|
||||||
|
|
@ -1904,8 +1915,6 @@ void Unit::CalculateMeleeDamage(Unit* pVictim, CalcDamageInfo* damageInfo, Weapo
|
||||||
else
|
else
|
||||||
mod += damageInfo->target->GetTotalAuraModifier(SPELL_AURA_MOD_ATTACKER_MELEE_CRIT_DAMAGE);
|
mod += damageInfo->target->GetTotalAuraModifier(SPELL_AURA_MOD_ATTACKER_MELEE_CRIT_DAMAGE);
|
||||||
|
|
||||||
mod += GetTotalAuraModifierByMiscMask(SPELL_AURA_MOD_CRIT_DAMAGE_BONUS, SPELL_SCHOOL_MASK_NORMAL);
|
|
||||||
|
|
||||||
if (mod != 0)
|
if (mod != 0)
|
||||||
damageInfo->damage = int32((damageInfo->damage) * float((100.0f + mod) / 100.0f));
|
damageInfo->damage = int32((damageInfo->damage) * float((100.0f + mod) / 100.0f));
|
||||||
|
|
||||||
|
|
@ -2917,6 +2926,8 @@ void Unit::AttackerStateUpdate(Unit* pVictim, WeaponAttackType attType, bool ext
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
RemoveAurasWithInterruptFlags(AURA_INTERRUPT_FLAG_MELEE_ATTACK);
|
||||||
|
|
||||||
// attack can be redirected to another target
|
// attack can be redirected to another target
|
||||||
pVictim = SelectMagnetTarget(pVictim);
|
pVictim = SelectMagnetTarget(pVictim);
|
||||||
|
|
||||||
|
|
@ -2935,6 +2946,22 @@ void Unit::AttackerStateUpdate(Unit* pVictim, WeaponAttackType attType, bool ext
|
||||||
DEBUG_FILTER_LOG(LOG_FILTER_COMBAT, "AttackerStateUpdate: (NPC) %u attacked %u (TypeId: %u) for %u dmg, absorbed %u, blocked %u, resisted %u.",
|
DEBUG_FILTER_LOG(LOG_FILTER_COMBAT, "AttackerStateUpdate: (NPC) %u attacked %u (TypeId: %u) for %u dmg, absorbed %u, blocked %u, resisted %u.",
|
||||||
GetGUIDLow(), pVictim->GetGUIDLow(), pVictim->GetTypeId(), damageInfo.damage, damageInfo.absorb, damageInfo.blocked_amount, damageInfo.resist);
|
GetGUIDLow(), pVictim->GetGUIDLow(), pVictim->GetTypeId(), damageInfo.damage, damageInfo.absorb, damageInfo.blocked_amount, damageInfo.resist);
|
||||||
|
|
||||||
|
if (Unit* owner = GetOwner())
|
||||||
|
if (owner->GetTypeId() == TYPEID_UNIT)
|
||||||
|
{
|
||||||
|
owner->SetInCombatWith(pVictim);
|
||||||
|
owner->AddThreat(pVictim);
|
||||||
|
pVictim->SetInCombatWith(owner);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (GuidSet::const_iterator itr = m_guardianPets.begin(); itr != m_guardianPets.end(); ++itr)
|
||||||
|
if (Unit* pet = (Unit*)GetMap()->GetPet(*itr))
|
||||||
|
{
|
||||||
|
pet->SetInCombatWith(pVictim);
|
||||||
|
pet->AddThreat(pVictim);
|
||||||
|
pVictim->SetInCombatWith(pet);
|
||||||
|
}
|
||||||
|
|
||||||
// if damage pVictim call AI reaction
|
// if damage pVictim call AI reaction
|
||||||
pVictim->AttackedBy(this);
|
pVictim->AttackedBy(this);
|
||||||
|
|
||||||
|
|
@ -3101,25 +3128,19 @@ MeleeHitOutcome Unit::RollMeleeOutcomeAgainst(const Unit* pVictim, WeaponAttackT
|
||||||
}
|
}
|
||||||
|
|
||||||
// mobs can score crushing blows if they're 4 or more levels above victim
|
// mobs can score crushing blows if they're 4 or more levels above victim
|
||||||
if (GetLevelForTarget(pVictim) >= pVictim->GetLevelForTarget(this) + 4 &&
|
// having defense above your maximum (from items, talents etc.) has no effect
|
||||||
// can be from by creature (if can) or from controlled player that considered as creature
|
// mob's level * 5 - player's current defense skill - add 2% chance per lacking skill point, min. is 20%
|
||||||
((GetTypeId() != TYPEID_PLAYER && !((Creature*)this)->IsPet() &&
|
if ((getLevel() - 4) >= pVictim->getLevel() && !IsNonMeleeSpellCasted(false) /* It should have been !spellCasted but wrath doesn't have that? */
|
||||||
!(((Creature*)this)->GetCreatureInfo()->ExtraFlags & CREATURE_EXTRA_FLAG_NO_CRUSH)) ||
|
&& roll < (tmp = (((attackerMaxSkillValueForLevel - tmp) * 200) - 2000)))
|
||||||
GetTypeId() == TYPEID_PLAYER && GetCharmerOrOwnerGuid()))
|
|
||||||
{
|
{
|
||||||
// when their weapon skill is 15 or more above victim's defense skill
|
uint32 typeId = GetTypeId();
|
||||||
tmp = victimMaxSkillValueForLevel;
|
/* It should have been !(((Creature*)this)->GetCreatureInfo()->ExtraFlags & CREATURE_EXTRA_FLAG_NO_CRUSH) but wrath doesn't have that? */
|
||||||
// tmp = mob's level * 5 - player's current defense skill
|
if ((typeId == TYPEID_UNIT && !(GetOwnerGuid() && GetOwner()->GetTypeId() == TYPEID_PLAYER)
|
||||||
tmp = attackerMaxSkillValueForLevel - tmp;
|
&& !(static_cast<Creature const*>(this)->GetCreatureInfo()->ExtraFlags & CREATURE_EXTRA_FLAG_NO_CRUSH))
|
||||||
if (tmp >= 15)
|
|| (typeId == TYPEID_PLAYER && GetCharmerGuid() && GetCharmer()->GetTypeId() == TYPEID_UNIT))
|
||||||
{
|
{
|
||||||
// add 2% chance per lacking skill point, min. is 15%
|
DEBUG_FILTER_LOG(LOG_FILTER_COMBAT, "RollMeleeOutcomeAgainst: CRUSHING %d)", tmp);
|
||||||
tmp = tmp * 200 - 1500;
|
return MELEE_HIT_CRUSHING;
|
||||||
if (roll < (sum += tmp))
|
|
||||||
{
|
|
||||||
DEBUG_FILTER_LOG(LOG_FILTER_COMBAT, "RollMeleeOutcomeAgainst: CRUSHING <%d, %d)", sum - tmp, sum);
|
|
||||||
return MELEE_HIT_CRUSHING;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -3848,7 +3869,7 @@ void Unit::_UpdateAutoRepeatSpell()
|
||||||
|
|
||||||
// we want to shoot
|
// we want to shoot
|
||||||
Spell* spell = new Spell(this, m_currentSpells[CURRENT_AUTOREPEAT_SPELL]->m_spellInfo, true);
|
Spell* spell = new Spell(this, m_currentSpells[CURRENT_AUTOREPEAT_SPELL]->m_spellInfo, true);
|
||||||
spell->prepare(&(m_currentSpells[CURRENT_AUTOREPEAT_SPELL]->m_targets));
|
spell->SpellStart(&(m_currentSpells[CURRENT_AUTOREPEAT_SPELL]->m_targets));
|
||||||
|
|
||||||
// all went good, reset attack
|
// all went good, reset attack
|
||||||
resetAttackTimer(RANGED_ATTACK);
|
resetAttackTimer(RANGED_ATTACK);
|
||||||
|
|
@ -4557,31 +4578,9 @@ bool Unit::RemoveNoStackAurasDueToAuraHolder(SpellAuraHolder* holder)
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (i_spellId == spellId) continue;
|
|
||||||
|
|
||||||
bool is_triggered_by_spell = false;
|
|
||||||
// prevent triggering aura of removing aura that triggered it
|
// prevent triggering aura of removing aura that triggered it
|
||||||
for(int j = 0; j < MAX_EFFECT_INDEX; ++j)
|
if (((*i).second->GetTriggeredBy() && (*i).second->GetTriggeredBy()->Id == spellId)
|
||||||
{
|
|| (holder->GetTriggeredBy() && holder->GetTriggeredBy()->Id == i_spellId))
|
||||||
SpellEffectEntry const* iSpellEffect = i_spellProto->GetSpellEffect(SpellEffectIndex(j));
|
|
||||||
if(!iSpellEffect)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if (iSpellEffect->EffectTriggerSpell == spellId)
|
|
||||||
is_triggered_by_spell = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// prevent triggered aura of removing aura that triggering it (triggered effect early some aura of parent spell
|
|
||||||
for(int j = 0; j < MAX_EFFECT_INDEX; ++j)
|
|
||||||
{
|
|
||||||
SpellEffectEntry const* spellEffect = i_spellProto->GetSpellEffect(SpellEffectIndex(j));
|
|
||||||
if(!spellEffect)
|
|
||||||
continue;
|
|
||||||
if (spellEffect->EffectTriggerSpell == i_spellId)
|
|
||||||
is_triggered_by_spell = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (is_triggered_by_spell)
|
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
SpellSpecific i_spellId_spec = GetSpellSpecific(i_spellId);
|
SpellSpecific i_spellId_spec = GetSpellSpecific(i_spellId);
|
||||||
|
|
@ -4982,6 +4981,46 @@ void Unit::RemoveAurasWithAttribute(uint32 flags)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Unit::RemoveAurasOnCast(SpellEntry const* castedSpellEntry)
|
||||||
|
{
|
||||||
|
for (SpellAuraHolderMap::iterator iter = m_spellAuraHolders.begin(); iter != m_spellAuraHolders.end();)
|
||||||
|
{
|
||||||
|
SpellAuraHolder* holder = iter->second;
|
||||||
|
SpellEntry const* spellEntry = holder->GetSpellProto();
|
||||||
|
bool removeThisHolder = false;
|
||||||
|
|
||||||
|
if (spellEntry->GetAuraInterruptFlags() & AURA_INTERRUPT_FLAG_UNK2)
|
||||||
|
{
|
||||||
|
if (castedSpellEntry->HasAttribute(SPELL_ATTR_EX_NOT_BREAK_STEALTH))
|
||||||
|
{
|
||||||
|
bool foundStealth = false;
|
||||||
|
for (int32 i = 0; i < MAX_EFFECT_INDEX; ++i)
|
||||||
|
{
|
||||||
|
if (Aura* aura = holder->m_auras[i])
|
||||||
|
{
|
||||||
|
if (aura->GetModifier()->m_auraname == SPELL_AURA_MOD_STEALTH)
|
||||||
|
{
|
||||||
|
foundStealth = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
removeThisHolder = !foundStealth;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
removeThisHolder = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (removeThisHolder)
|
||||||
|
{
|
||||||
|
RemoveSpellAuraHolder(iter->second);
|
||||||
|
iter = m_spellAuraHolders.begin();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
++iter;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void Unit::RemoveNotOwnTrackedTargetAuras(uint32 newPhase)
|
void Unit::RemoveNotOwnTrackedTargetAuras(uint32 newPhase)
|
||||||
{
|
{
|
||||||
// tracked aura targets from other casters are removed if the phase does no more fit
|
// tracked aura targets from other casters are removed if the phase does no more fit
|
||||||
|
|
@ -5882,7 +5921,7 @@ bool Unit::IsHostileTo(Unit const* unit) const
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
// Sanctuary
|
// Sanctuary
|
||||||
if (pTarget->HasByteFlag(UNIT_FIELD_BYTES_2, 1, UNIT_BYTE2_FLAG_SUPPORTABLE) && pTester->HasByteFlag(UNIT_FIELD_BYTES_2, 1, UNIT_BYTE2_FLAG_SUPPORTABLE))
|
if (pTarget->HasFlag(PLAYER_FLAGS, PLAYER_FLAGS_SANCTUARY) && pTester->HasFlag(PLAYER_FLAGS, PLAYER_FLAGS_SANCTUARY))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
// PvP FFA state
|
// PvP FFA state
|
||||||
|
|
@ -5994,7 +6033,7 @@ bool Unit::IsFriendlyTo(Unit const* unit) const
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
// Sanctuary
|
// Sanctuary
|
||||||
if (pTarget->HasByteFlag(UNIT_FIELD_BYTES_2, 1, UNIT_BYTE2_FLAG_SUPPORTABLE) && pTester->HasByteFlag(UNIT_FIELD_BYTES_2, 1, UNIT_BYTE2_FLAG_SUPPORTABLE))
|
if (pTarget->HasFlag(PLAYER_FLAGS, PLAYER_FLAGS_SANCTUARY) && pTester->HasFlag(PLAYER_FLAGS, PLAYER_FLAGS_SANCTUARY))
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
// PvP FFA state
|
// PvP FFA state
|
||||||
|
|
@ -6115,10 +6154,13 @@ bool Unit::Attack(Unit* victim, bool meleeAttack)
|
||||||
if (m_attacking == victim)
|
if (m_attacking == victim)
|
||||||
{
|
{
|
||||||
// switch to melee attack from ranged/magic
|
// switch to melee attack from ranged/magic
|
||||||
if (meleeAttack && !hasUnitState(UNIT_STAT_MELEE_ATTACKING))
|
if (meleeAttack)
|
||||||
{
|
{
|
||||||
addUnitState(UNIT_STAT_MELEE_ATTACKING);
|
if (!hasUnitState(UNIT_STAT_MELEE_ATTACKING))
|
||||||
SendMeleeAttackStart(victim);
|
{
|
||||||
|
addUnitState(UNIT_STAT_MELEE_ATTACKING);
|
||||||
|
SendMeleeAttackStart(victim);
|
||||||
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
|
|
@ -7237,6 +7279,14 @@ bool Unit::IsSpellCrit(Unit* pVictim, SpellEntry const* spellProto, SpellSchoolM
|
||||||
if (spellProto->HasAttribute(SPELL_ATTR_EX2_CANT_CRIT))
|
if (spellProto->HasAttribute(SPELL_ATTR_EX2_CANT_CRIT))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
// Creatures do not crit with their spells or abilities, unless it is owned by a player (pet, totem, etc)
|
||||||
|
if (GetTypeId() != TYPEID_PLAYER)
|
||||||
|
{
|
||||||
|
Unit* owner = GetOwner();
|
||||||
|
if (!owner || owner->GetTypeId() != TYPEID_PLAYER)
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
float crit_chance = 0.0f;
|
float crit_chance = 0.0f;
|
||||||
switch(spellProto->GetDmgClass())
|
switch(spellProto->GetDmgClass())
|
||||||
{
|
{
|
||||||
|
|
@ -7420,6 +7470,10 @@ uint32 Unit::SpellCriticalDamageBonus(SpellEntry const* spellProto, uint32 damag
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Apply SPELL_AURA_MOD_CRIT_DAMAGE_BONUS modifier first
|
||||||
|
const int32 pctBonus = GetTotalAuraModifierByMiscMask(SPELL_AURA_MOD_CRIT_DAMAGE_BONUS, GetSpellSchoolMask(spellProto));
|
||||||
|
crit_bonus += int32((damage + crit_bonus) * float(pctBonus / 100.0f));
|
||||||
|
|
||||||
// adds additional damage to crit_bonus (from talents)
|
// adds additional damage to crit_bonus (from talents)
|
||||||
if (Player* modOwner = GetSpellModOwner())
|
if (Player* modOwner = GetSpellModOwner())
|
||||||
modOwner->ApplySpellMod(spellProto->Id, SPELLMOD_CRIT_DAMAGE_BONUS, crit_bonus);
|
modOwner->ApplySpellMod(spellProto->Id, SPELLMOD_CRIT_DAMAGE_BONUS, crit_bonus);
|
||||||
|
|
@ -7438,8 +7492,6 @@ uint32 Unit::SpellCriticalDamageBonus(SpellEntry const* spellProto, uint32 damag
|
||||||
else
|
else
|
||||||
critPctDamageMod += pVictim->GetTotalAuraModifierByMiscMask(SPELL_AURA_MOD_ATTACKER_SPELL_CRIT_DAMAGE, GetSpellSchoolMask(spellProto));
|
critPctDamageMod += pVictim->GetTotalAuraModifierByMiscMask(SPELL_AURA_MOD_ATTACKER_SPELL_CRIT_DAMAGE, GetSpellSchoolMask(spellProto));
|
||||||
|
|
||||||
critPctDamageMod += GetTotalAuraModifierByMiscMask(SPELL_AURA_MOD_CRIT_DAMAGE_BONUS, GetSpellSchoolMask(spellProto));
|
|
||||||
|
|
||||||
if (critPctDamageMod != 0)
|
if (critPctDamageMod != 0)
|
||||||
crit_bonus = int32(crit_bonus * float((100.0f + critPctDamageMod) / 100.0f));
|
crit_bonus = int32(crit_bonus * float((100.0f + critPctDamageMod) / 100.0f));
|
||||||
|
|
||||||
|
|
@ -7535,9 +7587,9 @@ uint32 Unit::SpellHealingBonusDone(Unit* pVictim, SpellEntry const* spellProto,
|
||||||
int ownHotCount = 0; // counted HoT types amount, not stacks
|
int ownHotCount = 0; // counted HoT types amount, not stacks
|
||||||
|
|
||||||
Unit::AuraList const& RejorRegr = pVictim->GetAurasByType(SPELL_AURA_PERIODIC_HEAL);
|
Unit::AuraList const& RejorRegr = pVictim->GetAurasByType(SPELL_AURA_PERIODIC_HEAL);
|
||||||
for(Unit::AuraList::const_iterator i = RejorRegr.begin(); i != RejorRegr.end(); ++i)
|
for (Unit::AuraList::const_iterator itr = RejorRegr.begin(); itr != RejorRegr.end(); ++itr)
|
||||||
if ((*i)->GetSpellProto()->GetSpellFamilyName() == SPELLFAMILY_DRUID &&
|
if ((*itr)->GetSpellProto()->GetSpellFamilyName() == SPELLFAMILY_DRUID &&
|
||||||
(*i)->GetCasterGuid() == GetObjectGuid())
|
(*itr)->GetCasterGuid() == GetObjectGuid())
|
||||||
++ownHotCount;
|
++ownHotCount;
|
||||||
|
|
||||||
if (ownHotCount)
|
if (ownHotCount)
|
||||||
|
|
@ -8274,13 +8326,11 @@ void Unit::Mount(uint32 mount, uint32 spellId)
|
||||||
// Normal case (Unsummon only permanent pet)
|
// Normal case (Unsummon only permanent pet)
|
||||||
else if (Pet* pet = GetPet())
|
else if (Pet* pet = GetPet())
|
||||||
{
|
{
|
||||||
if (pet->IsPermanentPetFor((Player*)this) && !((Player*)this)->InArena() &&
|
if (pet->isControlled() && (!(pet->isTemporarySummoned() || ((Player*)this)->InArena())
|
||||||
sWorld.getConfig(CONFIG_BOOL_PET_UNSUMMON_AT_MOUNT))
|
|| sWorld.getConfig(CONFIG_BOOL_PET_UNSUMMON_AT_MOUNT)))
|
||||||
{
|
|
||||||
((Player*)this)->UnsummonPetTemporaryIfAny();
|
((Player*)this)->UnsummonPetTemporaryIfAny();
|
||||||
}
|
|
||||||
else
|
else
|
||||||
pet->ApplyModeFlags(PET_MODE_DISABLE_ACTIONS, true);
|
pet->SetModeFlags(PET_MODE_DISABLE_ACTIONS);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -79,9 +79,9 @@ enum SpellAuraInterruptFlags
|
||||||
AURA_INTERRUPT_FLAG_NOT_ABOVEWATER = 0x00000080, // 7 removed by entering water
|
AURA_INTERRUPT_FLAG_NOT_ABOVEWATER = 0x00000080, // 7 removed by entering water
|
||||||
AURA_INTERRUPT_FLAG_NOT_UNDERWATER = 0x00000100, // 8 removed by leaving water
|
AURA_INTERRUPT_FLAG_NOT_UNDERWATER = 0x00000100, // 8 removed by leaving water
|
||||||
AURA_INTERRUPT_FLAG_NOT_SHEATHED = 0x00000200, // 9 removed by unsheathing
|
AURA_INTERRUPT_FLAG_NOT_SHEATHED = 0x00000200, // 9 removed by unsheathing
|
||||||
AURA_INTERRUPT_FLAG_UNK10 = 0x00000400, // 10
|
AURA_INTERRUPT_FLAG_TALK = 0x00000400, // 10 talk to npc / loot? action on creature
|
||||||
AURA_INTERRUPT_FLAG_UNK11 = 0x00000800, // 11
|
AURA_INTERRUPT_FLAG_USE = 0x00000800, // 11 mine/use/open action on gameobject
|
||||||
AURA_INTERRUPT_FLAG_UNK12 = 0x00001000, // 12 removed by attack?
|
AURA_INTERRUPT_FLAG_MELEE_ATTACK = 0x00001000, // 12 removed by attack
|
||||||
AURA_INTERRUPT_FLAG_UNK13 = 0x00002000, // 13
|
AURA_INTERRUPT_FLAG_UNK13 = 0x00002000, // 13
|
||||||
AURA_INTERRUPT_FLAG_UNK14 = 0x00004000, // 14
|
AURA_INTERRUPT_FLAG_UNK14 = 0x00004000, // 14
|
||||||
AURA_INTERRUPT_FLAG_UNK15 = 0x00008000, // 15 removed by casting a spell?
|
AURA_INTERRUPT_FLAG_UNK15 = 0x00008000, // 15 removed by casting a spell?
|
||||||
|
|
@ -3141,6 +3141,9 @@ class Unit : public WorldObject
|
||||||
*/
|
*/
|
||||||
void RemoveAllAurasOnEvade();
|
void RemoveAllAurasOnEvade();
|
||||||
|
|
||||||
|
// remove specific aura on cast
|
||||||
|
void RemoveAurasOnCast(SpellEntry const* castedSpellEntry);
|
||||||
|
|
||||||
// removing specific aura FROM stack by diff reasons and selections
|
// removing specific aura FROM stack by diff reasons and selections
|
||||||
void RemoveAuraHolderFromStack(uint32 spellId, uint32 stackAmount = 1, ObjectGuid casterGuid = ObjectGuid(), AuraRemoveMode mode = AURA_REMOVE_BY_DEFAULT);
|
void RemoveAuraHolderFromStack(uint32 spellId, uint32 stackAmount = 1, ObjectGuid casterGuid = ObjectGuid(), AuraRemoveMode mode = AURA_REMOVE_BY_DEFAULT);
|
||||||
void RemoveAuraHolderDueToSpellByDispel(uint32 spellId, uint32 stackAmount, ObjectGuid casterGuid, Unit* dispeller);
|
void RemoveAuraHolderDueToSpellByDispel(uint32 spellId, uint32 stackAmount, ObjectGuid casterGuid, Unit* dispeller);
|
||||||
|
|
|
||||||
|
|
@ -321,6 +321,9 @@ void VehicleInfo::UnBoard(Unit* passenger, bool changeVehicle)
|
||||||
|
|
||||||
UnBoardPassenger(passenger); // Use TransportBase to remove the passenger from storage list
|
UnBoardPassenger(passenger); // Use TransportBase to remove the passenger from storage list
|
||||||
|
|
||||||
|
// Remove passenger modifications
|
||||||
|
RemoveSeatMods(passenger, seatEntry->m_flags);
|
||||||
|
|
||||||
if (!changeVehicle) // Send expected unboarding packages
|
if (!changeVehicle) // Send expected unboarding packages
|
||||||
{
|
{
|
||||||
// Update movementInfo
|
// Update movementInfo
|
||||||
|
|
@ -354,9 +357,6 @@ void VehicleInfo::UnBoard(Unit* passenger, bool changeVehicle)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Remove passenger modifications
|
|
||||||
RemoveSeatMods(passenger, seatEntry->m_flags);
|
|
||||||
|
|
||||||
// Some creature vehicles get despawned after passenger unboarding
|
// Some creature vehicles get despawned after passenger unboarding
|
||||||
if (m_owner->GetTypeId() == TYPEID_UNIT)
|
if (m_owner->GetTypeId() == TYPEID_UNIT)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -136,8 +136,8 @@ void OutdoorPvPMgr::HandlePlayerEnterZone(Player* player, uint32 zoneId)
|
||||||
{
|
{
|
||||||
if (OutdoorPvP* script = GetScript(zoneId))
|
if (OutdoorPvP* script = GetScript(zoneId))
|
||||||
script->HandlePlayerEnterZone(player, true);
|
script->HandlePlayerEnterZone(player, true);
|
||||||
else if (OutdoorPvP* script = GetScriptOfAffectedZone(zoneId))
|
else if (OutdoorPvP* affectedScript = GetScriptOfAffectedZone(zoneId))
|
||||||
script->HandlePlayerEnterZone(player, false);
|
affectedScript->HandlePlayerEnterZone(player, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -151,8 +151,8 @@ void OutdoorPvPMgr::HandlePlayerLeaveZone(Player* player, uint32 zoneId)
|
||||||
// teleport: called once from Player::CleanupsBeforeDelete, once from Player::UpdateZone
|
// teleport: called once from Player::CleanupsBeforeDelete, once from Player::UpdateZone
|
||||||
if (OutdoorPvP* script = GetScript(zoneId))
|
if (OutdoorPvP* script = GetScript(zoneId))
|
||||||
script->HandlePlayerLeaveZone(player, true);
|
script->HandlePlayerLeaveZone(player, true);
|
||||||
else if (OutdoorPvP* script = GetScriptOfAffectedZone(zoneId))
|
else if (OutdoorPvP* affectedScript = GetScriptOfAffectedZone(zoneId))
|
||||||
script->HandlePlayerLeaveZone(player, false);
|
affectedScript->HandlePlayerLeaveZone(player, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
void OutdoorPvPMgr::Update(uint32 diff)
|
void OutdoorPvPMgr::Update(uint32 diff)
|
||||||
|
|
|
||||||
|
|
@ -107,6 +107,9 @@ void HostileReference::fireStatusChanged(ThreatRefStatusChangeEvent& pThreatRefS
|
||||||
|
|
||||||
void HostileReference::addThreat(float pMod)
|
void HostileReference::addThreat(float pMod)
|
||||||
{
|
{
|
||||||
|
if (pMod + iThreat < 0)
|
||||||
|
pMod = -iThreat;
|
||||||
|
|
||||||
iThreat += pMod;
|
iThreat += pMod;
|
||||||
// the threat is changed. Source and target unit have to be availabe
|
// the threat is changed. Source and target unit have to be availabe
|
||||||
// if the link was cut before relink it again
|
// if the link was cut before relink it again
|
||||||
|
|
@ -495,12 +498,16 @@ Unit* ThreatManager::getHostileTarget()
|
||||||
|
|
||||||
float ThreatManager::getThreat(Unit* pVictim, bool pAlsoSearchOfflineList)
|
float ThreatManager::getThreat(Unit* pVictim, bool pAlsoSearchOfflineList)
|
||||||
{
|
{
|
||||||
|
if (!pVictim)
|
||||||
|
return 0.0f;
|
||||||
|
|
||||||
float threat = 0.0f;
|
float threat = 0.0f;
|
||||||
HostileReference* ref = iThreatContainer.getReferenceByTarget(pVictim);
|
|
||||||
if (!ref && pAlsoSearchOfflineList)
|
if (HostileReference* ref = iThreatContainer.getReferenceByTarget(pVictim))
|
||||||
ref = iThreatOfflineContainer.getReferenceByTarget(pVictim);
|
|
||||||
if (ref)
|
|
||||||
threat = ref->getThreat();
|
threat = ref->getThreat();
|
||||||
|
else if (pAlsoSearchOfflineList)
|
||||||
|
threat = iThreatOfflineContainer.getReferenceByTarget(pVictim)->getThreat();
|
||||||
|
|
||||||
return threat;
|
return threat;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -531,7 +531,7 @@ enum SpellCastTargetFlags
|
||||||
TARGET_FLAG_OBJECT = 0x00000800, // pguid, 2 spells
|
TARGET_FLAG_OBJECT = 0x00000800, // pguid, 2 spells
|
||||||
TARGET_FLAG_TRADE_ITEM = 0x00001000, // pguid, 0 spells
|
TARGET_FLAG_TRADE_ITEM = 0x00001000, // pguid, 0 spells
|
||||||
TARGET_FLAG_STRING = 0x00002000, // string, 0 spells
|
TARGET_FLAG_STRING = 0x00002000, // string, 0 spells
|
||||||
TARGET_FLAG_UNK1 = 0x00004000, // 199 spells, opening object/lock
|
TARGET_FLAG_GAMEOBJECT_ITEM = 0x00004000, // 199 spells, opening object/lock
|
||||||
TARGET_FLAG_CORPSE = 0x00008000, // pguid, resurrection spells
|
TARGET_FLAG_CORPSE = 0x00008000, // pguid, resurrection spells
|
||||||
TARGET_FLAG_UNK2 = 0x00010000, // pguid, not used in any spells as of 3.0.3 (can be set dynamically)
|
TARGET_FLAG_UNK2 = 0x00010000, // pguid, not used in any spells as of 3.0.3 (can be set dynamically)
|
||||||
TARGET_FLAG_GLYPH = 0x00020000, // used in glyph spells
|
TARGET_FLAG_GLYPH = 0x00020000, // used in glyph spells
|
||||||
|
|
|
||||||
|
|
@ -279,7 +279,7 @@ enum SpellAttributes
|
||||||
SPELL_ATTR_TRADESPELL = 0x00000020,// 5 trade spells, will be added by client to a sublist of profession spell
|
SPELL_ATTR_TRADESPELL = 0x00000020,// 5 trade spells, will be added by client to a sublist of profession spell
|
||||||
SPELL_ATTR_PASSIVE = 0x00000040,// 6 Passive spell
|
SPELL_ATTR_PASSIVE = 0x00000040,// 6 Passive spell
|
||||||
SPELL_ATTR_UNK7 = 0x00000080,// 7 can't be linked in chat?
|
SPELL_ATTR_UNK7 = 0x00000080,// 7 can't be linked in chat?
|
||||||
SPELL_ATTR_UNK8 = 0x00000100,// 8 hide created item in tooltip (for effect=24)
|
SPELL_ATTR_UNK8 = 0x00000100,// 8
|
||||||
SPELL_ATTR_UNK9 = 0x00000200,// 9
|
SPELL_ATTR_UNK9 = 0x00000200,// 9
|
||||||
SPELL_ATTR_ON_NEXT_SWING_2 = 0x00000400,// 10 on next swing 2
|
SPELL_ATTR_ON_NEXT_SWING_2 = 0x00000400,// 10 on next swing 2
|
||||||
SPELL_ATTR_UNK11 = 0x00000800,// 11
|
SPELL_ATTR_UNK11 = 0x00000800,// 11
|
||||||
|
|
@ -422,7 +422,7 @@ enum SpellAttributesEx4
|
||||||
SPELL_ATTR_EX4_UNK4 = 0x00000010,// 4 This will no longer cause guards to attack on use??
|
SPELL_ATTR_EX4_UNK4 = 0x00000010,// 4 This will no longer cause guards to attack on use??
|
||||||
SPELL_ATTR_EX4_UNK5 = 0x00000020,// 5
|
SPELL_ATTR_EX4_UNK5 = 0x00000020,// 5
|
||||||
SPELL_ATTR_EX4_NOT_STEALABLE = 0x00000040,// 6 although such auras might be dispellable, they cannot be stolen
|
SPELL_ATTR_EX4_NOT_STEALABLE = 0x00000040,// 6 although such auras might be dispellable, they cannot be stolen
|
||||||
SPELL_ATTR_EX4_UNK7 = 0x00000080,// 7
|
SPELL_ATTR_EX4_CAN_CAST_WHILE_CASTING = 0x00000080,// 7 In theory, can use this spell while another is channeled/cast/autocast
|
||||||
SPELL_ATTR_EX4_STACK_DOT_MODIFIER = 0x00000100,// 8 no effect on non DoTs?
|
SPELL_ATTR_EX4_STACK_DOT_MODIFIER = 0x00000100,// 8 no effect on non DoTs?
|
||||||
SPELL_ATTR_EX4_UNK9 = 0x00000200,// 9
|
SPELL_ATTR_EX4_UNK9 = 0x00000200,// 9
|
||||||
SPELL_ATTR_EX4_SPELL_VS_EXTEND_COST = 0x00000400,// 10 Rogue Shiv have this flag
|
SPELL_ATTR_EX4_SPELL_VS_EXTEND_COST = 0x00000400,// 10 Rogue Shiv have this flag
|
||||||
|
|
@ -495,7 +495,7 @@ enum SpellAttributesEx6
|
||||||
SPELL_ATTR_EX6_UNK5 = 0x00000020,// 5
|
SPELL_ATTR_EX6_UNK5 = 0x00000020,// 5
|
||||||
SPELL_ATTR_EX6_UNK6 = 0x00000040,// 6
|
SPELL_ATTR_EX6_UNK6 = 0x00000040,// 6
|
||||||
SPELL_ATTR_EX6_UNK7 = 0x00000080,// 7
|
SPELL_ATTR_EX6_UNK7 = 0x00000080,// 7
|
||||||
SPELL_ATTR_EX6_UNK8 = 0x00000100,// 8
|
SPELL_ATTR_EX6_IGNORE_CC_TARGETS = 0x00000100,// 8 ignores target with cc effects
|
||||||
SPELL_ATTR_EX6_UNK9 = 0x00000200,// 9
|
SPELL_ATTR_EX6_UNK9 = 0x00000200,// 9
|
||||||
SPELL_ATTR_EX6_UNK10 = 0x00000400,// 10
|
SPELL_ATTR_EX6_UNK10 = 0x00000400,// 10
|
||||||
SPELL_ATTR_EX6_NOT_IN_RAID_INSTANCE = 0x00000800,// 11 not usable in raid instance
|
SPELL_ATTR_EX6_NOT_IN_RAID_INSTANCE = 0x00000800,// 11 not usable in raid instance
|
||||||
|
|
|
||||||
|
|
@ -1016,8 +1016,8 @@ void AchievementMgr::UpdateAchievementCriteria(AchievementCriteriaTypes type, ui
|
||||||
case ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_QUEST_COUNT:
|
case ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_QUEST_COUNT:
|
||||||
{
|
{
|
||||||
uint32 counter = 0;
|
uint32 counter = 0;
|
||||||
for (QuestStatusMap::const_iterator itr = GetPlayer()->getQuestStatusMap().begin(); itr != GetPlayer()->getQuestStatusMap().end(); ++itr)
|
for (QuestStatusMap::const_iterator questItr = GetPlayer()->getQuestStatusMap().begin(); questItr != GetPlayer()->getQuestStatusMap().end(); ++questItr)
|
||||||
if (itr->second.m_rewarded)
|
if (questItr->second.m_rewarded)
|
||||||
++counter;
|
++counter;
|
||||||
change = counter;
|
change = counter;
|
||||||
progressType = PROGRESS_HIGHEST;
|
progressType = PROGRESS_HIGHEST;
|
||||||
|
|
@ -1030,10 +1030,10 @@ void AchievementMgr::UpdateAchievementCriteria(AchievementCriteriaTypes type, ui
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
uint32 counter = 0;
|
uint32 counter = 0;
|
||||||
for (QuestStatusMap::const_iterator itr = GetPlayer()->getQuestStatusMap().begin(); itr != GetPlayer()->getQuestStatusMap().end(); ++itr)
|
for (QuestStatusMap::const_iterator questItr = GetPlayer()->getQuestStatusMap().begin(); questItr != GetPlayer()->getQuestStatusMap().end(); ++questItr)
|
||||||
{
|
{
|
||||||
Quest const* quest = sObjectMgr.GetQuestTemplate(itr->first);
|
Quest const* quest = sObjectMgr.GetQuestTemplate(questItr->first);
|
||||||
if (itr->second.m_rewarded && quest->GetZoneOrSort() >= 0 && uint32(quest->GetZoneOrSort()) == achievementCriteria->complete_quests_in_zone.zoneID)
|
if (questItr->second.m_rewarded && quest->GetZoneOrSort() >= 0 && uint32(quest->GetZoneOrSort()) == achievementCriteria->complete_quests_in_zone.zoneID)
|
||||||
++counter;
|
++counter;
|
||||||
}
|
}
|
||||||
change = counter;
|
change = counter;
|
||||||
|
|
|
||||||
|
|
@ -362,7 +362,9 @@ Map::Add(T* obj)
|
||||||
DEBUG_LOG("%s enters grid[%u,%u]", obj->GetGuidStr().c_str(), cell.GridX(), cell.GridY());
|
DEBUG_LOG("%s enters grid[%u,%u]", obj->GetGuidStr().c_str(), cell.GridX(), cell.GridY());
|
||||||
|
|
||||||
obj->GetViewPoint().Event_AddedToWorld(&(*grid)(cell.CellX(), cell.CellY()));
|
obj->GetViewPoint().Event_AddedToWorld(&(*grid)(cell.CellX(), cell.CellY()));
|
||||||
|
obj->SetItsNewObject(true);
|
||||||
UpdateObjectVisibility(obj, cell, p);
|
UpdateObjectVisibility(obj, cell, p);
|
||||||
|
obj->SetItsNewObject(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Map::MessageBroadcast(Player const* player, WorldPacket* msg, bool to_self)
|
void Map::MessageBroadcast(Player const* player, WorldPacket* msg, bool to_self)
|
||||||
|
|
|
||||||
|
|
@ -263,7 +263,7 @@ void WorldSession::HandlePetAction(WorldPacket& recv_data)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
spell->prepare(&(spell->m_targets));
|
spell->SpellStart(&(spell->m_targets));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
@ -704,7 +704,7 @@ void WorldSession::HandlePetCastSpellOpcode(WorldPacket& recvPacket)
|
||||||
pet->SendPetAIReaction();
|
pet->SendPetAIReaction();
|
||||||
}
|
}
|
||||||
|
|
||||||
spell->prepare(&(spell->m_targets), triggeredByAura);
|
spell->SpellStart(&(spell->m_targets), triggeredByAura);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -244,7 +244,7 @@ void SpellCastTargets::read(ByteBuffer& data, Unit* caster)
|
||||||
if (m_targetMask & (TARGET_FLAG_UNIT | TARGET_FLAG_UNK2))
|
if (m_targetMask & (TARGET_FLAG_UNIT | TARGET_FLAG_UNK2))
|
||||||
data >> m_unitTargetGUID.ReadAsPacked();
|
data >> m_unitTargetGUID.ReadAsPacked();
|
||||||
|
|
||||||
if (m_targetMask & (TARGET_FLAG_OBJECT))
|
if (m_targetMask & (TARGET_FLAG_OBJECT | TARGET_FLAG_GAMEOBJECT_ITEM))
|
||||||
data >> m_GOTargetGUID.ReadAsPacked();
|
data >> m_GOTargetGUID.ReadAsPacked();
|
||||||
|
|
||||||
if ((m_targetMask & (TARGET_FLAG_ITEM | TARGET_FLAG_TRADE_ITEM)) && caster->GetTypeId() == TYPEID_PLAYER)
|
if ((m_targetMask & (TARGET_FLAG_ITEM | TARGET_FLAG_TRADE_ITEM)) && caster->GetTypeId() == TYPEID_PLAYER)
|
||||||
|
|
@ -416,7 +416,7 @@ Spell::Spell(Unit* caster, SpellEntry const* info, bool triggered, ObjectGuid or
|
||||||
for (int i = 0; i < MAX_EFFECT_INDEX; ++i)
|
for (int i = 0; i < MAX_EFFECT_INDEX; ++i)
|
||||||
m_currentBasePoints[i] = m_spellInfo->CalculateSimpleValue(SpellEffectIndex(i));
|
m_currentBasePoints[i] = m_spellInfo->CalculateSimpleValue(SpellEffectIndex(i));
|
||||||
|
|
||||||
m_spellState = SPELL_STATE_PREPARING;
|
m_spellState = SPELL_STATE_CREATED;
|
||||||
|
|
||||||
m_castPositionX = m_castPositionY = m_castPositionZ = 0;
|
m_castPositionX = m_castPositionY = m_castPositionZ = 0;
|
||||||
m_TriggerSpells.clear();
|
m_TriggerSpells.clear();
|
||||||
|
|
@ -1854,6 +1854,13 @@ void Spell::SetTargetMap(SpellEffectIndex effIndex, uint32 targetMode, UnitList&
|
||||||
++next;
|
++next;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!prev->IsWithinLOSInMap(*next)
|
||||||
|
|| (m_spellInfo->HasAttribute(SPELL_ATTR_EX6_IGNORE_CC_TARGETS) && !(*next)->CanFreeMove()))
|
||||||
|
{
|
||||||
|
++next;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
prev = *next;
|
prev = *next;
|
||||||
targetUnitMap.push_back(prev);
|
targetUnitMap.push_back(prev);
|
||||||
tempTargetUnitMap.erase(next);
|
tempTargetUnitMap.erase(next);
|
||||||
|
|
@ -2986,8 +2993,13 @@ void Spell::SetTargetMap(SpellEffectIndex effIndex, uint32 targetMode, UnitList&
|
||||||
}
|
}
|
||||||
|
|
||||||
// remove caster from the list if required by attribute
|
// remove caster from the list if required by attribute
|
||||||
if (targetMode != TARGET_SELF && targetMode != TARGET_SELF2 && m_spellInfo->HasAttribute(SPELL_ATTR_EX_CANT_TARGET_SELF))
|
if (m_spellInfo->HasAttribute(SPELL_ATTR_EX_CANT_TARGET_SELF))
|
||||||
targetUnitMap.remove(m_caster);
|
{
|
||||||
|
const SpellEffectEntry* spellEffect = m_spellInfo->GetSpellEffect(effIndex);
|
||||||
|
|
||||||
|
if (targetMode != TARGET_SELF && targetMode != TARGET_SELF2 && (spellEffect && spellEffect->Effect != SPELL_EFFECT_SUMMON))
|
||||||
|
targetUnitMap.remove(m_caster);
|
||||||
|
}
|
||||||
|
|
||||||
if (unMaxTargets && targetUnitMap.size() > unMaxTargets)
|
if (unMaxTargets && targetUnitMap.size() > unMaxTargets)
|
||||||
{
|
{
|
||||||
|
|
@ -3064,34 +3076,11 @@ void Spell::SetTargetMap(SpellEffectIndex effIndex, uint32 targetMode, UnitList&
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Spell::prepare(SpellCastTargets const* targets, Aura* triggeredByAura)
|
SpellCastResult Spell::PreCastCheck(Aura* triggeredByAura /*= nullptr*/)
|
||||||
{
|
{
|
||||||
m_targets = *targets;
|
|
||||||
|
|
||||||
m_spellState = SPELL_STATE_PREPARING;
|
|
||||||
|
|
||||||
m_castPositionX = m_caster->GetPositionX();
|
|
||||||
m_castPositionY = m_caster->GetPositionY();
|
|
||||||
m_castPositionZ = m_caster->GetPositionZ();
|
|
||||||
m_castOrientation = m_caster->GetOrientation();
|
|
||||||
|
|
||||||
if (triggeredByAura)
|
|
||||||
m_triggeredByAuraSpell = triggeredByAura->GetSpellProto();
|
|
||||||
|
|
||||||
// create and add update event for this spell
|
|
||||||
SpellEvent* Event = new SpellEvent(this);
|
|
||||||
m_caster->m_Events.AddEvent(Event, m_caster->m_Events.CalculateTime(1));
|
|
||||||
|
|
||||||
// Prevent casting at cast another spell (ServerSide check)
|
// Prevent casting at cast another spell (ServerSide check)
|
||||||
if (m_caster->IsNonMeleeSpellCasted(false, true, true) && m_cast_count)
|
if (m_caster->IsNonMeleeSpellCasted(false, true, true) && m_cast_count && !m_spellInfo->HasAttribute(SPELL_ATTR_EX4_CAN_CAST_WHILE_CASTING))
|
||||||
{
|
return SPELL_FAILED_SPELL_IN_PROGRESS;
|
||||||
SendCastResult(SPELL_FAILED_SPELL_IN_PROGRESS);
|
|
||||||
finish(false);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Fill cost data
|
|
||||||
m_powerCost = CalculatePowerCost(m_spellInfo, m_caster, this, m_CastItem);
|
|
||||||
|
|
||||||
SpellCastResult result = CheckCast(true);
|
SpellCastResult result = CheckCast(true);
|
||||||
if (result != SPELL_CAST_OK && !IsAutoRepeat()) // always cast autorepeat dummy for triggering
|
if (result != SPELL_CAST_OK && !IsAutoRepeat()) // always cast autorepeat dummy for triggering
|
||||||
|
|
@ -3101,10 +3090,49 @@ void Spell::prepare(SpellCastTargets const* targets, Aura* triggeredByAura)
|
||||||
SendChannelUpdate(0);
|
SendChannelUpdate(0);
|
||||||
triggeredByAura->GetHolder()->SetAuraDuration(0);
|
triggeredByAura->GetHolder()->SetAuraDuration(0);
|
||||||
}
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
return SPELL_CAST_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Spell::SpellStart(SpellCastTargets const* targets, Aura* triggeredByAura)
|
||||||
|
{
|
||||||
|
m_spellState = SPELL_STATE_STARTING;
|
||||||
|
m_targets = *targets;
|
||||||
|
|
||||||
|
if (m_CastItem)
|
||||||
|
m_CastItemGuid = m_CastItem->GetObjectGuid();
|
||||||
|
|
||||||
|
m_castPositionX = m_caster->GetPositionX();
|
||||||
|
m_castPositionY = m_caster->GetPositionY();
|
||||||
|
m_castPositionZ = m_caster->GetPositionZ();
|
||||||
|
m_castOrientation = m_caster->GetOrientation();
|
||||||
|
|
||||||
|
if (triggeredByAura)
|
||||||
|
m_triggeredByAuraSpell = triggeredByAura->GetSpellProto();
|
||||||
|
|
||||||
|
// create and add update event for this spell
|
||||||
|
SpellEvent* Event = new SpellEvent(this);
|
||||||
|
m_caster->m_Events.AddEvent(Event, m_caster->m_Events.CalculateTime(1));
|
||||||
|
|
||||||
|
// Fill cost data
|
||||||
|
m_powerCost = m_IsTriggeredSpell ? 0 : CalculatePowerCost(m_spellInfo, m_caster, this, m_CastItem);
|
||||||
|
|
||||||
|
SpellCastResult result = PreCastCheck();
|
||||||
|
if (result != SPELL_CAST_OK)
|
||||||
|
{
|
||||||
SendCastResult(result);
|
SendCastResult(result);
|
||||||
finish(false);
|
finish(false);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
Prepare();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Spell::Prepare()
|
||||||
|
{
|
||||||
|
m_spellState = SPELL_STATE_PREPARING;
|
||||||
|
|
||||||
// Prepare data for triggers
|
// Prepare data for triggers
|
||||||
prepareDataForTriggerSystem();
|
prepareDataForTriggerSystem();
|
||||||
|
|
@ -3116,13 +3144,8 @@ void Spell::prepare(SpellCastTargets const* targets, Aura* triggeredByAura)
|
||||||
// set timer base at cast time
|
// set timer base at cast time
|
||||||
ReSetTimer();
|
ReSetTimer();
|
||||||
|
|
||||||
// stealth must be removed at cast starting (at show channel bar)
|
if (!m_IsTriggeredSpell)
|
||||||
// skip triggered spell (item equip spell casting and other not explicit character casts/item uses)
|
m_caster->RemoveAurasOnCast(m_spellInfo);
|
||||||
if (!m_IsTriggeredSpell && isSpellBreakStealth(m_spellInfo))
|
|
||||||
{
|
|
||||||
m_caster->RemoveSpellsCausingAura(SPELL_AURA_MOD_STEALTH);
|
|
||||||
m_caster->RemoveSpellsCausingAura(SPELL_AURA_FEIGN_DEATH);
|
|
||||||
}
|
|
||||||
|
|
||||||
// add non-triggered (with cast time and without)
|
// add non-triggered (with cast time and without)
|
||||||
if (!m_IsTriggeredSpell)
|
if (!m_IsTriggeredSpell)
|
||||||
|
|
@ -3134,6 +3157,10 @@ void Spell::prepare(SpellCastTargets const* targets, Aura* triggeredByAura)
|
||||||
SendSpellStart();
|
SendSpellStart();
|
||||||
|
|
||||||
TriggerGlobalCooldown();
|
TriggerGlobalCooldown();
|
||||||
|
|
||||||
|
// Execute instant spells immediate
|
||||||
|
if (m_timer == 0 && !IsNextMeleeSwingSpell() && !IsAutoRepeat() && !IsChanneledSpell(m_spellInfo))
|
||||||
|
cast();
|
||||||
}
|
}
|
||||||
// execute triggered without cast time explicitly in call point
|
// execute triggered without cast time explicitly in call point
|
||||||
else if (m_timer == 0)
|
else if (m_timer == 0)
|
||||||
|
|
@ -5087,7 +5114,7 @@ void Spell::CastTriggerSpells()
|
||||||
for (SpellInfoList::const_iterator si = m_TriggerSpells.begin(); si != m_TriggerSpells.end(); ++si)
|
for (SpellInfoList::const_iterator si = m_TriggerSpells.begin(); si != m_TriggerSpells.end(); ++si)
|
||||||
{
|
{
|
||||||
Spell* spell = new Spell(m_caster, (*si), true, m_originalCasterGUID);
|
Spell* spell = new Spell(m_caster, (*si), true, m_originalCasterGUID);
|
||||||
spell->prepare(&m_targets); // use original spell original targets
|
spell->SpellStart(&m_targets); // use original spell original targets
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -6072,23 +6099,43 @@ SpellCastResult Spell::CheckCast(bool strict)
|
||||||
}
|
}
|
||||||
case SPELL_EFFECT_SUMMON_PET:
|
case SPELL_EFFECT_SUMMON_PET:
|
||||||
{
|
{
|
||||||
if (m_caster->GetPetGuid()) // let warlock do a replacement summon
|
if (m_caster->GetCharmGuid())
|
||||||
|
return SPELL_FAILED_ALREADY_HAVE_CHARM;
|
||||||
|
|
||||||
|
uint32 plClass = m_caster->getClass();
|
||||||
|
if (plClass == CLASS_HUNTER)
|
||||||
{
|
{
|
||||||
|
if (Creature* pet = m_caster->GetPet())
|
||||||
Pet* pet = ((Player*)m_caster)->GetPet();
|
|
||||||
|
|
||||||
if (m_caster->GetTypeId() == TYPEID_PLAYER && m_caster->getClass() == CLASS_WARLOCK)
|
|
||||||
{
|
{
|
||||||
if (strict) // Summoning Disorientation, trigger pet stun (cast by pet so it doesn't attack player)
|
if (!pet->IsAlive() || pet->IsDead()) // this one will not play along; tried and retried countless times....
|
||||||
pet->CastSpell(pet, 32752, true, NULL, NULL, pet->GetObjectGuid());
|
return SPELL_FAILED_TARGETS_DEAD;
|
||||||
|
else
|
||||||
|
return SPELL_FAILED_ALREADY_HAVE_SUMMON;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Pet* dbPet = new Pet;
|
||||||
|
if (dbPet->LoadPetFromDB((Player*)m_caster, 0))
|
||||||
|
return SPELL_CAST_OK; // still returns an error to the player, so this error must come from somewhere else...
|
||||||
|
else
|
||||||
|
{
|
||||||
|
delete dbPet;
|
||||||
|
return SPELL_FAILED_NO_PET;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (m_caster->GetPetGuid())
|
||||||
|
{
|
||||||
|
if (plClass == CLASS_WARLOCK) // let warlock do a replacement summon
|
||||||
|
{
|
||||||
|
if (strict) // Summoning Disorientation, trigger pet stun (cast by pet so it doesn't attack player)
|
||||||
|
if (Pet* pet = ((Player*)m_caster)->GetPet())
|
||||||
|
pet->CastSpell(pet, 32752, true, nullptr, nullptr, pet->GetObjectGuid());
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
return SPELL_FAILED_ALREADY_HAVE_SUMMON;
|
return SPELL_FAILED_ALREADY_HAVE_SUMMON;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m_caster->GetCharmGuid())
|
|
||||||
return SPELL_FAILED_ALREADY_HAVE_CHARM;
|
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case SPELL_EFFECT_SUMMON_PLAYER:
|
case SPELL_EFFECT_SUMMON_PLAYER:
|
||||||
|
|
@ -6438,16 +6485,21 @@ SpellCastResult Spell::CheckPetCast(Unit* target)
|
||||||
if (!m_caster->IsAlive())
|
if (!m_caster->IsAlive())
|
||||||
return SPELL_FAILED_CASTER_DEAD;
|
return SPELL_FAILED_CASTER_DEAD;
|
||||||
|
|
||||||
if (m_caster->IsNonMeleeSpellCasted(false)) // prevent spellcast interruption by another spellcast
|
if (m_caster->IsNonMeleeSpellCasted(false) && !m_spellInfo->HasAttribute(SPELL_ATTR_EX4_CAN_CAST_WHILE_CASTING)) // prevent spellcast interruption by another spellcast
|
||||||
return SPELL_FAILED_SPELL_IN_PROGRESS;
|
return SPELL_FAILED_SPELL_IN_PROGRESS;
|
||||||
if (m_caster->IsInCombat() && IsNonCombatSpell(m_spellInfo))
|
if (m_caster->IsInCombat() && IsNonCombatSpell(m_spellInfo))
|
||||||
return SPELL_FAILED_AFFECTING_COMBAT;
|
return SPELL_FAILED_AFFECTING_COMBAT;
|
||||||
|
|
||||||
if (m_caster->GetTypeId() == TYPEID_UNIT && (((Creature*)m_caster)->IsPet() || m_caster->IsCharmed()))
|
if (m_caster->GetTypeId() == TYPEID_UNIT && (((Creature*)m_caster)->IsPet() || m_caster->IsCharmed()))
|
||||||
{
|
{
|
||||||
// dead owner (pets still alive when owners ressed?)
|
// dead owner (currently only ghouled players can have alive pet casting)
|
||||||
if (m_caster->GetCharmerOrOwner() && !m_caster->GetCharmerOrOwner()->IsAlive())
|
Unit* charmer = m_caster->GetCharmerOrOwner();
|
||||||
return SPELL_FAILED_CASTER_DEAD;
|
if (charmer)
|
||||||
|
{
|
||||||
|
Player* pCharmer = charmer->GetTypeId() == TYPEID_PLAYER ? static_cast<Player*>(charmer) : nullptr;
|
||||||
|
if (!charmer->IsAlive() && (!pCharmer || !pCharmer->IsGhouled()))
|
||||||
|
return SPELL_FAILED_CASTER_DEAD;
|
||||||
|
}
|
||||||
|
|
||||||
if (!target && m_targets.getUnitTarget())
|
if (!target && m_targets.getUnitTarget())
|
||||||
target = m_targets.getUnitTarget();
|
target = m_targets.getUnitTarget();
|
||||||
|
|
|
||||||
|
|
@ -390,7 +390,7 @@ class Spell
|
||||||
Spell(Unit* caster, SpellEntry const* info, bool triggered, ObjectGuid originalCasterGUID = ObjectGuid(), SpellEntry const* triggeredBy = NULL);
|
Spell(Unit* caster, SpellEntry const* info, bool triggered, ObjectGuid originalCasterGUID = ObjectGuid(), SpellEntry const* triggeredBy = NULL);
|
||||||
~Spell();
|
~Spell();
|
||||||
|
|
||||||
void prepare(SpellCastTargets const* targets, Aura* triggeredByAura = NULL);
|
void SpellStart(SpellCastTargets const* targets, Aura* triggeredByAura = nullptr);
|
||||||
|
|
||||||
void cancel();
|
void cancel();
|
||||||
|
|
||||||
|
|
@ -537,6 +537,9 @@ class Spell
|
||||||
bool IgnoreItemRequirements() const; // some item use spells have unexpected reagent data
|
bool IgnoreItemRequirements() const; // some item use spells have unexpected reagent data
|
||||||
void UpdateOriginalCasterPointer();
|
void UpdateOriginalCasterPointer();
|
||||||
|
|
||||||
|
SpellCastResult PreCastCheck(Aura* triggeredByAura = nullptr);
|
||||||
|
void Prepare();
|
||||||
|
|
||||||
Unit* m_caster;
|
Unit* m_caster;
|
||||||
|
|
||||||
ObjectGuid m_originalCasterGUID; // real source of cast (aura caster/etc), used for spell targets selection
|
ObjectGuid m_originalCasterGUID; // real source of cast (aura caster/etc), used for spell targets selection
|
||||||
|
|
|
||||||
|
|
@ -611,9 +611,9 @@ Aura* CreateAura(SpellEntry const* spellproto, SpellEffectIndex eff, int32* curr
|
||||||
return new Aura(spellproto, eff, currentBasePoints, holder, target, caster, castItem);
|
return new Aura(spellproto, eff, currentBasePoints, holder, target, caster, castItem);
|
||||||
}
|
}
|
||||||
|
|
||||||
SpellAuraHolder* CreateSpellAuraHolder(SpellEntry const* spellproto, Unit* target, WorldObject* caster, Item* castItem)
|
SpellAuraHolder* CreateSpellAuraHolder(SpellEntry const* spellproto, Unit* target, WorldObject* caster, Item* castItem /*= nullptr*/, SpellEntry const* triggeredBy /*= nullptr*/)
|
||||||
{
|
{
|
||||||
return new SpellAuraHolder(spellproto, target, caster, castItem);
|
return new SpellAuraHolder(spellproto, target, caster, castItem, triggeredBy);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Aura::SetModifier(AuraType t, int32 a, uint32 pt, int32 miscValue)
|
void Aura::SetModifier(AuraType t, int32 a, uint32 pt, int32 miscValue)
|
||||||
|
|
@ -4670,15 +4670,15 @@ void Aura::HandleAuraModStun(bool apply, bool Real)
|
||||||
target->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_STUNNED);
|
target->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_STUNNED);
|
||||||
target->CastStop(target->GetObjectGuid() == GetCasterGuid() ? GetId() : 0);
|
target->CastStop(target->GetObjectGuid() == GetCasterGuid() ? GetId() : 0);
|
||||||
|
|
||||||
// Creature specific
|
Unit* charmer = target->GetCharmer();
|
||||||
if (target->GetTypeId() != TYPEID_PLAYER)
|
if (target->GetTypeId() == TYPEID_PLAYER || (charmer && charmer->GetTypeId() == TYPEID_PLAYER))
|
||||||
{ target->StopMoving(); }
|
|
||||||
else
|
|
||||||
{
|
{
|
||||||
((Player*)target)->m_movementInfo.SetMovementFlags(MOVEFLAG_NONE);
|
target->m_movementInfo.SetMovementFlags(MOVEFLAG_NONE);
|
||||||
target->SetStandState(UNIT_STAND_STATE_STAND);// in 1.5 client
|
target->SetStandState(UNIT_STAND_STATE_STAND);// in 1.5 client
|
||||||
target->SetRoot(true);
|
target->SetRoot(true);
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
target->StopMoving();
|
||||||
|
|
||||||
// Summon the Naj'entus Spine GameObject on target if spell is Impaling Spine
|
// Summon the Naj'entus Spine GameObject on target if spell is Impaling Spine
|
||||||
if (GetId() == 39837)
|
if (GetId() == 39837)
|
||||||
|
|
@ -7594,7 +7594,10 @@ void Aura::PeriodicTick()
|
||||||
{ spell->cancel(); }
|
{ spell->cancel(); }
|
||||||
|
|
||||||
if (Player* modOwner = pCaster->GetSpellModOwner())
|
if (Player* modOwner = pCaster->GetSpellModOwner())
|
||||||
{ modOwner->ApplySpellMod(GetId(), SPELLMOD_MULTIPLE_VALUE, multiplier); }
|
{
|
||||||
|
modOwner->ApplySpellMod(GetId(), SPELLMOD_ALL_EFFECTS, new_damage);
|
||||||
|
modOwner->ApplySpellMod(GetId(), SPELLMOD_MULTIPLE_VALUE, multiplier);
|
||||||
|
}
|
||||||
|
|
||||||
int32 heal = pCaster->SpellHealingBonusTaken(pCaster, spellProto, int32(new_damage * multiplier), DOT, GetStackAmount());
|
int32 heal = pCaster->SpellHealingBonusTaken(pCaster, spellProto, int32(new_damage * multiplier), DOT, GetStackAmount());
|
||||||
|
|
||||||
|
|
@ -7602,6 +7605,9 @@ void Aura::PeriodicTick()
|
||||||
pCaster->CalculateHealAbsorb(heal, &absorbHeal);
|
pCaster->CalculateHealAbsorb(heal, &absorbHeal);
|
||||||
|
|
||||||
int32 gain = pCaster->DealHeal(pCaster, heal - absorbHeal, spellProto, false, absorbHeal);
|
int32 gain = pCaster->DealHeal(pCaster, heal - absorbHeal, spellProto, false, absorbHeal);
|
||||||
|
// Health Leech effects do not generate healing aggro
|
||||||
|
if (m_modifier.m_auraname == SPELL_AURA_PERIODIC_LEECH)
|
||||||
|
break;
|
||||||
pCaster->getHostileRefManager().threatAssist(pCaster, gain * 0.5f * sSpellMgr.GetSpellThreatMultiplier(spellProto), spellProto);
|
pCaster->getHostileRefManager().threatAssist(pCaster, gain * 0.5f * sSpellMgr.GetSpellThreatMultiplier(spellProto), spellProto);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
@ -7803,8 +7809,8 @@ void Aura::PeriodicTick()
|
||||||
drain_amount = target->GetPower(POWER_MANA) > pdamage ? pdamage : target->GetPower(POWER_MANA);
|
drain_amount = target->GetPower(POWER_MANA) > pdamage ? pdamage : target->GetPower(POWER_MANA);
|
||||||
target->ModifyPower(POWER_MANA, -drain_amount);
|
target->ModifyPower(POWER_MANA, -drain_amount);
|
||||||
|
|
||||||
SpellPeriodicAuraLogInfo pInfo(this, drain_amount, 0, 0, 0, 0.0f);
|
SpellPeriodicAuraLogInfo info(this, drain_amount, 0, 0, 0, 0.0f);
|
||||||
target->SendPeriodicAuraLog(&pInfo);
|
target->SendPeriodicAuraLog(&info);
|
||||||
}
|
}
|
||||||
// no break here
|
// no break here
|
||||||
}
|
}
|
||||||
|
|
@ -9119,8 +9125,8 @@ bool Aura::HasMechanic(uint32 mechanic) const
|
||||||
return m_spellEffect->EffectMechanic == mechanic;
|
return m_spellEffect->EffectMechanic == mechanic;
|
||||||
}
|
}
|
||||||
|
|
||||||
SpellAuraHolder::SpellAuraHolder(SpellEntry const* spellproto, Unit* target, WorldObject* caster, Item* castItem) :
|
SpellAuraHolder::SpellAuraHolder(SpellEntry const* spellproto, Unit* target, WorldObject* caster, Item* castItem, SpellEntry const* triggeredBy) :
|
||||||
m_spellProto(spellproto),
|
m_spellProto(spellproto), m_triggeredBy(triggeredBy),
|
||||||
m_target(target), m_castItemGuid(castItem ? castItem->GetObjectGuid() : ObjectGuid()),
|
m_target(target), m_castItemGuid(castItem ? castItem->GetObjectGuid() : ObjectGuid()),
|
||||||
m_auraSlot(MAX_AURAS), m_auraFlags(AFLAG_NONE), m_auraLevel(1),
|
m_auraSlot(MAX_AURAS), m_auraFlags(AFLAG_NONE), m_auraLevel(1),
|
||||||
m_procCharges(0), m_stackAmount(1),
|
m_procCharges(0), m_stackAmount(1),
|
||||||
|
|
|
||||||
|
|
@ -83,7 +83,7 @@ struct ReapplyAffectedPassiveAurasHelper;
|
||||||
class SpellAuraHolder
|
class SpellAuraHolder
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
SpellAuraHolder(SpellEntry const* spellproto, Unit* target, WorldObject* caster, Item* castItem);
|
SpellAuraHolder(SpellEntry const* spellproto, Unit* target, WorldObject* caster, Item* castItem, SpellEntry const* triggeredBy);
|
||||||
Aura* m_auras[MAX_EFFECT_INDEX];
|
Aura* m_auras[MAX_EFFECT_INDEX];
|
||||||
|
|
||||||
void AddAura(Aura* aura, SpellEffectIndex index);
|
void AddAura(Aura* aura, SpellEffectIndex index);
|
||||||
|
|
@ -104,6 +104,7 @@ class SpellAuraHolder
|
||||||
bool ModStackAmount(int32 num); // return true if last charge dropped
|
bool ModStackAmount(int32 num); // return true if last charge dropped
|
||||||
|
|
||||||
Aura* GetAuraByEffectIndex(SpellEffectIndex index) const { return m_auras[index]; }
|
Aura* GetAuraByEffectIndex(SpellEffectIndex index) const { return m_auras[index]; }
|
||||||
|
SpellEntry const* GetTriggeredBy() const { return m_triggeredBy; }
|
||||||
|
|
||||||
uint32 GetId() const { return m_spellProto->Id; }
|
uint32 GetId() const { return m_spellProto->Id; }
|
||||||
SpellEntry const* GetSpellProto() const { return m_spellProto; }
|
SpellEntry const* GetSpellProto() const { return m_spellProto; }
|
||||||
|
|
@ -206,6 +207,7 @@ class SpellAuraHolder
|
||||||
ObjectGuid m_casterGuid;
|
ObjectGuid m_casterGuid;
|
||||||
ObjectGuid m_castItemGuid; // it is NOT safe to keep a pointer to the item because it may get deleted
|
ObjectGuid m_castItemGuid; // it is NOT safe to keep a pointer to the item because it may get deleted
|
||||||
time_t m_applyTime;
|
time_t m_applyTime;
|
||||||
|
SpellEntry const* m_triggeredBy; // Spell responsible for this holder
|
||||||
|
|
||||||
uint8 m_auraSlot; // Aura slot on unit (for show in client)
|
uint8 m_auraSlot; // Aura slot on unit (for show in client)
|
||||||
uint8 m_auraFlags; // Aura info flag (for send data to client)
|
uint8 m_auraFlags; // Aura info flag (for send data to client)
|
||||||
|
|
@ -578,5 +580,5 @@ class SingleEnemyTargetAura : public Aura
|
||||||
};
|
};
|
||||||
|
|
||||||
Aura* CreateAura(SpellEntry const* spellproto, SpellEffectIndex eff, int32* currentBasePoints, SpellAuraHolder* holder, Unit* target, Unit* caster = NULL, Item* castItem = NULL);
|
Aura* CreateAura(SpellEntry const* spellproto, SpellEffectIndex eff, int32* currentBasePoints, SpellAuraHolder* holder, Unit* target, Unit* caster = NULL, Item* castItem = NULL);
|
||||||
SpellAuraHolder* CreateSpellAuraHolder(SpellEntry const* spellproto, Unit* target, WorldObject* caster, Item* castItem = NULL);
|
SpellAuraHolder* CreateSpellAuraHolder(SpellEntry const* spellproto, Unit* target, WorldObject* caster, Item* castItem = nullptr, SpellEntry const* triggeredBy = nullptr);
|
||||||
#endif
|
#endif
|
||||||
|
|
|
||||||
|
|
@ -307,7 +307,7 @@ void Spell::EffectInstaKill(SpellEffectEntry const* /*effect*/)
|
||||||
data << uint32(m_spellInfo->Id);
|
data << uint32(m_spellInfo->Id);
|
||||||
m_caster->SendMessageToSet(&data, true);
|
m_caster->SendMessageToSet(&data, true);
|
||||||
|
|
||||||
m_caster->DealDamage(unitTarget, unitTarget->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false);
|
m_caster->DealDamage(unitTarget, unitTarget->GetHealth(), nullptr, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, m_spellInfo, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Spell::EffectEnvironmentalDMG(SpellEffectEntry const* effect)
|
void Spell::EffectEnvironmentalDMG(SpellEffectEntry const* effect)
|
||||||
|
|
@ -1384,6 +1384,13 @@ void Spell::EffectDummy(SpellEffectEntry const* effect)
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
case 32027: // Expedition Flare
|
||||||
|
{
|
||||||
|
// 32029 = Expedition Preserver | 32030 = Expedition Scout
|
||||||
|
m_caster->CastSpell(m_caster, (urand(0, 1) ? 32029 : 32030), true);
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
case 32146: // Liquid Fire
|
case 32146: // Liquid Fire
|
||||||
{
|
{
|
||||||
if (!unitTarget || unitTarget->GetTypeId() != TYPEID_UNIT || m_caster->GetTypeId() != TYPEID_PLAYER)
|
if (!unitTarget || unitTarget->GetTypeId() != TYPEID_UNIT || m_caster->GetTypeId() != TYPEID_PLAYER)
|
||||||
|
|
@ -1609,7 +1616,7 @@ void Spell::EffectDummy(SpellEffectEntry const* effect)
|
||||||
unitTarget->CastSpell(m_caster, 42486, true);
|
unitTarget->CastSpell(m_caster, 42486, true);
|
||||||
|
|
||||||
// There is no known spell to kill the target
|
// There is no known spell to kill the target
|
||||||
unitTarget->DealDamage(unitTarget, unitTarget->GetHealth(), nullptr, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, nullptr, false);
|
m_caster->DealDamage(unitTarget, unitTarget->GetHealth(), nullptr, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, nullptr, false);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
case 42489: // Cast Ooze Zap When Energized
|
case 42489: // Cast Ooze Zap When Energized
|
||||||
|
|
@ -5372,6 +5379,10 @@ void Spell::EffectApplyAreaAura(SpellEffectEntry const* effect)
|
||||||
|
|
||||||
void Spell::EffectSummonType(SpellEffectEntry const* effect)
|
void Spell::EffectSummonType(SpellEffectEntry const* effect)
|
||||||
{
|
{
|
||||||
|
// if this spell already have an aura applied cancel the summon
|
||||||
|
if (m_caster->HasAura(m_spellInfo->Id))
|
||||||
|
return;
|
||||||
|
|
||||||
uint32 prop_id = effect->EffectMiscValueB;
|
uint32 prop_id = effect->EffectMiscValueB;
|
||||||
SummonPropertiesEntry const *summon_prop = sSummonPropertiesStore.LookupEntry(prop_id);
|
SummonPropertiesEntry const *summon_prop = sSummonPropertiesStore.LookupEntry(prop_id);
|
||||||
if(!summon_prop)
|
if(!summon_prop)
|
||||||
|
|
@ -5564,7 +5575,7 @@ void Spell::EffectSummonType(SpellEffectEntry const* effect)
|
||||||
if (!summonResult)
|
if (!summonResult)
|
||||||
return; // No further handling required
|
return; // No further handling required
|
||||||
|
|
||||||
for (CreatureSummonPositions::iterator itr = summonPositions.begin(); itr != summonPositions.end(); ++itr)
|
for (itr = summonPositions.begin(); itr != summonPositions.end(); ++itr)
|
||||||
{
|
{
|
||||||
MANGOS_ASSERT(itr->creature || itr != summonPositions.begin());
|
MANGOS_ASSERT(itr->creature || itr != summonPositions.begin());
|
||||||
if (!itr->creature)
|
if (!itr->creature)
|
||||||
|
|
@ -5930,21 +5941,27 @@ bool Spell::DoSummonPet(SpellEffectEntry const* effect)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32 level = m_caster->getLevel(); // TODO Engineering Pets have also caster-level? (if they exist)
|
Pet* spawnCreature = new Pet();
|
||||||
Pet* spawnCreature = new Pet(SUMMON_PET);
|
|
||||||
|
|
||||||
if (m_caster->GetTypeId() == TYPEID_PLAYER && spawnCreature->LoadPetFromDB((Player*)m_caster, pet_entry))
|
// set timer for unsummon
|
||||||
|
if (m_duration > 0)
|
||||||
|
spawnCreature->SetDuration(m_duration);
|
||||||
|
|
||||||
|
if (m_caster->GetTypeId() == TYPEID_PLAYER)
|
||||||
{
|
{
|
||||||
// Summon in dest location
|
if (spawnCreature->LoadPetFromDB((Player*)m_caster, pet_entry))
|
||||||
if (m_targets.m_targetMask & TARGET_FLAG_DEST_LOCATION)
|
{
|
||||||
spawnCreature->Relocate(m_targets.m_destX, m_targets.m_destY, m_targets.m_destZ, -m_caster->GetOrientation());
|
// Summon in dest location
|
||||||
|
if (m_targets.m_targetMask & TARGET_FLAG_DEST_LOCATION)
|
||||||
|
spawnCreature->Relocate(m_targets.m_destX, m_targets.m_destY, m_targets.m_destZ, -m_caster->GetOrientation());
|
||||||
|
|
||||||
// set timer for unsummon
|
return true;
|
||||||
if (m_duration > 0)
|
}
|
||||||
spawnCreature->SetDuration(m_duration);
|
|
||||||
|
|
||||||
return false;
|
spawnCreature->setPetType(SUMMON_PET);
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
spawnCreature->setPetType(GUARDIAN_PET);
|
||||||
|
|
||||||
// Summon in dest location
|
// Summon in dest location
|
||||||
CreatureCreatePos pos(m_caster->GetMap(), m_targets.m_destX, m_targets.m_destY, m_targets.m_destZ, -m_caster->GetOrientation(), m_caster->GetPhaseMask());
|
CreatureCreatePos pos(m_caster->GetMap(), m_targets.m_destX, m_targets.m_destY, m_targets.m_destZ, -m_caster->GetOrientation(), m_caster->GetPhaseMask());
|
||||||
|
|
@ -5961,35 +5978,27 @@ bool Spell::DoSummonPet(SpellEffectEntry const* effect)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uint32 level = std::max(m_caster->getLevel() + effect->EffectMultipleValue, 1.0f);
|
||||||
|
|
||||||
spawnCreature->SetRespawnCoord(pos);
|
spawnCreature->SetRespawnCoord(pos);
|
||||||
|
|
||||||
// set timer for unsummon
|
|
||||||
if (m_duration > 0)
|
|
||||||
spawnCreature->SetDuration(m_duration);
|
|
||||||
|
|
||||||
spawnCreature->SetOwnerGuid(m_caster->GetObjectGuid());
|
spawnCreature->SetOwnerGuid(m_caster->GetObjectGuid());
|
||||||
spawnCreature->SetUInt32Value(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_NONE);
|
|
||||||
spawnCreature->SetPowerType(POWER_MANA);
|
|
||||||
spawnCreature->setFaction(m_caster->getFaction());
|
spawnCreature->setFaction(m_caster->getFaction());
|
||||||
spawnCreature->SetUInt32Value(UNIT_FIELD_PET_NAME_TIMESTAMP, 0);
|
spawnCreature->SetUInt32Value(UNIT_FIELD_PET_NAME_TIMESTAMP, 0);
|
||||||
spawnCreature->SetUInt32Value(UNIT_FIELD_PETEXPERIENCE, 0);
|
|
||||||
spawnCreature->SetUInt32Value(UNIT_FIELD_PETNEXTLEVELEXP, 1000);
|
|
||||||
spawnCreature->SetCreatorGuid(m_caster->GetObjectGuid());
|
spawnCreature->SetCreatorGuid(m_caster->GetObjectGuid());
|
||||||
spawnCreature->SetUInt32Value(UNIT_CREATED_BY_SPELL, m_spellInfo->Id);
|
spawnCreature->SetUInt32Value(UNIT_CREATED_BY_SPELL, m_spellInfo->Id);
|
||||||
|
|
||||||
spawnCreature->InitStatsForLevel(level, m_caster);
|
spawnCreature->InitStatsForLevel(level);
|
||||||
|
|
||||||
spawnCreature->GetCharmInfo()->SetPetNumber(pet_number, false);
|
spawnCreature->GetCharmInfo()->SetPetNumber(pet_number, false);
|
||||||
|
|
||||||
spawnCreature->AIM_Initialize();
|
|
||||||
spawnCreature->InitPetCreateSpells();
|
spawnCreature->InitPetCreateSpells();
|
||||||
spawnCreature->InitLevelupSpellsForLevel();
|
spawnCreature->InitLevelupSpellsForLevel();
|
||||||
spawnCreature->SetHealth(spawnCreature->GetMaxHealth());
|
|
||||||
spawnCreature->SetPower(POWER_MANA, spawnCreature->GetMaxPower(POWER_MANA));
|
|
||||||
|
|
||||||
// spawnCreature->SetName(""); // generated by client
|
// spawnCreature->SetName(""); // generated by client
|
||||||
|
|
||||||
map->Add((Creature*)spawnCreature);
|
map->Add((Creature*)spawnCreature);
|
||||||
|
spawnCreature->AIM_Initialize();
|
||||||
|
|
||||||
m_caster->SetPet(spawnCreature);
|
m_caster->SetPet(spawnCreature);
|
||||||
|
|
||||||
|
|
@ -5999,13 +6008,25 @@ bool Spell::DoSummonPet(SpellEffectEntry const* effect)
|
||||||
spawnCreature->SavePetToDB(PET_SAVE_AS_CURRENT);
|
spawnCreature->SavePetToDB(PET_SAVE_AS_CURRENT);
|
||||||
((Player*)m_caster)->PetSpellInitialize();
|
((Player*)m_caster)->PetSpellInitialize();
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Notify Summoner
|
||||||
|
if (m_originalCaster && (m_originalCaster != m_caster)
|
||||||
|
&& (m_originalCaster->GetTypeId() == TYPEID_UNIT) && ((Creature*)m_originalCaster)->AI())
|
||||||
|
{
|
||||||
|
((Creature*)m_originalCaster)->AI()->JustSummoned(spawnCreature);
|
||||||
|
if (m_originalCaster->IsInCombat() && !(spawnCreature->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PASSIVE)))
|
||||||
|
((Creature*)spawnCreature)->AI()->AttackStart(m_originalCaster->getAttackerForHelper());
|
||||||
|
}
|
||||||
|
else if ((m_caster->GetTypeId() == TYPEID_UNIT) && ((Creature*)m_caster)->AI())
|
||||||
|
{
|
||||||
|
((Creature*)m_caster)->AI()->JustSummoned(spawnCreature);
|
||||||
|
if (m_caster->IsInCombat() && !(spawnCreature->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PASSIVE)))
|
||||||
|
((Creature*)spawnCreature)->AI()->AttackStart(m_caster->getAttackerForHelper());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (m_caster->GetTypeId() == TYPEID_UNIT && ((Creature*)m_caster)->AI())
|
return true;
|
||||||
((Creature*)m_caster)->AI()->JustSummoned((Creature*)spawnCreature);
|
|
||||||
if (m_originalCaster && m_originalCaster != m_caster && m_originalCaster->GetTypeId() == TYPEID_UNIT && ((Creature*)m_originalCaster)->AI())
|
|
||||||
((Creature*)m_originalCaster)->AI()->JustSummoned((Creature*)spawnCreature);
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Spell::DoSummonVehicle(CreatureSummonPositions& list, SummonPropertiesEntry const* prop, SpellEffectEntry const * effect, uint32 /*level*/)
|
bool Spell::DoSummonVehicle(CreatureSummonPositions& list, SummonPropertiesEntry const* prop, SpellEffectEntry const * effect, uint32 /*level*/)
|
||||||
|
|
@ -6496,7 +6517,7 @@ void Spell::EffectEnchantItemTmp(SpellEffectEntry const* effect)
|
||||||
Spell* spell = new Spell(m_caster, spellInfo, true);
|
Spell* spell = new Spell(m_caster, spellInfo, true);
|
||||||
SpellCastTargets targets;
|
SpellCastTargets targets;
|
||||||
targets.setItemTarget(itemTarget);
|
targets.setItemTarget(itemTarget);
|
||||||
spell->prepare(&targets);
|
spell->SpellStart(&targets);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -11232,6 +11253,18 @@ void Spell::EffectTransmitted(SpellEffectEntry const* effect)
|
||||||
{
|
{
|
||||||
uint32 name_id = effect->EffectMiscValue;
|
uint32 name_id = effect->EffectMiscValue;
|
||||||
|
|
||||||
|
switch (m_spellInfo->Id)
|
||||||
|
{
|
||||||
|
case 29886: // Create Soulwell
|
||||||
|
if (m_caster->HasAura(18692))
|
||||||
|
name_id = 183510;
|
||||||
|
else if (m_caster->HasAura(18693))
|
||||||
|
name_id = 183511;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
GameObjectInfo const* goinfo = ObjectMgr::GetGameObjectInfo(name_id);
|
GameObjectInfo const* goinfo = ObjectMgr::GetGameObjectInfo(name_id);
|
||||||
|
|
||||||
if (!goinfo)
|
if (!goinfo)
|
||||||
|
|
|
||||||
|
|
@ -433,7 +433,7 @@ void WorldSession::HandleCastSpellOpcode(WorldPacket& recvPacket)
|
||||||
Spell* spell = new Spell(mover, spellInfo, triggeredByAura ? true : false, mover->GetObjectGuid(), triggeredByAura ? triggeredByAura->GetSpellProto() : NULL);
|
Spell* spell = new Spell(mover, spellInfo, triggeredByAura ? true : false, mover->GetObjectGuid(), triggeredByAura ? triggeredByAura->GetSpellProto() : NULL);
|
||||||
spell->m_cast_count = cast_count; // set count of casts
|
spell->m_cast_count = cast_count; // set count of casts
|
||||||
spell->m_glyphIndex = glyphIndex;
|
spell->m_glyphIndex = glyphIndex;
|
||||||
spell->prepare(&targets, triggeredByAura);
|
spell->SpellStart(&targets, triggeredByAura);
|
||||||
}
|
}
|
||||||
|
|
||||||
void WorldSession::HandleCancelCastOpcode(WorldPacket& recvPacket)
|
void WorldSession::HandleCancelCastOpcode(WorldPacket& recvPacket)
|
||||||
|
|
|
||||||
|
|
@ -521,10 +521,10 @@ void WorldSession::HandleAcceptTradeOpcode(WorldPacket& recvPacket)
|
||||||
trader->ModifyMoney(my_trade->GetMoney());
|
trader->ModifyMoney(my_trade->GetMoney());
|
||||||
|
|
||||||
if (my_spell)
|
if (my_spell)
|
||||||
my_spell->prepare(&my_targets);
|
my_spell->SpellStart(&my_targets);
|
||||||
|
|
||||||
if (his_spell)
|
if (his_spell)
|
||||||
his_spell->prepare(&his_targets);
|
his_spell->SpellStart(&his_targets);
|
||||||
|
|
||||||
// cleanup
|
// cleanup
|
||||||
clearAcceptTradeMode(my_trade, his_trade);
|
clearAcceptTradeMode(my_trade, his_trade);
|
||||||
|
|
|
||||||
|
|
@ -358,7 +358,7 @@ bool Transport::GenerateWaypoints(uint32 pathid, std::set<uint32>& mapids)
|
||||||
newY = keyFrames[i].node->y + (keyFrames[i + 1].node->y - keyFrames[i].node->y) * d / keyFrames[i + 1].distFromPrev;
|
newY = keyFrames[i].node->y + (keyFrames[i + 1].node->y - keyFrames[i].node->y) * d / keyFrames[i + 1].distFromPrev;
|
||||||
newZ = keyFrames[i].node->z + (keyFrames[i + 1].node->z - keyFrames[i].node->z) * d / keyFrames[i + 1].distFromPrev;
|
newZ = keyFrames[i].node->z + (keyFrames[i + 1].node->z - keyFrames[i].node->z) * d / keyFrames[i + 1].distFromPrev;
|
||||||
|
|
||||||
bool teleport = false;
|
teleport = false;
|
||||||
if (keyFrames[i].node->mapid != cM)
|
if (keyFrames[i].node->mapid != cM)
|
||||||
{
|
{
|
||||||
teleport = true;
|
teleport = true;
|
||||||
|
|
@ -366,7 +366,7 @@ bool Transport::GenerateWaypoints(uint32 pathid, std::set<uint32>& mapids)
|
||||||
}
|
}
|
||||||
|
|
||||||
// sLog.outString("T: %d, D: %f, x: %f, y: %f, z: %f", t, d, newX, newY, newZ);
|
// sLog.outString("T: %d, D: %f, x: %f, y: %f, z: %f", t, d, newX, newY, newZ);
|
||||||
WayPoint pos(keyFrames[i].node->mapid, newX, newY, newZ, teleport);
|
pos = WayPoint(keyFrames[i].node->mapid, newX, newY, newZ, teleport);
|
||||||
if (teleport)
|
if (teleport)
|
||||||
m_WayPoints[t] = pos;
|
m_WayPoints[t] = pos;
|
||||||
}
|
}
|
||||||
|
|
@ -412,7 +412,7 @@ bool Transport::GenerateWaypoints(uint32 pathid, std::set<uint32>& mapids)
|
||||||
cM = keyFrames[i + 1].node->mapid;
|
cM = keyFrames[i + 1].node->mapid;
|
||||||
}
|
}
|
||||||
|
|
||||||
WayPoint pos(keyFrames[i + 1].node->mapid, keyFrames[i + 1].node->x, keyFrames[i + 1].node->y, keyFrames[i + 1].node->z, teleport,
|
pos = WayPoint(keyFrames[i + 1].node->mapid, keyFrames[i + 1].node->x, keyFrames[i + 1].node->y, keyFrames[i + 1].node->z, teleport,
|
||||||
keyFrames[i + 1].node->arrivalEventID, keyFrames[i + 1].node->departureEventID);
|
keyFrames[i + 1].node->arrivalEventID, keyFrames[i + 1].node->departureEventID);
|
||||||
|
|
||||||
// sLog.outString("T: %d, x: %f, y: %f, z: %f, t:%d", t, pos.x, pos.y, pos.z, teleport);
|
// sLog.outString("T: %d, x: %f, y: %f, z: %f, t:%d", t, pos.x, pos.y, pos.z, teleport);
|
||||||
|
|
|
||||||
|
|
@ -3109,10 +3109,10 @@ SpellAuraProcResult Unit::HandleProcTriggerSpellAuraProc(Unit* pVictim, uint32 d
|
||||||
}
|
}
|
||||||
case 69023: // Mirrored Soul
|
case 69023: // Mirrored Soul
|
||||||
{
|
{
|
||||||
int32 basepoints = (int32)(damage * 0.45f);
|
int32 basepoints2 = (int32)(damage * 0.45f);
|
||||||
if (Unit* caster = triggeredByAura->GetCaster())
|
if (Unit* caster = triggeredByAura->GetCaster())
|
||||||
// Actually this spell should be sent with SMSG_SPELL_START
|
// Actually this spell should be sent with SMSG_SPELL_START
|
||||||
CastCustomSpell(caster, 69034, &basepoints, nullptr, nullptr, true, nullptr, triggeredByAura, GetObjectGuid());
|
CastCustomSpell(caster, 69034, &basepoints2, nullptr, nullptr, true, nullptr, triggeredByAura, GetObjectGuid());
|
||||||
|
|
||||||
return SPELL_AURA_PROC_OK;
|
return SPELL_AURA_PROC_OK;
|
||||||
}
|
}
|
||||||
|
|
@ -3212,8 +3212,8 @@ SpellAuraProcResult Unit::HandleProcTriggerSpellAuraProc(Unit* pVictim, uint32 d
|
||||||
if ((*i)->GetSpellProto()->GetSpellFamilyName() == SPELLFAMILY_WARLOCK && (*i)->GetSpellProto()->SpellIconID == 113)
|
if ((*i)->GetSpellProto()->GetSpellFamilyName() == SPELLFAMILY_WARLOCK && (*i)->GetSpellProto()->SpellIconID == 113)
|
||||||
{
|
{
|
||||||
// basepoints of trigger spell stored in dummyeffect of spellProto
|
// basepoints of trigger spell stored in dummyeffect of spellProto
|
||||||
int32 basepoints = GetMaxPower(POWER_MANA) * (*i)->GetSpellProto()->CalculateSimpleValue(EFFECT_INDEX_2) / 100;
|
int32 basepoints2 = GetMaxPower(POWER_MANA) * (*i)->GetSpellProto()->CalculateSimpleValue(EFFECT_INDEX_2) / 100;
|
||||||
CastCustomSpell(this, 18371, &basepoints, nullptr, nullptr, true, castItem, triggeredByAura);
|
CastCustomSpell(this, 18371, &basepoints2, nullptr, nullptr, true, castItem, triggeredByAura);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -252,8 +252,6 @@ World::AddSession_(WorldSession* s)
|
||||||
// prevent decrease sessions count if session queued
|
// prevent decrease sessions count if session queued
|
||||||
if (RemoveQueuedSession(old->second))
|
if (RemoveQueuedSession(old->second))
|
||||||
{ decrease_session = false; }
|
{ decrease_session = false; }
|
||||||
// not remove replaced session form queue if listed
|
|
||||||
delete old->second;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -468,6 +466,7 @@ void World::LoadConfigSettings(bool reload)
|
||||||
setConfigPos(CONFIG_FLOAT_RATE_DROP_ITEM_LEGENDARY, "Rate.Drop.Item.Legendary", 1.0f);
|
setConfigPos(CONFIG_FLOAT_RATE_DROP_ITEM_LEGENDARY, "Rate.Drop.Item.Legendary", 1.0f);
|
||||||
setConfigPos(CONFIG_FLOAT_RATE_DROP_ITEM_ARTIFACT, "Rate.Drop.Item.Artifact", 1.0f);
|
setConfigPos(CONFIG_FLOAT_RATE_DROP_ITEM_ARTIFACT, "Rate.Drop.Item.Artifact", 1.0f);
|
||||||
setConfigPos(CONFIG_FLOAT_RATE_DROP_ITEM_REFERENCED, "Rate.Drop.Item.Referenced", 1.0f);
|
setConfigPos(CONFIG_FLOAT_RATE_DROP_ITEM_REFERENCED, "Rate.Drop.Item.Referenced", 1.0f);
|
||||||
|
setConfigPos(CONFIG_FLOAT_RATE_DROP_ITEM_QUEST, "Rate.Drop.Item.Quest", 1.0f);
|
||||||
setConfigPos(CONFIG_FLOAT_RATE_DROP_MONEY, "Rate.Drop.Money", 1.0f);
|
setConfigPos(CONFIG_FLOAT_RATE_DROP_MONEY, "Rate.Drop.Money", 1.0f);
|
||||||
setConfigPos(CONFIG_FLOAT_RATE_DROP_CURRENCY, "Rate.Drop.Currency", 1.0f);
|
setConfigPos(CONFIG_FLOAT_RATE_DROP_CURRENCY, "Rate.Drop.Currency", 1.0f);
|
||||||
setConfigPos(CONFIG_FLOAT_RATE_DROP_CURRENCY_AMOUNT, "Rate.Drop.Currency.Amount", 1.0f);
|
setConfigPos(CONFIG_FLOAT_RATE_DROP_CURRENCY_AMOUNT, "Rate.Drop.Currency.Amount", 1.0f);
|
||||||
|
|
|
||||||
|
|
@ -263,6 +263,7 @@ enum eConfigFloatValues
|
||||||
CONFIG_FLOAT_RATE_DROP_ITEM_LEGENDARY,
|
CONFIG_FLOAT_RATE_DROP_ITEM_LEGENDARY,
|
||||||
CONFIG_FLOAT_RATE_DROP_ITEM_ARTIFACT,
|
CONFIG_FLOAT_RATE_DROP_ITEM_ARTIFACT,
|
||||||
CONFIG_FLOAT_RATE_DROP_ITEM_REFERENCED,
|
CONFIG_FLOAT_RATE_DROP_ITEM_REFERENCED,
|
||||||
|
CONFIG_FLOAT_RATE_DROP_ITEM_QUEST,
|
||||||
CONFIG_FLOAT_RATE_DROP_MONEY,
|
CONFIG_FLOAT_RATE_DROP_MONEY,
|
||||||
CONFIG_FLOAT_RATE_DROP_CURRENCY,
|
CONFIG_FLOAT_RATE_DROP_CURRENCY,
|
||||||
CONFIG_FLOAT_RATE_DROP_CURRENCY_AMOUNT,
|
CONFIG_FLOAT_RATE_DROP_CURRENCY_AMOUNT,
|
||||||
|
|
|
||||||
|
|
@ -1272,6 +1272,7 @@ Visibility.AIRelocationNotifyDelay = 1000
|
||||||
# Rate.Drop.Item.Legendary
|
# Rate.Drop.Item.Legendary
|
||||||
# Rate.Drop.Item.Artifact
|
# Rate.Drop.Item.Artifact
|
||||||
# Rate.Drop.Item.Referenced
|
# Rate.Drop.Item.Referenced
|
||||||
|
# Rate.Drop.Item.Quest
|
||||||
# Rate.Drop.Money
|
# Rate.Drop.Money
|
||||||
# Rate.Drop.Currency
|
# Rate.Drop.Currency
|
||||||
# Drop rates (items by quality, money and currency drop chance)
|
# Drop rates (items by quality, money and currency drop chance)
|
||||||
|
|
@ -1423,6 +1424,7 @@ Rate.Drop.Item.Epic = 1
|
||||||
Rate.Drop.Item.Legendary = 1
|
Rate.Drop.Item.Legendary = 1
|
||||||
Rate.Drop.Item.Artifact = 1
|
Rate.Drop.Item.Artifact = 1
|
||||||
Rate.Drop.Item.Referenced = 1
|
Rate.Drop.Item.Referenced = 1
|
||||||
|
Rate.Drop.Item.Quest = 1
|
||||||
Rate.Drop.Money = 1
|
Rate.Drop.Money = 1
|
||||||
Rate.Drop.Currency = 1
|
Rate.Drop.Currency = 1
|
||||||
Rate.Drop.Currency.Amount = 1
|
Rate.Drop.Currency.Amount = 1
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue