mirror of
https://github.com/mangosfour/server.git
synced 2025-12-22 13:37:08 +00:00
Merge commit 'origin/master' into 320
Conflicts: src/game/Player.cpp src/game/Totem.cpp
This commit is contained in:
commit
4c709772c1
61 changed files with 912 additions and 454 deletions
|
|
@ -1297,7 +1297,7 @@ void AchievementMgr::UpdateAchievementCriteria(AchievementCriteriaTypes type, ui
|
|||
if(IsCompletedCriteria(achievementCriteria,achievement))
|
||||
CompletedCriteriaFor(achievement);
|
||||
|
||||
// check again the completeness for SUMM and REQ COUNT achievements,
|
||||
// check again the completeness for SUMM and REQ COUNT achievements,
|
||||
// as they don't depend on the completed criteria but on the sum of the progress of each individual criteria
|
||||
if (achievement->flags & ACHIEVEMENT_FLAG_SUMM)
|
||||
{
|
||||
|
|
@ -1513,7 +1513,7 @@ bool AchievementMgr::IsCompletedAchievement(AchievementEntry const* entry)
|
|||
return false;
|
||||
}
|
||||
|
||||
// Default case - need complete all or
|
||||
// Default case - need complete all or
|
||||
bool completed_all = true;
|
||||
for(AchievementCriteriaEntryList::const_iterator itr = cList->begin(); itr != cList->end(); ++itr)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -1819,6 +1819,10 @@ bool Creature::CanAssistTo(const Unit* u, const Unit* enemy, bool checkfaction /
|
|||
if (!isAlive())
|
||||
return false;
|
||||
|
||||
// we don't need help from non-combatant ;)
|
||||
if (isCivilian())
|
||||
return false;
|
||||
|
||||
// skip fighting creature
|
||||
if (isInCombat())
|
||||
return false;
|
||||
|
|
|
|||
|
|
@ -92,7 +92,7 @@ class MANGOS_DLL_SPEC CreatureAI
|
|||
// Called at waypoint reached or point movement finished
|
||||
virtual void MovementInform(uint32 /*MovementType*/, uint32 /*Data*/) {}
|
||||
|
||||
// Called at text emote receive from player
|
||||
// Called at text emote receive from player
|
||||
virtual void ReceiveEmote(Player* /*pPlayer*/, uint32 /*text_emote*/) {}
|
||||
|
||||
///== Triggered Actions Requested ==================
|
||||
|
|
|
|||
|
|
@ -661,7 +661,7 @@ struct CinematicCameraEntry
|
|||
float start_x; // 3
|
||||
float start_y; // 4
|
||||
float start_z; // 5
|
||||
float unk6; // 6 speed?
|
||||
float unk6; // 6 speed?
|
||||
};
|
||||
*/
|
||||
|
||||
|
|
|
|||
|
|
@ -50,7 +50,6 @@ GameObject::GameObject() : WorldObject()
|
|||
m_spawnedByDefault = true;
|
||||
m_usetimes = 0;
|
||||
m_spellId = 0;
|
||||
m_charges = 5;
|
||||
m_cooldownTime = 0;
|
||||
m_goInfo = NULL;
|
||||
|
||||
|
|
@ -156,10 +155,6 @@ bool GameObject::Create(uint32 guidlow, uint32 name_id, Map *map, uint32 phaseMa
|
|||
|
||||
SetGoAnimProgress(animprogress);
|
||||
|
||||
// Spell charges for GAMEOBJECT_TYPE_SPELLCASTER (22)
|
||||
if (goinfo->type == GAMEOBJECT_TYPE_SPELLCASTER)
|
||||
m_charges = goinfo->spellcaster.charges;
|
||||
|
||||
//Notify the map's instance data.
|
||||
//Only works if you create the object in it, not if it is moves to that map.
|
||||
//Normally non-players do not teleport to other maps.
|
||||
|
|
@ -282,99 +277,107 @@ void GameObject::Update(uint32 /*p_time*/)
|
|||
}
|
||||
}
|
||||
|
||||
// traps can have time and can not have
|
||||
GameObjectInfo const* goInfo = GetGOInfo();
|
||||
if(goInfo->type == GAMEOBJECT_TYPE_TRAP)
|
||||
if(isSpawned())
|
||||
{
|
||||
// traps
|
||||
Unit* owner = GetOwner();
|
||||
Unit* ok = NULL; // pointer to appropriate target if found any
|
||||
|
||||
if(m_cooldownTime >= time(NULL))
|
||||
return;
|
||||
|
||||
bool IsBattleGroundTrap = false;
|
||||
//FIXME: this is activation radius (in different casting radius that must be selected from spell data)
|
||||
//TODO: move activated state code (cast itself) to GO_ACTIVATED, in this place only check activating and set state
|
||||
float radius = goInfo->trap.radius;
|
||||
if(!radius)
|
||||
// traps can have time and can not have
|
||||
GameObjectInfo const* goInfo = GetGOInfo();
|
||||
if(goInfo->type == GAMEOBJECT_TYPE_TRAP)
|
||||
{
|
||||
if(goInfo->trap.cooldown != 3) // cast in other case (at some triggering/linked go/etc explicit call)
|
||||
if(m_cooldownTime >= time(NULL))
|
||||
return;
|
||||
else
|
||||
{
|
||||
if(m_respawnTime > 0)
|
||||
break;
|
||||
|
||||
radius = goInfo->trap.cooldown; // battlegrounds gameobjects has data2 == 0 && data5 == 3
|
||||
IsBattleGroundTrap = true;
|
||||
// traps
|
||||
Unit* owner = GetOwner();
|
||||
Unit* ok = NULL; // pointer to appropriate target if found any
|
||||
|
||||
bool IsBattleGroundTrap = false;
|
||||
//FIXME: this is activation radius (in different casting radius that must be selected from spell data)
|
||||
//TODO: move activated state code (cast itself) to GO_ACTIVATED, in this place only check activating and set state
|
||||
float radius = goInfo->trap.radius;
|
||||
if(!radius)
|
||||
{
|
||||
if(goInfo->trap.cooldown != 3) // cast in other case (at some triggering/linked go/etc explicit call)
|
||||
return;
|
||||
else
|
||||
{
|
||||
if(m_respawnTime > 0)
|
||||
break;
|
||||
|
||||
radius = goInfo->trap.cooldown; // battlegrounds gameobjects has data2 == 0 && data5 == 3
|
||||
IsBattleGroundTrap = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool NeedDespawn = (goInfo->trap.charges != 0);
|
||||
CellPair p(MaNGOS::ComputeCellPair(GetPositionX(),GetPositionY()));
|
||||
Cell cell(p);
|
||||
cell.data.Part.reserved = ALL_DISTRICT;
|
||||
|
||||
CellPair p(MaNGOS::ComputeCellPair(GetPositionX(),GetPositionY()));
|
||||
Cell cell(p);
|
||||
cell.data.Part.reserved = ALL_DISTRICT;
|
||||
|
||||
// Note: this hack with search required until GO casting not implemented
|
||||
// search unfriendly creature
|
||||
if(owner && NeedDespawn) // hunter trap
|
||||
{
|
||||
MaNGOS::AnyUnfriendlyUnitInObjectRangeCheck u_check(this, owner, radius);
|
||||
MaNGOS::UnitSearcher<MaNGOS::AnyUnfriendlyUnitInObjectRangeCheck> checker(this,ok, u_check);
|
||||
|
||||
CellLock<GridReadGuard> cell_lock(cell, p);
|
||||
|
||||
TypeContainerVisitor<MaNGOS::UnitSearcher<MaNGOS::AnyUnfriendlyUnitInObjectRangeCheck>, GridTypeMapContainer > grid_object_checker(checker);
|
||||
cell_lock->Visit(cell_lock, grid_object_checker, *GetMap());
|
||||
|
||||
// or unfriendly player/pet
|
||||
if(!ok)
|
||||
// Note: this hack with search required until GO casting not implemented
|
||||
// search unfriendly creature
|
||||
if(owner && goInfo->trap.charges > 0) // hunter trap
|
||||
{
|
||||
TypeContainerVisitor<MaNGOS::UnitSearcher<MaNGOS::AnyUnfriendlyUnitInObjectRangeCheck>, WorldTypeMapContainer > world_object_checker(checker);
|
||||
MaNGOS::AnyUnfriendlyUnitInObjectRangeCheck u_check(this, owner, radius);
|
||||
MaNGOS::UnitSearcher<MaNGOS::AnyUnfriendlyUnitInObjectRangeCheck> checker(this,ok, u_check);
|
||||
|
||||
CellLock<GridReadGuard> cell_lock(cell, p);
|
||||
|
||||
TypeContainerVisitor<MaNGOS::UnitSearcher<MaNGOS::AnyUnfriendlyUnitInObjectRangeCheck>, GridTypeMapContainer > grid_object_checker(checker);
|
||||
cell_lock->Visit(cell_lock, grid_object_checker, *GetMap());
|
||||
|
||||
// or unfriendly player/pet
|
||||
if(!ok)
|
||||
{
|
||||
TypeContainerVisitor<MaNGOS::UnitSearcher<MaNGOS::AnyUnfriendlyUnitInObjectRangeCheck>, WorldTypeMapContainer > world_object_checker(checker);
|
||||
cell_lock->Visit(cell_lock, world_object_checker, *GetMap());
|
||||
}
|
||||
}
|
||||
else // environmental trap
|
||||
{
|
||||
// environmental damage spells already have around enemies targeting but this not help in case not existed GO casting support
|
||||
|
||||
// affect only players
|
||||
Player* p_ok = NULL;
|
||||
MaNGOS::AnyPlayerInObjectRangeCheck p_check(this, radius);
|
||||
MaNGOS::PlayerSearcher<MaNGOS::AnyPlayerInObjectRangeCheck> checker(this,p_ok, p_check);
|
||||
|
||||
CellLock<GridReadGuard> cell_lock(cell, p);
|
||||
|
||||
TypeContainerVisitor<MaNGOS::PlayerSearcher<MaNGOS::AnyPlayerInObjectRangeCheck>, WorldTypeMapContainer > world_object_checker(checker);
|
||||
cell_lock->Visit(cell_lock, world_object_checker, *GetMap());
|
||||
ok = p_ok;
|
||||
}
|
||||
|
||||
if (ok)
|
||||
{
|
||||
Unit *caster = owner ? owner : ok;
|
||||
|
||||
caster->CastSpell(ok, goInfo->trap.spellId, true, 0, 0, GetGUID());
|
||||
m_cooldownTime = time(NULL) + 4; // 4 seconds
|
||||
|
||||
// count charges
|
||||
if(goInfo->trap.charges > 0)
|
||||
AddUse();
|
||||
|
||||
if(IsBattleGroundTrap && ok->GetTypeId() == TYPEID_PLAYER)
|
||||
{
|
||||
//BattleGround gameobjects case
|
||||
if(((Player*)ok)->InBattleGround())
|
||||
if(BattleGround *bg = ((Player*)ok)->GetBattleGround())
|
||||
bg->HandleTriggerBuff(GetGUID());
|
||||
}
|
||||
}
|
||||
}
|
||||
else // environmental trap
|
||||
|
||||
if(uint32 max_charges = goInfo->GetCharges())
|
||||
{
|
||||
// environmental damage spells already have around enemies targeting but this not help in case not existed GO casting support
|
||||
|
||||
// affect only players
|
||||
Player* p_ok = NULL;
|
||||
MaNGOS::AnyPlayerInObjectRangeCheck p_check(this, radius);
|
||||
MaNGOS::PlayerSearcher<MaNGOS::AnyPlayerInObjectRangeCheck> checker(this,p_ok, p_check);
|
||||
|
||||
CellLock<GridReadGuard> cell_lock(cell, p);
|
||||
|
||||
TypeContainerVisitor<MaNGOS::PlayerSearcher<MaNGOS::AnyPlayerInObjectRangeCheck>, WorldTypeMapContainer > world_object_checker(checker);
|
||||
cell_lock->Visit(cell_lock, world_object_checker, *GetMap());
|
||||
ok = p_ok;
|
||||
}
|
||||
|
||||
if (ok)
|
||||
{
|
||||
Unit *caster = owner ? owner : ok;
|
||||
|
||||
caster->CastSpell(ok, goInfo->trap.spellId, true, 0, 0, GetGUID());
|
||||
m_cooldownTime = time(NULL) + 4; // 4 seconds
|
||||
|
||||
if(NeedDespawn)
|
||||
SetLootState(GO_JUST_DEACTIVATED); // can be despawned or destroyed
|
||||
|
||||
if(IsBattleGroundTrap && ok->GetTypeId() == TYPEID_PLAYER)
|
||||
if (m_usetimes >= max_charges)
|
||||
{
|
||||
//BattleGround gameobjects case
|
||||
if(((Player*)ok)->InBattleGround())
|
||||
if(BattleGround *bg = ((Player*)ok)->GetBattleGround())
|
||||
bg->HandleTriggerBuff(GetGUID());
|
||||
m_usetimes = 0;
|
||||
SetLootState(GO_JUST_DEACTIVATED); // can be despawned or destroyed
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (m_charges && m_usetimes >= m_charges)
|
||||
SetLootState(GO_JUST_DEACTIVATED); // can be despawned or destroyed
|
||||
|
||||
break;
|
||||
}
|
||||
case GO_ACTIVATED:
|
||||
|
|
|
|||
|
|
@ -442,6 +442,17 @@ struct GameObjectInfo
|
|||
}
|
||||
}
|
||||
|
||||
uint32 GetCharges() const // despawn at uses amount
|
||||
{
|
||||
switch(type)
|
||||
{
|
||||
case GAMEOBJECT_TYPE_TRAP: return trap.charges;
|
||||
case GAMEOBJECT_TYPE_GUARDPOST: return guardpost.charges;
|
||||
case GAMEOBJECT_TYPE_SPELLCASTER: return spellcaster.charges;
|
||||
default: return 0;
|
||||
}
|
||||
}
|
||||
|
||||
uint32 GetLinkedGameObjectEntry() const
|
||||
{
|
||||
switch(type)
|
||||
|
|
@ -663,7 +674,6 @@ class MANGOS_DLL_SPEC GameObject : public WorldObject
|
|||
bool isActiveObject() const { return false; }
|
||||
uint64 GetRotation() const { return m_rotation; }
|
||||
protected:
|
||||
uint32 m_charges; // Spell charges for GAMEOBJECT_TYPE_SPELLCASTER (22)
|
||||
uint32 m_spellId;
|
||||
time_t m_respawnTime; // (secs) time of next respawn (or despawn if GO have owner()),
|
||||
uint32 m_respawnDelayTime; // (secs) if 0 then current GO state no dependent from timer
|
||||
|
|
|
|||
|
|
@ -695,40 +695,40 @@ void Guild::Roster(WorldSession *session)
|
|||
data << (uint32)m_ranks.size();
|
||||
for (RankList::const_iterator ritr = m_ranks.begin(); ritr != m_ranks.end(); ++ritr)
|
||||
{
|
||||
data << (uint32)ritr->rights;
|
||||
data << (uint32)ritr->BankMoneyPerDay; // count of: withdraw gold(gold/day) Note: in game set gold, in packet set bronze.
|
||||
data << uint32(ritr->rights);
|
||||
data << uint32(ritr->BankMoneyPerDay); // count of: withdraw gold(gold/day) Note: in game set gold, in packet set bronze.
|
||||
for (int i = 0; i < GUILD_BANK_MAX_TABS; ++i)
|
||||
{
|
||||
data << (uint32)ritr->TabRight[i]; // for TAB_i rights: view tabs = 0x01, deposit items =0x02
|
||||
data << (uint32)ritr->TabSlotPerDay[i]; // for TAB_i count of: withdraw items(stack/day)
|
||||
data << uint32(ritr->TabRight[i]); // for TAB_i rights: view tabs = 0x01, deposit items =0x02
|
||||
data << uint32(ritr->TabSlotPerDay[i]); // for TAB_i count of: withdraw items(stack/day)
|
||||
}
|
||||
}
|
||||
for (MemberList::const_iterator itr = members.begin(); itr != members.end(); ++itr)
|
||||
{
|
||||
if (Player *pl = ObjectAccessor::FindPlayer(MAKE_NEW_GUID(itr->first, 0, HIGHGUID_PLAYER)))
|
||||
{
|
||||
data << (uint64)pl->GetGUID();
|
||||
data << (uint8)1;
|
||||
data << (std::string)pl->GetName();
|
||||
data << (uint32)itr->second.RankId;
|
||||
data << (uint8)pl->getLevel();
|
||||
data << (uint8)pl->getClass();
|
||||
data << (uint8)0; // new 2.4.0
|
||||
data << (uint32)pl->GetZoneId();
|
||||
data << uint64(pl->GetGUID());
|
||||
data << uint8(1);
|
||||
data << pl->GetName();
|
||||
data << uint32(itr->second.RankId);
|
||||
data << uint8(pl->getLevel());
|
||||
data << uint8(pl->getClass());
|
||||
data << uint8(0); // new 2.4.0
|
||||
data << uint32(pl->GetZoneId());
|
||||
data << itr->second.Pnote;
|
||||
data << itr->second.OFFnote;
|
||||
}
|
||||
else
|
||||
{
|
||||
data << uint64(MAKE_NEW_GUID(itr->first, 0, HIGHGUID_PLAYER));
|
||||
data << (uint8)0;
|
||||
data << uint8(0);
|
||||
data << itr->second.name;
|
||||
data << (uint32)itr->second.RankId;
|
||||
data << (uint8)itr->second.level;
|
||||
data << (uint8)itr->second.Class;
|
||||
data << (uint8)0; // new 2.4.0
|
||||
data << (uint32)itr->second.zoneId;
|
||||
data << (float(time(NULL)-itr->second.logout_time) / DAY);
|
||||
data << uint32(itr->second.RankId);
|
||||
data << uint8(itr->second.level);
|
||||
data << uint8(itr->second.Class);
|
||||
data << uint8(0); // new 2.4.0
|
||||
data << uint32(itr->second.zoneId);
|
||||
data << float(float(time(NULL)-itr->second.logout_time) / DAY);
|
||||
data << itr->second.Pnote;
|
||||
data << itr->second.OFFnote;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4362,6 +4362,8 @@ bool ChatHandler::HandleResetLevelCommand(const char * args)
|
|||
? sWorld.getConfig(CONFIG_START_PLAYER_LEVEL)
|
||||
: sWorld.getConfig(CONFIG_START_HEROIC_PLAYER_LEVEL);
|
||||
|
||||
target->_ApplyAllLevelScaleItemMods(false);
|
||||
|
||||
target->SetLevel(start_level);
|
||||
target->InitRunes();
|
||||
target->InitStatsForLevel(true);
|
||||
|
|
@ -4370,6 +4372,8 @@ bool ChatHandler::HandleResetLevelCommand(const char * args)
|
|||
target->InitTalentForLevel();
|
||||
target->SetUInt32Value(PLAYER_XP,0);
|
||||
|
||||
target->_ApplyAllLevelScaleItemMods(true);
|
||||
|
||||
// reset level for pet
|
||||
if(Pet* pet = target->GetPet())
|
||||
pet->SynchronizeLevelWithOwner();
|
||||
|
|
|
|||
|
|
@ -1423,7 +1423,7 @@ void WorldSession::HandleSetTitleOpcode( WorldPacket & recv_data )
|
|||
recv_data >> title;
|
||||
|
||||
// -1 at none
|
||||
if(title > 0 && title < 192)
|
||||
if(title > 0 && title < MAX_TITLE_INDEX)
|
||||
{
|
||||
if(!GetPlayer()->HasTitle(title))
|
||||
return;
|
||||
|
|
|
|||
|
|
@ -586,6 +586,7 @@ void Object::_BuildValuesUpdate(uint8 updatetype, ByteBuffer * data, UpdateMask
|
|||
return;
|
||||
|
||||
bool IsActivateToQuest = false;
|
||||
bool IsPerCasterAuraState = false;
|
||||
if (updatetype == UPDATETYPE_CREATE_OBJECT || updatetype == UPDATETYPE_CREATE_OBJECT2)
|
||||
{
|
||||
if (isType(TYPEMASK_GAMEOBJECT) && !((GameObject*)this)->IsTransport())
|
||||
|
|
@ -596,6 +597,14 @@ void Object::_BuildValuesUpdate(uint8 updatetype, ByteBuffer * data, UpdateMask
|
|||
updateMask->SetBit(GAMEOBJECT_DYNAMIC);
|
||||
}
|
||||
}
|
||||
else if (isType(TYPEMASK_UNIT))
|
||||
{
|
||||
if( ((Unit*)this)->HasAuraState(AURA_STATE_CONFLAGRATE))
|
||||
{
|
||||
IsPerCasterAuraState = true;
|
||||
updateMask->SetBit(UNIT_FIELD_AURASTATE);
|
||||
}
|
||||
}
|
||||
}
|
||||
else // case UPDATETYPE_VALUES
|
||||
{
|
||||
|
|
@ -608,6 +617,14 @@ void Object::_BuildValuesUpdate(uint8 updatetype, ByteBuffer * data, UpdateMask
|
|||
updateMask->SetBit(GAMEOBJECT_DYNAMIC);
|
||||
updateMask->SetBit(GAMEOBJECT_BYTES_1);
|
||||
}
|
||||
else if (isType(TYPEMASK_UNIT))
|
||||
{
|
||||
if( ((Unit*)this)->HasAuraState(AURA_STATE_CONFLAGRATE))
|
||||
{
|
||||
IsPerCasterAuraState = true;
|
||||
updateMask->SetBit(UNIT_FIELD_AURASTATE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
WPAssert(updateMask && updateMask->GetCount() == m_valuesCount);
|
||||
|
|
@ -632,6 +649,19 @@ void Object::_BuildValuesUpdate(uint8 updatetype, ByteBuffer * data, UpdateMask
|
|||
|
||||
*data << uint32(appendValue);
|
||||
}
|
||||
else if (index == UNIT_FIELD_AURASTATE)
|
||||
{
|
||||
if(IsPerCasterAuraState)
|
||||
{
|
||||
// IsPerCasterAuraState set if related pet caster aura state set already
|
||||
if (((Unit*)this)->HasAuraStateForCaster(AURA_STATE_CONFLAGRATE,target->GetGUID()))
|
||||
*data << m_uint32Values[ index ];
|
||||
else
|
||||
*data << (m_uint32Values[ index ] & ~(1 << (AURA_STATE_CONFLAGRATE-1)));
|
||||
}
|
||||
else
|
||||
*data << m_uint32Values[ index ];
|
||||
}
|
||||
// FIXME: Some values at server stored in float format but must be sent to client in uint32 format
|
||||
else if(index >= UNIT_FIELD_BASEATTACKTIME && index <= UNIT_FIELD_RANGEDATTACKTIME)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -572,7 +572,7 @@ void ObjectMgr::LoadCreatureTemplates()
|
|||
|
||||
// used later for scale
|
||||
CreatureDisplayInfoEntry const* displayScaleEntry = NULL;
|
||||
|
||||
|
||||
if (cInfo->DisplayID_A[0])
|
||||
{
|
||||
CreatureDisplayInfoEntry const* displayEntry = sCreatureDisplayInfoStore.LookupEntry(cInfo->DisplayID_A[0]);
|
||||
|
|
@ -6685,7 +6685,7 @@ uint8 ObjectMgr::CheckPlayerName( const std::string& name, bool create )
|
|||
uint32 strictMask = sWorld.getConfig(CONFIG_STRICT_PLAYER_NAMES);
|
||||
if(!isValidString(wname,strictMask,false,create))
|
||||
return CHAR_NAME_MIXED_LANGUAGES;
|
||||
|
||||
|
||||
return CHAR_NAME_SUCCESS;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -236,7 +236,7 @@ enum ConditionType
|
|||
CONDITION_SKILL = 7, // skill_id skill_value
|
||||
CONDITION_QUESTREWARDED = 8, // quest_id 0
|
||||
CONDITION_QUESTTAKEN = 9, // quest_id 0, for condition true while quest active.
|
||||
CONDITION_AD_COMMISSION_AURA = 10, // 0 0, for condition true while one from AD ñommission aura active
|
||||
CONDITION_AD_COMMISSION_AURA = 10, // 0 0, for condition true while one from AD commission aura active
|
||||
CONDITION_NO_AURA = 11, // spell_id effindex
|
||||
CONDITION_ACTIVE_EVENT = 12, // event_id
|
||||
};
|
||||
|
|
|
|||
|
|
@ -146,7 +146,7 @@ bool Pet::LoadPetFromDB( Player* owner, uint32 petentry, uint32 petnumber, bool
|
|||
}
|
||||
|
||||
uint32 pet_number = fields[0].GetUInt32();
|
||||
|
||||
|
||||
if (current && owner->IsPetNeedBeTemporaryUnsummoned())
|
||||
{
|
||||
owner->SetTemporaryUnsummonedPetNumber(pet_number);
|
||||
|
|
|
|||
|
|
@ -612,8 +612,8 @@ bool Player::Create( uint32 guidlow, const std::string& name, uint8 race, uint8
|
|||
|
||||
// Played time
|
||||
m_Last_tick = time(NULL);
|
||||
m_Played_time[0] = 0;
|
||||
m_Played_time[1] = 0;
|
||||
m_Played_time[PLAYED_TIME_TOTAL] = 0;
|
||||
m_Played_time[PLAYED_TIME_LEVEL] = 0;
|
||||
|
||||
// base stats and related field values
|
||||
InitStatsForLevel();
|
||||
|
|
@ -1286,8 +1286,8 @@ void Player::Update( uint32 p_time )
|
|||
if (now > m_Last_tick)
|
||||
{
|
||||
uint32 elapsed = uint32(now - m_Last_tick);
|
||||
m_Played_time[0] += elapsed; // Total played time
|
||||
m_Played_time[1] += elapsed; // Level played time
|
||||
m_Played_time[PLAYED_TIME_TOTAL] += elapsed; // Total played time
|
||||
m_Played_time[PLAYED_TIME_LEVEL] += elapsed; // Level played time
|
||||
m_Last_tick = now;
|
||||
}
|
||||
|
||||
|
|
@ -2378,9 +2378,12 @@ void Player::GiveLevel(uint32 level)
|
|||
SetUInt32Value(PLAYER_NEXT_LEVEL_XP, objmgr.GetXPForLevel(level));
|
||||
|
||||
//update level, max level of skills
|
||||
if(getLevel()!= level)
|
||||
m_Played_time[1] = 0; // Level Played Time reset
|
||||
m_Played_time[PLAYED_TIME_LEVEL] = 0; // Level Played Time reset
|
||||
|
||||
_ApplyAllLevelScaleItemMods(false);
|
||||
|
||||
SetLevel(level);
|
||||
|
||||
UpdateSkillsForLevel ();
|
||||
|
||||
// save base values (bonuses already included in stored stats
|
||||
|
|
@ -2405,6 +2408,8 @@ void Player::GiveLevel(uint32 level)
|
|||
SetPower(POWER_FOCUS, 0);
|
||||
SetPower(POWER_HAPPINESS, 0);
|
||||
|
||||
_ApplyAllLevelScaleItemMods(true);
|
||||
|
||||
// update level to hunter/summon pet
|
||||
if (Pet* pet = GetPet())
|
||||
pet->SynchronizeLevelWithOwner();
|
||||
|
|
@ -6487,13 +6492,16 @@ void Player::_ApplyItemMods(Item *item, uint8 slot,bool apply)
|
|||
sLog.outDebug("_ApplyItemMods complete.");
|
||||
}
|
||||
|
||||
void Player::_ApplyItemBonuses(ItemPrototype const *proto, uint8 slot, bool apply)
|
||||
void Player::_ApplyItemBonuses(ItemPrototype const *proto, uint8 slot, bool apply, bool only_level_scale /*= false*/)
|
||||
{
|
||||
if(slot >= INVENTORY_SLOT_BAG_END || !proto)
|
||||
return;
|
||||
|
||||
ScalingStatDistributionEntry const *ssd = proto->ScalingStatDistribution ? sScalingStatDistributionStore.LookupEntry(proto->ScalingStatDistribution) : 0;
|
||||
ScalingStatValuesEntry const *ssv = proto->ScalingStatValue ? sScalingStatValuesStore.LookupEntry(getLevel()) : 0;
|
||||
ScalingStatDistributionEntry const *ssd = proto->ScalingStatDistribution ? sScalingStatDistributionStore.LookupEntry(proto->ScalingStatDistribution) : NULL;
|
||||
ScalingStatValuesEntry const *ssv = proto->ScalingStatValue ? sScalingStatValuesStore.LookupEntry(getLevel()) : NULL;
|
||||
|
||||
if(only_level_scale && !(ssd && ssv))
|
||||
return;
|
||||
|
||||
for (int i = 0; i < MAX_ITEM_PROTO_STATS; ++i)
|
||||
{
|
||||
|
|
@ -7216,6 +7224,24 @@ void Player::_ApplyAllItemMods()
|
|||
sLog.outDebug("_ApplyAllItemMods complete.");
|
||||
}
|
||||
|
||||
void Player::_ApplyAllLevelScaleItemMods(bool apply)
|
||||
{
|
||||
for (int i = 0; i < INVENTORY_SLOT_BAG_END; ++i)
|
||||
{
|
||||
if(m_items[i])
|
||||
{
|
||||
if(m_items[i]->IsBroken())
|
||||
continue;
|
||||
|
||||
ItemPrototype const *proto = m_items[i]->GetProto();
|
||||
if(!proto)
|
||||
continue;
|
||||
|
||||
_ApplyItemBonuses(proto,i, apply, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Player::_ApplyAmmoBonuses()
|
||||
{
|
||||
// check ammo
|
||||
|
|
@ -13850,8 +13876,8 @@ bool Player::MinimalLoadFromDB( QueryResult *result, uint32 guid )
|
|||
|
||||
// the instance id is not needed at character enum
|
||||
|
||||
m_Played_time[0] = fields[7].GetUInt32();
|
||||
m_Played_time[1] = fields[8].GetUInt32();
|
||||
m_Played_time[PLAYED_TIME_TOTAL] = fields[7].GetUInt32();
|
||||
m_Played_time[PLAYED_TIME_LEVEL] = fields[8].GetUInt32();
|
||||
|
||||
m_atLoginFlags = fields[9].GetUInt32();
|
||||
|
||||
|
|
@ -14349,8 +14375,8 @@ bool Player::LoadFromDB( uint32 guid, SqlQueryHolder *holder )
|
|||
}
|
||||
|
||||
m_cinematic = fields[19].GetUInt32();
|
||||
m_Played_time[0]= fields[20].GetUInt32();
|
||||
m_Played_time[1]= fields[21].GetUInt32();
|
||||
m_Played_time[PLAYED_TIME_TOTAL]= fields[20].GetUInt32();
|
||||
m_Played_time[PLAYED_TIME_LEVEL]= fields[21].GetUInt32();
|
||||
|
||||
m_resetTalentsCost = fields[25].GetUInt32();
|
||||
m_resetTalentsTime = time_t(fields[26].GetUInt64());
|
||||
|
|
@ -15611,9 +15637,9 @@ void Player::SaveToDB()
|
|||
ss << m_cinematic;
|
||||
|
||||
ss << ", ";
|
||||
ss << m_Played_time[0];
|
||||
ss << m_Played_time[PLAYED_TIME_TOTAL];
|
||||
ss << ", ";
|
||||
ss << m_Played_time[1];
|
||||
ss << m_Played_time[PLAYED_TIME_LEVEL];
|
||||
|
||||
ss << ", ";
|
||||
ss << finiteAlways(m_rest_bonus);
|
||||
|
|
@ -19515,7 +19541,7 @@ bool Player::isTotalImmune()
|
|||
|
||||
bool Player::HasTitle(uint32 bitIndex)
|
||||
{
|
||||
if (bitIndex > 192)
|
||||
if (bitIndex > MAX_TITLE_INDEX)
|
||||
return false;
|
||||
|
||||
uint32 fieldIndexOffset = bitIndex / 32;
|
||||
|
|
@ -19529,9 +19555,19 @@ void Player::SetTitle(CharTitlesEntry const* title, bool lost)
|
|||
uint32 flag = 1 << (title->bit_index % 32);
|
||||
|
||||
if(lost)
|
||||
{
|
||||
if(!HasFlag(PLAYER__FIELD_KNOWN_TITLES + fieldIndexOffset, flag))
|
||||
return;
|
||||
|
||||
RemoveFlag(PLAYER__FIELD_KNOWN_TITLES + fieldIndexOffset, flag);
|
||||
}
|
||||
else
|
||||
{
|
||||
if(HasFlag(PLAYER__FIELD_KNOWN_TITLES + fieldIndexOffset, flag))
|
||||
return;
|
||||
|
||||
SetFlag(PLAYER__FIELD_KNOWN_TITLES + fieldIndexOffset, flag);
|
||||
}
|
||||
|
||||
WorldPacket data(SMSG_TITLE_EARNED, 4 + 4);
|
||||
data << uint32(title->bit_index);
|
||||
|
|
|
|||
|
|
@ -478,6 +478,8 @@ enum PlayerFlags
|
|||
#define PLAYER_TITLE_HAND_OF_ADAL UI64LIT(0x0000008000000000) // 39
|
||||
#define PLAYER_TITLE_VENGEFUL_GLADIATOR UI64LIT(0x0000010000000000) // 40
|
||||
|
||||
#define MAX_TITLE_INDEX (3*64) // 3 uint64 fields
|
||||
|
||||
// used in PLAYER_FIELD_BYTES values
|
||||
enum PlayerFieldByteFlags
|
||||
{
|
||||
|
|
@ -848,6 +850,14 @@ enum EnviromentalDamage
|
|||
DAMAGE_FALL_TO_VOID = 6 // custom case for fall without durability loss
|
||||
};
|
||||
|
||||
enum PlayedTimeIndex
|
||||
{
|
||||
PLAYED_TIME_TOTAL = 0,
|
||||
PLAYED_TIME_LEVEL = 1
|
||||
};
|
||||
|
||||
#define MAX_PLAYED_TIME_INDEX 2
|
||||
|
||||
// used at player loading query list preparing, and later result selection
|
||||
enum PlayerLoginQueryIndex
|
||||
{
|
||||
|
|
@ -1043,9 +1053,9 @@ class MANGOS_DLL_SPEC Player : public Unit
|
|||
// Played Time Stuff
|
||||
time_t m_logintime;
|
||||
time_t m_Last_tick;
|
||||
uint32 m_Played_time[2];
|
||||
uint32 GetTotalPlayedTime() { return m_Played_time[0]; };
|
||||
uint32 GetLevelPlayedTime() { return m_Played_time[1]; };
|
||||
uint32 m_Played_time[MAX_PLAYED_TIME_INDEX];
|
||||
uint32 GetTotalPlayedTime() { return m_Played_time[PLAYED_TIME_TOTAL]; };
|
||||
uint32 GetLevelPlayedTime() { return m_Played_time[PLAYED_TIME_LEVEL]; };
|
||||
|
||||
void setDeathState(DeathState s); // overwrite Unit::setDeathState
|
||||
|
||||
|
|
@ -1868,7 +1878,8 @@ class MANGOS_DLL_SPEC Player : public Unit
|
|||
void _ApplyItemMods(Item *item,uint8 slot,bool apply);
|
||||
void _RemoveAllItemMods();
|
||||
void _ApplyAllItemMods();
|
||||
void _ApplyItemBonuses(ItemPrototype const *proto,uint8 slot,bool apply);
|
||||
void _ApplyAllLevelScaleItemMods(bool apply);
|
||||
void _ApplyItemBonuses(ItemPrototype const *proto,uint8 slot,bool apply, bool only_level_scale = false);
|
||||
void _ApplyAmmoBonuses();
|
||||
bool EnchantmentFitsRequirements(uint32 enchantmentcondition, int8 slot);
|
||||
void ToggleMetaGemsActive(uint8 exceptslot, bool apply);
|
||||
|
|
|
|||
|
|
@ -330,7 +330,7 @@ void PlayerDumpWriter::DumpTable(std::string& dump, uint32 guid, char const*tabl
|
|||
std::string PlayerDumpWriter::GetDump(uint32 guid)
|
||||
{
|
||||
std::string dump;
|
||||
|
||||
|
||||
dump += "IMPORTANT NOTE: This sql queries not created for apply directly, use '.pdump load' command in console or client chat instead.\n";
|
||||
dump += "IMPORTANT NOTE: NOT APPLY ITS DIRECTLY to character DB or you will DAMAGE and CORRUPT character DB\n\n";
|
||||
|
||||
|
|
|
|||
|
|
@ -652,10 +652,10 @@ enum SpellEffects
|
|||
SPELL_EFFECT_APPLY_AREA_AURA_ENEMY = 129,
|
||||
SPELL_EFFECT_REDIRECT_THREAT = 130,
|
||||
SPELL_EFFECT_131 = 131,
|
||||
SPELL_EFFECT_132 = 132,
|
||||
SPELL_EFFECT_PLAY_MUSIC = 132,
|
||||
SPELL_EFFECT_UNLEARN_SPECIALIZATION = 133,
|
||||
SPELL_EFFECT_KILL_CREDIT2 = 134,
|
||||
SPELL_EFFECT_135 = 135,
|
||||
SPELL_EFFECT_CALL_PET = 135,
|
||||
SPELL_EFFECT_HEAL_PCT = 136,
|
||||
SPELL_EFFECT_ENERGIZE_PCT = 137,
|
||||
SPELL_EFFECT_138 = 138,
|
||||
|
|
@ -897,7 +897,7 @@ enum AuraState
|
|||
//AURA_STATE_UNKNOWN11 = 11, // t|
|
||||
AURA_STATE_FAERIE_FIRE = 12, // c t|
|
||||
AURA_STATE_HEALTHLESS_35_PERCENT = 13, // C T |
|
||||
AURA_STATE_IMMOLATE = 14, // T |
|
||||
AURA_STATE_CONFLAGRATE = 14, // T | per-caster
|
||||
AURA_STATE_SWIFTMEND = 15, // T |
|
||||
AURA_STATE_DEADLY_POISON = 16, // T |
|
||||
AURA_STATE_ENRAGE = 17, // C |
|
||||
|
|
|
|||
|
|
@ -1238,12 +1238,7 @@ void Spell::DoSpellHitOnUnit(Unit *unit, const uint32 effectMask)
|
|||
unit->IncrDiminishing(m_diminishGroup);
|
||||
|
||||
// Apply additional spell effects to target
|
||||
while (!m_preCastSpells.empty())
|
||||
{
|
||||
uint32 spellId = *m_preCastSpells.begin();
|
||||
m_caster->CastSpell(unit, spellId, true, m_CastItem);
|
||||
m_preCastSpells.erase(m_preCastSpells.begin());
|
||||
}
|
||||
CastPreCastSpells(unit);
|
||||
|
||||
for(uint32 effectNumber = 0; effectNumber < 3; ++effectNumber)
|
||||
{
|
||||
|
|
@ -2283,6 +2278,7 @@ void Spell::cast(bool skipCheck)
|
|||
}
|
||||
}
|
||||
|
||||
// different triggred (for caster) and precast (casted before apply effect to target) cases
|
||||
switch(m_spellInfo->SpellFamilyName)
|
||||
{
|
||||
case SPELLFAMILY_GENERIC:
|
||||
|
|
@ -2307,9 +2303,21 @@ void Spell::cast(bool skipCheck)
|
|||
if (m_spellInfo->Mechanic == MECHANIC_SHIELD &&
|
||||
(m_spellInfo->SpellFamilyFlags & UI64LIT(0x0000000000000001)))
|
||||
AddPrecastSpell(6788); // Weakened Soul
|
||||
// Dispersion (transform)
|
||||
if (m_spellInfo->Id == 47585)
|
||||
AddPrecastSpell(60069); // Dispersion (mana regen)
|
||||
|
||||
switch(m_spellInfo->Id)
|
||||
{
|
||||
case 47585: AddPrecastSpell(60069); break; // Dispersion (transform)
|
||||
case 15237: AddTriggeredSpell(23455); break;// Holy Nova, rank 1
|
||||
case 15430: AddTriggeredSpell(23458); break;// Holy Nova, rank 2
|
||||
case 15431: AddTriggeredSpell(23459); break;// Holy Nova, rank 3
|
||||
case 27799: AddTriggeredSpell(27803); break;// Holy Nova, rank 4
|
||||
case 27800: AddTriggeredSpell(27804); break;// Holy Nova, rank 5
|
||||
case 27801: AddTriggeredSpell(27805); break;// Holy Nova, rank 6
|
||||
case 25331: AddTriggeredSpell(25329); break;// Holy Nova, rank 7
|
||||
case 48077: AddTriggeredSpell(48075); break;// Holy Nova, rank 8
|
||||
case 48078: AddTriggeredSpell(48076); break;// Holy Nova, rank 9
|
||||
default:break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case SPELLFAMILY_PALADIN:
|
||||
|
|
@ -2338,22 +2346,6 @@ void Spell::cast(bool skipCheck)
|
|||
break;
|
||||
}
|
||||
|
||||
// Conflagrate - consumes immolate
|
||||
if ((m_spellInfo->TargetAuraState == AURA_STATE_IMMOLATE) && m_targets.getUnitTarget())
|
||||
{
|
||||
// for caster applied auras only
|
||||
Unit::AuraList const &mPeriodic = m_targets.getUnitTarget()->GetAurasByType(SPELL_AURA_PERIODIC_DAMAGE);
|
||||
for(Unit::AuraList::const_iterator i = mPeriodic.begin(); i != mPeriodic.end(); ++i)
|
||||
{
|
||||
if( (*i)->GetSpellProto()->SpellFamilyName == SPELLFAMILY_WARLOCK && ((*i)->GetSpellProto()->SpellFamilyFlags & 4) &&
|
||||
(*i)->GetCasterGUID()==m_caster->GetGUID() )
|
||||
{
|
||||
m_targets.getUnitTarget()->RemoveAura((*i)->GetId(), (*i)->GetEffIndex());
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// traded items have trade slot instead of guid in m_itemTargetGUID
|
||||
// set to real guid to be sent later to the client
|
||||
m_targets.updateTradeSlotItem();
|
||||
|
|
@ -2765,7 +2757,7 @@ void Spell::finish(bool ok)
|
|||
|
||||
// call triggered spell only at successful cast (after clear combo points -> for add some if need)
|
||||
if(!m_TriggerSpells.empty())
|
||||
TriggerSpell();
|
||||
CastTriggerSpells();
|
||||
|
||||
// Stop Attack for some spells
|
||||
if( m_spellInfo->Attributes & SPELL_ATTR_STOP_ATTACK_TARGET )
|
||||
|
|
@ -3604,15 +3596,48 @@ void Spell::HandleEffects(Unit *pUnitTarget,Item *pItemTarget,GameObject *pGOTar
|
|||
*/
|
||||
}
|
||||
|
||||
void Spell::TriggerSpell()
|
||||
|
||||
void Spell::AddTriggeredSpell( uint32 spellId )
|
||||
{
|
||||
for(TriggerSpells::const_iterator si=m_TriggerSpells.begin(); si!=m_TriggerSpells.end(); ++si)
|
||||
SpellEntry const *spellInfo = sSpellStore.LookupEntry(spellId );
|
||||
|
||||
if(!spellInfo)
|
||||
{
|
||||
sLog.outError("Spell::AddTriggeredSpell: unknown spell id %u used as triggred spell for spell %u)", spellId, m_spellInfo->Id);
|
||||
return;
|
||||
}
|
||||
|
||||
m_TriggerSpells.push_back(spellInfo);
|
||||
}
|
||||
|
||||
void Spell::AddPrecastSpell( uint32 spellId )
|
||||
{
|
||||
SpellEntry const *spellInfo = sSpellStore.LookupEntry(spellId );
|
||||
|
||||
if(!spellInfo)
|
||||
{
|
||||
sLog.outError("Spell::AddPrecastSpell: unknown spell id %u used as pre-cast spell for spell %u)", spellId, m_spellInfo->Id);
|
||||
return;
|
||||
}
|
||||
|
||||
m_preCastSpells.push_back(spellInfo);
|
||||
}
|
||||
|
||||
void Spell::CastTriggerSpells()
|
||||
{
|
||||
for(SpellInfoList::const_iterator si=m_TriggerSpells.begin(); si!=m_TriggerSpells.end(); ++si)
|
||||
{
|
||||
Spell* spell = new Spell(m_caster, (*si), true, m_originalCasterGUID, m_selfContainer);
|
||||
spell->prepare(&m_targets); // use original spell original targets
|
||||
}
|
||||
}
|
||||
|
||||
void Spell::CastPreCastSpells(Unit* target)
|
||||
{
|
||||
for(SpellInfoList::const_iterator si=m_preCastSpells.begin(); si!=m_preCastSpells.end(); ++si)
|
||||
m_caster->CastSpell(target, (*si), true, m_CastItem);
|
||||
}
|
||||
|
||||
SpellCastResult Spell::CheckCast(bool strict)
|
||||
{
|
||||
// check cooldowns to prevent cheating
|
||||
|
|
@ -3714,7 +3739,7 @@ SpellCastResult Spell::CheckCast(bool strict)
|
|||
if(target != m_caster)
|
||||
{
|
||||
// target state requirements (apply to non-self only), to allow cast affects to self like Dirty Deeds
|
||||
if(m_spellInfo->TargetAuraState && !target->HasAuraState(AuraState(m_spellInfo->TargetAuraState)))
|
||||
if(m_spellInfo->TargetAuraState && !target->HasAuraStateForCaster(AuraState(m_spellInfo->TargetAuraState),m_caster->GetGUID()))
|
||||
return SPELL_FAILED_TARGET_AURASTATE;
|
||||
|
||||
// Not allow casting on flying player
|
||||
|
|
@ -5802,4 +5827,4 @@ void Spell::FillRaidOrPartyHealthPriorityTargets( UnitList &TagUnitMap, Unit* ta
|
|||
TagUnitMap.push_back(healthQueue.top().getUnit());
|
||||
healthQueue.pop();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -320,6 +320,7 @@ class Spell
|
|||
void EffectActivateRune(uint32 i);
|
||||
void EffectTitanGrip(uint32 i);
|
||||
void EffectEnchantItemPrismatic(uint32 i);
|
||||
void EffectPlayMusic(uint32 i);
|
||||
|
||||
Spell( Unit* Caster, SpellEntry const *info, bool triggered, uint64 originalCasterGUID = 0, Spell** triggeringContainer = NULL );
|
||||
~Spell();
|
||||
|
|
@ -333,7 +334,6 @@ class Spell
|
|||
void TakeRunePower();
|
||||
void TakeReagents();
|
||||
void TakeCastItem();
|
||||
void TriggerSpell();
|
||||
|
||||
SpellCastResult CheckCast(bool strict);
|
||||
SpellCastResult CheckPetCast(Unit* target);
|
||||
|
|
@ -438,8 +438,12 @@ class Spell
|
|||
|
||||
bool CheckTargetCreatureType(Unit* target) const;
|
||||
|
||||
void AddTriggeredSpell(SpellEntry const* spell) { m_TriggerSpells.push_back(spell); }
|
||||
void AddPrecastSpell(uint32 spellId) { m_preCastSpells.push_back(spellId); }
|
||||
void AddTriggeredSpell(SpellEntry const* spellInfo) { m_TriggerSpells.push_back(spellInfo); }
|
||||
void AddPrecastSpell(SpellEntry const* spellInfo) { m_preCastSpells.push_back(spellInfo); }
|
||||
void AddTriggeredSpell(uint32 spellId);
|
||||
void AddPrecastSpell(uint32 spellId);
|
||||
void CastPreCastSpells(Unit* target);
|
||||
void CastTriggerSpells();
|
||||
|
||||
void CleanupTargetList();
|
||||
protected:
|
||||
|
|
@ -558,10 +562,9 @@ class Spell
|
|||
// -------------------------------------------
|
||||
|
||||
//List For Triggered Spells
|
||||
typedef std::list<SpellEntry const*> TriggerSpells;
|
||||
typedef std::list<uint32> SpellPrecasts;
|
||||
TriggerSpells m_TriggerSpells;
|
||||
SpellPrecasts m_preCastSpells;
|
||||
typedef std::list<SpellEntry const*> SpellInfoList;
|
||||
SpellInfoList m_TriggerSpells; // casted by caster to same targets settings in m_targets at success finish of current spell
|
||||
SpellInfoList m_preCastSpells; // casted by caster to each target at spell hit before spell effects apply
|
||||
|
||||
uint32 m_spellState;
|
||||
uint32 m_timer;
|
||||
|
|
|
|||
|
|
@ -996,9 +996,13 @@ void Aura::_AddAura()
|
|||
if (IsSealSpell(m_spellProto))
|
||||
m_target->ModifyAuraState(AURA_STATE_JUDGEMENT, true);
|
||||
|
||||
// Conflagrate aura state on Immolate
|
||||
if (m_spellProto->SpellFamilyName == SPELLFAMILY_WARLOCK && m_spellProto->SpellFamilyFlags & 4)
|
||||
m_target->ModifyAuraState(AURA_STATE_IMMOLATE, true);
|
||||
// Conflagrate aura state on Immolate and Shadowflame
|
||||
if (m_spellProto->SpellFamilyName == SPELLFAMILY_WARLOCK &&
|
||||
// Immolate
|
||||
((m_spellProto->SpellFamilyFlags & UI64LIT(0x0000000000000004)) ||
|
||||
// Shadowflame
|
||||
(m_spellProto->SpellFamilyFlags2 & 0x00000002)))
|
||||
m_target->ModifyAuraState(AURA_STATE_CONFLAGRATE, true);
|
||||
|
||||
// Faerie Fire (druid versions)
|
||||
if (m_spellProto->SpellFamilyName == SPELLFAMILY_DRUID && (m_spellProto->SpellFamilyFlags & UI64LIT(0x0000000000000400)))
|
||||
|
|
@ -1094,6 +1098,7 @@ void Aura::_RemoveAura()
|
|||
|
||||
uint32 removeState = 0;
|
||||
uint64 removeFamilyFlag = m_spellProto->SpellFamilyFlags;
|
||||
uint32 removeFamilyFlag2 = m_spellProto->SpellFamilyFlags2;
|
||||
switch(m_spellProto->SpellFamilyName)
|
||||
{
|
||||
case SPELLFAMILY_PALADIN:
|
||||
|
|
@ -1101,8 +1106,14 @@ void Aura::_RemoveAura()
|
|||
removeState = AURA_STATE_JUDGEMENT; // Update Seals information
|
||||
break;
|
||||
case SPELLFAMILY_WARLOCK:
|
||||
if(m_spellProto->SpellFamilyFlags & UI64LIT(0x4))
|
||||
removeState = AURA_STATE_IMMOLATE; // Conflagrate aura state
|
||||
// Conflagrate aura state on Immolate and Shadowflame,
|
||||
if ((m_spellProto->SpellFamilyFlags & UI64LIT(0x0000000000000004)) ||
|
||||
(m_spellProto->SpellFamilyFlags2 & 0x00000002))
|
||||
{
|
||||
removeFamilyFlag = UI64LIT(0x0000000000000004);
|
||||
removeFamilyFlag2 = 0x00000002;
|
||||
removeState = AURA_STATE_CONFLAGRATE;
|
||||
}
|
||||
break;
|
||||
case SPELLFAMILY_DRUID:
|
||||
if(m_spellProto->SpellFamilyFlags & UI64LIT(0x0000000000000400))
|
||||
|
|
@ -1135,7 +1146,7 @@ void Aura::_RemoveAura()
|
|||
{
|
||||
SpellEntry const *auraSpellInfo = (*i).second->GetSpellProto();
|
||||
if(auraSpellInfo->SpellFamilyName == m_spellProto->SpellFamilyName &&
|
||||
auraSpellInfo->SpellFamilyFlags & removeFamilyFlag)
|
||||
(auraSpellInfo->SpellFamilyFlags & removeFamilyFlag || auraSpellInfo->SpellFamilyFlags2 & removeFamilyFlag2))
|
||||
{
|
||||
found = true;
|
||||
break;
|
||||
|
|
@ -1841,6 +1852,49 @@ void Aura::TriggerSpell()
|
|||
// }
|
||||
// break;
|
||||
// }
|
||||
case SPELLFAMILY_HUNTER:
|
||||
{
|
||||
switch (auraId)
|
||||
{
|
||||
// Sniper training
|
||||
case 53302:
|
||||
case 53303:
|
||||
case 53304:
|
||||
if (target->GetTypeId() != TYPEID_PLAYER)
|
||||
return;
|
||||
|
||||
// Reset reapply counter at move
|
||||
if (((Player*)target)->isMoving())
|
||||
{
|
||||
m_modifier.m_amount = 6;
|
||||
return;
|
||||
}
|
||||
|
||||
// We are standing at the moment
|
||||
if (m_modifier.m_amount > 0)
|
||||
{
|
||||
--m_modifier.m_amount;
|
||||
return;
|
||||
}
|
||||
|
||||
// select rank of buff
|
||||
switch(auraId)
|
||||
{
|
||||
case 53302: trigger_spell_id = 64418; break;
|
||||
case 53303: trigger_spell_id = 64419; break;
|
||||
case 53304: trigger_spell_id = 64420; break;
|
||||
}
|
||||
|
||||
// If aura is active - no need to continue
|
||||
if (target->HasAura(trigger_spell_id))
|
||||
return;
|
||||
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case SPELLFAMILY_DRUID:
|
||||
{
|
||||
switch(auraId)
|
||||
|
|
@ -2004,6 +2058,10 @@ void Aura::TriggerSpell()
|
|||
caster->CastCustomSpell(target, trigger_spell_id, &m_modifier.m_amount, NULL, NULL, true, NULL, this);
|
||||
return;
|
||||
}
|
||||
// Ground Slam
|
||||
case 33525:
|
||||
target->CastSpell(target, trigger_spell_id, true);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -3927,12 +3985,22 @@ void Aura::HandleAuraModIncreaseSwimSpeed(bool /*apply*/, bool Real)
|
|||
m_target->UpdateSpeed(MOVE_SWIM, true);
|
||||
}
|
||||
|
||||
void Aura::HandleAuraModDecreaseSpeed(bool /*apply*/, bool Real)
|
||||
void Aura::HandleAuraModDecreaseSpeed(bool apply, bool Real)
|
||||
{
|
||||
// all applied/removed only at real aura add/remove
|
||||
if(!Real)
|
||||
return;
|
||||
|
||||
if (apply)
|
||||
{
|
||||
// Gronn Lord's Grasp, becomes stoned
|
||||
if (GetId() == 33572)
|
||||
{
|
||||
if (GetStackAmount() >= 5 && !m_target->HasAura(33652))
|
||||
m_target->CastSpell(m_target, 33652, true);
|
||||
}
|
||||
}
|
||||
|
||||
m_target->UpdateSpeed(MOVE_RUN, true);
|
||||
m_target->UpdateSpeed(MOVE_SWIM, true);
|
||||
m_target->UpdateSpeed(MOVE_FLIGHT, true);
|
||||
|
|
@ -4308,8 +4376,8 @@ void Aura::HandlePeriodicDamage(bool apply, bool Real)
|
|||
// Rake
|
||||
if (m_spellProto->SpellFamilyFlags & UI64LIT(0x0000000000001000) && m_spellProto->Effect[2]==SPELL_EFFECT_ADD_COMBO_POINTS)
|
||||
{
|
||||
// $AP*0.18 bonus per tick
|
||||
m_modifier.m_amount += int32(caster->GetTotalAttackPowerValue(BASE_ATTACK) * 18 / 100);
|
||||
// $AP*0.18/3 bonus per tick
|
||||
m_modifier.m_amount += int32(caster->GetTotalAttackPowerValue(BASE_ATTACK) * 6 / 100);
|
||||
return;
|
||||
}
|
||||
// Lacerate
|
||||
|
|
|
|||
|
|
@ -215,9 +215,10 @@ class MANGOS_DLL_SPEC Aura
|
|||
virtual ~Aura();
|
||||
|
||||
void SetModifier(AuraType t, int32 a, uint32 pt, int32 miscValue);
|
||||
Modifier* GetModifier() {return &m_modifier;}
|
||||
int32 GetMiscValue() {return m_spellProto->EffectMiscValue[m_effIndex];}
|
||||
int32 GetMiscBValue() {return m_spellProto->EffectMiscValueB[m_effIndex];}
|
||||
Modifier* GetModifier() { return &m_modifier; }
|
||||
Modifier const* GetModifier() const { return &m_modifier; }
|
||||
int32 GetMiscValue() const { return m_spellProto->EffectMiscValue[m_effIndex]; }
|
||||
int32 GetMiscBValue() const { return m_spellProto->EffectMiscValueB[m_effIndex]; }
|
||||
|
||||
SpellEntry const* GetSpellProto() const { return m_spellProto; }
|
||||
uint32 GetId() const{ return m_spellProto->Id; }
|
||||
|
|
|
|||
|
|
@ -189,7 +189,7 @@ pEffect SpellEffects[TOTAL_SPELL_EFFECTS]=
|
|||
&Spell::EffectApplyAreaAura, //129 SPELL_EFFECT_APPLY_AREA_AURA_ENEMY
|
||||
&Spell::EffectNULL, //130 SPELL_EFFECT_REDIRECT_THREAT
|
||||
&Spell::EffectUnused, //131 SPELL_EFFECT_131 used in some test spells
|
||||
&Spell::EffectNULL, //132 SPELL_EFFECT_PLAY_MUSIC sound id in misc value (SoundEntries.dbc)
|
||||
&Spell::EffectPlayMusic, //132 SPELL_EFFECT_PLAY_MUSIC sound id in misc value (SoundEntries.dbc)
|
||||
&Spell::EffectUnlearnSpecialization, //133 SPELL_EFFECT_UNLEARN_SPECIALIZATION unlearn profession specialization
|
||||
&Spell::EffectKillCredit, //134 SPELL_EFFECT_KILL_CREDIT misc value is creature entry
|
||||
&Spell::EffectNULL, //135 SPELL_EFFECT_CALL_PET
|
||||
|
|
@ -404,9 +404,72 @@ void Spell::EffectSchoolDMG(uint32 effect_idx)
|
|||
// Incinerate Rank 1 & 2
|
||||
if ((m_spellInfo->SpellFamilyFlags & UI64LIT(0x00004000000000)) && m_spellInfo->SpellIconID==2128)
|
||||
{
|
||||
// Incinerate does more dmg (dmg*0.25) if the target is Immolated.
|
||||
if(unitTarget->HasAuraState(AURA_STATE_IMMOLATE))
|
||||
damage += int32(damage*0.25f);
|
||||
// Incinerate does more dmg (dmg*0.25) if the target have Immolate debuff.
|
||||
// Check aura state for speed but aura state set not only for Immolate spell
|
||||
if(unitTarget->HasAuraState(AURA_STATE_CONFLAGRATE))
|
||||
{
|
||||
Unit::AuraList const& RejorRegr = unitTarget->GetAurasByType(SPELL_AURA_PERIODIC_DAMAGE);
|
||||
for(Unit::AuraList::const_iterator i = RejorRegr.begin(); i != RejorRegr.end(); ++i)
|
||||
{
|
||||
// Immolate
|
||||
if((*i)->GetSpellProto()->SpellFamilyName == SPELLFAMILY_WARLOCK &&
|
||||
((*i)->GetSpellProto()->SpellFamilyFlags & UI64LIT(0x00000000000004)))
|
||||
{
|
||||
damage += damage/4;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// Shadowflame
|
||||
else if (m_spellInfo->SpellFamilyFlags & UI64LIT(0x0001000000000000))
|
||||
{
|
||||
// Apply DOT part
|
||||
switch(m_spellInfo->Id)
|
||||
{
|
||||
case 47897: m_caster->CastSpell(unitTarget, 47960, true); break;
|
||||
case 61290: m_caster->CastSpell(unitTarget, 61291, true); break;
|
||||
default:
|
||||
sLog.outError("Spell::EffectDummy: Unhandeled Shadowflame spell rank %u",m_spellInfo->Id);
|
||||
break;
|
||||
}
|
||||
}
|
||||
// Conflagrate - consumes Immolate or Shadowflame
|
||||
else if (m_spellInfo->TargetAuraState == AURA_STATE_CONFLAGRATE)
|
||||
{
|
||||
Aura const* aura = NULL; // found req. aura for damage calculation
|
||||
|
||||
Unit::AuraList const &mPeriodic = unitTarget->GetAurasByType(SPELL_AURA_PERIODIC_DAMAGE);
|
||||
for(Unit::AuraList::const_iterator i = mPeriodic.begin(); i != mPeriodic.end(); ++i)
|
||||
{
|
||||
// for caster applied auras only
|
||||
if ((*i)->GetSpellProto()->SpellFamilyName != SPELLFAMILY_WARLOCK ||
|
||||
(*i)->GetCasterGUID()!=m_caster->GetGUID())
|
||||
continue;
|
||||
|
||||
// Immolate
|
||||
if ((*i)->GetSpellProto()->SpellFamilyFlags & UI64LIT(0x0000000000000004))
|
||||
{
|
||||
aura = *i; // it selected always if exist
|
||||
break;
|
||||
}
|
||||
|
||||
// Shadowflame
|
||||
if ((*i)->GetSpellProto()->SpellFamilyFlags2 & 0x00000002)
|
||||
aura = *i; // remember but wait possible Immolate as primary priority
|
||||
}
|
||||
|
||||
// found Immolate or Shadowflame
|
||||
if (aura)
|
||||
{
|
||||
int32 damagetick = m_caster->SpellDamageBonus(unitTarget, aura->GetSpellProto(), aura->GetModifier()->m_amount, DOT);
|
||||
damage += damagetick * 4;
|
||||
|
||||
// Glyph of Conflagrate
|
||||
if (!m_caster->HasAura(56235))
|
||||
unitTarget->RemoveAurasByCasterSpell(aura->GetId(), m_caster->GetGUID());
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
|
@ -839,7 +902,7 @@ void Spell::EffectDummy(uint32 i)
|
|||
case 23448: // Transporter Arrival - Ultrasafe Transporter: Gadgetzan - backfires
|
||||
{
|
||||
int32 r = irand(0, 119);
|
||||
if ( r < 20 ) // Transporter Malfunction - 1/6 polymorph
|
||||
if ( r < 20 ) // Transporter Malfunction - 1/6 polymorph
|
||||
m_caster->CastSpell(m_caster, 23444, true);
|
||||
else if ( r < 100 ) // Evil Twin - 4/6 evil twin
|
||||
m_caster->CastSpell(m_caster, 23445, true);
|
||||
|
|
@ -1064,13 +1127,13 @@ void Spell::EffectDummy(uint32 i)
|
|||
m_caster->CastSpell(m_caster, 45088, true);
|
||||
return;
|
||||
}
|
||||
case 55004: // Nitro Boosts
|
||||
if(!m_CastItem) return;
|
||||
if(roll_chance_i(95)) // Nitro Boosts - success
|
||||
m_caster->CastSpell(m_caster, 54861, true, m_CastItem);
|
||||
else // Knocked Up - backfire 5%
|
||||
m_caster->CastSpell(m_caster, 46014, true, m_CastItem);
|
||||
return;
|
||||
case 55004: // Nitro Boosts
|
||||
if(!m_CastItem) return;
|
||||
if(roll_chance_i(95)) // Nitro Boosts - success
|
||||
m_caster->CastSpell(m_caster, 54861, true, m_CastItem);
|
||||
else // Knocked Up - backfire 5%
|
||||
m_caster->CastSpell(m_caster, 46014, true, m_CastItem);
|
||||
return;
|
||||
case 50243: // Teach Language
|
||||
{
|
||||
if(m_caster->GetTypeId() != TYPEID_PLAYER)
|
||||
|
|
@ -1147,6 +1210,21 @@ void Spell::EffectDummy(uint32 i)
|
|||
case 58418: // Portal to Orgrimmar
|
||||
case 58420: // Portal to Stormwind
|
||||
return; // implemented in EffectScript[0]
|
||||
case 59640: // Underbelly Elixir
|
||||
{
|
||||
if(m_caster->GetTypeId() != TYPEID_PLAYER)
|
||||
return;
|
||||
|
||||
uint32 spell_id = 0;
|
||||
switch(urand(1,3))
|
||||
{
|
||||
case 1: spell_id = 59645; break;
|
||||
case 2: spell_id = 59831; break;
|
||||
case 3: spell_id = 59843; break;
|
||||
}
|
||||
m_caster->CastSpell(m_caster,spell_id,true,NULL);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
//All IconID Check in there
|
||||
|
|
@ -1431,7 +1509,7 @@ void Spell::EffectDummy(uint32 i)
|
|||
m_caster->CastSpell(unitTarget, 5940, true);
|
||||
return;
|
||||
}
|
||||
case 14185: // Preparation Rogue
|
||||
case 14185: // Preparation
|
||||
{
|
||||
if(m_caster->GetTypeId()!=TYPEID_PLAYER)
|
||||
return;
|
||||
|
|
@ -1483,7 +1561,7 @@ void Spell::EffectDummy(uint32 i)
|
|||
|
||||
switch(m_spellInfo->Id)
|
||||
{
|
||||
case 23989: //Readiness talent
|
||||
case 23989: // Readiness talent
|
||||
{
|
||||
if(m_caster->GetTypeId()!=TYPEID_PLAYER)
|
||||
return;
|
||||
|
|
@ -1645,8 +1723,8 @@ void Spell::EffectDummy(uint32 i)
|
|||
}
|
||||
break;
|
||||
case SPELLFAMILY_SHAMAN:
|
||||
//Shaman Rockbiter Weapon
|
||||
if (m_spellInfo->SpellFamilyFlags == 0x400000)
|
||||
// Rockbiter Weapon
|
||||
if (m_spellInfo->SpellFamilyFlags & 0x400000)
|
||||
{
|
||||
// TODO: use expect spell for enchant (if exist talent)
|
||||
// In 3.0.3 no mods present for rockbiter
|
||||
|
|
@ -1719,8 +1797,7 @@ void Spell::EffectDummy(uint32 i)
|
|||
if(!unitTarget || unitTarget->getPowerType() != POWER_MANA)
|
||||
return;
|
||||
// Glyph of Mana Tide
|
||||
Unit *owner = m_caster->GetOwner();
|
||||
if (owner)
|
||||
if(Unit *owner = m_caster->GetOwner())
|
||||
if (Aura *dummy = owner->GetDummyAura(55441))
|
||||
damage+=dummy->GetModifier()->m_amount;
|
||||
// Regenerate 6% of Total Mana Every 3 secs
|
||||
|
|
@ -2016,7 +2093,7 @@ void Spell::EffectTriggerSpell(uint32 i)
|
|||
m_caster->CastSpell(unitTarget,spellInfo,true,m_CastItem,NULL,m_originalCasterGUID);
|
||||
}
|
||||
else
|
||||
m_TriggerSpells.push_back(spellInfo);
|
||||
AddTriggeredSpell(spellInfo);
|
||||
}
|
||||
|
||||
void Spell::EffectTriggerMissileSpell(uint32 effect_idx)
|
||||
|
|
@ -5668,14 +5745,10 @@ void Spell::EffectSummonObject(uint32 i)
|
|||
default: return;
|
||||
}
|
||||
|
||||
uint64 guid = m_caster->m_ObjectSlot[slot];
|
||||
if(guid != 0)
|
||||
if(uint64 guid = m_caster->m_ObjectSlot[slot])
|
||||
{
|
||||
GameObject* obj = NULL;
|
||||
if( m_caster )
|
||||
obj = m_caster->GetMap()->GetGameObject(guid);
|
||||
|
||||
if(obj) obj->Delete();
|
||||
if(GameObject* obj = m_caster ? m_caster->GetMap()->GetGameObject(guid) : NULL)
|
||||
obj->SetLootState(GO_JUST_DEACTIVATED);
|
||||
m_caster->m_ObjectSlot[slot] = 0;
|
||||
}
|
||||
|
||||
|
|
@ -6610,3 +6683,21 @@ void Spell::EffectRenamePet(uint32 /*eff_idx*/)
|
|||
|
||||
unitTarget->SetByteValue(UNIT_FIELD_BYTES_2, 2, UNIT_RENAME_ALLOWED);
|
||||
}
|
||||
|
||||
void Spell::EffectPlayMusic(uint32 i)
|
||||
{
|
||||
if(!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER)
|
||||
return;
|
||||
|
||||
uint32 soundid = m_spellInfo->EffectMiscValue[i];
|
||||
|
||||
if (!sSoundEntriesStore.LookupEntry(soundid))
|
||||
{
|
||||
sLog.outError("EffectPlayMusic: Sound (Id: %u) not exist in spell %u.",soundid,m_spellInfo->Id);
|
||||
return;
|
||||
}
|
||||
|
||||
WorldPacket data(SMSG_PLAY_MUSIC, 4);
|
||||
data << uint32(soundid);
|
||||
((Player*)unitTarget)->GetSession()->SendPacket(&data);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -133,11 +133,11 @@ void WorldSession::HandleUseItemOpcode(WorldPacket& recvPacket)
|
|||
// send spell error
|
||||
if (SpellEntry const* spellInfo = sSpellStore.LookupEntry(spellid))
|
||||
{
|
||||
// for implicit area/coord target spells
|
||||
// for implicit area/coord target spells
|
||||
if (IsPointEffectTarget(Targets(spellInfo->EffectImplicitTargetA[0])) ||
|
||||
IsAreaEffectTarget(Targets(spellInfo->EffectImplicitTargetA[0])))
|
||||
Spell::SendCastResult(_player,spellInfo,cast_count,SPELL_FAILED_NO_VALID_TARGETS);
|
||||
// for explicit target spells
|
||||
// for explicit target spells
|
||||
else
|
||||
Spell::SendCastResult(_player,spellInfo,cast_count,SPELL_FAILED_BAD_TARGETS);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1176,6 +1176,10 @@ bool SpellMgr::IsNoStackSpellDueToSpell(uint32 spellId_1, uint32 spellId_2) cons
|
|||
if( (spellInfo_1->SpellIconID == 313 || spellInfo_1->SpellIconID == 2039) && (spellInfo_2->SpellIconID == 544 || spellInfo_2->SpellIconID == 91) ||
|
||||
(spellInfo_2->SpellIconID == 313 || spellInfo_2->SpellIconID == 2039) && (spellInfo_1->SpellIconID == 544 || spellInfo_1->SpellIconID == 91) )
|
||||
return false;
|
||||
|
||||
// Metamorphosis, diff effects
|
||||
if (spellInfo_1->SpellIconID == 3314 && spellInfo_2->SpellIconID == 3314)
|
||||
return false;
|
||||
}
|
||||
// Detect Invisibility and Mana Shield (multi-family check)
|
||||
if( spellInfo_1->Id == 132 && spellInfo_2->SpellIconID == 209 && spellInfo_2->SpellVisual[0] == 968 )
|
||||
|
|
@ -2907,6 +2911,13 @@ DiminishingGroup GetDiminishingReturnsGroupForSpell(SpellEntry const* spellproto
|
|||
return DIMINISHING_LIMITONLY;
|
||||
break;
|
||||
}
|
||||
case SPELLFAMILY_PRIEST:
|
||||
{
|
||||
// Vampiric Embrace
|
||||
if ((spellproto->SpellFamilyFlags & UI64LIT(0x00000000004)) && spellproto->SpellIconID == 150)
|
||||
return DIMINISHING_LIMITONLY;
|
||||
break;
|
||||
}
|
||||
case SPELLFAMILY_DEATHKNIGHT:
|
||||
{
|
||||
// Hungering Cold (no flags)
|
||||
|
|
@ -2970,6 +2981,13 @@ int32 GetDiminishingReturnsLimitDuration(DiminishingGroup group, SpellEntry cons
|
|||
return 40000;
|
||||
break;
|
||||
}
|
||||
case SPELLFAMILY_PRIEST:
|
||||
{
|
||||
// Vampiric Embrace - limit to 60 seconds in PvP (3.1)
|
||||
if ((spellproto->SpellFamilyFlags & UI64LIT(0x00000000004)) && spellproto->SpellIconID == 150)
|
||||
return 60000;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -68,15 +68,16 @@ enum SpellFamilyNames
|
|||
};
|
||||
|
||||
//Some SpellFamilyFlags
|
||||
#define SPELLFAMILYFLAG_ROGUE_VANISH UI64LIT(0x000000800)
|
||||
#define SPELLFAMILYFLAG_ROGUE_STEALTH UI64LIT(0x000400000)
|
||||
#define SPELLFAMILYFLAG_ROGUE_BACKSTAB UI64LIT(0x000800004)
|
||||
#define SPELLFAMILYFLAG_ROGUE_SAP UI64LIT(0x000000080)
|
||||
#define SPELLFAMILYFLAG_ROGUE_FEINT UI64LIT(0x008000000)
|
||||
#define SPELLFAMILYFLAG_ROGUE_KIDNEYSHOT UI64LIT(0x000200000)
|
||||
#define SPELLFAMILYFLAG_ROGUE__FINISHING_MOVE UI64LIT(0x9003E0000)
|
||||
#define SPELLFAMILYFLAG_ROGUE_VANISH UI64LIT(0x0000000000000800)
|
||||
#define SPELLFAMILYFLAG_ROGUE_STEALTH UI64LIT(0x0000000000400000)
|
||||
#define SPELLFAMILYFLAG_ROGUE_BACKSTAB UI64LIT(0x0000000000800004)
|
||||
#define SPELLFAMILYFLAG_ROGUE_SAP UI64LIT(0x0000000000000080)
|
||||
#define SPELLFAMILYFLAG_ROGUE_FEINT UI64LIT(0x0000000008000000)
|
||||
#define SPELLFAMILYFLAG_ROGUE_KIDNEYSHOT UI64LIT(0x0000000000200000)
|
||||
#define SPELLFAMILYFLAG_ROGUE__FINISHING_MOVE UI64LIT(0x00000009003E0000)
|
||||
|
||||
#define SPELLFAMILYFLAG_PALADIN_SEALS UI64LIT(0x26000C000A000000)
|
||||
|
||||
// Spell clasification
|
||||
enum SpellSpecific
|
||||
{
|
||||
|
|
|
|||
|
|
@ -167,4 +167,4 @@ bool Totem::IsImmunedToSpellEffect(SpellEntry const* spellInfo, uint32 index) co
|
|||
break;
|
||||
}
|
||||
return Creature::IsImmunedToSpellEffect(spellInfo, index);
|
||||
}
|
||||
}
|
||||
|
|
@ -7456,6 +7456,34 @@ void Unit::RemoveAllAttackers()
|
|||
}
|
||||
}
|
||||
|
||||
bool Unit::HasAuraStateForCaster(AuraState flag, uint64 caster) const
|
||||
{
|
||||
if(!HasAuraState(flag))
|
||||
return false;
|
||||
|
||||
// single per-caster aura state
|
||||
if(flag == AURA_STATE_CONFLAGRATE)
|
||||
{
|
||||
Unit::AuraList const& dotList = GetAurasByType(SPELL_AURA_PERIODIC_DAMAGE);
|
||||
for(Unit::AuraList::const_iterator i = dotList.begin(); i != dotList.end(); ++i)
|
||||
{
|
||||
if ((*i)->GetSpellProto()->SpellFamilyName == SPELLFAMILY_WARLOCK &&
|
||||
(*i)->GetCasterGUID() == caster &&
|
||||
// Immolate
|
||||
(((*i)->GetSpellProto()->SpellFamilyFlags & UI64LIT(0x0000000000000004)) ||
|
||||
// Shadowflame
|
||||
((*i)->GetSpellProto()->SpellFamilyFlags2 & 0x00000002)))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void Unit::ModifyAuraState(AuraState flag, bool apply)
|
||||
{
|
||||
if (apply)
|
||||
|
|
@ -7508,7 +7536,6 @@ void Unit::ModifyAuraState(AuraState flag, bool apply)
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
Unit *Unit::GetOwner() const
|
||||
{
|
||||
if(uint64 ownerid = GetOwnerGUID())
|
||||
|
|
@ -7640,19 +7667,24 @@ int32 Unit::DealHeal(Unit *pVictim, uint32 addhealth, SpellEntry const *spellPro
|
|||
{
|
||||
int32 gain = pVictim->ModifyHealth(int32(addhealth));
|
||||
|
||||
if (GetTypeId()==TYPEID_PLAYER)
|
||||
Unit* unit = this;
|
||||
|
||||
if( GetTypeId()==TYPEID_UNIT && ((Creature*)this)->isTotem() && ((Totem*)this)->GetTotemType()!=TOTEM_STATUE)
|
||||
unit = GetOwner();
|
||||
|
||||
if (unit->GetTypeId()==TYPEID_PLAYER)
|
||||
{
|
||||
// overheal = addhealth - gain
|
||||
SendHealSpellLog(pVictim, spellProto->Id, addhealth, addhealth - gain, critical);
|
||||
unit->SendHealSpellLog(pVictim, spellProto->Id, addhealth, addhealth - gain, critical);
|
||||
|
||||
if (BattleGround *bg = ((Player*)this)->GetBattleGround())
|
||||
bg->UpdatePlayerScore((Player*)this, SCORE_HEALING_DONE, gain);
|
||||
if (BattleGround *bg = ((Player*)unit)->GetBattleGround())
|
||||
bg->UpdatePlayerScore((Player*)unit, SCORE_HEALING_DONE, gain);
|
||||
|
||||
// use the actual gain, as the overheal shall not be counted, skip gain 0 (it ignored anyway in to criteria)
|
||||
if (gain)
|
||||
((Player*)this)->GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_HEALING_DONE, gain, 0, pVictim);
|
||||
((Player*)unit)->GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_HEALING_DONE, gain, 0, pVictim);
|
||||
|
||||
((Player*)this)->GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_HEAL_CASTED, addhealth);
|
||||
((Player*)unit)->GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_HEAL_CASTED, addhealth);
|
||||
}
|
||||
|
||||
if (pVictim->GetTypeId()==TYPEID_PLAYER)
|
||||
|
|
|
|||
|
|
@ -1406,6 +1406,7 @@ class MANGOS_DLL_SPEC Unit : public WorldObject
|
|||
float GetAPMultiplier(WeaponAttackType attType, bool normalized);
|
||||
void ModifyAuraState(AuraState flag, bool apply);
|
||||
bool HasAuraState(AuraState flag) const { return HasFlag(UNIT_FIELD_AURASTATE, 1<<(flag-1)); }
|
||||
bool HasAuraStateForCaster(AuraState flag, uint64 caster) const;
|
||||
void UnsummonAllTotems();
|
||||
Unit* SelectMagnetTarget(Unit *victim, SpellEntry const *spellInfo = NULL);
|
||||
int32 SpellBaseDamageBonus(SpellSchoolMask schoolMask);
|
||||
|
|
|
|||
|
|
@ -9,8 +9,4 @@
|
|||
#include "Database/SQLStorage.h"
|
||||
#include "Opcodes.h"
|
||||
#include "SharedDefines.h"
|
||||
|
||||
#ifdef FASTBUILD
|
||||
//add additional headers here to speed up compilation in release builds even more
|
||||
#include "ObjectMgr.h"
|
||||
#endif
|
||||
|
|
@ -488,8 +488,8 @@ LogColors = ""
|
|||
#
|
||||
# AllFlightPaths
|
||||
# Players will start with all flight paths (Note: ALL flight paths, not only player's team)
|
||||
# Default: 0 (true)
|
||||
# 1 (false)
|
||||
# Default: 0 (false)
|
||||
# 1 (true)
|
||||
#
|
||||
# AlwaysMaxSkillForLevel
|
||||
# Players will automatically gain max level dependent (weapon/defense) skill when logging in, leveling up etc.
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
#ifndef __REVISION_NR_H__
|
||||
#define __REVISION_NR_H__
|
||||
#define REVISION_NR "8192"
|
||||
#define REVISION_NR "8225"
|
||||
#endif // __REVISION_NR_H__
|
||||
|
|
|
|||
|
|
@ -241,7 +241,7 @@ namespace VMAP
|
|||
|
||||
char destnamebuffer[500];
|
||||
char fullnamedestnamebuffer[500];
|
||||
|
||||
|
||||
if(nameCollection.iMainFiles.size() >0)
|
||||
{
|
||||
sprintf(destnamebuffer,"%03u_%i_%i.vmap",pMapId, pYPos, pXPos); // flip it here too
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue