Merge branch 'master' into git

This commit is contained in:
ShinDarth
2016-08-07 14:55:21 +02:00
84 changed files with 1531 additions and 680 deletions
+11 -9
View File
@@ -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);
}
}
}
}
+1 -1
View File
@@ -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)
+34 -3
View File
@@ -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);
+1
View File
@@ -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}
+151 -1
View File
@@ -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);
}
}
}
+10
View File
@@ -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:
+34 -17
View File
@@ -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);
+6 -1
View File
@@ -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();
+19 -2
View File
@@ -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;
+2
View File
@@ -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;
+138 -4
View File
@@ -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
{
+3 -1
View File
@@ -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);
+20 -14
View File
@@ -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
-36
View File
@@ -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
+69 -22
View File
@@ -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:
+135 -59
View File
@@ -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;
+5 -26
View File
@@ -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;
+5 -2
View File
@@ -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;
+26 -7
View File
@@ -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);
+14 -3
View File
@@ -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; }
+16 -8
View File
@@ -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();
+2
View File
@@ -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,