Merge branch 'master' into git
This commit is contained in:
@@ -492,16 +492,18 @@ void PetAI::HandleReturnMovement()
|
||||
{
|
||||
if (!me->GetCharmInfo()->IsAtStay() && !me->GetCharmInfo()->IsReturning())
|
||||
{
|
||||
// Return to previous position where stay was clicked
|
||||
if (me->GetMotionMaster()->GetMotionSlotType(MOTION_SLOT_CONTROLLED) == NULL_MOTION_TYPE)
|
||||
if (me->GetCharmInfo()->HasStayPosition())
|
||||
{
|
||||
float x, y, z;
|
||||
|
||||
me->GetCharmInfo()->GetStayPosition(x, y, z);
|
||||
ClearCharmInfoFlags();
|
||||
me->GetCharmInfo()->SetIsReturning(true);
|
||||
me->GetMotionMaster()->Clear();
|
||||
me->GetMotionMaster()->MovePoint(me->GetGUIDLow(), x, y, z);
|
||||
// Return to previous position where stay was clicked
|
||||
if (me->GetMotionMaster()->GetMotionSlotType(MOTION_SLOT_CONTROLLED) == NULL_MOTION_TYPE)
|
||||
{
|
||||
float x, y, z;
|
||||
me->GetCharmInfo()->GetStayPosition(x, y, z);
|
||||
ClearCharmInfoFlags();
|
||||
me->GetCharmInfo()->SetIsReturning(true);
|
||||
me->GetMotionMaster()->Clear();
|
||||
me->GetMotionMaster()->MovePoint(me->GetUInt32Value(OBJECT_FIELD_GUID), x, y, z);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1196,7 +1196,7 @@ class SmartTrigger : public AreaTriggerScript
|
||||
}
|
||||
};
|
||||
|
||||
void AddSC_SmartSCripts()
|
||||
void AddSC_SmartScripts()
|
||||
{
|
||||
new SmartTrigger();
|
||||
}
|
||||
|
||||
@@ -201,15 +201,13 @@ bool BattlefieldWG::Update(uint32 diff)
|
||||
else
|
||||
m_saveTimer -= diff;
|
||||
|
||||
// Update Tenacity
|
||||
// Update Tenacity every 2,5 sec.
|
||||
if (IsWarTime())
|
||||
{
|
||||
if (m_tenacityUpdateTimer <= diff)
|
||||
{
|
||||
m_tenacityUpdateTimer = 10000;
|
||||
if (!m_updateTenacityList.empty())
|
||||
UpdateTenacity();
|
||||
m_updateTenacityList.clear();
|
||||
m_tenacityUpdateTimer = 2500;
|
||||
UpdateTenacity();
|
||||
}
|
||||
else
|
||||
m_tenacityUpdateTimer -= diff;
|
||||
@@ -1087,42 +1085,7 @@ void BattlefieldWG::UpdateTenacity()
|
||||
newStack = int32((1.0f - ((float)alliancePlayers / hordePlayers)) * 4.0f); // negative, should cast on horde
|
||||
}
|
||||
|
||||
// Return if no change in stack and apply tenacity to new player
|
||||
if (newStack == m_tenacityStack)
|
||||
{
|
||||
for (GuidSet::const_iterator itr = m_updateTenacityList.begin(); itr != m_updateTenacityList.end(); ++itr)
|
||||
if (Player* newPlayer = ObjectAccessor::FindPlayer(*itr))
|
||||
if ((newPlayer->GetTeamId() == TEAM_ALLIANCE && m_tenacityStack > 0) || (newPlayer->GetTeamId() == TEAM_HORDE && m_tenacityStack < 0))
|
||||
{
|
||||
newStack = std::min(abs(newStack), 20);
|
||||
uint32 buff_honor = GetHonorBuff(newStack);
|
||||
newPlayer->SetAuraStack(SPELL_TENACITY, newPlayer, newStack);
|
||||
if (buff_honor)
|
||||
newPlayer->CastSpell(newPlayer, buff_honor, true);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (m_tenacityStack != 0)
|
||||
{
|
||||
if (m_tenacityStack > 0 && newStack <= 0) // old buff was on alliance
|
||||
team = TEAM_ALLIANCE;
|
||||
else if (m_tenacityStack < 0 && newStack >= 0) // old buff was on horde
|
||||
team = TEAM_HORDE;
|
||||
}
|
||||
|
||||
m_tenacityStack = newStack;
|
||||
// Remove old buff
|
||||
if (team != TEAM_NEUTRAL)
|
||||
{
|
||||
for (GuidSet::const_iterator itr = m_PlayersInWar[team].begin(); itr != m_PlayersInWar[team].end(); ++itr)
|
||||
if (Player* player = ObjectAccessor::FindPlayer(*itr))
|
||||
player->RemoveAurasDueToSpell(SPELL_TENACITY);
|
||||
|
||||
for (GuidSet::const_iterator itr = m_vehicles[team].begin(); itr != m_vehicles[team].end(); ++itr)
|
||||
if (Unit* unit = ObjectAccessor::FindUnit(*itr))
|
||||
unit->RemoveAurasDueToSpell(SPELL_TENACITY_VEHICLE);
|
||||
}
|
||||
// new way to check: always add stacks if they exist, to every one in the game
|
||||
|
||||
// Apply new buff
|
||||
if (newStack)
|
||||
@@ -1147,6 +1110,28 @@ void BattlefieldWG::UpdateTenacity()
|
||||
unit->CastSpell(unit, buff_honor, true);
|
||||
}
|
||||
}
|
||||
|
||||
if (m_tenacityStack != 0)
|
||||
{
|
||||
if (m_tenacityStack > 0 && newStack <= 0) // old buff was on alliance
|
||||
team = TEAM_ALLIANCE;
|
||||
else if (m_tenacityStack < 0 && newStack >= 0) // old buff was on horde
|
||||
team = TEAM_HORDE;
|
||||
}
|
||||
|
||||
// Remove old buff
|
||||
if (team != TEAM_NEUTRAL)
|
||||
{
|
||||
for (GuidSet::const_iterator itr = m_PlayersInWar[team].begin(); itr != m_PlayersInWar[team].end(); ++itr)
|
||||
if (Player* player = ObjectAccessor::FindPlayer(*itr))
|
||||
player->RemoveAurasDueToSpell(SPELL_TENACITY);
|
||||
|
||||
for (GuidSet::const_iterator itr = m_vehicles[team].begin(); itr != m_vehicles[team].end(); ++itr)
|
||||
if (Unit* unit = ObjectAccessor::FindUnit(*itr))
|
||||
unit->RemoveAurasDueToSpell(SPELL_TENACITY_VEHICLE);
|
||||
}
|
||||
|
||||
m_tenacityStack = newStack; // Assign new tenacity value
|
||||
}
|
||||
|
||||
WintergraspCapturePoint::WintergraspCapturePoint(BattlefieldWG* battlefield, TeamId teamInControl) : BfCapturePoint(battlefield)
|
||||
|
||||
@@ -665,17 +665,48 @@ void Battleground::RewardHonorToTeam(uint32 honor, TeamId teamId)
|
||||
|
||||
void Battleground::RewardReputationToTeam(uint32 factionId, uint32 reputation, TeamId teamId)
|
||||
{
|
||||
if (FactionEntry const* factionEntry = sFactionStore.LookupEntry(factionId))
|
||||
for (BattlegroundPlayerMap::const_iterator itr = m_Players.begin(); itr != m_Players.end(); ++itr)
|
||||
if (itr->second->GetBgTeamId() == teamId)
|
||||
{
|
||||
uint32 realFactionId = GetRealRepFactionForPlayer(factionId, itr->second);
|
||||
|
||||
uint32 repGain = reputation;
|
||||
AddPct(repGain, itr->second->GetTotalAuraModifier(SPELL_AURA_MOD_REPUTATION_GAIN));
|
||||
AddPct(repGain, itr->second->GetTotalAuraModifierByMiscValue(SPELL_AURA_MOD_FACTION_REPUTATION_GAIN, factionId));
|
||||
itr->second->GetReputationMgr().ModifyReputation(factionEntry, repGain);
|
||||
AddPct(repGain, itr->second->GetTotalAuraModifierByMiscValue(SPELL_AURA_MOD_FACTION_REPUTATION_GAIN, realFactionId));
|
||||
if (FactionEntry const* factionEntry = sFactionStore.LookupEntry(realFactionId))
|
||||
itr->second->GetReputationMgr().ModifyReputation(factionEntry, repGain);
|
||||
}
|
||||
}
|
||||
|
||||
uint32 Battleground::GetRealRepFactionForPlayer(uint32 factionId, Player* player)
|
||||
{
|
||||
if (player)
|
||||
{
|
||||
// if the bg team is not the original team, reverse reputation
|
||||
if (player->GetBgTeamId() != player->GetTeamId(true))
|
||||
{
|
||||
switch (factionId)
|
||||
{
|
||||
case BG_REP_AB_ALLIANCE:
|
||||
return BG_REP_AB_HORDE;
|
||||
case BG_REP_AB_HORDE:
|
||||
return BG_REP_AB_ALLIANCE;
|
||||
case BG_REP_AV_ALLIANCE:
|
||||
return BG_REP_AV_HORDE;
|
||||
case BG_REP_AV_HORDE:
|
||||
return BG_REP_AV_ALLIANCE;
|
||||
case BG_REP_WS_ALLIANCE:
|
||||
return BG_REP_WS_HORDE;
|
||||
case BG_REP_WS_HORDE:
|
||||
return BG_REP_WS_ALLIANCE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return factionId;
|
||||
}
|
||||
|
||||
|
||||
void Battleground::UpdateWorldState(uint32 Field, uint32 Value)
|
||||
{
|
||||
WorldPacket data;
|
||||
|
||||
@@ -116,6 +116,16 @@ enum BattlegroundSpells
|
||||
SPELL_THE_LAST_STANDING = 26549, // Arena achievement related
|
||||
};
|
||||
|
||||
enum BattlegroundReputations
|
||||
{
|
||||
BG_REP_AV_HORDE = 729,
|
||||
BG_REP_AV_ALLIANCE = 730,
|
||||
BG_REP_AB_HORDE = 510,
|
||||
BG_REP_AB_ALLIANCE = 509,
|
||||
BG_REP_WS_HORDE = 889,
|
||||
BG_REP_WS_ALLIANCE = 890,
|
||||
};
|
||||
|
||||
enum BattlegroundTimeIntervals
|
||||
{
|
||||
CHECK_PLAYER_POSITION_INVERVAL = 9000, // ms
|
||||
@@ -453,6 +463,7 @@ class Battleground
|
||||
void RemoveAuraOnTeam(uint32 spellId, TeamId teamId);
|
||||
void RewardHonorToTeam(uint32 honor, TeamId teamId);
|
||||
void RewardReputationToTeam(uint32 factionId, uint32 reputation, TeamId teamId);
|
||||
uint32 GetRealRepFactionForPlayer(uint32 factionId, Player* player);
|
||||
|
||||
void UpdateWorldState(uint32 Field, uint32 Value);
|
||||
void UpdateWorldStateForPlayer(uint32 Field, uint32 Value, Player* player);
|
||||
|
||||
@@ -205,6 +205,7 @@ include_directories(
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/World
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/ArenaSpectator
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/Misc
|
||||
${CMAKE_SOURCE_DIR}/src/server/scripts/
|
||||
${CMAKE_SOURCE_DIR}/src/server/scripts/PrecompiledHeaders
|
||||
${ACE_INCLUDE_DIR}
|
||||
${MYSQL_INCLUDE_DIR}
|
||||
|
||||
@@ -40,7 +40,7 @@
|
||||
Pet::Pet(Player* owner, PetType type) : Guardian(NULL, owner ? owner->GetGUID() : 0, true),
|
||||
m_usedTalentCount(0), m_removed(false), m_owner(owner),
|
||||
m_happinessTimer(PET_LOSE_HAPPINES_INTERVAL), m_petRegenTimer(PET_FOCUS_REGEN_INTERVAL), m_petType(type), m_duration(0),
|
||||
m_auraRaidUpdateMask(0), m_loading(false), m_declinedname(NULL), asynchLoadType(PET_LOAD_DEFAULT)
|
||||
m_auraRaidUpdateMask(0), m_loading(false), m_declinedname(NULL), m_tempspell(0), m_tempspellTarget(NULL), m_tempoldTarget(NULL), m_tempspellIsPositive(false), asynchLoadType(PET_LOAD_DEFAULT)
|
||||
{
|
||||
m_unitTypeMask |= UNIT_MASK_PET;
|
||||
if (type == HUNTER_PET)
|
||||
@@ -384,6 +384,115 @@ void Pet::Update(uint32 diff)
|
||||
}
|
||||
}
|
||||
|
||||
if (m_tempspell != 0)
|
||||
{
|
||||
Unit* tempspellTarget = m_tempspellTarget;
|
||||
Unit* tempoldTarget = m_tempoldTarget;
|
||||
bool tempspellIsPositive = m_tempspellIsPositive;
|
||||
uint32 tempspell = m_tempspell;
|
||||
Unit* charmer = GetCharmerOrOwner();
|
||||
if (!charmer)
|
||||
return;
|
||||
|
||||
if (!GetCharmInfo())
|
||||
return;
|
||||
|
||||
if (tempspellTarget && tempspellTarget->IsAlive())
|
||||
{
|
||||
SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(tempspell);
|
||||
if (!spellInfo)
|
||||
return;
|
||||
float max_range = GetSpellMaxRangeForTarget(tempspellTarget, spellInfo);
|
||||
|
||||
if (IsWithinLOSInMap(tempspellTarget) && GetDistance(tempspellTarget) < max_range)
|
||||
{
|
||||
if (tempspellTarget && !GetCharmInfo()->GetGlobalCooldownMgr().HasGlobalCooldown(spellInfo) && !HasSpellCooldown(tempspell))
|
||||
{
|
||||
StopMoving();
|
||||
GetMotionMaster()->Clear(false);
|
||||
GetMotionMaster()->MoveIdle();
|
||||
|
||||
GetCharmInfo()->SetIsCommandAttack(false);
|
||||
GetCharmInfo()->SetIsAtStay(true);
|
||||
GetCharmInfo()->SetIsCommandFollow(false);
|
||||
GetCharmInfo()->SetIsFollowing(false);
|
||||
GetCharmInfo()->SetIsReturning(false);
|
||||
GetCharmInfo()->SaveStayPosition(true);
|
||||
|
||||
CastSpell(tempspellTarget, tempspell, true);
|
||||
m_tempspell = 0;
|
||||
m_tempspellTarget = NULL;
|
||||
|
||||
if (tempspellIsPositive)
|
||||
{
|
||||
if (tempoldTarget && tempoldTarget->IsAlive())
|
||||
{
|
||||
GetCharmInfo()->SetIsCommandAttack(true);
|
||||
GetCharmInfo()->SetIsAtStay(false);
|
||||
GetCharmInfo()->SetIsFollowing(false);
|
||||
GetCharmInfo()->SetIsCommandFollow(false);
|
||||
GetCharmInfo()->SetIsReturning(false);
|
||||
|
||||
if (ToCreature() && ToCreature()->IsAIEnabled)
|
||||
ToCreature()->AI()->AttackStart(tempoldTarget);
|
||||
}
|
||||
else
|
||||
{
|
||||
GetCharmInfo()->SetCommandState(COMMAND_FOLLOW);
|
||||
GetCharmInfo()->SetIsCommandAttack(false);
|
||||
GetCharmInfo()->SetIsAtStay(false);
|
||||
GetCharmInfo()->SetIsReturning(true);
|
||||
GetCharmInfo()->SetIsCommandFollow(true);
|
||||
GetCharmInfo()->SetIsFollowing(false);
|
||||
GetMotionMaster()->MoveFollow(charmer, PET_FOLLOW_DIST, GetFollowAngle());
|
||||
}
|
||||
|
||||
m_tempoldTarget = NULL;
|
||||
m_tempspellIsPositive = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
m_tempspell = 0;
|
||||
m_tempspellTarget = NULL;
|
||||
m_tempoldTarget = NULL;
|
||||
m_tempspellIsPositive = false;
|
||||
|
||||
Unit* victim = charmer->GetVictim();
|
||||
if (victim && victim->IsAlive())
|
||||
{
|
||||
StopMoving();
|
||||
GetMotionMaster()->Clear(false);
|
||||
GetMotionMaster()->MoveIdle();
|
||||
|
||||
GetCharmInfo()->SetIsCommandAttack(true);
|
||||
GetCharmInfo()->SetIsAtStay(false);
|
||||
GetCharmInfo()->SetIsFollowing(false);
|
||||
GetCharmInfo()->SetIsCommandFollow(false);
|
||||
GetCharmInfo()->SetIsReturning(false);
|
||||
|
||||
if (ToCreature() && ToCreature()->IsAIEnabled)
|
||||
ToCreature()->AI()->AttackStart(victim);
|
||||
}
|
||||
else
|
||||
{
|
||||
StopMoving();
|
||||
GetMotionMaster()->Clear(false);
|
||||
GetMotionMaster()->MoveIdle();
|
||||
|
||||
GetCharmInfo()->SetCommandState(COMMAND_FOLLOW);
|
||||
GetCharmInfo()->SetIsCommandAttack(false);
|
||||
GetCharmInfo()->SetIsAtStay(false);
|
||||
GetCharmInfo()->SetIsReturning(true);
|
||||
GetCharmInfo()->SetIsCommandFollow(true);
|
||||
GetCharmInfo()->SetIsFollowing(false);
|
||||
GetMotionMaster()->MoveFollow(charmer, PET_FOLLOW_DIST, GetFollowAngle());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (getPetType() == HUNTER_PET)
|
||||
{
|
||||
m_happinessTimer -= diff;
|
||||
@@ -2103,3 +2212,44 @@ void Pet::SetDisplayId(uint32 modelId)
|
||||
if (player->GetGroup())
|
||||
player->SetGroupUpdateFlag(GROUP_UPDATE_FLAG_PET_MODEL_ID);
|
||||
}
|
||||
|
||||
void Pet::CastWhenWillAvailable(uint32 spellid, Unit* spellTarget, Unit* oldTarget, bool spellIsPositive)
|
||||
{
|
||||
if (!spellid)
|
||||
return;
|
||||
|
||||
if (!spellTarget)
|
||||
return;
|
||||
|
||||
m_tempspellTarget = spellTarget;
|
||||
m_tempspell = spellid;
|
||||
m_tempspellIsPositive = spellIsPositive;
|
||||
|
||||
if (oldTarget)
|
||||
m_tempoldTarget = oldTarget;
|
||||
}
|
||||
|
||||
void Pet::ClearCastWhenWillAvailable()
|
||||
{
|
||||
m_tempspellIsPositive = false;
|
||||
m_tempspell = 0;
|
||||
m_tempspellTarget = NULL;
|
||||
m_tempoldTarget = NULL;
|
||||
}
|
||||
|
||||
void Pet::RemoveSpellCooldown(uint32 spell_id, bool update /* = false */)
|
||||
{
|
||||
m_CreatureSpellCooldowns.erase(spell_id);
|
||||
|
||||
if (update)
|
||||
{
|
||||
|
||||
if (Player* playerOwner = GetCharmerOrOwnerPlayerOrPlayerItself())
|
||||
{
|
||||
WorldPacket data(SMSG_CLEAR_COOLDOWN, 4 + 8);
|
||||
data << uint32(spell_id);
|
||||
data << uint64(GetGUID());
|
||||
playerOwner->SendDirectMessage(&data);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -120,6 +120,10 @@ class Pet : public Guardian
|
||||
void LearnPetPassives();
|
||||
void CastPetAuras(bool current);
|
||||
|
||||
void CastWhenWillAvailable(uint32 spellid, Unit* spellTarget, Unit* oldTarget, bool spellIsPositive = false);
|
||||
void ClearCastWhenWillAvailable();
|
||||
void RemoveSpellCooldown(uint32 spell_id, bool update /* = false */);
|
||||
|
||||
void _SaveSpellCooldowns(SQLTransaction& trans, bool logout);
|
||||
void _SaveAuras(SQLTransaction& trans, bool logout);
|
||||
void _SaveSpells(SQLTransaction& trans);
|
||||
@@ -175,6 +179,12 @@ class Pet : public Guardian
|
||||
int32 m_petRegenTimer; // xinef: used for focus regeneration
|
||||
|
||||
DeclinedName *m_declinedname;
|
||||
|
||||
Unit* m_tempspellTarget;
|
||||
Unit* m_tempoldTarget;
|
||||
bool m_tempspellIsPositive;
|
||||
uint32 m_tempspell;
|
||||
|
||||
uint8 asynchLoadType;
|
||||
|
||||
private:
|
||||
|
||||
@@ -84,6 +84,7 @@
|
||||
#include "GameObjectAI.h"
|
||||
#include "PoolMgr.h"
|
||||
#include "SavingSystem.h"
|
||||
#include "TicketMgr.h"
|
||||
|
||||
#define ZONE_UPDATE_INTERVAL (2*IN_MILLISECONDS)
|
||||
|
||||
@@ -678,6 +679,7 @@ Player::Player(WorldSession* session): Unit(true), m_mover(this)
|
||||
#pragma warning(default:4355)
|
||||
#endif
|
||||
|
||||
m_drwGUID = 0;
|
||||
m_speakTime = 0;
|
||||
m_speakCount = 0;
|
||||
|
||||
@@ -1114,7 +1116,7 @@ bool Player::Create(uint32 guidlow, CharacterCreateInfo* createInfo)
|
||||
GetReputationMgr().SetReputation(sFactionStore.LookupEntry(1077), 42999);
|
||||
|
||||
// Factions depending on team, like cities and some more stuff
|
||||
switch (GetTeamId())
|
||||
switch (GetTeamId(true))
|
||||
{
|
||||
case TEAM_ALLIANCE:
|
||||
GetReputationMgr().SetReputation(sFactionStore.LookupEntry(72), 42999);
|
||||
@@ -4729,6 +4731,11 @@ void Player::DeleteFromDB(uint64 playerguid, uint32 accountId, bool updateRealmC
|
||||
// remove from arena teams
|
||||
LeaveAllArenaTeams(playerguid);
|
||||
|
||||
// close player ticket if any
|
||||
GmTicket* ticket = sTicketMgr->GetTicketByPlayer(playerguid);
|
||||
if (ticket)
|
||||
ticket->SetClosedBy(playerguid);
|
||||
|
||||
// remove from group
|
||||
if (uint32 groupId = GetGroupIdFromStorage(guid))
|
||||
if (Group* group = sGroupMgr->GetGroupByGUID(groupId))
|
||||
@@ -4923,9 +4930,18 @@ void Player::DeleteFromDB(uint64 playerguid, uint32 accountId, bool updateRealmC
|
||||
stmt->setUInt32(0, guid);
|
||||
trans->Append(stmt);
|
||||
|
||||
stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_PLAYER_GM_TICKETS);
|
||||
stmt->setUInt32(0, guid);
|
||||
trans->Append(stmt);
|
||||
if (sWorld->getBoolConfig(CONFIG_DELETE_CHARACTER_TICKET_TRACE))
|
||||
{
|
||||
stmt = CharacterDatabase.GetPreparedStatement(CHAR_UPD_PLAYER_GM_TICKETS_ON_CHAR_DELETION);
|
||||
stmt->setUInt32(0, guid);
|
||||
trans->Append(stmt);
|
||||
}
|
||||
else
|
||||
{
|
||||
stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_PLAYER_GM_TICKETS);
|
||||
stmt->setUInt32(0, guid);
|
||||
trans->Append(stmt);
|
||||
}
|
||||
|
||||
stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_ITEM_INSTANCE_BY_OWNER);
|
||||
stmt->setUInt32(0, guid);
|
||||
@@ -7045,7 +7061,7 @@ void Player::RewardReputation(Unit* victim, float rate)
|
||||
ChampioningFaction = GetChampioningFaction();
|
||||
}
|
||||
|
||||
TeamId teamId = GetTeamId();
|
||||
TeamId teamId = GetTeamId(true); // Always check player original reputation when rewarding
|
||||
|
||||
if (Rep->RepFaction1 && (!Rep->TeamDependent || teamId == TEAM_ALLIANCE))
|
||||
{
|
||||
@@ -7168,12 +7184,13 @@ bool Player::RewardHonor(Unit* uVictim, uint32 groupsize, int32 honor, bool awar
|
||||
if (HasAura(SPELL_AURA_PLAYER_INACTIVE))
|
||||
return false;
|
||||
|
||||
// check if player has same IP
|
||||
/* check if player has same IP
|
||||
if (uVictim && uVictim->GetTypeId() == TYPEID_PLAYER)
|
||||
{
|
||||
if (GetSession()->GetRemoteAddress() == uVictim->ToPlayer()->GetSession()->GetRemoteAddress())
|
||||
return false;
|
||||
}
|
||||
*/
|
||||
|
||||
uint64 victim_guid = 0;
|
||||
uint32 victim_rank = 0;
|
||||
@@ -7216,7 +7233,7 @@ bool Player::RewardHonor(Unit* uVictim, uint32 groupsize, int32 honor, bool awar
|
||||
// [29..38] Other title and player name
|
||||
// [39+] Nothing
|
||||
uint32 victim_title = victim->GetUInt32Value(PLAYER_CHOSEN_TITLE);
|
||||
// Get Killer titles, CharTitlesEntry::bit_index
|
||||
// Get Killer titles, CharTitlesEntry::bit_index
|
||||
// Ranks:
|
||||
// title[1..14] -> rank[5..18]
|
||||
// title[15..28] -> rank[5..18]
|
||||
@@ -7471,12 +7488,12 @@ void Player::UpdateArea(uint32 newArea)
|
||||
AreaTableEntry const* zone = GetAreaEntryByAreaID(area->zone);
|
||||
uint32 areaFlags = area->flags;
|
||||
bool isSanctuary = area->IsSanctuary();
|
||||
bool isInn = area->IsInn(GetTeamId());
|
||||
bool isInn = area->IsInn(GetTeamId(true));
|
||||
if (zone)
|
||||
{
|
||||
areaFlags |= zone->flags;
|
||||
isSanctuary |= zone->IsSanctuary();
|
||||
isInn |= zone->IsInn(GetTeamId());
|
||||
isInn |= zone->IsInn(GetTeamId(true));
|
||||
}
|
||||
|
||||
// previously this was in UpdateZone (but after UpdateArea) so nothing will break
|
||||
@@ -7576,10 +7593,10 @@ void Player::UpdateZone(uint32 newZone, uint32 newArea)
|
||||
switch (zone->team)
|
||||
{
|
||||
case AREATEAM_ALLY:
|
||||
pvpInfo.IsInHostileArea = GetTeamId() != TEAM_ALLIANCE && (sWorld->IsPvPRealm() || zone->flags & AREA_FLAG_CAPITAL);
|
||||
pvpInfo.IsInHostileArea = GetTeamId(true) != TEAM_ALLIANCE && (sWorld->IsPvPRealm() || zone->flags & AREA_FLAG_CAPITAL);
|
||||
break;
|
||||
case AREATEAM_HORDE:
|
||||
pvpInfo.IsInHostileArea = GetTeamId() != TEAM_HORDE && (sWorld->IsPvPRealm() || zone->flags & AREA_FLAG_CAPITAL);
|
||||
pvpInfo.IsInHostileArea = GetTeamId(true) != TEAM_HORDE && (sWorld->IsPvPRealm() || zone->flags & AREA_FLAG_CAPITAL);
|
||||
break;
|
||||
case AREATEAM_NONE:
|
||||
// overwrite for battlegrounds, maybe batter some zone flags but current known not 100% fit to this
|
||||
@@ -17568,7 +17585,7 @@ bool Player::LoadFromDB(uint32 guid, SQLQueryHolder *holder)
|
||||
else if (!taxi_nodes.empty())
|
||||
{
|
||||
instanceId = 0;
|
||||
if (!m_taxi.LoadTaxiDestinationsFromString(taxi_nodes, GetTeamId()))
|
||||
if (!m_taxi.LoadTaxiDestinationsFromString(taxi_nodes, GetTeamId(true)))
|
||||
{
|
||||
// xinef: could no load valid data for taxi, relocate to homebind and clear
|
||||
m_taxi.ClearTaxiDestinations();
|
||||
@@ -19030,9 +19047,9 @@ bool Player::Satisfy(AccessRequirement const* ar, uint32 target_map, bool report
|
||||
}
|
||||
|
||||
uint32 missingQuest = 0;
|
||||
if (GetTeamId() == TEAM_ALLIANCE && ar->quest_A && !GetQuestRewardStatus(ar->quest_A))
|
||||
if (GetTeamId(true) == TEAM_ALLIANCE && ar->quest_A && !GetQuestRewardStatus(ar->quest_A))
|
||||
missingQuest = ar->quest_A;
|
||||
else if (GetTeamId() == TEAM_HORDE && ar->quest_H && !GetQuestRewardStatus(ar->quest_H))
|
||||
else if (GetTeamId(true) == TEAM_HORDE && ar->quest_H && !GetQuestRewardStatus(ar->quest_H))
|
||||
missingQuest = ar->quest_H;
|
||||
|
||||
uint32 missingAchievement = 0;
|
||||
@@ -21196,7 +21213,7 @@ bool Player::ActivateTaxiPathTo(std::vector<uint32> const& nodes, Creature* npc
|
||||
// only one mount ID for both sides. Probably not good to use 315 in case DBC nodes
|
||||
// change but I couldn't find a suitable alternative. OK to use class because only DK
|
||||
// can use this taxi.
|
||||
uint32 mount_display_id = sObjectMgr->GetTaxiMountDisplayId(sourcenode, GetTeamId(), npc == NULL || (sourcenode == 315 && getClass() == CLASS_DEATH_KNIGHT));
|
||||
uint32 mount_display_id = sObjectMgr->GetTaxiMountDisplayId(sourcenode, GetTeamId(true), npc == NULL || (sourcenode == 315 && getClass() == CLASS_DEATH_KNIGHT));
|
||||
|
||||
// in spell case allow 0 model
|
||||
if ((mount_display_id == 0 && spellid == 0) || sourcepath == 0)
|
||||
@@ -21273,7 +21290,7 @@ void Player::ContinueTaxiFlight()
|
||||
|
||||
;//sLog->outDebug(LOG_FILTER_UNITS, "WORLD: Restart character %u taxi flight", GetGUIDLow());
|
||||
|
||||
uint32 mountDisplayId = sObjectMgr->GetTaxiMountDisplayId(sourceNode, GetTeamId(), true);
|
||||
uint32 mountDisplayId = sObjectMgr->GetTaxiMountDisplayId(sourceNode, GetTeamId(true), true);
|
||||
if (!mountDisplayId)
|
||||
return;
|
||||
|
||||
@@ -21514,7 +21531,7 @@ bool Player::BuyItemFromVendorSlot(uint64 vendorguid, uint32 vendorslot, uint32
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!IsGameMaster() && ((pProto->Flags2 & ITEM_FLAGS_EXTRA_HORDE_ONLY && GetTeamId() == TEAM_ALLIANCE) || (pProto->Flags2 == ITEM_FLAGS_EXTRA_ALLIANCE_ONLY && GetTeamId() == TEAM_HORDE)))
|
||||
if (!IsGameMaster() && ((pProto->Flags2 & ITEM_FLAGS_EXTRA_HORDE_ONLY && GetTeamId(true) == TEAM_ALLIANCE) || (pProto->Flags2 == ITEM_FLAGS_EXTRA_ALLIANCE_ONLY && GetTeamId(true) == TEAM_HORDE)))
|
||||
return false;
|
||||
|
||||
Creature* creature = GetNPCIfCanInteractWith(vendorguid, UNIT_NPC_FLAG_VENDOR);
|
||||
|
||||
@@ -2074,7 +2074,7 @@ class Player : public Unit, public GridObject<Player>
|
||||
void CheckAreaExploreAndOutdoor(void);
|
||||
|
||||
static TeamId TeamIdForRace(uint8 race);
|
||||
TeamId GetTeamId() const { return m_team; }
|
||||
TeamId GetTeamId(bool original = false) const { return original ? TeamIdForRace(getRace()) : m_team; };
|
||||
void setFactionForRace(uint8 race);
|
||||
|
||||
void InitDisplayIds();
|
||||
@@ -2573,6 +2573,11 @@ class Player : public Unit, public GridObject<Player>
|
||||
uint32 m_pendingSpectatorInviteInstanceId;
|
||||
std::set<uint32> m_receivedSpectatorResetFor;
|
||||
|
||||
// Dancing Rune weapon
|
||||
void setRuneWeaponGUID(uint64 guid) { m_drwGUID = guid; };
|
||||
uint64 getRuneWeaponGUID() { return m_drwGUID; };
|
||||
uint64 m_drwGUID;
|
||||
|
||||
bool CanSeeDKPet() const { return m_ExtraFlags & PLAYER_EXTRA_SHOW_DK_PET; }
|
||||
void SetShowDKPet(bool on) { if (on) m_ExtraFlags |= PLAYER_EXTRA_SHOW_DK_PET; else m_ExtraFlags &= ~PLAYER_EXTRA_SHOW_DK_PET; };
|
||||
void PrepareCharmAISpells();
|
||||
|
||||
@@ -2749,7 +2749,7 @@ SpellMissInfo Unit::MagicSpellHitResult(Unit* victim, SpellInfo const* spell)
|
||||
|
||||
int32 tmp = 10000 - HitChance;
|
||||
|
||||
int32 rand = irand(0, 10000);
|
||||
int32 rand = irand(1, 10000); // Needs to be 1 to 10000 to avoid the 1/10000 chance to miss on 100% hit rating
|
||||
|
||||
if (rand < tmp)
|
||||
return SPELL_MISS_MISS;
|
||||
@@ -5047,6 +5047,11 @@ uint32 Unit::GetDiseasesByCaster(uint64 casterGUID, uint8 mode)
|
||||
SPELL_AURA_NONE
|
||||
};
|
||||
|
||||
uint64 drwGUID = 0;
|
||||
|
||||
if (Player* playerCaster = ObjectAccessor::GetPlayer(*this, casterGUID))
|
||||
drwGUID = playerCaster->getRuneWeaponGUID();
|
||||
|
||||
uint32 diseases = 0;
|
||||
for (uint8 index = 0; diseaseAuraTypes[index] != SPELL_AURA_NONE; ++index)
|
||||
{
|
||||
@@ -5054,7 +5059,7 @@ uint32 Unit::GetDiseasesByCaster(uint64 casterGUID, uint8 mode)
|
||||
{
|
||||
// Get auras with disease dispel type by caster
|
||||
if ((*i)->GetSpellInfo()->Dispel == DISPEL_DISEASE
|
||||
&& (*i)->GetCasterGUID() == casterGUID)
|
||||
&& ((*i)->GetCasterGUID() == casterGUID || (*i)->GetCasterGUID() == drwGUID)) // if its caster or his dancing rune weapon
|
||||
{
|
||||
++diseases;
|
||||
|
||||
@@ -18618,6 +18623,18 @@ void CharmInfo::GetStayPosition(float &x, float &y, float &z)
|
||||
z = _stayZ;
|
||||
}
|
||||
|
||||
void CharmInfo::RemoveStayPosition()
|
||||
{
|
||||
_stayX = 0.0f;
|
||||
_stayY = 0.0f;
|
||||
_stayZ = 0.0f;
|
||||
}
|
||||
|
||||
bool CharmInfo::HasStayPosition()
|
||||
{
|
||||
return _stayX && _stayY && _stayZ;
|
||||
}
|
||||
|
||||
void CharmInfo::SetIsAtStay(bool val)
|
||||
{
|
||||
_isAtStay = val;
|
||||
|
||||
@@ -1224,6 +1224,8 @@ struct CharmInfo
|
||||
bool IsReturning();
|
||||
void SaveStayPosition(bool atCurrentPos);
|
||||
void GetStayPosition(float &x, float &y, float &z);
|
||||
void RemoveStayPosition();
|
||||
bool HasStayPosition();
|
||||
|
||||
void SetForcedSpell(uint32 id) { _forcedSpellId = id; }
|
||||
int32 GetForcedSpell() { return _forcedSpellId; }
|
||||
|
||||
@@ -2006,7 +2006,7 @@ void WorldSession::HandleCharFactionOrRaceChange(WorldPacket& recvData)
|
||||
if (recvData.GetOpcode() == CMSG_CHAR_FACTION_CHANGE)
|
||||
{
|
||||
// if player is in a guild
|
||||
if (playerData->guildId)
|
||||
if (playerData->guildId && !sWorld->getBoolConfig(CONFIG_ALLOW_TWO_SIDE_INTERACTION_GUILD))
|
||||
{
|
||||
WorldPacket data(SMSG_CHAR_FACTION_CHANGE, 1);
|
||||
data << (uint8)CHAR_CREATE_CHARACTER_IN_GUILD;
|
||||
|
||||
@@ -507,6 +507,9 @@ void WorldSession::HandlePetActionHelper(Unit* pet, uint64 guid1, uint16 spellid
|
||||
charmInfo->SetIsReturning(false);
|
||||
charmInfo->SetIsAtStay(!controlledMotion);
|
||||
charmInfo->SaveStayPosition(controlledMotion);
|
||||
if (pet->ToPet())
|
||||
pet->ToPet()->ClearCastWhenWillAvailable();
|
||||
|
||||
|
||||
charmInfo->SetForcedSpell(0);
|
||||
charmInfo->SetForcedTargetGUID(0);
|
||||
@@ -518,6 +521,8 @@ void WorldSession::HandlePetActionHelper(Unit* pet, uint64 guid1, uint16 spellid
|
||||
pet->InterruptNonMeleeSpells(false);
|
||||
pet->ClearInPetCombat();
|
||||
pet->GetMotionMaster()->MoveFollow(_player, PET_FOLLOW_DIST, pet->GetFollowAngle());
|
||||
if (pet->ToPet())
|
||||
pet->ToPet()->ClearCastWhenWillAvailable();
|
||||
charmInfo->SetCommandState(COMMAND_FOLLOW);
|
||||
|
||||
charmInfo->SetIsCommandAttack(false);
|
||||
@@ -525,7 +530,7 @@ void WorldSession::HandlePetActionHelper(Unit* pet, uint64 guid1, uint16 spellid
|
||||
charmInfo->SetIsReturning(true);
|
||||
charmInfo->SetIsCommandFollow(true);
|
||||
charmInfo->SetIsFollowing(false);
|
||||
|
||||
charmInfo->RemoveStayPosition();
|
||||
charmInfo->SetForcedSpell(0);
|
||||
charmInfo->SetForcedTargetGUID(0);
|
||||
break;
|
||||
@@ -641,6 +646,8 @@ void WorldSession::HandlePetActionHelper(Unit* pet, uint64 guid1, uint16 spellid
|
||||
{
|
||||
case REACT_PASSIVE: //passive
|
||||
pet->AttackStop();
|
||||
if (pet->ToPet())
|
||||
pet->ToPet()->ClearCastWhenWillAvailable();
|
||||
pet->ClearInPetCombat();
|
||||
|
||||
case REACT_DEFENSIVE: //recovery
|
||||
@@ -658,9 +665,6 @@ void WorldSession::HandlePetActionHelper(Unit* pet, uint64 guid1, uint16 spellid
|
||||
{
|
||||
Unit* unit_target = NULL;
|
||||
|
||||
if (guid2)
|
||||
unit_target = ObjectAccessor::GetUnit(*_player, guid2);
|
||||
|
||||
// do not cast unknown spells
|
||||
SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(spellid);
|
||||
if (!spellInfo)
|
||||
@@ -669,6 +673,11 @@ void WorldSession::HandlePetActionHelper(Unit* pet, uint64 guid1, uint16 spellid
|
||||
return;
|
||||
}
|
||||
|
||||
if (guid2)
|
||||
unit_target = ObjectAccessor::GetUnit(*_player, guid2);
|
||||
else if (!spellInfo->IsPositive())
|
||||
return;
|
||||
|
||||
for (uint32 i = 0; i < MAX_SPELL_EFFECTS; ++i)
|
||||
{
|
||||
if (spellInfo->Effects[i].TargetA.GetTarget() == TARGET_UNIT_SRC_AREA_ENEMY || spellInfo->Effects[i].TargetA.GetTarget() == TARGET_UNIT_DEST_AREA_ENEMY || spellInfo->Effects[i].TargetA.GetTarget() == TARGET_DEST_DYNOBJ_ENEMY)
|
||||
@@ -743,6 +752,131 @@ void WorldSession::HandlePetActionHelper(Unit* pet, uint64 guid1, uint16 spellid
|
||||
charmInfo->SetForcedSpell(0);
|
||||
charmInfo->SetForcedTargetGUID(0);
|
||||
}
|
||||
else if (pet->ToPet() && (result == SPELL_FAILED_LINE_OF_SIGHT || result == SPELL_FAILED_OUT_OF_RANGE))
|
||||
{
|
||||
unit_target = spell->m_targets.GetUnitTarget();
|
||||
bool haspositiveeffect = false;
|
||||
|
||||
if (!unit_target)
|
||||
return;
|
||||
|
||||
// search positive effects for spell
|
||||
for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i)
|
||||
{
|
||||
if (spellInfo->_IsPositiveEffect(i, true))
|
||||
{
|
||||
haspositiveeffect = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (pet->isPossessed() || pet->IsVehicle())
|
||||
Spell::SendCastResult(GetPlayer(), spellInfo, 0, result);
|
||||
else if (GetPlayer()->IsFriendlyTo(unit_target) && !haspositiveeffect)
|
||||
spell->SendPetCastResult(SPELL_FAILED_TARGET_FRIENDLY);
|
||||
else
|
||||
spell->SendPetCastResult(SPELL_FAILED_DONT_REPORT);
|
||||
|
||||
if (!pet->HasSpellCooldown(spellid))
|
||||
if(pet->ToPet())
|
||||
pet->ToPet()->RemoveSpellCooldown(spellid, true);
|
||||
|
||||
spell->finish(false);
|
||||
delete spell;
|
||||
|
||||
if (_player->HasAuraType(SPELL_AURA_MOD_PACIFY))
|
||||
return;
|
||||
|
||||
bool tempspellIsPositive = false;
|
||||
|
||||
if (!GetPlayer()->IsFriendlyTo(unit_target))
|
||||
{
|
||||
// only place where pet can be player
|
||||
Unit* TargetUnit = ObjectAccessor::GetUnit(*_player, guid2);
|
||||
if (!TargetUnit)
|
||||
return;
|
||||
|
||||
if (Unit* owner = pet->GetOwner())
|
||||
if (!owner->IsValidAttackTarget(TargetUnit))
|
||||
return;
|
||||
|
||||
pet->ClearUnitState(UNIT_STATE_FOLLOW);
|
||||
// This is true if pet has no target or has target but targets differs.
|
||||
if (pet->GetVictim() != TargetUnit || (pet->GetVictim() == TargetUnit && !pet->GetCharmInfo()->IsCommandAttack()))
|
||||
{
|
||||
if (pet->GetVictim())
|
||||
pet->AttackStop();
|
||||
|
||||
if (pet->GetTypeId() != TYPEID_PLAYER && pet->ToCreature() && pet->ToCreature()->IsAIEnabled)
|
||||
{
|
||||
charmInfo->SetIsCommandAttack(true);
|
||||
charmInfo->SetIsAtStay(false);
|
||||
charmInfo->SetIsFollowing(false);
|
||||
charmInfo->SetIsCommandFollow(false);
|
||||
charmInfo->SetIsReturning(false);
|
||||
|
||||
pet->ToCreature()->AI()->AttackStart(TargetUnit);
|
||||
|
||||
if (pet->IsPet() && ((Pet*)pet)->getPetType() == SUMMON_PET && pet != TargetUnit && urand(0, 100) < 10)
|
||||
pet->SendPetTalk((uint32)PET_TALK_SPECIAL_SPELL);
|
||||
else
|
||||
pet->SendPetAIReaction(guid1);
|
||||
}
|
||||
else // charmed player
|
||||
{
|
||||
if (pet->GetVictim() && pet->GetVictim() != TargetUnit)
|
||||
pet->AttackStop();
|
||||
|
||||
charmInfo->SetIsCommandAttack(true);
|
||||
charmInfo->SetIsAtStay(false);
|
||||
charmInfo->SetIsFollowing(false);
|
||||
charmInfo->SetIsCommandFollow(false);
|
||||
charmInfo->SetIsReturning(false);
|
||||
|
||||
pet->Attack(TargetUnit, true);
|
||||
pet->SendPetAIReaction(guid1);
|
||||
}
|
||||
|
||||
pet->ToPet()->CastWhenWillAvailable(spellid, unit_target, NULL, tempspellIsPositive);
|
||||
}
|
||||
}
|
||||
else if (haspositiveeffect)
|
||||
{
|
||||
bool tempspellIsPositive = true;
|
||||
pet->ClearUnitState(UNIT_STATE_FOLLOW);
|
||||
// This is true if pet has no target or has target but targets differs.
|
||||
Unit* victim = pet->GetVictim();
|
||||
if (victim)
|
||||
{
|
||||
pet->AttackStop();
|
||||
}
|
||||
else
|
||||
victim = NULL;
|
||||
|
||||
if (pet->GetTypeId() != TYPEID_PLAYER && pet->ToCreature() && pet->ToCreature()->IsAIEnabled)
|
||||
{
|
||||
pet->StopMoving();
|
||||
pet->GetMotionMaster()->Clear();
|
||||
|
||||
charmInfo->SetIsCommandAttack(false);
|
||||
charmInfo->SetIsAtStay(false);
|
||||
charmInfo->SetIsFollowing(false);
|
||||
charmInfo->SetIsCommandFollow(false);
|
||||
charmInfo->SetIsReturning(false);
|
||||
|
||||
pet->GetMotionMaster()->MoveChase(unit_target);
|
||||
|
||||
if (pet->IsPet() && ((Pet*)pet)->getPetType() == SUMMON_PET && pet != unit_target && urand(0, 100) < 10)
|
||||
pet->SendPetTalk((uint32)PET_TALK_SPECIAL_SPELL);
|
||||
else
|
||||
{
|
||||
pet->SendPetAIReaction(guid1);
|
||||
}
|
||||
|
||||
pet->ToPet()->CastWhenWillAvailable(spellid, unit_target, victim, tempspellIsPositive);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// dont spam alerts
|
||||
|
||||
@@ -35,6 +35,7 @@ struct MapEntry;
|
||||
class Player;
|
||||
class Group;
|
||||
class InstanceSaveManager;
|
||||
class InstanceSave;
|
||||
|
||||
struct InstancePlayerBind
|
||||
{
|
||||
|
||||
@@ -2682,10 +2682,12 @@ void InstanceMap::PermBindAllPlayers()
|
||||
{
|
||||
player = itr->GetSource();
|
||||
group = player->GetGroup();
|
||||
|
||||
// players inside an instance cannot be bound to other instances
|
||||
// some players may already be permanently bound, in this case nothing happens
|
||||
InstancePlayerBind* bind = sInstanceSaveMgr->PlayerGetBoundInstance(player->GetGUIDLow(), save->GetMapId(), save->GetDifficulty());
|
||||
if ((!group || !group->isLFGGroup() || !group->IsLfgRandomInstance()) && (!bind || !bind->perm))
|
||||
|
||||
if (!bind || !bind->perm)
|
||||
{
|
||||
WorldPacket data(SMSG_INSTANCE_SAVE_CREATED, 4);
|
||||
data << uint32(0);
|
||||
|
||||
@@ -160,27 +160,33 @@ namespace Trinity
|
||||
|
||||
inline uint32 Gain(Player* player, Unit* u)
|
||||
{
|
||||
uint32 gain;
|
||||
Creature* creature = u->ToCreature();
|
||||
uint32 gain = 0;
|
||||
|
||||
if (u->GetTypeId() == TYPEID_UNIT &&
|
||||
(((Creature*)u)->IsTotem() || ((Creature*)u)->IsPet() ||
|
||||
(((Creature*)u)->GetCreatureTemplate()->flags_extra & CREATURE_FLAG_EXTRA_NO_XP_AT_KILL) ||
|
||||
u->IsCritter()))
|
||||
gain = 0;
|
||||
else
|
||||
if (!creature || (!creature->IsTotem() && !creature->IsPet() && !creature->IsCritter() &&
|
||||
!(creature->GetCreatureTemplate()->flags_extra & CREATURE_FLAG_EXTRA_NO_XP_AT_KILL)))
|
||||
{
|
||||
float xpMod = 1.0f;
|
||||
|
||||
gain = BaseGain(player->getLevel(), u->getLevel(), GetContentLevelsForMapAndZone(u->GetMapId(), u->GetZoneId()));
|
||||
|
||||
if (gain != 0 && u->GetTypeId() == TYPEID_UNIT && ((Creature*)u)->isElite())
|
||||
if (gain && creature)
|
||||
{
|
||||
// Elites in instances have a 2.75x XP bonus instead of the regular 2x world bonus.
|
||||
if (u->GetMap()->IsDungeon())
|
||||
gain = uint32(gain * 2.75);
|
||||
else
|
||||
gain *= 2;
|
||||
if (creature->isElite())
|
||||
{
|
||||
// Elites in instances have a 2.75x XP bonus instead of the regular 2x world bonus.
|
||||
if (u->GetMap() && u->GetMap()->IsDungeon())
|
||||
xpMod *= 2.75f;
|
||||
else
|
||||
xpMod *= 2.0f;
|
||||
}
|
||||
|
||||
// This requires TrinityCore creature_template.ExperienceModifier feature
|
||||
// xpMod *= creature->GetCreatureTemplate()->ModExperience;
|
||||
}
|
||||
|
||||
gain = uint32(gain * sWorld->getRate(RATE_XP_KILL));
|
||||
xpMod *= isBattleGround ? sWorld->getRate(RATE_XP_BG_KILL) : sWorld->getRate(RATE_XP_KILL);
|
||||
gain = uint32(gain * xpMod);
|
||||
}
|
||||
|
||||
//sScriptMgr->OnGainCalculation(gain, player, u); // pussywizard: optimization
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,36 +0,0 @@
|
||||
/*
|
||||
* Copyright (C)
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation; either version 2 of the License, or (at your
|
||||
* option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef SC_SCRIPTLOADER_H
|
||||
#define SC_SCRIPTLOADER_H
|
||||
|
||||
void AddScripts();
|
||||
void CheckIfScriptsInDatabaseExist();
|
||||
void AddSpellScripts();
|
||||
void AddCommandScripts();
|
||||
void AddWorldScripts();
|
||||
void AddEventScripts();
|
||||
void AddEasternKingdomsScripts();
|
||||
void AddKalimdorScripts();
|
||||
void AddOutlandScripts();
|
||||
void AddNorthrendScripts();
|
||||
void AddBattlegroundScripts();
|
||||
void AddPetScripts();
|
||||
void AddOutdoorPvPScripts();
|
||||
void AddCustomScripts();
|
||||
|
||||
#endif
|
||||
@@ -163,6 +163,7 @@ class ScriptRegistry
|
||||
ScriptMgr::ScriptMgr()
|
||||
: _scriptCount(0), _scheduledScripts(0)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
ScriptMgr::~ScriptMgr()
|
||||
@@ -171,18 +172,8 @@ ScriptMgr::~ScriptMgr()
|
||||
|
||||
void ScriptMgr::Initialize()
|
||||
{
|
||||
uint32 oldMSTime = getMSTime();
|
||||
|
||||
LoadDatabase();
|
||||
|
||||
sLog->outString("Loading C++ scripts");
|
||||
|
||||
FillSpellSummary();
|
||||
AddScripts();
|
||||
CheckIfScriptsInDatabaseExist();
|
||||
|
||||
sLog->outString(">> Loaded %u C++ scripts in %u ms", GetScriptCount(), GetMSTimeDiffToNow(oldMSTime));
|
||||
sLog->outString();
|
||||
sLog->outString("Loading C++ scripts");
|
||||
}
|
||||
|
||||
void ScriptMgr::Unload()
|
||||
@@ -223,7 +214,32 @@ void ScriptMgr::Unload()
|
||||
|
||||
void ScriptMgr::LoadDatabase()
|
||||
{
|
||||
uint32 oldMSTime = getMSTime();
|
||||
|
||||
sScriptSystemMgr->LoadScriptWaypoints();
|
||||
|
||||
// Add all scripts that must be loaded after db/maps
|
||||
ScriptRegistry<WorldMapScript>::AddALScripts();
|
||||
ScriptRegistry<BattlegroundMapScript>::AddALScripts();
|
||||
ScriptRegistry<InstanceMapScript>::AddALScripts();
|
||||
ScriptRegistry<SpellScriptLoader>::AddALScripts();
|
||||
ScriptRegistry<ItemScript>::AddALScripts();
|
||||
ScriptRegistry<CreatureScript>::AddALScripts();
|
||||
ScriptRegistry<GameObjectScript>::AddALScripts();
|
||||
ScriptRegistry<AreaTriggerScript>::AddALScripts();
|
||||
ScriptRegistry<BattlegroundScript>::AddALScripts();
|
||||
ScriptRegistry<OutdoorPvPScript>::AddALScripts();
|
||||
ScriptRegistry<WeatherScript>::AddALScripts();
|
||||
ScriptRegistry<ConditionScript>::AddALScripts();
|
||||
ScriptRegistry<TransportScript>::AddALScripts();
|
||||
ScriptRegistry<AchievementCriteriaScript>::AddALScripts();
|
||||
|
||||
FillSpellSummary();
|
||||
|
||||
CheckIfScriptsInDatabaseExist();
|
||||
|
||||
sLog->outString(">> Loaded %u C++ scripts in %u ms", GetScriptCount(), GetMSTimeDiffToNow(oldMSTime));
|
||||
sLog->outString();
|
||||
}
|
||||
|
||||
struct TSpellSummary
|
||||
@@ -232,6 +248,40 @@ struct TSpellSummary
|
||||
uint8 Effects; // set of enum SelectEffect
|
||||
} *SpellSummary;
|
||||
|
||||
void ScriptMgr::CheckIfScriptsInDatabaseExist()
|
||||
{
|
||||
ObjectMgr::ScriptNameContainer& sn = sObjectMgr->GetScriptNames();
|
||||
for (ObjectMgr::ScriptNameContainer::iterator itr = sn.begin(); itr != sn.end(); ++itr)
|
||||
if (uint32 sid = sObjectMgr->GetScriptId((*itr).c_str()))
|
||||
{
|
||||
if (!ScriptRegistry<SpellScriptLoader>::GetScriptById(sid) &&
|
||||
!ScriptRegistry<ServerScript>::GetScriptById(sid) &&
|
||||
!ScriptRegistry<WorldScript>::GetScriptById(sid) &&
|
||||
!ScriptRegistry<FormulaScript>::GetScriptById(sid) &&
|
||||
!ScriptRegistry<WorldMapScript>::GetScriptById(sid) &&
|
||||
!ScriptRegistry<InstanceMapScript>::GetScriptById(sid) &&
|
||||
!ScriptRegistry<BattlegroundMapScript>::GetScriptById(sid) &&
|
||||
!ScriptRegistry<ItemScript>::GetScriptById(sid) &&
|
||||
!ScriptRegistry<CreatureScript>::GetScriptById(sid) &&
|
||||
!ScriptRegistry<GameObjectScript>::GetScriptById(sid) &&
|
||||
!ScriptRegistry<AreaTriggerScript>::GetScriptById(sid) &&
|
||||
!ScriptRegistry<BattlegroundScript>::GetScriptById(sid) &&
|
||||
!ScriptRegistry<OutdoorPvPScript>::GetScriptById(sid) &&
|
||||
!ScriptRegistry<CommandScript>::GetScriptById(sid) &&
|
||||
!ScriptRegistry<WeatherScript>::GetScriptById(sid) &&
|
||||
!ScriptRegistry<AuctionHouseScript>::GetScriptById(sid) &&
|
||||
!ScriptRegistry<ConditionScript>::GetScriptById(sid) &&
|
||||
!ScriptRegistry<VehicleScript>::GetScriptById(sid) &&
|
||||
!ScriptRegistry<DynamicObjectScript>::GetScriptById(sid) &&
|
||||
!ScriptRegistry<TransportScript>::GetScriptById(sid) &&
|
||||
!ScriptRegistry<AchievementCriteriaScript>::GetScriptById(sid) &&
|
||||
!ScriptRegistry<PlayerScript>::GetScriptById(sid) &&
|
||||
!ScriptRegistry<GuildScript>::GetScriptById(sid) &&
|
||||
!ScriptRegistry<GroupScript>::GetScriptById(sid))
|
||||
sLog->outErrorDb("Script named '%s' is assigned in database, but has no code!", (*itr).c_str());
|
||||
}
|
||||
}
|
||||
|
||||
void ScriptMgr::FillSpellSummary()
|
||||
{
|
||||
SpellSummary = new TSpellSummary[sSpellMgr->GetSpellInfoStoreSize()];
|
||||
@@ -403,9 +453,14 @@ void ScriptMgr::OnOpenStateChange(bool open)
|
||||
FOREACH_SCRIPT(WorldScript)->OnOpenStateChange(open);
|
||||
}
|
||||
|
||||
void ScriptMgr::OnConfigLoad(bool reload)
|
||||
void ScriptMgr::OnBeforeConfigLoad(bool reload)
|
||||
{
|
||||
FOREACH_SCRIPT(WorldScript)->OnConfigLoad(reload);
|
||||
FOREACH_SCRIPT(WorldScript)->OnBeforeConfigLoad(reload);
|
||||
}
|
||||
|
||||
void ScriptMgr::OnAfterConfigLoad(bool reload)
|
||||
{
|
||||
FOREACH_SCRIPT(WorldScript)->OnAfterConfigLoad(reload);
|
||||
}
|
||||
|
||||
void ScriptMgr::OnMotdChange(std::string& newMotd)
|
||||
@@ -1292,27 +1347,18 @@ FormulaScript::FormulaScript(const char* name)
|
||||
WorldMapScript::WorldMapScript(const char* name, uint32 mapId)
|
||||
: ScriptObject(name), MapScript<Map>(mapId)
|
||||
{
|
||||
if (GetEntry() && !GetEntry()->IsWorldMap())
|
||||
sLog->outError("WorldMapScript for map %u is invalid.", mapId);
|
||||
|
||||
ScriptRegistry<WorldMapScript>::AddScript(this);
|
||||
}
|
||||
|
||||
InstanceMapScript::InstanceMapScript(const char* name, uint32 mapId)
|
||||
: ScriptObject(name), MapScript<InstanceMap>(mapId)
|
||||
{
|
||||
if (GetEntry() && !GetEntry()->IsDungeon())
|
||||
sLog->outError("InstanceMapScript for map %u is invalid.", mapId);
|
||||
|
||||
ScriptRegistry<InstanceMapScript>::AddScript(this);
|
||||
}
|
||||
|
||||
BattlegroundMapScript::BattlegroundMapScript(const char* name, uint32 mapId)
|
||||
: ScriptObject(name), MapScript<BattlegroundMap>(mapId)
|
||||
{
|
||||
if (GetEntry() && !GetEntry()->IsBattleground())
|
||||
sLog->outError("BattlegroundMapScript for map %u is invalid.", mapId);
|
||||
|
||||
ScriptRegistry<BattlegroundMapScript>::AddScript(this);
|
||||
}
|
||||
|
||||
@@ -1420,6 +1466,7 @@ GroupScript::GroupScript(const char* name)
|
||||
|
||||
// Instantiate static members of ScriptRegistry.
|
||||
template<class TScript> std::map<uint32, TScript*> ScriptRegistry<TScript>::ScriptPointerList;
|
||||
template<class TScript> std::vector<TScript*> ScriptRegistry<TScript>::ALScripts;
|
||||
template<class TScript> uint32 ScriptRegistry<TScript>::_scriptIdCounter = 0;
|
||||
|
||||
// Specialize for each script type class like so:
|
||||
|
||||
@@ -159,6 +159,8 @@ class ScriptObject
|
||||
// Do not override this in scripts; it should be overridden by the various script type classes. It indicates
|
||||
// whether or not this script type must be assigned in the database.
|
||||
virtual bool IsDatabaseBound() const { return false; }
|
||||
virtual bool isAfterLoadScript() const { return IsDatabaseBound(); }
|
||||
virtual void checkValidity() { }
|
||||
|
||||
const std::string& GetName() const { return _name; }
|
||||
|
||||
@@ -242,7 +244,10 @@ class WorldScript : public ScriptObject
|
||||
virtual void OnOpenStateChange(bool /*open*/) { }
|
||||
|
||||
// Called after the world configuration is (re)loaded.
|
||||
virtual void OnConfigLoad(bool /*reload*/) { }
|
||||
virtual void OnAfterConfigLoad(bool /*reload*/) { }
|
||||
|
||||
// Called before the world configuration is (re)loaded.
|
||||
virtual void OnBeforeConfigLoad(bool /*reload*/) { }
|
||||
|
||||
// Called before the message of the day is changed.
|
||||
virtual void OnMotdChange(std::string& /*newMotd*/) { }
|
||||
@@ -296,17 +301,22 @@ class FormulaScript : public ScriptObject
|
||||
template<class TMap> class MapScript : public UpdatableScript<TMap>
|
||||
{
|
||||
MapEntry const* _mapEntry;
|
||||
uint32 _mapId;
|
||||
|
||||
protected:
|
||||
|
||||
MapScript(uint32 mapId)
|
||||
: _mapEntry(sMapStore.LookupEntry(mapId))
|
||||
: _mapId(mapId)
|
||||
{
|
||||
if (!_mapEntry)
|
||||
sLog->outError("Invalid MapScript for %u; no such map ID.", mapId);
|
||||
}
|
||||
|
||||
public:
|
||||
void checkMap() {
|
||||
_mapEntry = sMapStore.LookupEntry(_mapId);
|
||||
|
||||
if (!_mapEntry)
|
||||
sLog->outError("Invalid MapScript for %u; no such map ID.", _mapId);
|
||||
}
|
||||
|
||||
// Gets the MapEntry structure associated with this script. Can return NULL.
|
||||
MapEntry const* GetEntry() { return _mapEntry; }
|
||||
@@ -338,6 +348,17 @@ class WorldMapScript : public ScriptObject, public MapScript<Map>
|
||||
protected:
|
||||
|
||||
WorldMapScript(const char* name, uint32 mapId);
|
||||
|
||||
public:
|
||||
|
||||
bool isAfterLoadScript() const { return true; }
|
||||
|
||||
void checkValidity() {
|
||||
checkMap();
|
||||
|
||||
if (GetEntry() && !GetEntry()->IsWorldMap())
|
||||
sLog->outError("WorldMapScript for map %u is invalid.", GetEntry()->MapID);
|
||||
}
|
||||
};
|
||||
|
||||
class InstanceMapScript : public ScriptObject, public MapScript<InstanceMap>
|
||||
@@ -350,6 +371,13 @@ class InstanceMapScript : public ScriptObject, public MapScript<InstanceMap>
|
||||
|
||||
bool IsDatabaseBound() const { return true; }
|
||||
|
||||
void checkValidity() {
|
||||
checkMap();
|
||||
|
||||
if (GetEntry() && !GetEntry()->IsDungeon())
|
||||
sLog->outError("InstanceMapScript for map %u is invalid.", GetEntry()->MapID);
|
||||
}
|
||||
|
||||
// Gets an InstanceScript object for this instance.
|
||||
virtual InstanceScript* GetInstanceScript(InstanceMap* /*map*/) const { return NULL; }
|
||||
};
|
||||
@@ -359,6 +387,17 @@ class BattlegroundMapScript : public ScriptObject, public MapScript<Battleground
|
||||
protected:
|
||||
|
||||
BattlegroundMapScript(const char* name, uint32 mapId);
|
||||
|
||||
public:
|
||||
|
||||
bool isAfterLoadScript() const { return true; }
|
||||
|
||||
void checkValidity() {
|
||||
checkMap();
|
||||
|
||||
if (GetEntry() && !GetEntry()->IsBattleground())
|
||||
sLog->outError("BattlegroundMapScript for map %u is invalid.", GetEntry()->MapID);
|
||||
}
|
||||
};
|
||||
|
||||
class ItemScript : public ScriptObject
|
||||
@@ -799,6 +838,7 @@ class ScriptMgr
|
||||
void Initialize();
|
||||
void LoadDatabase();
|
||||
void FillSpellSummary();
|
||||
void CheckIfScriptsInDatabaseExist();
|
||||
|
||||
const char* ScriptsVersion() const { return "Integrated Trinity Scripts"; }
|
||||
|
||||
@@ -825,7 +865,8 @@ class ScriptMgr
|
||||
public: /* WorldScript */
|
||||
|
||||
void OnOpenStateChange(bool open);
|
||||
void OnConfigLoad(bool reload);
|
||||
void OnBeforeConfigLoad(bool reload);
|
||||
void OnAfterConfigLoad(bool reload);
|
||||
void OnMotdChange(std::string& newMotd);
|
||||
void OnShutdownInitiate(ShutdownExitCode code, ShutdownMask mask);
|
||||
void OnShutdownCancel();
|
||||
@@ -1023,78 +1064,95 @@ class ScriptRegistry
|
||||
typedef std::map<uint32, TScript*> ScriptMap;
|
||||
typedef typename ScriptMap::iterator ScriptMapIterator;
|
||||
|
||||
typedef std::vector<TScript*> ScriptVector;
|
||||
typedef typename ScriptVector::iterator ScriptVectorIterator;
|
||||
|
||||
// The actual list of scripts. This will be accessed concurrently, so it must not be modified
|
||||
// after server startup.
|
||||
static ScriptMap ScriptPointerList;
|
||||
// After database load scripts
|
||||
static ScriptVector ALScripts;
|
||||
|
||||
static void AddScript(TScript* const script)
|
||||
{
|
||||
ASSERT(script);
|
||||
|
||||
// See if the script is using the same memory as another script. If this happens, it means that
|
||||
// someone forgot to allocate new memory for a script.
|
||||
for (ScriptMapIterator it = ScriptPointerList.begin(); it != ScriptPointerList.end(); ++it)
|
||||
if (!_checkMemory(script))
|
||||
return;
|
||||
|
||||
if (script->isAfterLoadScript())
|
||||
{
|
||||
if (it->second == script)
|
||||
{
|
||||
sLog->outError("Script '%s' has same memory pointer as '%s'.",
|
||||
script->GetName().c_str(), it->second->GetName().c_str());
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (script->IsDatabaseBound())
|
||||
{
|
||||
// Get an ID for the script. An ID only exists if it's a script that is assigned in the database
|
||||
// through a script name (or similar).
|
||||
uint32 id = sObjectMgr->GetScriptId(script->GetName().c_str());
|
||||
if (id)
|
||||
{
|
||||
// Try to find an existing script.
|
||||
bool existing = false;
|
||||
for (ScriptMapIterator it = ScriptPointerList.begin(); it != ScriptPointerList.end(); ++it)
|
||||
{
|
||||
// If the script names match...
|
||||
if (it->second->GetName() == script->GetName())
|
||||
{
|
||||
// ... It exists.
|
||||
existing = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// If the script isn't assigned -> assign it!
|
||||
if (!existing)
|
||||
{
|
||||
ScriptPointerList[id] = script;
|
||||
sScriptMgr->IncrementScriptCount();
|
||||
}
|
||||
else
|
||||
{
|
||||
// If the script is already assigned -> delete it!
|
||||
sLog->outError("Script '%s' already assigned with the same script name, so the script can't work.",
|
||||
script->GetName().c_str());
|
||||
|
||||
ASSERT(false); // Error that should be fixed ASAP.
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// The script uses a script name from database, but isn't assigned to anything.
|
||||
if (script->GetName().find("Smart") == std::string::npos)
|
||||
sLog->outErrorDb("Script named '%s' does not have a script name assigned in database.",
|
||||
script->GetName().c_str());
|
||||
}
|
||||
ALScripts.push_back(script);
|
||||
}
|
||||
else
|
||||
{
|
||||
script->checkValidity();
|
||||
|
||||
// We're dealing with a code-only script; just add it.
|
||||
ScriptPointerList[_scriptIdCounter++] = script;
|
||||
sScriptMgr->IncrementScriptCount();
|
||||
}
|
||||
}
|
||||
|
||||
static void AddALScripts() {
|
||||
for(ScriptVectorIterator it = ALScripts.begin(); it != ALScripts.end(); ++it) {
|
||||
TScript* const script = *it;
|
||||
|
||||
script->checkValidity();
|
||||
|
||||
if (script->IsDatabaseBound()) {
|
||||
|
||||
if (!_checkMemory(script))
|
||||
return;
|
||||
|
||||
// Get an ID for the script. An ID only exists if it's a script that is assigned in the database
|
||||
// through a script name (or similar).
|
||||
uint32 id = sObjectMgr->GetScriptId(script->GetName().c_str());
|
||||
if (id)
|
||||
{
|
||||
// Try to find an existing script.
|
||||
bool existing = false;
|
||||
for (ScriptMapIterator it = ScriptPointerList.begin(); it != ScriptPointerList.end(); ++it)
|
||||
{
|
||||
// If the script names match...
|
||||
if (it->second->GetName() == script->GetName())
|
||||
{
|
||||
// ... It exists.
|
||||
existing = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// If the script isn't assigned -> assign it!
|
||||
if (!existing)
|
||||
{
|
||||
ScriptPointerList[id] = script;
|
||||
sScriptMgr->IncrementScriptCount();
|
||||
}
|
||||
else
|
||||
{
|
||||
// If the script is already assigned -> delete it!
|
||||
sLog->outError("Script '%s' already assigned with the same script name, so the script can't work.",
|
||||
script->GetName().c_str());
|
||||
|
||||
ASSERT(false); // Error that should be fixed ASAP.
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// The script uses a script name from database, but isn't assigned to anything.
|
||||
if (script->GetName().find("Smart") == std::string::npos)
|
||||
sLog->outErrorDb("Script named '%s' does not have a script name assigned in database.",
|
||||
script->GetName().c_str());
|
||||
}
|
||||
} else {
|
||||
// We're dealing with a code-only script; just add it.
|
||||
ScriptPointerList[_scriptIdCounter++] = script;
|
||||
sScriptMgr->IncrementScriptCount();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Gets a script by its ID (assigned by ObjectMgr).
|
||||
static TScript* GetScriptById(uint32 id)
|
||||
{
|
||||
@@ -1106,6 +1164,24 @@ class ScriptRegistry
|
||||
}
|
||||
|
||||
private:
|
||||
// See if the script is using the same memory as another script. If this happens, it means that
|
||||
// someone forgot to allocate new memory for a script.
|
||||
static bool _checkMemory(TScript* const script) {
|
||||
// See if the script is using the same memory as another script. If this happens, it means that
|
||||
// someone forgot to allocate new memory for a script.
|
||||
for (ScriptMapIterator it = ScriptPointerList.begin(); it != ScriptPointerList.end(); ++it)
|
||||
{
|
||||
if (it->second == script)
|
||||
{
|
||||
sLog->outError("Script '%s' has same memory pointer as '%s'.",
|
||||
script->GetName().c_str(), it->second->GetName().c_str());
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// Counter used for code-only scripts.
|
||||
static uint32 _scriptIdCounter;
|
||||
|
||||
@@ -1930,39 +1930,22 @@ void Spell::SearchChainTargets(std::list<WorldObject*>& targets, uint32 chainTar
|
||||
|
||||
// max dist which spell can reach
|
||||
float searchRadius = jumpRadius;
|
||||
if (isBouncingFar && !isChainHeal)
|
||||
if (isBouncingFar)
|
||||
searchRadius *= chainTargets;
|
||||
|
||||
// Xinef: the distance should be increased by caster size, it is neglected in latter calculations
|
||||
std::list<WorldObject*> tempTargets;
|
||||
SearchAreaTargets(tempTargets, searchRadius, (m_spellInfo->DmgClass == SPELL_DAMAGE_CLASS_MELEE ? m_caster : target), m_caster, objectType, selectType, condList);
|
||||
SearchAreaTargets(tempTargets, searchRadius, target, m_caster, objectType, selectType, condList);
|
||||
tempTargets.remove(target);
|
||||
|
||||
// xinef: if we have select category nearby and checktype entry, select random of what we have, not by distance
|
||||
if (selectCategory == TARGET_SELECT_CATEGORY_NEARBY && selectType == TARGET_CHECK_ENTRY)
|
||||
{
|
||||
Trinity::Containers::RandomResizeList(tempTargets, chainTargets);
|
||||
targets = tempTargets;
|
||||
return;
|
||||
}
|
||||
|
||||
// remove targets which are always invalid for chain spells
|
||||
// for some spells allow only chain targets in front of caster (swipe for example)
|
||||
if (!isBouncingFar)
|
||||
{
|
||||
float allowedArc = 0.0f;
|
||||
if (m_spellInfo->DmgClass == SPELL_DAMAGE_CLASS_MELEE)
|
||||
allowedArc = (M_PI*7.0f) / 18.0f; // 70 degrees
|
||||
else if (m_spellInfo->DmgClass == SPELL_DAMAGE_CLASS_RANGED)
|
||||
allowedArc = M_PI*0.5f; // 90 degrees
|
||||
|
||||
for (std::list<WorldObject*>::iterator itr = tempTargets.begin(); itr != tempTargets.end();)
|
||||
{
|
||||
std::list<WorldObject*>::iterator checkItr = itr++;
|
||||
if (!m_caster->HasInArc(static_cast<float>(M_PI), *checkItr))
|
||||
tempTargets.erase(checkItr);
|
||||
else if (allowedArc > 0.0f && !m_caster->HasInArc(allowedArc, *checkItr, (*checkItr)->GetObjectSize()))
|
||||
tempTargets.erase(checkItr);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1976,14 +1959,10 @@ void Spell::SearchChainTargets(std::list<WorldObject*>& targets, uint32 chainTar
|
||||
uint32 maxHPDeficit = 0;
|
||||
for (std::list<WorldObject*>::iterator itr = tempTargets.begin(); itr != tempTargets.end(); ++itr)
|
||||
{
|
||||
if (Unit* itrTarget = (*itr)->ToUnit())
|
||||
if (Unit* unit = (*itr)->ToUnit())
|
||||
{
|
||||
uint32 deficit = itrTarget->GetMaxHealth() - itrTarget->GetHealth();
|
||||
// xinef: chain should not heal targets with max health
|
||||
if (deficit == 0)
|
||||
continue;
|
||||
|
||||
if ((deficit > maxHPDeficit || foundItr == tempTargets.end()) && target->IsWithinDist(itrTarget, jumpRadius) && target->IsWithinLOSInMap(itrTarget))
|
||||
uint32 deficit = unit->GetMaxHealth() - unit->GetHealth();
|
||||
if ((deficit > maxHPDeficit || foundItr == tempTargets.end()) && target->IsWithinDist(unit, jumpRadius) && target->IsWithinLOSInMap(unit))
|
||||
{
|
||||
foundItr = itr;
|
||||
maxHPDeficit = deficit;
|
||||
|
||||
@@ -3133,6 +3133,9 @@ void SpellMgr::LoadSpellCustomAttr()
|
||||
spellInfo->RecoveryTime = 1500;
|
||||
spellInfo->_requireCooldownInfo = true;
|
||||
break;
|
||||
case 44535: // Spirit Heal, abilities also have no cost
|
||||
spellInfo->Effects[EFFECT_0].MiscValue = 127;
|
||||
break;
|
||||
}
|
||||
|
||||
switch (spellInfo->SpellFamilyName)
|
||||
@@ -3558,12 +3561,12 @@ void SpellMgr::LoadDbcDataCorrections()
|
||||
spellInfo->EffectSpellClassMask[0][0] = 0;
|
||||
spellInfo->EffectSpellClassMask[0][2] = 0x8000000;
|
||||
break;
|
||||
// Judgements Facing
|
||||
/* Judgements Facing -- SCEICCO: not sure this is offylike
|
||||
case 20271:
|
||||
case 53407:
|
||||
case 53408:
|
||||
spellInfo->FacingCasterFlags |= SPELL_FACING_FLAG_INFRONT;
|
||||
break;
|
||||
break;*/
|
||||
// Seal of Light trigger
|
||||
case 20167:
|
||||
spellInfo->spellLevel = 0;
|
||||
|
||||
@@ -32,11 +32,11 @@ inline float GetAge(uint64 t) { return float(time(NULL) - t) / DAY; }
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// GM ticket
|
||||
GmTicket::GmTicket() : _id(0), _playerGuid(0), _posX(0), _posY(0), _posZ(0), _mapId(0), _createTime(0), _lastModifiedTime(0),
|
||||
_closedBy(0), _assignedTo(0), _completed(false), _escalatedStatus(TICKET_UNASSIGNED), _viewed(false),
|
||||
GmTicket::GmTicket() : _id(0), _type(TICKET_TYPE_OPEN), _playerGuid(0), _posX(0), _posY(0), _posZ(0), _mapId(0), _createTime(0), _lastModifiedTime(0),
|
||||
_closedBy(0), _resolvedBy(0), _assignedTo(0), _completed(false), _escalatedStatus(TICKET_UNASSIGNED), _viewed(false),
|
||||
_needResponse(false), _needMoreHelp(false) { }
|
||||
|
||||
GmTicket::GmTicket(Player* player) : _createTime(time(NULL)), _lastModifiedTime(time(NULL)), _closedBy(0), _assignedTo(0), _completed(false), _escalatedStatus(TICKET_UNASSIGNED), _viewed(false), _needMoreHelp(false)
|
||||
GmTicket::GmTicket(Player* player) : _type(TICKET_TYPE_OPEN), _createTime(time(NULL)), _lastModifiedTime(time(NULL)), _closedBy(0), _resolvedBy(0), _assignedTo(0), _completed(false), _escalatedStatus(TICKET_UNASSIGNED), _viewed(false), _needMoreHelp(false)
|
||||
{
|
||||
_id = sTicketMgr->GenerateTicketId();
|
||||
_playerName = player->GetName();
|
||||
@@ -47,10 +47,11 @@ GmTicket::~GmTicket() { }
|
||||
|
||||
bool GmTicket::LoadFromDB(Field* fields)
|
||||
{
|
||||
// 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
|
||||
// ticketId, guid, name, message, createTime, mapId, posX, posY, posZ, lastModifiedTime, closedBy, assignedTo, comment, response, completed, escalated, viewed, haveTicket
|
||||
// 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
|
||||
// id, type, playerGuid, name, message, createTime, mapId, posX, posY, posZ, lastModifiedTime, closedBy, assignedTo, comment, response, completed, escalated, viewed, haveTicket, resolvedBy
|
||||
uint8 index = 0;
|
||||
_id = fields[ index].GetUInt32();
|
||||
_type = TicketType(fields[++index].GetUInt8());
|
||||
_playerGuid = MAKE_NEW_GUID(fields[++index].GetUInt32(), 0, HIGHGUID_PLAYER);
|
||||
_playerName = fields[++index].GetString();
|
||||
_message = fields[++index].GetString();
|
||||
@@ -68,16 +69,19 @@ bool GmTicket::LoadFromDB(Field* fields)
|
||||
_escalatedStatus = GMTicketEscalationStatus(fields[++index].GetUInt8());
|
||||
_viewed = fields[++index].GetBool();
|
||||
_needMoreHelp = fields[++index].GetBool();
|
||||
_resolvedBy = fields[++index].GetInt32();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void GmTicket::SaveToDB(SQLTransaction& trans) const
|
||||
{
|
||||
// 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
|
||||
// ticketId, guid, name, message, createTime, mapId, posX, posY, posZ, lastModifiedTime, closedBy, assignedTo, comment, completed, escalated, viewed
|
||||
// 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
|
||||
// id, type, playerGuid, name, description, createTime, mapId, posX, posY, posZ, lastModifiedTime, closedBy, assignedTo, comment, response, completed, escalated, viewed, needMoreHelp, resolvedBy
|
||||
uint8 index = 0;
|
||||
PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_REP_GM_TICKET);
|
||||
stmt->setUInt32( index, _id);
|
||||
stmt->setUInt8 (++index, uint8(_type));
|
||||
stmt->setUInt32(++index, GUID_LOPART(_playerGuid));
|
||||
stmt->setString(++index, _playerName);
|
||||
stmt->setString(++index, _message);
|
||||
@@ -95,6 +99,7 @@ void GmTicket::SaveToDB(SQLTransaction& trans) const
|
||||
stmt->setUInt8 (++index, uint8(_escalatedStatus));
|
||||
stmt->setBool (++index, _viewed);
|
||||
stmt->setBool (++index, _needMoreHelp);
|
||||
stmt->setInt32 (++index, GUID_LOPART(_resolvedBy));
|
||||
|
||||
CharacterDatabase.ExecuteOrAppend(trans, stmt);
|
||||
}
|
||||
@@ -363,6 +368,20 @@ void TicketMgr::RemoveTicket(uint32 ticketId)
|
||||
}
|
||||
}
|
||||
|
||||
void TicketMgr::ResolveAndCloseTicket(uint32 ticketId, int64 source)
|
||||
{
|
||||
if (GmTicket* ticket = GetTicket(ticketId))
|
||||
{
|
||||
SQLTransaction trans = SQLTransaction(NULL);
|
||||
ticket->SetClosedBy(source);
|
||||
ticket->SetResolvedBy(source);
|
||||
if (source)
|
||||
--_openTicketCount;
|
||||
ticket->SaveToDB(trans);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void TicketMgr::ShowList(ChatHandler& handler, bool onlineOnly) const
|
||||
{
|
||||
handler.SendSysMessage(onlineOnly ? LANG_COMMAND_TICKETSHOWONLINELIST : LANG_COMMAND_TICKETSHOWLIST);
|
||||
|
||||
@@ -78,6 +78,13 @@ enum LagReportType
|
||||
LAG_REPORT_TYPE_SPELL = 6
|
||||
};
|
||||
|
||||
enum TicketType
|
||||
{
|
||||
TICKET_TYPE_OPEN = 0,
|
||||
TICKET_TYPE_CLOSED = 1,
|
||||
TICKET_TYPE_CHARACTER_DELETED = 2,
|
||||
};
|
||||
|
||||
class GmTicket
|
||||
{
|
||||
public:
|
||||
@@ -85,7 +92,7 @@ public:
|
||||
GmTicket(Player* player);
|
||||
~GmTicket();
|
||||
|
||||
bool IsClosed() const { return _closedBy; }
|
||||
bool IsClosed() const { return _type != TICKET_TYPE_OPEN; }
|
||||
bool IsCompleted() const { return _completed; }
|
||||
bool IsFromPlayer(uint64 guid) const { return guid == _playerGuid; }
|
||||
bool IsAssigned() const { return _assignedTo != 0; }
|
||||
@@ -119,7 +126,8 @@ public:
|
||||
else if (_escalatedStatus == TICKET_UNASSIGNED)
|
||||
_escalatedStatus = TICKET_ASSIGNED;
|
||||
}
|
||||
void SetClosedBy(int64 value) { _closedBy = value; }
|
||||
void SetClosedBy(int64 value) { _closedBy = value; _type = TICKET_TYPE_CLOSED; }
|
||||
void SetResolvedBy(int64 value) { _resolvedBy = value; }
|
||||
void SetCompleted() { _completed = true; }
|
||||
void SetMessage(std::string const& message)
|
||||
{
|
||||
@@ -151,6 +159,7 @@ public:
|
||||
private:
|
||||
uint32 _id;
|
||||
uint64 _playerGuid;
|
||||
TicketType _type; // 0 = Open, 1 = Closed, 2 = Character deleted
|
||||
std::string _playerName;
|
||||
float _posX;
|
||||
float _posY;
|
||||
@@ -159,7 +168,8 @@ private:
|
||||
std::string _message;
|
||||
uint64 _createTime;
|
||||
uint64 _lastModifiedTime;
|
||||
int64 _closedBy; // 0 = Open, -1 = Console, playerGuid = player abandoned ticket, other = GM who closed it.
|
||||
int64 _closedBy; // 0 = Open or Closed by Console (if type = 1), playerGuid = GM who closed it or player abandoned ticket or read the GM response message.
|
||||
int64 _resolvedBy; // 0 = Open, -1 = Resolved by Console, GM who resolved it by closing or completing the ticket.
|
||||
uint64 _assignedTo;
|
||||
std::string _comment;
|
||||
bool _completed;
|
||||
@@ -213,6 +223,7 @@ public:
|
||||
|
||||
void AddTicket(GmTicket* ticket);
|
||||
void CloseTicket(uint32 ticketId, int64 source = -1);
|
||||
void ResolveAndCloseTicket(uint32 ticketId, int64 source); // used when GM resolves a ticket by simply closing it
|
||||
void RemoveTicket(uint32 ticketId);
|
||||
|
||||
bool GetStatus() const { return _status; }
|
||||
|
||||
@@ -429,13 +429,18 @@ void World::LoadConfigSettings(bool reload)
|
||||
{
|
||||
if (!sConfigMgr->Reload())
|
||||
{
|
||||
sLog->outError("World settings reload fail: can't read settings from %s.", sConfigMgr->GetFilename().c_str());
|
||||
sLog->outError("World settings reload fail: can't read settings.");
|
||||
return;
|
||||
}
|
||||
|
||||
sLog->ReloadConfig(); // Reload log levels and filters
|
||||
}
|
||||
|
||||
sScriptMgr->OnBeforeConfigLoad(reload);
|
||||
|
||||
// Reload log levels and filters
|
||||
// doing it again to allow sScriptMgr
|
||||
// to change log confs at start
|
||||
sLog->ReloadConfig();
|
||||
|
||||
///- Read the player limit and the Message of the day from the config file
|
||||
if (!reload)
|
||||
SetPlayerAmountLimit(sConfigMgr->GetIntDefault("PlayerLimit", 100));
|
||||
@@ -443,6 +448,7 @@ void World::LoadConfigSettings(bool reload)
|
||||
|
||||
///- Read ticket system setting from the config file
|
||||
m_bool_configs[CONFIG_ALLOW_TICKETS] = sConfigMgr->GetBoolDefault("AllowTickets", true);
|
||||
m_bool_configs[CONFIG_DELETE_CHARACTER_TICKET_TRACE] = sConfigMgr->GetBoolDefault("DeletedCharacterTicketTrace", false);
|
||||
|
||||
///- Get string for new logins (newly created characters)
|
||||
SetNewCharString(sConfigMgr->GetStringDefault("PlayerStart.String", ""));
|
||||
@@ -1043,6 +1049,7 @@ void World::LoadConfigSettings(bool reload)
|
||||
m_float_configs[CONFIG_LISTEN_RANGE_YELL] = sConfigMgr->GetFloatDefault("ListenRange.Yell", 300.0f);
|
||||
|
||||
m_bool_configs[CONFIG_BATTLEGROUND_CAST_DESERTER] = sConfigMgr->GetBoolDefault("Battleground.CastDeserter", true);
|
||||
m_bool_configs[CONFIG_BATTLEGROUND_RANDOM_CROSSFACTION] = sConfigMgr->GetBoolDefault("Battleground.RandomCrossFaction.Enable", true); // [AZTH] RBG Crossfaction
|
||||
m_bool_configs[CONFIG_BATTLEGROUND_QUEUE_ANNOUNCER_ENABLE] = sConfigMgr->GetBoolDefault("Battleground.QueueAnnouncer.Enable", false);
|
||||
m_int_configs[CONFIG_BATTLEGROUND_PREMATURE_FINISH_TIMER] = sConfigMgr->GetIntDefault ("Battleground.PrematureFinishTimer", 5 * MINUTE * IN_MILLISECONDS);
|
||||
m_int_configs[CONFIG_BATTLEGROUND_PREMADE_GROUP_WAIT_FOR_MATCH] = sConfigMgr->GetIntDefault ("Battleground.PremadeGroupWaitForMatch", 30 * MINUTE * IN_MILLISECONDS);
|
||||
@@ -1234,8 +1241,7 @@ void World::LoadConfigSettings(bool reload)
|
||||
m_int_configs[CONFIG_BIRTHDAY_TIME] = sConfigMgr->GetIntDefault("BirthdayTime", 1222964635);
|
||||
|
||||
// call ScriptMgr if we're reloading the configuration
|
||||
if (reload)
|
||||
sScriptMgr->OnConfigLoad(reload);
|
||||
sScriptMgr->OnAfterConfigLoad(reload);
|
||||
}
|
||||
|
||||
extern void LoadGameObjectModelList();
|
||||
@@ -1251,6 +1257,9 @@ void World::SetInitialWorldSettings()
|
||||
|
||||
///- Initialize detour memory management
|
||||
dtAllocSetCustom(dtCustomAlloc, dtCustomFree);
|
||||
|
||||
sLog->outString("Initializing Scripts...");
|
||||
sScriptMgr->Initialize();
|
||||
|
||||
///- Initialize config settings
|
||||
LoadConfigSettings();
|
||||
@@ -1698,9 +1707,8 @@ void World::SetInitialWorldSettings()
|
||||
sLog->outString("Loading Creature Text Locales...");
|
||||
sCreatureTextMgr->LoadCreatureTextLocales();
|
||||
|
||||
sLog->outString("Initializing Scripts...");
|
||||
sScriptMgr->Initialize();
|
||||
sScriptMgr->OnConfigLoad(false); // must be done after the ScriptMgr has been properly initialized
|
||||
sLog->outString("Loading Scripts...");
|
||||
sScriptMgr->LoadDatabase();
|
||||
|
||||
sLog->outString("Validating spell scripts...");
|
||||
sObjectMgr->ValidateSpellScripts();
|
||||
|
||||
@@ -127,6 +127,7 @@ enum WorldBoolConfigs
|
||||
CONFIG_DIE_COMMAND_MODE,
|
||||
CONFIG_DECLINED_NAMES_USED,
|
||||
CONFIG_BATTLEGROUND_CAST_DESERTER,
|
||||
CONFIG_BATTLEGROUND_RANDOM_CROSSFACTION, // [AZTH] RBG Crossfaction
|
||||
CONFIG_BATTLEGROUND_QUEUE_ANNOUNCER_ENABLE,
|
||||
CONFIG_BG_XP_FOR_KILL,
|
||||
CONFIG_ARENA_AUTO_DISTRIBUTE_POINTS,
|
||||
@@ -143,6 +144,7 @@ enum WorldBoolConfigs
|
||||
CONFIG_SHOW_KICK_IN_WORLD,
|
||||
CONFIG_AUTOBROADCAST,
|
||||
CONFIG_ALLOW_TICKETS,
|
||||
CONFIG_DELETE_CHARACTER_TICKET_TRACE,
|
||||
CONFIG_DBC_ENFORCE_ITEM_ATTRIBUTES,
|
||||
CONFIG_PRESERVE_CUSTOM_CHANNELS,
|
||||
CONFIG_WINTERGRASP_ENABLE,
|
||||
|
||||
Reference in New Issue
Block a user