Merge commit 'origin/master' into 320

Conflicts:
	src/game/Player.cpp
	src/game/Totem.cpp
This commit is contained in:
tomrus88 2009-07-21 08:22:30 +04:00
commit 4c709772c1
61 changed files with 912 additions and 454 deletions

View file

@ -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)
{

View file

@ -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;

View file

@ -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 ==================

View file

@ -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?
};
*/

View file

@ -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:

View file

@ -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

View file

@ -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;
}

View file

@ -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();

View file

@ -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;

View file

@ -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)
{

View file

@ -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;
}

View file

@ -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
};

View file

@ -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);

View file

@ -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);

View file

@ -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);

View file

@ -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";

View file

@ -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 |

View file

@ -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();
}
}
}

View file

@ -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;

View file

@ -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

View file

@ -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; }

View file

@ -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);
}

View file

@ -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);
}

View file

@ -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;
}

View file

@ -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
{

View file

@ -167,4 +167,4 @@ bool Totem::IsImmunedToSpellEffect(SpellEntry const* spellInfo, uint32 index) co
break;
}
return Creature::IsImmunedToSpellEffect(spellInfo, index);
}
}

View file

@ -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)

View file

@ -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);

View file

@ -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

View file

@ -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.

View file

@ -1,4 +1,4 @@
#ifndef __REVISION_NR_H__
#define __REVISION_NR_H__
#define REVISION_NR "8192"
#define REVISION_NR "8225"
#endif // __REVISION_NR_H__

View file

@ -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