aboutsummaryrefslogtreecommitdiff
path: root/src/game
diff options
context:
space:
mode:
Diffstat (limited to 'src/game')
-rw-r--r--src/game/AchievementMgr.cpp366
-rw-r--r--src/game/AchievementMgr.h103
-rw-r--r--src/game/BattleGround.cpp286
-rw-r--r--src/game/BattleGround.h4
-rw-r--r--src/game/BattleGroundAB.cpp118
-rw-r--r--src/game/BattleGroundAV.cpp4
-rw-r--r--src/game/BattleGroundBE.cpp14
-rw-r--r--src/game/BattleGroundEY.cpp118
-rw-r--r--src/game/BattleGroundHandler.cpp208
-rw-r--r--src/game/BattleGroundMgr.cpp446
-rw-r--r--src/game/BattleGroundMgr.h23
-rw-r--r--src/game/BattleGroundNA.cpp14
-rw-r--r--src/game/BattleGroundRL.cpp14
-rw-r--r--src/game/BattleGroundSA.cpp2
-rw-r--r--src/game/BattleGroundWS.cpp128
-rw-r--r--src/game/CMakeLists.txt4
-rw-r--r--src/game/CharacterHandler.cpp11
-rw-r--r--src/game/Chat.cpp11
-rw-r--r--src/game/Chat.h7
-rw-r--r--src/game/Creature.cpp3
-rw-r--r--src/game/Creature.h28
-rw-r--r--src/game/CreatureAI.cpp32
-rw-r--r--src/game/CreatureAI.h2
-rw-r--r--src/game/CreatureAIRegistry.cpp2
-rw-r--r--src/game/CreatureAISelector.cpp35
-rw-r--r--src/game/CreatureEventAI.cpp1661
-rw-r--r--src/game/CreatureEventAI.h309
-rw-r--r--src/game/CreatureEventAIMgr.cpp560
-rw-r--r--src/game/CreatureEventAIMgr.h46
-rw-r--r--src/game/CreatureGroups.cpp70
-rw-r--r--src/game/CreatureGroups.h9
-rw-r--r--src/game/DBCEnums.h6
-rw-r--r--src/game/DBCStructure.h2
-rw-r--r--src/game/GameObject.cpp47
-rw-r--r--src/game/GameObject.h14
-rw-r--r--src/game/GridNotifiers.h113
-rw-r--r--src/game/HomeMovementGenerator.cpp2
-rw-r--r--src/game/InstanceData.h4
-rw-r--r--src/game/Language.h3
-rw-r--r--src/game/Level0.cpp1
-rw-r--r--src/game/Level3.cpp33
-rw-r--r--src/game/Makefile.am267
-rw-r--r--src/game/Map.cpp51
-rw-r--r--src/game/Map.h6
-rw-r--r--src/game/MiscHandler.cpp16
-rw-r--r--src/game/MotionMaster.cpp16
-rw-r--r--src/game/MotionMaster.h3
-rw-r--r--src/game/MovementHandler.cpp88
-rw-r--r--src/game/NPCHandler.cpp49
-rw-r--r--src/game/Object.cpp102
-rw-r--r--src/game/Object.h9
-rw-r--r--src/game/ObjectAccessor.h11
-rw-r--r--src/game/ObjectGridLoader.cpp6
-rw-r--r--src/game/ObjectMgr.cpp245
-rw-r--r--src/game/Pet.cpp252
-rw-r--r--src/game/Pet.h13
-rw-r--r--src/game/PetitionsHandler.cpp4
-rw-r--r--src/game/Player.cpp272
-rw-r--r--src/game/Player.h35
-rw-r--r--src/game/Spell.cpp55
-rw-r--r--src/game/Spell.h2
-rw-r--r--src/game/SpellAuras.cpp277
-rw-r--r--src/game/SpellAuras.h9
-rw-r--r--src/game/SpellEffects.cpp215
-rw-r--r--src/game/SpellHandler.cpp2
-rw-r--r--src/game/SpellMgr.cpp38
-rw-r--r--src/game/TemporarySummon.cpp26
-rw-r--r--src/game/Unit.cpp699
-rw-r--r--src/game/Unit.h42
-rw-r--r--src/game/World.cpp25
-rw-r--r--src/game/World.h2
-rw-r--r--src/game/WorldSession.cpp2
72 files changed, 5631 insertions, 2071 deletions
diff --git a/src/game/AchievementMgr.cpp b/src/game/AchievementMgr.cpp
index da192844a70..26df402e5aa 100644
--- a/src/game/AchievementMgr.cpp
+++ b/src/game/AchievementMgr.cpp
@@ -37,56 +37,6 @@
INSTANTIATE_SINGLETON_1(AchievementGlobalMgr);
-const CriteriaCastSpellRequirement AchievementGlobalMgr::m_criteriaCastSpellRequirements[CRITERIA_CAST_SPELL_REQ_COUNT] =
- {
- {5272, 3057, 0, 0},
- {5273, 2784, 0, 0},
- {5752, 9099, 0, 0},
- {5753, 8403, 0, 0},
- {5772, 0, 0, RACE_GNOME},
- {5774, 0, 0, RACE_BLOODELF},
- {5775, 0, 0, RACE_DRAENEI},
- {5776, 0, 0, RACE_DWARF},
- {5777, 0, 0, RACE_HUMAN},
- {5778, 0, 0, RACE_NIGHTELF},
- {5779, 0, 0, RACE_ORC},
- {5780, 0, 0, RACE_TAUREN},
- {5781, 0, 0, RACE_TROLL},
- {5782, 0, 0, RACE_UNDEAD_PLAYER},
- {6225, 5661, 0, 0},
- {6226, 26044, 0, 0},
- {6228, 739, 0, 0},
- {6229, 927, 0, 0},
- {6230, 1444, 0, 0},
- {6231, 8140, 0, 0},
- {6232, 5489, 0, 0},
- {6233,12336, 0, 0},
- {6234, 1351, 0, 0},
- {6235, 5484, 0, 0},
- {6236, 1182, 0, 0},
- {6237, 0, CLASS_DEATH_KNIGHT, RACE_ORC},
- {6238, 0, CLASS_WARRIOR, RACE_HUMAN},
- {6239, 0, CLASS_SHAMAN, RACE_TAUREN},
- {6240, 0, CLASS_DRUID, RACE_NIGHTELF},
- {6241, 0, CLASS_ROGUE, RACE_UNDEAD_PLAYER},
- {6242, 0, CLASS_HUNTER, RACE_TROLL},
- {6243, 0, CLASS_MAGE, RACE_GNOME},
- {6244, 0, CLASS_PALADIN, RACE_DWARF},
- {6245, 0, CLASS_WARLOCK, RACE_BLOODELF},
- {6246, 0, CLASS_PRIEST, RACE_DRAENEI},
- {6312, 0, CLASS_WARLOCK, RACE_GNOME},
- {6313, 0, CLASS_DEATH_KNIGHT, RACE_HUMAN},
- {6314, 0, CLASS_PRIEST, RACE_NIGHTELF},
- {6315, 0, CLASS_SHAMAN, RACE_ORC},
- {6316, 0, CLASS_DRUID, RACE_TAUREN},
- {6317, 0, CLASS_ROGUE, RACE_TROLL},
- {6318, 0, CLASS_WARRIOR, RACE_UNDEAD_PLAYER},
- {6319, 0, CLASS_MAGE, RACE_BLOODELF},
- {6320, 0, CLASS_PALADIN, RACE_DRAENEI},
- {6321, 0, CLASS_HUNTER, RACE_DWARF},
- {6662, 31261, 0, 0}
- };
-
namespace MaNGOS
{
class AchievementChatBuilder
@@ -117,6 +67,156 @@ namespace MaNGOS
};
} // namespace MaNGOS
+
+bool AchievementCriteriaData::IsValid(AchievementCriteriaEntry const* criteria)
+{
+ if(dataType >= MAX_ACHIEVEMENT_CRITERIA_DATA_TYPE)
+ {
+ sLog.outErrorDb( "Table `achievement_criteria_data` for criteria (Entry: %u) have wrong data type (%u), ignore.", criteria->ID,dataType);
+ return false;
+ }
+
+ switch(criteria->requiredType)
+ {
+ case ACHIEVEMENT_CRITERIA_TYPE_CAST_SPELL2:
+ case ACHIEVEMENT_CRITERIA_TYPE_DO_EMOTE:
+ break;
+ default:
+ sLog.outErrorDb( "Table `achievement_criteria_data` have data for not supported criteria type (Entry: %u Type: %u), ignore.", criteria->ID, criteria->requiredType);
+ return false;
+ }
+
+ switch(dataType)
+ {
+ case ACHIEVEMENT_CRITERIA_DATA_TYPE_NONE:
+ return true;
+ case ACHIEVEMENT_CRITERIA_DATA_TYPE_T_CREATURE:
+ if(!creature.id || !objmgr.GetCreatureTemplate(creature.id))
+ {
+ sLog.outErrorDb( "Table `achievement_criteria_data` (Entry: %u Type: %u) for data type ACHIEVEMENT_CRITERIA_DATA_TYPE_CREATURE (%u) have not existed creature id in value1 (%u), ignore.",
+ criteria->ID, criteria->requiredType,dataType,creature.id);
+ return false;
+ }
+ return true;
+ case ACHIEVEMENT_CRITERIA_DATA_TYPE_T_PLAYER_CLASS_RACE:
+ if(!classRace.class_id && !classRace.race_id)
+ {
+ sLog.outErrorDb( "Table `achievement_criteria_data` (Entry: %u Type: %u) for data type ACHIEVEMENT_CRITERIA_DATA_TYPE_PLAYER_CLASS_RACE (%u) must have not 0 in one from value fields, ignore.",
+ criteria->ID, criteria->requiredType,dataType);
+ return false;
+ }
+ if(classRace.class_id && ((1 << (classRace.class_id-1)) & CLASSMASK_ALL_PLAYABLE)==0)
+ {
+ sLog.outErrorDb( "Table `achievement_criteria_data` (Entry: %u Type: %u) for data type ACHIEVEMENT_CRITERIA_DATA_TYPE_CREATURE (%u) have not existed class in value1 (%u), ignore.",
+ criteria->ID, criteria->requiredType,dataType,classRace.class_id);
+ return false;
+ }
+ if(classRace.race_id && ((1 << (classRace.race_id-1)) & RACEMASK_ALL_PLAYABLE)==0)
+ {
+ sLog.outErrorDb( "Table `achievement_criteria_data` (Entry: %u Type: %u) for data type ACHIEVEMENT_CRITERIA_DATA_TYPE_CREATURE (%u) have not existed race in value2 (%u), ignore.",
+ criteria->ID, criteria->requiredType,dataType,classRace.race_id);
+ return false;
+ }
+ return true;
+ case ACHIEVEMENT_CRITERIA_DATA_TYPE_T_PLAYER_LESS_HEALTH:
+ if(health.percent < 1 || health.percent > 100)
+ {
+ sLog.outErrorDb( "Table `achievement_criteria_data` (Entry: %u Type: %u) for data type ACHIEVEMENT_CRITERIA_DATA_TYPE_PLAYER_LESS_HEALTH (%u) have wrong percent value in value1 (%u), ignore.",
+ criteria->ID, criteria->requiredType,dataType,health.percent);
+ return false;
+ }
+ return true;
+ case ACHIEVEMENT_CRITERIA_DATA_TYPE_T_PLAYER_DEAD:
+ return true;
+ case ACHIEVEMENT_CRITERIA_DATA_TYPE_S_AURA:
+ case ACHIEVEMENT_CRITERIA_DATA_TYPE_T_AURA:
+ {
+ SpellEntry const* spellEntry = sSpellStore.LookupEntry(aura.spell_id);
+ if(!spellEntry)
+ {
+ sLog.outErrorDb( "Table `achievement_criteria_data` (Entry: %u Type: %u) for data type %s (%u) have wrong spell id in value1 (%u), ignore.",
+ criteria->ID, criteria->requiredType,(dataType==ACHIEVEMENT_CRITERIA_DATA_TYPE_S_AURA?"ACHIEVEMENT_CRITERIA_DATA_TYPE_S_AURA":"ACHIEVEMENT_CRITERIA_DATA_TYPE_T_AURA"),dataType,aura.spell_id);
+ return false;
+ }
+ if(aura.effect_idx >= 3)
+ {
+ sLog.outErrorDb( "Table `achievement_criteria_data` (Entry: %u Type: %u) for data type %s (%u) have wrong spell effect index in value2 (%u), ignore.",
+ criteria->ID, criteria->requiredType,(dataType==ACHIEVEMENT_CRITERIA_DATA_TYPE_S_AURA?"ACHIEVEMENT_CRITERIA_DATA_TYPE_S_AURA":"ACHIEVEMENT_CRITERIA_DATA_TYPE_T_AURA"),dataType,aura.effect_idx);
+ return false;
+ }
+ if(!spellEntry->EffectApplyAuraName[aura.effect_idx])
+ {
+ sLog.outErrorDb( "Table `achievement_criteria_data` (Entry: %u Type: %u) for data type %s (%u) have non-aura spell effect (ID: %u Effect: %u), ignore.",
+ criteria->ID, criteria->requiredType,(dataType==ACHIEVEMENT_CRITERIA_DATA_TYPE_S_AURA?"ACHIEVEMENT_CRITERIA_DATA_TYPE_S_AURA":"ACHIEVEMENT_CRITERIA_DATA_TYPE_T_AURA"),dataType,aura.spell_id,aura.effect_idx);
+ return false;
+ }
+ return true;
+ }
+ case ACHIEVEMENT_CRITERIA_DATA_TYPE_S_AREA:
+ if(!GetAreaEntryByAreaID(area.id))
+ {
+ sLog.outErrorDb( "Table `achievement_criteria_data` (Entry: %u Type: %u) for data type ACHIEVEMENT_CRITERIA_DATA_TYPE_S_AREA (%u) have wrong area id in value1 (%u), ignore.",
+ criteria->ID, criteria->requiredType,dataType,area.id);
+ return false;
+ }
+ return true;
+ default:
+ sLog.outErrorDb( "Table `achievement_criteria_data` (Entry: %u Type: %u) have data for not supported data type (%u), ignore.", criteria->ID, criteria->requiredType,dataType);
+ return false;
+ }
+ return false;
+}
+
+bool AchievementCriteriaData::Meets(Player const* source, Unit const* target) const
+{
+ switch(dataType)
+ {
+ case ACHIEVEMENT_CRITERIA_DATA_TYPE_NONE:
+ return true;
+ case ACHIEVEMENT_CRITERIA_DATA_TYPE_T_CREATURE:
+ if (!target || target->GetTypeId()!=TYPEID_UNIT)
+ return false;
+ if (target->GetEntry() != creature.id)
+ return false;
+ return true;
+ case ACHIEVEMENT_CRITERIA_DATA_TYPE_T_PLAYER_CLASS_RACE:
+ if (!target || target->GetTypeId()!=TYPEID_PLAYER)
+ return false;
+ if(classRace.class_id && classRace.class_id != ((Player*)target)->getClass())
+ return false;
+ if(classRace.race_id && classRace.race_id != ((Player*)target)->getRace())
+ return false;
+ return true;
+ case ACHIEVEMENT_CRITERIA_DATA_TYPE_T_PLAYER_LESS_HEALTH:
+ if (!target || target->GetTypeId()!=TYPEID_PLAYER)
+ return false;
+ return target->GetHealth()*100 <= health.percent*target->GetMaxHealth();
+ case ACHIEVEMENT_CRITERIA_DATA_TYPE_T_PLAYER_DEAD:
+ return target && target->GetTypeId() == TYPEID_PLAYER && !target->isAlive() && ((Player*)target)->GetDeathTimer() != 0;
+ case ACHIEVEMENT_CRITERIA_DATA_TYPE_S_AURA:
+ return source->HasAura(aura.spell_id,aura.effect_idx);
+ case ACHIEVEMENT_CRITERIA_DATA_TYPE_S_AREA:
+ {
+ uint32 zone_id,area_id;
+ source->GetZoneAndAreaId(zone_id,area_id);
+ return area.id==zone_id || area.id==area_id;
+ }
+ case ACHIEVEMENT_CRITERIA_DATA_TYPE_T_AURA:
+ return target && target->HasAura(aura.spell_id,aura.effect_idx);
+ }
+
+ return false;
+}
+
+bool AchievementCriteriaDataSet::Meets(Player const* source, Unit const* target) const
+{
+ for(Storage::const_iterator itr = storage.begin(); itr != storage.end(); ++itr)
+ if(!itr->Meets(source,target))
+ return false;
+
+ return true;
+}
+
AchievementMgr::AchievementMgr(Player *player)
{
m_player = player;
@@ -542,6 +642,10 @@ void AchievementMgr::UpdateAchievementCriteria(AchievementCriteriaTypes type, ui
}
case ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_QUESTS_IN_ZONE:
{
+ // speedup for non-login case
+ if(miscvalue1 && miscvalue1 != achievementCriteria->complete_quests_in_zone.zoneID)
+ continue;
+
uint32 counter =0;
for(QuestStatusMap::iterator itr = GetPlayer()->getQuestStatusMap().begin(); itr!=GetPlayer()->getQuestStatusMap().end(); itr++)
{
@@ -573,14 +677,14 @@ void AchievementMgr::UpdateAchievementCriteria(AchievementCriteriaTypes type, ui
// AchievementMgr::UpdateAchievementCriteria might also be called on login - skip in this case
if(!miscvalue1)
continue;
- // skip wrong arena achievements, if not achievIdByArenaSlot then normal totla death counter
+ // skip wrong arena achievements, if not achievIdByArenaSlot then normal total death counter
bool notfit = false;
for(int i = 0; i < MAX_ARENA_SLOT; ++i)
{
if(achievIdByArenaSlot[i] == achievement->ID)
{
BattleGround* bg = GetPlayer()->GetBattleGround();
- if(!bg || ArenaTeam::GetSlotByType(bg->GetArenaType())!=i)
+ if(!bg || !bg->isArena() || ArenaTeam::GetSlotByType(bg->GetArenaType()) != i)
notfit = true;
break;
@@ -805,22 +909,18 @@ void AchievementMgr::UpdateAchievementCriteria(AchievementCriteriaTypes type, ui
case ACHIEVEMENT_CRITERIA_TYPE_DO_EMOTE:
{
// miscvalue1 = emote
- // miscvalue2 = achievement->ID for special requirement
if(!miscvalue1)
continue;
if(miscvalue1 != achievementCriteria->do_emote.emoteID)
continue;
if(achievementCriteria->do_emote.count)
{
- // harcoded case
- if(achievement->ID==247)
- {
- if (!unit || unit->GetTypeId() != TYPEID_PLAYER ||
- unit->isAlive() || ((Player*)unit)->GetDeathTimer() == 0)
- continue;
- }
- // expected as scripted case
- else if(!miscvalue2 || !achievement->ID != miscvalue2)
+ // those requirements couldn't be found in the dbc
+ AchievementCriteriaDataSet const* data = achievementmgr.GetCriteriaDataSet(achievementCriteria);
+ if(!data)
+ continue;
+
+ if(!data->Meets(GetPlayer(),unit))
continue;
}
@@ -884,24 +984,19 @@ void AchievementMgr::UpdateAchievementCriteria(AchievementCriteriaTypes type, ui
break;
case ACHIEVEMENT_CRITERIA_TYPE_CAST_SPELL2:
{
+ if (!miscvalue1)
+ continue;
+
if (!miscvalue1 || miscvalue1 != achievementCriteria->cast_spell.spellID)
continue;
// those requirements couldn't be found in the dbc
- if (CriteriaCastSpellRequirement const* requirement = AchievementGlobalMgr::GetCriteriaCastSpellRequirement(achievementCriteria))
- {
- if (!unit)
- continue;
-
- if (requirement->creatureEntry && unit->GetEntry() != requirement->creatureEntry)
- continue;
-
- if (requirement->playerRace && (unit->GetTypeId() != TYPEID_PLAYER || unit->getRace()!=requirement->playerRace))
- continue;
+ AchievementCriteriaDataSet const* data = achievementmgr.GetCriteriaDataSet(achievementCriteria);
+ if(!data)
+ continue;
- if (requirement->playerClass && (unit->GetTypeId() != TYPEID_PLAYER || unit->getClass()!=requirement->playerClass))
- continue;
- }
+ if(!data->Meets(GetPlayer(),unit))
+ continue;
SetCriteriaProgress(achievementCriteria, 1, PROGRESS_ACCUMULATE);
break;
@@ -966,6 +1061,13 @@ void AchievementMgr::UpdateAchievementCriteria(AchievementCriteriaTypes type, ui
if(IsCompletedCriteria(achievementCriteria,achievement))
CompletedCriteria(achievementCriteria,achievement);
+ // check again the completeness for SUMM and REQ COUNT achievements,
+ // as they don't depend on the completed criteria but on the sum of the progress of each individual criteria
+ if (achievement->flags & ACHIEVEMENT_FLAG_SUMM)
+ {
+ if (IsCompletedAchievement(achievement))
+ CompletedAchievement(achievement);
+ }
if(AchievementEntryList const* achRefList = achievementmgr.GetAchievementByReferencedId(achievement->ID))
{
@@ -1111,9 +1213,12 @@ void AchievementMgr::CompletedCriteria(AchievementCriteriaEntry const* criteria,
CompletedAchievement(achievement);
}
-// TODO: achievement 705 requires 4 criteria to be fulfilled
bool AchievementMgr::IsCompletedAchievement(AchievementEntry const* entry)
{
+ // counter can never complete
+ if(entry->flags & ACHIEVEMENT_FLAG_COUNTER)
+ return false;
+
// for achievement with referenced achievement criterias get from referenced and counter from self
uint32 achievmentForTestId = entry->refAchievement ? entry->refAchievement : entry->ID;
uint32 achievmentForTestCount = entry->count;
@@ -1121,10 +1226,32 @@ bool AchievementMgr::IsCompletedAchievement(AchievementEntry const* entry)
AchievementCriteriaEntryList const* cList = achievementmgr.GetAchievementCriteriaByAchievement(achievmentForTestId);
if(!cList)
return false;
-
uint32 count = 0;
- bool completed_all = true;
+ // For SUMM achievements, we have to count the progress of each criteria of the achievement.
+ // Oddly, the target count is NOT countained in the achievement, but in each individual criteria
+ if (entry->flags & ACHIEVEMENT_FLAG_SUMM)
+ {
+ for(AchievementCriteriaEntryList::const_iterator itr = cList->begin(); itr != cList->end(); ++itr)
+ {
+ AchievementCriteriaEntry const* criteria = *itr;
+
+ CriteriaProgressMap::const_iterator itrProgress = m_criteriaProgress.find(criteria->ID);
+ if(itrProgress == m_criteriaProgress.end())
+ continue;
+
+ CriteriaProgress const* progress = &itrProgress->second;
+ count += progress->counter;
+
+ // for counters, field4 contains the main count requirement
+ if (count >= criteria->raw.count)
+ return true;
+ }
+ return false;
+ }
+
+ // Default case - need complete all or
+ bool completed_all = true;
for(AchievementCriteriaEntryList::const_iterator itr = cList->begin(); itr != cList->end(); ++itr)
{
AchievementCriteriaEntry const* criteria = *itr;
@@ -1388,6 +1515,83 @@ void AchievementGlobalMgr::LoadAchievementReferenceList()
sLog.outString(">> Loaded %u achievement references.",count);
}
+void AchievementGlobalMgr::LoadAchievementCriteriaData()
+{
+ m_criteriaDataMap.clear(); // need for reload case
+
+ QueryResult *result = WorldDatabase.Query("SELECT criteria_id, type, value1, value2 FROM achievement_criteria_data");
+
+ if(!result)
+ {
+ barGoLink bar(1);
+ bar.step();
+
+ sLog.outString();
+ sLog.outString(">> Loaded 0 additional achievement criteria data. DB table `achievement_criteria_data` is empty.");
+ return;
+ }
+
+ uint32 count = 0;
+ barGoLink bar(result->GetRowCount());
+ do
+ {
+ bar.step();
+ Field *fields = result->Fetch();
+ uint32 criteria_id = fields[0].GetUInt32();
+
+ AchievementCriteriaEntry const* criteria = sAchievementCriteriaStore.LookupEntry(criteria_id);
+
+ if (!criteria)
+ {
+ sLog.outErrorDb( "Table `achievement_criteria_data` have data for not existed criteria (Entry: %u), ignore.", criteria_id);
+ continue;
+ }
+
+ AchievementCriteriaData data(fields[1].GetUInt32(),fields[2].GetUInt32(),fields[3].GetUInt32());
+
+ if(!data.IsValid(criteria))
+ continue;
+
+ // this will allocate empty data set storage
+ AchievementCriteriaDataSet& dataSet = m_criteriaDataMap[criteria_id];
+
+ // add real data only for not NONE data types
+ if(data.dataType!=ACHIEVEMENT_CRITERIA_DATA_TYPE_NONE)
+ dataSet.Add(data);
+
+ // counting data by and data types
+ ++count;
+ } while(result->NextRow());
+
+ delete result;
+
+ // post loading checks
+ for (uint32 entryId = 0; entryId < sAchievementCriteriaStore.GetNumRows(); ++entryId)
+ {
+ AchievementCriteriaEntry const* criteria = sAchievementCriteriaStore.LookupEntry(entryId);
+ if(!criteria)
+ continue;
+
+ switch(criteria->requiredType)
+ {
+ case ACHIEVEMENT_CRITERIA_TYPE_CAST_SPELL2:
+ if(!GetCriteriaDataSet(criteria))
+ sLog.outErrorDb( "Table `achievement_criteria_data` not have expected data for for criteria (Entry: %u Type: %u).", criteria->ID, criteria->requiredType);
+ break;
+ case ACHIEVEMENT_CRITERIA_TYPE_DO_EMOTE: // need skip generic cases
+ if(criteria->do_emote.count && !GetCriteriaDataSet(criteria))
+ sLog.outErrorDb( "Table `achievement_criteria_data` not have expected data for for criteria (Entry: %u Type: %u).", criteria->ID, criteria->requiredType);
+ break;
+ default: // unexpected case processed in IsValid check
+ break;
+ }
+
+ }
+
+ sLog.outString();
+ sLog.outString(">> Loaded %u additional achievement criteria data.",count);
+}
+
void AchievementGlobalMgr::LoadCompletedAchievements()
{
QueryResult *result = CharacterDatabase.Query("SELECT achievement FROM character_achievement GROUP BY achievement");
@@ -1418,7 +1622,7 @@ void AchievementGlobalMgr::LoadCompletedAchievements()
void AchievementGlobalMgr::LoadRewards()
{
- m_achievementRewards.clear(); // need for reload case
+ m_achievementRewards.clear(); // need for reload case
// 0 1 2 3 4 5 6
QueryResult *result = WorldDatabase.Query("SELECT entry, title_A, title_H, item, sender, subject, text FROM achievement_reward");
@@ -1434,6 +1638,7 @@ void AchievementGlobalMgr::LoadRewards()
return;
}
+ uint32 count = 0;
barGoLink bar(result->GetRowCount());
do
@@ -1517,13 +1722,14 @@ void AchievementGlobalMgr::LoadRewards()
}
m_achievementRewards[entry] = reward;
+ ++count;
} while (result->NextRow());
delete result;
sLog.outString();
- sLog.outString( ">> Loaded %lu achievement reward locale strings", (unsigned long)m_achievementRewardLocales.size() );
+ sLog.outString( ">> Loaded %u achievement rewards", count );
}
void AchievementGlobalMgr::LoadRewardLocales()
diff --git a/src/game/AchievementMgr.h b/src/game/AchievementMgr.h
index b45c63f7301..391afedbb46 100644
--- a/src/game/AchievementMgr.h
+++ b/src/game/AchievementMgr.h
@@ -27,9 +27,6 @@
#include <map>
#include <string>
-#define CRITERIA_CAST_SPELL_REQ_COUNT 46
-#define ACHIEVEMENT_REWARD_COUNT 57
-
typedef std::list<AchievementCriteriaEntry const*> AchievementCriteriaEntryList;
typedef std::list<AchievementEntry const*> AchievementEntryList;
@@ -43,14 +40,92 @@ struct CriteriaProgress
bool changed;
};
-struct CriteriaCastSpellRequirement
+enum AchievementCriteriaDataType
+{ // value1 value2 comment
+ ACHIEVEMENT_CRITERIA_DATA_TYPE_NONE = 0, // 0 0
+ ACHIEVEMENT_CRITERIA_DATA_TYPE_T_CREATURE = 1, // creature_id 0
+ ACHIEVEMENT_CRITERIA_DATA_TYPE_T_PLAYER_CLASS_RACE = 2, // class_id race_id
+ ACHIEVEMENT_CRITERIA_DATA_TYPE_T_PLAYER_LESS_HEALTH= 3, // health_percent 0
+ ACHIEVEMENT_CRITERIA_DATA_TYPE_T_PLAYER_DEAD = 4, // 0 0 not corpse (not released body)
+ ACHIEVEMENT_CRITERIA_DATA_TYPE_S_AURA = 5, // spell_id effect_idx
+ ACHIEVEMENT_CRITERIA_DATA_TYPE_S_AREA = 6, // area id 0
+ ACHIEVEMENT_CRITERIA_DATA_TYPE_T_AURA = 7, // spell_id effect_idx
+};
+
+#define MAX_ACHIEVEMENT_CRITERIA_DATA_TYPE 8 // maximum value in AchievementCriteriaDataType enum
+
+class Player;
+class Unit;
+
+struct AchievementCriteriaData
+{
+ AchievementCriteriaDataType dataType;
+ union
+ {
+ // ACHIEVEMENT_CRITERIA_DATA_TYPE_T_CREATURE
+ struct
+ {
+ uint32 id;
+ } creature;
+ // ACHIEVEMENT_CRITERIA_DATA_TYPE_T_PLAYER_CLASS_RACE
+ struct
+ {
+ uint32 class_id;
+ uint32 race_id;
+ } classRace;
+ // ACHIEVEMENT_CRITERIA_DATA_TYPE_T_PLAYER_LESS_HEALTH
+ struct
+ {
+ uint32 percent;
+ } health;
+ // ACHIEVEMENT_CRITERIA_DATA_TYPE_T_AURA
+ // ACHIEVEMENT_CRITERIA_DATA_TYPE_S_AURA
+ struct
+ {
+ uint32 spell_id;
+ uint32 effect_idx;
+ } aura;
+ // ACHIEVEMENT_CRITERIA_DATA_TYPE_S_AREA
+ struct
+ {
+ uint32 id;
+ } area;
+ // ...
+ struct
+ {
+ uint32 value1;
+ uint32 value2;
+ } raw;
+ };
+
+ AchievementCriteriaData() : dataType(ACHIEVEMENT_CRITERIA_DATA_TYPE_NONE)
+ {
+ raw.value1 = 0;
+ raw.value2 = 0;
+ }
+
+ AchievementCriteriaData(uint32 _dataType, uint32 _value1, uint32 _value2) : dataType(AchievementCriteriaDataType(_dataType))
+ {
+ raw.value1 = _value1;
+ raw.value2 = _value2;
+ }
+
+ bool IsValid(AchievementCriteriaEntry const* criteria);
+ bool Meets(Player const* source, Unit const* target) const;
+};
+
+struct AchievementCriteriaDataSet
{
- uint32 achievementCriteriaId;
- uint32 creatureEntry;
- uint8 playerClass;
- uint8 playerRace;
+ typedef std::vector<AchievementCriteriaData> Storage;
+ void Add(AchievementCriteriaData const& data) { storage.push_back(data); }
+ bool Meets(Player const* source, Unit const* target) const;
+ private:
+ Storage storage;
};
+
+typedef std::map<uint32,AchievementCriteriaDataSet> AchievementCriteriaDataMap;
+
struct AchievementReward
{
uint32 titleId[2];
@@ -145,13 +220,10 @@ class AchievementGlobalMgr
return iter!=m_achievementRewardLocales.end() ? &iter->second : NULL;
}
- static CriteriaCastSpellRequirement const * GetCriteriaCastSpellRequirement(AchievementCriteriaEntry const *achievementCriteria)
+ AchievementCriteriaDataSet const* GetCriteriaDataSet(AchievementCriteriaEntry const *achievementCriteria)
{
- for (uint32 i=0; i < CRITERIA_CAST_SPELL_REQ_COUNT; ++i)
- if (m_criteriaCastSpellRequirements[i].achievementCriteriaId == achievementCriteria->ID)
- return &m_criteriaCastSpellRequirements[i];
-
- return NULL;
+ AchievementCriteriaDataMap::const_iterator iter = m_criteriaDataMap.find(achievementCriteria->ID);
+ return iter!=m_criteriaDataMap.end() ? &iter->second : NULL;
}
bool IsRealmCompleted(AchievementEntry const* achievement) const
@@ -165,12 +237,13 @@ class AchievementGlobalMgr
}
void LoadAchievementCriteriaList();
+ void LoadAchievementCriteriaData();
void LoadAchievementReferenceList();
void LoadCompletedAchievements();
void LoadRewards();
void LoadRewardLocales();
private:
- static const CriteriaCastSpellRequirement m_criteriaCastSpellRequirements[];
+ AchievementCriteriaDataMap m_criteriaDataMap;
// store achievement criterias by type to speed up lookup
AchievementCriteriaEntryList m_AchievementCriteriasByType[ACHIEVEMENT_CRITERIA_TYPE_TOTAL];
diff --git a/src/game/BattleGround.cpp b/src/game/BattleGround.cpp
index 9add7ed98da..fffedb56ad8 100644
--- a/src/game/BattleGround.cpp
+++ b/src/game/BattleGround.cpp
@@ -46,7 +46,7 @@ namespace MaNGOS
{
char const* text = objmgr.GetMangosString(i_textId,loc_idx);
- if(i_args)
+ if (i_args)
{
// we need copy va_list before use or original va_list will corrupted
va_list ap;
@@ -121,7 +121,7 @@ template<class Do>
void BattleGround::BroadcastWorker(Do& _do)
{
for(BattleGroundPlayerMap::iterator itr = m_Players.begin(); itr != m_Players.end(); ++itr)
- if(Player *plr = ObjectAccessor::FindPlayer(MAKE_NEW_GUID(itr->first, 0, HIGHGUID_PLAYER)))
+ if (Player *plr = ObjectAccessor::FindPlayer(MAKE_NEW_GUID(itr->first, 0, HIGHGUID_PLAYER)))
_do(plr);
}
@@ -223,8 +223,8 @@ BattleGround::~BattleGround()
sBattleGroundMgr.RemoveBattleGround(GetInstanceID(), GetTypeID());
// unload map
- if(Map * map = MapManager::Instance().FindMap(GetMapId(), GetInstanceID()))
- if(map->IsBattleGroundOrArena())
+ if (Map * map = MapManager::Instance().FindMap(GetMapId(), GetInstanceID()))
+ if (map->IsBattleGroundOrArena())
((BattleGroundMap*)map)->SetUnload();
// remove from bg free slot queue
this->RemoveFromBGFreeSlotQueue();
@@ -232,17 +232,17 @@ BattleGround::~BattleGround()
void BattleGround::Update(uint32 diff)
{
- if(!GetPlayersSize() && !GetReviveQueueSize())
+ if (!GetPlayersSize() && !GetReviveQueueSize())
//BG is empty
return;
// remove offline players from bg after 5 minutes
- if( !m_OfflineQueue.empty() )
+ if (!m_OfflineQueue.empty())
{
BattleGroundPlayerMap::iterator itr = m_Players.find(*(m_OfflineQueue.begin()));
- if( itr != m_Players.end() )
+ if (itr != m_Players.end())
{
- if( itr->second.OfflineRemoveTime <= sWorld.GetGameTime() )
+ if (itr->second.OfflineRemoveTime <= sWorld.GetGameTime())
{
RemovePlayerAtLeave(itr->first, true, true);// remove player from BG
m_OfflineQueue.pop_front(); // remove from offline queue
@@ -259,7 +259,7 @@ void BattleGround::Update(uint32 diff)
m_LastResurrectTime += diff;
if (m_LastResurrectTime >= RESURRECTION_INTERVAL)
{
- if(GetReviveQueueSize())
+ if (GetReviveQueueSize())
{
for(std::map<uint64, std::vector<uint64> >::iterator itr = m_ReviveQueue.begin(); itr != m_ReviveQueue.end(); ++itr)
{
@@ -267,7 +267,7 @@ void BattleGround::Update(uint32 diff)
for(std::vector<uint64>::iterator itr2 = (itr->second).begin(); itr2 != (itr->second).end(); ++itr2)
{
Player *plr = objmgr.GetPlayer(*itr2);
- if(!plr)
+ if (!plr)
continue;
if (!sh)
@@ -296,7 +296,7 @@ void BattleGround::Update(uint32 diff)
for(std::vector<uint64>::iterator itr = m_ResurrectQueue.begin(); itr != m_ResurrectQueue.end(); ++itr)
{
Player *plr = objmgr.GetPlayer(*itr);
- if(!plr)
+ if (!plr)
continue;
plr->ResurrectPlayer(1.0f);
plr->CastSpell(plr, SPELL_SPIRIT_HEAL_MANA, true);
@@ -310,20 +310,20 @@ void BattleGround::Update(uint32 diff)
/*********************************************************/
// if less then minimum players are in on one side, then start premature finish timer
- if(GetStatus() == STATUS_IN_PROGRESS && !isArena() && sBattleGroundMgr.GetPrematureFinishTime() && (GetPlayersCountByTeam(ALLIANCE) < GetMinPlayersPerTeam() || GetPlayersCountByTeam(HORDE) < GetMinPlayersPerTeam()))
+ if (GetStatus() == STATUS_IN_PROGRESS && !isArena() && sBattleGroundMgr.GetPrematureFinishTime() && (GetPlayersCountByTeam(ALLIANCE) < GetMinPlayersPerTeam() || GetPlayersCountByTeam(HORDE) < GetMinPlayersPerTeam()))
{
- if(!m_PrematureCountDown)
+ if (!m_PrematureCountDown)
{
m_PrematureCountDown = true;
m_PrematureCountDownTimer = sBattleGroundMgr.GetPrematureFinishTime();
}
- else if(m_PrematureCountDownTimer < diff)
+ else if (m_PrematureCountDownTimer < diff)
{
// time's up!
uint32 winner = 0;
- if( GetPlayersCountByTeam(ALLIANCE) >= GetMinPlayersPerTeam() )
+ if (GetPlayersCountByTeam(ALLIANCE) >= GetMinPlayersPerTeam())
winner = ALLIANCE;
- else if( GetPlayersCountByTeam(HORDE) >= GetMinPlayersPerTeam() )
+ else if (GetPlayersCountByTeam(HORDE) >= GetMinPlayersPerTeam())
winner = HORDE;
EndBattleGround(winner);
@@ -333,15 +333,15 @@ void BattleGround::Update(uint32 diff)
{
uint32 newtime = m_PrematureCountDownTimer - diff;
// announce every minute
- if( newtime > (MINUTE * IN_MILISECONDS) )
+ if (newtime > (MINUTE * IN_MILISECONDS))
{
- if( newtime / (MINUTE * IN_MILISECONDS) != m_PrematureCountDownTimer / (MINUTE * IN_MILISECONDS) )
+ if (newtime / (MINUTE * IN_MILISECONDS) != m_PrematureCountDownTimer / (MINUTE * IN_MILISECONDS))
PSendMessageToAll(LANG_BATTLEGROUND_PREMATURE_FINISH_WARNING, CHAT_MSG_SYSTEM, NULL, (uint32)(m_PrematureCountDownTimer / (MINUTE * IN_MILISECONDS)));
}
else
{
//announce every 15 seconds
- if( newtime / (15 * IN_MILISECONDS) != m_PrematureCountDownTimer / (15 * IN_MILISECONDS) )
+ if (newtime / (15 * IN_MILISECONDS) != m_PrematureCountDownTimer / (15 * IN_MILISECONDS))
PSendMessageToAll(LANG_BATTLEGROUND_PREMATURE_FINISH_WARNING_SECS, CHAT_MSG_SYSTEM, NULL, (uint32)(m_PrematureCountDownTimer / IN_MILISECONDS));
}
m_PrematureCountDownTimer = newtime;
@@ -363,7 +363,7 @@ void BattleGround::Update(uint32 diff)
m_Events |= BG_STARTING_EVENT_1;
// setup here, only when at least one player has ported to the map
- if(!SetupBattleGround())
+ if (!SetupBattleGround())
{
EndNow();
return;
@@ -398,12 +398,12 @@ void BattleGround::Update(uint32 diff)
SetStartDelayTime(m_StartDelayTimes[BG_STARTING_EVENT_FOURTH]);
//remove preparation
- if( isArena() )
+ if (isArena())
{
//TODO : add arena sound PlaySoundToAll(SOUND_ARENA_START);
for(BattleGroundPlayerMap::const_iterator itr = GetPlayers().begin(); itr != GetPlayers().end(); ++itr)
- if(Player *plr = objmgr.GetPlayer(itr->first))
+ if (Player *plr = objmgr.GetPlayer(itr->first))
plr->RemoveAurasDueToSpell(SPELL_ARENA_PREPARATION);
CheckArenaWinConditions();
@@ -414,10 +414,10 @@ void BattleGround::Update(uint32 diff)
PlaySoundToAll(SOUND_BG_START);
for(BattleGroundPlayerMap::const_iterator itr = GetPlayers().begin(); itr != GetPlayers().end(); ++itr)
- if(Player* plr = objmgr.GetPlayer(itr->first))
+ if (Player* plr = objmgr.GetPlayer(itr->first))
plr->RemoveAurasDueToSpell(SPELL_PREPARATION);
//Announce BG starting
- if( sWorld.getConfig(CONFIG_BATTLEGROUND_QUEUE_ANNOUNCER_ENABLE) )
+ if (sWorld.getConfig(CONFIG_BATTLEGROUND_QUEUE_ANNOUNCER_ENABLE))
{
sWorld.SendWorldText(LANG_BG_STARTED_ANNOUNCE_WORLD, GetName(), GetMinLevel(), GetMaxLevel());
}
@@ -429,11 +429,11 @@ void BattleGround::Update(uint32 diff)
/*** BATTLEGROUND ENDING SYSTEM ***/
/*********************************************************/
- if(GetStatus() == STATUS_WAIT_LEAVE)
+ if (GetStatus() == STATUS_WAIT_LEAVE)
{
// remove all players from battleground after 2 minutes
m_EndTime -= diff;
- if( m_EndTime <= 0)
+ if (m_EndTime <= 0)
{
m_EndTime = 0;
BattleGroundPlayerMap::iterator itr, next;
@@ -466,7 +466,7 @@ void BattleGround::SendPacketToAll(WorldPacket *packet)
for(BattleGroundPlayerMap::iterator itr = m_Players.begin(); itr != m_Players.end(); ++itr)
{
Player *plr = objmgr.GetPlayer(itr->first);
- if(plr)
+ if (plr)
plr->GetSession()->SendPacket(packet);
else
sLog.outError("BattleGround: Player " I64FMTD " not found!", itr->first);
@@ -479,19 +479,19 @@ void BattleGround::SendPacketToTeam(uint32 TeamID, WorldPacket *packet, Player *
{
Player *plr = objmgr.GetPlayer(itr->first);
- if(!plr)
+ if (!plr)
{
sLog.outError("BattleGround: Player " I64FMTD " not found!", itr->first);
continue;
}
- if(!self && sender == plr)
+ if (!self && sender == plr)
continue;
uint32 team = itr->second.Team;
if(!team) team = plr->GetTeam();
- if(team == TeamID)
+ if (team == TeamID)
plr->GetSession()->SendPacket(packet);
}
}
@@ -511,7 +511,7 @@ void BattleGround::PlaySoundToTeam(uint32 SoundID, uint32 TeamID)
{
Player *plr = objmgr.GetPlayer(itr->first);
- if(!plr)
+ if (!plr)
{
sLog.outError("BattleGround: Player " I64FMTD " not found!", itr->first);
continue;
@@ -520,7 +520,7 @@ void BattleGround::PlaySoundToTeam(uint32 SoundID, uint32 TeamID)
uint32 team = itr->second.Team;
if(!team) team = plr->GetTeam();
- if(team == TeamID)
+ if (team == TeamID)
{
sBattleGroundMgr.BuildPlaySoundPacket(&data, SoundID);
plr->GetSession()->SendPacket(&data);
@@ -534,7 +534,7 @@ void BattleGround::CastSpellOnTeam(uint32 SpellID, uint32 TeamID)
{
Player *plr = objmgr.GetPlayer(itr->first);
- if(!plr)
+ if (!plr)
{
sLog.outError("BattleGround: Player " I64FMTD " not found!", itr->first);
continue;
@@ -543,7 +543,7 @@ void BattleGround::CastSpellOnTeam(uint32 SpellID, uint32 TeamID)
uint32 team = itr->second.Team;
if(!team) team = plr->GetTeam();
- if(team == TeamID)
+ if (team == TeamID)
plr->CastSpell(plr, SpellID, true);
}
}
@@ -571,7 +571,7 @@ void BattleGround::RewardHonorToTeam(uint32 Honor, uint32 TeamID)
{
Player *plr = objmgr.GetPlayer(itr->first);
- if(!plr)
+ if (!plr)
{
sLog.outError("BattleGround: Player " I64FMTD " not found!", itr->first);
continue;
@@ -580,7 +580,7 @@ void BattleGround::RewardHonorToTeam(uint32 Honor, uint32 TeamID)
uint32 team = itr->second.Team;
if(!team) team = plr->GetTeam();
- if(team == TeamID)
+ if (team == TeamID)
UpdatePlayerScore(plr, SCORE_BONUS_HONOR, Honor);
}
}
@@ -589,14 +589,14 @@ void BattleGround::RewardReputationToTeam(uint32 faction_id, uint32 Reputation,
{
FactionEntry const* factionEntry = sFactionStore.LookupEntry(faction_id);
- if(!factionEntry)
+ if (!factionEntry)
return;
for(BattleGroundPlayerMap::iterator itr = m_Players.begin(); itr != m_Players.end(); ++itr)
{
Player *plr = objmgr.GetPlayer(itr->first);
- if(!plr)
+ if (!plr)
{
sLog.outError("BattleGround: Player " I64FMTD " not found!", itr->first);
continue;
@@ -605,7 +605,7 @@ void BattleGround::RewardReputationToTeam(uint32 faction_id, uint32 Reputation,
uint32 team = itr->second.Team;
if(!team) team = plr->GetTeam();
- if(team == TeamID)
+ if (team == TeamID)
plr->GetReputationMgr().ModifyReputation(factionEntry, Reputation);
}
}
@@ -635,7 +635,7 @@ void BattleGround::EndBattleGround(uint32 winner)
WorldPacket data;
int32 winmsg_id = 0;
- if(winner == ALLIANCE)
+ if (winner == ALLIANCE)
{
winmsg_id = isBattleGround() ? LANG_BG_A_WINS : LANG_ARENA_GOLD_WINS;
@@ -643,7 +643,7 @@ void BattleGround::EndBattleGround(uint32 winner)
SetWinner(WINNER_ALLIANCE);
}
- else if(winner == HORDE)
+ else if (winner == HORDE)
{
winmsg_id = isBattleGround() ? LANG_BG_H_WINS : LANG_ARENA_GREEN_WINS;
@@ -661,11 +661,11 @@ void BattleGround::EndBattleGround(uint32 winner)
m_EndTime = TIME_TO_AUTOREMOVE;
// arena rating calculation
- if(isArena() && isRated())
+ if (isArena() && isRated())
{
winner_arena_team = objmgr.GetArenaTeamById(GetArenaTeamIdForTeam(winner));
loser_arena_team = objmgr.GetArenaTeamById(GetArenaTeamIdForTeam(GetOtherTeam(winner)));
- if( winner_arena_team && loser_arena_team )
+ if (winner_arena_team && loser_arena_team)
{
loser_rating = loser_arena_team->GetStats().rating;
winner_rating = winner_arena_team->GetStats().rating;
@@ -687,12 +687,12 @@ void BattleGround::EndBattleGround(uint32 winner)
Player *plr = objmgr.GetPlayer(itr->first);
uint32 team = itr->second.Team;
- if(!plr)
+ if (!plr)
{
//if rated arena match - make member lost!
- if(isArena() && isRated() && winner_arena_team && loser_arena_team)
+ if (isArena() && isRated() && winner_arena_team && loser_arena_team)
{
- if(team == winner)
+ if (team == winner)
winner_arena_team->OfflineMemberLost(itr->first, loser_rating);
else
loser_arena_team->OfflineMemberLost(itr->first, winner_rating);
@@ -705,7 +705,7 @@ void BattleGround::EndBattleGround(uint32 winner)
if(plr->HasAuraType(SPELL_AURA_SPIRIT_OF_REDEMPTION))
plr->RemoveAurasByType(SPELL_AURA_MOD_SHAPESHIFT);
- if(!plr->isAlive())
+ if (!plr->isAlive())
{
plr->ResurrectPlayer(1.0f);
plr->SpawnCorpseBones();
@@ -715,15 +715,15 @@ void BattleGround::EndBattleGround(uint32 winner)
//if(!team) team = plr->GetTeam();
// per player calculation
- if(isArena() && isRated() && winner_arena_team && loser_arena_team)
+ if (isArena() && isRated() && winner_arena_team && loser_arena_team)
{
- if(team == winner)
+ if (team == winner)
winner_arena_team->MemberWon(plr,loser_rating);
else
loser_arena_team->MemberLost(plr,winner_rating);
}
- if(team == winner)
+ if (team == winner)
{
RewardMark(plr,ITEM_WINNER_COUNT);
RewardQuest(plr);
@@ -746,7 +746,7 @@ void BattleGround::EndBattleGround(uint32 winner)
plr->GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_BATTLEGROUND, 1);
}
- if(isArena() && isRated() && winner_arena_team && loser_arena_team)
+ if (isArena() && isRated() && winner_arena_team && loser_arena_team)
{
// update arena points only after increasing the player's match count!
//obsolete: winner_arena_team->UpdateArenaPointsHelper();
@@ -760,10 +760,7 @@ void BattleGround::EndBattleGround(uint32 winner)
loser_arena_team->NotifyStatsChanged();
}
- // inform invited players about the removal
- sBattleGroundMgr.m_BattleGroundQueues[BattleGroundMgr::BGQueueTypeId(GetTypeID(), GetArenaType())].BGEndedRemoveInvites(this);
-
- if(winmsg_id)
+ if (winmsg_id)
SendMessageToAll(winmsg_id, CHAT_MSG_BG_SYSTEM_NEUTRAL);
}
@@ -789,7 +786,7 @@ uint32 BattleGround::GetBattlemasterEntry() const
void BattleGround::RewardMark(Player *plr,uint32 count)
{
// 'Inactive' this aura prevents the player from gaining honor points and battleground tokens
- if(plr->GetDummyAura(SPELL_AURA_PLAYER_INACTIVE))
+ if (plr->GetDummyAura(SPELL_AURA_PLAYER_INACTIVE))
return;
if(!plr || !count)
@@ -826,7 +823,7 @@ void BattleGround::RewardMark(Player *plr,uint32 count)
if(Item* item = plr->StoreNewItem( dest, mark, true, 0))
plr->SendNewItem(item,count,false,true);
- if(no_space_count > 0)
+ if (no_space_count > 0)
SendRewardMarkByMail(plr,mark,no_space_count);
}
}
@@ -834,14 +831,14 @@ void BattleGround::RewardMark(Player *plr,uint32 count)
void BattleGround::SendRewardMarkByMail(Player *plr,uint32 mark, uint32 count)
{
uint32 bmEntry = GetBattlemasterEntry();
- if(!bmEntry)
+ if (!bmEntry)
return;
ItemPrototype const* markProto = objmgr.GetItemPrototype(mark);
- if(!markProto)
+ if (!markProto)
return;
- if(Item* markItem = Item::CreateItem(mark,count,plr))
+ if (Item* markItem = Item::CreateItem(mark,count,plr))
{
// save new item before send
markItem->SaveToDB(); // save for prevent lost at next mail load, if send fail then item will deleted
@@ -853,8 +850,8 @@ void BattleGround::SendRewardMarkByMail(Player *plr,uint32 mark, uint32 count)
// subject: item name
std::string subject = markProto->Name1;
int loc_idx = plr->GetSession()->GetSessionDbLocaleIndex();
- if ( loc_idx >= 0 )
- if(ItemLocale const *il = objmgr.GetItemLocale(markProto->ItemId))
+ if (loc_idx >= 0 )
+ if (ItemLocale const *il = objmgr.GetItemLocale(markProto->ItemId))
if (il->Name.size() > size_t(loc_idx) && !il->Name[loc_idx].empty())
subject = il->Name[loc_idx];
@@ -871,7 +868,7 @@ void BattleGround::SendRewardMarkByMail(Player *plr,uint32 mark, uint32 count)
void BattleGround::RewardQuest(Player *plr)
{
// 'Inactive' this aura prevents the player from gaining honor points and battleground tokens
- if(plr->GetDummyAura(SPELL_AURA_PLAYER_INACTIVE))
+ if (plr->GetDummyAura(SPELL_AURA_PLAYER_INACTIVE))
return;
uint32 quest;
@@ -907,7 +904,7 @@ void BattleGround::RemovePlayerAtLeave(uint64 guid, bool Transport, bool SendPac
bool participant = false;
// Remove from lists/maps
BattleGroundPlayerMap::iterator itr = m_Players.find(guid);
- if(itr != m_Players.end())
+ if (itr != m_Players.end())
{
UpdatePlayersCountByTeam(team, true); // -1 player
m_Players.erase(itr);
@@ -916,7 +913,7 @@ void BattleGround::RemovePlayerAtLeave(uint64 guid, bool Transport, bool SendPac
}
std::map<uint64, BattleGroundScore*>::iterator itr2 = m_PlayerScores.find(guid);
- if(itr2 != m_PlayerScores.end())
+ if (itr2 != m_PlayerScores.end())
{
delete itr2->second; // delete player's score
m_PlayerScores.erase(itr2);
@@ -942,38 +939,32 @@ void BattleGround::RemovePlayerAtLeave(uint64 guid, bool Transport, bool SendPac
{
BattleGroundTypeId bgTypeId = GetTypeID();
BattleGroundQueueTypeId bgQueueTypeId = BattleGroundMgr::BGQueueTypeId(GetTypeID(), GetArenaType());
- if(plr)
+ if (plr)
{
plr->ClearAfkReports();
if(!team) team = plr->GetTeam();
// if arena, remove the specific arena auras
- if(isArena())
+ if (isArena())
{
plr->RemoveArenaAuras(true); // removes debuffs / dots etc., we don't want the player to die after porting out
bgTypeId=BATTLEGROUND_AA; // set the bg type to all arenas (it will be used for queue refreshing)
- // summon old pet if there was one and there isn't a current pet
- if(!plr->GetGuardianPet() && plr->GetTemporaryUnsummonedPetNumber())
- {
- Pet* NewPet = new Pet(plr);
- if(!NewPet->LoadPetFromDB(plr, 0, (plr)->GetTemporaryUnsummonedPetNumber(), true))
- delete NewPet;
+ // unsummon current and summon old pet if there was one and there isn't a current pet
+ plr->RemovePet(NULL, PET_SAVE_NOT_IN_SLOT);
+ plr->ResummonPetTemporaryUnSummonedIfAny();
- (plr)->SetTemporaryUnsummonedPetNumber(0);
- }
-
- if(isRated() && GetStatus() == STATUS_IN_PROGRESS)
+ if (isRated() && GetStatus() == STATUS_IN_PROGRESS)
{
//left a rated match while the encounter was in progress, consider as loser
ArenaTeam * winner_arena_team = objmgr.GetArenaTeamById(GetArenaTeamIdForTeam(GetOtherTeam(team)));
ArenaTeam * loser_arena_team = objmgr.GetArenaTeamById(GetArenaTeamIdForTeam(team));
- if(winner_arena_team && loser_arena_team)
+ if (winner_arena_team && loser_arena_team)
loser_arena_team->MemberLost(plr,winner_arena_team->GetRating());
}
}
- if(SendPacket)
+ if (SendPacket)
{
WorldPacket data;
sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, this, plr->GetBattleGroundQueueIndex(bgQueueTypeId), STATUS_NONE, 0, 0, 0);
@@ -986,18 +977,18 @@ void BattleGround::RemovePlayerAtLeave(uint64 guid, bool Transport, bool SendPac
else
// removing offline participant
{
- if(isRated() && GetStatus() == STATUS_IN_PROGRESS)
+ if (isRated() && GetStatus() == STATUS_IN_PROGRESS)
{
//left a rated match while the encounter was in progress, consider as loser
ArenaTeam * others_arena_team = objmgr.GetArenaTeamById(GetArenaTeamIdForTeam(GetOtherTeam(team)));
ArenaTeam * players_arena_team = objmgr.GetArenaTeamById(GetArenaTeamIdForTeam(team));
- if( others_arena_team && players_arena_team )
+ if (others_arena_team && players_arena_team)
players_arena_team->OfflineMemberLost(guid, others_arena_team->GetRating());
}
}
// remove from raid group if player is member
- if(Group *group = GetBgRaid(team))
+ if (Group *group = GetBgRaid(team))
{
if( !group->RemoveMember(guid, 0) ) // group was disbanded
{
@@ -1007,7 +998,7 @@ void BattleGround::RemovePlayerAtLeave(uint64 guid, bool Transport, bool SendPac
}
DecreaseInvitedCount(team);
//we should update battleground queue, but only if bg isn't ending
- if( isBattleGround() && GetStatus() < STATUS_WAIT_LEAVE )
+ if (isBattleGround() && GetStatus() < STATUS_WAIT_LEAVE)
sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].Update(bgTypeId, GetQueueId());
// Let others know
WorldPacket data;
@@ -1015,20 +1006,20 @@ void BattleGround::RemovePlayerAtLeave(uint64 guid, bool Transport, bool SendPac
SendPacketToTeam(team, &data, plr, false);
}
- if( plr )
+ if (plr)
{
// Do next only if found in battleground
plr->SetBattleGroundId(0, BATTLEGROUND_TYPE_NONE); // We're not in BG.
// reset destination bg team
plr->SetBGTeam(0);
- if(Transport)
+ if (Transport)
plr->TeleportTo(plr->GetBattleGroundEntryPoint());
sLog.outDetail("BATTLEGROUND: Removed player %s from BattleGround.", plr->GetName());
}
- if(!GetPlayersSize() && !GetInvitedCount(HORDE) && !GetInvitedCount(ALLIANCE))
+ if (!GetPlayersSize() && !GetInvitedCount(HORDE) && !GetInvitedCount(ALLIANCE))
{
// if no players left AND no invitees left, set this bg to delete in next update
// direct deletion could cause crashes
@@ -1095,40 +1086,28 @@ void BattleGround::AddPlayer(Player *plr)
SendPacketToTeam(team, &data, plr, false);
// add arena specific auras
- if(isArena())
+ if (isArena())
{
plr->RemoveArenaSpellCooldowns();
plr->RemoveArenaAuras();
plr->RemoveAllEnchantments(TEMP_ENCHANTMENT_SLOT);
if(team == ALLIANCE) // gold
{
- if(plr->GetTeam() == HORDE)
+ if (plr->GetTeam() == HORDE)
plr->CastSpell(plr, SPELL_HORDE_GOLD_FLAG,true);
else
plr->CastSpell(plr, SPELL_ALLIANCE_GOLD_FLAG,true);
}
else // green
{
- if(plr->GetTeam() == HORDE)
+ if (plr->GetTeam() == HORDE)
plr->CastSpell(plr, SPELL_HORDE_GREEN_FLAG,true);
else
plr->CastSpell(plr, SPELL_ALLIANCE_GREEN_FLAG,true);
}
plr->DestroyConjuredItems(true);
-
- Pet* pet = plr->GetPet();
- if(pet)
- {
- if(pet->getPetType() == SUMMON_PET || pet->getPetType() == HUNTER_PET)
- {
- (plr)->SetTemporaryUnsummonedPetNumber(pet->GetCharmInfo()->GetPetNumber());
- (plr)->SetOldPetSpell(pet->GetUInt32Value(UNIT_CREATED_BY_SPELL));
- }
- (plr)->RemovePet(NULL,PET_SAVE_NOT_IN_SLOT);
- }
- else
- (plr)->SetTemporaryUnsummonedPetNumber(0);
+ plr->UnsummonPetTemporaryIfAny();
if(GetStatus() == STATUS_WAIT_JOIN) // not started yet
{
@@ -1164,7 +1143,7 @@ void BattleGround::AddOrSetPlayerToCorrectBgGroup(Player *plr, uint64 plr_guid,
}
else // raid already exist
{
- if(group->IsMember(plr_guid))
+ if (group->IsMember(plr_guid))
{
uint8 subgroup = group->GetMemberGroup(plr_guid);
plr->SetBattleGroundRaid(group, subgroup);
@@ -1172,8 +1151,8 @@ void BattleGround::AddOrSetPlayerToCorrectBgGroup(Player *plr, uint64 plr_guid,
else
{
group->AddMember(plr_guid, plr->GetName());
- if( Group* originalGroup = plr->GetOriginalGroup() )
- if( originalGroup->IsLeader(plr_guid) )
+ if (Group* originalGroup = plr->GetOriginalGroup())
+ if (originalGroup->IsLeader(plr_guid))
group->ChangeLeader(plr_guid);
}
}
@@ -1185,7 +1164,7 @@ void BattleGround::EventPlayerLoggedIn(Player* player, uint64 plr_guid)
// player is correct pointer
for(std::deque<uint64>::iterator itr = m_OfflineQueue.begin(); itr != m_OfflineQueue.end(); ++itr)
{
- if( *itr == plr_guid )
+ if (*itr == plr_guid)
{
m_OfflineQueue.erase(itr);
break;
@@ -1203,14 +1182,14 @@ void BattleGround::EventPlayerLoggedOut(Player* player)
// player is correct pointer, it is checked in WorldSession::LogoutPlayer()
m_OfflineQueue.push_back(player->GetGUID());
m_Players[player->GetGUID()].OfflineRemoveTime = sWorld.GetGameTime() + MAX_OFFLINE_TIME;
- if( GetStatus() == STATUS_IN_PROGRESS )
+ if (GetStatus() == STATUS_IN_PROGRESS)
{
- if( isBattleGround() )
+ if (isBattleGround())
EventPlayerDroppedFlag(player);
else
{
//1 player is logging out, if it is the last, then end arena!
- if( GetAlivePlayersCountByTeam(player->GetTeam()) <= 1 && GetPlayersCountByTeam(GetOtherTeam(player->GetTeam())) )
+ if (GetAlivePlayersCountByTeam(player->GetTeam()) <= 1 && GetPlayersCountByTeam(GetOtherTeam(player->GetTeam())))
EndBattleGround(GetOtherTeam(player->GetTeam()));
}
}
@@ -1220,7 +1199,7 @@ void BattleGround::EventPlayerLoggedOut(Player* player)
void BattleGround::AddToBGFreeSlotQueue()
{
// make sure to add only once
- if(!m_InBGFreeSlotQueue && isBattleGround())
+ if (!m_InBGFreeSlotQueue && isBattleGround())
{
sBattleGroundMgr.BGFreeSlotQueue[m_TypeID].push_front(this);
m_InBGFreeSlotQueue = true;
@@ -1280,10 +1259,10 @@ void BattleGround::UpdatePlayerScore(Player *Source, uint32 type, uint32 value)
break;
case SCORE_BONUS_HONOR: // Honor bonus
// do not add honor in arenas
- if(isBattleGround())
+ if (isBattleGround())
{
// reward honor instantly
- if(Source->RewardHonor(NULL, 1, value))
+ if (Source->RewardHonor(NULL, 1, value))
itr->second->BonusHonor += value;
}
break;
@@ -1305,12 +1284,11 @@ void BattleGround::AddPlayerToResurrectQueue(uint64 npc_guid, uint64 player_guid
m_ReviveQueue[npc_guid].push_back(player_guid);
Player *plr = objmgr.GetPlayer(player_guid);
- if(!plr)
+ if (!plr)
return;
- plr->CastSpell(plr, SPELL_WAITING_FOR_RESURRECT, true);
SpellEntry const *spellInfo = sSpellStore.LookupEntry( SPELL_WAITING_FOR_RESURRECT );
- if(spellInfo)
+ if (spellInfo)
{
Aura *Aur = new Aura(spellInfo, 1, NULL, plr);
plr->AddAura(Aur);
@@ -1323,12 +1301,12 @@ void BattleGround::RemovePlayerFromResurrectQueue(uint64 player_guid)
{
for(std::vector<uint64>::iterator itr2 =(itr->second).begin(); itr2 != (itr->second).end(); ++itr2)
{
- if(*itr2 == player_guid)
+ if (*itr2 == player_guid)
{
(itr->second).erase(itr2);
Player *plr = objmgr.GetPlayer(player_guid);
- if(!plr)
+ if (!plr)
return;
plr->RemoveAurasDueToSpell(SPELL_WAITING_FOR_RESURRECT);
@@ -1342,7 +1320,7 @@ void BattleGround::RemovePlayerFromResurrectQueue(uint64 player_guid)
bool BattleGround::AddObject(uint32 type, uint32 entry, float x, float y, float z, float o, float rotation0, float rotation1, float rotation2, float rotation3, uint32 respawnTime)
{
Map * map = MapManager::Instance().FindMap(GetMapId(),GetInstanceID());
- if(!map)
+ if (!map)
return false;
// must be created this way, adding to godatamap would add it to the base map of the instance
@@ -1380,7 +1358,7 @@ bool BattleGround::AddObject(uint32 type, uint32 entry, float x, float y, float
data.go_state = 1;
*/
// add to world, so it can be later looked up from HashMapHolder
- go->AddToWorld();
+ map->Add(go);
m_BgObjects[type] = go->GetGUID();
return true;
}
@@ -1390,10 +1368,10 @@ bool BattleGround::AddObject(uint32 type, uint32 entry, float x, float y, float
void BattleGround::DoorClose(uint32 type)
{
GameObject *obj = HashMapHolder<GameObject>::Find(m_BgObjects[type]);
- if(obj)
+ if (obj)
{
//if doors are open, close it
- if( obj->getLootState() == GO_ACTIVATED && !obj->GetGoState() )
+ if (obj->getLootState() == GO_ACTIVATED && !obj->GetGoState())
{
//change state to allow door to be closed
obj->SetLootState(GO_READY);
@@ -1409,7 +1387,7 @@ void BattleGround::DoorClose(uint32 type)
void BattleGround::DoorOpen(uint32 type)
{
GameObject *obj = HashMapHolder<GameObject>::Find(m_BgObjects[type]);
- if(obj)
+ if (obj)
{
//change state to be sure they will be opened
obj->SetLootState(GO_READY);
@@ -1440,15 +1418,15 @@ Creature* BattleGround::GetBGCreature(uint32 type)
void BattleGround::SpawnBGObject(uint32 type, uint32 respawntime)
{
Map * map = MapManager::Instance().FindMap(GetMapId(),GetInstanceID());
- if(!map)
+ if (!map)
return;
- if( respawntime == 0 )
+ if (respawntime == 0)
{
GameObject *obj = HashMapHolder<GameObject>::Find(m_BgObjects[type]);
- if(obj)
+ if (obj)
{
//we need to change state from GO_JUST_DEACTIVATED to GO_READY in case battleground is starting again
- if( obj->getLootState() == GO_JUST_DEACTIVATED )
+ if (obj->getLootState() == GO_JUST_DEACTIVATED)
obj->SetLootState(GO_READY);
obj->SetRespawnTime(0);
map->Add(obj);
@@ -1457,7 +1435,7 @@ void BattleGround::SpawnBGObject(uint32 type, uint32 respawntime)
else
{
GameObject *obj = HashMapHolder<GameObject>::Find(m_BgObjects[type]);
- if(obj)
+ if (obj)
{
map->Add(obj);
obj->SetRespawnTime(respawntime);
@@ -1469,7 +1447,7 @@ void BattleGround::SpawnBGObject(uint32 type, uint32 respawntime)
Creature* BattleGround::AddCreature(uint32 entry, uint32 type, uint32 teamval, float x, float y, float z, float o, uint32 respawntime)
{
Map * map = MapManager::Instance().FindMap(GetMapId(),GetInstanceID());
- if(!map)
+ if (!map)
return NULL;
Creature* pCreature = new Creature;
@@ -1482,7 +1460,7 @@ Creature* BattleGround::AddCreature(uint32 entry, uint32 type, uint32 teamval, f
pCreature->Relocate(x, y, z, o);
- if(!pCreature->IsPositionValid())
+ if (!pCreature->IsPositionValid())
{
sLog.outError("Creature (guidlow %d, entry %d) not added to battleground. Suggested coordinates isn't valid (X: %f Y: %f)",pCreature->GetGUIDLow(),pCreature->GetEntry(),pCreature->GetPositionX(),pCreature->GetPositionY());
delete pCreature;
@@ -1502,13 +1480,13 @@ Creature* BattleGround::AddCreature(uint32 entry, uint32 type, uint32 teamval, f
void BattleGround::SpawnBGCreature(uint32 type, uint32 respawntime)
{
Map * map = MapManager::Instance().FindMap(GetMapId(),GetInstanceId());
- if(!map)
+ if (!map)
return false;
- if(respawntime == 0)
+ if (respawntime == 0)
{
Creature *obj = HashMapHolder<Creature>::Find(m_BgCreatures[type]);
- if(obj)
+ if (obj)
{
//obj->Respawn(); // bugged
obj->SetRespawnTime(0);
@@ -1519,7 +1497,7 @@ void BattleGround::SpawnBGCreature(uint32 type, uint32 respawntime)
else
{
Creature *obj = HashMapHolder<Creature>::Find(m_BgCreatures[type]);
- if(obj)
+ if (obj)
{
obj->setDeathState(DEAD);
obj->SetRespawnTime(respawntime);
@@ -1530,11 +1508,11 @@ void BattleGround::SpawnBGCreature(uint32 type, uint32 respawntime)
*/
bool BattleGround::DelCreature(uint32 type)
{
- if(!m_BgCreatures[type])
+ if (!m_BgCreatures[type])
return true;
Creature *cr = HashMapHolder<Creature>::Find(m_BgCreatures[type]);
- if(!cr)
+ if (!cr)
{
sLog.outError("Can't find creature guid: %u",GUID_LOPART(m_BgCreatures[type]));
return false;
@@ -1548,11 +1526,11 @@ bool BattleGround::DelCreature(uint32 type)
bool BattleGround::DelObject(uint32 type)
{
- if(!m_BgObjects[type])
+ if (!m_BgObjects[type])
return true;
GameObject *obj = HashMapHolder<GameObject>::Find(m_BgObjects[type]);
- if(!obj)
+ if (!obj)
{
sLog.outError("Can't find gobject guid: %u",GUID_LOPART(m_BgObjects[type]));
return false;
@@ -1567,13 +1545,13 @@ bool BattleGround::AddSpiritGuide(uint32 type, float x, float y, float z, float
{
uint32 entry = 0;
- if(team == ALLIANCE)
+ if (team == ALLIANCE)
entry = 13116;
else
entry = 13117;
Creature* pCreature = AddCreature(entry,type,team,x,y,z,o);
- if(!pCreature)
+ if (!pCreature)
{
sLog.outError("Can't create Spirit guide. BattleGround not created!");
EndNow();
@@ -1631,8 +1609,6 @@ void BattleGround::EndNow()
RemoveFromBGFreeSlotQueue();
SetStatus(STATUS_WAIT_LEAVE);
SetEndTime(0);
- // inform invited players about the removal
- sBattleGroundMgr.m_BattleGroundQueues[BattleGroundMgr::BGQueueTypeId(GetTypeID(), GetArenaType())].BGEndedRemoveInvites(this);
}
//to be removed
@@ -1650,7 +1626,7 @@ buffs are in their positions when battleground starts
void BattleGround::HandleTriggerBuff(uint64 const& go_guid)
{
GameObject *obj = HashMapHolder<GameObject>::Find(go_guid);
- if(!obj || obj->GetGoType() != GAMEOBJECT_TYPE_TRAP || !obj->isSpawned())
+ if (!obj || obj->GetGoType() != GAMEOBJECT_TYPE_TRAP || !obj->isSpawned())
return;
//change buff type, when buff is used:
@@ -1666,13 +1642,13 @@ void BattleGround::HandleTriggerBuff(uint64 const& go_guid)
//randomly select new buff
uint8 buff = urand(0, 2);
uint32 entry = obj->GetEntry();
- if( m_BuffChange && entry != Buff_Entries[buff] )
+ if (m_BuffChange && entry != Buff_Entries[buff])
{
//despawn current buff
SpawnBGObject(index, RESPAWN_ONE_DAY);
//set index for new one
for (uint8 currBuffTypeIndex = 0; currBuffTypeIndex < 3; ++currBuffTypeIndex)
- if( entry == Buff_Entries[currBuffTypeIndex] )
+ if (entry == Buff_Entries[currBuffTypeIndex])
{
index -= currBuffTypeIndex;
index += buff;
@@ -1690,7 +1666,7 @@ void BattleGround::HandleKillPlayer( Player *player, Player *killer )
UpdatePlayerScore(player, SCORE_DEATHS, 1);
// add +1 kills to group and +1 killing_blows to killer
- if( killer )
+ if (killer)
{
UpdatePlayerScore(killer, SCORE_HONORABLE_KILLS, 1);
UpdatePlayerScore(killer, SCORE_KILLING_BLOWS, 1);
@@ -1699,16 +1675,16 @@ void BattleGround::HandleKillPlayer( Player *player, Player *killer )
{
Player *plr = objmgr.GetPlayer(itr->first);
- if(!plr || plr == killer)
+ if (!plr || plr == killer)
continue;
- if( plr->GetTeam() == killer->GetTeam() && plr->IsAtGroupRewardDistance(player) )
+ if (plr->GetTeam() == killer->GetTeam() && plr->IsAtGroupRewardDistance(player))
UpdatePlayerScore(plr, SCORE_HONORABLE_KILLS, 1);
}
}
// to be able to remove insignia -- ONLY IN BattleGrounds
- if( !isArena() )
+ if (!isArena())
player->SetFlag( UNIT_FIELD_FLAGS, UNIT_FLAG_SKINNABLE );
}
@@ -1717,7 +1693,7 @@ void BattleGround::HandleKillPlayer( Player *player, Player *killer )
uint32 BattleGround::GetPlayerTeam(uint64 guid)
{
BattleGroundPlayerMap::const_iterator itr = m_Players.find(guid);
- if(itr!=m_Players.end())
+ if (itr!=m_Players.end())
return itr->second.Team;
return 0;
}
@@ -1730,14 +1706,14 @@ uint32 BattleGround::GetOtherTeam(uint32 teamId)
bool BattleGround::IsPlayerInBattleGround(uint64 guid)
{
BattleGroundPlayerMap::const_iterator itr = m_Players.find(guid);
- if(itr != m_Players.end())
+ if (itr != m_Players.end())
return true;
return false;
}
void BattleGround::PlayerAddedToBGCheckIfBGIsRunning(Player* plr)
{
- if(GetStatus() != STATUS_WAIT_LEAVE)
+ if (GetStatus() != STATUS_WAIT_LEAVE)
return;
WorldPacket data;
@@ -1757,10 +1733,10 @@ uint32 BattleGround::GetAlivePlayersCountByTeam(uint32 Team) const
int count = 0;
for(BattleGroundPlayerMap::const_iterator itr = m_Players.begin(); itr != m_Players.end(); ++itr)
{
- if(itr->second.Team == Team)
+ if (itr->second.Team == Team)
{
Player * pl = objmgr.GetPlayer(itr->first);
- if(pl && pl->isAlive())
+ if (pl && pl->isAlive())
++count;
}
}
@@ -1790,9 +1766,9 @@ void BattleGround::HandleKillUnit(Creature *creature, Player *killer)
void BattleGround::CheckArenaWinConditions()
{
- if( !GetAlivePlayersCountByTeam(ALLIANCE) && GetPlayersCountByTeam(HORDE) )
+ if (!GetAlivePlayersCountByTeam(ALLIANCE) && GetPlayersCountByTeam(HORDE))
EndBattleGround(HORDE);
- else if( GetPlayersCountByTeam(ALLIANCE) && !GetAlivePlayersCountByTeam(HORDE) )
+ else if (GetPlayersCountByTeam(ALLIANCE) && !GetAlivePlayersCountByTeam(HORDE))
EndBattleGround(ALLIANCE);
}
diff --git a/src/game/BattleGround.h b/src/game/BattleGround.h
index d33eb76e02c..9788f264502 100644
--- a/src/game/BattleGround.h
+++ b/src/game/BattleGround.h
@@ -361,7 +361,7 @@ class BattleGround
void IncreaseInvitedCount(uint32 team) { (team == ALLIANCE) ? ++m_InvitedAlliance : ++m_InvitedHorde; }
uint32 GetInvitedCount(uint32 team) const
{
- if( team == ALLIANCE )
+ if (team == ALLIANCE)
return m_InvitedAlliance;
else
return m_InvitedHorde;
@@ -444,7 +444,7 @@ class BattleGround
uint32 GetAlivePlayersCountByTeam(uint32 Team) const; // used in arenas to correctly handle death in spirit of redemption / last stand etc. (killer = killed) cases
void UpdatePlayersCountByTeam(uint32 Team, bool remove)
{
- if(remove)
+ if (remove)
--m_PlayersCount[GetTeamIndexByTeamId(Team)];
else
++m_PlayersCount[GetTeamIndexByTeamId(Team)];
diff --git a/src/game/BattleGroundAB.cpp b/src/game/BattleGroundAB.cpp
index 90bbd411773..40f60960377 100644
--- a/src/game/BattleGroundAB.cpp
+++ b/src/game/BattleGroundAB.cpp
@@ -60,16 +60,16 @@ void BattleGroundAB::Update(uint32 diff)
{
BattleGround::Update(diff);
- if( GetStatus() == STATUS_IN_PROGRESS )
+ if (GetStatus() == STATUS_IN_PROGRESS)
{
int team_points[BG_TEAMS_COUNT] = { 0, 0 };
for (int node = 0; node < BG_AB_DYNAMIC_NODES_COUNT; ++node)
{
// 3 sec delay to spawn new banner instead previous despawned one
- if( m_BannerTimers[node].timer )
+ if (m_BannerTimers[node].timer)
{
- if( m_BannerTimers[node].timer > diff )
+ if (m_BannerTimers[node].timer > diff)
m_BannerTimers[node].timer -= diff;
else
{
@@ -79,9 +79,9 @@ void BattleGroundAB::Update(uint32 diff)
}
// 1-minute to occupy a node from contested state
- if( m_NodeTimers[node] )
+ if (m_NodeTimers[node])
{
- if( m_NodeTimers[node] > diff )
+ if (m_NodeTimers[node] > diff)
m_NodeTimers[node] -= diff;
else
{
@@ -98,7 +98,7 @@ void BattleGroundAB::Update(uint32 diff)
_NodeOccupied(node,(teamIndex == 0) ? ALLIANCE:HORDE);
// Message to chatlog
- if(teamIndex == 0)
+ if (teamIndex == 0)
{
// FIXME: team and node names not localized
SendMessage2ToAll(LANG_BG_AB_NODE_TAKEN,CHAT_MSG_BG_SYSTEM_ALLIANCE,NULL,LANG_BG_AB_ALLY,_GetNodeNameId(node));
@@ -114,7 +114,7 @@ void BattleGroundAB::Update(uint32 diff)
}
for (int team = 0; team < BG_TEAMS_COUNT; ++team)
- if( m_Nodes[node] == team + BG_AB_NODE_TYPE_OCCUPIED )
+ if (m_Nodes[node] == team + BG_AB_NODE_TYPE_OCCUPIED)
++team_points[team];
}
@@ -122,28 +122,28 @@ void BattleGroundAB::Update(uint32 diff)
for (int team = 0; team < BG_TEAMS_COUNT; ++team)
{
int points = team_points[team];
- if( !points )
+ if (!points)
continue;
m_lastTick[team] += diff;
- if( m_lastTick[team] > BG_AB_TickIntervals[points] )
+ if (m_lastTick[team] > BG_AB_TickIntervals[points])
{
m_lastTick[team] -= BG_AB_TickIntervals[points];
m_TeamScores[team] += BG_AB_TickPoints[points];
m_HonorScoreTics[team] += BG_AB_TickPoints[points];
m_ReputationScoreTics[team] += BG_AB_TickPoints[points];
- if( m_ReputationScoreTics[team] >= m_ReputationTics )
+ if (m_ReputationScoreTics[team] >= m_ReputationTics)
{
(team == BG_TEAM_ALLIANCE) ? RewardReputationToTeam(509, 10, ALLIANCE) : RewardReputationToTeam(510, 10, HORDE);
m_ReputationScoreTics[team] -= m_ReputationTics;
}
- if( m_HonorScoreTics[team] >= m_HonorTics )
+ if (m_HonorScoreTics[team] >= m_HonorTics)
{
RewardHonorToTeam(GetBonusHonorFromKill(1), (team == BG_TEAM_ALLIANCE) ? ALLIANCE : HORDE);
m_HonorScoreTics[team] -= m_HonorTics;
}
- if( !m_IsInformedNearVictory && m_TeamScores[team] > BG_AB_WARNING_NEAR_VICTORY_SCORE )
+ if (!m_IsInformedNearVictory && m_TeamScores[team] > BG_AB_WARNING_NEAR_VICTORY_SCORE)
{
- if( team == BG_TEAM_ALLIANCE )
+ if (team == BG_TEAM_ALLIANCE)
SendMessageToAll(LANG_BG_AB_A_NEAR_VICTORY, CHAT_MSG_BG_SYSTEM_NEUTRAL);
else
SendMessageToAll(LANG_BG_AB_H_NEAR_VICTORY, CHAT_MSG_BG_SYSTEM_NEUTRAL);
@@ -151,19 +151,19 @@ void BattleGroundAB::Update(uint32 diff)
m_IsInformedNearVictory = true;
}
- if( m_TeamScores[team] > BG_AB_MAX_TEAM_SCORE )
+ if (m_TeamScores[team] > BG_AB_MAX_TEAM_SCORE)
m_TeamScores[team] = BG_AB_MAX_TEAM_SCORE;
- if( team == BG_TEAM_ALLIANCE )
+ if (team == BG_TEAM_ALLIANCE)
UpdateWorldState(BG_AB_OP_RESOURCES_ALLY, m_TeamScores[team]);
- if( team == BG_TEAM_HORDE )
+ if (team == BG_TEAM_HORDE)
UpdateWorldState(BG_AB_OP_RESOURCES_HORDE, m_TeamScores[team]);
}
}
// Test win condition
- if( m_TeamScores[BG_TEAM_ALLIANCE] >= BG_AB_MAX_TEAM_SCORE )
+ if (m_TeamScores[BG_TEAM_ALLIANCE] >= BG_AB_MAX_TEAM_SCORE)
EndBattleGround(ALLIANCE);
- if( m_TeamScores[BG_TEAM_HORDE] >= BG_AB_MAX_TEAM_SCORE )
+ if (m_TeamScores[BG_TEAM_HORDE] >= BG_AB_MAX_TEAM_SCORE)
EndBattleGround(HORDE);
}
}
@@ -218,19 +218,19 @@ void BattleGroundAB::RemovePlayer(Player * /*plr*/, uint64 /*guid*/)
void BattleGroundAB::HandleAreaTrigger(Player *Source, uint32 Trigger)
{
- if( GetStatus() != STATUS_IN_PROGRESS )
+ if (GetStatus() != STATUS_IN_PROGRESS)
return;
switch(Trigger)
{
case 3948: // Arathi Basin Alliance Exit.
- if( Source->GetTeam() != ALLIANCE )
+ if (Source->GetTeam() != ALLIANCE)
Source->GetSession()->SendAreaTriggerMessage("Only The Alliance can use that portal");
else
Source->LeaveBattleground();
break;
case 3949: // Arathi Basin Horde Exit.
- if( Source->GetTeam() != HORDE )
+ if (Source->GetTeam() != HORDE)
Source->GetSession()->SendAreaTriggerMessage("Only The Horde can use that portal");
else
Source->LeaveBattleground();
@@ -255,7 +255,7 @@ void BattleGroundAB::HandleAreaTrigger(Player *Source, uint32 Trigger)
void BattleGroundAB::_CreateBanner(uint8 node, uint8 type, uint8 teamIndex, bool delay)
{
// Just put it into the queue
- if( delay )
+ if (delay)
{
m_BannerTimers[node].timer = 2000;
m_BannerTimers[node].type = type;
@@ -268,7 +268,7 @@ void BattleGroundAB::_CreateBanner(uint8 node, uint8 type, uint8 teamIndex, bool
SpawnBGObject(obj, RESPAWN_IMMEDIATELY);
// handle aura with banner
- if( !type )
+ if (!type)
return;
obj = node * 8 + ((type == BG_AB_NODE_TYPE_OCCUPIED) ? (5 + teamIndex) : 7);
SpawnBGObject(obj, RESPAWN_IMMEDIATELY);
@@ -280,7 +280,7 @@ void BattleGroundAB::_DelBanner(uint8 node, uint8 type, uint8 teamIndex)
SpawnBGObject(obj, RESPAWN_ONE_DAY);
// handle aura with banner
- if( !type )
+ if (!type)
return;
obj = node * 8 + ((type == BG_AB_NODE_TYPE_OCCUPIED) ? (5 + teamIndex) : 7);
SpawnBGObject(obj, RESPAWN_ONE_DAY);
@@ -317,9 +317,9 @@ void BattleGroundAB::FillInitialWorldStates(WorldPacket& data)
// How many bases each team owns
uint8 ally = 0, horde = 0;
for (uint8 node = 0; node < BG_AB_DYNAMIC_NODES_COUNT; ++node)
- if( m_Nodes[node] == BG_AB_NODE_STATUS_ALLY_OCCUPIED )
+ if (m_Nodes[node] == BG_AB_NODE_STATUS_ALLY_OCCUPIED)
++ally;
- else if( m_Nodes[node] == BG_AB_NODE_STATUS_HORDE_OCCUPIED )
+ else if (m_Nodes[node] == BG_AB_NODE_STATUS_HORDE_OCCUPIED)
++horde;
data << uint32(BG_AB_OP_OCCUPIED_BASES_ALLY) << uint32(ally);
@@ -340,7 +340,7 @@ void BattleGroundAB::_SendNodeUpdate(uint8 node)
// Send node owner state update to refresh map icons on client
const uint8 plusArray[] = {0, 2, 3, 0, 1};
- if( m_prevNodes[node] )
+ if (m_prevNodes[node])
UpdateWorldState(BG_AB_OP_NODESTATES[node] + plusArray[m_prevNodes[node]], 0);
else
UpdateWorldState(BG_AB_OP_NODEICONS[node], 0);
@@ -350,9 +350,9 @@ void BattleGroundAB::_SendNodeUpdate(uint8 node)
// How many bases each team owns
uint8 ally = 0, horde = 0;
for (uint8 i = 0; i < BG_AB_DYNAMIC_NODES_COUNT; ++i)
- if( m_Nodes[i] == BG_AB_NODE_STATUS_ALLY_OCCUPIED )
+ if (m_Nodes[i] == BG_AB_NODE_STATUS_ALLY_OCCUPIED)
++ally;
- else if( m_Nodes[i] == BG_AB_NODE_STATUS_HORDE_OCCUPIED )
+ else if (m_Nodes[i] == BG_AB_NODE_STATUS_HORDE_OCCUPIED)
++horde;
UpdateWorldState(BG_AB_OP_OCCUPIED_BASES_ALLY, ally);
@@ -361,30 +361,30 @@ void BattleGroundAB::_SendNodeUpdate(uint8 node)
void BattleGroundAB::_NodeOccupied(uint8 node,Team team)
{
- if( !AddSpiritGuide(node, BG_AB_SpiritGuidePos[node][0], BG_AB_SpiritGuidePos[node][1], BG_AB_SpiritGuidePos[node][2], BG_AB_SpiritGuidePos[node][3], team) )
+ if (!AddSpiritGuide(node, BG_AB_SpiritGuidePos[node][0], BG_AB_SpiritGuidePos[node][1], BG_AB_SpiritGuidePos[node][2], BG_AB_SpiritGuidePos[node][3], team))
sLog.outError("Failed to spawn spirit guide! point: %u, team: %u,", node, team);
// SpawnBGCreature(node,RESPAWN_IMMEDIATELY);
uint8 capturedNodes = 0;
for (uint8 i = 0; i < BG_AB_DYNAMIC_NODES_COUNT; ++i)
{
- if( m_Nodes[node] == GetTeamIndexByTeamId(team) + BG_AB_NODE_TYPE_OCCUPIED && !m_NodeTimers[i])
+ if (m_Nodes[node] == GetTeamIndexByTeamId(team) + BG_AB_NODE_TYPE_OCCUPIED && !m_NodeTimers[i])
++capturedNodes;
}
- if(capturedNodes >= 5)
+ if (capturedNodes >= 5)
CastSpellOnTeam(SPELL_AB_QUEST_REWARD_5_BASES, team);
- if(capturedNodes >= 4)
+ if (capturedNodes >= 4)
CastSpellOnTeam(SPELL_AB_QUEST_REWARD_4_BASES, team);
}
void BattleGroundAB::_NodeDeOccupied(uint8 node)
{
- if( node >= BG_AB_DYNAMIC_NODES_COUNT)
+ if (node >= BG_AB_DYNAMIC_NODES_COUNT)
return;
// Those who are waiting to resurrect at this node are taken to the closest own node's graveyard
std::vector<uint64> ghost_list = m_ReviveQueue[m_BgCreatures[node]];
- if( !ghost_list.empty() )
+ if (!ghost_list.empty())
{
WorldSafeLocsEntry const *ClosestGrave = NULL;
for (std::vector<uint64>::const_iterator itr = ghost_list.begin(); itr != ghost_list.end(); ++itr)
@@ -401,7 +401,7 @@ void BattleGroundAB::_NodeDeOccupied(uint8 node)
}
}
- if( m_BgCreatures[node] )
+ if (m_BgCreatures[node])
DelCreature(node);
// buff object isn't despawned
@@ -410,7 +410,7 @@ void BattleGroundAB::_NodeDeOccupied(uint8 node)
/* Invoked if a player used a banner as a gameobject */
void BattleGroundAB::EventPlayerClickedOnFlag(Player *source, GameObject* /*target_obj*/)
{
- if( GetStatus() != STATUS_IN_PROGRESS )
+ if (GetStatus() != STATUS_IN_PROGRESS)
return;
uint8 node = BG_AB_NODE_STABLES;
@@ -421,7 +421,7 @@ void BattleGroundAB::EventPlayerClickedOnFlag(Player *source, GameObject* /*targ
obj=HashMapHolder<GameObject>::Find(m_BgObjects[node*8+BG_AB_OBJECT_AURA_CONTESTED]);
}
- if( node == BG_AB_DYNAMIC_NODES_COUNT)
+ if (node == BG_AB_DYNAMIC_NODES_COUNT)
{
// this means our player isn't close to any of banners - maybe cheater ??
return;
@@ -430,13 +430,13 @@ void BattleGroundAB::EventPlayerClickedOnFlag(Player *source, GameObject* /*targ
uint8 teamIndex = GetTeamIndexByTeamId(source->GetTeam());
// Check if player really could use this banner, not cheated
- if( !(m_Nodes[node] == 0 || teamIndex == m_Nodes[node]%2) )
+ if (!(m_Nodes[node] == 0 || teamIndex == m_Nodes[node]%2))
return;
source->RemoveAurasWithInterruptFlags(AURA_INTERRUPT_FLAG_ENTER_PVP_COMBAT);
uint32 sound = 0;
// If node is neutral, change to contested
- if( m_Nodes[node] == BG_AB_NODE_TYPE_NEUTRAL )
+ if (m_Nodes[node] == BG_AB_NODE_TYPE_NEUTRAL)
{
UpdatePlayerScore(source, SCORE_BASES_ASSAULTED, 1);
m_prevNodes[node] = m_Nodes[node];
@@ -449,7 +449,7 @@ void BattleGroundAB::EventPlayerClickedOnFlag(Player *source, GameObject* /*targ
m_NodeTimers[node] = BG_AB_FLAG_CAPTURING_TIME;
// FIXME: team and node names not localized
- if(teamIndex == 0)
+ if (teamIndex == 0)
SendMessage2ToAll(LANG_BG_AB_NODE_CLAIMED,CHAT_MSG_BG_SYSTEM_ALLIANCE, source, _GetNodeNameId(node), LANG_BG_AB_ALLY);
else
SendMessage2ToAll(LANG_BG_AB_NODE_CLAIMED,CHAT_MSG_BG_SYSTEM_HORDE, source, _GetNodeNameId(node), LANG_BG_AB_HORDE);
@@ -457,10 +457,10 @@ void BattleGroundAB::EventPlayerClickedOnFlag(Player *source, GameObject* /*targ
sound = BG_AB_SOUND_NODE_CLAIMED;
}
// If node is contested
- else if( (m_Nodes[node] == BG_AB_NODE_STATUS_ALLY_CONTESTED) || (m_Nodes[node] == BG_AB_NODE_STATUS_HORDE_CONTESTED) )
+ else if ((m_Nodes[node] == BG_AB_NODE_STATUS_ALLY_CONTESTED) || (m_Nodes[node] == BG_AB_NODE_STATUS_HORDE_CONTESTED))
{
// If last state is NOT occupied, change node to enemy-contested
- if( m_prevNodes[node] < BG_AB_NODE_TYPE_OCCUPIED )
+ if (m_prevNodes[node] < BG_AB_NODE_TYPE_OCCUPIED)
{
UpdatePlayerScore(source, SCORE_BASES_ASSAULTED, 1);
m_prevNodes[node] = m_Nodes[node];
@@ -473,7 +473,7 @@ void BattleGroundAB::EventPlayerClickedOnFlag(Player *source, GameObject* /*targ
m_NodeTimers[node] = BG_AB_FLAG_CAPTURING_TIME;
// FIXME: node names not localized
- if(teamIndex == 0)
+ if (teamIndex == 0)
SendMessage2ToAll(LANG_BG_AB_NODE_ASSAULTED,CHAT_MSG_BG_SYSTEM_ALLIANCE, source, _GetNodeNameId(node));
else
SendMessage2ToAll(LANG_BG_AB_NODE_ASSAULTED,CHAT_MSG_BG_SYSTEM_HORDE, source, _GetNodeNameId(node));
@@ -493,7 +493,7 @@ void BattleGroundAB::EventPlayerClickedOnFlag(Player *source, GameObject* /*targ
_NodeOccupied(node,(teamIndex == 0) ? ALLIANCE:HORDE);
// FIXME: node names not localized
- if(teamIndex == 0)
+ if (teamIndex == 0)
SendMessage2ToAll(LANG_BG_AB_NODE_DEFENDED,CHAT_MSG_BG_SYSTEM_ALLIANCE, source, _GetNodeNameId(node));
else
SendMessage2ToAll(LANG_BG_AB_NODE_DEFENDED,CHAT_MSG_BG_SYSTEM_HORDE, source, _GetNodeNameId(node));
@@ -515,7 +515,7 @@ void BattleGroundAB::EventPlayerClickedOnFlag(Player *source, GameObject* /*targ
m_NodeTimers[node] = BG_AB_FLAG_CAPTURING_TIME;
// FIXME: node names not localized
- if(teamIndex == 0)
+ if (teamIndex == 0)
SendMessage2ToAll(LANG_BG_AB_NODE_ASSAULTED,CHAT_MSG_BG_SYSTEM_ALLIANCE, source, _GetNodeNameId(node));
else
SendMessage2ToAll(LANG_BG_AB_NODE_ASSAULTED,CHAT_MSG_BG_SYSTEM_HORDE, source, _GetNodeNameId(node));
@@ -524,10 +524,10 @@ void BattleGroundAB::EventPlayerClickedOnFlag(Player *source, GameObject* /*targ
}
// If node is occupied again, send "X has taken the Y" msg.
- if( m_Nodes[node] >= BG_AB_NODE_TYPE_OCCUPIED )
+ if (m_Nodes[node] >= BG_AB_NODE_TYPE_OCCUPIED)
{
// FIXME: team and node names not localized
- if(teamIndex == 0)
+ if (teamIndex == 0)
SendMessage2ToAll(LANG_BG_AB_NODE_TAKEN,CHAT_MSG_BG_SYSTEM_ALLIANCE, NULL, LANG_BG_AB_ALLY, _GetNodeNameId(node));
else
SendMessage2ToAll(LANG_BG_AB_NODE_TAKEN,CHAT_MSG_BG_SYSTEM_HORDE, NULL, LANG_BG_AB_HORDE, _GetNodeNameId(node));
@@ -539,7 +539,7 @@ bool BattleGroundAB::SetupBattleGround()
{
for (int i = 0 ; i < BG_AB_DYNAMIC_NODES_COUNT; ++i)
{
- if( !AddObject(BG_AB_OBJECT_BANNER_NEUTRAL + 8*i,BG_AB_OBJECTID_NODE_BANNER_0 + i,BG_AB_NodePositions[i][0],BG_AB_NodePositions[i][1],BG_AB_NodePositions[i][2],BG_AB_NodePositions[i][3], 0, 0, sin(BG_AB_NodePositions[i][3]/2), cos(BG_AB_NodePositions[i][3]/2),RESPAWN_ONE_DAY)
+ if (!AddObject(BG_AB_OBJECT_BANNER_NEUTRAL + 8*i,BG_AB_OBJECTID_NODE_BANNER_0 + i,BG_AB_NodePositions[i][0],BG_AB_NodePositions[i][1],BG_AB_NodePositions[i][2],BG_AB_NodePositions[i][3], 0, 0, sin(BG_AB_NodePositions[i][3]/2), cos(BG_AB_NodePositions[i][3]/2),RESPAWN_ONE_DAY)
|| !AddObject(BG_AB_OBJECT_BANNER_CONT_A + 8*i,BG_AB_OBJECTID_BANNER_CONT_A,BG_AB_NodePositions[i][0],BG_AB_NodePositions[i][1],BG_AB_NodePositions[i][2],BG_AB_NodePositions[i][3], 0, 0, sin(BG_AB_NodePositions[i][3]/2), cos(BG_AB_NodePositions[i][3]/2),RESPAWN_ONE_DAY)
|| !AddObject(BG_AB_OBJECT_BANNER_CONT_H + 8*i,BG_AB_OBJECTID_BANNER_CONT_H,BG_AB_NodePositions[i][0],BG_AB_NodePositions[i][1],BG_AB_NodePositions[i][2],BG_AB_NodePositions[i][3], 0, 0, sin(BG_AB_NodePositions[i][3]/2), cos(BG_AB_NodePositions[i][3]/2),RESPAWN_ONE_DAY)
|| !AddObject(BG_AB_OBJECT_BANNER_ALLY + 8*i,BG_AB_OBJECTID_BANNER_A,BG_AB_NodePositions[i][0],BG_AB_NodePositions[i][1],BG_AB_NodePositions[i][2],BG_AB_NodePositions[i][3], 0, 0, sin(BG_AB_NodePositions[i][3]/2), cos(BG_AB_NodePositions[i][3]/2),RESPAWN_ONE_DAY)
@@ -553,7 +553,7 @@ bool BattleGroundAB::SetupBattleGround()
return false;
}
}
- if( !AddObject(BG_AB_OBJECT_GATE_A,BG_AB_OBJECTID_GATE_A,BG_AB_DoorPositions[0][0],BG_AB_DoorPositions[0][1],BG_AB_DoorPositions[0][2],BG_AB_DoorPositions[0][3],BG_AB_DoorPositions[0][4],BG_AB_DoorPositions[0][5],BG_AB_DoorPositions[0][6],BG_AB_DoorPositions[0][7],RESPAWN_IMMEDIATELY)
+ if (!AddObject(BG_AB_OBJECT_GATE_A,BG_AB_OBJECTID_GATE_A,BG_AB_DoorPositions[0][0],BG_AB_DoorPositions[0][1],BG_AB_DoorPositions[0][2],BG_AB_DoorPositions[0][3],BG_AB_DoorPositions[0][4],BG_AB_DoorPositions[0][5],BG_AB_DoorPositions[0][6],BG_AB_DoorPositions[0][7],RESPAWN_IMMEDIATELY)
|| !AddObject(BG_AB_OBJECT_GATE_H,BG_AB_OBJECTID_GATE_H,BG_AB_DoorPositions[1][0],BG_AB_DoorPositions[1][1],BG_AB_DoorPositions[1][2],BG_AB_DoorPositions[1][3],BG_AB_DoorPositions[1][4],BG_AB_DoorPositions[1][5],BG_AB_DoorPositions[1][6],BG_AB_DoorPositions[1][7],RESPAWN_IMMEDIATELY)
)
{
@@ -563,7 +563,7 @@ bool BattleGroundAB::SetupBattleGround()
//buffs
for (int i = 0; i < BG_AB_DYNAMIC_NODES_COUNT; ++i)
{
- if( !AddObject(BG_AB_OBJECT_SPEEDBUFF_STABLES + 3 * i, Buff_Entries[0], BG_AB_BuffPositions[i][0], BG_AB_BuffPositions[i][1], BG_AB_BuffPositions[i][2], BG_AB_BuffPositions[i][3], 0, 0, sin(BG_AB_BuffPositions[i][3]/2), cos(BG_AB_BuffPositions[i][3]/2), RESPAWN_ONE_DAY)
+ if (!AddObject(BG_AB_OBJECT_SPEEDBUFF_STABLES + 3 * i, Buff_Entries[0], BG_AB_BuffPositions[i][0], BG_AB_BuffPositions[i][1], BG_AB_BuffPositions[i][2], BG_AB_BuffPositions[i][3], 0, 0, sin(BG_AB_BuffPositions[i][3]/2), cos(BG_AB_BuffPositions[i][3]/2), RESPAWN_ONE_DAY)
|| !AddObject(BG_AB_OBJECT_SPEEDBUFF_STABLES + 3 * i + 1, Buff_Entries[1], BG_AB_BuffPositions[i][0], BG_AB_BuffPositions[i][1], BG_AB_BuffPositions[i][2], BG_AB_BuffPositions[i][3], 0, 0, sin(BG_AB_BuffPositions[i][3]/2), cos(BG_AB_BuffPositions[i][3]/2), RESPAWN_ONE_DAY)
|| !AddObject(BG_AB_OBJECT_SPEEDBUFF_STABLES + 3 * i + 2, Buff_Entries[2], BG_AB_BuffPositions[i][0], BG_AB_BuffPositions[i][1], BG_AB_BuffPositions[i][2], BG_AB_BuffPositions[i][3], 0, 0, sin(BG_AB_BuffPositions[i][3]/2), cos(BG_AB_BuffPositions[i][3]/2), RESPAWN_ONE_DAY)
)
@@ -600,16 +600,16 @@ void BattleGroundAB::Reset()
}
for (uint8 i = 0; i < BG_AB_ALL_NODES_COUNT; ++i)
- if(m_BgCreatures[i])
+ if (m_BgCreatures[i])
DelCreature(i);
}
void BattleGroundAB::EndBattleGround(uint32 winner)
{
//win reward
- if( winner == ALLIANCE )
+ if (winner == ALLIANCE)
RewardHonorToTeam(GetBonusHonorFromKill(1), ALLIANCE);
- if( winner == HORDE )
+ if (winner == HORDE)
RewardHonorToTeam(GetBonusHonorFromKill(1), HORDE);
//complete map_end rewards (even if no team wins)
RewardHonorToTeam(GetBonusHonorFromKill(1), HORDE);
@@ -625,12 +625,12 @@ WorldSafeLocsEntry const* BattleGroundAB::GetClosestGraveYard(Player* player)
// Is there any occupied node for this team?
std::vector<uint8> nodes;
for (uint8 i = 0; i < BG_AB_DYNAMIC_NODES_COUNT; ++i)
- if( m_Nodes[i] == teamIndex + 3 )
+ if (m_Nodes[i] == teamIndex + 3)
nodes.push_back(i);
WorldSafeLocsEntry const* good_entry = NULL;
// If so, select the closest node to place ghost on
- if( !nodes.empty() )
+ if (!nodes.empty())
{
float plr_x = player->GetPositionX();
float plr_y = player->GetPositionY();
@@ -639,10 +639,10 @@ WorldSafeLocsEntry const* BattleGroundAB::GetClosestGraveYard(Player* player)
for (uint8 i = 0; i < nodes.size(); ++i)
{
WorldSafeLocsEntry const*entry = sWorldSafeLocsStore.LookupEntry( BG_AB_GraveyardIds[nodes[i]] );
- if( !entry )
+ if (!entry)
continue;
float dist = (entry->x - plr_x)*(entry->x - plr_x)+(entry->y - plr_y)*(entry->y - plr_y);
- if( mindist > dist )
+ if (mindist > dist)
{
mindist = dist;
good_entry = entry;
@@ -651,7 +651,7 @@ WorldSafeLocsEntry const* BattleGroundAB::GetClosestGraveYard(Player* player)
nodes.clear();
}
// If not, place ghost on starting location
- if( !good_entry )
+ if (!good_entry)
good_entry = sWorldSafeLocsStore.LookupEntry( BG_AB_GraveyardIds[teamIndex+5] );
return good_entry;
diff --git a/src/game/BattleGroundAV.cpp b/src/game/BattleGroundAV.cpp
index 6320623f453..bc0b50d21f0 100644
--- a/src/game/BattleGroundAV.cpp
+++ b/src/game/BattleGroundAV.cpp
@@ -543,7 +543,7 @@ void BattleGroundAV::RemovePlayer(Player* plr,uint64 /*guid*/)
void BattleGroundAV::HandleAreaTrigger(Player *Source, uint32 Trigger)
{
// this is wrong way to implement these things. On official it done by gameobject spell cast.
- if(GetStatus() != STATUS_IN_PROGRESS)
+ if (GetStatus() != STATUS_IN_PROGRESS)
return;
uint32 SpellId = 0;
@@ -576,7 +576,7 @@ void BattleGroundAV::HandleAreaTrigger(Player *Source, uint32 Trigger)
break;
}
- if(SpellId)
+ if (SpellId)
Source->CastSpell(Source, SpellId, true);
}
diff --git a/src/game/BattleGroundBE.cpp b/src/game/BattleGroundBE.cpp
index f417c353c1c..dd45b78d924 100644
--- a/src/game/BattleGroundBE.cpp
+++ b/src/game/BattleGroundBE.cpp
@@ -50,7 +50,7 @@ void BattleGroundBE::Update(uint32 diff)
{
BattleGround::Update(diff);
- /*if(GetStatus() == STATUS_IN_PROGRESS)
+ /*if (GetStatus() == STATUS_IN_PROGRESS)
{
// update something
}*/
@@ -88,7 +88,7 @@ void BattleGroundBE::AddPlayer(Player *plr)
void BattleGroundBE::RemovePlayer(Player* /*plr*/, uint64 /*guid*/)
{
- if(GetStatus() == STATUS_WAIT_LEAVE)
+ if (GetStatus() == STATUS_WAIT_LEAVE)
return;
UpdateWorldState(0x9f1, GetAlivePlayersCountByTeam(ALLIANCE));
@@ -99,10 +99,10 @@ void BattleGroundBE::RemovePlayer(Player* /*plr*/, uint64 /*guid*/)
void BattleGroundBE::HandleKillPlayer(Player *player, Player *killer)
{
- if(GetStatus() != STATUS_IN_PROGRESS)
+ if (GetStatus() != STATUS_IN_PROGRESS)
return;
- if(!killer)
+ if (!killer)
{
sLog.outError("Killer player not found");
return;
@@ -125,7 +125,7 @@ bool BattleGroundBE::HandlePlayerUnderMap(Player *player)
void BattleGroundBE::HandleAreaTrigger(Player *Source, uint32 Trigger)
{
// this is wrong way to implement these things. On official it done by gameobject spell cast.
- if(GetStatus() != STATUS_IN_PROGRESS)
+ if (GetStatus() != STATUS_IN_PROGRESS)
return;
//uint32 SpellId = 0;
@@ -144,7 +144,7 @@ void BattleGroundBE::HandleAreaTrigger(Player *Source, uint32 Trigger)
break;
}
- //if(buff_guid)
+ //if (buff_guid)
// HandleTriggerBuff(buff_guid,Source);
}
@@ -164,7 +164,7 @@ void BattleGroundBE::Reset()
bool BattleGroundBE::SetupBattleGround()
{
// gates
- if( !AddObject(BG_BE_OBJECT_DOOR_1, BG_BE_OBJECT_TYPE_DOOR_1, 6287.277f, 282.1877f, 3.810925f, -2.260201f, 0, 0, 0.9044551f, -0.4265689f, RESPAWN_IMMEDIATELY)
+ if (!AddObject(BG_BE_OBJECT_DOOR_1, BG_BE_OBJECT_TYPE_DOOR_1, 6287.277f, 282.1877f, 3.810925f, -2.260201f, 0, 0, 0.9044551f, -0.4265689f, RESPAWN_IMMEDIATELY)
|| !AddObject(BG_BE_OBJECT_DOOR_2, BG_BE_OBJECT_TYPE_DOOR_2, 6189.546f, 241.7099f, 3.101481f, 0.8813917f, 0, 0, 0.4265689f, 0.9044551f, RESPAWN_IMMEDIATELY)
|| !AddObject(BG_BE_OBJECT_DOOR_3, BG_BE_OBJECT_TYPE_DOOR_3, 6299.116f, 296.5494f, 3.308032f, 0.8813917f, 0, 0, 0.4265689f, 0.9044551f, RESPAWN_IMMEDIATELY)
|| !AddObject(BG_BE_OBJECT_DOOR_4, BG_BE_OBJECT_TYPE_DOOR_4, 6177.708f, 227.3481f, 3.604374f, -2.260201f, 0, 0, 0.9044551f, -0.4265689f, RESPAWN_IMMEDIATELY)
diff --git a/src/game/BattleGroundEY.cpp b/src/game/BattleGroundEY.cpp
index f50f2d332e1..04ab25c30cc 100644
--- a/src/game/BattleGroundEY.cpp
+++ b/src/game/BattleGroundEY.cpp
@@ -59,10 +59,10 @@ void BattleGroundEY::Update(uint32 diff)
{
BattleGround::Update(diff);
- if( GetStatus() == STATUS_IN_PROGRESS )
+ if (GetStatus() == STATUS_IN_PROGRESS)
{
m_PointAddingTimer -= diff;
- if(m_PointAddingTimer <= 0)
+ if (m_PointAddingTimer <= 0)
{
m_PointAddingTimer = BG_EY_FPOINTS_TICK_TIME;
if (m_TeamPointsCount[BG_TEAM_ALLIANCE] > 0)
@@ -71,11 +71,11 @@ void BattleGroundEY::Update(uint32 diff)
AddPoints(HORDE, BG_EY_TickPoints[m_TeamPointsCount[BG_TEAM_HORDE] - 1]);
}
- if(m_FlagState == BG_EY_FLAG_STATE_WAIT_RESPAWN || m_FlagState == BG_EY_FLAG_STATE_ON_GROUND)
+ if (m_FlagState == BG_EY_FLAG_STATE_WAIT_RESPAWN || m_FlagState == BG_EY_FLAG_STATE_ON_GROUND)
{
m_FlagsTimer -= diff;
- if(m_FlagsTimer < 0)
+ if (m_FlagsTimer < 0)
{
m_FlagsTimer = 0;
if (m_FlagState == BG_EY_FLAG_STATE_WAIT_RESPAWN)
@@ -86,7 +86,7 @@ void BattleGroundEY::Update(uint32 diff)
}
m_TowerCapCheckTimer -= diff;
- if(m_TowerCapCheckTimer <= 0)
+ if (m_TowerCapCheckTimer <= 0)
{
//check if player joined point
/*I used this order of calls, because although we will check if one player is in gameobject's distance 2 times
@@ -150,7 +150,7 @@ void BattleGroundEY::CheckSomeoneJoinedPoint()
while (j < m_PlayersNearPoint[EY_POINTS_MAX].size())
{
Player *plr = objmgr.GetPlayer(m_PlayersNearPoint[EY_POINTS_MAX][j]);
- if(!plr)
+ if (!plr)
{
sLog.outError("BattleGroundEY: Player " I64FMTD " not found!", m_PlayersNearPoint[EY_POINTS_MAX][j]);
++j;
@@ -184,7 +184,7 @@ void BattleGroundEY::CheckSomeoneLeftPoint()
for(uint8 i = 0; i < EY_POINTS_MAX; ++i)
{
obj = HashMapHolder<GameObject>::Find(m_BgObjects[BG_EY_OBJECT_TOWER_CAP_FEL_REALVER + i]);
- if(obj)
+ if (obj)
{
uint8 j = 0;
while (j < m_PlayersNearPoint[i].size())
@@ -268,9 +268,9 @@ void BattleGroundEY::UpdateTeamScore(uint32 Team)
{
uint32 score = GetTeamScore(Team);
//TODO there should be some sound played when one team is near victory!! - and define variables
- /*if( !m_IsInformedNearVictory && score >= BG_EY_WARNING_NEAR_VICTORY_SCORE )
+ /*if (!m_IsInformedNearVictory && score >= BG_EY_WARNING_NEAR_VICTORY_SCORE)
{
- if( Team == ALLIANCE )
+ if (Team == ALLIANCE)
SendMessageToAll(LANG_BG_EY_A_NEAR_VICTORY, CHAT_MSG_BG_SYSTEM_NEUTRAL);
else
SendMessageToAll(LANG_BG_EY_H_NEAR_VICTORY, CHAT_MSG_BG_SYSTEM_NEUTRAL);
@@ -278,13 +278,13 @@ void BattleGroundEY::UpdateTeamScore(uint32 Team)
m_IsInformedNearVictory = true;
}*/
- if( score >= BG_EY_MAX_TEAM_SCORE )
+ if (score >= BG_EY_MAX_TEAM_SCORE)
{
score = BG_EY_MAX_TEAM_SCORE;
EndBattleGround(Team);
}
- if(Team == ALLIANCE)
+ if (Team == ALLIANCE)
UpdateWorldState(EY_ALLIANCE_RESOURCES, score);
else
UpdateWorldState(EY_HORDE_RESOURCES, score);
@@ -293,9 +293,9 @@ void BattleGroundEY::UpdateTeamScore(uint32 Team)
void BattleGroundEY::EndBattleGround(uint32 winner)
{
//win reward
- if( winner == ALLIANCE )
+ if (winner == ALLIANCE)
RewardHonorToTeam(GetBonusHonorFromKill(1), ALLIANCE);
- if( winner == HORDE )
+ if (winner == HORDE)
RewardHonorToTeam(GetBonusHonorFromKill(1), HORDE);
//complete map reward
RewardHonorToTeam(GetBonusHonorFromKill(1), ALLIANCE);
@@ -306,7 +306,7 @@ void BattleGroundEY::EndBattleGround(uint32 winner)
void BattleGroundEY::UpdatePointsCount(uint32 Team)
{
- if(Team == ALLIANCE)
+ if (Team == ALLIANCE)
UpdateWorldState(EY_ALLIANCE_BASE, m_TeamPointsCount[BG_TEAM_ALLIANCE]);
else
UpdateWorldState(EY_HORDE_BASE, m_TeamPointsCount[BG_TEAM_HORDE]);
@@ -318,14 +318,14 @@ void BattleGroundEY::UpdatePointsIcons(uint32 Team, uint32 Point)
if (m_PointState[Point] == EY_POINT_UNDER_CONTROL)
{
UpdateWorldState(m_PointsIconStruct[Point].WorldStateControlIndex, 0);
- if(Team == ALLIANCE)
+ if (Team == ALLIANCE)
UpdateWorldState(m_PointsIconStruct[Point].WorldStateAllianceControlledIndex, 1);
else
UpdateWorldState(m_PointsIconStruct[Point].WorldStateHordeControlledIndex, 1);
}
else
{
- if(Team == ALLIANCE)
+ if (Team == ALLIANCE)
UpdateWorldState(m_PointsIconStruct[Point].WorldStateAllianceControlledIndex, 0);
else
UpdateWorldState(m_PointsIconStruct[Point].WorldStateHordeControlledIndex, 0);
@@ -350,15 +350,15 @@ void BattleGroundEY::RemovePlayer(Player *plr, uint64 guid)
for (int j = EY_POINTS_MAX; j >= 0; --j)
{
for(int i = 0; i < m_PlayersNearPoint[j].size(); ++i)
- if(m_PlayersNearPoint[j][i] == guid)
+ if (m_PlayersNearPoint[j][i] == guid)
m_PlayersNearPoint[j].erase(m_PlayersNearPoint[j].begin() + i);
}
- if(IsFlagPickedup())
+ if (IsFlagPickedup())
{
- if(m_FlagKeeper == guid)
+ if (m_FlagKeeper == guid)
{
- if(plr)
- this->EventPlayerDroppedFlag(plr);
+ if (plr)
+ EventPlayerDroppedFlag(plr);
else
{
SetFlagPicker(0);
@@ -370,7 +370,7 @@ void BattleGroundEY::RemovePlayer(Player *plr, uint64 guid)
void BattleGroundEY::HandleAreaTrigger(Player *Source, uint32 Trigger)
{
- if(GetStatus() != STATUS_IN_PROGRESS)
+ if (GetStatus() != STATUS_IN_PROGRESS)
return;
if(!Source->isAlive()) //hack code, must be removed later
@@ -379,23 +379,23 @@ void BattleGroundEY::HandleAreaTrigger(Player *Source, uint32 Trigger)
switch(Trigger)
{
case TR_BLOOD_ELF_POINT:
- if(m_PointState[BLOOD_ELF] == EY_POINT_UNDER_CONTROL && m_PointOwnedByTeam[BLOOD_ELF] == Source->GetTeam())
- if(m_FlagState && GetFlagPickerGUID() == Source->GetGUID())
+ if (m_PointState[BLOOD_ELF] == EY_POINT_UNDER_CONTROL && m_PointOwnedByTeam[BLOOD_ELF] == Source->GetTeam())
+ if (m_FlagState && GetFlagPickerGUID() == Source->GetGUID())
EventPlayerCapturedFlag(Source, BG_EY_OBJECT_FLAG_BLOOD_ELF);
break;
case TR_FEL_REALVER_POINT:
- if(m_PointState[FEL_REALVER] == EY_POINT_UNDER_CONTROL && m_PointOwnedByTeam[FEL_REALVER] == Source->GetTeam())
- if(m_FlagState && GetFlagPickerGUID() == Source->GetGUID())
+ if (m_PointState[FEL_REALVER] == EY_POINT_UNDER_CONTROL && m_PointOwnedByTeam[FEL_REALVER] == Source->GetTeam())
+ if (m_FlagState && GetFlagPickerGUID() == Source->GetGUID())
EventPlayerCapturedFlag(Source, BG_EY_OBJECT_FLAG_FEL_REALVER);
break;
case TR_MAGE_TOWER_POINT:
- if(m_PointState[MAGE_TOWER] == EY_POINT_UNDER_CONTROL && m_PointOwnedByTeam[MAGE_TOWER] == Source->GetTeam())
- if(m_FlagState && GetFlagPickerGUID() == Source->GetGUID())
+ if (m_PointState[MAGE_TOWER] == EY_POINT_UNDER_CONTROL && m_PointOwnedByTeam[MAGE_TOWER] == Source->GetTeam())
+ if (m_FlagState && GetFlagPickerGUID() == Source->GetGUID())
EventPlayerCapturedFlag(Source, BG_EY_OBJECT_FLAG_MAGE_TOWER);
break;
case TR_DRAENEI_RUINS_POINT:
- if(m_PointState[DRAENEI_RUINS] == EY_POINT_UNDER_CONTROL && m_PointOwnedByTeam[DRAENEI_RUINS] == Source->GetTeam())
- if(m_FlagState && GetFlagPickerGUID() == Source->GetGUID())
+ if (m_PointState[DRAENEI_RUINS] == EY_POINT_UNDER_CONTROL && m_PointOwnedByTeam[DRAENEI_RUINS] == Source->GetTeam())
+ if (m_FlagState && GetFlagPickerGUID() == Source->GetGUID())
EventPlayerCapturedFlag(Source, BG_EY_OBJECT_FLAG_DRAENEI_RUINS);
break;
case 4512:
@@ -419,7 +419,7 @@ void BattleGroundEY::HandleAreaTrigger(Player *Source, uint32 Trigger)
bool BattleGroundEY::SetupBattleGround()
{
// doors
- if( !AddObject(BG_EY_OBJECT_DOOR_A, BG_OBJECT_A_DOOR_EY_ENTRY, 2527.6f, 1596.91f, 1262.13f, -3.12414f, -0.173642f, -0.001515f, 0.98477f, -0.008594f, RESPAWN_IMMEDIATELY)
+ if (!AddObject(BG_EY_OBJECT_DOOR_A, BG_OBJECT_A_DOOR_EY_ENTRY, 2527.6f, 1596.91f, 1262.13f, -3.12414f, -0.173642f, -0.001515f, 0.98477f, -0.008594f, RESPAWN_IMMEDIATELY)
|| !AddObject(BG_EY_OBJECT_DOOR_H, BG_OBJECT_H_DOOR_EY_ENTRY, 1803.21f, 1539.49f, 1261.09f, 3.14159f, 0.173648f, 0, 0.984808f, 0, RESPAWN_IMMEDIATELY)
// banners (alliance)
|| !AddObject(BG_EY_OBJECT_A_BANNER_FEL_REALVER_CENTER, BG_OBJECT_A_BANNER_EY_ENTRY, 2057.46f, 1735.07f, 1187.91f, -0.925024f, 0, 0, 0.446198f, -0.894934f, RESPAWN_ONE_DAY)
@@ -481,12 +481,12 @@ bool BattleGroundEY::SetupBattleGround()
for (int i = 0; i < EY_POINTS_MAX; ++i)
{
AreaTriggerEntry const* at = sAreaTriggerStore.LookupEntry(m_Points_Trigger[i]);
- if( !at )
+ if (!at)
{
sLog.outError("BattleGroundEY: Unknown trigger: %u", m_Points_Trigger[i]);
continue;
}
- if ( !AddObject(BG_EY_OBJECT_SPEEDBUFF_FEL_REALVER + i * 3, Buff_Entries[0], at->x, at->y, at->z, 0.907571f, 0, 0, 0.438371f, 0.898794f, RESPAWN_ONE_DAY)
+ if (!AddObject(BG_EY_OBJECT_SPEEDBUFF_FEL_REALVER + i * 3, Buff_Entries[0], at->x, at->y, at->z, 0.907571f, 0, 0, 0.438371f, 0.898794f, RESPAWN_ONE_DAY)
|| !AddObject(BG_EY_OBJECT_SPEEDBUFF_FEL_REALVER + i * 3 + 1, Buff_Entries[1], at->x, at->y, at->z, 0.907571f, 0, 0, 0.438371f, 0.898794f, RESPAWN_ONE_DAY)
|| !AddObject(BG_EY_OBJECT_SPEEDBUFF_FEL_REALVER + i * 3 + 2, Buff_Entries[2], at->x, at->y, at->z, 0.907571f, 0, 0, 0.438371f, 0.898794f, RESPAWN_ONE_DAY)
)
@@ -495,14 +495,14 @@ bool BattleGroundEY::SetupBattleGround()
WorldSafeLocsEntry const *sg = NULL;
sg = sWorldSafeLocsStore.LookupEntry(EY_GRAVEYARD_MAIN_ALLIANCE);
- if( !sg || !AddSpiritGuide(EY_SPIRIT_MAIN_ALLIANCE, sg->x, sg->y, sg->z, 3.124139f, ALLIANCE) )
+ if (!sg || !AddSpiritGuide(EY_SPIRIT_MAIN_ALLIANCE, sg->x, sg->y, sg->z, 3.124139f, ALLIANCE))
{
sLog.outErrorDb("BatteGroundEY: Failed to spawn spirit guide! BattleGround not created!");
return false;
}
sg = sWorldSafeLocsStore.LookupEntry(EY_GRAVEYARD_MAIN_HORDE);
- if( !sg || !AddSpiritGuide(EY_SPIRIT_MAIN_HORDE, sg->x, sg->y, sg->z, 3.193953f, HORDE) )
+ if (!sg || !AddSpiritGuide(EY_SPIRIT_MAIN_HORDE, sg->x, sg->y, sg->z, 3.193953f, HORDE))
{
sLog.outErrorDb("BatteGroundEY: Failed to spawn spirit guide! BattleGround not created!");
return false;
@@ -552,7 +552,7 @@ void BattleGroundEY::RespawnFlag(bool send_message)
m_FlagState = BG_EY_FLAG_STATE_ON_BASE;
SpawnBGObject(BG_EY_OBJECT_FLAG_NETHERSTORM, RESPAWN_IMMEDIATELY);
- if(send_message)
+ if (send_message)
{
SendMessageToAll(LANG_BG_EY_RESETED_FLAG, CHAT_MSG_BG_SYSTEM_NEUTRAL);
PlaySoundToAll(BG_EY_SOUND_FLAG_RESET); // flags respawned sound...
@@ -566,7 +566,7 @@ void BattleGroundEY::RespawnFlagAfterDrop()
RespawnFlag(true);
GameObject *obj = HashMapHolder<GameObject>::Find(GetDroppedFlagGUID());
- if(obj)
+ if (obj)
obj->Delete();
else
sLog.outError("BattleGroundEY: Unknown dropped flag guid: %u",GUID_LOPART(GetDroppedFlagGUID()));
@@ -576,7 +576,7 @@ void BattleGroundEY::RespawnFlagAfterDrop()
void BattleGroundEY::HandleKillPlayer(Player *player, Player *killer)
{
- if(GetStatus() != STATUS_IN_PROGRESS)
+ if (GetStatus() != STATUS_IN_PROGRESS)
return;
BattleGround::HandleKillPlayer(player, killer);
@@ -585,11 +585,11 @@ void BattleGroundEY::HandleKillPlayer(Player *player, Player *killer)
void BattleGroundEY::EventPlayerDroppedFlag(Player *Source)
{
- if(GetStatus() != STATUS_IN_PROGRESS)
+ if (GetStatus() != STATUS_IN_PROGRESS)
{
// if not running, do not cast things at the dropper player, neither send unnecessary messages
// just take off the aura
- if(IsFlagPickedup() && GetFlagPickerGUID() == Source->GetGUID())
+ if (IsFlagPickedup() && GetFlagPickerGUID() == Source->GetGUID())
{
SetFlagPicker(0);
Source->RemoveAurasDueToSpell(BG_EY_NETHERSTORM_FLAG_SPELL);
@@ -597,10 +597,10 @@ void BattleGroundEY::EventPlayerDroppedFlag(Player *Source)
return;
}
- if(!IsFlagPickedup())
+ if (!IsFlagPickedup())
return;
- if(GetFlagPickerGUID() != Source->GetGUID())
+ if (GetFlagPickerGUID() != Source->GetGUID())
return;
SetFlagPicker(0);
@@ -613,7 +613,7 @@ void BattleGroundEY::EventPlayerDroppedFlag(Player *Source)
UpdateWorldState(NETHERSTORM_FLAG_STATE_HORDE, BG_EY_FLAG_STATE_WAIT_RESPAWN);
UpdateWorldState(NETHERSTORM_FLAG_STATE_ALLIANCE, BG_EY_FLAG_STATE_WAIT_RESPAWN);
- if(Source->GetTeam() == ALLIANCE)
+ if (Source->GetTeam() == ALLIANCE)
SendMessageToAll(LANG_BG_EY_DROPPED_FLAG, CHAT_MSG_BG_SYSTEM_ALLIANCE, NULL);
else
SendMessageToAll(LANG_BG_EY_DROPPED_FLAG, CHAT_MSG_BG_SYSTEM_HORDE, NULL);
@@ -621,10 +621,10 @@ void BattleGroundEY::EventPlayerDroppedFlag(Player *Source)
void BattleGroundEY::EventPlayerClickedOnFlag(Player *Source, GameObject* target_obj)
{
- if(GetStatus() != STATUS_IN_PROGRESS || this->IsFlagPickedup() || !Source->IsWithinDistInMap(target_obj, 10))
+ if (GetStatus() != STATUS_IN_PROGRESS || IsFlagPickedup() || !Source->IsWithinDistInMap(target_obj, 10))
return;
- if(Source->GetTeam() == ALLIANCE)
+ if (Source->GetTeam() == ALLIANCE)
{
UpdateWorldState(NETHERSTORM_FLAG_STATE_ALLIANCE, BG_EY_FLAG_STATE_ON_PLAYER);
PlaySoundToAll(BG_EY_SOUND_FLAG_PICKED_UP_ALLIANCE);
@@ -645,7 +645,7 @@ void BattleGroundEY::EventPlayerClickedOnFlag(Player *Source, GameObject* target
Source->CastSpell(Source, BG_EY_NETHERSTORM_FLAG_SPELL, true);
Source->RemoveAurasWithInterruptFlags(AURA_INTERRUPT_FLAG_ENTER_PVP_COMBAT);
- if(Source->GetTeam() == ALLIANCE)
+ if (Source->GetTeam() == ALLIANCE)
PSendMessageToAll(LANG_BG_EY_HAS_TAKEN_FLAG, CHAT_MSG_BG_SYSTEM_ALLIANCE, NULL, Source->GetName());
else
PSendMessageToAll(LANG_BG_EY_HAS_TAKEN_FLAG, CHAT_MSG_BG_SYSTEM_HORDE, NULL, Source->GetName());
@@ -653,13 +653,13 @@ void BattleGroundEY::EventPlayerClickedOnFlag(Player *Source, GameObject* target
void BattleGroundEY::EventTeamLostPoint(Player *Source, uint32 Point)
{
- if(GetStatus() != STATUS_IN_PROGRESS)
+ if (GetStatus() != STATUS_IN_PROGRESS)
return;
//Natural point
uint32 Team = m_PointOwnedByTeam[Point];
- if(!Team)
+ if (!Team)
return;
if (Team == ALLIANCE)
@@ -697,7 +697,7 @@ void BattleGroundEY::EventTeamLostPoint(Player *Source, uint32 Point)
void BattleGroundEY::EventTeamCapturedPoint(Player *Source, uint32 Point)
{
- if(GetStatus() != STATUS_IN_PROGRESS)
+ if (GetStatus() != STATUS_IN_PROGRESS)
return;
uint32 Team = Source->GetTeam();
@@ -731,12 +731,12 @@ void BattleGroundEY::EventTeamCapturedPoint(Player *Source, uint32 Point)
else
SendMessageToAll(m_CapturingPointTypes[Point].MessageIdHorde,CHAT_MSG_BG_SYSTEM_HORDE, Source);
- if(m_BgCreatures[Point])
+ if (m_BgCreatures[Point])
DelCreature(Point);
WorldSafeLocsEntry const *sg = NULL;
sg = sWorldSafeLocsStore.LookupEntry(m_CapturingPointTypes[Point].GraveYardId);
- if(!sg || !AddSpiritGuide(Point, sg->x, sg->y, sg->z, 3.124139f, Team))
+ if (!sg || !AddSpiritGuide(Point, sg->x, sg->y, sg->z, 3.124139f, Team))
sLog.outError("BatteGroundEY: Failed to spawn spirit guide! point: %u, team: %u, graveyard_id: %u",
Point, Team, m_CapturingPointTypes[Point].GraveYardId);
@@ -748,7 +748,7 @@ void BattleGroundEY::EventTeamCapturedPoint(Player *Source, uint32 Point)
void BattleGroundEY::EventPlayerCapturedFlag(Player *Source, uint32 BgObjectType)
{
- if(GetStatus() != STATUS_IN_PROGRESS || this->GetFlagPickerGUID() != Source->GetGUID())
+ if (GetStatus() != STATUS_IN_PROGRESS || GetFlagPickerGUID() != Source->GetGUID())
return;
SetFlagPicker(0);
@@ -757,7 +757,7 @@ void BattleGroundEY::EventPlayerCapturedFlag(Player *Source, uint32 BgObjectType
Source->RemoveAurasWithInterruptFlags(AURA_INTERRUPT_FLAG_ENTER_PVP_COMBAT);
- if(Source->GetTeam() == ALLIANCE)
+ if (Source->GetTeam() == ALLIANCE)
PlaySoundToAll(BG_EY_SOUND_FLAG_CAPTURED_ALLIANCE);
else
PlaySoundToAll(BG_EY_SOUND_FLAG_CAPTURED_HORDE);
@@ -768,7 +768,7 @@ void BattleGroundEY::EventPlayerCapturedFlag(Player *Source, uint32 BgObjectType
m_FlagCapturedBgObjectType = BgObjectType;
uint8 team_id = 0;
- if(Source->GetTeam() == ALLIANCE)
+ if (Source->GetTeam() == ALLIANCE)
{
team_id = BG_TEAM_ALLIANCE;
SendMessageToAll(LANG_BG_EY_CAPTURED_FLAG_A, CHAT_MSG_BG_SYSTEM_ALLIANCE, Source);
@@ -779,7 +779,7 @@ void BattleGroundEY::EventPlayerCapturedFlag(Player *Source, uint32 BgObjectType
SendMessageToAll(LANG_BG_EY_CAPTURED_FLAG_H, CHAT_MSG_BG_SYSTEM_HORDE, Source);
}
- if(m_TeamPointsCount[team_id] > 0)
+ if (m_TeamPointsCount[team_id] > 0)
AddPoints(Source->GetTeam(), BG_EY_FlagPoints[m_TeamPointsCount[team_id] - 1]);
UpdatePlayerScore(Source, SCORE_FLAG_CAPTURES, 1);
@@ -871,7 +871,7 @@ WorldSafeLocsEntry const *BattleGroundEY::GetClosestGraveYard(Player* player)
entry = sWorldSafeLocsStore.LookupEntry(g_id);
nearestEntry = entry;
- if(!entry)
+ if (!entry)
{
sLog.outError("BattleGroundEY: Not found the main team graveyard. Graveyard system isn't working!");
return NULL;
@@ -887,15 +887,15 @@ WorldSafeLocsEntry const *BattleGroundEY::GetClosestGraveYard(Player* player)
for(uint8 i = 0; i < EY_POINTS_MAX; ++i)
{
- if(m_PointOwnedByTeam[i]==player->GetTeam() && m_PointState[i]==EY_POINT_UNDER_CONTROL)
+ if (m_PointOwnedByTeam[i]==player->GetTeam() && m_PointState[i]==EY_POINT_UNDER_CONTROL)
{
entry = sWorldSafeLocsStore.LookupEntry(m_CapturingPointTypes[i].GraveYardId);
- if(!entry)
+ if (!entry)
sLog.outError("BattleGroundEY: Not found graveyard: %u",m_CapturingPointTypes[i].GraveYardId);
else
{
distance = (entry->x - plr_x)*(entry->x - plr_x) + (entry->y - plr_y)*(entry->y - plr_y) + (entry->z - plr_z)*(entry->z - plr_z);
- if(distance < nearestDistance)
+ if (distance < nearestDistance)
{
nearestDistance = distance;
nearestEntry = entry;
diff --git a/src/game/BattleGroundHandler.cpp b/src/game/BattleGroundHandler.cpp
index f3be835e0f2..6e94a8c8a9f 100644
--- a/src/game/BattleGroundHandler.cpp
+++ b/src/game/BattleGroundHandler.cpp
@@ -43,7 +43,7 @@ void WorldSession::HandleBattleGroundHelloOpcode( WorldPacket & recv_data )
sLog.outDebug( "WORLD: Recvd CMSG_BATTLEMASTER_HELLO Message from: " I64FMT, guid);
Creature *unit = ObjectAccessor::GetCreature(*_player, guid);
- if(!unit)
+ if (!unit)
return;
if(!unit->isBattleMaster()) // it's not battlemaster
@@ -54,7 +54,7 @@ void WorldSession::HandleBattleGroundHelloOpcode( WorldPacket & recv_data )
BattleGroundTypeId bgTypeId = sBattleGroundMgr.GetBattleMasterBG(unit->GetEntry());
- if(!_player->GetBGAccessByLevel(bgTypeId))
+ if (!_player->GetBGAccessByLevel(bgTypeId))
{
// temp, must be gossip message...
SendNotification(LANG_YOUR_BG_LEVEL_REQ_ERROR);
@@ -87,7 +87,7 @@ void WorldSession::HandleBattleGroundJoinOpcode( WorldPacket & recv_data )
recv_data >> instanceId; // instance id, 0 if First Available selected
recv_data >> joinAsGroup; // join as group
- if(!sBattlemasterListStore.LookupEntry(bgTypeId_))
+ if (!sBattlemasterListStore.LookupEntry(bgTypeId_))
{
sLog.outError("Battleground: invalid bgtype (%u) received. possible cheater? player guid %u",bgTypeId_,_player->GetGUIDLow());
return;
@@ -101,11 +101,11 @@ void WorldSession::HandleBattleGroundJoinOpcode( WorldPacket & recv_data )
BattleGroundQueueTypeId bgQueueTypeId = BattleGroundMgr::BGQueueTypeId(bgTypeId, 0);
// ignore if player is already in BG
- if(_player->InBattleGround())
+ if (_player->InBattleGround())
return;
Creature *unit = ObjectAccessor::GetCreature(*_player, guid);
- if(!unit)
+ if (!unit)
return;
if(!unit->isBattleMaster()) // it's not battlemaster
@@ -113,20 +113,20 @@ void WorldSession::HandleBattleGroundJoinOpcode( WorldPacket & recv_data )
// get bg instance or bg template if instance not found
BattleGround * bg = NULL;
- if(instanceId)
+ if (instanceId)
BattleGround *bg = sBattleGroundMgr.GetBattleGroundThroughClientInstance(instanceId, bgTypeId, _player->GetBattleGroundQueueIdFromLevel(bgTypeId));
- if(!bg && !(bg = sBattleGroundMgr.GetBattleGroundTemplate(bgTypeId)))
+ if (!bg && !(bg = sBattleGroundMgr.GetBattleGroundTemplate(bgTypeId)))
{
sLog.outError("Battleground: no available bg / template found");
return;
}
// check queueing conditions
- if(!joinAsGroup)
+ if (!joinAsGroup)
{
// check Deserter debuff
- if( !_player->CanJoinToBattleground() )
+ if (!_player->CanJoinToBattleground())
{
WorldPacket data(SMSG_GROUP_JOINED_BATTLEGROUND, 4);
data << uint32(0xFFFFFFFE);
@@ -138,14 +138,14 @@ void WorldSession::HandleBattleGroundJoinOpcode( WorldPacket & recv_data )
//player is already in this queue
return;
// check if has free queue slots
- if(!_player->HasFreeBattleGroundQueueId())
+ if (!_player->HasFreeBattleGroundQueueId())
return;
}
else
{
grp = _player->GetGroup();
// no group found, error
- if(!grp)
+ if (!grp)
return;
uint32 err = grp->CanJoinBattleGroundQueue(bgTypeId, bgQueueTypeId, 0, bg->GetMaxPlayersPerTeam(), false, 0);
isPremade = (grp->GetMembersCount() >= bg->GetMinPlayersPerTeam());
@@ -160,7 +160,7 @@ void WorldSession::HandleBattleGroundJoinOpcode( WorldPacket & recv_data )
// _player->GetGroup() was already checked, grp is already initialized
GroupQueueInfo * ginfo = sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].AddGroup(_player, bgTypeId, 0, false, isPremade, 0);
uint32 avgTime = sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].GetAverageQueueWaitTime(ginfo, _player->GetBattleGroundQueueIdFromLevel(bgTypeId));
- if(joinAsGroup /* && _player->GetGroup()*/)
+ if (joinAsGroup /* && _player->GetGroup()*/)
{
sLog.outDebug("Battleground: the following players are joining as group:");
for(GroupReference *itr = grp->GetFirstMember(); itr != NULL; itr = itr->next())
@@ -200,7 +200,7 @@ void WorldSession::HandleBattleGroundJoinOpcode( WorldPacket & recv_data )
sLog.outDebug("Battleground: player joined queue for bg queue type %u bg type %u: GUID %u, NAME %s",bgQueueTypeId,bgTypeId,_player->GetGUIDLow(), _player->GetName());
}
sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].Update(bgTypeId, _player->GetBattleGroundQueueIdFromLevel(bgTypeId));
- if(!ginfo->IsInvitedToBGInstanceGUID)
+ if (!ginfo->IsInvitedToBGInstanceGUID)
sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].AnnounceWorld(ginfo, _player->GetGUID(), true);
}
@@ -213,40 +213,62 @@ void WorldSession::HandleBattleGroundPlayerPositionsOpcode( WorldPacket & /*recv
if(!bg) // can't be received if player not in battleground
return;
- if(bg->GetTypeID() == BATTLEGROUND_WS)
+ switch( bg->GetTypeID() )
{
- uint32 count1 = 0;
- uint32 count2 = 0;
+ case BATTLEGROUND_WS:
+ {
+ uint32 count1 = 0; //always constant zero?
+ uint32 count2 = 0; //count of next fields
- Player *ap = objmgr.GetPlayer(((BattleGroundWS*)bg)->GetAllianceFlagPickerGUID());
- if(ap) ++count2;
+ Player *ali_plr = objmgr.GetPlayer(((BattleGroundWS*)bg)->GetAllianceFlagPickerGUID());
+ if (ali_plr)
+ ++count2;
- Player *hp = objmgr.GetPlayer(((BattleGroundWS*)bg)->GetHordeFlagPickerGUID());
- if(hp) ++count2;
+ Player *horde_plr = objmgr.GetPlayer(((BattleGroundWS*)bg)->GetHordeFlagPickerGUID());
+ if (horde_plr)
+ ++count2;
- WorldPacket data(MSG_BATTLEGROUND_PLAYER_POSITIONS, (4+4+16*count1+16*count2));
- data << count1; // alliance flag holders count
- /*for(uint8 i = 0; i < count1; i++)
- {
- data << uint64(0); // guid
- data << (float)0; // x
- data << (float)0; // y
- }*/
- data << count2; // horde flag holders count
- if(ap)
- {
- data << (uint64)ap->GetGUID();
- data << (float)ap->GetPositionX();
- data << (float)ap->GetPositionY();
- }
- if(hp)
- {
- data << (uint64)hp->GetGUID();
- data << (float)hp->GetPositionX();
- data << (float)hp->GetPositionY();
- }
+ WorldPacket data(MSG_BATTLEGROUND_PLAYER_POSITIONS, (4+4+16*count1+16*count2));
+ data << count1; // alliance flag holders count - obsolete, now always 0
+ /*for(uint8 i = 0; i < count1; i++)
+ {
+ data << uint64(0); // guid
+ data << (float)0; // x
+ data << (float)0; // y
+ }*/
+ data << count2; // horde flag holders count - obsolete, now count of next fields
+ if (ali_plr)
+ {
+ data << (uint64)ali_plr->GetGUID();
+ data << (float)ali_plr->GetPositionX();
+ data << (float)ali_plr->GetPositionY();
+ }
+ if (horde_plr)
+ {
+ data << (uint64)horde_plr->GetGUID();
+ data << (float)horde_plr->GetPositionX();
+ data << (float)horde_plr->GetPositionY();
+ }
- SendPacket(&data);
+ SendPacket(&data);
+ }
+ break;
+ case BATTLEGROUND_EY:
+ //TODO : fix me!
+ break;
+ case BATTLEGROUND_AB:
+ case BATTLEGROUND_AV:
+ {
+ //for other BG types - send default
+ WorldPacket data(MSG_BATTLEGROUND_PLAYER_POSITIONS, (4+4));
+ data << uint32(0);
+ data << uint32(0);
+ SendPacket(&data);
+ }
+ break;
+ default:
+ //maybe it is sent also in arena - do nothing
+ break;
}
}
@@ -255,7 +277,7 @@ void WorldSession::HandleBattleGroundPVPlogdataOpcode( WorldPacket & /*recv_data
sLog.outDebug( "WORLD: Recvd MSG_PVP_LOG_DATA Message");
BattleGround *bg = _player->GetBattleGround();
- if(!bg)
+ if (!bg)
return;
WorldPacket data;
@@ -275,7 +297,7 @@ void WorldSession::HandleBattleGroundListOpcode( WorldPacket &recv_data )
recv_data >> bgTypeId; // id from DBC
BattlemasterListEntry const* bl = sBattlemasterListStore.LookupEntry(bgTypeId);
- if(!bl)
+ if (!bl)
{
sLog.outError("Battleground: invalid bgtype received.");
return;
@@ -301,25 +323,25 @@ void WorldSession::HandleBattleGroundPlayerPortOpcode( WorldPacket &recv_data )
recv_data >> type >> unk2 >> bgTypeId_ >> unk >> action;
- if( !sBattlemasterListStore.LookupEntry(bgTypeId_) )
+ if (!sBattlemasterListStore.LookupEntry(bgTypeId_))
{
sLog.outError("Battleground: invalid bgtype (%u) received.", bgTypeId_);
// update battleground slots for the player to fix his UI and sent data.
// this is a HACK, I don't know why the client starts sending invalid packets in the first place.
// it usually happens with extremely high latency (if debugging / stepping in the code for example)
- if( _player->InBattleGroundQueue() )
+ if (_player->InBattleGroundQueue())
{
// update all queues, send invitation info if player is invited, queue info if queued
for (uint32 i = 0; i < PLAYER_MAX_BATTLEGROUND_QUEUES; i++)
{
BattleGroundQueueTypeId bgQueueTypeId = _player->GetBattleGroundQueueTypeId(i);
- if( !bgQueueTypeId )
+ if (!bgQueueTypeId)
continue;
BattleGroundTypeId bgTypeId = BattleGroundMgr::BGTemplateId(bgQueueTypeId);
BattleGroundQueue::QueuedPlayersMap& qpMap = sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].m_QueuedPlayers;
BattleGroundQueue::QueuedPlayersMap::iterator itrPlayerStatus = qpMap.find(_player->GetGUID());
// if the player is not in queue, continue or no group information - this should never happen
- if( itrPlayerStatus == qpMap.end() || !itrPlayerStatus->second.GroupInfo )
+ if (itrPlayerStatus == qpMap.end() || !itrPlayerStatus->second.GroupInfo)
continue;
BattleGround * bg = NULL;
@@ -328,7 +350,7 @@ void WorldSession::HandleBattleGroundPlayerPortOpcode( WorldPacket &recv_data )
uint8 israted = itrPlayerStatus->second.GroupInfo->IsRated;
uint8 status = 0;
- if( !itrPlayerStatus->second.GroupInfo->IsInvitedToBGInstanceGUID )
+ if (!itrPlayerStatus->second.GroupInfo->IsInvitedToBGInstanceGUID)
{
// not invited to bg, get template
bg = sBattleGroundMgr.GetBattleGroundTemplate(bgTypeId);
@@ -342,7 +364,7 @@ void WorldSession::HandleBattleGroundPlayerPortOpcode( WorldPacket &recv_data )
}
// if bg not found, then continue, don't invite if already in the instance
- if( !bg || (_player->InBattleGround() && _player->GetBattleGround() && _player->GetBattleGround()->GetInstanceID() == bg->GetInstanceID()) )
+ if (!bg || (_player->InBattleGround() && _player->GetBattleGround() && _player->GetBattleGround()->GetInstanceID() == bg->GetInstanceID()))
continue;
// re - invite player with proper data
@@ -359,7 +381,7 @@ void WorldSession::HandleBattleGroundPlayerPortOpcode( WorldPacket &recv_data )
BattleGroundQueueTypeId bgQueueTypeId = BattleGroundMgr::BGQueueTypeId(bgTypeId, type);
BattleGroundQueue::QueuedPlayersMap& qpMap = sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].m_QueuedPlayers;
BattleGroundQueue::QueuedPlayersMap::iterator itrPlayerStatus = qpMap.find(_player->GetGUID());
- if( itrPlayerStatus == qpMap.end() )
+ if (itrPlayerStatus == qpMap.end())
{
sLog.outError("Battleground: itrplayerstatus not found.");
return;
@@ -367,7 +389,7 @@ void WorldSession::HandleBattleGroundPlayerPortOpcode( WorldPacket &recv_data )
instanceId = itrPlayerStatus->second.GroupInfo->IsInvitedToBGInstanceGUID;
// if action == 1, then instanceId is required
- if( !instanceId && action == 1 )
+ if (!instanceId && action == 1)
{
sLog.outError("Battleground: instance not found.");
return;
@@ -376,15 +398,15 @@ void WorldSession::HandleBattleGroundPlayerPortOpcode( WorldPacket &recv_data )
BattleGround *bg = sBattleGroundMgr.GetBattleGround(instanceId, bgTypeId);
// bg template might and must be used in case of leaving queue, when instance is not created yet
- if( !bg && action == 0 )
+ if (!bg && action == 0)
bg = sBattleGroundMgr.GetBattleGroundTemplate(bgTypeId);
- if( !bg )
+ if (!bg)
{
sLog.outError("Battleground: bg_template not found for type id %u.", bgTypeId);
return;
}
- if( _player->InBattleGroundQueue() )
+ if (_player->InBattleGroundQueue())
{
//we must use temporary variables, because GroupQueueInfo pointer can be deleted in BattleGroundQueue::RemovePlayer() function!
uint32 team = itrPlayerStatus->second.GroupInfo->Team;
@@ -394,10 +416,10 @@ void WorldSession::HandleBattleGroundPlayerPortOpcode( WorldPacket &recv_data )
uint32 opponentsRating = itrPlayerStatus->second.GroupInfo->OpponentsTeamRating;
//some checks if player isn't cheating - it is not exactly cheating, but we cannot allow it
- if( action == 1 && arenaType == 0)
+ if (action == 1 && arenaType == 0)
{
//if player is trying to enter battleground (not arena!) and he has deserter debuff, we must just remove him from queue
- if( !_player->CanJoinToBattleground() )
+ if (!_player->CanJoinToBattleground())
{
//send bg command result to show nice message
WorldPacket data2(SMSG_GROUP_JOINED_BATTLEGROUND, 4);
@@ -407,7 +429,7 @@ void WorldSession::HandleBattleGroundPlayerPortOpcode( WorldPacket &recv_data )
sLog.outDebug("Battleground: player %s (%u) has a deserter debuff, do not port him to battleground!", _player->GetName(), _player->GetGUIDLow());
}
//if player don't match battleground max level, then do not allow him to enter! (this might happen when player leveled up during his waiting in queue
- if( _player->getLevel() > bg->GetMaxLevel() )
+ if (_player->getLevel() > bg->GetMaxLevel())
{
sLog.outError("Battleground: Player %s (%u) has level higher than maxlevel of battleground! Do not port him to battleground!", _player->GetName(), _player->GetGUIDLow());
action = 0;
@@ -418,16 +440,16 @@ void WorldSession::HandleBattleGroundPlayerPortOpcode( WorldPacket &recv_data )
switch( action )
{
case 1: // port to battleground
- if( !_player->IsInvitedForBattleGroundQueueType(bgQueueTypeId) )
+ if (!_player->IsInvitedForBattleGroundQueueType(bgQueueTypeId))
return; // cheating?
// resurrect the player
- if( !_player->isAlive() )
+ if (!_player->isAlive())
{
_player->ResurrectPlayer(1.0f);
_player->SpawnCorpseBones();
}
// stop taxi flight at port
- if(_player->isInFlight())
+ if (_player->isInFlight())
{
_player->GetMotionMaster()->MovementExpired();
_player->m_taxi.ClearTaxiDestinations();
@@ -439,7 +461,7 @@ void WorldSession::HandleBattleGroundPlayerPortOpcode( WorldPacket &recv_data )
sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].RemovePlayer(_player->GetGUID(), false);
// this is still needed here if battleground "jumping" shouldn't add deserter debuff
// also this is required to prevent stuck at old battleground after SetBattleGroundId set to new
- if( BattleGround *currentBg = _player->GetBattleGround() )
+ if (BattleGround *currentBg = _player->GetBattleGround())
currentBg->RemovePlayerAtLeave(_player->GetGUID(), false, true);
// set the destination instance id
@@ -454,10 +476,10 @@ void WorldSession::HandleBattleGroundPlayerPortOpcode( WorldPacket &recv_data )
break;
case 0: // leave queue
// if player leaves rated arena match before match start, it is counted as he played but he lost
- if( isRated )
+ if (isRated)
{
ArenaTeam * at = objmgr.GetArenaTeamById(team);
- if( at )
+ if (at)
{
sLog.outDebug("UPDATING memberLost's personal arena rating for %u by opponents rating: %u, because he has left queue!", GUID_LOPART(_player->GetGUID()), opponentsRating);
at->MemberLost(_player, opponentsRating);
@@ -468,7 +490,7 @@ void WorldSession::HandleBattleGroundPlayerPortOpcode( WorldPacket &recv_data )
sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, bg, queueSlot, STATUS_NONE, 0, 0, 0);
sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].RemovePlayer(_player->GetGUID(), true);
// player left queue, we should update it - do not update Arena Queue
- if( !arenaType )
+ if (!arenaType)
sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].Update(bgTypeId, _player->GetBattleGroundQueueIdFromLevel(bgTypeId), arenaType, isRated, rating);
SendPacket(&data);
sLog.outDebug("Battleground: player %s (%u) left queue for bgtype %u, queue type %u.", _player->GetName(), _player->GetGUIDLow(), bg->GetTypeID(), bgQueueTypeId);
@@ -496,9 +518,9 @@ void WorldSession::HandleBattleGroundLeaveOpcode( WorldPacket & /*recv_data*/ )
// return;
// not allow leave battleground in combat
- if(_player->isInCombat())
- if(BattleGround* bg = _player->GetBattleGround())
- if(bg->GetStatus() != STATUS_WAIT_LEAVE)
+ if (_player->isInCombat())
+ if (BattleGround* bg = _player->GetBattleGround())
+ if (bg->GetStatus() != STATUS_WAIT_LEAVE)
return;
_player->LeaveBattleground();
@@ -515,16 +537,16 @@ void WorldSession::HandleBattlefieldStatusOpcode( WorldPacket & /*recv_data*/ )
for (uint8 i = 0; i < PLAYER_MAX_BATTLEGROUND_QUEUES; i++)
{
BattleGroundQueueTypeId bgQueueTypeId = _player->GetBattleGroundQueueTypeId(i);
- if( !bgQueueTypeId )
+ if (!bgQueueTypeId)
continue;
BattleGroundTypeId bgTypeId = BattleGroundMgr::BGTemplateId(bgQueueTypeId);
uint8 arenaType = BattleGroundMgr::BGArenaType(bgQueueTypeId);
- if( bgTypeId == _player->GetBattleGroundTypeId() )
+ if (bgTypeId == _player->GetBattleGroundTypeId())
{
bg = _player->GetBattleGround();
//i cannot check any variable from player class because player class doesn't know if player is in 2v2 / 3v3 or 5v5 arena
//so i must use bg pointer to get that information
- if( bg && bg->GetArenaType() == arenaType )
+ if (bg && bg->GetArenaType() == arenaType)
{
// this line is checked, i only don't know if GetStartTime is changing itself after bg end!
// send status in BattleGround
@@ -537,12 +559,12 @@ void WorldSession::HandleBattlefieldStatusOpcode( WorldPacket & /*recv_data*/ )
//get GroupQueueInfo for queue status
BattleGroundQueue::QueuedPlayersMap& qpMap = sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].m_QueuedPlayers;
BattleGroundQueue::QueuedPlayersMap::iterator itrPlayerStatus = qpMap.find(_player->GetGUID());
- if( itrPlayerStatus == qpMap.end() )
+ if (itrPlayerStatus == qpMap.end())
continue;
- if( itrPlayerStatus->second.GroupInfo->IsInvitedToBGInstanceGUID )
+ if (itrPlayerStatus->second.GroupInfo->IsInvitedToBGInstanceGUID)
{
bg = sBattleGroundMgr.GetBattleGround(itrPlayerStatus->second.GroupInfo->IsInvitedToBGInstanceGUID, bgTypeId);
- if( !bg )
+ if (!bg)
continue;
uint32 remainingTime = getMSTimeDiff(getMSTime(), itrPlayerStatus->second.GroupInfo->RemoveInviteTime);
// send status invited to BattleGround
@@ -552,7 +574,7 @@ void WorldSession::HandleBattlefieldStatusOpcode( WorldPacket & /*recv_data*/ )
else
{
BattleGround *bg = sBattleGroundMgr.GetBattleGroundTemplate(bgTypeId);
- if( !bg )
+ if (!bg)
continue;
uint32 avgTime = sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].GetAverageQueueWaitTime(itrPlayerStatus->second.GroupInfo, _player->GetBattleGroundQueueIdFromLevel(bgTypeId));
// send status in BattleGround Queue
@@ -569,14 +591,14 @@ void WorldSession::HandleAreaSpiritHealerQueryOpcode( WorldPacket & recv_data )
CHECK_PACKET_SIZE(recv_data, 8);
BattleGround *bg = _player->GetBattleGround();
- if(!bg)
+ if (!bg)
return;
uint64 guid;
recv_data >> guid;
Creature *unit = ObjectAccessor::GetCreature(*_player, guid);
- if(!unit)
+ if (!unit)
return;
if(!unit->isSpiritService()) // it's not spirit service
@@ -592,14 +614,14 @@ void WorldSession::HandleAreaSpiritHealerQueueOpcode( WorldPacket & recv_data )
CHECK_PACKET_SIZE(recv_data, 8);
BattleGround *bg = _player->GetBattleGround();
- if(!bg)
+ if (!bg)
return;
uint64 guid;
recv_data >> guid;
Creature *unit = ObjectAccessor::GetCreature(*_player, guid);
- if(!unit)
+ if (!unit)
return;
if(!unit->isSpiritService()) // it's not spirit service
@@ -616,7 +638,7 @@ void WorldSession::HandleBattleGroundArenaJoin( WorldPacket & recv_data )
recv_data.hexlike();
// ignore if we already in BG or BG queue
- if(_player->InBattleGround())
+ if (_player->InBattleGround())
return;
uint64 guid; // arena Battlemaster guid
@@ -628,7 +650,7 @@ void WorldSession::HandleBattleGroundArenaJoin( WorldPacket & recv_data )
recv_data >> guid >> arenaslot >> asGroup >> isRated;
Creature *unit = ObjectAccessor::GetCreature(*_player, guid);
- if(!unit)
+ if (!unit)
return;
if(!unit->isBattleMaster()) // it's not battle master
@@ -655,7 +677,7 @@ void WorldSession::HandleBattleGroundArenaJoin( WorldPacket & recv_data )
//check existance
BattleGround* bg = NULL;
- if( !(bg = sBattleGroundMgr.GetBattleGroundTemplate(BATTLEGROUND_AA)) )
+ if (!(bg = sBattleGroundMgr.GetBattleGroundTemplate(BATTLEGROUND_AA)))
{
sLog.outError("Battleground: template bg (all arenas) not found");
return;
@@ -665,21 +687,21 @@ void WorldSession::HandleBattleGroundArenaJoin( WorldPacket & recv_data )
BattleGroundQueueTypeId bgQueueTypeId = BattleGroundMgr::BGQueueTypeId(bgTypeId, arenatype);
// check queueing conditions
- if(!asGroup)
+ if (!asGroup)
{
// check if already in queue
if (_player->GetBattleGroundQueueIndex(bgQueueTypeId) < PLAYER_MAX_BATTLEGROUND_QUEUES)
//player is already in this queue
return;
// check if has free queue slots
- if(!_player->HasFreeBattleGroundQueueId())
+ if (!_player->HasFreeBattleGroundQueueId())
return;
}
else
{
grp = _player->GetGroup();
// no group found, error
- if(!grp)
+ if (!grp)
return;
uint32 err = grp->CanJoinBattleGroundQueue(bgTypeId, bgQueueTypeId, arenatype, arenatype, (bool)isRated, arenaslot);
if (err != BG_JOIN_ERR_OK)
@@ -691,12 +713,12 @@ void WorldSession::HandleBattleGroundArenaJoin( WorldPacket & recv_data )
uint32 ateamId = 0;
- if(isRated)
+ if (isRated)
{
ateamId = _player->GetArenaTeamId(arenaslot);
// check real arenateam existence only here (if it was moved to group->CanJoin .. () then we would ahve to get it twice)
ArenaTeam * at = objmgr.GetArenaTeamById(ateamId);
- if(!at)
+ if (!at)
{
_player->GetSession()->SendNotInArenaTeamPacket(arenatype);
return;
@@ -714,20 +736,20 @@ void WorldSession::HandleBattleGroundArenaJoin( WorldPacket & recv_data )
avg_pers_rating += member->GetUInt32Value(PLAYER_FIELD_ARENA_TEAM_INFO_1_1 + (arenaslot*6) + 5);
}
- if( arenatype )
+ if (arenatype)
avg_pers_rating /= arenatype;
// if avg personal rating is more than 150 points below the teams rating, the team will be queued against an opponent matching or similar to the average personal rating
- if(avg_pers_rating + 150 < arenaRating)
+ if (avg_pers_rating + 150 < arenaRating)
arenaRating = avg_pers_rating;
}
GroupQueueInfo * ginfo = sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].AddGroup(_player, bgTypeId, arenatype, isRated, false, arenaRating, ateamId);
uint32 avgTime = sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].GetAverageQueueWaitTime(ginfo, _player->GetBattleGroundQueueIdFromLevel(bgTypeId));
- if(asGroup)
+ if (asGroup)
{
sLog.outDebug("Battleground: arena join as group start");
- if(isRated)
+ if (isRated)
sLog.outDebug("Battleground: arena team id %u, leader %s queued with rating %u for type %u",_player->GetArenaTeamId(arenaslot),_player->GetName(),arenaRating,arenatype);
for(GroupReference *itr = grp->GetFirstMember(); itr != NULL; itr = itr->next())
{
@@ -749,7 +771,7 @@ void WorldSession::HandleBattleGroundArenaJoin( WorldPacket & recv_data )
sLog.outDebug("Battleground: player joined queue for arena as group bg queue type %u bg type %u: GUID %u, NAME %s",bgQueueTypeId,bgTypeId,member->GetGUIDLow(), member->GetName());
}
sLog.outDebug("Battleground: arena join as group end");
- if(isRated)
+ if (isRated)
sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].AnnounceWorld(ginfo, _player->GetGUID(), true);
}
else
@@ -777,7 +799,7 @@ void WorldSession::HandleBattleGroundReportAFK( WorldPacket & recv_data )
recv_data >> playerGuid;
Player *reportedPlayer = objmgr.GetPlayer(playerGuid);
- if(!reportedPlayer)
+ if (!reportedPlayer)
{
sLog.outDebug("WorldSession::HandleBattleGroundReportAFK: player not found");
return;
diff --git a/src/game/BattleGroundMgr.cpp b/src/game/BattleGroundMgr.cpp
index b3c21d6cb7d..6b7b3c99fe0 100644
--- a/src/game/BattleGroundMgr.cpp
+++ b/src/game/BattleGroundMgr.cpp
@@ -102,7 +102,7 @@ bool BattleGroundQueue::SelectionPool::KickGroup(uint32 size)
GroupsQueueType::iterator groupToKick = SelectedGroups.begin();
for (GroupsQueueType::iterator itr = groupToKick; itr != SelectedGroups.end(); ++itr)
{
- if( abs((int32)((*itr)->Players.size() - size)) <= 1 )
+ if (abs((int32)((*itr)->Players.size() - size)) <= 1)
{
groupToKick = itr;
found = true;
@@ -111,7 +111,7 @@ bool BattleGroundQueue::SelectionPool::KickGroup(uint32 size)
groupToKick = itr;
}
//if pool is empty, do nothing
- if( GetPlayerCount() )
+ if (GetPlayerCount())
{
//update player count
GroupQueueInfo* ginfo = (*groupToKick);
@@ -131,14 +131,14 @@ bool BattleGroundQueue::SelectionPool::KickGroup(uint32 size)
bool BattleGroundQueue::SelectionPool::AddGroup(GroupQueueInfo *ginfo, uint32 desiredCount)
{
//if group is larger than desired count - don't allow to add it to pool
- if( !ginfo->IsInvitedToBGInstanceGUID && desiredCount >= PlayerCount + ginfo->Players.size() )
+ if (!ginfo->IsInvitedToBGInstanceGUID && desiredCount >= PlayerCount + ginfo->Players.size())
{
SelectedGroups.push_back(ginfo);
// increase selected players count
PlayerCount += ginfo->Players.size();
return true;
}
- if( PlayerCount < desiredCount )
+ if (PlayerCount < desiredCount)
return true;
return false;
}
@@ -171,9 +171,9 @@ GroupQueueInfo * BattleGroundQueue::AddGroup(Player *leader, BattleGroundTypeId
//compute index (if group is premade or joined a rated match) to queues
uint32 index = 0;
- if(!isRated && !isPremade)
+ if (!isRated && !isPremade)
index += BG_TEAMS_COUNT;
- if(ginfo->Team == HORDE)
+ if (ginfo->Team == HORDE)
index++;
sLog.outDebug("Adding Group to BattleGroundQueue bgTypeId : %u, queue_id : %u, index : %u", BgTypeId, queue_id, index);
@@ -199,14 +199,14 @@ void BattleGroundQueue::PlayerInvitedToBGUpdateAverageWaitTime(GroupQueueInfo* g
{
uint32 timeInQueue = getMSTimeDiff(ginfo->JoinTime, getMSTime());
uint8 team_index = BG_TEAM_ALLIANCE; //default set to BG_TEAM_ALLIANCE - or non rated arenas!
- if( !ginfo->ArenaType )
+ if (!ginfo->ArenaType)
{
- if( ginfo->Team == HORDE )
+ if (ginfo->Team == HORDE)
team_index = BG_TEAM_HORDE;
}
else
{
- if( ginfo->IsRated )
+ if (ginfo->IsRated)
team_index = BG_TEAM_HORDE; //for rated arenas use BG_TEAM_HORDE
}
@@ -226,18 +226,18 @@ void BattleGroundQueue::PlayerInvitedToBGUpdateAverageWaitTime(GroupQueueInfo* g
uint32 BattleGroundQueue::GetAverageQueueWaitTime(GroupQueueInfo* ginfo, BGQueueIdBasedOnLevel queue_id)
{
uint8 team_index = BG_TEAM_ALLIANCE; //default set to BG_TEAM_ALLIANCE - or non rated arenas!
- if( !ginfo->ArenaType )
+ if (!ginfo->ArenaType)
{
- if( ginfo->Team == HORDE )
+ if (ginfo->Team == HORDE)
team_index = BG_TEAM_HORDE;
}
else
{
- if( ginfo->IsRated )
+ if (ginfo->IsRated)
team_index = BG_TEAM_HORDE; //for rated arenas use BG_TEAM_HORDE
}
//check if there is enought values(we always add values > 0)
- if(m_WaitTimes[team_index][queue_id][COUNT_OF_PLAYERS_TO_AVERAGE_WAIT_TIME - 1] )
+ if (m_WaitTimes[team_index][queue_id][COUNT_OF_PLAYERS_TO_AVERAGE_WAIT_TIME - 1] )
return (m_SumOfWaitTimes[team_index][queue_id] / COUNT_OF_PLAYERS_TO_AVERAGE_WAIT_TIME);
else
//if there aren't enough values return 0 - not available
@@ -254,7 +254,7 @@ void BattleGroundQueue::RemovePlayer(const uint64& guid, bool decreaseInvitedCou
//remove player from map, if he's there
itr = m_QueuedPlayers.find(guid);
- if( itr == m_QueuedPlayers.end() )
+ if (itr == m_QueuedPlayers.end())
{
sLog.outError("BattleGroundQueue: couldn't find player to remove GUID: %u", GUID_LOPART(guid));
return;
@@ -275,7 +275,7 @@ void BattleGroundQueue::RemovePlayer(const uint64& guid, bool decreaseInvitedCou
{
for(group_itr_tmp = m_QueuedGroups[queue_id_tmp][j].begin(); group_itr_tmp != m_QueuedGroups[queue_id_tmp][j].end(); ++group_itr_tmp)
{
- if( (*group_itr_tmp) == group )
+ if ((*group_itr_tmp) == group)
{
queue_id = queue_id_tmp;
group_itr = group_itr_tmp;
@@ -287,7 +287,7 @@ void BattleGroundQueue::RemovePlayer(const uint64& guid, bool decreaseInvitedCou
}
}
//player can't be in queue without group, but just in case
- if( queue_id == -1 )
+ if (queue_id == -1)
{
sLog.outError("BattleGroundQueue: ERROR Cannot find groupinfo for player GUID: %u", GUID_LOPART(guid));
return;
@@ -301,14 +301,14 @@ void BattleGroundQueue::RemovePlayer(const uint64& guid, bool decreaseInvitedCou
// remove player queue info from group queue info
std::map<uint64, PlayerQueueInfo*>::iterator pitr = group->Players.find(guid);
- if( pitr != group->Players.end() )
+ if (pitr != group->Players.end())
group->Players.erase(pitr);
// if invited to bg, and should decrease invited count, then do it
- if( decreaseInvitedCount && group->IsInvitedToBGInstanceGUID )
+ if (decreaseInvitedCount && group->IsInvitedToBGInstanceGUID)
{
BattleGround* bg = sBattleGroundMgr.GetBattleGround(group->IsInvitedToBGInstanceGUID, group->BgTypeId);
- if( bg )
+ if (bg)
bg->DecreaseInvitedCount(group->Team);
}
@@ -316,18 +316,18 @@ void BattleGroundQueue::RemovePlayer(const uint64& guid, bool decreaseInvitedCou
m_QueuedPlayers.erase(itr);
//if we left BG queue(not porting) OR if arena team left queue for rated match
- if( (decreaseInvitedCount && !group->ArenaType) || (group->ArenaType && group->IsRated && group->Players.empty()) )
+ if ((decreaseInvitedCount && !group->ArenaType) || (group->ArenaType && group->IsRated && group->Players.empty()))
AnnounceWorld(group, guid, false);
//if player leaves queue and he is invited to rated arena match, then he have to loose
- if( group->IsInvitedToBGInstanceGUID && group->IsRated && decreaseInvitedCount )
+ if (group->IsInvitedToBGInstanceGUID && group->IsRated && decreaseInvitedCount)
{
ArenaTeam * at = objmgr.GetArenaTeamById(group->ArenaTeamId);
- if( at )
+ if (at)
{
sLog.outDebug("UPDATING memberLost's personal arena rating for %u by opponents rating: %u", GUID_LOPART(guid), group->OpponentsTeamRating);
Player *plr = objmgr.GetPlayer(guid);
- if( plr )
+ if (plr)
at->MemberLost(plr, group->OpponentsTeamRating);
else
at->OfflineMemberLost(guid, group->OpponentsTeamRating);
@@ -336,7 +336,7 @@ void BattleGroundQueue::RemovePlayer(const uint64& guid, bool decreaseInvitedCou
}
// remove group queue info if needed
- if( group->Players.empty() )
+ if (group->Players.empty())
{
m_QueuedGroups[queue_id][index].erase(group_itr);
delete group;
@@ -344,11 +344,11 @@ void BattleGroundQueue::RemovePlayer(const uint64& guid, bool decreaseInvitedCou
// if group wasn't empty, so it wasn't deleted, and player have left a rated
// queue -> everyone from the group should leave too
// don't remove recursively if already invited to bg!
- else if( !group->IsInvitedToBGInstanceGUID && group->IsRated )
+ else if (!group->IsInvitedToBGInstanceGUID && group->IsRated)
{
// remove next player, this is recursive
// first send removal information
- if(Player *plr2 = objmgr.GetPlayer(group->Players.begin()->first))
+ if (Player *plr2 = objmgr.GetPlayer(group->Players.begin()->first))
{
BattleGround * bg = sBattleGroundMgr.GetBattleGroundTemplate(group->BgTypeId);
BattleGroundQueueTypeId bgQueueTypeId = BattleGroundMgr::BGQueueTypeId(group->BgTypeId, group->ArenaType);
@@ -369,14 +369,14 @@ void BattleGroundQueue::AnnounceWorld(GroupQueueInfo *ginfo, const uint64& playe
{
if(ginfo->ArenaType) //if Arena
{
- if( sWorld.getConfig(CONFIG_ARENA_QUEUE_ANNOUNCER_ENABLE) && ginfo->IsRated )
+ if (sWorld.getConfig(CONFIG_ARENA_QUEUE_ANNOUNCER_ENABLE) && ginfo->IsRated)
{
BattleGround* bg = sBattleGroundMgr.GetBattleGroundTemplate(ginfo->BgTypeId);
- if(!bg)
+ if (!bg)
return;
char const* bgName = bg->GetName();
- if(isAddedToQueue)
+ if (isAddedToQueue)
sWorld.SendWorldText(LANG_ARENA_QUEUE_ANNOUNCE_WORLD_JOIN, bgName, ginfo->ArenaType, ginfo->ArenaType, ginfo->ArenaTeamRating);
else
sWorld.SendWorldText(LANG_ARENA_QUEUE_ANNOUNCE_WORLD_EXIT, bgName, ginfo->ArenaType, ginfo->ArenaType, ginfo->ArenaTeamRating);
@@ -384,11 +384,11 @@ void BattleGroundQueue::AnnounceWorld(GroupQueueInfo *ginfo, const uint64& playe
}
else //if BG
{
- if( sWorld.getConfig(CONFIG_BATTLEGROUND_QUEUE_ANNOUNCER_ENABLE) )
+ if (sWorld.getConfig(CONFIG_BATTLEGROUND_QUEUE_ANNOUNCER_ENABLE))
{
Player *plr = objmgr.GetPlayer(playerGUID);
BattleGround* bg = sBattleGroundMgr.GetBattleGroundTemplate(ginfo->BgTypeId);
- if(!bg || !plr)
+ if (!bg || !plr)
return;
BGQueueIdBasedOnLevel queue_id = plr->GetBattleGroundQueueIdFromLevel(bg->GetTypeID());
@@ -399,14 +399,14 @@ void BattleGroundQueue::AnnounceWorld(GroupQueueInfo *ginfo, const uint64& playe
uint32 q_min_level = (queue_id + 1) * 10;
GroupsQueueType::const_iterator itr;
for(itr = m_QueuedGroups[queue_id][BG_QUEUE_NORMAL_ALLIANCE].begin(); itr != m_QueuedGroups[queue_id][BG_QUEUE_NORMAL_ALLIANCE].end(); ++itr)
- if( !(*itr)->IsInvitedToBGInstanceGUID )
+ if (!(*itr)->IsInvitedToBGInstanceGUID)
qAlliance += (*itr)->Players.size();
for(itr = m_QueuedGroups[queue_id][BG_QUEUE_NORMAL_HORDE].begin(); itr != m_QueuedGroups[queue_id][BG_QUEUE_NORMAL_HORDE].end(); ++itr)
- if( !(*itr)->IsInvitedToBGInstanceGUID )
+ if (!(*itr)->IsInvitedToBGInstanceGUID)
qHorde += (*itr)->Players.size();
// Show queue status to player only (when joining queue)
- if( sWorld.getConfig(CONFIG_BATTLEGROUND_QUEUE_ANNOUNCER_PLAYERONLY) )
+ if (sWorld.getConfig(CONFIG_BATTLEGROUND_QUEUE_ANNOUNCER_PLAYERONLY))
{
ChatHandler(plr).PSendSysMessage(LANG_BG_QUEUE_ANNOUNCE_SELF,
bgName, q_min_level, q_min_level + 10, qAlliance, MinPlayers, qHorde, MinPlayers);
@@ -424,29 +424,48 @@ void BattleGroundQueue::AnnounceWorld(GroupQueueInfo *ginfo, const uint64& playe
bool BattleGroundQueue::InviteGroupToBG(GroupQueueInfo * ginfo, BattleGround * bg, uint32 side)
{
// set side if needed
- if( side )
+ if (side)
ginfo->Team = side;
- if( !ginfo->IsInvitedToBGInstanceGUID )
+ if (!ginfo->IsInvitedToBGInstanceGUID)
{
// not yet invited
// set invitation
ginfo->IsInvitedToBGInstanceGUID = bg->GetInstanceID();
- BattleGroundQueueTypeId bgQueueTypeId = BattleGroundMgr::BGQueueTypeId(bg->GetTypeID(), bg->GetArenaType());
+ BattleGroundTypeId bgTypeId = bg->GetTypeID();
+ BattleGroundQueueTypeId bgQueueTypeId = BattleGroundMgr::BGQueueTypeId(bgTypeId, bg->GetArenaType());
BGQueueIdBasedOnLevel queue_id = bg->GetQueueId();
+
+ // set ArenaTeamId for rated matches
+ if (bg->isArena() && bg->isRated())
+ bg->SetArenaTeamIdForTeam(ginfo->Team, ginfo->ArenaTeamId);
+
+ ginfo->RemoveInviteTime = getMSTime() + INVITE_ACCEPT_WAIT_TIME;
+
// loop through the players
for(std::map<uint64,PlayerQueueInfo*>::iterator itr = ginfo->Players.begin(); itr != ginfo->Players.end(); ++itr)
{
// get the player
Player* plr = objmgr.GetPlayer(itr->first);
// if offline, skip him, this should not happen - player is removed from queue when he logs out
- if( !plr )
+ if (!plr)
continue;
// invite the player
PlayerInvitedToBGUpdateAverageWaitTime(ginfo, queue_id);
- ginfo->RemoveInviteTime = getMSTime() + INVITE_ACCEPT_WAIT_TIME;
- sBattleGroundMgr.InvitePlayer(plr, bg->GetInstanceID(), bg->GetTypeID(), ginfo->Team);
+ //sBattleGroundMgr.InvitePlayer(plr, bg, ginfo->Team);
+
+ // set invited player counters
+ bg->IncreaseInvitedCount(ginfo->Team);
+
+ plr->SetInviteForBattleGroundQueueType(bgQueueTypeId, ginfo->IsInvitedToBGInstanceGUID);
+
+ // create remind invite events
+ BGQueueInviteEvent* inviteEvent = new BGQueueInviteEvent(plr->GetGUID(), ginfo->IsInvitedToBGInstanceGUID, bgTypeId, ginfo->RemoveInviteTime);
+ plr->m_Events.AddEvent(inviteEvent, plr->m_Events.CalculateTime(INVITATION_REMIND_TIME));
+ // create automatic remove events
+ BGQueueRemoveEvent* removeEvent = new BGQueueRemoveEvent(plr->GetGUID(), ginfo->IsInvitedToBGInstanceGUID, bgTypeId, bgQueueTypeId, ginfo->RemoveInviteTime);
+ plr->m_Events.AddEvent(removeEvent, plr->m_Events.CalculateTime(INVITE_ACCEPT_WAIT_TIME));
WorldPacket data;
@@ -464,63 +483,6 @@ bool BattleGroundQueue::InviteGroupToBG(GroupQueueInfo * ginfo, BattleGround * b
return false;
}
-// used to remove the Enter Battle window if the battle has already ended, but someone still has it
-// (this can happen in arenas mainly, since the preparation is shorter than the timer for the bgqueueremove event
-void BattleGroundQueue::BGEndedRemoveInvites(BattleGround *bg)
-{
- BGQueueIdBasedOnLevel queue_id = bg->GetQueueId();
- uint32 bgInstanceId = bg->GetInstanceID();
- BattleGroundQueueTypeId bgQueueTypeId = BattleGroundMgr::BGQueueTypeId(bg->GetTypeID(), bg->GetArenaType());
- GroupsQueueType::iterator itr, next;
- for(uint32 i = 0; i < BG_QUEUE_GROUP_TYPES_COUNT; i++)
- {
- itr = m_QueuedGroups[queue_id][i].begin();
- next = itr;
- while (next != m_QueuedGroups[queue_id][i].end())
- {
- // must do this way, because the groupinfo will be deleted when all playerinfos are removed
- itr = next;
- ++next;
- GroupQueueInfo * ginfo = (*itr);
- // if group was invited to this bg instance, then remove all references
- if( ginfo->IsInvitedToBGInstanceGUID == bgInstanceId )
- {
- // after removing this much playerinfos, the ginfo will be deleted, so we'll use a for loop
- uint32 to_remove = ginfo->Players.size();
- for(uint32 j = 0; j < to_remove; j++)
- {
- // always remove the first one in the group
- std::map<uint64, PlayerQueueInfo * >::iterator itr2 = ginfo->Players.begin();
- if( itr2 == ginfo->Players.end() )
- {
- sLog.outError("Empty Players in ginfo, this should never happen!");
- return;
- }
- // get the player
- Player * plr = objmgr.GetPlayer(itr2->first);
- if( !plr )
- {
- sLog.outError("Player offline when trying to remove from GroupQueueInfo, this should never happen.");
- continue;
- }
-
- // get the queueslot
- uint32 queueSlot = plr->GetBattleGroundQueueIndex(bgQueueTypeId);
- if (queueSlot < PLAYER_MAX_BATTLEGROUND_QUEUES) // player is in queue
- {
- plr->RemoveBattleGroundQueueId(bgQueueTypeId);
- // remove player from queue, this might delete the ginfo as well! don't use that pointer after this!
- RemovePlayer(itr2->first, true);
- WorldPacket data;
- sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, bg, queueSlot, STATUS_NONE, 0, 0, 0);
- plr->GetSession()->SendPacket(&data);
- }
- }
- }
- }
- }
-}
-
/*
This function is inviting players to already running battlegrounds
Invitation type is based on config file
@@ -564,18 +526,18 @@ void BattleGroundQueue::FillPlayersToBG(BattleGround* bg, BGQueueIdBasedOnLevel
while( abs(diffAli - diffHorde) > 1 && (m_SelectionPools[BG_TEAM_HORDE].GetPlayerCount() > 0 || m_SelectionPools[BG_TEAM_ALLIANCE].GetPlayerCount() > 0) )
{
//each cycle execution we need to kick at least 1 group
- if( diffAli < diffHorde )
+ if (diffAli < diffHorde)
{
//kick alliance group, add to pool new group if needed
- if( m_SelectionPools[BG_TEAM_ALLIANCE].KickGroup(diffHorde - diffAli) )
+ if (m_SelectionPools[BG_TEAM_ALLIANCE].KickGroup(diffHorde - diffAli))
{
for (; aliIndex < aliCount && m_SelectionPools[BG_TEAM_ALLIANCE].AddGroup((*Ali_itr), (aliFree >= diffHorde) ? aliFree - diffHorde : 0); aliIndex++)
++Ali_itr;
}
//if ali selection is already empty, then kick horde group, but if there are less horde than ali in bg - break;
- if( !m_SelectionPools[BG_TEAM_ALLIANCE].GetPlayerCount() )
+ if (!m_SelectionPools[BG_TEAM_ALLIANCE].GetPlayerCount())
{
- if( aliFree <= diffHorde + 1 )
+ if (aliFree <= diffHorde + 1)
break;
m_SelectionPools[BG_TEAM_HORDE].KickGroup(diffHorde - diffAli);
}
@@ -583,14 +545,14 @@ void BattleGroundQueue::FillPlayersToBG(BattleGround* bg, BGQueueIdBasedOnLevel
else
{
//kick horde group, add to pool new group if needed
- if( m_SelectionPools[BG_TEAM_HORDE].KickGroup(diffAli - diffHorde) )
+ if (m_SelectionPools[BG_TEAM_HORDE].KickGroup(diffAli - diffHorde))
{
for (; hordeIndex < hordeCount && m_SelectionPools[BG_TEAM_HORDE].AddGroup((*Horde_itr), (hordeFree >= diffAli) ? hordeFree - diffAli : 0); hordeIndex++)
++Horde_itr;
}
- if( !m_SelectionPools[BG_TEAM_HORDE].GetPlayerCount() )
+ if (!m_SelectionPools[BG_TEAM_HORDE].GetPlayerCount())
{
- if( hordeFree <= diffAli + 1 )
+ if (hordeFree <= diffAli + 1)
break;
m_SelectionPools[BG_TEAM_ALLIANCE].KickGroup(diffAli - diffHorde);
}
@@ -607,19 +569,19 @@ void BattleGroundQueue::FillPlayersToBG(BattleGround* bg, BGQueueIdBasedOnLevel
bool BattleGroundQueue::CheckPremadeMatch(BGQueueIdBasedOnLevel queue_id, uint32 MinPlayersPerTeam, uint32 MaxPlayersPerTeam)
{
//check match
- if(!m_QueuedGroups[queue_id][BG_QUEUE_PREMADE_ALLIANCE].empty() && !m_QueuedGroups[queue_id][BG_QUEUE_PREMADE_HORDE].empty())
+ if (!m_QueuedGroups[queue_id][BG_QUEUE_PREMADE_ALLIANCE].empty() && !m_QueuedGroups[queue_id][BG_QUEUE_PREMADE_HORDE].empty())
{
//start premade match
//if groups aren't invited
GroupsQueueType::const_iterator ali_group, horde_group;
for( ali_group = m_QueuedGroups[queue_id][BG_QUEUE_PREMADE_ALLIANCE].begin(); ali_group != m_QueuedGroups[queue_id][BG_QUEUE_PREMADE_ALLIANCE].end(); ++ali_group)
- if( !(*ali_group)->IsInvitedToBGInstanceGUID )
+ if (!(*ali_group)->IsInvitedToBGInstanceGUID)
break;
for( horde_group = m_QueuedGroups[queue_id][BG_QUEUE_PREMADE_HORDE].begin(); horde_group != m_QueuedGroups[queue_id][BG_QUEUE_PREMADE_HORDE].end(); ++horde_group)
- if( !(*horde_group)->IsInvitedToBGInstanceGUID )
+ if (!(*horde_group)->IsInvitedToBGInstanceGUID)
break;
- if( ali_group != m_QueuedGroups[queue_id][BG_QUEUE_PREMADE_ALLIANCE].end() && horde_group != m_QueuedGroups[queue_id][BG_QUEUE_PREMADE_HORDE].end())
+ if (ali_group != m_QueuedGroups[queue_id][BG_QUEUE_PREMADE_ALLIANCE].end() && horde_group != m_QueuedGroups[queue_id][BG_QUEUE_PREMADE_HORDE].end())
{
m_SelectionPools[BG_TEAM_ALLIANCE].AddGroup((*ali_group), MaxPlayersPerTeam);
m_SelectionPools[BG_TEAM_HORDE].AddGroup((*horde_group), MaxPlayersPerTeam);
@@ -631,7 +593,7 @@ bool BattleGroundQueue::CheckPremadeMatch(BGQueueIdBasedOnLevel queue_id, uint32
for(itr = m_QueuedGroups[queue_id][BG_QUEUE_NORMAL_ALLIANCE + i].begin(); itr != m_QueuedGroups[queue_id][BG_QUEUE_NORMAL_ALLIANCE + i].end(); ++itr)
{
//if itr can join BG and player count is less that maxPlayers, then add group to selectionpool
- if( !(*itr)->IsInvitedToBGInstanceGUID && !m_SelectionPools[i].AddGroup((*itr), maxPlayers) )
+ if (!(*itr)->IsInvitedToBGInstanceGUID && !m_SelectionPools[i].AddGroup((*itr), maxPlayers))
break;
}
}
@@ -646,10 +608,10 @@ bool BattleGroundQueue::CheckPremadeMatch(BGQueueIdBasedOnLevel queue_id, uint32
uint32 time_before = getMSTime() - sWorld.getConfig(CONFIG_BATTLEGROUND_PREMADE_GROUP_WAIT_FOR_MATCH);
for(uint32 i = 0; i < BG_TEAMS_COUNT; i++)
{
- if(!m_QueuedGroups[queue_id][BG_QUEUE_PREMADE_ALLIANCE + i].empty())
+ if (!m_QueuedGroups[queue_id][BG_QUEUE_PREMADE_ALLIANCE + i].empty())
{
GroupsQueueType::iterator itr = m_QueuedGroups[queue_id][BG_QUEUE_PREMADE_ALLIANCE + i].begin();
- if(!(*itr)->IsInvitedToBGInstanceGUID && ((*itr)->JoinTime < time_before || (*itr)->Players.size() < MinPlayersPerTeam))
+ if (!(*itr)->IsInvitedToBGInstanceGUID && ((*itr)->JoinTime < time_before || (*itr)->Players.size() < MinPlayersPerTeam))
{
//we must insert group to normal queue and erase pointer from premade queue
m_QueuedGroups[queue_id][BG_QUEUE_NORMAL_ALLIANCE + i].push_front((*itr));
@@ -670,17 +632,17 @@ bool BattleGroundQueue::CheckNormalMatch(BattleGround* bg_template, BGQueueIdBas
itr_team[i] = m_QueuedGroups[queue_id][BG_QUEUE_NORMAL_ALLIANCE + i].begin();
for(; itr_team[i] != m_QueuedGroups[queue_id][BG_QUEUE_NORMAL_ALLIANCE + i].end(); ++(itr_team[i]))
{
- if( !(*(itr_team[i]))->IsInvitedToBGInstanceGUID )
+ if (!(*(itr_team[i]))->IsInvitedToBGInstanceGUID)
{
m_SelectionPools[i].AddGroup(*(itr_team[i]), maxPlayers);
- if( m_SelectionPools[i].GetPlayerCount() >= minPlayers )
+ if (m_SelectionPools[i].GetPlayerCount() >= minPlayers)
break;
}
}
}
//try to invite same number of players - this cycle may cause longer wait time even if there are enough players in queue, but we want ballanced bg
uint32 j = BG_TEAM_ALLIANCE;
- if( m_SelectionPools[BG_TEAM_HORDE].GetPlayerCount() < m_SelectionPools[BG_TEAM_ALLIANCE].GetPlayerCount() )
+ if (m_SelectionPools[BG_TEAM_HORDE].GetPlayerCount() < m_SelectionPools[BG_TEAM_ALLIANCE].GetPlayerCount())
j = BG_TEAM_HORDE;
if( sWorld.getConfig(CONFIG_BATTLEGROUND_INVITATION_TYPE) != 0
&& m_SelectionPools[BG_TEAM_HORDE].GetPlayerCount() >= minPlayers && m_SelectionPools[BG_TEAM_ALLIANCE].GetPlayerCount() >= minPlayers )
@@ -689,16 +651,16 @@ bool BattleGroundQueue::CheckNormalMatch(BattleGround* bg_template, BGQueueIdBas
++(itr_team[j]); //this will not cause a crash, because for cycle above reached break;
for(; itr_team[j] != m_QueuedGroups[queue_id][BG_QUEUE_NORMAL_ALLIANCE + j].end(); ++(itr_team[j]))
{
- if( !(*(itr_team[j]))->IsInvitedToBGInstanceGUID )
- if( !m_SelectionPools[j].AddGroup(*(itr_team[j]), m_SelectionPools[(j + 1) % BG_TEAMS_COUNT].GetPlayerCount()) )
+ if (!(*(itr_team[j]))->IsInvitedToBGInstanceGUID)
+ if (!m_SelectionPools[j].AddGroup(*(itr_team[j]), m_SelectionPools[(j + 1) % BG_TEAMS_COUNT].GetPlayerCount()))
break;
}
// do not allow to start bg with more than 2 players more on 1 faction
- if( abs((int32)(m_SelectionPools[BG_TEAM_HORDE].GetPlayerCount() - m_SelectionPools[BG_TEAM_ALLIANCE].GetPlayerCount())) > 2 )
+ if (abs((int32)(m_SelectionPools[BG_TEAM_HORDE].GetPlayerCount() - m_SelectionPools[BG_TEAM_ALLIANCE].GetPlayerCount())) > 2)
return false;
}
//allow 1v0 if debug bg
- if( sBattleGroundMgr.isTesting() && bg_template->isBattleGround() && (m_SelectionPools[BG_TEAM_ALLIANCE].GetPlayerCount() || m_SelectionPools[BG_TEAM_HORDE].GetPlayerCount()) )
+ if (sBattleGroundMgr.isTesting() && bg_template->isBattleGround() && (m_SelectionPools[BG_TEAM_ALLIANCE].GetPlayerCount() || m_SelectionPools[BG_TEAM_HORDE].GetPlayerCount()))
return true;
//return true if there are enough players in selection pools - enable to work .debug bg command correctly
return m_SelectionPools[BG_TEAM_ALLIANCE].GetPlayerCount() >= minPlayers && m_SelectionPools[BG_TEAM_HORDE].GetPlayerCount() >= minPlayers;
@@ -707,12 +669,12 @@ bool BattleGroundQueue::CheckNormalMatch(BattleGround* bg_template, BGQueueIdBas
// this method will check if we can invite players to same faction skirmish match
bool BattleGroundQueue::CheckSkirmishForSameFaction(BGQueueIdBasedOnLevel queue_id, uint32 minPlayersPerTeam)
{
- if( m_SelectionPools[BG_TEAM_ALLIANCE].GetPlayerCount() < minPlayersPerTeam && m_SelectionPools[BG_TEAM_HORDE].GetPlayerCount() < minPlayersPerTeam )
+ if (m_SelectionPools[BG_TEAM_ALLIANCE].GetPlayerCount() < minPlayersPerTeam && m_SelectionPools[BG_TEAM_HORDE].GetPlayerCount() < minPlayersPerTeam)
return false;
uint32 teamIndex = BG_TEAM_ALLIANCE;
uint32 otherTeam = BG_TEAM_HORDE;
uint32 otherTeamId = HORDE;
- if ( m_SelectionPools[BG_TEAM_HORDE].GetPlayerCount() == minPlayersPerTeam )
+ if (m_SelectionPools[BG_TEAM_HORDE].GetPlayerCount() == minPlayersPerTeam )
{
teamIndex = BG_TEAM_HORDE;
otherTeam = BG_TEAM_ALLIANCE;
@@ -725,9 +687,9 @@ bool BattleGroundQueue::CheckSkirmishForSameFaction(BGQueueIdBasedOnLevel queue_
//set itr_team to group that was added to selection pool latest
GroupsQueueType::iterator itr_team = m_QueuedGroups[queue_id][BG_QUEUE_NORMAL_ALLIANCE + teamIndex].begin();
for(; itr_team != m_QueuedGroups[queue_id][BG_QUEUE_NORMAL_ALLIANCE + teamIndex].end(); ++itr_team)
- if( ginfo == *itr_team )
+ if (ginfo == *itr_team)
break;
- if( itr_team == m_QueuedGroups[queue_id][BG_QUEUE_NORMAL_ALLIANCE + teamIndex].end() )
+ if (itr_team == m_QueuedGroups[queue_id][BG_QUEUE_NORMAL_ALLIANCE + teamIndex].end())
return false;
GroupsQueueType::iterator itr_team2 = itr_team;
++itr_team2;
@@ -735,10 +697,10 @@ bool BattleGroundQueue::CheckSkirmishForSameFaction(BGQueueIdBasedOnLevel queue_
for(; itr_team2 != m_QueuedGroups[queue_id][BG_QUEUE_NORMAL_ALLIANCE + teamIndex].end(); ++itr_team2)
{
//if selection pool is full then break;
- if( !(*itr_team2)->IsInvitedToBGInstanceGUID && !m_SelectionPools[otherTeam].AddGroup(*itr_team2, minPlayersPerTeam) )
+ if (!(*itr_team2)->IsInvitedToBGInstanceGUID && !m_SelectionPools[otherTeam].AddGroup(*itr_team2, minPlayersPerTeam))
break;
}
- if( m_SelectionPools[otherTeam].GetPlayerCount() != minPlayersPerTeam )
+ if (m_SelectionPools[otherTeam].GetPlayerCount() != minPlayersPerTeam)
return false;
//here we have correct 2 selections and we need to change one teams team and move selection pool teams to other team's queue
@@ -753,7 +715,7 @@ bool BattleGroundQueue::CheckSkirmishForSameFaction(BGQueueIdBasedOnLevel queue_
++itr2;
for(; itr2 != m_QueuedGroups[queue_id][BG_QUEUE_NORMAL_ALLIANCE + teamIndex].end(); ++itr2)
{
- if( *itr2 == *itr )
+ if (*itr2 == *itr)
{
m_QueuedGroups[queue_id][BG_QUEUE_NORMAL_ALLIANCE + teamIndex].erase(itr2);
break;
@@ -806,7 +768,7 @@ void BattleGroundQueue::Update(BattleGroundTypeId bgTypeId, BGQueueIdBasedOnLeve
for(GroupsQueueType::const_iterator itr = m_SelectionPools[BG_TEAM_HORDE].SelectedGroups.begin(); itr != m_SelectionPools[BG_TEAM_HORDE].SelectedGroups.end(); ++itr)
InviteGroupToBG((*itr), bg, (*itr)->Team);
- if( !bg->HasFreeSlots() )
+ if (!bg->HasFreeSlots())
{
// remove BG from BGFreeSlotQueue
bg->RemoveFromBGFreeSlotQueue();
@@ -817,7 +779,7 @@ void BattleGroundQueue::Update(BattleGroundTypeId bgTypeId, BGQueueIdBasedOnLeve
// finished iterating through the bgs with free slots, maybe we need to create a new bg
BattleGround * bg_template = sBattleGroundMgr.GetBattleGroundTemplate(bgTypeId);
- if( !bg_template )
+ if (!bg_template)
{
sLog.outError("Battleground: Update: bg template not found for %u", bgTypeId);
return;
@@ -825,11 +787,11 @@ void BattleGroundQueue::Update(BattleGroundTypeId bgTypeId, BGQueueIdBasedOnLeve
// get the min. players per team, properly for larger arenas as well. (must have full teams for arena matches!)
uint32 MinPlayersPerTeam = bg_template->GetMinPlayersPerTeam();
uint32 MaxPlayersPerTeam = bg_template->GetMaxPlayersPerTeam();
- if( sBattleGroundMgr.isTesting() )
+ if (sBattleGroundMgr.isTesting())
MinPlayersPerTeam = 1;
- if( bg_template->isArena() )
+ if (bg_template->isArena())
{
- if( sBattleGroundMgr.isArenaTesting() )
+ if (sBattleGroundMgr.isArenaTesting())
{
MaxPlayersPerTeam = 1;
MinPlayersPerTeam = 1;
@@ -860,14 +822,14 @@ void BattleGroundQueue::Update(BattleGroundTypeId bgTypeId, BGQueueIdBasedOnLeve
m_SelectionPools[BG_TEAM_ALLIANCE].Init();
m_SelectionPools[BG_TEAM_HORDE].Init();
- if( bg_template->isBattleGround() )
+ if (bg_template->isBattleGround())
{
//check if there is premade against premade match
- if( CheckPremadeMatch(queue_id, MinPlayersPerTeam, MaxPlayersPerTeam) )
+ if (CheckPremadeMatch(queue_id, MinPlayersPerTeam, MaxPlayersPerTeam))
{
//create new battleground
BattleGround * bg2 = NULL;
- if( !(bg2 = sBattleGroundMgr.CreateNewBattleGround(bgTypeId, queue_id, 0, false)) )
+ if (!(bg2 = sBattleGroundMgr.CreateNewBattleGround(bgTypeId, queue_id, 0, false)))
{
sLog.outError("BattleGroundQueue::Update - Cannot create battleground: %u", bgTypeId);
return;
@@ -885,15 +847,15 @@ void BattleGroundQueue::Update(BattleGroundTypeId bgTypeId, BGQueueIdBasedOnLeve
}
// now check if there are in queues enough players to start new game of (normal battleground, or non-rated arena)
- if( !isRated )
+ if (!isRated)
{
// if there are enough players in pools, start new battleground or non rated arena
- if( CheckNormalMatch(bg_template, queue_id, MinPlayersPerTeam, MaxPlayersPerTeam)
+ if (CheckNormalMatch(bg_template, queue_id, MinPlayersPerTeam, MaxPlayersPerTeam)
|| (bg_template->isArena() && CheckSkirmishForSameFaction(queue_id, MinPlayersPerTeam)) )
{
// we successfully created a pool
BattleGround * bg2 = NULL;
- if( !(bg2 = sBattleGroundMgr.CreateNewBattleGround(bgTypeId, queue_id, arenaType, false)) )
+ if (!(bg2 = sBattleGroundMgr.CreateNewBattleGround(bgTypeId, queue_id, arenaType, false)))
{
sLog.outError("BattleGroundQueue::Update - Cannot create battleground: %u", bgTypeId);
return;
@@ -907,31 +869,31 @@ void BattleGroundQueue::Update(BattleGroundTypeId bgTypeId, BGQueueIdBasedOnLeve
bg2->StartBattleGround();
}
}
- else if( bg_template->isArena() )
+ else if (bg_template->isArena())
{
// found out the minimum and maximum ratings the newly added team should battle against
// arenaRating is the rating of the latest joined team, or 0
// 0 is on (automatic update call) and we must set it to team's with longest wait time
- if ( !arenaRating )
+ if (!arenaRating )
{
GroupQueueInfo* front1 = NULL;
GroupQueueInfo* front2 = NULL;
- if( !m_QueuedGroups[queue_id][BG_QUEUE_PREMADE_ALLIANCE].empty() )
+ if (!m_QueuedGroups[queue_id][BG_QUEUE_PREMADE_ALLIANCE].empty())
{
front1 = m_QueuedGroups[queue_id][BG_QUEUE_PREMADE_ALLIANCE].front();
arenaRating = front1->ArenaTeamRating;
}
- if( !m_QueuedGroups[queue_id][BG_QUEUE_PREMADE_HORDE].empty() )
+ if (!m_QueuedGroups[queue_id][BG_QUEUE_PREMADE_HORDE].empty())
{
front2 = m_QueuedGroups[queue_id][BG_QUEUE_PREMADE_HORDE].front();
arenaRating = front2->ArenaTeamRating;
}
- if( front1 && front2 )
+ if (front1 && front2)
{
- if( front1->JoinTime < front2->JoinTime )
+ if (front1->JoinTime < front2->JoinTime)
arenaRating = front1->ArenaTeamRating;
}
- else if( !front1 && !front2 )
+ else if (!front1 && !front2)
return; //queues are empty
}
@@ -971,7 +933,7 @@ void BattleGroundQueue::Update(BattleGroundTypeId bgTypeId, BGQueueIdBasedOnLeve
// if we don't have, we must try to continue search in same queue
// tmp variables are correctly set
// this code isn't much userfriendly - but it is supposed to continue search for mathing group in HORDE queue
- if( m_SelectionPools[BG_TEAM_ALLIANCE].GetPlayerCount() == 0 && m_SelectionPools[BG_TEAM_HORDE].GetPlayerCount() )
+ if (m_SelectionPools[BG_TEAM_ALLIANCE].GetPlayerCount() == 0 && m_SelectionPools[BG_TEAM_HORDE].GetPlayerCount())
{
itr_team[BG_TEAM_ALLIANCE] = itr_team[BG_TEAM_HORDE];
++itr_team[BG_TEAM_ALLIANCE];
@@ -987,7 +949,7 @@ void BattleGroundQueue::Update(BattleGroundTypeId bgTypeId, BGQueueIdBasedOnLeve
}
}
// this code isn't much userfriendly - but it is supposed to continue search for mathing group in ALLIANCE queue
- if( m_SelectionPools[BG_TEAM_HORDE].GetPlayerCount() == 0 && m_SelectionPools[BG_TEAM_ALLIANCE].GetPlayerCount() )
+ if (m_SelectionPools[BG_TEAM_HORDE].GetPlayerCount() == 0 && m_SelectionPools[BG_TEAM_ALLIANCE].GetPlayerCount())
{
itr_team[BG_TEAM_HORDE] = itr_team[BG_TEAM_ALLIANCE];
++itr_team[BG_TEAM_HORDE];
@@ -1004,10 +966,10 @@ void BattleGroundQueue::Update(BattleGroundTypeId bgTypeId, BGQueueIdBasedOnLeve
}
//if we have 2 teams, then start new arena and invite players!
- if( m_SelectionPools[BG_TEAM_ALLIANCE].GetPlayerCount() && m_SelectionPools[BG_TEAM_HORDE].GetPlayerCount() )
+ if (m_SelectionPools[BG_TEAM_ALLIANCE].GetPlayerCount() && m_SelectionPools[BG_TEAM_HORDE].GetPlayerCount())
{
BattleGround* arena = NULL;
- if( !(arena = sBattleGroundMgr.CreateNewBattleGround(bgTypeId, queue_id, arenaType, true)) )
+ if (!(arena = sBattleGroundMgr.CreateNewBattleGround(bgTypeId, queue_id, arenaType, true)))
{
sLog.outError("BattlegroundQueue::Update couldn't create arena instance for rated arena match!");
return;
@@ -1018,7 +980,7 @@ void BattleGroundQueue::Update(BattleGroundTypeId bgTypeId, BGQueueIdBasedOnLeve
(*(itr_team[BG_TEAM_HORDE]))->OpponentsTeamRating = (*(itr_team[BG_TEAM_ALLIANCE]))->ArenaTeamRating;
sLog.outDebug("setting oposite teamrating for team %u to %u", (*(itr_team[BG_TEAM_HORDE]))->ArenaTeamId, (*(itr_team[BG_TEAM_HORDE]))->OpponentsTeamRating);
// now we must move team if we changed its faction to another faction queue, because then we will spam log by errors in Queue::RemovePlayer
- if( (*(itr_team[BG_TEAM_ALLIANCE]))->Team != ALLIANCE )
+ if ((*(itr_team[BG_TEAM_ALLIANCE]))->Team != ALLIANCE)
{
// add to alliance queue
m_QueuedGroups[queue_id][BG_QUEUE_PREMADE_ALLIANCE].push_front(*(itr_team[BG_TEAM_ALLIANCE]));
@@ -1026,7 +988,7 @@ void BattleGroundQueue::Update(BattleGroundTypeId bgTypeId, BGQueueIdBasedOnLeve
m_QueuedGroups[queue_id][BG_QUEUE_PREMADE_HORDE].erase(itr_team[BG_TEAM_ALLIANCE]);
itr_team[BG_TEAM_ALLIANCE] = m_QueuedGroups[queue_id][BG_QUEUE_PREMADE_ALLIANCE].begin();
}
- if( (*(itr_team[BG_TEAM_HORDE]))->Team != HORDE )
+ if ((*(itr_team[BG_TEAM_HORDE]))->Team != HORDE)
{
m_QueuedGroups[queue_id][BG_QUEUE_PREMADE_HORDE].push_front(*(itr_team[BG_TEAM_HORDE]));
m_QueuedGroups[queue_id][BG_QUEUE_PREMADE_ALLIANCE].erase(itr_team[BG_TEAM_HORDE]);
@@ -1050,28 +1012,27 @@ void BattleGroundQueue::Update(BattleGroundTypeId bgTypeId, BGQueueIdBasedOnLeve
bool BGQueueInviteEvent::Execute(uint64 /*e_time*/, uint32 /*p_time*/)
{
Player* plr = objmgr.GetPlayer( m_PlayerGuid );
-
// player logged off (we should do nothing, he is correctly removed from queue in another procedure)
if (!plr)
return true;
- // Player can be in another BG queue and must be removed in normal way in any case
-
BattleGround* bg = sBattleGroundMgr.GetBattleGround(m_BgInstanceGUID, m_BgTypeId);
+ //if battleground ended and its instance deleted - do nothing
if (!bg)
return true;
BattleGroundQueueTypeId bgQueueTypeId = BattleGroundMgr::BGQueueTypeId(bg->GetTypeID(), bg->GetArenaType());
uint32 queueSlot = plr->GetBattleGroundQueueIndex(bgQueueTypeId);
- if (queueSlot < PLAYER_MAX_BATTLEGROUND_QUEUES) // player is in queue
+ if( queueSlot < PLAYER_MAX_BATTLEGROUND_QUEUES ) // player is in queue or in battleground
{
- // check if player is invited to this bg ... this check must be here, because when player leaves queue and joins another, it would cause a problems
+ // check if player is invited to this bg
BattleGroundQueue::QueuedPlayersMap const& qpMap = sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].m_QueuedPlayers;
BattleGroundQueue::QueuedPlayersMap::const_iterator qItr = qpMap.find(m_PlayerGuid);
- if (qItr != qpMap.end() && qItr->second.GroupInfo->IsInvitedToBGInstanceGUID == m_BgInstanceGUID)
+ if( qItr != qpMap.end() && qItr->second.GroupInfo->IsInvitedToBGInstanceGUID == m_BgInstanceGUID
+ && qItr->second.GroupInfo->RemoveInviteTime == m_RemoveTime )
{
WorldPacket data;
- //here must be remaining time
+ //we must send remaining time in queue
sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, bg, queueSlot, STATUS_WAIT_JOIN, INVITE_ACCEPT_WAIT_TIME - INVITATION_REMIND_TIME, 0, qItr->second.GroupInfo->ArenaType);
plr->GetSession()->SendPacket(&data);
}
@@ -1081,10 +1042,18 @@ bool BGQueueInviteEvent::Execute(uint64 /*e_time*/, uint32 /*p_time*/)
void BGQueueInviteEvent::Abort(uint64 /*e_time*/)
{
- //this should not be called
- sLog.outError("Battleground invite event ABORTED!");
+ //do nothing
}
+/*
+ this event has many possibilities when it is executed:
+ 1. player is in battleground ( he clicked enter on invitation window )
+ 2. player left battleground queue and he isn't there any more
+ 3. player left battleground queue and he joined it again and IsInvitedToBGInstanceGUID = 0
+ 4. player left queue and he joined again and he has been invited to same battleground again -> we should not remove him from queue yet
+ 5. player is invited to bg and he didn't choose what to do and timer expired - only in this condition we should call queue::RemovePlayer
+ we must remove player in the 5. case even if battleground object doesn't exist!
+*/
bool BGQueueRemoveEvent::Execute(uint64 /*e_time*/, uint32 /*p_time*/)
{
Player* plr = objmgr.GetPlayer( m_PlayerGuid );
@@ -1093,30 +1062,32 @@ bool BGQueueRemoveEvent::Execute(uint64 /*e_time*/, uint32 /*p_time*/)
return true;
BattleGround* bg = sBattleGroundMgr.GetBattleGround(m_BgInstanceGUID, m_BgTypeId);
- if (!bg)
- return true;
-
- sLog.outDebug("Battleground: removing player %u from bg queue for instance %u because of not pressing enter battle in time.",plr->GetGUIDLow(),m_BgInstanceGUID);
+ //battleground can be deleted already when we are removing queue info
+ //bg pointer can be NULL! so use it carefully!
- BattleGroundQueueTypeId bgQueueTypeId = BattleGroundMgr::BGQueueTypeId(bg->GetTypeID(), bg->GetArenaType());
- uint32 queueSlot = plr->GetBattleGroundQueueIndex(bgQueueTypeId);
- if (queueSlot < PLAYER_MAX_BATTLEGROUND_QUEUES) // player is in queue
+ uint32 queueSlot = plr->GetBattleGroundQueueIndex(m_BgQueueTypeId);
+ if( queueSlot < PLAYER_MAX_BATTLEGROUND_QUEUES ) // player is in queue, or in Battleground
{
- // check if player is invited to this bg ... this check must be here, because when player leaves queue and joins another, it would cause a problems
- BattleGroundQueue::QueuedPlayersMap& qpMap = sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].m_QueuedPlayers;
+ // check if player is in queue for this BG and if we are removing his invite event
+ BattleGroundQueue::QueuedPlayersMap& qpMap = sBattleGroundMgr.m_BattleGroundQueues[m_BgQueueTypeId].m_QueuedPlayers;
BattleGroundQueue::QueuedPlayersMap::iterator qMapItr = qpMap.find(m_PlayerGuid);
- if (qMapItr != qpMap.end() && qMapItr->second.GroupInfo && qMapItr->second.GroupInfo->IsInvitedToBGInstanceGUID == m_BgInstanceGUID)
+ if( qMapItr != qpMap.end() && qMapItr->second.GroupInfo
+ && qMapItr->second.GroupInfo->IsInvitedToBGInstanceGUID == m_BgInstanceGUID
+ && qMapItr->second.GroupInfo->RemoveInviteTime == m_RemoveTime )
{
- plr->RemoveBattleGroundQueueId(bgQueueTypeId);
- sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].RemovePlayer(m_PlayerGuid, true);
- sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].Update(bg->GetTypeID(), bg->GetQueueId());
+ sLog.outDebug("Battleground: removing player %u from bg queue for instance %u because of not pressing enter battle in time.",plr->GetGUIDLow(),m_BgInstanceGUID);
+
+ plr->RemoveBattleGroundQueueId(m_BgQueueTypeId);
+ sBattleGroundMgr.m_BattleGroundQueues[m_BgQueueTypeId].RemovePlayer(m_PlayerGuid, true);
+ //update queues if battleground isn't ended
+ if (bg)
+ sBattleGroundMgr.m_BattleGroundQueues[m_BgQueueTypeId].Update(m_BgTypeId, bg->GetQueueId());
+
WorldPacket data;
sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, bg, queueSlot, STATUS_NONE, 0, 0, 0);
plr->GetSession()->SendPacket(&data);
}
}
- else
- sLog.outDebug("Battleground: Player was already removed from queue");
//event will be deleted
return true;
@@ -1124,8 +1095,7 @@ bool BGQueueRemoveEvent::Execute(uint64 /*e_time*/, uint32 /*p_time*/)
void BGQueueRemoveEvent::Abort(uint64 /*e_time*/)
{
- //this should not be called
- sLog.outError("Battleground remove event ABORTED!");
+ //do nothing
}
/*********************************************************/
@@ -1153,7 +1123,7 @@ void BattleGroundMgr::DeleteAllBattleGrounds()
{
BattleGround * bg = itr->second;
m_BattleGrounds[i].erase(itr++);
- if(!m_ClientBattleGroundIds[i][bg->GetQueueId()].empty())
+ if (!m_ClientBattleGroundIds[i][bg->GetQueueId()].empty())
m_ClientBattleGroundIds[i][bg->GetQueueId()].erase(bg->GetClientInstanceID());
delete bg;
}
@@ -1176,7 +1146,7 @@ void BattleGroundMgr::Update(uint32 diff)
{
itr = m_BattleGrounds[i].begin();
// skip updating battleground template
- if( itr != m_BattleGrounds[i].end() )
+ if (itr != m_BattleGrounds[i].end())
++itr;
for(; itr != m_BattleGrounds[i].end(); itr = next)
{
@@ -1185,21 +1155,21 @@ void BattleGroundMgr::Update(uint32 diff)
itr->second->Update(diff);
// use the SetDeleteThis variable
// direct deletion caused crashes
- if(itr->second->m_SetDeleteThis)
+ if (itr->second->m_SetDeleteThis)
{
BattleGround * bg = itr->second;
m_BattleGrounds[i].erase(itr);
- if(!m_ClientBattleGroundIds[i][bg->GetQueueId()].empty())
+ if (!m_ClientBattleGroundIds[i][bg->GetQueueId()].empty())
m_ClientBattleGroundIds[i][bg->GetQueueId()].erase(bg->GetClientInstanceID());
delete bg;
}
}
}
// if rating difference counts, maybe force-update queues
- if(sWorld.getConfig(CONFIG_ARENA_MAX_RATING_DIFFERENCE) && sWorld.getConfig(CONFIG_ARENA_RATING_DISCARD_TIMER))
+ if (sWorld.getConfig(CONFIG_ARENA_MAX_RATING_DIFFERENCE) && sWorld.getConfig(CONFIG_ARENA_RATING_DISCARD_TIMER))
{
// it's time to force update
- if(m_NextRatingDiscardUpdate < diff)
+ if (m_NextRatingDiscardUpdate < diff)
{
// forced update for level 70 rated arenas
sLog.outDebug("BattleGroundMgr: UPDATING ARENA QUEUES");
@@ -1214,9 +1184,9 @@ void BattleGroundMgr::Update(uint32 diff)
else
m_NextRatingDiscardUpdate -= diff;
}
- if(sWorld.getConfig(CONFIG_ARENA_AUTO_DISTRIBUTE_POINTS))
+ if (sWorld.getConfig(CONFIG_ARENA_AUTO_DISTRIBUTE_POINTS))
{
- if(m_AutoDistributionTimeChecker < diff)
+ if (m_AutoDistributionTimeChecker < diff)
{
if(time(NULL) > m_NextAutoDistributionTime)
{
@@ -1234,7 +1204,8 @@ void BattleGroundMgr::Update(uint32 diff)
void BattleGroundMgr::BuildBattleGroundStatusPacket(WorldPacket *data, BattleGround *bg, uint8 QueueSlot, uint8 StatusID, uint32 Time1, uint32 Time2, uint8 arenatype)
{
// we can be in 3 queues in same time...
- if(StatusID == 0)
+
+ if (StatusID == 0 || !bg)
{
data->Initialize(SMSG_BATTLEFIELD_STATUS, 4*3);
*data << uint32(QueueSlot); // queue id (0...2)
@@ -1291,7 +1262,7 @@ void BattleGroundMgr::BuildBattleGroundStatusPacket(WorldPacket *data, BattleGro
break;
}
- if(bg->isArena() && (StatusID == STATUS_WAIT_QUEUE))
+ if (bg->isArena() && (StatusID == STATUS_WAIT_QUEUE))
*data << uint32(BATTLEGROUND_AA); // all arenas I don't think so.
else
*data << uint32(bg->GetTypeID()); // BG id from DBC
@@ -1344,14 +1315,14 @@ void BattleGroundMgr::BuildPvpLogDataPacket(WorldPacket *data, BattleGround *bg)
{
uint32 at_id = bg->m_ArenaTeamIds[i];
ArenaTeam * at = objmgr.GetArenaTeamById(at_id);
- if(at)
+ if (at)
*data << at->GetName();
else
*data << (uint8)0;
}
}
- if(bg->GetStatus() != STATUS_WAIT_LEAVE)
+ if (bg->GetStatus() != STATUS_WAIT_LEAVE)
{
*data << uint8(0); // bg not ended
}
@@ -1367,7 +1338,7 @@ void BattleGroundMgr::BuildPvpLogDataPacket(WorldPacket *data, BattleGround *bg)
{
*data << (uint64)itr->first;
*data << (int32)itr->second->KillingBlows;
- if(type == 0)
+ if (type == 0)
{
*data << (int32)itr->second->HonorableKills;
*data << (int32)itr->second->Deaths;
@@ -1377,9 +1348,9 @@ void BattleGroundMgr::BuildPvpLogDataPacket(WorldPacket *data, BattleGround *bg)
{
Player *plr = objmgr.GetPlayer(itr->first);
uint32 team = bg->GetPlayerTeam(itr->first);
- if(!team && plr)
+ if (!team && plr)
team = plr->GetTeam();
- if( ( bg->GetWinner()==0 && team == ALLIANCE ) || ( bg->GetWinner()==1 && team==HORDE ) )
+ if (( bg->GetWinner()==0 && team == ALLIANCE ) || ( bg->GetWinner()==1 && team==HORDE ))
*data << uint8(1);
else
*data << uint8(0);
@@ -1467,57 +1438,20 @@ void BattleGroundMgr::BuildPlayerJoinedBattleGroundPacket(WorldPacket *data, Pla
*data << uint64(plr->GetGUID());
}
-void BattleGroundMgr::InvitePlayer(Player* plr, uint32 bgInstanceGUID, BattleGroundTypeId bgTypeId, uint32 team)
-{
- // set invited player counters:
- BattleGround* bg = GetBattleGround(bgInstanceGUID, bgTypeId);
- if(!bg)
- return;
- bg->IncreaseInvitedCount(team);
-
- plr->SetInviteForBattleGroundQueueType(BGQueueTypeId(bg->GetTypeID(),bg->GetArenaType()), bgInstanceGUID);
-
- // set the arena teams for rated matches
- if(bg->isArena() && bg->isRated())
- {
- switch(bg->GetArenaType())
- {
- case ARENA_TYPE_2v2:
- bg->SetArenaTeamIdForTeam(team, plr->GetArenaTeamId(0));
- break;
- case ARENA_TYPE_3v3:
- bg->SetArenaTeamIdForTeam(team, plr->GetArenaTeamId(1));
- break;
- case ARENA_TYPE_5v5:
- bg->SetArenaTeamIdForTeam(team, plr->GetArenaTeamId(2));
- break;
- default:
- break;
- }
- }
-
- // create invite events:
- //add events to player's counters ---- this is not good way - there should be something like global event processor, where we should add those events
- BGQueueInviteEvent* inviteEvent = new BGQueueInviteEvent(plr->GetGUID(), bgInstanceGUID, bgTypeId);
- plr->m_Events.AddEvent(inviteEvent, plr->m_Events.CalculateTime(INVITATION_REMIND_TIME));
- BGQueueRemoveEvent* removeEvent = new BGQueueRemoveEvent(plr->GetGUID(), bgInstanceGUID, bgTypeId, team);
- plr->m_Events.AddEvent(removeEvent, plr->m_Events.CalculateTime(INVITE_ACCEPT_WAIT_TIME));
-}
-
BattleGround * BattleGroundMgr::GetBattleGroundThroughClientInstance(uint32 instanceId, BattleGroundTypeId bgTypeId, BGQueueIdBasedOnLevel queue_id)
{
//cause at HandleBattleGroundJoinOpcode the clients sends the instanceid he gets from
//SMSG_BATTLEFIELD_LIST we need to find the battleground with this clientinstance-id
BattleGround* bg = GetBattleGroundTemplate(bgTypeId);
- if( !bg )
+ if (!bg)
return NULL;
- if(bg->isArena())
+ if (bg->isArena())
return GetBattleGround(instanceId, bgTypeId);
for(BattleGroundSet::iterator itr = m_BattleGrounds[bgTypeId].begin(); itr != m_BattleGrounds[bgTypeId].end(); ++itr)
{
- if(itr->second->GetClientInstanceID() == instanceId)
+ if (itr->second->GetClientInstanceID() == instanceId)
return itr->second;
}
return NULL;
@@ -1527,12 +1461,12 @@ BattleGround * BattleGroundMgr::GetBattleGround(uint32 InstanceID, BattleGroundT
{
//search if needed
BattleGroundSet::iterator itr;
- if( bgTypeId == BATTLEGROUND_TYPE_NONE)
+ if (bgTypeId == BATTLEGROUND_TYPE_NONE)
{
for(uint32 i = BATTLEGROUND_AV; i < MAX_BATTLEGROUND_TYPE_ID; i++)
{
itr = m_BattleGrounds[i].find(InstanceID);
- if( itr != m_BattleGrounds[i].end() )
+ if (itr != m_BattleGrounds[i].end())
return itr->second;
}
return NULL;
@@ -1549,7 +1483,7 @@ BattleGround * BattleGroundMgr::GetBattleGroundTemplate(BattleGroundTypeId bgTyp
uint32 BattleGroundMgr::CreateClientVisibleInstanceId(BattleGroundTypeId bgTypeId, BGQueueIdBasedOnLevel queue_id)
{
- if( IsArenaType(bgTypeId) )
+ if (IsArenaType(bgTypeId))
return 0; //arenas don't have client-instanceids
// we create here an instanceid, which is just for
@@ -1574,20 +1508,20 @@ BattleGround * BattleGroundMgr::CreateNewBattleGround(BattleGroundTypeId bgTypeI
{
// get the template BG
BattleGround *bg_template = GetBattleGroundTemplate(bgTypeId);
- if(!bg_template)
+ if (!bg_template)
{
sLog.outError("BattleGround: CreateNewBattleGround - bg template not found for %u", bgTypeId);
return NULL;
}
//for arenas there is random map used
- if(bg_template->isArena())
+ if (bg_template->isArena())
{
BattleGroundTypeId arenas[] = {BATTLEGROUND_NA, BATTLEGROUND_BE, BATTLEGROUND_RL};
uint32 arena_num = urand(0,2);
bgTypeId = arenas[arena_num];
bg_template = GetBattleGroundTemplate(bgTypeId);
- if(!bg_template)
+ if (!bg_template)
{
sLog.outError("BattleGround: CreateNewBattleGround - bg template not found for %u", bgTypeId);
return NULL;
@@ -1713,7 +1647,7 @@ void BattleGroundMgr::CreateInitialBattleGrounds()
// 0 1 2 3 4 5 6 7 8
QueryResult *result = WorldDatabase.Query("SELECT id, MinPlayersPerTeam,MaxPlayersPerTeam,MinLvl,MaxLvl,AllianceStartLoc,AllianceStartO,HordeStartLoc,HordeStartO FROM battleground_template");
- if(!result)
+ if (!result)
{
barGoLink bar(1);
@@ -1735,7 +1669,7 @@ void BattleGroundMgr::CreateInitialBattleGrounds()
// can be overwrite by values from DB
bl = sBattlemasterListStore.LookupEntry(bgTypeID_);
- if(!bl)
+ if (!bl)
{
sLog.outError("Battleground ID %u not found in BattlemasterList.dbc. Battleground not created.", bgTypeID_);
continue;
@@ -1749,12 +1683,12 @@ void BattleGroundMgr::CreateInitialBattleGrounds()
MinLvl = fields[3].GetUInt32();
MaxLvl = fields[4].GetUInt32();
//check values from DB
- if( MaxPlayersPerTeam == 0 || MinPlayersPerTeam == 0 || MinPlayersPerTeam > MaxPlayersPerTeam )
+ if (MaxPlayersPerTeam == 0 || MinPlayersPerTeam == 0 || MinPlayersPerTeam > MaxPlayersPerTeam)
{
MaxPlayersPerTeam = bl->maxplayersperteam;
MinPlayersPerTeam = bl->maxplayersperteam / 2;
}
- if( MinLvl == 0 || MaxLvl == 0 || MinLvl > MaxLvl )
+ if (MinLvl == 0 || MaxLvl == 0 || MinLvl > MaxLvl)
{
MinLvl = bl->minlvl;
MaxLvl = bl->maxlvl;
@@ -1763,14 +1697,14 @@ void BattleGroundMgr::CreateInitialBattleGrounds()
start1 = fields[5].GetUInt32();
start = sWorldSafeLocsStore.LookupEntry(start1);
- if(start)
+ if (start)
{
AStartLoc[0] = start->x;
AStartLoc[1] = start->y;
AStartLoc[2] = start->z;
AStartLoc[3] = fields[6].GetFloat();
}
- else if(bgTypeID == BATTLEGROUND_AA)
+ else if (bgTypeID == BATTLEGROUND_AA)
{
AStartLoc[0] = 0;
AStartLoc[1] = 0;
@@ -1786,14 +1720,14 @@ void BattleGroundMgr::CreateInitialBattleGrounds()
start2 = fields[7].GetUInt32();
start = sWorldSafeLocsStore.LookupEntry(start2);
- if(start)
+ if (start)
{
HStartLoc[0] = start->x;
HStartLoc[1] = start->y;
HStartLoc[2] = start->z;
HStartLoc[3] = fields[8].GetFloat();
}
- else if(bgTypeID == BATTLEGROUND_AA)
+ else if (bgTypeID == BATTLEGROUND_AA)
{
HStartLoc[0] = 0;
HStartLoc[1] = 0;
@@ -1807,7 +1741,7 @@ void BattleGroundMgr::CreateInitialBattleGrounds()
}
//sLog.outDetail("Creating battleground %s, %u-%u", bl->name[sWorld.GetDBClang()], MinLvl, MaxLvl);
- if(!CreateBattleGround(bgTypeID, IsArena, MinPlayersPerTeam, MaxPlayersPerTeam, MinLvl, MaxLvl, bl->name[sWorld.GetDefaultDbcLocale()], bl->mapid[0], AStartLoc[0], AStartLoc[1], AStartLoc[2], AStartLoc[3], HStartLoc[0], HStartLoc[1], HStartLoc[2], HStartLoc[3]))
+ if (!CreateBattleGround(bgTypeID, IsArena, MinPlayersPerTeam, MaxPlayersPerTeam, MinLvl, MaxLvl, bl->name[sWorld.GetDefaultDbcLocale()], bl->mapid[0], AStartLoc[0], AStartLoc[1], AStartLoc[2], AStartLoc[3], HStartLoc[0], HStartLoc[1], HStartLoc[2], HStartLoc[3]))
continue;
++count;
@@ -1821,11 +1755,11 @@ void BattleGroundMgr::CreateInitialBattleGrounds()
void BattleGroundMgr::InitAutomaticArenaPointDistribution()
{
- if(sWorld.getConfig(CONFIG_ARENA_AUTO_DISTRIBUTE_POINTS))
+ if (sWorld.getConfig(CONFIG_ARENA_AUTO_DISTRIBUTE_POINTS))
{
sLog.outDebug("Initializing Automatic Arena Point Distribution");
QueryResult * result = CharacterDatabase.Query("SELECT NextArenaPointDistributionTime FROM saved_variables");
- if(!result)
+ if (!result)
{
sLog.outDebug("Battleground: Next arena point distribution time not found in SavedVariables, reseting it now.");
m_NextAutoDistributionTime = time(NULL) + BATTLEGROUND_ARENA_POINT_DISTRIBUTION_DAY * sWorld.getConfig(CONFIG_ARENA_AUTO_DISTRIBUTE_INTERVAL_DAYS);
@@ -1853,7 +1787,7 @@ void BattleGroundMgr::DistributeArenaPoints()
//at first update all points for all team members
for(ObjectMgr::ArenaTeamMap::iterator team_itr = objmgr.GetArenaTeamMapBegin(); team_itr != objmgr.GetArenaTeamMapEnd(); ++team_itr)
{
- if(ArenaTeam * at = team_itr->second)
+ if (ArenaTeam * at = team_itr->second)
{
at->UpdateArenaPointsHelper(PlayerPoints);
}
@@ -1877,7 +1811,7 @@ void BattleGroundMgr::DistributeArenaPoints()
sWorld.SendWorldText(LANG_DIST_ARENA_POINTS_TEAM_START);
for(ObjectMgr::ArenaTeamMap::iterator titr = objmgr.GetArenaTeamMapBegin(); titr != objmgr.GetArenaTeamMapEnd(); ++titr)
{
- if(ArenaTeam * at = titr->second)
+ if (ArenaTeam * at = titr->second)
{
at->FinishWeek(); // set played this week etc values to 0 in memory, too
at->SaveToDB(); // save changes
@@ -1894,7 +1828,7 @@ void BattleGroundMgr::BuildBattleGroundListPacket(WorldPacket *data, const uint6
{
uint32 PlayerLevel = 10;
- if(plr)
+ if (plr)
PlayerLevel = plr->getLevel();
data->Initialize(SMSG_BATTLEFIELD_LIST);
@@ -1926,12 +1860,12 @@ void BattleGroundMgr::BuildBattleGroundListPacket(WorldPacket *data, const uint6
void BattleGroundMgr::SendToBattleGround(Player *pl, uint32 instanceId, BattleGroundTypeId bgTypeId)
{
BattleGround *bg = GetBattleGround(instanceId, bgTypeId);
- if(bg)
+ if (bg)
{
uint32 mapid = bg->GetMapId();
float x, y, z, O;
uint32 team = pl->GetBGTeam();
- if(team==0)
+ if (team==0)
team = pl->GetTeam();
bg->GetTeamStartLoc(team, x, y, z, O);
@@ -1948,7 +1882,7 @@ void BattleGroundMgr::SendAreaSpiritHealerQueryOpcode(Player *pl, BattleGround *
{
WorldPacket data(SMSG_AREA_SPIRIT_HEALER_TIME, 12);
uint32 time_ = 30000 - bg->GetLastResurrectTime(); // resurrect every 30 seconds
- if(time_ == uint32(-1))
+ if (time_ == uint32(-1))
time_ = 0;
data << guid << time_;
pl->GetSession()->SendPacket(&data);
@@ -2039,7 +1973,7 @@ uint8 BattleGroundMgr::BGArenaType(BattleGroundQueueTypeId bgQueueTypeId)
void BattleGroundMgr::ToggleTesting()
{
m_Testing = !m_Testing;
- if(m_Testing)
+ if (m_Testing)
sWorld.SendWorldText(LANG_DEBUG_BG_ON);
else
sWorld.SendWorldText(LANG_DEBUG_BG_OFF);
@@ -2048,7 +1982,7 @@ void BattleGroundMgr::ToggleTesting()
void BattleGroundMgr::ToggleArenaTesting()
{
m_ArenaTesting = !m_ArenaTesting;
- if(m_ArenaTesting)
+ if (m_ArenaTesting)
sWorld.SendWorldText(LANG_DEBUG_ARENA_ON);
else
sWorld.SendWorldText(LANG_DEBUG_ARENA_OFF);
@@ -2092,7 +2026,7 @@ void BattleGroundMgr::LoadBattleMastersEntry()
uint32 count = 0;
- if( !result )
+ if (!result)
{
barGoLink bar( 1 );
bar.step();
diff --git a/src/game/BattleGroundMgr.h b/src/game/BattleGroundMgr.h
index e43b6e0e4a1..889b8b6f4fe 100644
--- a/src/game/BattleGroundMgr.h
+++ b/src/game/BattleGroundMgr.h
@@ -86,7 +86,6 @@ class BattleGroundQueue
uint32 GetAverageQueueWaitTime(GroupQueueInfo* ginfo, BGQueueIdBasedOnLevel queue_id);
void DecreaseGroupLength(uint32 queueId, uint32 AsGroup);
- void BGEndedRemoveInvites(BattleGround * bg);
void AnnounceWorld(GroupQueueInfo *ginfo, const uint64& playerGUID, bool isAddedToQueue);
typedef std::map<uint64, PlayerQueueInfo> QueuedPlayersMap;
@@ -138,8 +137,8 @@ class BattleGroundQueue
class BGQueueInviteEvent : public BasicEvent
{
public:
- BGQueueInviteEvent(const uint64& pl_guid, uint32 BgInstanceGUID, BattleGroundTypeId BgTypeId) :
- m_PlayerGuid(pl_guid), m_BgInstanceGUID(BgInstanceGUID), m_BgTypeId(BgTypeId)
+ BGQueueInviteEvent(const uint64& pl_guid, uint32 BgInstanceGUID, BattleGroundTypeId BgTypeId, uint32 removeTime) :
+ m_PlayerGuid(pl_guid), m_BgInstanceGUID(BgInstanceGUID), m_BgTypeId(BgTypeId), m_RemoveTime(removeTime)
{
};
virtual ~BGQueueInviteEvent() {};
@@ -149,17 +148,20 @@ class BGQueueInviteEvent : public BasicEvent
private:
uint64 m_PlayerGuid;
uint32 m_BgInstanceGUID;
+ uint32 m_RemoveTime;
BattleGroundTypeId m_BgTypeId;
};
/*
- This class is used to remove player from BG queue after 2 minutes from first invitation
+ This class is used to remove player from BG queue after 1 minute 20 seconds from first invitation
+ We must store removeInvite time in case player left queue and joined and is invited again
+ We must store bgQueueTypeId, because battleground can be deleted already, when player entered it
*/
class BGQueueRemoveEvent : public BasicEvent
{
public:
- BGQueueRemoveEvent(const uint64& pl_guid, uint32 bgInstanceGUID, BattleGroundTypeId BgTypeId, uint32 playersTeam) :
- m_PlayerGuid(pl_guid), m_BgInstanceGUID(bgInstanceGUID), m_BgTypeId(BgTypeId), m_PlayersTeam(playersTeam)
+ BGQueueRemoveEvent(const uint64& pl_guid, uint32 bgInstanceGUID, BattleGroundTypeId BgTypeId, BattleGroundQueueTypeId bgQueueTypeId, uint32 removeTime) :
+ m_PlayerGuid(pl_guid), m_BgInstanceGUID(bgInstanceGUID), m_BgTypeId(BgTypeId), m_BgQueueTypeId(bgQueueTypeId), m_RemoveTime(removeTime)
{
};
virtual ~BGQueueRemoveEvent() {};
@@ -169,8 +171,9 @@ class BGQueueRemoveEvent : public BasicEvent
private:
uint64 m_PlayerGuid;
uint32 m_BgInstanceGUID;
- uint32 m_PlayersTeam;
+ uint32 m_RemoveTime;
BattleGroundTypeId m_BgTypeId;
+ BattleGroundQueueTypeId m_BgQueueTypeId;
};
class BattleGroundMgr
@@ -192,10 +195,6 @@ class BattleGroundMgr
void BuildPlaySoundPacket(WorldPacket *data, uint32 soundid);
void SendAreaSpiritHealerQueryOpcode(Player *pl, BattleGround *bg, const uint64& guid);
- /* Player invitation */
- // called from Queue update, or from Addplayer to queue
- void InvitePlayer(Player* plr, uint32 bgInstanceGUID, BattleGroundTypeId bgTypeId, uint32 team);
-
/* Battlegrounds */
BattleGround* GetBattleGroundThroughClientInstance(uint32 instanceId, BattleGroundTypeId bgTypeId, BGQueueIdBasedOnLevel queue_id);
BattleGround* GetBattleGround(uint32 InstanceID, BattleGroundTypeId bgTypeId); //there must be uint32 because MAX_BATTLEGROUND_TYPE_ID means unknown
@@ -234,7 +233,7 @@ class BattleGroundMgr
BattleGroundTypeId GetBattleMasterBG(uint32 entry) const
{
BattleMastersMap::const_iterator itr = mBattleMastersMap.find(entry);
- if(itr != mBattleMastersMap.end())
+ if (itr != mBattleMastersMap.end())
return itr->second;
return BATTLEGROUND_WS;
}
diff --git a/src/game/BattleGroundNA.cpp b/src/game/BattleGroundNA.cpp
index b4c1b22d2de..364ba972bec 100644
--- a/src/game/BattleGroundNA.cpp
+++ b/src/game/BattleGroundNA.cpp
@@ -50,7 +50,7 @@ void BattleGroundNA::Update(uint32 diff)
{
BattleGround::Update(diff);
- /*if(GetStatus() == STATUS_IN_PROGRESS)
+ /*if (GetStatus() == STATUS_IN_PROGRESS)
{
// update something
}*/
@@ -85,7 +85,7 @@ void BattleGroundNA::AddPlayer(Player *plr)
void BattleGroundNA::RemovePlayer(Player* /*plr*/, uint64 /*guid*/)
{
- if(GetStatus() == STATUS_WAIT_LEAVE)
+ if (GetStatus() == STATUS_WAIT_LEAVE)
return;
UpdateWorldState(0xa0f, GetAlivePlayersCountByTeam(ALLIANCE));
@@ -96,10 +96,10 @@ void BattleGroundNA::RemovePlayer(Player* /*plr*/, uint64 /*guid*/)
void BattleGroundNA::HandleKillPlayer(Player *player, Player *killer)
{
- if(GetStatus() != STATUS_IN_PROGRESS)
+ if (GetStatus() != STATUS_IN_PROGRESS)
return;
- if(!killer)
+ if (!killer)
{
sLog.outError("BattleGroundNA: Killer player not found");
return;
@@ -121,7 +121,7 @@ bool BattleGroundNA::HandlePlayerUnderMap(Player *player)
void BattleGroundNA::HandleAreaTrigger(Player *Source, uint32 Trigger)
{
- if(GetStatus() != STATUS_IN_PROGRESS)
+ if (GetStatus() != STATUS_IN_PROGRESS)
return;
//uint32 SpellId = 0;
@@ -137,7 +137,7 @@ void BattleGroundNA::HandleAreaTrigger(Player *Source, uint32 Trigger)
break;
}
- //if(buff_guid)
+ //if (buff_guid)
// HandleTriggerBuff(buff_guid,Source);
}
@@ -157,7 +157,7 @@ void BattleGroundNA::Reset()
bool BattleGroundNA::SetupBattleGround()
{
// gates
- if( !AddObject(BG_NA_OBJECT_DOOR_1, BG_NA_OBJECT_TYPE_DOOR_1, 4031.854, 2966.833, 12.6462, -2.648788, 0, 0, 0.9697962, -0.2439165, RESPAWN_IMMEDIATELY)
+ if (!AddObject(BG_NA_OBJECT_DOOR_1, BG_NA_OBJECT_TYPE_DOOR_1, 4031.854, 2966.833, 12.6462, -2.648788, 0, 0, 0.9697962, -0.2439165, RESPAWN_IMMEDIATELY)
|| !AddObject(BG_NA_OBJECT_DOOR_2, BG_NA_OBJECT_TYPE_DOOR_2, 4081.179, 2874.97, 12.39171, 0.4928045, 0, 0, 0.2439165, 0.9697962, RESPAWN_IMMEDIATELY)
|| !AddObject(BG_NA_OBJECT_DOOR_3, BG_NA_OBJECT_TYPE_DOOR_3, 4023.709, 2981.777, 10.70117, -2.648788, 0, 0, 0.9697962, -0.2439165, RESPAWN_IMMEDIATELY)
|| !AddObject(BG_NA_OBJECT_DOOR_4, BG_NA_OBJECT_TYPE_DOOR_4, 4090.064, 2858.438, 10.23631, 0.4928045, 0, 0, 0.2439165, 0.9697962, RESPAWN_IMMEDIATELY)
diff --git a/src/game/BattleGroundRL.cpp b/src/game/BattleGroundRL.cpp
index 0e764d3f4c7..033733aa61a 100644
--- a/src/game/BattleGroundRL.cpp
+++ b/src/game/BattleGroundRL.cpp
@@ -50,7 +50,7 @@ void BattleGroundRL::Update(uint32 diff)
{
BattleGround::Update(diff);
- /*if(GetStatus() == STATUS_IN_PROGRESS)
+ /*if (GetStatus() == STATUS_IN_PROGRESS)
{
// update something
}*/
@@ -85,7 +85,7 @@ void BattleGroundRL::AddPlayer(Player *plr)
void BattleGroundRL::RemovePlayer(Player* /*plr*/, uint64 /*guid*/)
{
- if(GetStatus() == STATUS_WAIT_LEAVE)
+ if (GetStatus() == STATUS_WAIT_LEAVE)
return;
UpdateWorldState(0xbb8, GetAlivePlayersCountByTeam(ALLIANCE));
@@ -96,10 +96,10 @@ void BattleGroundRL::RemovePlayer(Player* /*plr*/, uint64 /*guid*/)
void BattleGroundRL::HandleKillPlayer(Player *player, Player *killer)
{
- if(GetStatus() != STATUS_IN_PROGRESS)
+ if (GetStatus() != STATUS_IN_PROGRESS)
return;
- if(!killer)
+ if (!killer)
{
sLog.outError("Killer player not found");
return;
@@ -122,7 +122,7 @@ bool BattleGroundRL::HandlePlayerUnderMap(Player *player)
void BattleGroundRL::HandleAreaTrigger(Player *Source, uint32 Trigger)
{
// this is wrong way to implement these things. On official it done by gameobject spell cast.
- if(GetStatus() != STATUS_IN_PROGRESS)
+ if (GetStatus() != STATUS_IN_PROGRESS)
return;
//uint32 SpellId = 0;
@@ -138,7 +138,7 @@ void BattleGroundRL::HandleAreaTrigger(Player *Source, uint32 Trigger)
break;
}
- //if(buff_guid)
+ //if (buff_guid)
// HandleTriggerBuff(buff_guid,Source);
}
@@ -158,7 +158,7 @@ void BattleGroundRL::Reset()
bool BattleGroundRL::SetupBattleGround()
{
// gates
- if( !AddObject(BG_RL_OBJECT_DOOR_1, BG_RL_OBJECT_TYPE_DOOR_1, 1293.561, 1601.938, 31.60557, -1.457349, 0, 0, -0.6658813, 0.7460576, RESPAWN_IMMEDIATELY)
+ if (!AddObject(BG_RL_OBJECT_DOOR_1, BG_RL_OBJECT_TYPE_DOOR_1, 1293.561, 1601.938, 31.60557, -1.457349, 0, 0, -0.6658813, 0.7460576, RESPAWN_IMMEDIATELY)
|| !AddObject(BG_RL_OBJECT_DOOR_2, BG_RL_OBJECT_TYPE_DOOR_2, 1278.648, 1730.557, 31.60557, 1.684245, 0, 0, 0.7460582, 0.6658807, RESPAWN_IMMEDIATELY)
// buffs
|| !AddObject(BG_RL_OBJECT_BUFF_1, BG_RL_OBJECT_TYPE_BUFF_1, 1328.719971, 1632.719971, 36.730400, -1.448624, 0, 0, 0.6626201, -0.7489557, 120)
diff --git a/src/game/BattleGroundSA.cpp b/src/game/BattleGroundSA.cpp
index 68ef2af19be..5e6b02edfce 100644
--- a/src/game/BattleGroundSA.cpp
+++ b/src/game/BattleGroundSA.cpp
@@ -65,7 +65,7 @@ void BattleGroundSA::RemovePlayer(Player* /*plr*/,uint64 /*guid*/)
void BattleGroundSA::HandleAreaTrigger(Player *Source, uint32 Trigger)
{
// this is wrong way to implement these things. On official it done by gameobject spell cast.
- if(GetStatus() != STATUS_IN_PROGRESS)
+ if (GetStatus() != STATUS_IN_PROGRESS)
return;
}
diff --git a/src/game/BattleGroundWS.cpp b/src/game/BattleGroundWS.cpp
index ecf93db7cfa..fac59229e63 100644
--- a/src/game/BattleGroundWS.cpp
+++ b/src/game/BattleGroundWS.cpp
@@ -67,43 +67,43 @@ void BattleGroundWS::Update(uint32 diff)
{
BattleGround::Update(diff);
- if(GetStatus() == STATUS_IN_PROGRESS)
+ if (GetStatus() == STATUS_IN_PROGRESS)
{
- if(m_FlagState[BG_TEAM_ALLIANCE] == BG_WS_FLAG_STATE_WAIT_RESPAWN)
+ if (m_FlagState[BG_TEAM_ALLIANCE] == BG_WS_FLAG_STATE_WAIT_RESPAWN)
{
m_FlagsTimer[BG_TEAM_ALLIANCE] -= diff;
- if(m_FlagsTimer[BG_TEAM_ALLIANCE] < 0)
+ if (m_FlagsTimer[BG_TEAM_ALLIANCE] < 0)
{
m_FlagsTimer[BG_TEAM_ALLIANCE] = 0;
RespawnFlag(ALLIANCE, true);
}
}
- if(m_FlagState[BG_TEAM_ALLIANCE] == BG_WS_FLAG_STATE_ON_GROUND)
+ if (m_FlagState[BG_TEAM_ALLIANCE] == BG_WS_FLAG_STATE_ON_GROUND)
{
m_FlagsDropTimer[BG_TEAM_ALLIANCE] -= diff;
- if(m_FlagsDropTimer[BG_TEAM_ALLIANCE] < 0)
+ if (m_FlagsDropTimer[BG_TEAM_ALLIANCE] < 0)
{
m_FlagsDropTimer[BG_TEAM_ALLIANCE] = 0;
RespawnFlagAfterDrop(ALLIANCE);
}
}
- if(m_FlagState[BG_TEAM_HORDE] == BG_WS_FLAG_STATE_WAIT_RESPAWN)
+ if (m_FlagState[BG_TEAM_HORDE] == BG_WS_FLAG_STATE_WAIT_RESPAWN)
{
m_FlagsTimer[BG_TEAM_HORDE] -= diff;
- if(m_FlagsTimer[BG_TEAM_HORDE] < 0)
+ if (m_FlagsTimer[BG_TEAM_HORDE] < 0)
{
m_FlagsTimer[BG_TEAM_HORDE] = 0;
RespawnFlag(HORDE, true);
}
}
- if(m_FlagState[BG_TEAM_HORDE] == BG_WS_FLAG_STATE_ON_GROUND)
+ if (m_FlagState[BG_TEAM_HORDE] == BG_WS_FLAG_STATE_ON_GROUND)
{
m_FlagsDropTimer[BG_TEAM_HORDE] -= diff;
- if(m_FlagsDropTimer[BG_TEAM_HORDE] < 0)
+ if (m_FlagsDropTimer[BG_TEAM_HORDE] < 0)
{
m_FlagsDropTimer[BG_TEAM_HORDE] = 0;
RespawnFlagAfterDrop(HORDE);
@@ -150,7 +150,7 @@ void BattleGroundWS::AddPlayer(Player *plr)
void BattleGroundWS::RespawnFlag(uint32 Team, bool captured)
{
- if(Team == ALLIANCE)
+ if (Team == ALLIANCE)
{
sLog.outDebug("Respawn Alliance flag");
m_FlagState[BG_TEAM_ALLIANCE] = BG_WS_FLAG_STATE_ON_BASE;
@@ -161,7 +161,7 @@ void BattleGroundWS::RespawnFlag(uint32 Team, bool captured)
m_FlagState[BG_TEAM_HORDE] = BG_WS_FLAG_STATE_ON_BASE;
}
- if(captured)
+ if (captured)
{
//when map_update will be allowed for battlegrounds this code will be useless
SpawnBGObject(BG_WS_OBJECT_H_FLAG, RESPAWN_IMMEDIATELY);
@@ -173,11 +173,11 @@ void BattleGroundWS::RespawnFlag(uint32 Team, bool captured)
void BattleGroundWS::RespawnFlagAfterDrop(uint32 team)
{
- if(GetStatus() != STATUS_IN_PROGRESS)
+ if (GetStatus() != STATUS_IN_PROGRESS)
return;
RespawnFlag(team,false);
- if(team == ALLIANCE)
+ if (team == ALLIANCE)
{
SpawnBGObject(BG_WS_OBJECT_A_FLAG, RESPAWN_IMMEDIATELY);
SendMessageToAll(LANG_BG_WS_ALLIANCE_FLAG_RESPAWNED, CHAT_MSG_BG_SYSTEM_NEUTRAL);
@@ -191,7 +191,7 @@ void BattleGroundWS::RespawnFlagAfterDrop(uint32 team)
PlaySoundToAll(BG_WS_SOUND_FLAGS_RESPAWNED);
GameObject *obj = HashMapHolder<GameObject>::Find(GetDroppedFlagGUID(team));
- if(obj)
+ if (obj)
obj->Delete();
else
sLog.outError("unknown droped flag bg, guid: %u",GUID_LOPART(GetDroppedFlagGUID(team)));
@@ -201,13 +201,13 @@ void BattleGroundWS::RespawnFlagAfterDrop(uint32 team)
void BattleGroundWS::EventPlayerCapturedFlag(Player *Source)
{
- if(GetStatus() != STATUS_IN_PROGRESS)
+ if (GetStatus() != STATUS_IN_PROGRESS)
return;
uint32 winner = 0;
Source->RemoveAurasWithInterruptFlags(AURA_INTERRUPT_FLAG_ENTER_PVP_COMBAT);
- if(Source->GetTeam() == ALLIANCE)
+ if (Source->GetTeam() == ALLIANCE)
{
if (!this->IsHordeFlagPickedup())
return;
@@ -216,7 +216,7 @@ void BattleGroundWS::EventPlayerCapturedFlag(Player *Source)
m_FlagState[BG_TEAM_HORDE] = BG_WS_FLAG_STATE_WAIT_RESPAWN;
// Drop Horde Flag from Player
Source->RemoveAurasDueToSpell(BG_WS_SPELL_WARSONG_FLAG);
- if(GetTeamScore(ALLIANCE) < BG_WS_MAX_TEAM_SCORE)
+ if (GetTeamScore(ALLIANCE) < BG_WS_MAX_TEAM_SCORE)
AddPoint(ALLIANCE, 1);
PlaySoundToAll(BG_WS_SOUND_FLAG_CAPTURED_ALLIANCE);
RewardReputationToTeam(890, m_ReputationCapture, ALLIANCE);
@@ -230,7 +230,7 @@ void BattleGroundWS::EventPlayerCapturedFlag(Player *Source)
m_FlagState[BG_TEAM_ALLIANCE] = BG_WS_FLAG_STATE_WAIT_RESPAWN;
// Drop Alliance Flag from Player
Source->RemoveAurasDueToSpell(BG_WS_SPELL_SILVERWING_FLAG);
- if(GetTeamScore(HORDE) < BG_WS_MAX_TEAM_SCORE)
+ if (GetTeamScore(HORDE) < BG_WS_MAX_TEAM_SCORE)
AddPoint(HORDE, 1);
PlaySoundToAll(BG_WS_SOUND_FLAG_CAPTURED_HORDE);
RewardReputationToTeam(889, m_ReputationCapture, HORDE);
@@ -241,7 +241,7 @@ void BattleGroundWS::EventPlayerCapturedFlag(Player *Source)
SpawnBGObject(BG_WS_OBJECT_H_FLAG, BG_WS_FLAG_RESPAWN_TIME);
SpawnBGObject(BG_WS_OBJECT_A_FLAG, BG_WS_FLAG_RESPAWN_TIME);
- if(Source->GetTeam() == ALLIANCE)
+ if (Source->GetTeam() == ALLIANCE)
SendMessageToAll(LANG_BG_WS_CAPTURED_HF, CHAT_MSG_BG_SYSTEM_ALLIANCE, Source);
else
SendMessageToAll(LANG_BG_WS_CAPTURED_AF, CHAT_MSG_BG_SYSTEM_HORDE, Source);
@@ -251,13 +251,13 @@ void BattleGroundWS::EventPlayerCapturedFlag(Player *Source)
// only flag capture should be updated
UpdatePlayerScore(Source, SCORE_FLAG_CAPTURES, 1); // +1 flag captures
- if(GetTeamScore(ALLIANCE) == BG_WS_MAX_TEAM_SCORE)
+ if (GetTeamScore(ALLIANCE) == BG_WS_MAX_TEAM_SCORE)
winner = ALLIANCE;
- if(GetTeamScore(HORDE) == BG_WS_MAX_TEAM_SCORE)
+ if (GetTeamScore(HORDE) == BG_WS_MAX_TEAM_SCORE)
winner = HORDE;
- if(winner)
+ if (winner)
{
UpdateWorldState(BG_WS_FLAG_UNK_ALLIANCE, 0);
UpdateWorldState(BG_WS_FLAG_UNK_HORDE, 0);
@@ -275,15 +275,15 @@ void BattleGroundWS::EventPlayerCapturedFlag(Player *Source)
void BattleGroundWS::EventPlayerDroppedFlag(Player *Source)
{
- if(GetStatus() != STATUS_IN_PROGRESS)
+ if (GetStatus() != STATUS_IN_PROGRESS)
{
// if not running, do not cast things at the dropper player (prevent spawning the "dropped" flag), neither send unnecessary messages
// just take off the aura
- if(Source->GetTeam() == ALLIANCE)
+ if (Source->GetTeam() == ALLIANCE)
{
- if(!this->IsHordeFlagPickedup())
+ if (!this->IsHordeFlagPickedup())
return;
- if(GetHordeFlagPickerGUID() == Source->GetGUID())
+ if (GetHordeFlagPickerGUID() == Source->GetGUID())
{
SetHordeFlagPicker(0);
Source->RemoveAurasDueToSpell(BG_WS_SPELL_WARSONG_FLAG);
@@ -291,9 +291,9 @@ void BattleGroundWS::EventPlayerDroppedFlag(Player *Source)
}
else
{
- if(!this->IsAllianceFlagPickedup())
+ if (!this->IsAllianceFlagPickedup())
return;
- if(GetAllianceFlagPickerGUID() == Source->GetGUID())
+ if (GetAllianceFlagPickerGUID() == Source->GetGUID())
{
SetAllianceFlagPicker(0);
Source->RemoveAurasDueToSpell(BG_WS_SPELL_SILVERWING_FLAG);
@@ -304,11 +304,11 @@ void BattleGroundWS::EventPlayerDroppedFlag(Player *Source)
bool set = false;
- if(Source->GetTeam() == ALLIANCE)
+ if (Source->GetTeam() == ALLIANCE)
{
- if(!this->IsHordeFlagPickedup())
+ if (!IsHordeFlagPickedup())
return;
- if(GetHordeFlagPickerGUID() == Source->GetGUID())
+ if (GetHordeFlagPickerGUID() == Source->GetGUID())
{
SetHordeFlagPicker(0);
Source->RemoveAurasDueToSpell(BG_WS_SPELL_WARSONG_FLAG);
@@ -319,9 +319,9 @@ void BattleGroundWS::EventPlayerDroppedFlag(Player *Source)
}
else
{
- if(!this->IsAllianceFlagPickedup())
+ if (!IsAllianceFlagPickedup())
return;
- if(GetAllianceFlagPickerGUID() == Source->GetGUID())
+ if (GetAllianceFlagPickerGUID() == Source->GetGUID())
{
SetAllianceFlagPicker(0);
Source->RemoveAurasDueToSpell(BG_WS_SPELL_SILVERWING_FLAG);
@@ -336,7 +336,7 @@ void BattleGroundWS::EventPlayerDroppedFlag(Player *Source)
Source->CastSpell(Source, SPELL_RECENTLY_DROPPED_FLAG, true);
UpdateFlagState(Source->GetTeam(), 1);
- if(Source->GetTeam() == ALLIANCE)
+ if (Source->GetTeam() == ALLIANCE)
{
SendMessageToAll(LANG_BG_WS_DROPPED_HF, CHAT_MSG_BG_SYSTEM_HORDE, Source);
UpdateWorldState(BG_WS_FLAG_UNK_HORDE, uint32(-1));
@@ -353,7 +353,7 @@ void BattleGroundWS::EventPlayerDroppedFlag(Player *Source)
void BattleGroundWS::EventPlayerClickedOnFlag(Player *Source, GameObject* target_obj)
{
- if(GetStatus() != STATUS_IN_PROGRESS)
+ if (GetStatus() != STATUS_IN_PROGRESS)
return;
int32 message_id = 0;
@@ -392,9 +392,9 @@ void BattleGroundWS::EventPlayerClickedOnFlag(Player *Source, GameObject* target
}
//Alliance flag on ground(not in base) (returned or picked up again from ground!)
- if(this->GetFlagState(ALLIANCE) == BG_WS_FLAG_STATE_ON_GROUND && Source->IsWithinDistInMap(target_obj, 10) && target_obj->GetGOInfo()->id == BG_OBJECT_A_FLAG_GROUND_WS_ENTRY)
+ if (GetFlagState(ALLIANCE) == BG_WS_FLAG_STATE_ON_GROUND && Source->IsWithinDistInMap(target_obj, 10))
{
- if(Source->GetTeam() == ALLIANCE)
+ if (Source->GetTeam() == ALLIANCE)
{
message_id = LANG_BG_WS_RETURNED_AF;
type = CHAT_MSG_BG_SYSTEM_ALLIANCE;
@@ -421,9 +421,9 @@ void BattleGroundWS::EventPlayerClickedOnFlag(Player *Source, GameObject* target
}
//Horde flag on ground(not in base) (returned or picked up again)
- if(this->GetFlagState(HORDE) == BG_WS_FLAG_STATE_ON_GROUND && Source->IsWithinDistInMap(target_obj, 10) && target_obj->GetGOInfo()->id == BG_OBJECT_H_FLAG_GROUND_WS_ENTRY)
+ if (GetFlagState(HORDE) == BG_WS_FLAG_STATE_ON_GROUND && Source->IsWithinDistInMap(target_obj, 10))
{
- if(Source->GetTeam() == HORDE)
+ if (Source->GetTeam() == HORDE)
{
message_id = LANG_BG_WS_RETURNED_HF;
type = CHAT_MSG_BG_SYSTEM_HORDE;
@@ -459,9 +459,9 @@ void BattleGroundWS::EventPlayerClickedOnFlag(Player *Source, GameObject* target
void BattleGroundWS::RemovePlayer(Player *plr, uint64 guid)
{
// sometimes flag aura not removed :(
- if(IsAllianceFlagPickedup() && m_FlagKeepers[BG_TEAM_ALLIANCE] == guid)
+ if (IsAllianceFlagPickedup() && m_FlagKeepers[BG_TEAM_ALLIANCE] == guid)
{
- if(!plr)
+ if (!plr)
{
sLog.outError("BattleGroundWS: Removing offline player who has the FLAG!!");
this->SetAllianceFlagPicker(0);
@@ -470,9 +470,9 @@ void BattleGroundWS::RemovePlayer(Player *plr, uint64 guid)
else
this->EventPlayerDroppedFlag(plr);
}
- if(IsHordeFlagPickedup() && m_FlagKeepers[BG_TEAM_HORDE] == guid)
+ if (IsHordeFlagPickedup() && m_FlagKeepers[BG_TEAM_HORDE] == guid)
{
- if(!plr)
+ if (!plr)
{
sLog.outError("BattleGroundWS: Removing offline player who has the FLAG!!");
this->SetHordeFlagPicker(0);
@@ -485,7 +485,7 @@ void BattleGroundWS::RemovePlayer(Player *plr, uint64 guid)
void BattleGroundWS::UpdateFlagState(uint32 team, uint32 value)
{
- if(team == ALLIANCE)
+ if (team == ALLIANCE)
UpdateWorldState(BG_WS_FLAG_STATE_ALLIANCE, value);
else
UpdateWorldState(BG_WS_FLAG_STATE_HORDE, value);
@@ -493,7 +493,7 @@ void BattleGroundWS::UpdateFlagState(uint32 team, uint32 value)
void BattleGroundWS::UpdateTeamScore(uint32 team)
{
- if(team == ALLIANCE)
+ if (team == ALLIANCE)
UpdateWorldState(BG_WS_FLAG_CAPTURES_ALLIANCE, GetTeamScore(team));
else
UpdateWorldState(BG_WS_FLAG_CAPTURES_HORDE, GetTeamScore(team));
@@ -502,7 +502,7 @@ void BattleGroundWS::UpdateTeamScore(uint32 team)
void BattleGroundWS::HandleAreaTrigger(Player *Source, uint32 Trigger)
{
// this is wrong way to implement these things. On official it done by gameobject spell cast.
- if(GetStatus() != STATUS_IN_PROGRESS)
+ if (GetStatus() != STATUS_IN_PROGRESS)
return;
//uint32 SpellId = 0;
@@ -528,13 +528,13 @@ void BattleGroundWS::HandleAreaTrigger(Player *Source, uint32 Trigger)
//buff_guid = m_BgObjects[BG_WS_OBJECT_BERSERKBUFF_2];
break;
case 3646: // Alliance Flag spawn
- if(m_FlagState[BG_TEAM_HORDE] && !m_FlagState[BG_TEAM_ALLIANCE])
- if(GetHordeFlagPickerGUID() == Source->GetGUID())
+ if (m_FlagState[BG_TEAM_HORDE] && !m_FlagState[BG_TEAM_ALLIANCE])
+ if (GetHordeFlagPickerGUID() == Source->GetGUID())
EventPlayerCapturedFlag(Source);
break;
case 3647: // Horde Flag spawn
- if(m_FlagState[BG_TEAM_ALLIANCE] && !m_FlagState[BG_TEAM_HORDE])
- if(GetAllianceFlagPickerGUID() == Source->GetGUID())
+ if (m_FlagState[BG_TEAM_ALLIANCE] && !m_FlagState[BG_TEAM_HORDE])
+ if (GetAllianceFlagPickerGUID() == Source->GetGUID())
EventPlayerCapturedFlag(Source);
break;
case 3649: // unk1
@@ -548,14 +548,14 @@ void BattleGroundWS::HandleAreaTrigger(Player *Source, uint32 Trigger)
break;
}
- //if(buff_guid)
+ //if (buff_guid)
// HandleTriggerBuff(buff_guid,Source);
}
bool BattleGroundWS::SetupBattleGround()
{
// flags
- if( !AddObject(BG_WS_OBJECT_A_FLAG, BG_OBJECT_A_FLAG_WS_ENTRY, 1540.423f, 1481.325f, 351.8284f, 3.089233f, 0, 0, 0.9996573f, 0.02617699f, BG_WS_FLAG_RESPAWN_TIME/1000)
+ if (!AddObject(BG_WS_OBJECT_A_FLAG, BG_OBJECT_A_FLAG_WS_ENTRY, 1540.423f, 1481.325f, 351.8284f, 3.089233f, 0, 0, 0.9996573f, 0.02617699f, BG_WS_FLAG_RESPAWN_TIME/1000)
|| !AddObject(BG_WS_OBJECT_H_FLAG, BG_OBJECT_H_FLAG_WS_ENTRY, 916.0226f, 1434.405f, 345.413f, 0.01745329f, 0, 0, 0.008726535f, 0.9999619f, BG_WS_FLAG_RESPAWN_TIME/1000)
// buffs
|| !AddObject(BG_WS_OBJECT_SPEEDBUFF_1, BG_OBJECTID_SPEEDBUFF_ENTRY, 1449.93f, 1470.71f, 342.6346f, -1.64061f, 0, 0, 0.7313537f, -0.6819983f, BUFF_RESPAWN_TIME)
@@ -583,14 +583,14 @@ bool BattleGroundWS::SetupBattleGround()
}
WorldSafeLocsEntry const *sg = sWorldSafeLocsStore.LookupEntry(WS_GRAVEYARD_MAIN_ALLIANCE);
- if(!sg || !AddSpiritGuide(WS_SPIRIT_MAIN_ALLIANCE, sg->x, sg->y, sg->z, 3.124139f, ALLIANCE))
+ if (!sg || !AddSpiritGuide(WS_SPIRIT_MAIN_ALLIANCE, sg->x, sg->y, sg->z, 3.124139f, ALLIANCE))
{
sLog.outErrorDb("BatteGroundWS: Failed to spawn Alliance spirit guide! BattleGround not created!");
return false;
}
sg = sWorldSafeLocsStore.LookupEntry(WS_GRAVEYARD_MAIN_HORDE);
- if(!sg || !AddSpiritGuide(WS_SPIRIT_MAIN_HORDE, sg->x, sg->y, sg->z, 3.193953f, HORDE))
+ if (!sg || !AddSpiritGuide(WS_SPIRIT_MAIN_HORDE, sg->x, sg->y, sg->z, 3.193953f, HORDE))
{
sLog.outErrorDb("BatteGroundWS: Failed to spawn Horde spirit guide! BattleGround not created!");
return false;
@@ -620,9 +620,9 @@ void BattleGroundWS::Reset()
m_HonorEndKills = (isBGWeekend) ? 4 : 2;
/* Spirit nodes is static at this BG and then not required deleting at BG reset.
- if(m_BgCreatures[WS_SPIRIT_MAIN_ALLIANCE])
+ if (m_BgCreatures[WS_SPIRIT_MAIN_ALLIANCE])
DelCreature(WS_SPIRIT_MAIN_ALLIANCE);
- if(m_BgCreatures[WS_SPIRIT_MAIN_HORDE])
+ if (m_BgCreatures[WS_SPIRIT_MAIN_HORDE])
DelCreature(WS_SPIRIT_MAIN_HORDE);
*/
}
@@ -630,9 +630,9 @@ void BattleGroundWS::Reset()
void BattleGroundWS::EndBattleGround(uint32 winner)
{
//win reward
- if( winner == ALLIANCE )
+ if (winner == ALLIANCE)
RewardHonorToTeam(GetBonusHonorFromKill(m_HonorWinKills), ALLIANCE);
- if( winner == HORDE )
+ if (winner == HORDE)
RewardHonorToTeam(GetBonusHonorFromKill(m_HonorWinKills), HORDE);
//complete map_end rewards (even if no team wins)
RewardHonorToTeam(GetBonusHonorFromKill(m_HonorEndKills), ALLIANCE);
@@ -643,7 +643,7 @@ void BattleGroundWS::EndBattleGround(uint32 winner)
void BattleGroundWS::HandleKillPlayer(Player *player, Player *killer)
{
- if(GetStatus() != STATUS_IN_PROGRESS)
+ if (GetStatus() != STATUS_IN_PROGRESS)
return;
EventPlayerDroppedFlag(player);
@@ -680,16 +680,16 @@ WorldSafeLocsEntry const* BattleGroundWS::GetClosestGraveYard(Player* player)
//if a player dies in preparation phase - then the player can't cheat
//and teleport to the graveyard outside the flagroom
//and start running around, while the doors are still closed
- if(player->GetTeam() == ALLIANCE)
+ if (player->GetTeam() == ALLIANCE)
{
- if(GetStatus() == STATUS_IN_PROGRESS)
+ if (GetStatus() == STATUS_IN_PROGRESS)
return sWorldSafeLocsStore.LookupEntry(WS_GRAVEYARD_MAIN_ALLIANCE);
else
return sWorldSafeLocsStore.LookupEntry(WS_GRAVEYARD_FLAGROOM_ALLIANCE);
}
else
{
- if(GetStatus() == STATUS_IN_PROGRESS)
+ if (GetStatus() == STATUS_IN_PROGRESS)
return sWorldSafeLocsStore.LookupEntry(WS_GRAVEYARD_MAIN_HORDE);
else
return sWorldSafeLocsStore.LookupEntry(WS_GRAVEYARD_FLAGROOM_HORDE);
@@ -701,14 +701,14 @@ void BattleGroundWS::FillInitialWorldStates(WorldPacket& data)
data << uint32(BG_WS_FLAG_CAPTURES_ALLIANCE) << uint32(GetTeamScore(ALLIANCE));
data << uint32(BG_WS_FLAG_CAPTURES_HORDE) << uint32(GetTeamScore(HORDE));
- if(m_FlagState[BG_TEAM_ALLIANCE] == BG_WS_FLAG_STATE_ON_GROUND)
+ if (m_FlagState[BG_TEAM_ALLIANCE] == BG_WS_FLAG_STATE_ON_GROUND)
data << uint32(BG_WS_FLAG_UNK_ALLIANCE) << uint32(-1);
else if (m_FlagState[BG_TEAM_ALLIANCE] == BG_WS_FLAG_STATE_ON_PLAYER)
data << uint32(BG_WS_FLAG_UNK_ALLIANCE) << uint32(1);
else
data << uint32(BG_WS_FLAG_UNK_ALLIANCE) << uint32(0);
- if(m_FlagState[BG_TEAM_HORDE] == BG_WS_FLAG_STATE_ON_GROUND)
+ if (m_FlagState[BG_TEAM_HORDE] == BG_WS_FLAG_STATE_ON_GROUND)
data << uint32(BG_WS_FLAG_UNK_HORDE) << uint32(-1);
else if (m_FlagState[BG_TEAM_HORDE] == BG_WS_FLAG_STATE_ON_PLAYER)
data << uint32(BG_WS_FLAG_UNK_HORDE) << uint32(1);
diff --git a/src/game/CMakeLists.txt b/src/game/CMakeLists.txt
index 97f6c3bde6f..081d9669696 100644
--- a/src/game/CMakeLists.txt
+++ b/src/game/CMakeLists.txt
@@ -73,6 +73,8 @@ SET(game_STAT_SRCS
CreatureAIRegistry.h
CreatureAISelector.cpp
CreatureAISelector.h
+ CreatureEventAI.cpp
+ CreatureEventAIMgr.cpp
Creature.cpp
Creature.h
CreatureGroups.cpp
@@ -293,4 +295,4 @@ SET(game_STAT_SRCS
)
add_library(game STATIC ${game_STAT_SRCS})
-ADD_DEPENDENCIES(game revision.h) \ No newline at end of file
+ADD_DEPENDENCIES(game revision.h)
diff --git a/src/game/CharacterHandler.cpp b/src/game/CharacterHandler.cpp
index eaf0ec5af0f..a2e189603f9 100644
--- a/src/game/CharacterHandler.cpp
+++ b/src/game/CharacterHandler.cpp
@@ -165,7 +165,7 @@ void WorldSession::HandleCharEnumOpcode( WorldPacket & /*recv_data*/ )
"SELECT characters.guid, characters.data, characters.name, characters.position_x, characters.position_y, characters.position_z, characters.map, characters.totaltime, characters.leveltime, "
// 9 10 11 12 13
"characters.at_login, character_pet.entry, character_pet.modelid, character_pet.level, guild_member.guildid "
- "FROM characters LEFT JOIN character_pet ON characters.guid=character_pet.owner AND character_pet.slot='0' "
+ "FROM characters LEFT JOIN character_pet ON characters.guid=character_pet.owner AND character_pet.slot='%u' "
"LEFT JOIN guild_member ON characters.guid = guild_member.guid "
"WHERE characters.account = '%u' ORDER BY characters.guid"
:
@@ -174,11 +174,11 @@ void WorldSession::HandleCharEnumOpcode( WorldPacket & /*recv_data*/ )
"SELECT characters.guid, characters.data, characters.name, characters.position_x, characters.position_y, characters.position_z, characters.map, characters.totaltime, characters.leveltime, "
// 9 10 11 12 13 14
"characters.at_login, character_pet.entry, character_pet.modelid, character_pet.level, guild_member.guildid, genitive "
- "FROM characters LEFT JOIN character_pet ON characters.guid = character_pet.owner AND character_pet.slot='0' "
+ "FROM characters LEFT JOIN character_pet ON characters.guid = character_pet.owner AND character_pet.slot='%u' "
"LEFT JOIN character_declinedname ON characters.guid = character_declinedname.guid "
"LEFT JOIN guild_member ON characters.guid = guild_member.guid "
"WHERE characters.account = '%u' ORDER BY characters.guid",
- GetAccountId());
+ PET_SAVE_AS_CURRENT,GetAccountId());
}
void WorldSession::HandleCharCreateOpcode( WorldPacket & recv_data )
@@ -814,9 +814,8 @@ void WorldSession::HandlePlayerLogin(LoginQueryHolder * holder)
SendDoFlight( MountId, path, startNode );
}
- // Load pet if any and player is alive and not in taxi flight
- if(pCurrChar->isAlive() && pCurrChar->m_taxi.GetTaxiSource()==0)
- pCurrChar->LoadPet();
+ // Load pet if any (if player not alive and in taxi flight or another then pet will remember as temporary unsummoned)
+ pCurrChar->LoadPet();
// Set FFA PvP for non GM in non-rest mode
if(sWorld.IsFFAPvPRealm() && !pCurrChar->isGameMaster() && !pCurrChar->HasFlag(PLAYER_FLAGS,PLAYER_FLAGS_RESTING) )
diff --git a/src/game/Chat.cpp b/src/game/Chat.cpp
index 50bb6b7832f..f63a550b7de 100644
--- a/src/game/Chat.cpp
+++ b/src/game/Chat.cpp
@@ -136,6 +136,8 @@ ChatCommand * ChatHandler::getCommandTable()
static ChatCommand debugCommandTable[] =
{
{ "setbit", SEC_ADMINISTRATOR, false, &ChatHandler::HandleDebugSet32Bit, "", NULL },
+ { "threat", SEC_ADMINISTRATOR, false, &ChatHandler::HandleDebugThreatList, "", NULL },
+ { "hostil", SEC_ADMINISTRATOR, false, &ChatHandler::HandleDebugHostilRefList, "", NULL },
{ "anim", SEC_GAMEMASTER, false, &ChatHandler::HandleDebugAnimCommand, "", NULL },
{ "arena", SEC_ADMINISTRATOR, false, &ChatHandler::HandleDebugArenaCommand, "", NULL },
{ "bg", SEC_ADMINISTRATOR, false, &ChatHandler::HandleDebugBattlegroundCommand, "", NULL },
@@ -232,7 +234,7 @@ ChatCommand * ChatHandler::getCommandTable()
{ "listbinds", SEC_ADMINISTRATOR, false, &ChatHandler::HandleInstanceListBindsCommand, "", NULL },
{ "unbind", SEC_ADMINISTRATOR, false, &ChatHandler::HandleInstanceUnbindCommand, "", NULL },
{ "stats", SEC_ADMINISTRATOR, true, &ChatHandler::HandleInstanceStatsCommand, "", NULL },
- { "savedata", SEC_ADMINISTRATOR, false, &ChatHandler::HandleInstanceSaveDataCommand, "", NULL },
+ { "savedata", SEC_ADMINISTRATOR, false, &ChatHandler::HandleInstanceSaveDataCommand, "", NULL },
{ NULL, 0, false, NULL, "", NULL }
};
@@ -384,6 +386,7 @@ ChatCommand * ChatHandler::getCommandTable()
static ChatCommand reloadCommandTable[] =
{
{ "all", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadAllCommand, "", NULL },
+ { "all_achievement",SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadAllAchievementCommand,"", NULL },
{ "all_area", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadAllAreaCommand, "", NULL },
{ "all_loot", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadAllLootCommand, "", NULL },
{ "all_npc", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadAllNpcCommand, "", NULL },
@@ -395,6 +398,8 @@ ChatCommand * ChatHandler::getCommandTable()
{ "config", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadConfigCommand, "", NULL },
+ { "achievement_criteria_data", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadAchievementCriteriaDataCommand, "", NULL },
+ { "achievement_reward", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadAchievementRewardCommand, "", NULL },
{ "areatrigger_tavern", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadAreaTriggerTavernCommand, "", NULL },
{ "areatrigger_teleport", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadAreaTriggerTeleportCommand, "", NULL },
{ "access_requirement", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadAccessRequirementCommand, "", NULL },
@@ -415,7 +420,7 @@ ChatCommand * ChatHandler::getCommandTable()
{ "gameobject_scripts", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadGameObjectScriptsCommand, "", NULL },
{ "item_enchantment_template", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadItemEnchantementsCommand, "", NULL },
{ "item_loot_template", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadLootTemplatesItemCommand, "", NULL },
- { "trinity_string", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadTrinityStringCommand, "", NULL },
+ { "locales_achievement_reward", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadLocalesAchievementRewardCommand,"", NULL },
{ "locales_creature", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadLocalesCreatureCommand, "", NULL },
{ "locales_gameobject", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadLocalesGameobjectCommand, "", NULL },
{ "locales_item", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadLocalesItemCommand, "", NULL },
@@ -458,6 +463,7 @@ ChatCommand * ChatHandler::getCommandTable()
{ "spell_target_position", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadSpellTargetPositionCommand, "", NULL },
{ "spell_threats", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadSpellThreatsCommand, "", NULL },
{ "spell_disabled", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadSpellDisabledCommand, "", NULL },
+ { "trinity_string", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadTrinityStringCommand, "", NULL },
{ "auctions", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadAuctionsCommand, "", NULL },
{ "waypoint_scripts", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadWpScriptsCommand, "", NULL },
{ "gm_tickets", SEC_ADMINISTRATOR, true, &ChatHandler::HandleGMTicketReloadCommand, "", NULL },
@@ -518,6 +524,7 @@ ChatCommand * ChatHandler::getCommandTable()
{
{ "difftime", SEC_CONSOLE, true, &ChatHandler::HandleServerSetDiffTimeCommand, "", NULL },
{ "loglevel", SEC_CONSOLE, true, &ChatHandler::HandleServerSetLogLevelCommand, "", NULL },
+ { "logfilelevel", SEC_CONSOLE, true, &ChatHandler::HandleServerSetLogFileLevelCommand, "", NULL },
{ "motd", SEC_ADMINISTRATOR, true, &ChatHandler::HandleServerSetMotdCommand, "", NULL },
{ "closed", SEC_ADMINISTRATOR, true, &ChatHandler::HandleServerSetClosedCommand, "", NULL },
{ NULL, 0, false, NULL, "", NULL }
diff --git a/src/game/Chat.h b/src/game/Chat.h
index 05892202718..7065c6dd0ed 100644
--- a/src/game/Chat.h
+++ b/src/game/Chat.h
@@ -291,6 +291,7 @@ class ChatHandler
bool HandleQuestComplete(const char * args);
bool HandleReloadAllCommand(const char* args);
+ bool HandleReloadAllAchievementCommand(const char* args);
bool HandleReloadAllAreaCommand(const char* args);
bool HandleReloadAllItemCommand(const char* args);
bool HandleReloadAllLootCommand(const char* args);
@@ -302,7 +303,8 @@ class ChatHandler
bool HandleReloadConfigCommand(const char* args);
- bool HandleReloadWpScriptsCommand(const char* args);
+ bool HandleReloadAchievementCriteriaDataCommand(const char* args);
+ bool HandleReloadAchievementRewardCommand(const char* args);
bool HandleReloadAreaTriggerTavernCommand(const char* args);
bool HandleReloadAreaTriggerTeleportCommand(const char* args);
bool HandleReloadAccessRequirementCommand(const char* args);
@@ -317,6 +319,7 @@ class ChatHandler
bool HandleReloadGOQuestRelationsCommand(const char* args);
bool HandleReloadGOQuestInvRelationsCommand(const char* args);
bool HandleReloadItemEnchantementsCommand(const char* args);
+ bool HandleReloadLocalesAchievementRewardCommand(const char* args);
bool HandleReloadLocalesCreatureCommand(const char* args);
bool HandleReloadLocalesGameobjectCommand(const char* args);
bool HandleReloadLocalesItemCommand(const char* args);
@@ -367,6 +370,7 @@ class ChatHandler
bool HandleReloadSpellPetAurasCommand(const char* args);
bool HandleReloadSpellDisabledCommand(const char* args);
bool HandleReloadAuctionsCommand(const char* args);
+ bool HandleReloadWpScriptsCommand(const char* args);
bool HandleResetAchievementsCommand(const char * args);
bool HandleResetAllCommand(const char * args);
@@ -390,6 +394,7 @@ class ChatHandler
bool HandleServerRestartCommand(const char* args);
bool HandleServerSetMotdCommand(const char* args);
bool HandleServerSetLogLevelCommand(const char* args);
+ bool HandleServerSetLogFileLevelCommand(const char* args);
bool HandleServerSetDiffTimeCommand(const char* args);
bool HandleServerShutDownCommand(const char* args);
bool HandleServerShutDownCancelCommand(const char* args);
diff --git a/src/game/Creature.cpp b/src/game/Creature.cpp
index 74ebe4406c8..7a4cac89408 100644
--- a/src/game/Creature.cpp
+++ b/src/game/Creature.cpp
@@ -116,7 +116,7 @@ bool AssistDelayEvent::Execute(uint64 /*e_time*/, uint32 /*p_time*/)
{
while (!m_assistants.empty())
{
- Creature* assistant = (Creature*)Unit::GetUnit(m_owner, *m_assistants.begin());
+ Creature* assistant = Unit::GetCreature(m_owner, *m_assistants.begin());
m_assistants.pop_front();
if (assistant && assistant->CanAssistTo(&m_owner, victim))
@@ -151,6 +151,7 @@ m_creatureInfo(NULL), m_reactState(REACT_AGGRESSIVE), m_formation(NULL), m_summo
m_CreatureCategoryCooldowns.clear();
m_GlobalCooldown = 0;
m_unit_movement_flags = MOVEMENTFLAG_WALK_MODE;
+ DisableReputationGain = false;
}
Creature::~Creature()
diff --git a/src/game/Creature.h b/src/game/Creature.h
index 02111ea9f70..ce890c34902 100644
--- a/src/game/Creature.h
+++ b/src/game/Creature.h
@@ -134,6 +134,7 @@ enum CreatureFlagsExtra
CREATURE_FLAG_EXTRA_WORLDEVENT = 0x00004000, // custom flag for world event creatures (left room for merging)
//CREATURE_FLAG_EXTRA_CHARM_AI = 0x00008000, // use ai when charmed
CREATURE_FLAG_EXTRA_NO_TAUNT = 0x00010000, // cannot be taunted
+ CREATURE_FLAG_EXTRA_NO_CRIT = 0x00020000, // creature can't do critical strikes
};
enum SummonMask
@@ -325,6 +326,29 @@ enum InhabitTypeValues
INHABIT_ANYWHERE = INHABIT_GROUND | INHABIT_WATER | INHABIT_AIR
};
+// Enums used by StringTextData::Type (CreatureEventAI)
+enum ChatType
+{
+ CHAT_TYPE_SAY = 0,
+ CHAT_TYPE_YELL = 1,
+ CHAT_TYPE_TEXT_EMOTE = 2,
+ CHAT_TYPE_BOSS_EMOTE = 3,
+ CHAT_TYPE_WHISPER = 4,
+ CHAT_TYPE_BOSS_WHISPER = 5,
+ CHAT_TYPE_ZONE_YELL = 6
+};
+
+//Selection method used by SelectTarget (CreatureEventAI)
+enum AttackingTarget
+{
+ ATTACKING_TARGET_RANDOM = 0, //Just selects a random target
+ ATTACKING_TARGET_TOPAGGRO, //Selects targes from top aggro to bottom
+ ATTACKING_TARGET_BOTTOMAGGRO, //Selects targets from bottom aggro to top
+ ATTACKING_TARGET_RANDOM_PLAYER, //Just selects a random target (player only)
+ ATTACKING_TARGET_TOPAGGRO_PLAYER, //Selects targes from top aggro to bottom (player only)
+ ATTACKING_TARGET_BOTTOMAGGRO_PLAYER, //Selects targets from bottom aggro to top (player only)
+};
+
// GCC have alternative #pragma pack() syntax and old gcc version not support pack(pop), also any gcc version not support it at some platform
#if defined( __GNUC__ )
#pragma pack()
@@ -658,6 +682,8 @@ class TRINITY_DLL_SPEC Creature : public Unit
Unit *SelectVictim();
void SetDeadByDefault (bool death_state) {m_isDeadByDefault = death_state;}
+ void SetDisableReputationGain(bool disable) { DisableReputationGain = disable; }
+ bool IsReputationGainDisabled() { return DisableReputationGain; }
protected:
bool CreateFromProto(uint32 guidlow,uint32 Entry,uint32 team, const CreatureData *data = NULL);
bool InitEntry(uint32 entry, uint32 team=ALLIANCE, const CreatureData* data=NULL);
@@ -706,6 +732,8 @@ class TRINITY_DLL_SPEC Creature : public Unit
float mHome_Z;
float mHome_O;
+ bool DisableReputationGain;
+
private:
//WaypointMovementGenerator vars
uint32 m_waypointID;
diff --git a/src/game/CreatureAI.cpp b/src/game/CreatureAI.cpp
index 45608ef317e..e7043c6042f 100644
--- a/src/game/CreatureAI.cpp
+++ b/src/game/CreatureAI.cpp
@@ -70,6 +70,38 @@ void CreatureAI::OnCharmed(bool apply)
me->IsAIEnabled = false;
}
+void CreatureAI::DoZoneInCombat(Unit* pUnit)
+{
+ if (!pUnit)
+ pUnit = me;
+
+ Map *map = pUnit->GetMap();
+
+ if (!map->IsDungeon()) //use IsDungeon instead of Instanceable, in case battlegrounds will be instantiated
+ {
+ sLog.outError("DoZoneInCombat call for map that isn't an instance (pUnit entry = %d)", pUnit->GetTypeId() == TYPEID_UNIT ? ((Creature*)pUnit)->GetEntry() : 0);
+ return;
+ }
+
+ if (!pUnit->CanHaveThreatList() || pUnit->getThreatManager().isThreatListEmpty())
+ {
+ sLog.outError("DoZoneInCombat called for creature that either cannot have threat list or has empty threat list (pUnit entry = %d)", pUnit->GetTypeId() == TYPEID_UNIT ? ((Creature*)pUnit)->GetEntry() : 0);
+ return;
+ }
+
+ Map::PlayerList const &PlayerList = map->GetPlayers();
+ for(Map::PlayerList::const_iterator i = PlayerList.begin(); i != PlayerList.end(); ++i)
+ {
+ if (Player* i_pl = i->getSource())
+ if (i_pl->isAlive())
+ {
+ pUnit->SetInCombatWith(i_pl);
+ i_pl->SetInCombatWith(pUnit);
+ pUnit->AddThreat(i_pl, 0.0f);
+ }
+ }
+}
+
void CreatureAI::MoveInLineOfSight(Unit *who)
{
if(!me->getVictim() && me->canStartAttack(who))
diff --git a/src/game/CreatureAI.h b/src/game/CreatureAI.h
index 7388aab786c..11d5bd372fd 100644
--- a/src/game/CreatureAI.h
+++ b/src/game/CreatureAI.h
@@ -158,6 +158,8 @@ class TRINITY_DLL_SPEC CreatureAI : public UnitAI
// Called at reaching home after evade
virtual void JustReachedHome() {}
+
+ void DoZoneInCombat(Unit* pUnit = NULL);
};
struct SelectableAI : public FactoryHolder<CreatureAI>, public Permissible<Creature>
diff --git a/src/game/CreatureAIRegistry.cpp b/src/game/CreatureAIRegistry.cpp
index 3d7fe1848fb..6253c06b8bc 100644
--- a/src/game/CreatureAIRegistry.cpp
+++ b/src/game/CreatureAIRegistry.cpp
@@ -26,6 +26,7 @@
#include "PossessedAI.h"
#include "TotemAI.h"
#include "OutdoorPvPObjectiveAI.h"
+#include "CreatureEventAI.h"
#include "RandomMovementGenerator.h"
#include "CreatureAIImpl.h"
#include "MovementGeneratorImpl.h"
@@ -46,6 +47,7 @@ namespace AIRegistry
(new CreatureAIFactory<TotemAI>("TotemAI"))->RegisterSelf();
(new CreatureAIFactory<OutdoorPvPObjectiveAI>("OutdoorPvPObjectiveAI"))->RegisterSelf();
(new CreatureAIFactory<PossessedAI>("PossessedAI"))->RegisterSelf();
+ (new CreatureAIFactory<CreatureEventAI>("EventAI"))->RegisterSelf();
(new MovementGeneratorFactory<RandomMovementGenerator<Creature> >(RANDOM_MOTION_TYPE))->RegisterSelf();
(new MovementGeneratorFactory<WaypointMovementGenerator<Creature> >(WAYPOINT_MOTION_TYPE))->RegisterSelf();
diff --git a/src/game/CreatureAISelector.cpp b/src/game/CreatureAISelector.cpp
index 74275c8b173..88384fd6f21 100644
--- a/src/game/CreatureAISelector.cpp
+++ b/src/game/CreatureAISelector.cpp
@@ -35,24 +35,24 @@ namespace FactorySelector
{
CreatureAI* selectAI(Creature *creature)
{
- //if(creature->isPossessed())
- // creature->InitPossessedAI();
+ const CreatureAICreator *ai_factory = NULL;
+ CreatureAIRegistry &ai_registry(CreatureAIRepository::Instance());
+
+ //player-controlled guardians with pet bar
+ if(creature->HasSummonMask(SUMMON_MASK_GUARDIAN) && ((Guardian*)creature)->GetOwner()->GetTypeId() == TYPEID_PLAYER)
+ ai_factory = ai_registry.GetRegistryItem("PetAI");
- // Allow scripting AI for normal creatures and not controlled pets (guardians and mini-pets)
- if((!creature->isPet() || !((Pet*)creature)->isControlled()) && !creature->isCharmed())
+ //scriptname in db
+ if(!ai_factory)
if(CreatureAI* scriptedAI = Script->GetAI(creature))
return scriptedAI;
- CreatureAIRegistry &ai_registry(CreatureAIRepository::Instance());
- assert( creature->GetCreatureInfo() != NULL );
- CreatureInfo const *cinfo=creature->GetCreatureInfo();
-
- const CreatureAICreator *ai_factory = NULL;
+ CreatureInfo const *cinfo = creature->GetCreatureInfo();
+ assert(cinfo);
+ // this seems to be useless
std::string ainame=cinfo->AIName;
-
- // select by script name
- if( !ainame.empty())
+ if(!ai_factory && !ainame.empty())
ai_factory = ai_registry.GetRegistryItem( ainame.c_str() );
// select by NPC flags
@@ -60,21 +60,12 @@ namespace FactorySelector
{
if( creature->isGuard() )
ai_factory = ai_registry.GetRegistryItem("GuardAI");
- else if(creature->isPet() || (creature->isCharmed() && !creature->isPossessed()))
+ else if(creature->HasSummonMask(SUMMON_MASK_GUARDIAN))
ai_factory = ai_registry.GetRegistryItem("PetAI");
else if(creature->isTotem())
ai_factory = ai_registry.GetRegistryItem("TotemAI");
else if(creature->GetCreatureInfo()->flags_extra & CREATURE_FLAG_EXTRA_TRIGGER)
ai_factory = ai_registry.GetRegistryItem("NullCreatureAI");
- else if(creature->isSummon() && ((TempSummon*)creature)->m_Properties)
- {
- if(((TempSummon*)creature)->m_Properties->Category == SUMMON_CATEGORY_PET
- || ((TempSummon*)creature)->m_Properties->Type == SUMMON_TYPE_GUARDIAN
- || ((TempSummon*)creature)->m_Properties->Type == SUMMON_TYPE_MINION)
- ai_factory = ai_registry.GetRegistryItem("PetAI");
- else if(((TempSummon*)creature)->m_Properties->Type == SUMMON_TYPE_MINIPET)
- ai_factory = ai_registry.GetRegistryItem("CritterAI");
- }
else if(creature->GetCreatureType() == CREATURE_TYPE_CRITTER)
ai_factory = ai_registry.GetRegistryItem("CritterAI");
}
diff --git a/src/game/CreatureEventAI.cpp b/src/game/CreatureEventAI.cpp
new file mode 100644
index 00000000000..daf5c74ca72
--- /dev/null
+++ b/src/game/CreatureEventAI.cpp
@@ -0,0 +1,1661 @@
+/*
+ * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/>
+ *
+ * Copyright (C) 2008-2009 Trinity <http://www.trinitycore.org/>
+ *
+ * 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, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include "Common.h"
+#include "CreatureEventAI.h"
+#include "CreatureEventAIMgr.h"
+#include "ObjectMgr.h"
+#include "Spell.h"
+#include "World.h"
+#include "Cell.h"
+#include "CellImpl.h"
+#include "GameEventMgr.h"
+#include "GridNotifiers.h"
+#include "GridNotifiersImpl.h"
+#include "WorldPacket.h"
+#include "InstanceData.h"
+
+int CreatureEventAI::Permissible(const Creature *creature)
+{
+ if( creature->GetCreatureInfo()->AIName == "EventAI" )
+ return PERMIT_BASE_SPECIAL;
+ return PERMIT_BASE_NO;
+}
+
+CreatureEventAI::CreatureEventAI(Creature *c) : CreatureAI(c), m_creature(*c), InCombat(false)
+{
+ CreatureEventAI_Event_Map::iterator CreatureEvents = CreatureEAI_Mgr.GetCreatureEventAIMap().find(m_creature.GetEntry());
+ if (CreatureEvents != CreatureEAI_Mgr.GetCreatureEventAIMap().end())
+ {
+ std::vector<CreatureEventAI_Event>::iterator i;
+ for (i = (*CreatureEvents).second.begin(); i != (*CreatureEvents).second.end(); ++i)
+ {
+
+ //Debug check
+ #ifndef _DEBUG
+ if ((*i).event_flags & EFLAG_DEBUG_ONLY)
+ continue;
+ #endif
+ if(((*i).event_flags & (EFLAG_HEROIC | EFLAG_NORMAL)) && m_creature.GetMap()->IsDungeon() )
+ {
+ if( (m_creature.GetMap()->IsHeroic() && (*i).event_flags & EFLAG_HEROIC) ||
+ (!m_creature.GetMap()->IsHeroic() && (*i).event_flags & EFLAG_NORMAL))
+ {
+ //event flagged for instance mode
+ CreatureEventAIList.push_back(CreatureEventAIHolder(*i));
+ }
+ continue;
+ }
+ CreatureEventAIList.push_back(CreatureEventAIHolder(*i));
+ }
+ //EventMap had events but they were not added because they must be for instance
+ if (CreatureEventAIList.empty())
+ sLog.outError("CreatureEventAI: CreatureId has events but no events added to list because of instance flags.", m_creature.GetEntry());
+ }
+ else
+ sLog.outError("CreatureEventAI: EventMap for Creature %u is empty but creature is using CreatureEventAI.", m_creature.GetEntry());
+
+ bEmptyList = CreatureEventAIList.empty();
+ Phase = 0;
+ CombatMovementEnabled = true;
+ MeleeEnabled = true;
+ AttackDistance = 0;
+ AttackAngle = 0.0f;
+
+ //Handle Spawned Events
+ if (!bEmptyList)
+ {
+ for (std::list<CreatureEventAIHolder>::iterator i = CreatureEventAIList.begin(); i != CreatureEventAIList.end(); ++i)
+ {
+ if ((*i).Event.event_type == EVENT_T_SPAWNED)
+ ProcessEvent(*i);
+ }
+ }
+}
+
+bool CreatureEventAI::ProcessEvent(CreatureEventAIHolder& pHolder, Unit* pActionInvoker)
+{
+ if (!pHolder.Enabled || pHolder.Time)
+ return false;
+
+ //Check the inverse phase mask (event doesn't trigger if current phase bit is set in mask)
+ if (pHolder.Event.event_inverse_phase_mask & (1 << Phase))
+ return false;
+
+ //Store random here so that all random actions match up
+ uint32 rnd = rand();
+
+ //Return if chance for event is not met
+ if (pHolder.Event.event_chance <= rnd % 100)
+ return false;
+
+ union
+ {
+ uint32 param1;
+ int32 param1_s;
+ };
+
+ union
+ {
+ uint32 param2;
+ int32 param2_s;
+ };
+
+ union
+ {
+ uint32 param3;
+ int32 param3_s;
+ };
+
+ union
+ {
+ uint32 param4;
+ int32 param4_s;
+ };
+
+ param1 = pHolder.Event.event_param1;
+ param2 = pHolder.Event.event_param2;
+ param3 = pHolder.Event.event_param3;
+ param4 = pHolder.Event.event_param4;
+
+ //Check event conditions based on the event type, also reset events
+ switch (pHolder.Event.event_type)
+ {
+ case EVENT_T_TIMER:
+ {
+ if (!InCombat)
+ return false;
+
+ //Repeat Timers
+ if (param3 == param4)
+ {
+ pHolder.Time = param3;
+
+ }else if (param4 > param3)
+ pHolder.Time = urand(param3, param4);
+ else
+ {
+ sLog.outErrorDb("CreatureEventAI: Creature %u using Event %u (Type = %u) has RandomMax < RandomMin. Event repeating disabled.", m_creature.GetEntry(), pHolder.Event.event_id, pHolder.Event.event_type);
+ pHolder.Enabled = false;
+ }
+ }
+ break;
+ case EVENT_T_TIMER_OOC:
+ {
+ if (InCombat)
+ return false;
+
+ //Repeat Timers
+ if (param3 == param4)
+ {
+ pHolder.Time = param3;
+
+ }else if (param4 > param3)
+ pHolder.Time = urand(param3, param4);
+ else
+ {
+
+ sLog.outErrorDb("CreatureEventAI: Creature %u using Event %u (Type = %u) has RandomMax < RandomMin. Event repeating disabled.", m_creature.GetEntry(), pHolder.Event.event_id, pHolder.Event.event_type);
+ pHolder.Enabled = false;
+ }
+ }
+ break;
+ case EVENT_T_HP:
+ {
+ if (!InCombat || !m_creature.GetMaxHealth())
+ return false;
+
+ uint32 perc = (m_creature.GetHealth()*100) / m_creature.GetMaxHealth();
+
+ if (perc > param1 || perc < param2)
+ return false;
+
+ //Repeat Timers
+ if (param3 == param4)
+ {
+ pHolder.Time = param3;
+
+ }else if (param4 > param3)
+ pHolder.Time = urand(param3, param4);
+ else
+ {
+
+ sLog.outErrorDb("CreatureEventAI: Creature %u using Event %u (Type = %u) has RandomMax < RandomMin. Event repeating disabled.", m_creature.GetEntry(), pHolder.Event.event_id, pHolder.Event.event_type);
+ pHolder.Enabled = false;
+ }
+ }
+ break;
+ case EVENT_T_MANA:
+ {
+ if (!InCombat || !m_creature.GetMaxPower(POWER_MANA))
+ return false;
+
+ uint32 perc = (m_creature.GetPower(POWER_MANA)*100) / m_creature.GetMaxPower(POWER_MANA);
+
+ if (perc > param1 || perc < param2)
+ return false;
+
+ //Repeat Timers
+ if (param3 == param4)
+ {
+ pHolder.Time = param3;
+
+ }else if (param4 > param3)
+ pHolder.Time = urand(param3, param4);
+ else
+ {
+
+ sLog.outErrorDb("CreatureEventAI: Creature %u using Event %u (Type = %u) has RandomMax < RandomMin. Event repeating disabled.", m_creature.GetEntry(), pHolder.Event.event_id, pHolder.Event.event_type);
+ pHolder.Enabled = false;
+ }
+ }
+ break;
+ case EVENT_T_AGGRO:
+ {
+ }
+ break;
+ case EVENT_T_KILL:
+ {
+ //Repeat Timers
+ if (param1 == param2)
+ {
+ pHolder.Time = param1;
+
+ }else if (param2 > param1)
+ pHolder.Time = urand(param1, param2);
+ else
+ {
+
+ sLog.outErrorDb("CreatureEventAI: Creature %u using Event %u (Type = %u) has RandomMax < RandomMin. Event repeating disabled.", m_creature.GetEntry(), pHolder.Event.event_id, pHolder.Event.event_type);
+ pHolder.Enabled = false;
+ }
+ }
+ case EVENT_T_DEATH:
+ {
+ }
+ break;
+ case EVENT_T_EVADE:
+ {
+ }
+ break;
+ case EVENT_T_SPELLHIT:
+ {
+ //Spell hit is special case, param1 and param2 handled within CreatureEventAI::SpellHit
+
+ //Repeat Timers
+ if (param3 == param4)
+ {
+ pHolder.Time = param3;
+
+ }else if (param4 > param3)
+ pHolder.Time = urand(param3, param4);
+ else
+ {
+
+ sLog.outErrorDb("CreatureEventAI: Creature %u using Event %u (Type = %u) has RandomMax < RandomMin. Event repeating disabled.", m_creature.GetEntry(), pHolder.Event.event_id, pHolder.Event.event_type);
+ pHolder.Enabled = false;
+ }
+ }
+ break;
+ case EVENT_T_RANGE:
+ {
+ //Repeat Timers
+ if (param3 == param4)
+ {
+ pHolder.Time = param3;
+
+ }else if (param4 > param3)
+ pHolder.Time = urand(param3, param4);
+ else
+ {
+
+ sLog.outErrorDb("CreatureEventAI: Creature %u using Event %u (Type = %u) has RandomMax < RandomMin. Event repeating disabled.", m_creature.GetEntry(), pHolder.Event.event_id, pHolder.Event.event_type);
+ pHolder.Enabled = false;
+ }
+ }
+ break;
+ case EVENT_T_OOC_LOS:
+ {
+ //Repeat Timers
+ if (param3 == param4)
+ {
+ pHolder.Time = param3;
+
+ }else if (param4 > param3)
+ pHolder.Time = urand(param3, param4);
+ else
+ {
+
+ sLog.outErrorDb("CreatureEventAI: Creature %u using Event %u (Type = %u) has RandomMax < RandomMin. Event repeating disabled.", m_creature.GetEntry(), pHolder.Event.event_id, pHolder.Event.event_type);
+ pHolder.Enabled = false;
+ }
+ }
+ break;
+ case EVENT_T_SPAWNED:
+ {
+ }
+ break;
+ case EVENT_T_TARGET_HP:
+ {
+ if (!InCombat || !m_creature.getVictim() || !m_creature.getVictim()->GetMaxHealth())
+ return false;
+
+ uint32 perc = (m_creature.getVictim()->GetHealth()*100) / m_creature.getVictim()->GetMaxHealth();
+
+ if (perc > param1 || perc < param2)
+ return false;
+
+ //Repeat Timers
+ if (param3 == param4)
+ {
+ pHolder.Time = param3;
+
+ }else if (param4 > param3)
+ pHolder.Time = urand(param3, param4);
+ else
+ {
+
+ sLog.outErrorDb("CreatureEventAI: Creature %u using Event %u (Type = %u) has RandomMax < RandomMin. Event repeating disabled.", m_creature.GetEntry(), pHolder.Event.event_id, pHolder.Event.event_type);
+ pHolder.Enabled = false;
+ }
+ }
+ break;
+ case EVENT_T_TARGET_CASTING:
+ {
+ if (!InCombat || !m_creature.getVictim() || !m_creature.getVictim()->IsNonMeleeSpellCasted(false, false, true))
+ return false;
+
+ //Repeat Timers
+ if (param1 == param2)
+ {
+ pHolder.Time = param1;
+
+ }else if (param2 > param1)
+ pHolder.Time = urand(param1, param2);
+ else
+ {
+
+ sLog.outErrorDb("CreatureEventAI: Creature %u using Event %u (Type = %u) has RandomMax < RandomMin. Event repeating disabled.", m_creature.GetEntry(), pHolder.Event.event_id, pHolder.Event.event_type);
+ pHolder.Enabled = false;
+ }
+ }
+ break;
+ case EVENT_T_FRIENDLY_HP:
+ {
+ if (!InCombat)
+ return false;
+
+ Unit* pUnit = DoSelectLowestHpFriendly(param2, param1);
+
+ if (!pUnit)
+ return false;
+
+ pActionInvoker = pUnit;
+
+ //Repeat Timers
+ if (param3 == param4)
+ {
+ pHolder.Time = param3;
+
+ }else if (param4 > param3)
+ pHolder.Time = urand(param3, param4);
+ else
+ {
+
+ sLog.outErrorDb("CreatureEventAI: Creature %u using Event %u (Type = %u) has RandomMax < RandomMin. Event repeating disabled.", m_creature.GetEntry(), pHolder.Event.event_id, pHolder.Event.event_type);
+ pHolder.Enabled = false;
+ }
+ }
+ break;
+ case EVENT_T_FRIENDLY_IS_CC:
+ {
+ if (!InCombat)
+ return false;
+
+ std::list<Creature*> pList;
+ DoFindFriendlyCC(pList, param2);
+
+ //List is empty
+ if (pList.empty())
+ return false;
+
+ //We don't really care about the whole list, just return first available
+ pActionInvoker = *(pList.begin());
+
+ //Repeat Timers
+ if (param3 == param4)
+ {
+ pHolder.Time = param3;
+
+ }else if (param4 > param3)
+ pHolder.Time = urand(param3, param4);
+ else
+ {
+ sLog.outErrorDb("CreatureEventAI: Creature %u using Event %u (Type = %u) has RandomMax < RandomMin. Event repeating disabled.", m_creature.GetEntry(), pHolder.Event.event_id, pHolder.Event.event_type);
+ pHolder.Enabled = false;
+ }
+ }
+ break;
+ case EVENT_T_FRIENDLY_MISSING_BUFF:
+ {
+ std::list<Creature*> pList;
+ DoFindFriendlyMissingBuff(pList, param2, param1);
+
+ //List is empty
+ if (pList.empty())
+ return false;
+
+ //We don't really care about the whole list, just return first available
+ pActionInvoker = *(pList.begin());
+
+ //Repeat Timers
+ if (param3 == param4)
+ {
+ pHolder.Time = param3;
+
+ }else if (param4 > param3)
+ pHolder.Time = urand(param3, param4);
+ else
+ {
+
+ sLog.outErrorDb("CreatureEventAI: Creature %u using Event %u (Type = %u) has RandomMax < RandomMin. Event repeating disabled.", m_creature.GetEntry(), pHolder.Event.event_id, pHolder.Event.event_type);
+ pHolder.Enabled = false;
+ }
+ }
+ break;
+ case EVENT_T_SUMMONED_UNIT:
+ {
+ //Prevent event from occuring on no unit or non creatures
+ if (!pActionInvoker || pActionInvoker->GetTypeId()!=TYPEID_UNIT)
+ return false;
+
+ //Creature id doesn't match up
+ if (param1 && ((Creature*)pActionInvoker)->GetEntry() != param1)
+ return false;
+
+ //Repeat Timers
+ if (param2 == param3)
+ {
+ pHolder.Time = param2;
+
+ }else if (param3 > param2)
+ pHolder.Time = urand(param2, param3);
+ else
+ {
+
+ sLog.outErrorDb("CreatureEventAI: Creature %u using Event %u (Type = %u) has RandomMax < RandomMin. Event repeating disabled.", m_creature.GetEntry(), pHolder.Event.event_id, pHolder.Event.event_type);
+ pHolder.Enabled = false;
+ }
+ }
+ break;
+ case EVENT_T_REACHED_HOME:
+ {
+ }
+ break;
+ case EVENT_T_RECEIVE_EMOTE:
+ {
+ }
+ break;
+ default:
+
+ sLog.outErrorDb("CreatureEventAI: Creature %u using Event %u has invalid Event Type(%u), missing from ProcessEvent() Switch.", m_creature.GetEntry(), pHolder.Event.event_id, pHolder.Event.event_type);
+ break;
+ }
+
+ //Disable non-repeatable events
+ if (!(pHolder.Event.event_flags & EFLAG_REPEATABLE))
+ pHolder.Enabled = false;
+
+ //Process actions
+ for (uint32 j = 0; j < MAX_ACTIONS; j++)
+ ProcessAction(pHolder.Event.action[j].type, pHolder.Event.action[j].param1, pHolder.Event.action[j].param2, pHolder.Event.action[j].param3, rnd, pHolder.Event.event_id, pActionInvoker);
+
+ return true;
+}
+
+void CreatureEventAI::ProcessAction(uint16 type, uint32 param1, uint32 param2, uint32 param3, uint32 rnd, uint32 EventId, Unit* pActionInvoker)
+{
+ switch (type)
+ {
+ case ACTION_T_TEXT:
+ {
+ if (!param1)
+ return;
+
+ uint32 temp = 0;
+
+ if (param2 && param3)
+ {
+ switch( rand()%3 )
+ {
+ case 0: temp = param1; break;
+ case 2: temp = param2; break;
+ case 3: temp = param3; break;
+ }
+ }else if ( param2 && urand(0,1) )
+ {
+ temp = param2;
+ }else
+ {
+ temp = param1;
+ }
+
+ if (temp)
+ {
+ Unit* target = NULL;
+ Unit* owner = NULL;
+
+ if (pActionInvoker)
+ {
+ if (pActionInvoker->GetTypeId() == TYPEID_PLAYER)
+ target = pActionInvoker;
+ else if (owner = pActionInvoker->GetOwner())
+ {
+ if (owner->GetTypeId() == TYPEID_PLAYER)
+ target = owner;
+ }
+ }
+ else if (target = m_creature.getVictim())
+ {
+ if (target->GetTypeId() != TYPEID_PLAYER)
+ {
+ if (owner = target->GetOwner())
+ {
+ if (owner->GetTypeId() == TYPEID_PLAYER)
+ target = owner;
+ }
+ }
+ }
+
+ DoScriptText(temp, &m_creature, target);
+ }
+ }
+ break;
+ case ACTION_T_SET_FACTION:
+ {
+ if (param1)
+ m_creature.setFaction(param1);
+ else
+ {
+ if (CreatureInfo const* ci = GetCreatureTemplateStore(m_creature.GetEntry()))
+ {
+ //if no id provided, assume reset and then use default
+ if (m_creature.getFaction() != ci->faction_A)
+ m_creature.setFaction(ci->faction_A);
+ }
+ }
+ }
+ break;
+ case ACTION_T_MORPH_TO_ENTRY_OR_MODEL:
+ {
+ if (param1 || param2)
+ {
+ //set model based on entry from creature_template
+ if (param1)
+ {
+ if (CreatureInfo const* ci = GetCreatureTemplateStore(param1))
+ {
+ //use default display
+ if (ci->Modelid1)
+ m_creature.SetDisplayId(ci->Modelid1);
+ }
+ }
+ //if no param1, then use value from param2 (modelId)
+ else
+ m_creature.SetDisplayId(param2);
+ }
+ else
+ m_creature.DeMorph();
+ }
+ break;
+ case ACTION_T_SOUND:
+ m_creature.PlayDirectSound(param1);
+ break;
+ case ACTION_T_EMOTE:
+ m_creature.HandleEmoteCommand(param1);
+ break;
+ case ACTION_T_RANDOM_SOUND:
+ {
+ uint32 temp = GetRandActionParam(rnd, param1, param2, param3);
+
+ if (temp != uint32(0xffffffff))
+ m_creature.PlayDirectSound( temp );
+ }
+ break;
+ case ACTION_T_RANDOM_EMOTE:
+ {
+ uint32 temp = GetRandActionParam(rnd, param1, param2, param3);
+
+ if (temp != uint32(0xffffffff))
+ m_creature.HandleEmoteCommand(temp);
+ }
+ break;
+ case ACTION_T_CAST:
+ {
+ Unit* target = GetTargetByType(param2, pActionInvoker);
+ Unit* caster = &m_creature;
+
+ if (!target)
+ return;
+
+ //Cast is always triggered if target is forced to cast on self
+ if (param3 & CAST_FORCE_TARGET_SELF)
+ {
+ param3 |= CAST_TRIGGERED;
+ caster = target;
+ }
+
+ //Allowed to cast only if not casting (unless we interrupt ourself) or if spell is triggered
+ bool canCast = !(caster->IsNonMeleeSpellCasted(false) && (param3 & CAST_TRIGGERED | CAST_INTURRUPT_PREVIOUS));
+
+ // If cast flag CAST_AURA_NOT_PRESENT is active, check if target already has aura on them
+ if(param3 & CAST_AURA_NOT_PRESENT)
+ {
+ if(target->HasAura(param1))
+ return;
+ }
+
+ if (canCast)
+ {
+ const SpellEntry* tSpell = GetSpellStore()->LookupEntry(param1);
+
+ //Verify that spell exists
+ if (tSpell)
+ {
+ //Check if cannot cast spell
+ if (!(param3 & (CAST_FORCE_TARGET_SELF | CAST_FORCE_CAST)) &&
+ !CanCast(target, tSpell, (param3 & CAST_TRIGGERED)))
+ {
+ //Melee current victim if flag not set
+ if (!(param3 & CAST_NO_MELEE_IF_OOM))
+ {
+ if (m_creature.GetMotionMaster()->GetCurrentMovementGeneratorType() == TARGETED_MOTION_TYPE)
+ {
+ AttackDistance = 0;
+ AttackAngle = 0;
+
+ m_creature.GetMotionMaster()->MoveChase(m_creature.getVictim(), AttackDistance, AttackAngle);
+ }
+ }
+
+ }
+ else
+ {
+ //Interrupt any previous spell
+ if (caster->IsNonMeleeSpellCasted(false) && param3 & CAST_INTURRUPT_PREVIOUS)
+ caster->InterruptNonMeleeSpells(false);
+
+ caster->CastSpell(target, param1, (param3 & CAST_TRIGGERED));
+ }
+
+ }else
+ sLog.outErrorDb("CreatureEventAI: event %d creature %d attempt to cast spell that doesn't exist %d", EventId, m_creature.GetEntry(), param1);
+ }
+ }
+ break;
+ case ACTION_T_SUMMON:
+ {
+ Unit* target = GetTargetByType(param2, pActionInvoker);
+
+ Creature* pCreature = NULL;
+
+ if (param3)
+ pCreature = m_creature.SummonCreature(param1, 0, 0, 0, 0, TEMPSUMMON_TIMED_OR_DEAD_DESPAWN, param3);
+ else
+ pCreature = m_creature.SummonCreature(param1, 0, 0, 0, 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 0);
+
+ if (!pCreature)
+ {
+
+ sLog.outErrorDb( "CreatureEventAI: failed to spawn creature %u. Spawn event %d is on creature %d", param1, EventId, m_creature.GetEntry());
+ }
+ else if (param2 != TARGET_T_SELF && target)
+ pCreature->AI()->AttackStart(target);
+ }
+ break;
+ case ACTION_T_THREAT_SINGLE_PCT:
+ {
+ Unit* target = GetTargetByType(param2, pActionInvoker);
+
+ if (target)
+ m_creature.getThreatManager().modifyThreatPercent(target, param1);
+ }
+ break;
+ case ACTION_T_THREAT_ALL_PCT:
+ {
+ Unit* Temp = NULL;
+
+ std::list<HostilReference*>::iterator i = m_creature.getThreatManager().getThreatList().begin();
+ for (; i != m_creature.getThreatManager().getThreatList().end(); ++i)
+ {
+ Temp = Unit::GetUnit(m_creature,(*i)->getUnitGuid());
+ if (Temp)
+ m_creature.getThreatManager().modifyThreatPercent(Temp, param1);
+ }
+ }
+ break;
+ case ACTION_T_QUEST_EVENT:
+ {
+ Unit* target = GetTargetByType(param2, pActionInvoker);
+
+ if (target && target->GetTypeId() == TYPEID_PLAYER)
+ ((Player*)target)->AreaExploredOrEventHappens(param1);
+ }
+ break;
+ case ACTION_T_CASTCREATUREGO:
+ {
+ Unit* target = GetTargetByType(param3, pActionInvoker);
+
+ if (target && target->GetTypeId() == TYPEID_PLAYER)
+ ((Player*)target)->CastedCreatureOrGO(param1, m_creature.GetGUID(), param2);
+ }
+ break;
+ case ACTION_T_SET_UNIT_FIELD:
+ {
+ Unit* target = GetTargetByType(param3, pActionInvoker);
+
+ if (param1 < OBJECT_END || param1 >= UNIT_END)
+ return;
+
+ if (target)
+ target->SetUInt32Value(param1, param2);
+ }
+ break;
+ case ACTION_T_SET_UNIT_FLAG:
+ {
+ Unit* target = GetTargetByType(param2, pActionInvoker);
+
+ if (target)
+ target->SetFlag(UNIT_FIELD_FLAGS, param1);
+ }
+ break;
+ case ACTION_T_REMOVE_UNIT_FLAG:
+ {
+ Unit* target = GetTargetByType(param2, pActionInvoker);
+
+ if (target)
+ target->RemoveFlag(UNIT_FIELD_FLAGS, param1);
+ }
+ break;
+ case ACTION_T_AUTO_ATTACK:
+ {
+ if (param1)
+ MeleeEnabled = true;
+ else MeleeEnabled = false;
+ }
+ break;
+ case ACTION_T_COMBAT_MOVEMENT:
+ {
+ CombatMovementEnabled = param1;
+
+ //Allow movement (create new targeted movement gen only if idle)
+ if (CombatMovementEnabled)
+ {
+ m_creature.GetMotionMaster()->MoveChase(m_creature.getVictim(), AttackDistance, AttackAngle);
+ }
+ else
+ {
+ m_creature.GetMotionMaster()->MoveIdle();
+ }
+ }
+ break;
+ case ACTION_T_SET_PHASE:
+ {
+ Phase = param1;
+ }
+ break;
+ case ACTION_T_INC_PHASE:
+ {
+ Phase += param1;
+
+ if (Phase > 31)
+
+ sLog.outErrorDb( "CreatureEventAI: Event %d incremented Phase above 31. Phase mask cannot be used with phases past 31. CreatureEntry = %d", EventId, m_creature.GetEntry());
+ }
+ break;
+ case ACTION_T_EVADE:
+ {
+ EnterEvadeMode();
+ }
+ break;
+ case ACTION_T_FLEE:
+ {
+ if(m_creature.HasAuraType(SPELL_AURA_PREVENTS_FLEEING))
+ break;
+ TimetoFleeLeft = 8000;
+ m_creature.DoFleeToGetAssistance();
+ IsFleeing = true;
+ }
+ break;
+ case ACTION_T_QUEST_EVENT_ALL:
+ {
+ Unit* Temp = NULL;
+ if( pActionInvoker && pActionInvoker->GetTypeId() == TYPEID_PLAYER )
+ {
+ Temp = Unit::GetUnit(m_creature,pActionInvoker->GetGUID());
+ if( Temp )
+ ((Player*)Temp)->GroupEventHappens(param1,&m_creature);
+ }
+ }
+ break;
+ case ACTION_T_CASTCREATUREGO_ALL:
+ {
+ Unit* Temp = NULL;
+
+ std::list<HostilReference*>::iterator i = m_creature.getThreatManager().getThreatList().begin();
+ for (; i != m_creature.getThreatManager().getThreatList().end(); ++i)
+ {
+ Temp = Unit::GetUnit(m_creature,(*i)->getUnitGuid());
+ if (Temp && Temp->GetTypeId() == TYPEID_PLAYER)
+ ((Player*)Temp)->CastedCreatureOrGO(param1, m_creature.GetGUID(), param2);
+ }
+ }
+ break;
+ case ACTION_T_REMOVEAURASFROMSPELL:
+ {
+ Unit* target = GetTargetByType(param1, pActionInvoker);
+
+ if (target)
+ target->RemoveAurasDueToSpell(param2);
+ }
+ break;
+ case ACTION_T_RANGED_MOVEMENT:
+ {
+ AttackDistance = param1;
+ AttackAngle = ((float)param2/180)*M_PI;
+
+ if (CombatMovementEnabled)
+ {
+ m_creature.GetMotionMaster()->MoveChase(m_creature.getVictim(), AttackDistance, AttackAngle);
+ }
+ }
+ break;
+ case ACTION_T_RANDOM_PHASE:
+ {
+ uint32 temp = GetRandActionParam(rnd, param1, param2, param3);
+
+ Phase = temp;
+ }
+ break;
+ case ACTION_T_RANDOM_PHASE_RANGE:
+ {
+ if (param2 > param1)
+ {
+ Phase = param1 + (rnd % (param2 - param1));
+ }
+ else
+ sLog.outErrorDb( "CreatureEventAI: ACTION_T_RANDOM_PHASE_RANGE cannot have Param2 <= Param1. Divide by Zero. Event = %d. CreatureEntry = %d", EventId, m_creature.GetEntry());
+ }
+ break;
+ case ACTION_T_SUMMON_ID:
+ {
+ Unit* target = GetTargetByType(param2, pActionInvoker);
+
+ //Duration
+ Creature* pCreature = NULL;
+
+ CreatureEventAI_Summon_Map::const_iterator i = CreatureEAI_Mgr.GetCreatureEventAISummonMap().find(param3);
+ if (i == CreatureEAI_Mgr.GetCreatureEventAISummonMap().end())
+ {
+
+ sLog.outErrorDb( "CreatureEventAI: failed to spawn creature %u. Summon map index %u does not exist. EventID %d. CreatureID %d", param1, param3, EventId, m_creature.GetEntry());
+ return;
+ }
+
+ if ((*i).second.SpawnTimeSecs)
+ pCreature = m_creature.SummonCreature(param1, (*i).second.position_x, (*i).second.position_y, (*i).second.position_z, (*i).second.orientation, TEMPSUMMON_TIMED_OR_DEAD_DESPAWN, (*i).second.SpawnTimeSecs);
+ else pCreature = m_creature.SummonCreature(param1, (*i).second.position_x, (*i).second.position_y, (*i).second.position_z, (*i).second.orientation, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 0);
+
+ if (!pCreature)
+ {
+
+ sLog.outErrorDb( "CreatureEventAI: failed to spawn creature %u. EventId %d.Creature %d", param1, EventId, m_creature.GetEntry());
+ }
+ else if (param2 != TARGET_T_SELF && target)
+ pCreature->AI()->AttackStart(target);
+ }
+ break;
+ case ACTION_T_KILLED_MONSTER:
+ {
+ //first attempt player who tapped creature
+ if (Player* pPlayer = m_creature.GetLootRecipient())
+ pPlayer->RewardPlayerAndGroupAtEvent(param1, &m_creature);
+ else
+ {
+ //if not available, use pActionInvoker
+ Unit* pTarget = GetTargetByType(param2, pActionInvoker);
+
+ if (Player* pPlayer = pTarget->GetCharmerOrOwnerPlayerOrPlayerItself())
+ pPlayer->RewardPlayerAndGroupAtEvent(param1, &m_creature);
+ }
+ }
+ break;
+ case ACTION_T_SET_INST_DATA:
+ {
+ InstanceData* pInst = (InstanceData*)m_creature.GetInstanceData();
+ if (!pInst)
+ {
+ sLog.outErrorDb("CreatureEventAI: Event %d attempt to set instance data without instance script. Creature %d", EventId, m_creature.GetEntry());
+ return;
+ }
+
+ pInst->SetData(param1, param2);
+ }
+ break;
+ case ACTION_T_SET_INST_DATA64:
+ {
+ Unit* target = GetTargetByType(param2, pActionInvoker);
+ if (!target)
+ {
+ sLog.outErrorDb("CreatureEventAI: Event %d attempt to set instance data64 but Target == NULL. Creature %d", EventId, m_creature.GetEntry());
+ return;
+ }
+
+ InstanceData* pInst = (InstanceData*)m_creature.GetInstanceData();
+ if (!pInst)
+ {
+ sLog.outErrorDb("CreatureEventAI: Event %d attempt to set instance data64 without instance script. Creature %d", EventId, m_creature.GetEntry());
+ return;
+ }
+
+ pInst->SetData64(param1, target->GetGUID());
+ }
+ break;
+ case ACTION_T_UPDATE_TEMPLATE:
+ {
+ if (m_creature.GetEntry() == param1)
+ {
+
+ sLog.outErrorDb("CreatureEventAI: Event %d ACTION_T_UPDATE_TEMPLATE call with param1 == current entry. Creature %d", EventId, m_creature.GetEntry());
+ return;
+ }
+
+ m_creature.UpdateEntry(param1, param2 ? HORDE : ALLIANCE);
+ }
+ break;
+ case ACTION_T_DIE:
+ {
+ if (m_creature.isDead())
+ {
+
+ sLog.outErrorDb("CreatureEventAI: Event %d ACTION_T_DIE on dead creature. Creature %d", EventId, m_creature.GetEntry());
+ return;
+ }
+ m_creature.DealDamage(&m_creature, m_creature.GetMaxHealth(),NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false);
+ }
+ break;
+ case ACTION_T_ZONE_COMBAT_PULSE:
+ {
+ if (!m_creature.isInCombat() || !m_creature.GetMap()->IsDungeon())
+ {
+
+ sLog.outErrorDb("CreatureEventAI: Event %d ACTION_T_ZONE_COMBAT_PULSE on creature out of combat or in non-dungeon map. Creature %d", EventId, m_creature.GetEntry());
+ return;
+ }
+
+ DoZoneInCombat(&m_creature);
+ }
+ break;
+
+ // TRINITY ONLY
+ case ACTION_T_SET_ACTIVE:
+ me->setActive(param1 ? true : false);
+ break;
+ case ACTION_T_SET_AGGRESSIVE:
+ me->SetReactState(ReactStates(param1));
+ break;
+ case ACTION_T_ATTACK_START_PULSE:
+ AttackStart(me->SelectNearestTarget((float)param1));
+ break;
+ }
+}
+
+void CreatureEventAI::JustRespawned()
+{
+ InCombat = false;
+ IsFleeing = false;
+ Reset();
+
+ if (bEmptyList)
+ return;
+
+ //Handle Spawned Events
+ for (std::list<CreatureEventAIHolder>::iterator i = CreatureEventAIList.begin(); i != CreatureEventAIList.end(); ++i)
+ {
+ if ((*i).Event.event_type == EVENT_T_SPAWNED)
+ ProcessEvent(*i);
+ }
+}
+
+void CreatureEventAI::Reset()
+{
+ EventUpdateTime = EVENT_UPDATE_TIME;
+ EventDiff = 0;
+
+ TimetoFleeLeft = 0;
+ IsFleeing = false;
+
+ if (bEmptyList)
+ return;
+
+ //Reset all events to enabled
+ for (std::list<CreatureEventAIHolder>::iterator i = CreatureEventAIList.begin(); i != CreatureEventAIList.end(); ++i)
+ {
+ switch ((*i).Event.event_type)
+ {
+ //Reset all out of combat timers
+ case EVENT_T_TIMER_OOC:
+ {
+ if ((*i).Event.event_param2 == (*i).Event.event_param1)
+ {
+ (*i).Time = (*i).Event.event_param1;
+ (*i).Enabled = true;
+ }
+ else if ((*i).Event.event_param2 > (*i).Event.event_param1)
+ {
+ (*i).Time = urand((*i).Event.event_param1, (*i).Event.event_param2);
+ (*i).Enabled = true;
+ }
+ else
+ sLog.outErrorDb("CreatureEventAI: Creature %u using Event %u (Type = %u) has InitialMax < InitialMin. Event disabled.", m_creature.GetEntry(), (*i).Event.event_id, (*i).Event.event_type);
+ }
+ break;
+ //default:
+ //TODO: enable below code line / verify this is correct to enable events previously disabled (ex. aggro yell), instead of enable this in void Aggro()
+ //(*i).Enabled = true;
+ //(*i).Time = 0;
+ //break;
+ }
+ }
+}
+
+void CreatureEventAI::JustReachedHome()
+{
+ m_creature.LoadCreaturesAddon();
+
+ if (!bEmptyList)
+ {
+ for (std::list<CreatureEventAIHolder>::iterator i = CreatureEventAIList.begin(); i != CreatureEventAIList.end(); ++i)
+ {
+ if ((*i).Event.event_type == EVENT_T_REACHED_HOME)
+ ProcessEvent(*i);
+ }
+ }
+
+ Reset();
+}
+
+void CreatureEventAI::EnterEvadeMode()
+{
+ m_creature.InterruptNonMeleeSpells(true);
+ m_creature.RemoveAllAuras();
+ m_creature.DeleteThreatList();
+ m_creature.CombatStop();
+
+ if (m_creature.isAlive())
+ m_creature.GetMotionMaster()->MoveTargetedHome();
+
+ m_creature.SetLootRecipient(NULL);
+
+ InCombat = false;
+
+ if (bEmptyList)
+ return;
+
+ //Handle Evade events
+ for (std::list<CreatureEventAIHolder>::iterator i = CreatureEventAIList.begin(); i != CreatureEventAIList.end(); ++i)
+ {
+ if ((*i).Event.event_type == EVENT_T_EVADE)
+ ProcessEvent(*i);
+ }
+}
+
+void CreatureEventAI::JustDied(Unit* killer)
+{
+ InCombat = false;
+ IsFleeing = false;
+ Reset();
+
+ if (bEmptyList)
+ return;
+
+ //Handle Evade events
+ for (std::list<CreatureEventAIHolder>::iterator i = CreatureEventAIList.begin(); i != CreatureEventAIList.end(); ++i)
+ {
+ if ((*i).Event.event_type == EVENT_T_DEATH)
+ ProcessEvent(*i, killer);
+ }
+}
+
+void CreatureEventAI::KilledUnit(Unit* victim)
+{
+ if (bEmptyList || victim->GetTypeId() != TYPEID_PLAYER)
+ return;
+
+ for (std::list<CreatureEventAIHolder>::iterator i = CreatureEventAIList.begin(); i != CreatureEventAIList.end(); ++i)
+ {
+ if ((*i).Event.event_type == EVENT_T_KILL)
+ ProcessEvent(*i, victim);
+ }
+}
+
+void CreatureEventAI::JustSummoned(Creature* pUnit)
+{
+ if (bEmptyList || !pUnit)
+ return;
+
+ for (std::list<CreatureEventAIHolder>::iterator i = CreatureEventAIList.begin(); i != CreatureEventAIList.end(); ++i)
+ {
+ if ((*i).Event.event_type == EVENT_T_SUMMONED_UNIT)
+ ProcessEvent(*i, pUnit);
+ }
+}
+
+void CreatureEventAI::Aggro(Unit *who)
+{
+ //Check for on combat start events
+ if (!bEmptyList)
+ {
+ for (std::list<CreatureEventAIHolder>::iterator i = CreatureEventAIList.begin(); i != CreatureEventAIList.end(); ++i)
+ {
+ switch ((*i).Event.event_type)
+ {
+ case EVENT_T_AGGRO:
+ (*i).Enabled = true;
+ ProcessEvent(*i, who);
+ break;
+ //Reset all in combat timers
+ case EVENT_T_TIMER:
+ if ((*i).Event.event_param2 == (*i).Event.event_param1)
+ {
+ (*i).Time = (*i).Event.event_param1;
+ (*i).Enabled = true;
+ }
+ else if ((*i).Event.event_param2 > (*i).Event.event_param1)
+ {
+ (*i).Time = urand((*i).Event.event_param1, (*i).Event.event_param2);
+ (*i).Enabled = true;
+ }
+ else
+ sLog.outErrorDb("CreatureEventAI: Creature %u using Event %u (Type = %u) has InitialMax < InitialMin. Event disabled.", m_creature.GetEntry(), (*i).Event.event_id, (*i).Event.event_type);
+ break;
+ //All normal events need to be re-enabled and their time set to 0
+ default:
+ (*i).Enabled = true;
+ (*i).Time = 0;
+ break;
+ }
+ }
+ }
+
+ EventUpdateTime = EVENT_UPDATE_TIME;
+ EventDiff = 0;
+}
+
+void CreatureEventAI::AttackStart(Unit *who)
+{
+ if (!who)
+ return;
+
+ if (m_creature.Attack(who, MeleeEnabled))
+ {
+ if (!InCombat)
+ {
+ InCombat = true;
+ Aggro(who);
+ }
+
+ if (CombatMovementEnabled)
+ {
+ m_creature.GetMotionMaster()->MoveChase(who, AttackDistance, AttackAngle);
+ }
+ else
+ {
+ m_creature.GetMotionMaster()->MoveIdle();
+ }
+ }
+}
+
+void CreatureEventAI::MoveInLineOfSight(Unit *who)
+{
+ if (!who || InCombat)
+ return;
+
+ //Check for OOC LOS Event
+ if (!bEmptyList && !m_creature.getVictim())
+ {
+ for (std::list<CreatureEventAIHolder>::iterator itr = CreatureEventAIList.begin(); itr != CreatureEventAIList.end(); ++itr)
+ {
+ if ((*itr).Event.event_type == EVENT_T_OOC_LOS)
+ {
+ //can trigger if closer than fMaxAllowedRange
+ float fMaxAllowedRange = (*itr).Event.event_param2;
+
+ //if range is ok and we are actually in LOS
+ if (m_creature.IsWithinDistInMap(who, fMaxAllowedRange) && m_creature.IsWithinLOSInMap(who))
+ {
+ //if friendly event&&who is not hostile OR hostile event&&who is hostile
+ if (((*itr).Event.event_param1 && !m_creature.IsHostileTo(who)) ||
+ ((!(*itr).Event.event_param1) && m_creature.IsHostileTo(who)))
+ ProcessEvent(*itr, who);
+ }
+ }
+ }
+ }
+
+ //if (m_creature.isCivilian() && m_creature.IsNeutralToAll())
+ // return;
+
+ if(me->canStartAttack(who))
+ AttackStart(who);
+}
+
+void CreatureEventAI::SpellHit(Unit* pUnit, const SpellEntry* pSpell)
+{
+
+ if (bEmptyList)
+ return;
+
+ for (std::list<CreatureEventAIHolder>::iterator i = CreatureEventAIList.begin(); i != CreatureEventAIList.end(); ++i)
+ {
+ if ((*i).Event.event_type == EVENT_T_SPELLHIT)
+ {
+ //If spell id matches (or no spell id) & if spell school matches (or no spell school)
+ if (!(*i).Event.event_param1 || pSpell->Id == (*i).Event.event_param1)
+ {
+ if ((*i).Event.event_param2_s == -1 || pSpell->SchoolMask == (*i).Event.event_param2)
+ ProcessEvent(*i, pUnit);
+ }
+ }
+ }
+}
+
+void CreatureEventAI::UpdateAI(const uint32 diff)
+{
+ //Check if we are in combat (also updates calls threat update code)
+ bool Combat = InCombat ? UpdateVictim() : false;
+
+ //Must return if creature isn't alive. Normally select hostil target and get victim prevent this
+ if (!m_creature.isAlive())
+ return;
+
+ if (IsFleeing)
+ {
+ if(TimetoFleeLeft < diff)
+ {
+ me->SetControlled(false, UNIT_STAT_FLEEING);
+ me->SetNoCallAssistance(false);
+ me->CallAssistance();
+ if(me->getVictim())
+ me->GetMotionMaster()->MoveChase(me->getVictim());
+ IsFleeing = false;
+ }
+ else
+ TimetoFleeLeft -= diff;
+
+ return;
+ }
+
+ if (!bEmptyList)
+ {
+ //Events are only updated once every EVENT_UPDATE_TIME ms to prevent lag with large amount of events
+ if (EventUpdateTime < diff)
+ {
+ EventDiff += diff;
+
+ //Check for time based events
+ for (std::list<CreatureEventAIHolder>::iterator i = CreatureEventAIList.begin(); i != CreatureEventAIList.end(); ++i)
+ {
+ //Decrement Timers
+ if ((*i).Time)
+ {
+ if ((*i).Time > EventDiff)
+ {
+ //Do not decrement timers if event cannot trigger in this phase
+ if (!((*i).Event.event_inverse_phase_mask & (1 << Phase)))
+ (*i).Time -= EventDiff;
+
+ //Skip processing of events that have time remaining
+ continue;
+ }
+ else (*i).Time = 0;
+ }
+
+ //Events that are updated every EVENT_UPDATE_TIME
+ switch ((*i).Event.event_type)
+ {
+ case EVENT_T_TIMER_OOC:
+ ProcessEvent(*i);
+ break;
+ case EVENT_T_TIMER:
+ case EVENT_T_MANA:
+ case EVENT_T_HP:
+ case EVENT_T_TARGET_HP:
+ case EVENT_T_TARGET_CASTING:
+ case EVENT_T_FRIENDLY_HP:
+ if (Combat)
+ ProcessEvent(*i);
+ break;
+ case EVENT_T_RANGE:
+ if (Combat)
+ {
+ if (m_creature.IsWithinDistInMap(m_creature.getVictim(),(float)(*i).Event.event_param2))
+ {
+ if (m_creature.GetDistance(m_creature.getVictim()) >= (float)(*i).Event.event_param1)
+ ProcessEvent(*i);
+ }
+ }
+ break;
+ }
+ }
+
+ EventDiff = 0;
+ EventUpdateTime = EVENT_UPDATE_TIME;
+ }
+ else
+ {
+ EventDiff += diff;
+ EventUpdateTime -= diff;
+ }
+ }
+
+ //Melee Auto-Attack
+ if (Combat && MeleeEnabled)
+ DoMeleeAttackIfReady();
+}
+
+inline Unit* CreatureEventAI::SelectUnit(AttackingTarget target, uint32 position)
+{
+ //ThreatList m_threatlist;
+ std::list<HostilReference*>& m_threatlist = m_creature.getThreatManager().getThreatList();
+ std::list<HostilReference*>::iterator i = m_threatlist.begin();
+ std::list<HostilReference*>::reverse_iterator r = m_threatlist.rbegin();
+
+ if (position >= m_threatlist.size() || !m_threatlist.size())
+ return NULL;
+
+ switch (target)
+ {
+ case ATTACKING_TARGET_RANDOM:
+ {
+ advance ( i , position + (rand() % (m_threatlist.size() - position ) ));
+ return Unit::GetUnit(m_creature,(*i)->getUnitGuid());
+ }
+ case ATTACKING_TARGET_TOPAGGRO:
+ {
+ advance ( i , position);
+ return Unit::GetUnit(m_creature,(*i)->getUnitGuid());
+ }
+ case ATTACKING_TARGET_BOTTOMAGGRO:
+ {
+ advance ( r , position);
+ return Unit::GetUnit(m_creature,(*r)->getUnitGuid());
+ }
+ }
+ return NULL;
+}
+
+inline uint32 CreatureEventAI::GetRandActionParam(uint32 rnd, uint32 param1, uint32 param2, uint32 param3)
+{
+ switch (rnd % 3)
+ {
+ case 0:
+ return param1;
+ break;
+ case 1:
+ return param2;
+ break;
+ case 2:
+ return param3;
+ break;
+ }
+ return 0;
+}
+
+inline Unit* CreatureEventAI::GetTargetByType(uint32 Target, Unit* pActionInvoker)
+{
+ switch (Target)
+ {
+ case TARGET_T_SELF:
+ return &m_creature;
+ break;
+ case TARGET_T_HOSTILE:
+ return m_creature.getVictim();
+ break;
+ case TARGET_T_HOSTILE_SECOND_AGGRO:
+ return SelectUnit(ATTACKING_TARGET_TOPAGGRO,1);
+ break;
+ case TARGET_T_HOSTILE_LAST_AGGRO:
+ return SelectUnit(ATTACKING_TARGET_BOTTOMAGGRO,0);
+ break;
+ case TARGET_T_HOSTILE_RANDOM:
+ return SelectUnit(ATTACKING_TARGET_RANDOM,0);
+ break;
+ case TARGET_T_HOSTILE_RANDOM_NOT_TOP:
+ return SelectUnit(ATTACKING_TARGET_RANDOM,1);
+ break;
+ case TARGET_T_ACTION_INVOKER:
+ return pActionInvoker;
+ break;
+ default:
+ return NULL;
+ break;
+ };
+}
+
+Unit* CreatureEventAI::DoSelectLowestHpFriendly(float range, uint32 MinHPDiff)
+{
+ CellPair p(MaNGOS::ComputeCellPair(m_creature.GetPositionX(), m_creature.GetPositionY()));
+ Cell cell(p);
+ cell.data.Part.reserved = ALL_DISTRICT;
+ cell.SetNoCreate();
+
+ Unit* pUnit = NULL;
+
+ MaNGOS::MostHPMissingInRange u_check(&m_creature, range, MinHPDiff);
+ MaNGOS::UnitLastSearcher<MaNGOS::MostHPMissingInRange> searcher(&m_creature, pUnit, u_check);
+
+ /*
+ typedef TYPELIST_4(GameObject, Creature*except pets*, DynamicObject, Corpse*Bones*) AllGridObjectTypes;
+ This means that if we only search grid then we cannot possibly return pets or players so this is safe
+ */
+ TypeContainerVisitor<MaNGOS::UnitLastSearcher<MaNGOS::MostHPMissingInRange>, GridTypeMapContainer > grid_unit_searcher(searcher);
+
+ CellLock<GridReadGuard> cell_lock(cell, p);
+ cell_lock->Visit(cell_lock, grid_unit_searcher, *m_creature.GetMap());
+ return pUnit;
+}
+
+void CreatureEventAI::DoFindFriendlyCC(std::list<Creature*>& _list, float range)
+{
+ CellPair p(MaNGOS::ComputeCellPair(m_creature.GetPositionX(), m_creature.GetPositionY()));
+ Cell cell(p);
+ cell.data.Part.reserved = ALL_DISTRICT;
+ cell.SetNoCreate();
+
+ MaNGOS::FriendlyCCedInRange u_check(&m_creature, range);
+ MaNGOS::CreatureListSearcher<MaNGOS::FriendlyCCedInRange> searcher(&m_creature, _list, u_check);
+
+ TypeContainerVisitor<MaNGOS::CreatureListSearcher<MaNGOS::FriendlyCCedInRange>, GridTypeMapContainer > grid_creature_searcher(searcher);
+
+ CellLock<GridReadGuard> cell_lock(cell, p);
+ cell_lock->Visit(cell_lock, grid_creature_searcher, *m_creature.GetMap());
+}
+
+void CreatureEventAI::DoFindFriendlyMissingBuff(std::list<Creature*>& _list, float range, uint32 spellid)
+{
+ CellPair p(MaNGOS::ComputeCellPair(m_creature.GetPositionX(), m_creature.GetPositionY()));
+ Cell cell(p);
+ cell.data.Part.reserved = ALL_DISTRICT;
+ cell.SetNoCreate();
+
+ MaNGOS::FriendlyMissingBuffInRange u_check(&m_creature, range, spellid);
+ MaNGOS::CreatureListSearcher<MaNGOS::FriendlyMissingBuffInRange> searcher(&m_creature, _list, u_check);
+
+ TypeContainerVisitor<MaNGOS::CreatureListSearcher<MaNGOS::FriendlyMissingBuffInRange>, GridTypeMapContainer > grid_creature_searcher(searcher);
+
+ CellLock<GridReadGuard> cell_lock(cell, p);
+ cell_lock->Visit(cell_lock, grid_creature_searcher, *m_creature.GetMap());
+}
+
+//*********************************
+//*** Functions used globally ***
+
+void CreatureEventAI::DoScriptText(int32 textEntry, WorldObject* pSource, Unit* target)
+{
+ if (!pSource)
+ {
+ sLog.outErrorDb("CreatureEventAI: DoScriptText entry %i, invalid Source pointer.",textEntry);
+ return;
+ }
+
+ if (textEntry >= 0)
+ {
+ sLog.outErrorDb("CreatureEventAI: DoScriptText with source entry %u (TypeId=%u, guid=%u) attempts to process text entry %i, but text entry must be negative.",pSource->GetEntry(),pSource->GetTypeId(),pSource->GetGUIDLow(),textEntry);
+ return;
+ }
+
+ CreatureEventAI_TextMap::const_iterator i = CreatureEAI_Mgr.GetCreatureEventAITextMap().find(textEntry);
+
+ if (i == CreatureEAI_Mgr.GetCreatureEventAITextMap().end())
+ {
+ sLog.outErrorDb("CreatureEventAI: DoScriptText with source entry %u (TypeId=%u, guid=%u) could not find text entry %i.",pSource->GetEntry(),pSource->GetTypeId(),pSource->GetGUIDLow(),textEntry);
+ return;
+ }
+
+ sLog.outDebug("CreatureEventAI: DoScriptText: text entry=%i, Sound=%u, Type=%u, Language=%u, Emote=%u",textEntry,(*i).second.SoundId,(*i).second.Type,(*i).second.Language,(*i).second.Emote);
+
+ if((*i).second.SoundId)
+ {
+ if (GetSoundEntriesStore()->LookupEntry((*i).second.SoundId))
+ pSource->PlayDirectSound((*i).second.SoundId);
+ else
+ sLog.outErrorDb("CreatureEventAI: DoScriptText entry %i tried to process invalid sound id %u.",textEntry,(*i).second.SoundId);
+ }
+
+ if((*i).second.Emote)
+ {
+ if (pSource->GetTypeId() == TYPEID_UNIT || pSource->GetTypeId() == TYPEID_PLAYER)
+ {
+ ((Unit*)pSource)->HandleEmoteCommand((*i).second.Emote);
+ }
+ else
+ sLog.outErrorDb("CreatureEventAI: DoScriptText entry %i tried to process emote for invalid TypeId (%u).",textEntry,pSource->GetTypeId());
+ }
+
+ switch((*i).second.Type)
+ {
+ case CHAT_TYPE_SAY:
+ pSource->MonsterSay(textEntry, (*i).second.Language, target ? target->GetGUID() : 0);
+ break;
+ case CHAT_TYPE_YELL:
+ pSource->MonsterYell(textEntry, (*i).second.Language, target ? target->GetGUID() : 0);
+ break;
+ case CHAT_TYPE_TEXT_EMOTE:
+ pSource->MonsterTextEmote(textEntry, target ? target->GetGUID() : 0);
+ break;
+ case CHAT_TYPE_BOSS_EMOTE:
+ pSource->MonsterTextEmote(textEntry, target ? target->GetGUID() : 0, true);
+ break;
+ case CHAT_TYPE_WHISPER:
+ {
+ if (target && target->GetTypeId() == TYPEID_PLAYER)
+ pSource->MonsterWhisper(textEntry, target->GetGUID());
+ else sLog.outErrorDb("CreatureEventAI: DoScriptText entry %i cannot whisper without target unit (TYPEID_PLAYER).", textEntry);
+ }break;
+ case CHAT_TYPE_BOSS_WHISPER:
+ {
+ if (target && target->GetTypeId() == TYPEID_PLAYER)
+ pSource->MonsterWhisper(textEntry, target->GetGUID(), true);
+ else sLog.outErrorDb("CreatureEventAI: DoScriptText entry %i cannot whisper without target unit (TYPEID_PLAYER).", textEntry);
+ }break;
+ case CHAT_TYPE_ZONE_YELL:
+ pSource->MonsterYellToZone(textEntry, (*i).second.Language, target ? target->GetGUID() : 0);
+ break;
+ }
+}
+
+bool CreatureEventAI::CanCast(Unit* Target, SpellEntry const *Spell, bool Triggered)
+{
+ //No target so we can't cast
+ if (!Target || !Spell)
+ return false;
+
+ //Silenced so we can't cast
+ if (!Triggered && me->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_SILENCED))
+ return false;
+
+ //Check for power
+ if (!Triggered && me->GetPower((Powers)Spell->powerType) < Spell->manaCost)
+ return false;
+
+ SpellRangeEntry const *TempRange = NULL;
+
+ TempRange = GetSpellRangeStore()->LookupEntry(Spell->rangeIndex);
+
+ //Spell has invalid range store so we can't use it
+ if (!TempRange)
+ return false;
+
+ //Unit is out of range of this spell
+ if (me->GetDistance(Target) > me->GetSpellMaxRangeForTarget(Target, TempRange)
+ || me->GetDistance(Target) < me->GetSpellMinRangeForTarget(Target, TempRange))
+ return false;
+
+ return true;
+}
+
+bool CreatureEventAI::ReceiveEmote(Player* pPlayer, Creature* pCreature, uint32 uiEmote)
+{
+ if(pCreature->isCharmed())
+ return true;
+
+ CreatureEventAI* pTmpCreature = (CreatureEventAI*)(pCreature->AI());
+
+ if (pTmpCreature->bEmptyList)
+ return true;
+
+ for (std::list<CreatureEventAIHolder>::iterator itr = pTmpCreature->CreatureEventAIList.begin(); itr != pTmpCreature->CreatureEventAIList.end(); ++itr)
+ {
+ if ((*itr).Event.event_type == EVENT_T_RECEIVE_EMOTE)
+ {
+ if ((*itr).Event.event_param1 != uiEmote)
+ return true;
+
+ bool bProcess = false;
+
+ switch((*itr).Event.event_param2)
+ {
+ //enum ConditionType
+ case CONDITION_NONE: // 0 0
+ bProcess = true;
+ break;
+ case CONDITION_AURA: // spell_id effindex
+ if (pPlayer->HasAura((*itr).Event.event_param3,(*itr).Event.event_param4))
+ bProcess = true;
+ break;
+ case CONDITION_ITEM: // item_id count
+ if (pPlayer->HasItemCount((*itr).Event.event_param3,(*itr).Event.event_param4))
+ bProcess = true;
+ break;
+ case CONDITION_ITEM_EQUIPPED: // item_id count
+ if (pPlayer->HasItemOrGemWithIdEquipped((*itr).Event.event_param3,(*itr).Event.event_param4))
+ bProcess = true;
+ break;
+ case CONDITION_ZONEID: // zone_id 0
+ if (pPlayer->GetZoneId() == (*itr).Event.event_param3)
+ bProcess = true;
+ break;
+ case CONDITION_REPUTATION_RANK: // faction_id min_rank
+ if (pPlayer->GetReputationRank((*itr).Event.event_param3) >= (*itr).Event.event_param4)
+ bProcess = true;
+ break;
+ case CONDITION_TEAM: // player_team 0, (469 - Alliance 67 - Horde)
+ if (pPlayer->GetTeam() == (*itr).Event.event_param3)
+ bProcess = true;
+ break;
+ case CONDITION_SKILL: // skill_id min skill_value
+ if (pPlayer->HasSkill((*itr).Event.event_param3) && pPlayer->GetSkillValue((*itr).Event.event_param3) >= (*itr).Event.event_param4)
+ bProcess = true;
+ break;
+ case CONDITION_QUESTREWARDED: // quest_id 0
+ if (pPlayer->GetQuestRewardStatus((*itr).Event.event_param3))
+ bProcess = true;
+ break;
+ case CONDITION_QUESTTAKEN: // quest_id 0, for condition true while quest active.
+ if (pPlayer->GetQuestStatus((*itr).Event.event_param3) == QUEST_STATUS_INCOMPLETE)
+ bProcess = true;
+ break;
+ case CONDITION_ACTIVE_EVENT: // event_id 0
+ if (IsHolidayActive(HolidayIds((*itr).Event.event_param3)))
+ bProcess = true;
+ break;
+ }
+
+ if (bProcess)
+ {
+ sLog.outDebug("CreatureEventAI: ReceiveEmote CreatureEventAI: Condition ok, processing");
+ pTmpCreature->ProcessEvent(*itr, pPlayer);
+ }
+ }
+ }
+
+ return true;
+}
diff --git a/src/game/CreatureEventAI.h b/src/game/CreatureEventAI.h
new file mode 100644
index 00000000000..74ea7a40a6a
--- /dev/null
+++ b/src/game/CreatureEventAI.h
@@ -0,0 +1,309 @@
+/*
+ * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/>
+ *
+ * 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, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef MANGOS_CREATURE_EAI_H
+#define MANGOS_CREATURE_EAI_H
+
+#include "Common.h"
+#include "Creature.h"
+#include "CreatureAI.h"
+#include "Unit.h"
+
+class Player;
+class WorldObject;
+
+#define EVENT_UPDATE_TIME 500
+#define SPELL_RUN_AWAY 8225
+#define MAX_ACTIONS 3
+#define TEXT_SOURCE_RANGE -1000000 //the amount of entries each text source has available
+
+enum Event_Types
+{
+ EVENT_T_TIMER = 0, //InitialMin, InitialMax, RepeatMin, RepeatMax
+ EVENT_T_TIMER_OOC = 1, //InitialMin, InitialMax, RepeatMin, RepeatMax
+ EVENT_T_HP = 2, //HPMax%, HPMin%, RepeatMin, RepeatMax
+ EVENT_T_MANA = 3, //ManaMax%,ManaMin% RepeatMin, RepeatMax
+ EVENT_T_AGGRO = 4, //NONE
+ EVENT_T_KILL = 5, //RepeatMin, RepeatMax
+ EVENT_T_DEATH = 6, //NONE
+ EVENT_T_EVADE = 7, //NONE
+ EVENT_T_SPELLHIT = 8, //SpellID, School, RepeatMin, RepeatMax
+ EVENT_T_RANGE = 9, //MinDist, MaxDist, RepeatMin, RepeatMax
+ EVENT_T_OOC_LOS = 10, //NoHostile, NoFriendly, RepeatMin, RepeatMax
+ EVENT_T_SPAWNED = 11, //NONE
+ EVENT_T_TARGET_HP = 12, //HPMax%, HPMin%, RepeatMin, RepeatMax
+ EVENT_T_TARGET_CASTING = 13, //RepeatMin, RepeatMax
+ EVENT_T_FRIENDLY_HP = 14, //HPDeficit, Radius, RepeatMin, RepeatMax
+ EVENT_T_FRIENDLY_IS_CC = 15, //DispelType, Radius, RepeatMin, RepeatMax
+ EVENT_T_FRIENDLY_MISSING_BUFF = 16, //SpellId, Radius, RepeatMin, RepeatMax
+ EVENT_T_SUMMONED_UNIT = 17, //CreatureId, RepeatMin, RepeatMax
+ EVENT_T_TARGET_MANA = 18, //ManaMax%, ManaMin%, RepeatMin, RepeatMax
+ EVENT_T_QUEST_ACCEPT = 19, //QuestID
+ EVENT_T_QUEST_COMPLETE = 20, //
+ EVENT_T_REACHED_HOME = 21, //NONE
+ EVENT_T_RECEIVE_EMOTE = 22, //EmoteId, Condition, CondValue1, CondValue2
+
+ EVENT_T_END,
+};
+
+enum Action_Types
+{
+ ACTION_T_NONE = 0, //No action
+ ACTION_T_TEXT = 1, //-TextId1, optionally -TextId2, optionally -TextId3(if -TextId2 exist). If more than just -TextId1 is defined, randomize. Negative values.
+ ACTION_T_SET_FACTION = 2, //FactionId (or 0 for default)
+ ACTION_T_MORPH_TO_ENTRY_OR_MODEL = 3, //Creature_template entry(param1) OR ModelId (param2) (or 0 for both to demorph)
+ ACTION_T_SOUND = 4, //SoundId
+ ACTION_T_EMOTE = 5, //EmoteId
+ ACTION_T_RANDOM_SAY = 6, //UNUSED
+ ACTION_T_RANDOM_YELL = 7, //UNUSED
+ ACTION_T_RANDOM_TEXTEMOTE = 8, //UNUSED
+ ACTION_T_RANDOM_SOUND = 9, //SoundId1, SoundId2, SoundId3 (-1 in any field means no output if randomed that field)
+ ACTION_T_RANDOM_EMOTE = 10, //EmoteId1, EmoteId2, EmoteId3 (-1 in any field means no output if randomed that field)
+ ACTION_T_CAST = 11, //SpellId, Target, CastFlags
+ ACTION_T_SUMMON = 12, //CreatureID, Target, Duration in ms
+ ACTION_T_THREAT_SINGLE_PCT = 13, //Threat%, Target
+ ACTION_T_THREAT_ALL_PCT = 14, //Threat%
+ ACTION_T_QUEST_EVENT = 15, //QuestID, Target
+ ACTION_T_CASTCREATUREGO = 16, //QuestID, SpellId, Target
+ ACTION_T_SET_UNIT_FIELD = 17, //Field_Number, Value, Target
+ ACTION_T_SET_UNIT_FLAG = 18, //Flags (may be more than one field OR'd together), Target
+ ACTION_T_REMOVE_UNIT_FLAG = 19, //Flags (may be more than one field OR'd together), Target
+ ACTION_T_AUTO_ATTACK = 20, //AllowAttackState (0 = stop attack, anything else means continue attacking)
+ ACTION_T_COMBAT_MOVEMENT = 21, //AllowCombatMovement (0 = stop combat based movement, anything else continue attacking)
+ ACTION_T_SET_PHASE = 22, //Phase
+ ACTION_T_INC_PHASE = 23, //Value (may be negative to decrement phase, should not be 0)
+ ACTION_T_EVADE = 24, //No Params
+ ACTION_T_FLEE = 25, //No Params
+ ACTION_T_QUEST_EVENT_ALL = 26, //QuestID
+ ACTION_T_CASTCREATUREGO_ALL = 27, //QuestId, SpellId
+ ACTION_T_REMOVEAURASFROMSPELL = 28, //Target, Spellid
+ ACTION_T_RANGED_MOVEMENT = 29, //Distance, Angle
+ ACTION_T_RANDOM_PHASE = 30, //PhaseId1, PhaseId2, PhaseId3
+ ACTION_T_RANDOM_PHASE_RANGE = 31, //PhaseMin, PhaseMax
+ ACTION_T_SUMMON_ID = 32, //CreatureId, Target, SpawnId
+ ACTION_T_KILLED_MONSTER = 33, //CreatureId, Target
+ ACTION_T_SET_INST_DATA = 34, //Field, Data
+ ACTION_T_SET_INST_DATA64 = 35, //Field, Target
+ ACTION_T_UPDATE_TEMPLATE = 36, //Entry, Team
+ ACTION_T_DIE = 37, //No Params
+ ACTION_T_ZONE_COMBAT_PULSE = 38, //No Params
+
+ ACTION_T_SET_ACTIVE = 101, //Apply
+ ACTION_T_SET_AGGRESSIVE = 102, //Apply
+ ACTION_T_ATTACK_START_PULSE = 103, //Distance
+
+ ACTION_T_END,
+};
+
+enum Target
+{
+ //Self (m_creature)
+ TARGET_T_SELF = 0, //Self cast
+
+ //Hostile targets (if pet then returns pet owner)
+ TARGET_T_HOSTILE, //Our current target (ie: highest aggro)
+ TARGET_T_HOSTILE_SECOND_AGGRO, //Second highest aggro (generaly used for cleaves and some special attacks)
+ TARGET_T_HOSTILE_LAST_AGGRO, //Dead last on aggro (no idea what this could be used for)
+ TARGET_T_HOSTILE_RANDOM, //Just any random target on our threat list
+ TARGET_T_HOSTILE_RANDOM_NOT_TOP, //Any random target except top threat
+
+ //Invoker targets (if pet then returns pet owner)
+ TARGET_T_ACTION_INVOKER, //Unit who caused this Event to occur (only works for EVENT_T_AGGRO, EVENT_T_KILL, EVENT_T_DEATH, EVENT_T_SPELLHIT, EVENT_T_OOC_LOS, EVENT_T_FRIENDLY_HP, EVENT_T_FRIENDLY_IS_CC, EVENT_T_FRIENDLY_MISSING_BUFF)
+
+ //Hostile targets (including pets)
+ TARGET_T_HOSTILE_WPET, //Current target (can be a pet)
+ TARGET_T_HOSTILE_WPET_SECOND_AGGRO, //Second highest aggro (generaly used for cleaves and some special attacks)
+ TARGET_T_HOSTILE_WPET_LAST_AGGRO, //Dead last on aggro (no idea what this could be used for)
+ TARGET_T_HOSTILE_WPET_RANDOM, //Just any random target on our threat list
+ TARGET_T_HOSTILE_WPET_RANDOM_NOT_TOP, //Any random target except top threat
+
+ TARGET_T_ACTION_INVOKER_WPET,
+
+ TARGET_T_END
+};
+
+enum CastFlags
+{
+ CAST_INTURRUPT_PREVIOUS = 0x01, //Interrupt any spell casting
+ CAST_TRIGGERED = 0x02, //Triggered (this makes spell cost zero mana and have no cast time)
+ CAST_FORCE_CAST = 0x04, //Forces cast even if creature is out of mana or out of range
+ CAST_NO_MELEE_IF_OOM = 0x08, //Prevents creature from entering melee if out of mana or out of range
+ CAST_FORCE_TARGET_SELF = 0x10, //Forces the target to cast this spell on itself
+ CAST_AURA_NOT_PRESENT = 0x20, //Only casts the spell if the target does not have an aura from the spell
+};
+
+enum EventFlags
+{
+ EFLAG_REPEATABLE = 0x01, //Event repeats
+ EFLAG_NORMAL = 0x02, //Event only occurs in Normal instance difficulty
+ EFLAG_HEROIC = 0x04, //Event only occurs in Heroic instance difficulty
+ EFLAG_RESERVED_3 = 0x08,
+ EFLAG_RESERVED_4 = 0x10,
+ EFLAG_RESERVED_5 = 0x20,
+ EFLAG_RESERVED_6 = 0x40,
+ EFLAG_DEBUG_ONLY = 0x80, //Event only occurs in debug build of SD2 only
+};
+
+// String text additional data, used in (CreatureEventAI)
+struct StringTextData
+{
+ uint32 SoundId;
+ uint8 Type;
+ uint32 Language;
+ uint32 Emote;
+};
+// Text Maps
+typedef UNORDERED_MAP<int32, StringTextData> CreatureEventAI_TextMap;
+
+struct CreatureEventAI_Event
+{
+ uint32 event_id;
+
+ uint32 creature_id;
+
+ uint16 event_type;
+ uint32 event_inverse_phase_mask;
+ uint8 event_chance;
+ uint8 event_flags;
+ union
+ {
+ uint32 event_param1;
+ int32 event_param1_s;
+ };
+ union
+ {
+ uint32 event_param2;
+ int32 event_param2_s;
+ };
+ union
+ {
+ uint32 event_param3;
+ int32 event_param3_s;
+ };
+ union
+ {
+ uint32 event_param4;
+ int32 event_param4_s;
+ };
+
+ struct _action
+ {
+ uint16 type;
+ union
+ {
+ uint32 param1;
+ int32 param1_s;
+ };
+ union
+ {
+ uint32 param2;
+ int32 param2_s;
+ };
+ union
+ {
+ uint32 param3;
+ int32 param3_s;
+ };
+ }action[MAX_ACTIONS];
+};
+//Event_Map
+typedef UNORDERED_MAP<uint32, std::vector<CreatureEventAI_Event> > CreatureEventAI_Event_Map;
+
+struct CreatureEventAI_Summon
+{
+ uint32 id;
+
+ float position_x;
+ float position_y;
+ float position_z;
+ float orientation;
+ uint32 SpawnTimeSecs;
+};
+
+//EventSummon_Map
+typedef UNORDERED_MAP<uint32, CreatureEventAI_Summon> CreatureEventAI_Summon_Map;
+
+struct CreatureEventAIHolder
+{
+ CreatureEventAIHolder(CreatureEventAI_Event p) : Event(p), Time(0), Enabled(true){}
+
+ CreatureEventAI_Event Event;
+ uint32 Time;
+ bool Enabled;
+};
+
+class TRINITY_DLL_SPEC CreatureEventAI : public CreatureAI
+{
+
+ public:
+ CreatureEventAI(Creature *c);
+ ~CreatureEventAI()
+ {
+ CreatureEventAIList.clear();
+ }
+ void JustRespawned();
+ void Reset();
+ void JustReachedHome();
+ void EnterEvadeMode();
+ void JustDied(Unit* killer);
+ void KilledUnit(Unit* victim);
+ void JustSummoned(Creature* pUnit);
+ void Aggro(Unit *who);
+ void AttackStart(Unit *who);
+ void MoveInLineOfSight(Unit *who);
+ void SpellHit(Unit* pUnit, const SpellEntry* pSpell);
+ void UpdateAI(const uint32 diff);
+ static int Permissible(const Creature *);
+
+ bool ProcessEvent(CreatureEventAIHolder& pHolder, Unit* pActionInvoker = NULL);
+ void ProcessAction(uint16 type, uint32 param1, uint32 param2, uint32 param3, uint32 rnd, uint32 EventId, Unit* pActionInvoker);
+ inline uint32 GetRandActionParam(uint32 rnd, uint32 param1, uint32 param2, uint32 param3);
+ inline Unit* GetTargetByType(uint32 Target, Unit* pActionInvoker);
+ inline Unit* SelectUnit(AttackingTarget target, uint32 position);
+
+ void DoScriptText(int32 textEntry, WorldObject* pSource, Unit* target);
+ bool CanCast(Unit* Target, SpellEntry const *Spell, bool Triggered);
+ bool ReceiveEmote(Player* pPlayer, Creature* pCreature, uint32 uiEmote);
+
+ Unit* DoSelectLowestHpFriendly(float range, uint32 MinHPDiff);
+ void DoFindFriendlyMissingBuff(std::list<Creature*>& _list, float range, uint32 spellid);
+ void DoFindFriendlyCC(std::list<Creature*>& _list, float range);
+
+ //Pointer to creature we are manipulating
+ Creature& m_creature;
+
+ //Bool for if we are in combat or not
+ bool InCombat;
+
+ //Holder for events (stores enabled, time, and eventid)
+ std::list<CreatureEventAIHolder> CreatureEventAIList;
+ uint32 EventUpdateTime; //Time between event updates
+ uint32 EventDiff; //Time between the last event call
+ bool bEmptyList;
+
+ //Variables used by Events themselves
+ uint8 Phase; //Current phase, max 32 phases
+ bool CombatMovementEnabled; //If we allow targeted movment gen (movement twoards top threat)
+ bool MeleeEnabled; //If we allow melee auto attack
+ uint32 AttackDistance; //Distance to attack from
+ float AttackAngle; //Angle of attack
+
+ uint32 TimetoFleeLeft;
+ bool IsFleeing;
+};
+#endif
diff --git a/src/game/CreatureEventAIMgr.cpp b/src/game/CreatureEventAIMgr.cpp
new file mode 100644
index 00000000000..3e6c2822759
--- /dev/null
+++ b/src/game/CreatureEventAIMgr.cpp
@@ -0,0 +1,560 @@
+/*
+ * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/>
+ *
+ * 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, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include "Common.h"
+#include "Database/DatabaseEnv.h"
+#include "Database/SQLStorage.h"
+#include "CreatureEventAI.h"
+#include "CreatureEventAIMgr.h"
+#include "ObjectMgr.h"
+#include "ProgressBar.h"
+#include "Policies/SingletonImp.h"
+#include "ObjectDefines.h"
+
+INSTANTIATE_SINGLETON_1(CreatureEventAIMgr);
+
+// -------------------
+void CreatureEventAIMgr::LoadCreatureEventAI_Texts()
+{
+ // Drop Existing Text Map, only done once and we are ready to add data from multiple sources.
+ m_CreatureEventAI_TextMap.clear();
+
+ // Load EventAI Text
+ LoadTrinityStrings(WorldDatabase,"creature_ai_texts",-1,1+(TEXT_SOURCE_RANGE));
+
+ // Gather Additional data from EventAI Texts
+ QueryResult *result = WorldDatabase.PQuery("SELECT entry, sound, type, language, emote FROM creature_ai_texts");
+
+ sLog.outString("Loading EventAI Texts additional data...");
+ if (result)
+ {
+ barGoLink bar(result->GetRowCount());
+ uint32 count = 0;
+
+ do
+ {
+ bar.step();
+ Field* fields = result->Fetch();
+ StringTextData temp;
+
+ int32 i = fields[0].GetInt32();
+ temp.SoundId = fields[1].GetInt32();
+ temp.Type = fields[2].GetInt32();
+ temp.Language = fields[3].GetInt32();
+ temp.Emote = fields[4].GetInt32();
+
+ if (i >= 0)
+ {
+ sLog.outErrorDb("CreatureEventAI: Entry %i in table `creature_ai_texts` is not a negative value.",i);
+ continue;
+ }
+
+ if (i <= TEXT_SOURCE_RANGE)
+ {
+ sLog.outErrorDb("CreatureEventAI: Entry %i in table `creature_ai_texts` is out of accepted entry range for table.",i);
+ continue;
+ }
+
+ if (temp.SoundId)
+ {
+ if (!GetSoundEntriesStore()->LookupEntry(temp.SoundId))
+ sLog.outErrorDb("CreatureEventAI: Entry %i in table `creature_ai_texts` has soundId %u but sound does not exist.",i,temp.SoundId);
+ }
+
+ if (!GetLanguageDescByID(temp.Language))
+ sLog.outErrorDb("CreatureEventAI: Entry %i in table `creature_ai_texts` using Language %u but Language does not exist.",i,temp.Language);
+
+ if (temp.Type > CHAT_TYPE_BOSS_WHISPER)
+ sLog.outErrorDb("CreatureEventAI: Entry %i in table `creature_ai_texts` has Type %u but this Chat Type does not exist.",i,temp.Type);
+
+ m_CreatureEventAI_TextMap[i] = temp;
+ ++count;
+ } while (result->NextRow());
+
+ delete result;
+
+ sLog.outString();
+ sLog.outString(">> Loaded %u additional CreatureEventAI Texts data.", count);
+ }else
+ {
+ barGoLink bar(1);
+ bar.step();
+ sLog.outString();
+ sLog.outString(">> Loaded 0 additional CreatureEventAI Texts data. DB table `creature_ai_texts` is empty.");
+ }
+
+}
+
+// -------------------
+void CreatureEventAIMgr::LoadCreatureEventAI_Summons()
+{
+
+ //Drop Existing EventSummon Map
+ m_CreatureEventAI_Summon_Map.clear();
+
+ //Gather additional data for EventAI
+ QueryResult *result = WorldDatabase.PQuery("SELECT id, position_x, position_y, position_z, orientation, spawntimesecs FROM creature_ai_summons");
+ if (result)
+ {
+ barGoLink bar(result->GetRowCount());
+ uint32 Count = 0;
+
+ do
+ {
+ bar.step();
+ Field *fields = result->Fetch();
+
+ CreatureEventAI_Summon temp;
+
+ uint32 i = fields[0].GetUInt32();
+ temp.position_x = fields[1].GetFloat();
+ temp.position_y = fields[2].GetFloat();
+ temp.position_z = fields[3].GetFloat();
+ temp.orientation = fields[4].GetFloat();
+ temp.SpawnTimeSecs = fields[5].GetUInt32();
+
+ //Add to map
+ m_CreatureEventAI_Summon_Map[i] = temp;
+ ++Count;
+ }while (result->NextRow());
+
+ delete result;
+
+ sLog.outString();
+ sLog.outString(">> Loaded %u CreatureEventAI summon definitions", Count);
+ }else
+ {
+ barGoLink bar(1);
+ bar.step();
+ sLog.outString();
+ sLog.outString(">> Loaded 0 CreatureEventAI Summon definitions. DB table `creature_ai_summons` is empty.");
+ }
+
+}
+
+// -------------------
+void CreatureEventAIMgr::LoadCreatureEventAI_Scripts()
+{
+ //Drop Existing EventAI List
+ m_CreatureEventAI_Event_Map.clear();
+
+ //Gather event data
+ QueryResult *result = WorldDatabase.PQuery("SELECT id, creature_id, event_type, event_inverse_phase_mask, event_chance, event_flags, "
+ "event_param1, event_param2, event_param3, event_param4, "
+ "action1_type, action1_param1, action1_param2, action1_param3, "
+ "action2_type, action2_param1, action2_param2, action2_param3, "
+ "action3_type, action3_param1, action3_param2, action3_param3 "
+ "FROM creature_ai_scripts");
+ if (result)
+ {
+ barGoLink bar(result->GetRowCount());
+ uint32 Count = 0;
+
+ do
+ {
+ bar.step();
+ Field *fields = result->Fetch();
+
+ CreatureEventAI_Event temp;
+
+ temp.event_id = fields[0].GetUInt32();
+ uint32 i = temp.event_id;
+ temp.creature_id = fields[1].GetUInt32();
+ uint32 creature_id = temp.creature_id;
+ temp.event_type = fields[2].GetUInt16();
+ temp.event_inverse_phase_mask = fields[3].GetUInt32();
+ temp.event_chance = fields[4].GetUInt8();
+ temp.event_flags = fields[5].GetUInt8();
+ temp.event_param1 = fields[6].GetUInt32();
+ temp.event_param2 = fields[7].GetUInt32();
+ temp.event_param3 = fields[8].GetUInt32();
+ temp.event_param4 = fields[9].GetUInt32();
+
+ CreatureInfo const* cInfo = sCreatureStorage.LookupEntry<CreatureInfo>(temp.creature_id);
+ //Creature does not exist in database
+ if (!cInfo)
+ {
+ sLog.outErrorDb("CreatureEventAI: Event %u has script for non-existing creature.", i);
+ continue;
+ }
+
+ //Report any errors in event
+ if (temp.event_type >= EVENT_T_END)
+ sLog.outErrorDb("CreatureEventAI: Event %u has incorrect event type. Maybe DB requires updated version of SD2.", i);
+
+ //No chance of this event occuring
+ if (temp.event_chance == 0)
+ sLog.outErrorDb("CreatureEventAI: Event %u has 0 percent chance. Event will never trigger!", i);
+
+ //Chance above 100, force it to be 100
+ if (temp.event_chance > 100)
+ {
+ sLog.outErrorDb("CreatureEventAI: Creature %u are using event %u with more than 100 percent chance. Adjusting to 100 percent.", temp.creature_id, i);
+ temp.event_chance = 100;
+ }
+
+ //Individual event checks
+ switch (temp.event_type)
+ {
+ case EVENT_T_HP:
+ case EVENT_T_MANA:
+ case EVENT_T_TARGET_HP:
+ {
+ if (temp.event_param2 > 100)
+ sLog.outErrorDb("CreatureEventAI: Creature %u are using percentage event(%u) with param2 (MinPercent) > 100. Event will never trigger! ", temp.creature_id, i);
+
+ if (temp.event_param1 <= temp.event_param2)
+ sLog.outErrorDb("CreatureEventAI: Creature %u are using percentage event(%u) with param1 <= param2 (MaxPercent <= MinPercent). Event will never trigger! ", temp.creature_id, i);
+
+ if (temp.event_flags & EFLAG_REPEATABLE && !temp.event_param3 && !temp.event_param4)
+ {
+ sLog.outErrorDb("CreatureEventAI: Creature %u has param3 and param4=0 (RepeatMin/RepeatMax) but cannot be repeatable without timers. Removing EFLAG_REPEATABLE for event %u.", temp.creature_id, i);
+ temp.event_flags &= ~EFLAG_REPEATABLE;
+ }
+ }
+ break;
+
+ case EVENT_T_SPELLHIT:
+ {
+ if (temp.event_param1)
+ {
+ SpellEntry const* pSpell = GetSpellStore()->LookupEntry(temp.event_param1);
+ if (!pSpell)
+ {
+ sLog.outErrorDb("CreatureEventAI: Creature %u has non-existant SpellID(%u) defined in event %u.", temp.creature_id, temp.event_param1, i);
+ continue;
+ }
+
+ if (temp.event_param2_s != -1 && temp.event_param2 != pSpell->SchoolMask)
+ sLog.outErrorDb("CreatureEventAI: Creature %u has param1(spellId %u) but param2 is not -1 and not equal to spell's school mask. Event %u can never trigger.", temp.creature_id, temp.event_param1, i);
+ }
+
+ //TODO: fix this system with SPELL_SCHOOL_MASK. Current complicate things, using int32(-1) instead of just 0
+ //SPELL_SCHOOL_MASK_NONE = 0 and does not exist, thus it can not ever trigger or be used in SpellHit()
+ if (temp.event_param2_s != -1 && temp.event_param2_s > SPELL_SCHOOL_MASK_ALL)
+ sLog.outErrorDb("CreatureEventAI: Creature %u is using invalid SpellSchoolMask(%u) defined in event %u.", temp.creature_id, temp.event_param2, i);
+
+ if (temp.event_param4 < temp.event_param3)
+ sLog.outErrorDb("CreatureEventAI: Creature %u are using repeatable event(%u) with param4 < param3 (RepeatMax < RepeatMin). Event will never repeat.", temp.creature_id, i);
+ }
+ break;
+
+ case EVENT_T_RANGE:
+ case EVENT_T_OOC_LOS:
+ case EVENT_T_FRIENDLY_HP:
+ case EVENT_T_FRIENDLY_IS_CC:
+ case EVENT_T_FRIENDLY_MISSING_BUFF:
+ {
+ if (temp.event_param4 < temp.event_param3)
+ sLog.outErrorDb("CreatureEventAI: Creature %u are using repeatable event(%u) with param4 < param3 (RepeatMax < RepeatMin). Event will never repeat.", temp.creature_id, i);
+ }
+ break;
+
+ case EVENT_T_TIMER:
+ case EVENT_T_TIMER_OOC:
+ {
+ if (temp.event_param2 < temp.event_param1)
+ sLog.outErrorDb("CreatureEventAI: Creature %u are using timed event(%u) with param2 < param1 (InitialMax < InitialMin). Event will never repeat.", temp.creature_id, i);
+
+ if (temp.event_param4 < temp.event_param3)
+ sLog.outErrorDb("CreatureEventAI: Creature %u are using repeatable event(%u) with param4 < param3 (RepeatMax < RepeatMin). Event will never repeat.", temp.creature_id, i);
+ }
+ break;
+
+ case EVENT_T_KILL:
+ case EVENT_T_TARGET_CASTING:
+ {
+ if (temp.event_param2 < temp.event_param1)
+ sLog.outErrorDb("CreatureEventAI: Creature %u are using event(%u) with param2 < param1 (RepeatMax < RepeatMin). Event will never repeat.", temp.creature_id, i);
+ }
+ break;
+
+ case EVENT_T_AGGRO:
+ case EVENT_T_DEATH:
+ case EVENT_T_EVADE:
+ case EVENT_T_SPAWNED:
+ case EVENT_T_REACHED_HOME:
+ {
+ if (temp.event_flags & EFLAG_REPEATABLE)
+ {
+ sLog.outErrorDb("CreatureEventAI: Creature %u has EFLAG_REPEATABLE set. Event can never be repeatable. Removing flag for event %u.", temp.creature_id, i);
+ temp.event_flags &= ~EFLAG_REPEATABLE;
+ }
+ }
+ break;
+ }
+
+ for (uint32 j = 0; j < MAX_ACTIONS; j++)
+ {
+ temp.action[j].type = fields[10+(j*4)].GetUInt16();
+ temp.action[j].param1 = fields[11+(j*4)].GetUInt32();
+ temp.action[j].param2 = fields[12+(j*4)].GetUInt32();
+ temp.action[j].param3 = fields[13+(j*4)].GetUInt32();
+
+ //Report any errors in actions
+ switch (temp.action[j].type)
+ {
+ case ACTION_T_TEXT:
+ {
+ if (temp.action[j].param1_s < 0)
+ {
+ if (m_CreatureEventAI_TextMap.find(temp.action[j].param1_s) == m_CreatureEventAI_TextMap.end())
+ sLog.outErrorDb("CreatureEventAI: Event %u Action %u param1 refrences non-existing entry in texts table.", i, j+1);
+ }
+ if (temp.action[j].param2_s < 0)
+ {
+ if (m_CreatureEventAI_TextMap.find(temp.action[j].param2_s) == m_CreatureEventAI_TextMap.end())
+ sLog.outErrorDb("CreatureEventAI: Event %u Action %u param2 refrences non-existing entry in texts table.", i, j+1);
+
+ if (!temp.action[j].param1_s)
+ sLog.outErrorDb("CreatureEventAI: Event %u Action %u has param2, but param1 is not set. Required for randomized text.", i, j+1);
+ }
+ if (temp.action[j].param3_s < 0)
+ {
+ if (m_CreatureEventAI_TextMap.find(temp.action[j].param3_s) == m_CreatureEventAI_TextMap.end())
+ sLog.outErrorDb("CreatureEventAI: Event %u Action %u param3 refrences non-existing entry in texts table.", i, j+1);
+
+ if (!temp.action[j].param1_s || !temp.action[j].param2_s)
+ sLog.outErrorDb("CreatureEventAI: Event %u Action %u has param3, but param1 and/or param2 is not set. Required for randomized text.", i, j+1);
+ }
+ }
+ break;
+ case ACTION_T_SET_FACTION:
+ if (temp.action[j].param1 !=0 && !GetFactionStore()->LookupEntry(temp.action[j].param1))
+ {
+ sLog.outErrorDb("CreatureEventAI: Event %u Action %u uses non-existant FactionId %u.", i, j+1, temp.action[j].param1);
+ temp.action[j].param1 = 0;
+ }
+ break;
+ case ACTION_T_MORPH_TO_ENTRY_OR_MODEL:
+ if (temp.action[j].param1 !=0 || temp.action[j].param2 !=0)
+ {
+ if (temp.action[j].param1 && !GetCreatureTemplateStore(temp.action[j].param1))
+ {
+ sLog.outErrorDb("CreatureEventAI: Event %u Action %u uses non-existant Creature entry %u.", i, j+1, temp.action[j].param1);
+ temp.action[j].param1 = 0;
+ }
+
+ if (temp.action[j].param2 && !GetCreatureDisplayStore()->LookupEntry(temp.action[j].param2))
+ {
+ sLog.outErrorDb("CreatureEventAI: Event %u Action %u uses non-existant ModelId %u.", i, j+1, temp.action[j].param2);
+ temp.action[j].param2 = 0;
+ }
+ }
+ break;
+ case ACTION_T_SOUND:
+ if (!GetSoundEntriesStore()->LookupEntry(temp.action[j].param1))
+ sLog.outErrorDb("CreatureEventAI: Event %u Action %u uses non-existant SoundID %u.", i, j+1, temp.action[j].param1);
+ break;
+/*
+ case ACTION_T_RANDOM_SOUND:
+ {
+ if(!GetSoundEntriesStore()->LookupEntry(temp.action[j].param1))
+ sLog.outErrorDb("CreatureEventAI: Event %u Action %u param1 uses non-existant SoundID %u.", i, j+1, temp.action[j].param1);
+ if(!GetSoundEntriesStore()->LookupEntry(temp.action[j].param2))
+ sLog.outErrorDb("CreatureEventAI: Event %u Action %u param2 uses non-existant SoundID %u.", i, j+1, temp.action[j].param2);
+ if(!GetSoundEntriesStore()->LookupEntry(temp.action[j].param3))
+ sLog.outErrorDb("CreatureEventAI: Event %u Action %u param3 uses non-existant SoundID %u.", i, j+1, temp.action[j].param3);
+ }
+ break;
+ */
+ case ACTION_T_CAST:
+ {
+ const SpellEntry *spell = GetSpellStore()->LookupEntry(temp.action[j].param1);
+ if (!spell)
+ sLog.outErrorDb("CreatureEventAI: Event %u Action %u uses non-existant SpellID %u.", i, j+1, temp.action[j].param1);
+ else
+ {
+ if (spell->RecoveryTime > 0 && temp.event_flags & EFLAG_REPEATABLE)
+ {
+ //output as debug for now, also because there's no general rule all spells have RecoveryTime
+ if (temp.event_param3 < spell->RecoveryTime)
+ debug_log("CreatureEventAI: Event %u Action %u uses SpellID %u but cooldown is longer(%u) than minumum defined in event param3(%u).", i, j+1,temp.action[j].param1, spell->RecoveryTime, temp.event_param3);
+ }
+ }
+
+ if (temp.action[j].param2 >= TARGET_T_END)
+ sLog.outErrorDb("CreatureEventAI: Event %u Action %u uses incorrect Target type", i, j+1);
+ }
+ break;
+ case ACTION_T_REMOVEAURASFROMSPELL:
+ {
+ if (!GetSpellStore()->LookupEntry(temp.action[j].param2))
+ sLog.outErrorDb("CreatureEventAI: Event %u Action %u uses non-existant SpellID %u.", i, j+1, temp.action[j].param2);
+
+ if (temp.action[j].param1 >= TARGET_T_END)
+ sLog.outErrorDb("CreatureEventAI: Event %u Action %u uses incorrect Target type", i, j+1);
+ }
+ break;
+ case ACTION_T_QUEST_EVENT:
+ {
+ if (Quest const* qid = GetQuestTemplateStore(temp.action[j].param1))
+ {
+ if (!qid->HasFlag(QUEST_TRINITY_FLAGS_EXPLORATION_OR_EVENT))
+ sLog.outErrorDb("CreatureEventAI: Event %u Action %u. SpecialFlags for quest entry %u does not include |2, Action will not have any effect.", i, j+1, temp.action[j].param1);
+ }
+ else
+ sLog.outErrorDb("CreatureEventAI: Event %u Action %u uses non-existant Quest entry %u.", i, j+1, temp.action[j].param1);
+
+ if (temp.action[j].param2 >= TARGET_T_END)
+ sLog.outErrorDb("CreatureEventAI: Event %u Action %u uses incorrect Target type", i, j+1);
+ }
+ break;
+ case ACTION_T_QUEST_EVENT_ALL:
+ {
+ if (Quest const* qid = GetQuestTemplateStore(temp.action[j].param1))
+ {
+ if (!qid->HasFlag(QUEST_TRINITY_FLAGS_EXPLORATION_OR_EVENT))
+ sLog.outErrorDb("CreatureEventAI: Event %u Action %u. SpecialFlags for quest entry %u does not include |2, Action will not have any effect.", i, j+1, temp.action[j].param1);
+ }
+ else
+ sLog.outErrorDb("CreatureEventAI: Event %u Action %u uses non-existant Quest entry %u.", i, j+1, temp.action[j].param1);
+ }
+ break;
+ case ACTION_T_CASTCREATUREGO:
+ {
+ if (!GetCreatureTemplateStore(temp.action[j].param1))
+ sLog.outErrorDb("CreatureEventAI: Event %u Action %u uses non-existant creature entry %u.", i, j+1, temp.action[j].param1);
+
+ if (!GetSpellStore()->LookupEntry(temp.action[j].param2))
+ sLog.outErrorDb("CreatureEventAI: Event %u Action %u uses non-existant SpellID %u.", i, j+1, temp.action[j].param2);
+
+ if (temp.action[j].param3 >= TARGET_T_END)
+ sLog.outErrorDb("CreatureEventAI: Event %u Action %u uses incorrect Target type", i, j+1);
+ }
+ break;
+ case ACTION_T_CASTCREATUREGO_ALL:
+ {
+ if (!GetQuestTemplateStore(temp.action[j].param1))
+ sLog.outErrorDb("CreatureEventAI: Event %u Action %u uses non-existant Quest entry %u.", i, j+1, temp.action[j].param1);
+
+ if (!GetSpellStore()->LookupEntry(temp.action[j].param2))
+ sLog.outErrorDb("CreatureEventAI: Event %u Action %u uses non-existant SpellID %u.", i, j+1, temp.action[j].param2);
+ }
+ break;
+
+ //2nd param target
+ case ACTION_T_SUMMON_ID:
+ {
+ if (!GetCreatureTemplateStore(temp.action[j].param1))
+ sLog.outErrorDb("CreatureEventAI: Event %u Action %u uses non-existant creature entry %u.", i, j+1, temp.action[j].param1);
+
+ if (m_CreatureEventAI_Summon_Map.find(temp.action[j].param3) == m_CreatureEventAI_Summon_Map.end())
+ sLog.outErrorDb("CreatureEventAI: Event %u Action %u summons missing CreatureEventAI_Summon %u", i, j+1, temp.action[j].param3);
+
+ if (temp.action[j].param2 >= TARGET_T_END)
+ sLog.outErrorDb("CreatureEventAI: Event %u Action %u uses incorrect Target type", i, j+1);
+ }
+ break;
+ case ACTION_T_KILLED_MONSTER:
+ {
+ if (!GetCreatureTemplateStore(temp.action[j].param1))
+ sLog.outErrorDb("CreatureEventAI: Event %u Action %u uses non-existant creature entry %u.", i, j+1, temp.action[j].param1);
+
+ if (temp.action[j].param2 >= TARGET_T_END)
+ sLog.outErrorDb("CreatureEventAI: Event %u Action %u uses incorrect Target type", i, j+1);
+ }
+ break;
+ case ACTION_T_SUMMON:
+ {
+ if (!GetCreatureTemplateStore(temp.action[j].param1))
+ sLog.outErrorDb("CreatureEventAI: Event %u Action %u uses non-existant creature entry %u.", i, j+1, temp.action[j].param1);
+
+ if (temp.action[j].param2 >= TARGET_T_END)
+ sLog.outErrorDb("CreatureEventAI: Event %u Action %u uses incorrect Target type", i, j+1);
+ }
+ break;
+ case ACTION_T_THREAT_SINGLE_PCT:
+ case ACTION_T_SET_UNIT_FLAG:
+ case ACTION_T_REMOVE_UNIT_FLAG:
+ if (temp.action[j].param2 >= TARGET_T_END)
+ sLog.outErrorDb("CreatureEventAI: Event %u Action %u uses incorrect Target type", i, j+1);
+ break;
+
+ //3rd param target
+ case ACTION_T_SET_UNIT_FIELD:
+ if (temp.action[j].param1 < OBJECT_END || temp.action[j].param1 >= UNIT_END)
+ sLog.outErrorDb("CreatureEventAI: Event %u Action %u param1 (UNIT_FIELD*). Index out of range for intended use.", i, j+1);
+ if (temp.action[j].param3 >= TARGET_T_END)
+ sLog.outErrorDb("CreatureEventAI: Event %u Action %u uses incorrect Target type", i, j+1);
+ break;
+
+ case ACTION_T_SET_PHASE:
+ if (temp.action[j].param1 > 31)
+ sLog.outErrorDb("CreatureEventAI: Event %u Action %u attempts to set phase > 31. Phase mask cannot be used past phase 31.", i, j+1);
+ break;
+
+ case ACTION_T_INC_PHASE:
+ if (!temp.action[j].param1)
+ sLog.outErrorDb("CreatureEventAI: Event %u Action %u is incrementing phase by 0. Was this intended?", i, j+1);
+ break;
+
+ case ACTION_T_SET_INST_DATA:
+ {
+ if (!(temp.event_flags & EFLAG_NORMAL) && !(temp.event_flags & EFLAG_HEROIC))
+ sLog.outErrorDb("CreatureEventAI: Event %u Action %u. Cannot set instance data without event flags (normal/heroic).", i, j+1);
+
+ if (temp.action[j].param2 > 4/*SPECIAL*/)
+ sLog.outErrorDb("CreatureEventAI: Event %u Action %u attempts to set instance data above encounter state 4. Custom case?", i, j+1);
+ }
+ break;
+ case ACTION_T_SET_INST_DATA64:
+ {
+ if (!(temp.event_flags & EFLAG_NORMAL) && !(temp.event_flags & EFLAG_HEROIC))
+ sLog.outErrorDb("CreatureEventAI: Event %u Action %u. Cannot set instance data without event flags (normal/heroic).", i, j+1);
+
+ if (temp.action[j].param2 >= TARGET_T_END)
+ sLog.outErrorDb("CreatureEventAI: Event %u Action %u uses incorrect Target type", i, j+1);
+ }
+ break;
+ case ACTION_T_UPDATE_TEMPLATE:
+ {
+ if (!GetCreatureTemplateStore(temp.action[j].param1))
+ sLog.outErrorDb("CreatureEventAI: Event %u Action %u uses non-existant creature entry %u.", i, j+1, temp.action[j].param1);
+ }
+ break;
+ case ACTION_T_RANDOM_SAY:
+ case ACTION_T_RANDOM_YELL:
+ case ACTION_T_RANDOM_TEXTEMOTE:
+ sLog.outErrorDb("CreatureEventAI: Event %u Action %u currently unused ACTION type. Did you forget to update database?", i, j+1);
+ break;
+
+ default:
+ if (temp.action[j].type >= ACTION_T_END)
+ sLog.outErrorDb("CreatureEventAI: Event %u Action %u has incorrect action type. Maybe DB requires updated version of SD2.", i, j+1);
+ break;
+ }
+ }
+
+ //Add to list
+ m_CreatureEventAI_Event_Map[creature_id].push_back(temp);
+ ++Count;
+ } while (result->NextRow());
+
+ delete result;
+
+ sLog.outString();
+ sLog.outString(">> Loaded %u CreatureEventAI scripts", Count);
+ }else
+ {
+ barGoLink bar(1);
+ bar.step();
+ sLog.outString();
+ sLog.outString(">> Loaded 0 CreatureEventAI scripts. DB table `creature_ai_scripts` is empty.");
+ }
+}
diff --git a/src/game/CreatureEventAIMgr.h b/src/game/CreatureEventAIMgr.h
new file mode 100644
index 00000000000..ea5989a74ed
--- /dev/null
+++ b/src/game/CreatureEventAIMgr.h
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/>
+ *
+ * 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, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef MANGOS_CREATURE_EAI_MGR_H
+#define MANGOS_CREATURE_EAI_MGR_H
+
+#include "Common.h"
+#include "CreatureEventAI.h"
+
+class CreatureEventAIMgr
+{
+ public:
+ CreatureEventAIMgr(){};
+ ~CreatureEventAIMgr(){};
+
+ void LoadCreatureEventAI_Texts();
+ void LoadCreatureEventAI_Summons();
+ void LoadCreatureEventAI_Scripts();
+
+ CreatureEventAI_Event_Map& GetCreatureEventAIMap() { return m_CreatureEventAI_Event_Map; }
+ CreatureEventAI_Summon_Map& GetCreatureEventAISummonMap() { return m_CreatureEventAI_Summon_Map; }
+ CreatureEventAI_TextMap& GetCreatureEventAITextMap() { return m_CreatureEventAI_TextMap; }
+
+ private:
+ CreatureEventAI_Event_Map m_CreatureEventAI_Event_Map;
+ CreatureEventAI_Summon_Map m_CreatureEventAI_Summon_Map;
+ CreatureEventAI_TextMap m_CreatureEventAI_TextMap;
+};
+
+#define CreatureEAI_Mgr MaNGOS::Singleton<CreatureEventAIMgr>::Instance()
+#endif
diff --git a/src/game/CreatureGroups.cpp b/src/game/CreatureGroups.cpp
index ed0fde19eb0..3b7a27cdab5 100644
--- a/src/game/CreatureGroups.cpp
+++ b/src/game/CreatureGroups.cpp
@@ -23,62 +23,52 @@
#include "ObjectMgr.h"
#include "ProgressBar.h"
#include "Policies/SingletonImp.h"
+#include "CreatureAI.h"
#define MAX_DESYNC 5.0f
INSTANTIATE_SINGLETON_1(CreatureGroupManager);
-CreatureGroupHolderType CreatureGroupHolder;
CreatureGroupInfoType CreatureGroupMap;
-void CreatureGroupManager::AddCreatureToGroup(uint32 group_id, Creature *member)
+void CreatureGroupManager::AddCreatureToGroup(uint32 groupId, Creature *member)
{
- CreatureGroupHolderType::iterator cgroup_data = CreatureGroupHolder.find(group_id);
+ Map *map = member->FindMap();
+ if(!map)
+ return;
+
+ CreatureGroupHolderType::iterator itr = map->CreatureGroupHolder.find(groupId);
//Add member to an existing group
- if(cgroup_data != CreatureGroupHolder.end())
+ if(itr != map->CreatureGroupHolder.end())
{
- typedef std::multimap<uint32, CreatureGroup *>::iterator multiplegroup;
- std::pair<multiplegroup, multiplegroup> range = CreatureGroupHolder.equal_range(group_id);
-
- for(multiplegroup i = range.first; i != range.second; ++i)
- {
- if(i->second->getInstanceID() == member->GetInstanceId())
- {
- sLog.outDebug("Group found: %u, inserting creature GUID: %u, Group InstanceID %u", group_id, member->GetGUIDLow(), i->second->getInstanceID());
- i->second->AddMember(member);
- return;
- }
- }
+ sLog.outDebug("Group found: %u, inserting creature GUID: %u, Group InstanceID %u", groupId, member->GetGUIDLow(), member->GetInstanceId());
+ itr->second->AddMember(member);
}
-
//Create new group
- sLog.outDebug("Group not found: %u. Creating new group.", group_id);
- CreatureGroup* cgroup = new CreatureGroup(group_id, member->GetInstanceId());
- CreatureGroupHolder.insert(std::make_pair(group_id, cgroup));
- cgroup->AddMember(member);
+ else
+ {
+ sLog.outDebug("Group not found: %u. Creating new group.", groupId);
+ CreatureGroup* group = new CreatureGroup(groupId);
+ map->CreatureGroupHolder[groupId] = group;
+ group->AddMember(member);
+ }
}
-void CreatureGroupManager::RemoveCreatureFromGroup(CreatureGroup *formation, Creature *member)
+void CreatureGroupManager::RemoveCreatureFromGroup(CreatureGroup *group, Creature *member)
{
- sLog.outDebug("Deleting member pointer to GUID: %u from group %u", formation->GetId(), member->GetDBTableGUIDLow());
- formation->RemoveMember(member);
+ sLog.outDebug("Deleting member pointer to GUID: %u from group %u", group->GetId(), member->GetDBTableGUIDLow());
+ group->RemoveMember(member);
- if(formation->isEmpty())
+ if(group->isEmpty())
{
- uint32 id = formation->GetId();
- typedef std::multimap<uint32, CreatureGroup *>::iterator multiplegroup;
- std::pair<multiplegroup, multiplegroup> range = CreatureGroupHolder.equal_range(id);
+ Map *map = member->FindMap();
+ if(!map)
+ return;
- for(multiplegroup i = range.first; i != range.second; ++i)
- {
- if(i->second == formation)
- {
- sLog.outDebug("Deleting group with InstanceID %u", i->second->getInstanceID());
- CreatureGroupHolder.erase(i);
- delete formation;
- }
- }
+ sLog.outDebug("Deleting group with InstanceID %u", member->GetInstanceId());
+ map->CreatureGroupHolder.erase(group->GetId());
+ delete group;
}
}
@@ -244,7 +234,11 @@ void CreatureGroup::LeaderMoveTo(float x, float y, float z)
float dx = x + cos(angle + pathangle) * dist;
float dy = y + sin(angle + pathangle) * dist;
- float dz;
+ float dz = z;
+
+ Trinity::NormalizeMapCoord(dx);
+ Trinity::NormalizeMapCoord(dy);
+
member->UpdateGroundPositionZ(dx, dy, dz);
if(member->GetDistance(m_leader) < dist + MAX_DESYNC)
diff --git a/src/game/CreatureGroups.h b/src/game/CreatureGroups.h
index aba86ffcaac..8c345aadd40 100644
--- a/src/game/CreatureGroups.h
+++ b/src/game/CreatureGroups.h
@@ -41,10 +41,8 @@ class CreatureGroupManager
void LoadCreatureFormations();
};
-typedef std::multimap<uint32/*leaderDBGUID*/, CreatureGroup*> CreatureGroupHolderType;
typedef UNORDERED_MAP<uint32/*memberDBGUID*/, FormationInfo*> CreatureGroupInfoType;
-extern CreatureGroupHolderType CreatureGroupHolder;
extern CreatureGroupInfoType CreatureGroupMap;
class CreatureGroup
@@ -54,17 +52,16 @@ class CreatureGroup
typedef std::map<Creature*, FormationInfo*> CreatureGroupMemberType;
CreatureGroupMemberType m_members;
- uint32 m_groupID, mInstanceID;
+ uint32 m_groupID;
bool m_Formed;
public:
//Group cannot be created empty
- explicit CreatureGroup(uint32 id, uint32 InstanceID) : m_groupID(id), m_leader(NULL), mInstanceID(InstanceID), m_Formed(false) {}
- ~CreatureGroup(){sLog.outDebug("Destroying group");}
+ explicit CreatureGroup(uint32 id) : m_groupID(id), m_leader(NULL), m_Formed(false) {}
+ ~CreatureGroup() { sLog.outDebug("Destroying group"); }
Creature* getLeader() const { return m_leader; }
uint32 GetId() const { return m_groupID; }
- uint32 getInstanceID() const { return mInstanceID; }
bool isEmpty() const { return m_members.empty(); }
bool isFormed() const { return m_Formed; }
diff --git a/src/game/DBCEnums.h b/src/game/DBCEnums.h
index c3139dc2a37..078804c19f4 100644
--- a/src/game/DBCEnums.h
+++ b/src/game/DBCEnums.h
@@ -45,9 +45,9 @@ enum AchievementFlags
ACHIEVEMENT_FLAG_COUNTER = 0x00000001, // Just count statistic (never stop and complete)
ACHIEVEMENT_FLAG_UNK2 = 0x00000002, // not used
ACHIEVEMENT_FLAG_STORE_MAX_VALUE = 0x00000004, // Store only max value? used only in "Reach level xx"
- ACHIEVEMENT_FLAG_SUMM = 0x00000008, // Use summ criteria value from all reqirements (and calculate max vale)
- ACHIEVEMENT_FLAG_MAX_USED = 0x00000010, // Show max criteria (and calculate max vale ??)
- ACHIEVEMENT_FLAG_REQ_COUNT = 0x00000020, // Use not zero req count (and calculate max vale)
+ ACHIEVEMENT_FLAG_SUMM = 0x00000008, // Use summ criteria value from all reqirements (and calculate max value)
+ ACHIEVEMENT_FLAG_MAX_USED = 0x00000010, // Show max criteria (and calculate max value ??)
+ ACHIEVEMENT_FLAG_REQ_COUNT = 0x00000020, // Use not zero req count (and calculate max value)
ACHIEVEMENT_FLAG_AVERANGE = 0x00000040, // Show as averange value (value / time_in_days) depend from other flag (by def use last criteria value)
ACHIEVEMENT_FLAG_BAR = 0x00000080, // Show as progress bar (value / max vale) depend from other flag (by def use last criteria value)
ACHIEVEMENT_FLAG_REALM_FIRST_REACH = 0x00000100, //
diff --git a/src/game/DBCStructure.h b/src/game/DBCStructure.h
index c46de44bf1f..7d3dea72ccf 100644
--- a/src/game/DBCStructure.h
+++ b/src/game/DBCStructure.h
@@ -479,7 +479,7 @@ struct AchievementCriteriaEntry
struct
{
uint32 field3; // 3 main requirement
- uint32 field4; // 4 main requirement count
+ uint32 count; // 4 main requirement count
uint32 additionalRequirement1_type; // 5 additional requirement 1 type
uint32 additionalRequirement1_value; // 6 additional requirement 1 value
uint32 additionalRequirement2_type; // 7 additional requirement 2 type
diff --git a/src/game/GameObject.cpp b/src/game/GameObject.cpp
index def17130372..89a03cac016 100644
--- a/src/game/GameObject.cpp
+++ b/src/game/GameObject.cpp
@@ -610,37 +610,34 @@ bool GameObject::LoadFromDB(uint32 guid, Map *map)
if (!Create(guid,entry, map, phaseMask, x, y, z, ang, rotation0, rotation1, rotation2, rotation3, animprogress, go_state, ArtKit) )
return false;
- switch(GetGOInfo()->type)
+ if(!GetDespawnPossibility())
{
- case GAMEOBJECT_TYPE_DOOR:
- case GAMEOBJECT_TYPE_BUTTON:
- /* this code (in comment) isn't correct because in battlegrounds we need despawnable doors and buttons, pls remove
- SetFlag(GAMEOBJECT_FLAGS, GO_FLAG_NODESPAWN);
+ SetFlag(GAMEOBJECT_FLAGS, GO_FLAG_NODESPAWN);
+ m_spawnedByDefault = true;
+ m_respawnDelayTime = 0;
+ m_respawnTime = 0;
+ }
+ else
+ {
+ if(data->spawntimesecs >= 0)
+ {
m_spawnedByDefault = true;
- m_respawnDelayTime = 0;
- m_respawnTime = 0;
- break;*/
- default:
- if(data->spawntimesecs >= 0)
- {
- m_spawnedByDefault = true;
- m_respawnDelayTime = data->spawntimesecs;
- m_respawnTime = objmgr.GetGORespawnTime(m_DBTableGuid, map->GetInstanceId());
+ m_respawnDelayTime = data->spawntimesecs;
+ m_respawnTime = objmgr.GetGORespawnTime(m_DBTableGuid, map->GetInstanceId());
- // ready to respawn
- if(m_respawnTime && m_respawnTime <= time(NULL))
- {
- m_respawnTime = 0;
- objmgr.SaveGORespawnTime(m_DBTableGuid,GetInstanceId(),0);
- }
- }
- else
+ // ready to respawn
+ if(m_respawnTime && m_respawnTime <= time(NULL))
{
- m_spawnedByDefault = false;
- m_respawnDelayTime = -data->spawntimesecs;
m_respawnTime = 0;
+ objmgr.SaveGORespawnTime(m_DBTableGuid,GetInstanceId(),0);
}
- break;
+ }
+ else
+ {
+ m_spawnedByDefault = false;
+ m_respawnDelayTime = -data->spawntimesecs;
+ m_respawnTime = 0;
+ }
}
return true;
diff --git a/src/game/GameObject.h b/src/game/GameObject.h
index 3d2d3c2de57..b0019048827 100644
--- a/src/game/GameObject.h
+++ b/src/game/GameObject.h
@@ -482,6 +482,20 @@ class TRINITY_DLL_SPEC GameObject : public WorldObject
}
}
+ bool GetDespawnPossibility() const
+ {
+ switch(GetGoType())
+ {
+ case GAMEOBJECT_TYPE_DOOR: return GetGOInfo()->door.noDamageImmune;
+ case GAMEOBJECT_TYPE_BUTTON: return GetGOInfo()->button.noDamageImmune;
+ case GAMEOBJECT_TYPE_QUESTGIVER: return GetGOInfo()->questgiver.noDamageImmune;
+ case GAMEOBJECT_TYPE_GOOBER: return GetGOInfo()->goober.noDamageImmune;
+ case GAMEOBJECT_TYPE_FLAGSTAND: return GetGOInfo()->flagstand.noDamageImmune;
+ case GAMEOBJECT_TYPE_FLAGDROP: return GetGOInfo()->flagdrop.noDamageImmune;
+ default: return true;
+ }
+ }
+
time_t GetRespawnTime() const { return m_respawnTime; }
time_t GetRespawnTimeEx() const
{
diff --git a/src/game/GridNotifiers.h b/src/game/GridNotifiers.h
index a7b8c753782..521a543c08c 100644
--- a/src/game/GridNotifiers.h
+++ b/src/game/GridNotifiers.h
@@ -628,6 +628,62 @@ namespace Trinity
// Unit checks
+ class MostHPMissingInRange
+ {
+ public:
+ MostHPMissingInRange(Unit const* obj, float range, uint32 hp) : i_obj(obj), i_range(range), i_hp(hp) {}
+ bool operator()(Unit* u)
+ {
+ if(u->isAlive() && u->isInCombat() && !i_obj->IsHostileTo(u) && i_obj->IsWithinDistInMap(u, i_range) && u->GetMaxHealth() - u->GetHealth() > i_hp)
+ {
+ i_hp = u->GetMaxHealth() - u->GetHealth();
+ return true;
+ }
+ return false;
+ }
+ private:
+ Unit const* i_obj;
+ float i_range;
+ uint32 i_hp;
+ };
+
+ class FriendlyCCedInRange
+ {
+ public:
+ FriendlyCCedInRange(Unit const* obj, float range) : i_obj(obj), i_range(range) {}
+ bool operator()(Unit* u)
+ {
+ if(u->isAlive() && u->isInCombat() && !i_obj->IsHostileTo(u) && i_obj->IsWithinDistInMap(u, i_range) &&
+ (u->isFeared() || u->isCharmed() || u->isFrozen() || u->hasUnitState(UNIT_STAT_STUNNED) || u->hasUnitState(UNIT_STAT_CONFUSED)))
+ {
+ return true;
+ }
+ return false;
+ }
+ private:
+ Unit const* i_obj;
+ float i_range;
+ };
+
+ class FriendlyMissingBuffInRange
+ {
+ public:
+ FriendlyMissingBuffInRange(Unit const* obj, float range, uint32 spellid) : i_obj(obj), i_range(range), i_spell(spellid) {}
+ bool operator()(Unit* u)
+ {
+ if(u->isAlive() && u->isInCombat() && !i_obj->IsHostileTo(u) && i_obj->IsWithinDistInMap(u, i_range) &&
+ !(u->HasAura(i_spell, 0) || u->HasAura(i_spell, 1) || u->HasAura(i_spell, 2)))
+ {
+ return true;
+ }
+ return false;
+ }
+ private:
+ Unit const* i_obj;
+ float i_range;
+ uint32 i_spell;
+ };
+
class AnyUnfriendlyUnitInObjectRangeCheck
{
public:
@@ -915,63 +971,6 @@ namespace Trinity
float i_range;
};
- // Searchers used by ScriptedAI
- class MostHPMissingInRange
- {
- public:
- MostHPMissingInRange(Unit const* obj, float range, uint32 hp) : i_obj(obj), i_range(range), i_hp(hp) {}
- bool operator()(Unit* u)
- {
- if(u->isAlive() && u->isInCombat() && !i_obj->IsHostileTo(u) && i_obj->IsWithinDistInMap(u, i_range) && u->GetMaxHealth() - u->GetHealth() > i_hp)
- {
- i_hp = u->GetMaxHealth() - u->GetHealth();
- return true;
- }
- return false;
- }
- private:
- Unit const* i_obj;
- float i_range;
- uint32 i_hp;
- };
-
- class FriendlyCCedInRange
- {
- public:
- FriendlyCCedInRange(Unit const* obj, float range) : i_obj(obj), i_range(range) {}
- bool operator()(Unit* u)
- {
- if(u->isAlive() && u->isInCombat() && !i_obj->IsHostileTo(u) && i_obj->IsWithinDistInMap(u, i_range) &&
- (u->isFeared() || u->isCharmed() || u->isFrozen() || u->hasUnitState(UNIT_STAT_STUNNED) || u->hasUnitState(UNIT_STAT_CONFUSED)))
- {
- return true;
- }
- return false;
- }
- private:
- Unit const* i_obj;
- float i_range;
- };
-
- class FriendlyMissingBuffInRange
- {
- public:
- FriendlyMissingBuffInRange(Unit const* obj, float range, uint32 spellid) : i_obj(obj), i_range(range), i_spell(spellid) {}
- bool operator()(Unit* u)
- {
- if(u->isAlive() && u->isInCombat() && /*!i_obj->IsHostileTo(u)*/ i_obj->IsFriendlyTo(u) && i_obj->IsWithinDistInMap(u, i_range) &&
- !(u->HasAura(i_spell)))
- {
- return true;
- }
- return false;
- }
- private:
- Unit const* i_obj;
- float i_range;
- uint32 i_spell;
- };
-
class AllFriendlyCreaturesInGrid
{
public:
diff --git a/src/game/HomeMovementGenerator.cpp b/src/game/HomeMovementGenerator.cpp
index 17174919b15..4f0ca2f8cec 100644
--- a/src/game/HomeMovementGenerator.cpp
+++ b/src/game/HomeMovementGenerator.cpp
@@ -69,7 +69,7 @@ HomeMovementGenerator<Creature>::Update(Creature &owner, const uint32& time_diff
// restore orientation of not moving creature at returning to home
if(owner.GetDefaultMovementType()==IDLE_MOTION_TYPE)
{
- sLog.outDebug("Entering HomeMovement::GetDestination(z,y,z)");
+ //sLog.outDebug("Entering HomeMovement::GetDestination(z,y,z)");
owner.SetOrientation(ori);
WorldPacket packet;
owner.BuildHeartBeatMsg(&packet);
diff --git a/src/game/InstanceData.h b/src/game/InstanceData.h
index b2571de66bd..c33beccfffb 100644
--- a/src/game/InstanceData.h
+++ b/src/game/InstanceData.h
@@ -67,6 +67,10 @@ class TRINITY_DLL_SPEC InstanceData
//called on creature creation
virtual void OnCreatureCreate(Creature * /*creature*/, uint32 /*creature_entry*/) {}
+ //All-purpose data storage 64 bit
+ virtual uint64 GetData64(uint32 /*Data*/) { return 0; }
+ virtual void SetData64(uint32 /*Data*/, uint64 /*Value*/) { }
+
//All-purpose data storage 32 bit
virtual uint32 GetData(uint32) { return 0; }
virtual void SetData(uint32, uint32 data) {}
diff --git a/src/game/Language.h b/src/game/Language.h
index 51df64227f8..8217193ea50 100644
--- a/src/game/Language.h
+++ b/src/game/Language.h
@@ -84,7 +84,8 @@ enum TrinityStrings
LANG_MOTD_CURRENT = 56,
LANG_USING_WORLD_DB = 57,
LANG_USING_SCRIPT_LIB = 58,
- // Room for more level 0 59-99 not used
+ LANG_USING_EVENT_AI = 59,
+ // Room for more level 0 60-99 not used
// level 1 chat
LANG_GLOBAL_NOTIFY = 100,
diff --git a/src/game/Level0.cpp b/src/game/Level0.cpp
index 50aa1e46538..5f8a6cf86ef 100644
--- a/src/game/Level0.cpp
+++ b/src/game/Level0.cpp
@@ -102,6 +102,7 @@ bool ChatHandler::HandleServerInfoCommand(const char* /*args*/)
//SendSysMessage(full);
//PSendSysMessage(LANG_USING_SCRIPT_LIB,sWorld.GetScriptsVersion());
//PSendSysMessage(LANG_USING_WORLD_DB,sWorld.GetDBVersion());
+ //PSendSysMessage(LANG_USING_EVENT_AI,sWorld.GetCreatureEventAIVersion());
PSendSysMessage(LANG_CONNECTED_USERS, activeClientsNum, maxActiveClientsNum, queuedClientsNum, maxQueuedClientsNum);
PSendSysMessage(LANG_UPTIME, str.c_str());
PSendSysMessage("Update time diff: %u.", updateTime);
diff --git a/src/game/Level3.cpp b/src/game/Level3.cpp
index 10b0cd198a0..8122166ef31 100644
--- a/src/game/Level3.cpp
+++ b/src/game/Level3.cpp
@@ -529,6 +529,7 @@ bool ChatHandler::HandleReloadAllCommand(const char*)
{
HandleReloadSkillFishingBaseLevelCommand("");
+ HandleReloadAllAchievementCommand("");
HandleReloadAllAreaCommand("");
HandleReloadAllLootCommand("");
HandleReloadAllNpcCommand("");
@@ -544,6 +545,13 @@ bool ChatHandler::HandleReloadAllCommand(const char*)
return true;
}
+bool ChatHandler::HandleReloadAllAchievementCommand(const char*)
+{
+ HandleReloadAchievementCriteriaDataCommand("");
+ HandleReloadAchievementRewardCommand("");
+ return true;
+}
+
bool ChatHandler::HandleReloadAllAreaCommand(const char*)
{
//HandleReloadQuestAreaTriggersCommand(""); -- reloaded in HandleReloadAllQuestCommand
@@ -632,6 +640,7 @@ bool ChatHandler::HandleReloadAllItemCommand(const char*)
bool ChatHandler::HandleReloadAllLocalesCommand(const char* /*args*/)
{
+ HandleReloadLocalesAchievementRewardCommand("a");
HandleReloadLocalesCreatureCommand("a");
HandleReloadLocalesGameobjectCommand("a");
HandleReloadLocalesItemCommand("a");
@@ -650,6 +659,22 @@ bool ChatHandler::HandleReloadConfigCommand(const char* /*args*/)
return true;
}
+bool ChatHandler::HandleReloadAchievementCriteriaDataCommand(const char*)
+{
+ sLog.outString( "Re-Loading Additional Achievement Criteria Data..." );
+ achievementmgr.LoadAchievementCriteriaData();
+ SendGlobalSysMessage("DB table `achievement_criteria_data` reloaded.");
+ return true;
+}
+
+bool ChatHandler::HandleReloadAchievementRewardCommand(const char*)
+{
+ sLog.outString( "Re-Loading Achievement Reward Data..." );
+ achievementmgr.LoadRewards();
+ SendGlobalSysMessage("DB table `achievement_reward` reloaded.");
+ return true;
+}
+
bool ChatHandler::HandleReloadAreaTriggerTavernCommand(const char*)
{
sLog.outString( "Re-Loading Tavern Area Triggers..." );
@@ -1194,6 +1219,14 @@ bool ChatHandler::HandleReloadSpellDisabledCommand(const char* /*arg*/)
return true;
}
+bool ChatHandler::HandleReloadLocalesAchievementRewardCommand(const char*)
+{
+ sLog.outString( "Re-Loading Locales Achievement Reward Data..." );
+ achievementmgr.LoadRewardLocales();
+ SendGlobalSysMessage("DB table `locales_achievement_reward` reloaded.");
+ return true;
+}
+
bool ChatHandler::HandleReloadLocalesCreatureCommand(const char* /*arg*/)
{
sLog.outString( "Re-Loading Locales Creature ...");
diff --git a/src/game/Makefile.am b/src/game/Makefile.am
index de27815594a..47c072a1188 100644
--- a/src/game/Makefile.am
+++ b/src/game/Makefile.am
@@ -31,6 +31,7 @@ noinst_LIBRARIES = libmangosgame.a
# libmangossgame library will later be reused by ...
libmangosgame_a_SOURCES = \
<<<<<<< HEAD:src/game/Makefile.am
+<<<<<<< HEAD:src/game/Makefile.am
AccountMgr.cpp \
AccountMgr.h \
AchievementMgr.h \
@@ -572,6 +573,272 @@ libmangosgame_a_SOURCES = \
GroupReference.h \
GroupRefManager.h
>>>>>>> 2429aaf2276d689e101ed88285f18449dbe4280d:src/game/Makefile.am
+=======
+ AccountMgr.cpp \
+ AccountMgr.h \
+ AchievementMgr.h \
+ AchievementMgr.cpp \
+ AggressorAI.cpp \
+ AggressorAI.h \
+ AnimalRandomMovementGenerator.h \
+ ArenaTeam.cpp \
+ ArenaTeam.h \
+ ArenaTeamHandler.cpp \
+ AuctionHouseHandler.cpp \
+ AuctionHouseMgr.cpp \
+ AuctionHouseMgr.h \
+ Bag.cpp \
+ Bag.h \
+ BattleGround.cpp \
+ BattleGroundAA.cpp \
+ BattleGroundAB.cpp \
+ BattleGroundAV.cpp \
+ BattleGroundBE.cpp \
+ BattleGroundDS.cpp \
+ BattleGroundEY.cpp \
+ BattleGroundNA.cpp \
+ BattleGroundRL.cpp \
+ BattleGroundRV.cpp \
+ BattleGroundSA.cpp \
+ BattleGroundWS.cpp \
+ BattleGround.h \
+ BattleGroundAA.h \
+ BattleGroundAB.h \
+ BattleGroundAV.h \
+ BattleGroundBE.h \
+ BattleGroundDS.h \
+ BattleGroundEY.h \
+ BattleGroundNA.h \
+ BattleGroundRL.h \
+ BattleGroundRV.h \
+ BattleGroundSA.h \
+ BattleGroundWS.h \
+ BattleGroundHandler.cpp \
+ BattleGroundMgr.cpp \
+ BattleGroundMgr.h \
+ Calendar.cpp \
+ Calendar.h \
+ CalendarHandler.cpp \
+ Cell.h \
+ CellImpl.h \
+ Channel.cpp \
+ Channel.h \
+ ChannelHandler.cpp \
+ ChannelMgr.h \
+ CharacterHandler.cpp \
+ Chat.cpp \
+ Chat.h \
+ ChatHandler.cpp \
+ CombatHandler.cpp \
+ ConfusedMovementGenerator.cpp \
+ ConfusedMovementGenerator.h \
+ Corpse.cpp \
+ Corpse.h \
+ CreatureAI.cpp \
+ CreatureAI.h \
+ CreatureAIImpl.h \
+ CreatureAIRegistry.cpp \
+ CreatureAIRegistry.h \
+ CreatureAISelector.cpp \
+ CreatureAISelector.h \
+ CreatureEventAI.cpp \
+ CreatureEventAI.h \
+ CreatureEventAIMgr.cpp \
+ CreatureEventAIMgr.h \
+ Creature.cpp \
+ Creature.h \
+ DBCEnums.h \
+ DBCfmt.h \
+ DBCStores.cpp \
+ DBCStores.h \
+ DBCStructure.h \
+ debugcmds.cpp \
+ DestinationHolder.cpp \
+ DestinationHolder.h \
+ DestinationHolderImp.h \
+ DuelHandler.cpp \
+ DynamicObject.cpp \
+ DynamicObject.h \
+ FleeingMovementGenerator.cpp \
+ FleeingMovementGenerator.h \
+ Formulas.h \
+ GameEventMgr.cpp \
+ GameEventMgr.h \
+ GameObject.cpp \
+ GameObject.h \
+ GlobalEvents.cpp \
+ GlobalEvents.h \
+ GMTicketHandler.cpp \
+ GMTicketMgr.cpp \
+ GMTicketMgr.h \
+ GossipDef.cpp \
+ GossipDef.h \
+ GridDefines.h \
+ GridNotifiers.cpp \
+ GridNotifiers.h \
+ GridNotifiersImpl.h \
+ GridStates.cpp \
+ GridStates.h \
+ Group.cpp \
+ Group.h \
+ GroupHandler.cpp \
+ GuardAI.cpp \
+ GuardAI.h \
+ Guild.cpp \
+ Guild.h \
+ GuildHandler.cpp \
+ HomeMovementGenerator.cpp \
+ HomeMovementGenerator.h \
+ HostilRefManager.cpp \
+ HostilRefManager.h \
+ IdleMovementGenerator.cpp \
+ IdleMovementGenerator.h \
+ InstanceData.cpp \
+ InstanceData.h \
+ InstanceSaveMgr.cpp \
+ InstanceSaveMgr.h \
+ Item.cpp \
+ Item.h \
+ ItemEnchantmentMgr.cpp \
+ ItemEnchantmentMgr.h \
+ ItemHandler.cpp \
+ ItemPrototype.h \
+ Language.h \
+ Level0.cpp \
+ Level1.cpp \
+ Level2.cpp \
+ Level3.cpp \
+ LFGHandler.cpp \
+ LootHandler.cpp \
+ LootMgr.cpp \
+ LootMgr.h \
+ Mail.cpp \
+ Mail.h \
+ Map.cpp \
+ Map.h \
+ MapInstanced.cpp \
+ MapInstanced.h \
+ MapManager.cpp \
+ MapManager.h \
+ MapReference.h \
+ MapRefManager.h \
+ MiscHandler.cpp \
+ MotionMaster.cpp \
+ MotionMaster.h \
+ MovementGenerator.cpp \
+ MovementGenerator.h \
+ MovementGeneratorImpl.h \
+ MovementHandler.cpp \
+ NPCHandler.cpp \
+ NPCHandler.h \
+ NullCreatureAI.cpp \
+ NullCreatureAI.h \
+ ObjectAccessor.cpp \
+ ObjectAccessor.h \
+ Object.cpp \
+ ObjectDefines.h \
+ ObjectGridLoader.cpp \
+ ObjectGridLoader.h \
+ Object.h \
+ ObjectMgr.cpp \
+ ObjectMgr.h \
+ ObjectPosSelector.cpp \
+ ObjectPosSelector.h \
+ Opcodes.cpp \
+ Opcodes.h \
+ Path.h \
+ PetAI.cpp \
+ PetAI.h \
+ Pet.cpp \
+ Pet.h \
+ PetHandler.cpp \
+ PetitionsHandler.cpp \
+ Player.cpp \
+ Player.h \
+ PlayerDump.cpp \
+ PlayerDump.h \
+ PointMovementGenerator.cpp \
+ PointMovementGenerator.h \
+ PoolHandler.cpp \
+ PoolHandler.h \
+ QueryHandler.cpp \
+ QuestDef.cpp \
+ QuestDef.h \
+ QuestHandler.cpp \
+ RandomMovementGenerator.cpp \
+ RandomMovementGenerator.h \
+ ReactorAI.cpp \
+ ReactorAI.h \
+ ReputationMgr.cpp \
+ ReputationMgr.h \
+ ScriptCalls.cpp \
+ ScriptCalls.h \
+ SharedDefines.h \
+ SkillHandler.cpp \
+ SpellAuraDefines.h \
+ SpellAuras.cpp \
+ SpellAuras.h \
+ Spell.cpp \
+ SpellEffects.cpp \
+ Spell.h \
+ SkillDiscovery.cpp \
+ SkillDiscovery.h \
+ SkillExtraItems.cpp \
+ SkillExtraItems.h \
+ SpellHandler.cpp \
+ SocialMgr.cpp \
+ SocialMgr.h \
+ SpellMgr.cpp \
+ SpellMgr.h \
+ StatSystem.cpp \
+ TargetedMovementGenerator.cpp \
+ TargetedMovementGenerator.h \
+ TaxiHandler.cpp \
+ TemporarySummon.cpp \
+ TemporarySummon.h \
+ TotemAI.cpp \
+ TotemAI.h \
+ Totem.cpp \
+ Totem.h \
+ TradeHandler.cpp \
+ Transports.cpp \
+ Transports.h \
+ ThreatManager.cpp \
+ ThreatManager.h \
+ Traveller.h \
+ Unit.cpp \
+ Unit.h \
+ UnitEvents.h \
+ UpdateData.cpp \
+ UpdateData.h \
+ UpdateFields.h \
+ UpdateMask.h \
+ Vehicle.cpp \
+ Vehicle.h \
+ VoiceChatHandler.cpp \
+ WaypointManager.cpp \
+ WaypointManager.h \
+ WaypointMovementGenerator.cpp \
+ WaypointMovementGenerator.h \
+ Weather.cpp \
+ Weather.h \
+ World.cpp \
+ World.h \
+ WorldLog.cpp \
+ WorldLog.h \
+ WorldSession.cpp \
+ WorldSession.h \
+ WorldSocket.cpp \
+ WorldSocket.h \
+ WorldSocketMgr.cpp \
+ WorldSocketMgr.h \
+ FollowerReference.cpp \
+ FollowerReference.h \
+ FollowerRefManager.h \
+ GroupReference.cpp \
+ GroupReference.h \
+ GroupRefManager.h
+>>>>>>> 5a6594330caefc0dc00a5fe792dcb0e344b457cb:src/game/Makefile.am
## Link against shared library
libmangosgame_a_LIBADD = ../shared/libmangosshared.a ../shared/Auth/libmangosauth.a ../shared/Config/libmangosconfig.a ../shared/Database/libmangosdatabase.a ../shared/vmap/libmangosvmaps.a
diff --git a/src/game/Map.cpp b/src/game/Map.cpp
index d6f06051c59..ac81b9c2a6d 100644
--- a/src/game/Map.cpp
+++ b/src/game/Map.cpp
@@ -307,9 +307,21 @@ void Map::RemoveFromGrid(DynamicObject* obj, NGridType *grid, Cell const& cell)
template<class T>
void Map::SwitchGridContainers(T* obj, bool on)
{
- CellPair pair = Trinity::ComputeCellPair(obj->GetPositionX(), obj->GetPositionY());
- Cell cell(pair);
+ CellPair p = Trinity::ComputeCellPair(obj->GetPositionX(), obj->GetPositionY());
+ if(p.x_coord >= TOTAL_NUMBER_OF_CELLS_PER_MAP || p.y_coord >= TOTAL_NUMBER_OF_CELLS_PER_MAP )
+ {
+ sLog.outError("Map::SwitchGridContainers: Object " I64FMT " have invalid coordinates X:%f Y:%f grid cell [%u:%u]", obj->GetGUID(), obj->GetPositionX(), obj->GetPositionY(), p.x_coord, p.y_coord);
+ return;
+ }
+
+ Cell cell(p);
+ if( !loaded(GridPair(cell.data.Part.grid_x, cell.data.Part.grid_y)) )
+ return;
+
+ DEBUG_LOG("Switch object " I64FMT " from grid[%u,%u] %u", obj->GetGUID(), cell.data.Part.grid_x, cell.data.Part.grid_y, on);
NGridType *ngrid = getNGrid(cell.GridX(), cell.GridY());
+ assert( ngrid != NULL );
+
GridType &grid = (*ngrid)(cell.CellX(), cell.CellY());
if(on)
@@ -465,7 +477,7 @@ bool Map::Add(Player *player)
SendInitTransports(player);
player->m_clientGUIDs.clear();
- AddNotifier(player);
+ //AddNotifier(player);
return true;
}
@@ -505,7 +517,7 @@ Map::Add(T *obj)
//if(obj->GetTypeId() != TYPEID_UNIT)
UpdateObjectVisibility(obj,cell,p);
- AddNotifier(obj);
+ //AddNotifier(obj);
}
void Map::MessageBroadcast(Player *player, WorldPacket *msg, bool to_self, bool to_possessor)
@@ -711,7 +723,7 @@ void Map::Update(const uint32 &t_diff)
}
}
- if(plr->m_seer != plr)
+ if(plr->m_seer != plr && !plr->hasUnitState(UNIT_STAT_ONVEHICLE))
{
Trinity::PlayerVisibilityNotifier notifier(*plr);
VisitAll(plr->m_seer->GetPositionX(), plr->m_seer->GetPositionY(), World::GetMaxVisibleDistance(), notifier);
@@ -1765,8 +1777,6 @@ float Map::GetVmapHeight(float x, float y, float z, bool useMaps) const
return vmapHeight;
}
-#include "World.h"
-
uint16 Map::GetAreaFlag(float x, float y, float z) const
{
uint16 areaflag;
@@ -1791,9 +1801,9 @@ uint16 Map::GetAreaFlag(float x, float y, float z) const
case 2456: // Death's Breach (Eastern Plaguelands)
if(z > 350.0f) areaflag = 1950; break;
// Dalaran
- case 1593:
- case 2484:
- case 2492:
+ case 1593: // Crystalsong Forest
+ case 2484: // The Twilight Rivulet (Crystalsong Forest)
+ case 2492: // Forlorn Woods (Crystalsong Forest)
if (x > 5568.0f && x < 6116.0f && y > 282.0f && y < 982.0f && z > 563.0f) areaflag = 2153; break;
// Maw of Neltharion (cave)
case 164: // Dragonblight
@@ -1801,6 +1811,27 @@ uint16 Map::GetAreaFlag(float x, float y, float z) const
case 1827: // Wintergrasp
case 2591: // The Cauldron of Flames (Wintergrasp)
if (x > 4364.0f && x < 4632.0f && y > 1545.0f && y < 1886.0f && z < 200.0f) areaflag = 1853; break;
+ // Undercity (sewers enter and path)
+ case 179: // Tirisfal Glades
+ if (x > 1595.0f && x < 1699.0f && y > 535.0f && y < 643.5f && z < 30.5f) areaflag = 685; break;
+ // Undercity (Royal Quarter)
+ case 210: // Silverpine Forest
+ case 316: // The Shining Strand (Silverpine Forest)
+ case 438: // Lordamere Lake (Silverpine Forest)
+ if (x > 1237.0f && x < 1401.0f && y > 284.0f && y < 440.0f && z < -40.0f) areaflag = 685; break;
+ // Undercity (cave and ground zone, part of royal quarter)
+ case 607: // Ruins of Lordaeron (Tirisfal Glades)
+ // ground and near to ground (by city walls)
+ if(z > 0.0f)
+ {
+ if (x > 1510.0f && x < 1839.0f && y > 29.77f && y < 433.0f) areaflag = 685;
+ }
+ // more wide underground, part of royal quarter
+ else
+ {
+ if (x > 1299.0f && x < 1839.0f && y > 10.0f && y < 440.0f) areaflag = 685;
+ }
+ break;
}
return areaflag;
diff --git a/src/game/Map.h b/src/game/Map.h
index 4d00a287b03..3d533da1675 100644
--- a/src/game/Map.h
+++ b/src/game/Map.h
@@ -44,6 +44,7 @@ class Group;
class InstanceSave;
class WorldObject;
class TempSummon;
+class CreatureGroup;
namespace ZThread
{
@@ -248,6 +249,8 @@ typedef UNORDERED_MAP<Creature*, CreatureMover> CreatureMoveList;
#define INVALID_HEIGHT -100000.0f // for check, must be equal to VMAP_INVALID_HEIGHT, real value for unknown height is VMAP_INVALID_HEIGHT_VALUE
#define MIN_UNLOAD_DELAY 1 // immediate unload
+typedef std::map<uint32/*leaderDBGUID*/, CreatureGroup*> CreatureGroupHolderType;
+
class TRINITY_DLL_SPEC Map : public GridRefManager<NGridType>, public Trinity::ObjectLevelLockable<Map, ZThread::Mutex>
{
friend class MapReference;
@@ -416,6 +419,9 @@ class TRINITY_DLL_SPEC Map : public GridRefManager<NGridType>, public Trinity::O
template<class NOTIFIER> void VisitGrid(const float &x, const float &y, float radius, NOTIFIER &notifier);
TempSummon *SummonCreature(uint32 entry, float x, float y, float z, float angle, SummonPropertiesEntry const *properties = NULL, uint32 duration = 0, Unit *summoner = NULL);
+
+ CreatureGroupHolderType CreatureGroupHolder;
+
private:
void LoadMapAndVMap(int gx, int gy);
void LoadVMap(int gx, int gy);
diff --git a/src/game/MiscHandler.cpp b/src/game/MiscHandler.cpp
index ca2c5609692..0ced3a57201 100644
--- a/src/game/MiscHandler.cpp
+++ b/src/game/MiscHandler.cpp
@@ -1171,22 +1171,6 @@ void WorldSession::HandleMoveRootAck(WorldPacket&/* recv_data*/)
*/
}
-void WorldSession::HandleMoveTeleportAck(WorldPacket&/* recv_data*/)
-{
- /*
- CHECK_PACKET_SIZE(recv_data,8+4);
-
- sLog.outDebug("MSG_MOVE_TELEPORT_ACK");
- uint64 guid;
- uint32 flags, time;
-
- recv_data >> guid;
- recv_data >> flags >> time;
- DEBUG_LOG("Guid " I64FMTD,guid);
- DEBUG_LOG("Flags %u, time %u",flags, time/IN_MILISECONDS);
- */
-}
-
void WorldSession::HandleSetActionBar(WorldPacket& recv_data)
{
CHECK_PACKET_SIZE(recv_data,1);
diff --git a/src/game/MotionMaster.cpp b/src/game/MotionMaster.cpp
index 6d7a40da045..ee6cc05a5d2 100644
--- a/src/game/MotionMaster.cpp
+++ b/src/game/MotionMaster.cpp
@@ -208,7 +208,7 @@ MotionMaster::MoveTargetedHome()
DEBUG_LOG("Pet or controlled unit (Entry: %u GUID: %u) targeting home",
i_owner->GetEntry(), i_owner->GetGUIDLow() );
- MoveFollow(i_owner, PET_FOLLOW_DIST, PET_FOLLOW_ANGLE, MOTION_SLOT_IDLE);
+ MoveFollow(target, PET_FOLLOW_DIST, PET_FOLLOW_ANGLE, MOTION_SLOT_IDLE);
}
else if(i_owner->GetTypeId() == TYPEID_UNIT)
{
@@ -305,7 +305,7 @@ MotionMaster::MovePoint(uint32 id, float x, float y, float z)
}
}
-void MotionMaster::MoveJumpFrom(float srcX, float srcY, float speedXY, float speedZ)
+void MotionMaster::MoveKnockbackFrom(float srcX, float srcY, float speedXY, float speedZ)
{
//this function may make players fall below map
if(i_owner->GetTypeId()==TYPEID_PLAYER)
@@ -317,6 +317,18 @@ void MotionMaster::MoveJumpFrom(float srcX, float srcY, float speedXY, float spe
MoveJump(x, y, z, speedXY, speedZ);
}
+void MotionMaster::MoveJumpTo(float angle, float speedXY, float speedZ)
+{
+ //this function may make players fall below map
+ if(i_owner->GetTypeId()==TYPEID_PLAYER)
+ return;
+
+ float x, y, z;
+ float dist = speedXY * speedZ * 0.1f;
+ i_owner->GetClosePoint(x, y, z, i_owner->GetObjectSize(), dist, angle);
+ MoveJump(x, y, z, speedXY, speedZ);
+}
+
void MotionMaster::MoveJump(float x, float y, float z, float speedXY, float speedZ)
{
uint32 moveFlag = MOVEFLAG_JUMP | MOVEFLAG_WALK;
diff --git a/src/game/MotionMaster.h b/src/game/MotionMaster.h
index 38a2b58825f..ea71495d216 100644
--- a/src/game/MotionMaster.h
+++ b/src/game/MotionMaster.h
@@ -141,7 +141,8 @@ class TRINITY_DLL_SPEC MotionMaster //: private std::stack<MovementGenerator *>
void MoveFleeing(Unit* enemy);
void MovePoint(uint32 id, float x,float y,float z);
void MoveCharge(float x, float y, float z, float speed = SPEED_CHARGE);
- void MoveJumpFrom(float srcX, float srcY, float speedXY, float speedZ);
+ void MoveKnockbackFrom(float srcX, float srcY, float speedXY, float speedZ);
+ void MoveJumpTo(float angle, float speedXY, float speedZ);
void MoveJump(float x, float y, float z, float speedXY, float speedZ);
void MoveTaxiFlight(uint32 path, uint32 pathnode);
void MoveDistract(uint32 time);
diff --git a/src/game/MovementHandler.cpp b/src/game/MovementHandler.cpp
index 69a8572e7a5..64c4fecdb53 100644
--- a/src/game/MovementHandler.cpp
+++ b/src/game/MovementHandler.cpp
@@ -41,6 +41,10 @@ void WorldSession::HandleMoveWorldportAckOpcode( WorldPacket & /*recv_data*/ )
void WorldSession::HandleMoveWorldportAckOpcode()
{
+ // ignore unexpected far teleports
+ if(!GetPlayer()->IsBeingTeleportedFar())
+ return;
+
// get the teleport destination
WorldLocation &loc = GetPlayer()->GetTeleportDest();
@@ -59,7 +63,7 @@ void WorldSession::HandleMoveWorldportAckOpcode()
if(GetPlayer()->m_InstanceValid == false && !mInstance)
GetPlayer()->m_InstanceValid = true;
- GetPlayer()->SetSemaphoreTeleport(false);
+ GetPlayer()->SetSemaphoreTeleportFar(false);
// relocate the player to the teleport destination
GetPlayer()->SetMapId(loc.mapid);
@@ -79,7 +83,6 @@ void WorldSession::HandleMoveWorldportAckOpcode()
{
sLog.outDebug("WORLD: teleport of player %s (%d) to location %d,%f,%f,%f,%f failed", GetPlayer()->GetName(), GetPlayer()->GetGUIDLow(), loc.mapid, loc.x, loc.y, loc.z, loc.o);
// teleport the player home
- GetPlayer()->SetDontMove(false);
if(!GetPlayer()->TeleportTo(GetPlayer()->m_homebindMapId, GetPlayer()->m_homebindX, GetPlayer()->m_homebindY, GetPlayer()->m_homebindZ, GetPlayer()->GetOrientation()))
{
// the player must always be able to teleport home
@@ -116,7 +119,6 @@ void WorldSession::HandleMoveWorldportAckOpcode()
if(!_player->InBattleGround())
{
// short preparations to continue flight
- GetPlayer()->SetDontMove(false);
FlightPathMovementGenerator* flight = (FlightPathMovementGenerator*)(GetPlayer()->GetMotionMaster()->top());
flight->Initialize(*GetPlayer());
return;
@@ -157,16 +159,53 @@ void WorldSession::HandleMoveWorldportAckOpcode()
GetPlayer()->CastSpell(GetPlayer(), 2479, true);
// resummon pet
- if(GetPlayer()->m_temporaryUnsummonedPetNumber)
- {
- Pet* NewPet = new Pet(GetPlayer());
- if(!NewPet->LoadPetFromDB(GetPlayer(), 0, GetPlayer()->m_temporaryUnsummonedPetNumber, true))
- delete NewPet;
+ GetPlayer()->ResummonPetTemporaryUnSummonedIfAny();
+}
+
+void WorldSession::HandleMoveTeleportAck(WorldPacket& recv_data)
+{
+ CHECK_PACKET_SIZE(recv_data,8+4);
+
+ sLog.outDebug("MSG_MOVE_TELEPORT_ACK");
+ uint64 guid;
+ uint32 flags, time;
- GetPlayer()->m_temporaryUnsummonedPetNumber = 0;
+ recv_data >> guid;
+ recv_data >> flags >> time;
+ DEBUG_LOG("Guid " I64FMTD,guid);
+ DEBUG_LOG("Flags %u, time %u",flags, time/IN_MILISECONDS);
+
+ Unit *mover = _player->m_mover;
+ Player *plMover = mover->GetTypeId()==TYPEID_PLAYER ? (Player*)mover : NULL;
+
+ if(!plMover || !plMover->IsBeingTeleportedNear())
+ return;
+
+ if(guid != plMover->GetGUID())
+ return;
+
+ plMover->SetSemaphoreTeleportNear(false);
+
+ uint32 old_zone = plMover->GetZoneId();
+
+ WorldLocation const& dest = plMover->GetTeleportDest();
+
+ plMover->SetPosition(dest.x, dest.y, dest.z, dest.o, true);
+
+ uint32 newzone, newarea;
+ plMover->GetZoneAndAreaId(newzone,newarea);
+ plMover->UpdateZone(newzone,newarea);
+
+ // new zone
+ if(old_zone != newzone)
+ {
+ // honorless target
+ if(plMover->pvpInfo.inHostileArea)
+ plMover->CastSpell(plMover, 2479, true);
}
- GetPlayer()->SetDontMove(false);
+ // resummon pet
+ GetPlayer()->ResummonPetTemporaryUnSummonedIfAny();
}
void WorldSession::HandleMovementOpcodes( WorldPacket & recv_data )
@@ -174,7 +213,11 @@ void WorldSession::HandleMovementOpcodes( WorldPacket & recv_data )
uint32 opcode = recv_data.GetOpcode();
//sLog.outDebug("WORLD: Recvd %s (%u, 0x%X) opcode", LookupOpcodeName(opcode), opcode, opcode);
- if(GetPlayer()->GetDontMove())
+ Unit *mover = _player->m_mover;
+ Player *plMover = mover->GetTypeId()==TYPEID_PLAYER ? (Player*)mover : NULL;
+
+ // ignore, waiting processing in WorldSession::HandleMoveWorldportAckOpcode and WorldSession::HandleMoveTeleportAck
+ if(plMover && plMover->IsBeingTeleported())
return;
/* extract packet */
@@ -192,9 +235,6 @@ void WorldSession::HandleMovementOpcodes( WorldPacket & recv_data )
if (!Trinity::IsValidMapCoord(movementInfo.x, movementInfo.y, movementInfo.z, movementInfo.o))
return;
- Unit *mover = _player->m_mover;
- Player *plMover = mover->GetTypeId()==TYPEID_PLAYER ? (Player*)mover : NULL;
-
/* handle special cases */
if (movementInfo.flags & MOVEMENTFLAG_ONTRANSPORT)
{
@@ -258,7 +298,6 @@ void WorldSession::HandleMovementOpcodes( WorldPacket & recv_data )
plMover->SetPosition(movementInfo.x, movementInfo.y, movementInfo.z, movementInfo.o);
plMover->m_movementInfo = movementInfo;
plMover->SetUnitMovementFlags(movementInfo.flags);
-
plMover->UpdateFallInformationIfNeed(movementInfo,recv_data.GetOpcode());
if(plMover->isMovingOrTurning())
@@ -280,10 +319,14 @@ void WorldSession::HandleMovementOpcodes( WorldPacket & recv_data )
if(plMover->isAlive())
{
plMover->EnvironmentalDamage(DAMAGE_FALL_TO_VOID, GetPlayer()->GetMaxHealth());
- // change the death state to CORPSE to prevent the death timer from
- // starting in the next player update
- plMover->KillPlayer();
- plMover->BuildPlayerRepop();
+ // pl can be alive if GM/etc
+ if(!plMover->isAlive())
+ {
+ // change the death state to CORPSE to prevent the death timer from
+ // starting in the next player update
+ plMover->KillPlayer();
+ plMover->BuildPlayerRepop();
+ }
}
// cancel the death timer here if started
@@ -294,7 +337,12 @@ void WorldSession::HandleMovementOpcodes( WorldPacket & recv_data )
else // creature charmed
{
if(Map *map = mover->GetMap())
+ {
+ //if(GetPlayer()->m_seer != mover)
+ if(((Creature*)mover)->isVehicle())
+ map->PlayerRelocation(GetPlayer(), movementInfo.x, movementInfo.y, movementInfo.z, movementInfo.o);
map->CreatureRelocation((Creature*)mover, movementInfo.x, movementInfo.y, movementInfo.z, movementInfo.o);
+ }
mover->SetUnitMovementFlags(movementInfo.flags);
}
}
@@ -435,8 +483,6 @@ void WorldSession::HandleDismissControlledVehicle(WorldPacket &recv_data)
if(Vehicle *vehicle = ObjectAccessor::GetVehicle(vehicleGUID))
{
_player->ExitVehicle(vehicle);
- if(!vehicle->GetDBTableGUIDLow())
- vehicle->Dismiss();
}
}
diff --git a/src/game/NPCHandler.cpp b/src/game/NPCHandler.cpp
index f3a268a3b06..8d1427c86b8 100644
--- a/src/game/NPCHandler.cpp
+++ b/src/game/NPCHandler.cpp
@@ -481,7 +481,6 @@ void WorldSession::SendBindPoint(Creature *npc)
_player->PlayerTalkClass->CloseGossip();
}
-//Need fix
void WorldSession::HandleListStabledPetsOpcode( WorldPacket & recv_data )
{
CHECK_PACKET_SIZE(recv_data,8);
@@ -518,7 +517,9 @@ void WorldSession::SendStablePet(uint64 guid )
Pet *pet = _player->GetPet();
+ size_t wpos = data.wpos();
data << uint8(0); // place holder for slot show number
+
data << uint8(GetPlayer()->m_stableSlots);
uint8 num = 0; // counter for place holder
@@ -530,12 +531,13 @@ void WorldSession::SendStablePet(uint64 guid )
data << uint32(pet->GetEntry());
data << uint32(pet->getLevel());
data << pet->GetName(); // petname
- data << uint8(0x01); // flags?, client slot 1 == current pet (0)
+ data << uint8(1); // 1 = current, 2/3 = in stable (any from 4,5,... create problems with proper show)
++num;
}
- // 0 1 2 3 4 5
- QueryResult* result = CharacterDatabase.PQuery("SELECT owner, slot, id, entry, level, name FROM character_pet WHERE owner = '%u' AND slot > 0 AND slot < 5",_player->GetGUIDLow());
+ // 0 1 2 3 4
+ QueryResult* result = CharacterDatabase.PQuery("SELECT owner, id, entry, level, name FROM character_pet WHERE owner = '%u' AND slot >= '%u' AND slot <= '%u' ORDER BY slot",
+ _player->GetGUIDLow(),PET_SAVE_FIRST_STABLE_SLOT,PET_SAVE_LAST_STABLE_SLOT);
if(result)
{
@@ -543,11 +545,11 @@ void WorldSession::SendStablePet(uint64 guid )
{
Field *fields = result->Fetch();
- data << uint32(fields[2].GetUInt32()); // petnumber
- data << uint32(fields[3].GetUInt32()); // creature entry
- data << uint32(fields[4].GetUInt32()); // level
- data << fields[5].GetString(); // name
- data << uint8(fields[1].GetUInt32()+1); // slot
+ data << uint32(fields[1].GetUInt32()); // petnumber
+ data << uint32(fields[2].GetUInt32()); // creature entry
+ data << uint32(fields[3].GetUInt32()); // level
+ data << fields[4].GetString(); // name
+ data << uint8(2); // 1 = current, 2/3 = in stable (any from 4,5,... create problems with proper show)
++num;
}while( result->NextRow() );
@@ -555,7 +557,7 @@ void WorldSession::SendStablePet(uint64 guid )
delete result;
}
- data.put<uint8>(8, num); // set real data to placeholder
+ data.put<uint8>(wpos, num); // set real data to placeholder
SendPacket(&data);
}
@@ -596,7 +598,8 @@ void WorldSession::HandleStablePet( WorldPacket & recv_data )
uint32 free_slot = 1;
- QueryResult *result = CharacterDatabase.PQuery("SELECT owner,slot,id FROM character_pet WHERE owner = '%u' AND slot > 0 AND slot < 5 ORDER BY slot ",_player->GetGUIDLow());
+ QueryResult *result = CharacterDatabase.PQuery("SELECT owner,slot,id FROM character_pet WHERE owner = '%u' AND slot >= '%u' AND slot <= '%u' ORDER BY slot ",
+ _player->GetGUIDLow(),PET_SAVE_FIRST_STABLE_SLOT,PET_SAVE_LAST_STABLE_SLOT);
if(result)
{
do
@@ -605,11 +608,16 @@ void WorldSession::HandleStablePet( WorldPacket & recv_data )
uint32 slot = fields[1].GetUInt32();
- if(slot==free_slot) // this slot not free
- ++free_slot;
+ // slots ordered in query, and if not equal then free
+ if(slot!=free_slot)
+ break;
+
+ // this slot not free, skip
+ ++free_slot;
}while( result->NextRow() );
+
+ delete result;
}
- delete result;
if( free_slot > 0 && free_slot <= GetPlayer()->m_stableSlots)
{
@@ -648,8 +656,7 @@ void WorldSession::HandleUnstablePet( WorldPacket & recv_data )
Pet* pet = _player->GetPet();
if(pet && pet->isAlive())
{
- uint8 i = 0x06;
- data << uint8(i);
+ data << uint8(0x06);
SendPacket(&data);
return;
}
@@ -660,7 +667,8 @@ void WorldSession::HandleUnstablePet( WorldPacket & recv_data )
Pet *newpet = NULL;
- QueryResult *result = CharacterDatabase.PQuery("SELECT entry FROM character_pet WHERE owner = '%u' AND id = '%u' AND slot > 0 AND slot < 5",_player->GetGUIDLow(),petnumber);
+ QueryResult *result = CharacterDatabase.PQuery("SELECT entry FROM character_pet WHERE owner = '%u' AND id = '%u' AND slot >='%u' AND slot <= '%u'",
+ _player->GetGUIDLow(),petnumber,PET_SAVE_FIRST_STABLE_SLOT,PET_SAVE_LAST_STABLE_SLOT);
if(result)
{
Field *fields = result->Fetch();
@@ -704,7 +712,7 @@ void WorldSession::HandleBuyStableSlot( WorldPacket & recv_data )
WorldPacket data(SMSG_STABLE_RESULT, 200);
- if(GetPlayer()->m_stableSlots < 4) // max slots amount = 4
+ if(GetPlayer()->m_stableSlots < MAX_PET_STABLES)
{
StableSlotPricesEntry const *SlotPrice = sStableSlotPricesStore.LookupEntry(GetPlayer()->m_stableSlots+1);
if(_player->GetMoney() >= SlotPrice->Price)
@@ -756,7 +764,8 @@ void WorldSession::HandleStableSwapPet( WorldPacket & recv_data )
return;
// find swapped pet slot in stable
- QueryResult *result = CharacterDatabase.PQuery("SELECT slot,entry FROM character_pet WHERE owner = '%u' AND id = '%u'",_player->GetGUIDLow(),pet_number);
+ QueryResult *result = CharacterDatabase.PQuery("SELECT slot,entry FROM character_pet WHERE owner = '%u' AND id = '%u'",
+ _player->GetGUIDLow(),pet_number);
if(!result)
return;
@@ -766,7 +775,7 @@ void WorldSession::HandleStableSwapPet( WorldPacket & recv_data )
uint32 petentry = fields[1].GetUInt32();
delete result;
- // move alive pet to slot or delele dead pet
+ // move alive pet to slot or delete dead pet
_player->RemovePet(pet,pet->isAlive() ? PetSaveMode(slot) : PET_SAVE_AS_DELETED);
// summon unstabled pet
diff --git a/src/game/Object.cpp b/src/game/Object.cpp
index b5f25596af3..c22d00628b2 100644
--- a/src/game/Object.cpp
+++ b/src/game/Object.cpp
@@ -85,17 +85,16 @@ Object::~Object( )
//if(m_objectUpdated)
// ObjectAccessor::Instance().RemoveUpdateObject(this);
- if(m_uint32Values)
+ if(IsInWorld())
{
- if(IsInWorld())
- {
- ///- Do NOT call RemoveFromWorld here, if the object is a player it will crash
- sLog.outCrash("Object::~Object - guid="I64FMTD", typeid=%d deleted but still in world!!", GetGUID(), GetTypeId());
- assert(false);
- }
+ sLog.outCrash("Object::~Object - guid="I64FMTD", typeid=%d deleted but still in world!!", GetGUID(), GetTypeId());
+ assert(false);
+ }
- assert(!m_objectUpdated);
+ assert(!m_objectUpdated);
+ if(m_uint32Values)
+ {
//DEBUG_LOG("Object desctr 1 check (%p)",(void*)this);
delete [] m_uint32Values;
delete [] m_uint32Values_mirror;
@@ -286,7 +285,7 @@ void Object::_BuildMovementUpdate(ByteBuffer * data, uint8 flags, uint32 flags2)
{
flags2 = ((Player*)this)->GetUnitMovementFlags();
- if(((Player*)this)->GetTransport())
+ if(((Player*)this)->GetTransport() || ((Player*)this)->hasUnitState(UNIT_STAT_ONVEHICLE))
flags2 |= MOVEMENTFLAG_ONTRANSPORT;
else
flags2 &= ~MOVEMENTFLAG_ONTRANSPORT;
@@ -336,7 +335,10 @@ void Object::_BuildMovementUpdate(ByteBuffer * data, uint8 flags, uint32 flags2)
{
if(GetTypeId() == TYPEID_PLAYER)
{
- *data << (uint64)((Player*)this)->GetTransport()->GetGUID();
+ if(((Player*)this)->hasUnitState(UNIT_STAT_ONVEHICLE))
+ *data << (uint64)((Player*)this)->GetCharmGUID();
+ else
+ *data << (uint64)((Player*)this)->GetTransport()->GetGUID();
*data << (float)((Player*)this)->GetTransOffsetX();
*data << (float)((Player*)this)->GetTransOffsetY();
*data << (float)((Player*)this)->GetTransOffsetZ();
@@ -667,13 +669,15 @@ void Object::_BuildValuesUpdate(uint8 updatetype, ByteBuffer * data, UpdateMask
if(GetTypeId() == TYPEID_PLAYER && target != this
&& ((Player*)this)->IsInSameRaidWith(target))
{
- /*if(index == UNIT_FIELD_BYTES_2)
+ // Allow targetting opposite faction in party when enabled in config
+ if(sWorld.getConfig(CONFIG_ALLOW_TWO_SIDE_INTERACTION_GROUP) && index == UNIT_FIELD_BYTES_2)
{
DEBUG_LOG("-- VALUES_UPDATE: Sending '%s' the blue-group-fix from '%s' (flag)", target->GetName(), ((Player*)this)->GetName());
- *data << ( m_uint32Values[ index ] & (UNIT_BYTE2_FLAG_SANCTUARY << 8) ); // this flag is at uint8 offset 1 !!
+ *data << ( m_uint32Values[ index ] & ((UNIT_BYTE2_FLAG_SANCTUARY /*| UNIT_BYTE2_FLAG_AURAS | UNIT_BYTE2_FLAG_UNK5*/) << 8) ); // this flag is at uint8 offset 1 !!
+
ch = true;
}
- else*/
+ else
{
FactionTemplateEntry const *ft1, *ft2;
ft1 = ((Player*)this)->getFactionTemplateEntry();
@@ -745,20 +749,10 @@ void Object::_BuildValuesUpdate(uint8 updatetype, ByteBuffer * data, UpdateMask
void Object::ClearUpdateMask(bool remove)
{
- if(!m_uint32Values_mirror || !m_uint32Values)
- {
- sLog.outCrash("Object::ClearUpdateMask: Object entry %u (type %u) does not have uint32Values", GetEntry(), GetTypeId());
- return;
- }
+ uint32 *temp = m_uint32Values;
- uint32 temp = m_uint32Values[0];
- temp = m_uint32Values_mirror[0];
+ memcpy(m_uint32Values_mirror, m_uint32Values, m_valuesCount*sizeof(uint32));
- for( uint16 index = 0; index < m_valuesCount; index ++ )
- {
- if(m_uint32Values_mirror[index]!= m_uint32Values[index])
- m_uint32Values_mirror[index] = m_uint32Values[index];
- }
if(m_objectUpdated)
{
if(remove)
@@ -802,27 +796,23 @@ bool Object::LoadValues(const char* data)
void Object::_SetUpdateBits(UpdateMask *updateMask, Player* /*target*/) const
{
- if(!m_uint32Values_mirror || !m_uint32Values)
- {
- sLog.outCrash("Object::_SetUpdateBits: Object entry %u (type %u) does not have uint32Values", GetEntry(), GetTypeId());
- return;
- }
-
- uint32 temp = m_uint32Values[0];
- temp = m_uint32Values_mirror[0];
+ uint32 *value = m_uint32Values;
+ uint32 *mirror = m_uint32Values_mirror;
- for(uint16 index = 0; index < m_valuesCount; ++index)
+ for(uint16 index = 0; index < m_valuesCount; ++index, ++value, ++mirror)
{
- if(m_uint32Values_mirror[index]!= m_uint32Values[index])
+ if(*mirror != *value)
updateMask->SetBit(index);
}
}
void Object::_SetCreateBits(UpdateMask *updateMask, Player* /*target*/) const
{
- for( uint16 index = 0; index < m_valuesCount; index++ )
+ uint32 *value = m_uint32Values;
+
+ for(uint16 index = 0; index < m_valuesCount; ++index, ++value)
{
- if(GetUInt32Value(index) != 0)
+ if(*value)
updateMask->SetBit(index);
}
}
@@ -1147,8 +1137,7 @@ bool Object::PrintIndexError(uint32 index, bool set) const
WorldObject::WorldObject()
: m_mapId(0), m_InstanceId(0), m_phaseMask(PHASEMASK_NORMAL),
- m_positionX(0.0f), m_positionY(0.0f), m_positionZ(0.0f), m_orientation(0.0f),
- mSemaphoreTeleport(false)
+ m_positionX(0.0f), m_positionY(0.0f), m_positionZ(0.0f), m_orientation(0.0f)
{
m_positionX = 0.0f;
m_positionY = 0.0f;
@@ -1160,8 +1149,6 @@ WorldObject::WorldObject()
m_name = "";
- mSemaphoreTeleport = false;
-
m_isActive = false;
IsTempWorldObject = false;
}
@@ -1256,6 +1243,13 @@ float WorldObject::GetDistance2d(float x, float y) const
return ( dist > 0 ? dist : 0);
}
+float WorldObject::GetExactDistance2d(const float x, const float y) const
+{
+ float dx = GetPositionX() - x;
+ float dy = GetPositionY() - y;
+ return sqrt((dx*dx) + (dy*dy));
+}
+
float WorldObject::GetDistance(const float x, const float y, const float z) const
{
float dx = GetPositionX() - x;
@@ -1618,7 +1612,17 @@ void WorldObject::BuildHeartBeatMsg(WorldPacket *data) const
*data << m_positionY;
*data << m_positionZ;
*data << m_orientation;
- *data << uint32(0);
+ if(GetTypeId() == TYPEID_PLAYER && ((Unit*)this)->hasUnitState(UNIT_STAT_ONVEHICLE))
+ {
+ *data << uint64(((Unit*)this)->GetCharmGUID());
+ *data << float(((Player*)this)->GetTransOffsetX());
+ *data << float(((Player*)this)->GetTransOffsetY());
+ *data << float(((Player*)this)->GetTransOffsetZ());
+ *data << float(((Player*)this)->GetTransOffsetO());
+ *data << uint32(((Player*)this)->GetTransTime());
+ *data << uint8(((Player*)this)->GetTransSeat());
+ }
+ *data << uint32(0); //fall time
}
void WorldObject::BuildTeleportAckMsg(WorldPacket *data, float x, float y, float z, float ang) const
@@ -1637,6 +1641,16 @@ void WorldObject::BuildTeleportAckMsg(WorldPacket *data, float x, float y, float
*data << y;
*data << z;
*data << ang;
+ if(GetTypeId() == TYPEID_PLAYER && ((Unit*)this)->hasUnitState(UNIT_STAT_ONVEHICLE))
+ {
+ *data << uint64(((Unit*)this)->GetCharmGUID());
+ *data << float(((Player*)this)->GetTransOffsetX());
+ *data << float(((Player*)this)->GetTransOffsetY());
+ *data << float(((Player*)this)->GetTransOffsetZ());
+ *data << float(((Player*)this)->GetTransOffsetO());
+ *data << uint32(((Player*)this)->GetTransTime());
+ *data << uint8(((Player*)this)->GetTransSeat());
+ }
*data << uint32(0);
}
@@ -1674,7 +1688,9 @@ Map const* WorldObject::GetBaseMap() const
void WorldObject::AddObjectToRemoveList()
{
- Map* map = MapManager::Instance().FindMap(GetMapId(), GetInstanceId());
+ assert(m_uint32Values);
+
+ Map* map = FindMap();
if(!map)
{
sLog.outError("Object (TypeId: %u Entry: %u GUID: %u) at attempt add to move list not have valid map (Id: %u).",GetTypeId(),GetEntry(),GetGUIDLow(),GetMapId());
diff --git a/src/game/Object.h b/src/game/Object.h
index a4b7506ca30..d46abd6d263 100644
--- a/src/game/Object.h
+++ b/src/game/Object.h
@@ -28,7 +28,6 @@
#include "GameSystem/GridReference.h"
#include "ObjectDefines.h"
#include "GridDefines.h"
-#include "CreatureAI.h"
#include "Map.h"
#include <set>
@@ -106,6 +105,7 @@ class InstanceData;
class GameObject;
class TempSummon;
class Vehicle;
+class CreatureAI;
typedef UNORDERED_MAP<Player*, UpdateData> UpdateDataMapType;
@@ -127,7 +127,7 @@ class TRINITY_DLL_SPEC Object
public:
virtual ~Object ( );
- const bool& IsInWorld() const { return m_inWorld; }
+ const bool IsInWorld() const { return m_inWorld; }
virtual void AddToWorld()
{
if(m_inWorld)
@@ -455,6 +455,7 @@ class TRINITY_DLL_SPEC WorldObject : public Object
float GetDistanceSq(const float &x, const float &y, const float &z) const;
float GetDistance2d(const WorldObject* obj) const;
float GetDistance2d(const float x, const float y) const;
+ float GetExactDistance2d(const float x, const float y) const;
float GetDistanceZ(const WorldObject* obj) const;
bool IsInMap(const WorldObject* obj) const
{
@@ -474,8 +475,6 @@ class TRINITY_DLL_SPEC WorldObject : public Object
virtual void SendMessageToSetInRange(WorldPacket *data, float dist, bool self, bool to_possessor = true);
void BuildHeartBeatMsg( WorldPacket *data ) const;
void BuildTeleportAckMsg( WorldPacket *data, float x, float y, float z, float ang) const;
- bool IsBeingTeleported() { return mSemaphoreTeleport; }
- void SetSemaphoreTeleport(bool semphsetting) { mSemaphoreTeleport = semphsetting; }
void MonsterSay(const char* text, uint32 language, uint64 TargetGuid);
void MonsterYell(const char* text, uint32 language, uint64 TargetGuid);
@@ -538,8 +537,6 @@ class TRINITY_DLL_SPEC WorldObject : public Object
float m_positionY;
float m_positionZ;
float m_orientation;
-
- bool mSemaphoreTeleport;
};
#endif
diff --git a/src/game/ObjectAccessor.h b/src/game/ObjectAccessor.h
index d1549712f30..1f413e2db40 100644
--- a/src/game/ObjectAccessor.h
+++ b/src/game/ObjectAccessor.h
@@ -164,22 +164,11 @@ class TRINITY_DLL_DECL ObjectAccessor : public Trinity::Singleton<ObjectAccessor
return HashMapHolder<Creature>::GetContainer();
}
- HashMapHolder<Unit>::MapType& GetUnits()
- {
- return HashMapHolder<Unit>::GetContainer();
- }
-
HashMapHolder<GameObject>::MapType& GetGameObjects()
{
return HashMapHolder<GameObject>::GetContainer();
}
- // note: possibly very heavy
- HashMapHolder<WorldObject>::MapType& GetWorldObjects()
- {
- return HashMapHolder<WorldObject>::GetContainer();
- }
-
template<class T> void AddObject(T *object)
{
HashMapHolder<T>::Insert(object);
diff --git a/src/game/ObjectGridLoader.cpp b/src/game/ObjectGridLoader.cpp
index 78727fc7c0a..d3e8397baaa 100644
--- a/src/game/ObjectGridLoader.cpp
+++ b/src/game/ObjectGridLoader.cpp
@@ -28,6 +28,7 @@
#include "Corpse.h"
#include "World.h"
#include "CellImpl.h"
+#include "CreatureAI.h"
class TRINITY_DLL_DECL ObjectGridRespawnMover
{
@@ -53,11 +54,10 @@ ObjectGridRespawnMover::Visit(CreatureMapType &m)
// creature in unloading grid can have respawn point in another grid
// if it will be unloaded then it will not respawn in original grid until unload/load original grid
// move to respawn point to prevent this case. For player view in respawn grid this will be normal respawn.
- for(CreatureMapType::iterator iter=m.begin(), next; iter != m.end(); iter = next)
+ for(CreatureMapType::iterator iter = m.begin(); iter != m.end();)
{
- next = iter; ++next;
-
Creature * c = iter->getSource();
+ ++iter;
assert(!c->isWorldCreature() && "ObjectGridRespawnMover don't must be called for pets");
diff --git a/src/game/ObjectMgr.cpp b/src/game/ObjectMgr.cpp
index 1b0f347b8aa..efb5d0974ca 100644
--- a/src/game/ObjectMgr.cpp
+++ b/src/game/ObjectMgr.cpp
@@ -5585,6 +5585,61 @@ struct SQLGameObjectLoader : public SQLStorageLoaderBase<SQLGameObjectLoader>
}
};
+inline void CheckGOLockId(GameObjectInfo const* goInfo,uint32 dataN,uint32 N)
+{
+ if (sLockStore.LookupEntry(dataN))
+ return;
+
+ sLog.outErrorDb("Gameobject (Entry: %u GoType: %u) have data%d=%u but lock (Id: %u) not found.",
+ goInfo->id,goInfo->type,N,goInfo->door.lockId,goInfo->door.lockId);
+}
+
+inline void CheckGOLinkedTrapId(GameObjectInfo const* goInfo,uint32 dataN,uint32 N)
+{
+ if (GameObjectInfo const* trapInfo = sGOStorage.LookupEntry<GameObjectInfo>(dataN))
+ {
+ if (trapInfo->type!=GAMEOBJECT_TYPE_TRAP)
+ sLog.outErrorDb("Gameobject (Entry: %u GoType: %u) have data%d=%u but GO (Entry %u) have not GAMEOBJECT_TYPE_TRAP (%u) type.",
+ goInfo->id,goInfo->type,N,dataN,dataN,GAMEOBJECT_TYPE_TRAP);
+ }
+ /* disable check for while (too many error reports baout not existed in trap templates
+ else
+ sLog.outErrorDb("Gameobject (Entry: %u GoType: %u) have data%d=%u but trap GO (Entry %u) not exist in `gameobject_template`.",
+ goInfo->id,goInfo->type,N,dataN,dataN);
+ */
+}
+
+inline void CheckGOSpellId(GameObjectInfo const* goInfo,uint32 dataN,uint32 N)
+{
+ if (sSpellStore.LookupEntry(dataN))
+ return;
+
+ sLog.outErrorDb("Gameobject (Entry: %u GoType: %u) have data%d=%u but Spell (Entry %u) not exist.",
+ goInfo->id,goInfo->type,N,dataN,dataN);
+}
+
+inline void CheckAndFixGOChairHeightId(GameObjectInfo const* goInfo,uint32 const& dataN,uint32 N)
+{
+ if (dataN <= (UNIT_STAND_STATE_SIT_HIGH_CHAIR-UNIT_STAND_STATE_SIT_LOW_CHAIR) )
+ return;
+
+ sLog.outErrorDb("Gameobject (Entry: %u GoType: %u) have data%d=%u but correct chair height in range 0..%i.",
+ goInfo->id,goInfo->type,N,dataN,UNIT_STAND_STATE_SIT_HIGH_CHAIR-UNIT_STAND_STATE_SIT_LOW_CHAIR);
+
+ // prevent client and server unexpected work
+ const_cast<uint32&>(dataN) = 0;
+}
+
+inline void CheckGONoDamageImmuneId(GameObjectInfo const* goInfo,uint32 dataN,uint32 N)
+{
+ // 0/1 correct values
+ if (dataN <= 1)
+ return;
+
+ sLog.outErrorDb("Gameobject (Entry: %u GoType: %u) have data%d=%u but expected boolean (0/1) noDamageImmune field value.",
+ goInfo->id,goInfo->type,N,dataN);
+}
+
void ObjectMgr::LoadGameobjectInfo()
{
SQLGameObjectLoader loader;
@@ -5594,139 +5649,104 @@ void ObjectMgr::LoadGameobjectInfo()
for(uint32 id = 1; id < sGOStorage.MaxEntry; id++)
{
GameObjectInfo const* goInfo = sGOStorage.LookupEntry<GameObjectInfo>(id);
- if(!goInfo)
+ if (!goInfo)
continue;
switch(goInfo->type)
{
case GAMEOBJECT_TYPE_DOOR: //0
{
- if(goInfo->door.lockId)
- {
- if(!sLockStore.LookupEntry(goInfo->door.lockId))
- sLog.outErrorDb("Gameobject (Entry: %u GoType: %u) have data1=%u but lock (Id: %u) not found.",
- id,goInfo->type,goInfo->door.lockId,goInfo->door.lockId);
- }
+ if (goInfo->door.lockId)
+ CheckGOLockId(goInfo,goInfo->door.lockId,1);
+ CheckGONoDamageImmuneId(goInfo,goInfo->door.noDamageImmune,3);
break;
}
case GAMEOBJECT_TYPE_BUTTON: //1
{
- if(goInfo->button.lockId)
- {
- if(!sLockStore.LookupEntry(goInfo->button.lockId))
- sLog.outErrorDb("Gameobject (Entry: %u GoType: %u) have data1=%u but lock (Id: %u) not found.",
- id,goInfo->type,goInfo->button.lockId,goInfo->button.lockId);
- }
+ if (goInfo->button.lockId)
+ CheckGOLockId(goInfo,goInfo->button.lockId,1);
+ CheckGONoDamageImmuneId(goInfo,goInfo->button.noDamageImmune,4);
+ break;
+ }
+ case GAMEOBJECT_TYPE_QUESTGIVER: //2
+ {
+ if (goInfo->questgiver.lockId)
+ CheckGOLockId(goInfo,goInfo->questgiver.lockId,0);
+ CheckGONoDamageImmuneId(goInfo,goInfo->questgiver.noDamageImmune,5);
break;
}
case GAMEOBJECT_TYPE_CHEST: //3
{
- if(goInfo->chest.lockId)
- {
- if(!sLockStore.LookupEntry(goInfo->chest.lockId))
- sLog.outErrorDb("Gameobject (Entry: %u GoType: %u) have data0=%u but lock (Id: %u) not found.",
- id,goInfo->type,goInfo->chest.lockId,goInfo->chest.lockId);
- }
- if(goInfo->chest.linkedTrapId) // linked trap
- {
- if(GameObjectInfo const* trapInfo = sGOStorage.LookupEntry<GameObjectInfo>(goInfo->chest.linkedTrapId))
- {
- if(trapInfo->type!=GAMEOBJECT_TYPE_TRAP)
- sLog.outErrorDb("Gameobject (Entry: %u GoType: %u) have data7=%u but GO (Entry %u) have not GAMEOBJECT_TYPE_TRAP (%u) type.",
- id,goInfo->type,goInfo->chest.linkedTrapId,goInfo->chest.linkedTrapId,GAMEOBJECT_TYPE_TRAP);
- }
- /* disable check for while
- else
- sLog.outErrorDb("Gameobject (Entry: %u GoType: %u) have data2=%u but trap GO (Entry %u) not exist in `gameobject_template`.",
- id,goInfo->type,goInfo->chest.linkedTrapId,goInfo->chest.linkedTrapId);
- */
- }
+ if (goInfo->chest.lockId)
+ CheckGOLockId(goInfo,goInfo->chest.lockId,0);
+
+ if (goInfo->chest.linkedTrapId) // linked trap
+ CheckGOLinkedTrapId(goInfo,goInfo->chest.linkedTrapId,7);
break;
}
case GAMEOBJECT_TYPE_TRAP: //6
{
- /* disable check for while
- if(goInfo->trap.spellId) // spell
- {
- if(!sSpellStore.LookupEntry(goInfo->trap.spellId))
- sLog.outErrorDb("Gameobject (Entry: %u GoType: %u) have data3=%u but Spell (Entry %u) not exist.",
- id,goInfo->type,goInfo->trap.spellId,goInfo->trap.spellId);
- }
+ if (goInfo->trap.lockId)
+ CheckGOLockId(goInfo,goInfo->trap.lockId,0);
+ /* disable check for while, too many not existed spells
+ if (goInfo->trap.spellId) // spell
+ CheckGOSpellId(goInfo,goInfo->trap.spellId,3);
*/
break;
}
case GAMEOBJECT_TYPE_CHAIR: //7
- if(goInfo->chair.height > (UNIT_STAND_STATE_SIT_HIGH_CHAIR-UNIT_STAND_STATE_SIT_LOW_CHAIR) )
- {
- sLog.outErrorDb("Gameobject (Entry: %u GoType: %u) have data1=%u but correct chair height in range 0..%i.",
- id,goInfo->type,goInfo->chair.height,UNIT_STAND_STATE_SIT_HIGH_CHAIR-UNIT_STAND_STATE_SIT_LOW_CHAIR);
-
- // prevent client and server unexpected work
- const_cast<GameObjectInfo*>(goInfo)->chair.height = 0;
- }
+ CheckAndFixGOChairHeightId(goInfo,goInfo->chair.height,1);
break;
case GAMEOBJECT_TYPE_SPELL_FOCUS: //8
{
- if(goInfo->spellFocus.focusId)
+ if (goInfo->spellFocus.focusId)
{
- if(!sSpellFocusObjectStore.LookupEntry(goInfo->spellFocus.focusId))
+ if (!sSpellFocusObjectStore.LookupEntry(goInfo->spellFocus.focusId))
sLog.outErrorDb("Gameobject (Entry: %u GoType: %u) have data0=%u but SpellFocus (Id: %u) not exist.",
id,goInfo->type,goInfo->spellFocus.focusId,goInfo->spellFocus.focusId);
}
- if(goInfo->spellFocus.linkedTrapId) // linked trap
- {
- if(GameObjectInfo const* trapInfo = sGOStorage.LookupEntry<GameObjectInfo>(goInfo->spellFocus.linkedTrapId))
- {
- if(trapInfo->type!=GAMEOBJECT_TYPE_TRAP)
- sLog.outErrorDb("Gameobject (Entry: %u GoType: %u) have data2=%u but GO (Entry %u) have not GAMEOBJECT_TYPE_TRAP (%u) type.",
- id,goInfo->type,goInfo->spellFocus.linkedTrapId,goInfo->spellFocus.linkedTrapId,GAMEOBJECT_TYPE_TRAP);
- }
- /* disable check for while
- else
- sLog.outErrorDb("Gameobject (Entry: %u GoType: %u) have data2=%u but trap GO (Entry %u) not exist in `gameobject_template`.",
- id,goInfo->type,goInfo->spellFocus.linkedTrapId,goInfo->spellFocus.linkedTrapId);
- */
- }
+ if (goInfo->spellFocus.linkedTrapId) // linked trap
+ CheckGOLinkedTrapId(goInfo,goInfo->spellFocus.linkedTrapId,2);
break;
}
case GAMEOBJECT_TYPE_GOOBER: //10
{
- if(goInfo->goober.pageId) // pageId
+ if (goInfo->goober.lockId)
+ CheckGOLockId(goInfo,goInfo->goober.lockId,0);
+
+ if (goInfo->goober.pageId) // pageId
{
- if(!sPageTextStore.LookupEntry<PageText>(goInfo->goober.pageId))
+ if (!sPageTextStore.LookupEntry<PageText>(goInfo->goober.pageId))
sLog.outErrorDb("Gameobject (Entry: %u GoType: %u) have data7=%u but PageText (Entry %u) not exist.",
id,goInfo->type,goInfo->goober.pageId,goInfo->goober.pageId);
}
- /* disable check for while
- if(goInfo->goober.spellId) // spell
- {
- if(!sSpellStore.LookupEntry(goInfo->goober.spellId))
- sLog.outErrorDb("Gameobject (Entry: %u GoType: %u) have data2=%u but Spell (Entry %u) not exist.",
- id,goInfo->type,goInfo->goober.spellId,goInfo->goober.spellId);
- }
+ /* disable check for while, too many not existed spells
+ if (goInfo->goober.spellId) // spell
+ CheckGOSpellId(goInfo,goInfo->goober.spellId,10);
*/
- if(goInfo->goober.linkedTrapId) // linked trap
- {
- if(GameObjectInfo const* trapInfo = sGOStorage.LookupEntry<GameObjectInfo>(goInfo->goober.linkedTrapId))
- {
- if(trapInfo->type!=GAMEOBJECT_TYPE_TRAP)
- sLog.outErrorDb("Gameobject (Entry: %u GoType: %u) have data12=%u but GO (Entry %u) have not GAMEOBJECT_TYPE_TRAP (%u) type.",
- id,goInfo->type,goInfo->goober.linkedTrapId,goInfo->goober.linkedTrapId,GAMEOBJECT_TYPE_TRAP);
- }
- /* disable check for while
- else
- sLog.outErrorDb("Gameobject (Entry: %u GoType: %u) have data12=%u but trap GO (Entry %u) not exist in `gameobject_template`.",
- id,goInfo->type,goInfo->goober.linkedTrapId,goInfo->goober.linkedTrapId);
- */
- }
+ CheckGONoDamageImmuneId(goInfo,goInfo->goober.noDamageImmune,11);
+ if (goInfo->goober.linkedTrapId) // linked trap
+ CheckGOLinkedTrapId(goInfo,goInfo->goober.linkedTrapId,12);
+ break;
+ }
+ case GAMEOBJECT_TYPE_AREADAMAGE: //12
+ {
+ if (goInfo->areadamage.lockId)
+ CheckGOLockId(goInfo,goInfo->areadamage.lockId,0);
+ break;
+ }
+ case GAMEOBJECT_TYPE_CAMERA: //13
+ {
+ if (goInfo->camera.lockId)
+ CheckGOLockId(goInfo,goInfo->camera.lockId,0);
break;
}
case GAMEOBJECT_TYPE_MO_TRANSPORT: //15
{
- if(goInfo->moTransport.taxiPathId)
+ if (goInfo->moTransport.taxiPathId)
{
- if(goInfo->moTransport.taxiPathId >= sTaxiPathNodesByPath.size() || sTaxiPathNodesByPath[goInfo->moTransport.taxiPathId].empty())
+ if (goInfo->moTransport.taxiPathId >= sTaxiPathNodesByPath.size() || sTaxiPathNodesByPath[goInfo->moTransport.taxiPathId].empty())
sLog.outErrorDb("Gameobject (Entry: %u GoType: %u) have data0=%u but TaxiPath (Id: %u) not exist.",
id,goInfo->type,goInfo->moTransport.taxiPathId,goInfo->moTransport.taxiPathId);
}
@@ -5734,35 +5754,40 @@ void ObjectMgr::LoadGameobjectInfo()
}
case GAMEOBJECT_TYPE_SUMMONING_RITUAL: //18
{
- /* disabled
- if(goInfo->summoningRitual.spellId)
- {
- if(!sSpellStore.LookupEntry(goInfo->summoningRitual.spellId))
- sLog.outErrorDb("Gameobject (Entry: %u GoType: %u) have data1=%u but Spell (Entry %u) not exist.",
- id,goInfo->type,goInfo->summoningRitual.spellId,goInfo->summoningRitual.spellId);
- }
+ /* disable check for while, too many not existed spells
+ // always must have spell
+ CheckGOSpellId(goInfo,goInfo->summoningRitual.spellId,1);
*/
break;
}
case GAMEOBJECT_TYPE_SPELLCASTER: //22
{
- if(goInfo->spellcaster.spellId) // spell
- {
- if(!sSpellStore.LookupEntry(goInfo->spellcaster.spellId))
- sLog.outErrorDb("Gameobject (Entry: %u GoType: %u) have data3=%u but Spell (Entry %u) not exist.",
- id,goInfo->type,goInfo->spellcaster.spellId,goInfo->spellcaster.spellId);
- }
+ // always must have spell
+ CheckGOSpellId(goInfo,goInfo->spellcaster.spellId,0);
+ break;
+ }
+ case GAMEOBJECT_TYPE_FLAGSTAND: //24
+ {
+ if (goInfo->flagstand.lockId)
+ CheckGOLockId(goInfo,goInfo->flagstand.lockId,0);
+ CheckGONoDamageImmuneId(goInfo,goInfo->flagstand.noDamageImmune,5);
+ break;
+ }
+ case GAMEOBJECT_TYPE_FISHINGHOLE: //25
+ {
+ if (goInfo->fishinghole.lockId)
+ CheckGOLockId(goInfo,goInfo->fishinghole.lockId,4);
+ break;
+ }
+ case GAMEOBJECT_TYPE_FLAGDROP: //26
+ {
+ if (goInfo->flagdrop.lockId)
+ CheckGOLockId(goInfo,goInfo->flagdrop.lockId,0);
+ CheckGONoDamageImmuneId(goInfo,goInfo->flagdrop.noDamageImmune,3);
break;
}
case GAMEOBJECT_TYPE_BARBER_CHAIR: //32
- if(goInfo->barberChair.chairheight > (UNIT_STAND_STATE_SIT_HIGH_CHAIR-UNIT_STAND_STATE_SIT_LOW_CHAIR) )
- {
- sLog.outErrorDb("Gameobject (Entry: %u GoType: %u) have data1=%u but correct chair height in range 0..%i.",
- id,goInfo->type,goInfo->barberChair.chairheight,UNIT_STAND_STATE_SIT_HIGH_CHAIR-UNIT_STAND_STATE_SIT_LOW_CHAIR);
-
- // prevent client and server unexpected work
- const_cast<GameObjectInfo*>(goInfo)->barberChair.chairheight = 0;
- }
+ CheckAndFixGOChairHeightId(goInfo,goInfo->barberChair.chairheight,0);
break;
}
}
diff --git a/src/game/Pet.cpp b/src/game/Pet.cpp
index 1d45ed3a7fd..e723298565a 100644
--- a/src/game/Pet.cpp
+++ b/src/game/Pet.cpp
@@ -99,20 +99,28 @@ bool Pet::LoadPetFromDB( Player* owner, uint32 petentry, uint32 petnumber, bool
QueryResult *result;
- if(petnumber)
- // known petnumber entry 0 1 2(?) 3 4 5 6 7 8(?) 9 10 11 12 13 14 15 16 17 18 19 20
- result = CharacterDatabase.PQuery("SELECT id, entry, owner, modelid, level, exp, Reactstate, talentpoints, slot, name, renamed, curhealth, curmana, curhappiness, abdata, TeachSpelldata, savetime, resettalents_cost, resettalents_time, CreatedBySpell, PetType FROM character_pet WHERE owner = '%u' AND id = '%u'",ownerid, petnumber);
- else if(current)
- // current pet (slot 0) 0 1 2(?) 3 4 5 6 7 8(?) 9 10 11 12 13 14 15 16 17 18 19 20
- result = CharacterDatabase.PQuery("SELECT id, entry, owner, modelid, level, exp, Reactstate, talentpoints, slot, name, renamed, curhealth, curmana, curhappiness, abdata, TeachSpelldata, savetime, resettalents_cost, resettalents_time, CreatedBySpell, PetType FROM character_pet WHERE owner = '%u' AND slot = '0'",ownerid );
- else if(petentry)
+ if (petnumber)
+ // known petnumber entry 0 1 2(?) 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
+ result = CharacterDatabase.PQuery("SELECT id, entry, owner, modelid, level, exp, Reactstate, talentpoints, slot, name, renamed, curhealth, curmana, curhappiness, abdata, TeachSpelldata, savetime, resettalents_cost, resettalents_time, CreatedBySpell, PetType "
+ "FROM character_pet WHERE owner = '%u' AND id = '%u'",
+ ownerid, petnumber);
+ else if (current)
+ // current pet (slot 0) 0 1 2(?) 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
+ result = CharacterDatabase.PQuery("SELECT id, entry, owner, modelid, level, exp, Reactstate, talentpoints, slot, name, renamed, curhealth, curmana, curhappiness, abdata, TeachSpelldata, savetime, resettalents_cost, resettalents_time, CreatedBySpell, PetType "
+ "FROM character_pet WHERE owner = '%u' AND slot = '%u'",
+ ownerid, PET_SAVE_AS_CURRENT );
+ else if (petentry)
// known petentry entry (unique for summoned pet, but non unique for hunter pet (only from current or not stabled pets)
- // 0 1 2(?) 3 4 5 6 7 8(?) 9 10 11 12 13 14 15 16 17 18 19 20
- result = CharacterDatabase.PQuery("SELECT id, entry, owner, modelid, level, exp, Reactstate, talentpoints, slot, name, renamed, curhealth, curmana, curhappiness, abdata, TeachSpelldata, savetime, resettalents_cost, resettalents_time, CreatedBySpell, PetType FROM character_pet WHERE owner = '%u' AND entry = '%u' AND (slot = '0' OR slot = '3') ",ownerid, petentry );
+ // 0 1 2(?) 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
+ result = CharacterDatabase.PQuery("SELECT id, entry, owner, modelid, level, exp, Reactstate, talentpoints, slot, name, renamed, curhealth, curmana, curhappiness, abdata, TeachSpelldata, savetime, resettalents_cost, resettalents_time, CreatedBySpell, PetType "
+ "FROM character_pet WHERE owner = '%u' AND entry = '%u' AND (slot = '%u' OR slot > '%u') ",
+ ownerid, petentry,PET_SAVE_AS_CURRENT,PET_SAVE_LAST_STABLE_SLOT);
else
// any current or other non-stabled pet (for hunter "call pet")
- // 0 1 2(?) 3 4 5 6 7 8(?) 9 10 11 12 13 14 15 16 17 18 19 20
- result = CharacterDatabase.PQuery("SELECT id, entry, owner, modelid, level, exp, Reactstate, talentpoints, slot, name, renamed, curhealth, curmana, curhappiness, abdata, TeachSpelldata, savetime, resettalents_cost, resettalents_time, CreatedBySpell, PetType FROM character_pet WHERE owner = '%u' AND (slot = '0' OR slot = '3') ",ownerid);
+ // 0 1 2(?) 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
+ result = CharacterDatabase.PQuery("SELECT id, entry, owner, modelid, level, exp, Reactstate, talentpoints, slot, name, renamed, curhealth, curmana, curhappiness, abdata, TeachSpelldata, savetime, resettalents_cost, resettalents_time, CreatedBySpell, PetType "
+ "FROM character_pet WHERE owner = '%u' AND (slot = '%u' OR slot > '%u') ",
+ ownerid,PET_SAVE_AS_CURRENT,PET_SAVE_LAST_STABLE_SLOT);
if(!result)
return false;
@@ -121,7 +129,7 @@ bool Pet::LoadPetFromDB( Player* owner, uint32 petentry, uint32 petnumber, bool
// update for case of current pet "slot = 0"
petentry = fields[1].GetUInt32();
- if(!petentry)
+ if (!petentry)
{
delete result;
return false;
@@ -133,16 +141,24 @@ bool Pet::LoadPetFromDB( Player* owner, uint32 petentry, uint32 petnumber, bool
bool is_temporary_summoned = spellInfo && GetSpellDuration(spellInfo) > 0;
// check temporary summoned pets like mage water elemental
- if(current && is_temporary_summoned)
+ if (current && is_temporary_summoned)
{
delete result;
return false;
}
+ uint32 pet_number = fields[0].GetUInt32();
+
+ if (current && owner->IsPetNeedBeTemporaryUnsummoned())
+ {
+ owner->SetTemporaryUnsummonedPetNumber(pet_number);
+ delete result;
+ return false;
+ }
+
Map *map = owner->GetMap();
uint32 guid = objmgr.GenerateLowGuid(HIGHGUID_PET);
- uint32 pet_number = fields[0].GetUInt32();
- if(!Create(guid, map, owner->GetPhaseMask(), petentry, pet_number))
+ if (!Create(guid, map, owner->GetPhaseMask(), petentry, pet_number))
{
delete result;
return false;
@@ -151,7 +167,8 @@ bool Pet::LoadPetFromDB( Player* owner, uint32 petentry, uint32 petnumber, bool
float px, py, pz;
owner->GetClosePoint(px, py, pz, GetObjectSize(), PET_FOLLOW_DIST, PET_FOLLOW_ANGLE);
Relocate(px, py, pz, owner->GetOrientation());
- if(!IsPositionValid())
+
+ if (!IsPositionValid())
{
sLog.outError("Pet (guidlow %d, entry %d) not loaded. Suggested coordinates isn't valid (X: %f Y: %f)",
GetGUIDLow(), GetEntry(), GetPositionX(), GetPositionY());
@@ -164,24 +181,29 @@ bool Pet::LoadPetFromDB( Player* owner, uint32 petentry, uint32 petnumber, bool
SetUInt32Value(UNIT_CREATED_BY_SPELL, summon_spell_id);
CreatureInfo const *cinfo = GetCreatureInfo();
- if(cinfo->type == CREATURE_TYPE_CRITTER)
+ if (cinfo->type == CREATURE_TYPE_CRITTER)
{
map->Add((Creature*)this);
delete result;
return true;
}
- if(getPetType() == HUNTER_PET || (getPetType() == SUMMON_PET && cinfo->type == CREATURE_TYPE_DEMON && owner->getClass() == CLASS_WARLOCK))
+ if (getPetType() == HUNTER_PET || (getPetType() == SUMMON_PET && cinfo->type == CREATURE_TYPE_DEMON && owner->getClass() == CLASS_WARLOCK))
m_charmInfo->SetPetNumber(pet_number, true);
else
m_charmInfo->SetPetNumber(pet_number, false);
// set current pet as current
+ // 0=current
+ // 1..MAX_PET_STABLES in stable slot
+ // PET_SAVE_NOT_IN_SLOT(100) = not stable slot (summoning))
if(fields[8].GetUInt32() != 0)
{
CharacterDatabase.BeginTransaction();
- CharacterDatabase.PExecute("UPDATE character_pet SET slot = '3' WHERE owner = '%u' AND slot = '0' AND id <> '%u'", ownerid, m_charmInfo->GetPetNumber());
- CharacterDatabase.PExecute("UPDATE character_pet SET slot = '0' WHERE owner = '%u' AND id = '%u'", ownerid, m_charmInfo->GetPetNumber());
+ CharacterDatabase.PExecute("UPDATE character_pet SET slot = '%u' WHERE owner = '%u' AND slot = '%u' AND id <> '%u'",
+ PET_SAVE_NOT_IN_SLOT, ownerid, PET_SAVE_AS_CURRENT, m_charmInfo->GetPetNumber());
+ CharacterDatabase.PExecute("UPDATE character_pet SET slot = '%u' WHERE owner = '%u' AND id = '%u'",
+ PET_SAVE_AS_CURRENT, ownerid, m_charmInfo->GetPetNumber());
CharacterDatabase.CommitTransaction();
}
@@ -191,7 +213,7 @@ bool Pet::LoadPetFromDB( Player* owner, uint32 petentry, uint32 petnumber, bool
SetUInt32Value(UNIT_NPC_FLAGS, 0);
SetName(fields[9].GetString());
- switch(getPetType())
+ switch (getPetType())
{
case SUMMON_PET:
petlevel=owner->getLevel();
@@ -247,12 +269,12 @@ bool Pet::LoadPetFromDB( Player* owner, uint32 petentry, uint32 petnumber, bool
_LoadSpells();
_LoadSpellCooldowns();
- if(!is_temporary_summoned)
+ if (!is_temporary_summoned)
{
// permanent controlled pets store state in DB
Tokens tokens = StrSplit(fields[14].GetString(), " ");
- if(tokens.size() != 20)
+ if (tokens.size() != 20)
{
delete result;
return false;
@@ -332,109 +354,112 @@ bool Pet::LoadPetFromDB( Player* owner, uint32 petentry, uint32 petnumber, bool
void Pet::SavePetToDB(PetSaveMode mode)
{
- if(!GetEntry())
+ if (!GetEntry())
return;
// save only fully controlled creature
- if(!isControlled())
+ if (!isControlled())
return;
+ // not save not player pets
+ if(!IS_PLAYER_GUID(GetOwnerGUID()))
+ return;
+
+ Player* pOwner = (Player*)GetOwner();
+ if (!pOwner)
+ return;
+
+ // not save pet as current if another pet temporary unsummoned
+ if (mode == PET_SAVE_AS_CURRENT && pOwner->GetTemporaryUnsummonedPetNumber() &&
+ pOwner->GetTemporaryUnsummonedPetNumber() != m_charmInfo->GetPetNumber())
+ {
+ // pet will lost anyway at restore temporary unsummoned
+ if(getPetType()==HUNTER_PET)
+ return;
+
+ // for warlock case
+ mode = PET_SAVE_NOT_IN_SLOT;
+ }
+
uint32 curhealth = GetHealth();
uint32 curmana = GetPower(POWER_MANA);
- switch(mode)
+ // stable and not in slot saves
+ if(mode > PET_SAVE_AS_CURRENT)
{
- case PET_SAVE_IN_STABLE_SLOT_1:
- case PET_SAVE_IN_STABLE_SLOT_2:
- case PET_SAVE_NOT_IN_SLOT:
- {
- RemoveAllAuras();
-
- //only alive hunter pets get auras saved, the others don't
- if(!(getPetType() == HUNTER_PET && isAlive()))
- m_Auras.clear();
- }
- default:
- break;
+ RemoveAllAuras();
}
_SaveSpells();
_SaveSpellCooldowns();
_SaveAuras();
- switch(mode)
+ // current/stable/not_in_slot
+ if(mode >= PET_SAVE_AS_CURRENT)
{
- case PET_SAVE_AS_CURRENT:
- case PET_SAVE_IN_STABLE_SLOT_1:
- case PET_SAVE_IN_STABLE_SLOT_2:
- case PET_SAVE_NOT_IN_SLOT:
+ uint32 owner = GUID_LOPART(GetOwnerGUID());
+ std::string name = m_name;
+ CharacterDatabase.escape_string(name);
+ CharacterDatabase.BeginTransaction();
+ // remove current data
+ CharacterDatabase.PExecute("DELETE FROM character_pet WHERE owner = '%u' AND id = '%u'", owner,m_charmInfo->GetPetNumber() );
+
+ // prevent duplicate using slot (except PET_SAVE_NOT_IN_SLOT)
+ if(mode <= PET_SAVE_LAST_STABLE_SLOT)
+ CharacterDatabase.PExecute("UPDATE character_pet SET slot = '%u' WHERE owner = '%u' AND slot = '%u'",
+ PET_SAVE_NOT_IN_SLOT, owner, uint32(mode) );
+
+ // prevent existence another hunter pet in PET_SAVE_AS_CURRENT and PET_SAVE_NOT_IN_SLOT
+ if(getPetType()==HUNTER_PET && (mode==PET_SAVE_AS_CURRENT||mode > PET_SAVE_LAST_STABLE_SLOT))
+ CharacterDatabase.PExecute("DELETE FROM character_pet WHERE owner = '%u' AND (slot = '%u' OR slot > '%u')",
+ owner,PET_SAVE_AS_CURRENT,PET_SAVE_LAST_STABLE_SLOT);
+ // save pet
+ std::ostringstream ss;
+ ss << "INSERT INTO character_pet ( id, entry, owner, modelid, level, exp, Reactstate, talentpoints, slot, name, renamed, curhealth, curmana, curhappiness, abdata, TeachSpelldata, savetime, resettalents_cost, resettalents_time, CreatedBySpell, PetType) "
+ << "VALUES ("
+ << m_charmInfo->GetPetNumber() << ", "
+ << GetEntry() << ", "
+ << owner << ", "
+ << GetNativeDisplayId() << ", "
+ << getLevel() << ", "
+ << GetUInt32Value(UNIT_FIELD_PETEXPERIENCE) << ", "
+ << uint32(GetReactState()) << ", "
+ << uint32(GetFreeTalentPoints()) << ", "
+ << uint32(mode) << ", '"
+ << name.c_str() << "', "
+ << uint32((GetByteValue(UNIT_FIELD_BYTES_2, 2) == UNIT_RENAME_ALLOWED)?0:1) << ", "
+ << (curhealth<1?1:curhealth) << ", "
+ << curmana << ", "
+ << GetPower(POWER_HAPPINESS) << ", '";
+
+ for(uint32 i = 0; i < 10; i++)
+ ss << uint32(m_charmInfo->GetActionBarEntry(i)->Type) << " " << uint32(m_charmInfo->GetActionBarEntry(i)->SpellOrAction) << " ";
+ ss << "', '";
+
+ //save spells the pet can teach to it's Master
{
- uint32 owner = GUID_LOPART(GetOwnerGUID());
- std::string name = m_name;
- CharacterDatabase.escape_string(name);
- CharacterDatabase.BeginTransaction();
- // remove current data
- CharacterDatabase.PExecute("DELETE FROM character_pet WHERE owner = '%u' AND id = '%u'", owner,m_charmInfo->GetPetNumber() );
-
- // prevent duplicate using slot (except PET_SAVE_NOT_IN_SLOT)
- if(mode!=PET_SAVE_NOT_IN_SLOT)
- CharacterDatabase.PExecute("UPDATE character_pet SET slot = 3 WHERE owner = '%u' AND slot = '%u'", owner, uint32(mode) );
-
- // prevent existence another hunter pet in PET_SAVE_AS_CURRENT and PET_SAVE_NOT_IN_SLOT
- if(getPetType()==HUNTER_PET && (mode==PET_SAVE_AS_CURRENT||mode==PET_SAVE_NOT_IN_SLOT))
- CharacterDatabase.PExecute("DELETE FROM character_pet WHERE owner = '%u' AND (slot = '0' OR slot = '3')", owner );
- // save pet
- std::ostringstream ss;
- ss << "INSERT INTO character_pet ( id, entry, owner, modelid, level, exp, Reactstate, talentpoints, slot, name, renamed, curhealth, curmana, curhappiness, abdata, TeachSpelldata, savetime, resettalents_cost, resettalents_time, CreatedBySpell, PetType) "
- << "VALUES ("
- << m_charmInfo->GetPetNumber() << ", "
- << GetEntry() << ", "
- << owner << ", "
- << GetNativeDisplayId() << ", "
- << getLevel() << ", "
- << GetUInt32Value(UNIT_FIELD_PETEXPERIENCE) << ", "
- << uint32(GetReactState()) << ", "
- << uint32(GetFreeTalentPoints()) << ", "
- << uint32(mode) << ", '"
- << name.c_str() << "', "
- << uint32((GetByteValue(UNIT_FIELD_BYTES_2, 2) == UNIT_RENAME_ALLOWED)?0:1) << ", "
- << (curhealth<1?1:curhealth) << ", "
- << curmana << ", "
- << GetPower(POWER_HAPPINESS) << ", '";
-
- for(uint32 i = 0; i < 10; i++)
- ss << uint32(m_charmInfo->GetActionBarEntry(i)->Type) << " " << uint32(m_charmInfo->GetActionBarEntry(i)->SpellOrAction) << " ";
- ss << "', '";
-
- //save spells the pet can teach to it's Master
- {
- int i = 0;
- for(TeachSpellMap::iterator itr = m_teachspells.begin(); i < 4 && itr != m_teachspells.end(); ++i, ++itr)
- ss << itr->first << " " << itr->second << " ";
- for(; i < 4; ++i)
- ss << uint32(0) << " " << uint32(0) << " ";
- }
-
- ss << "', "
- << time(NULL) << ", "
- << uint32(m_resetTalentsCost) << ", "
- << uint64(m_resetTalentsTime) << ", "
- << GetUInt32Value(UNIT_CREATED_BY_SPELL) << ", "
- << uint32(getPetType()) << ")";
+ int i = 0;
+ for(TeachSpellMap::iterator itr = m_teachspells.begin(); i < 4 && itr != m_teachspells.end(); ++i, ++itr)
+ ss << itr->first << " " << itr->second << " ";
+ for(; i < 4; ++i)
+ ss << uint32(0) << " " << uint32(0) << " ";
+ }
- CharacterDatabase.Execute( ss.str().c_str() );
+ ss << "', "
+ << time(NULL) << ", "
+ << uint32(m_resetTalentsCost) << ", "
+ << uint64(m_resetTalentsTime) << ", "
+ << GetUInt32Value(UNIT_CREATED_BY_SPELL) << ", "
+ << uint32(getPetType()) << ")";
- CharacterDatabase.CommitTransaction();
- break;
- }
- case PET_SAVE_AS_DELETED:
- {
- RemoveAllAuras();
- DeleteFromDB(m_charmInfo->GetPetNumber());
- break;
- }
- default:
- sLog.outError("Unknown pet save/remove mode: %d",mode);
+ CharacterDatabase.Execute( ss.str().c_str() );
+ CharacterDatabase.CommitTransaction();
+ }
+ // delete
+ else
+ {
+ RemoveAllAuras();
+ DeleteFromDB(m_charmInfo->GetPetNumber());
}
}
@@ -1148,15 +1173,14 @@ void Pet::_SaveAuras()
{
// skip all auras from spell that apply at cast SPELL_AURA_MOD_SHAPESHIFT or pet area auras.
// do not save single target auras (unless they were cast by the player)
- if (itr->second->IsPassive()
- || (itr->second->GetCasterGUID() != GetGUID() && itr->second->IsSingleTarget()))
+ if (itr->second->IsPassive() || itr->second->IsAuraType(SPELL_AURA_MOD_STEALTH))
continue;
- SpellEntry const *spellInfo = itr->second->GetSpellProto();
- for (uint8 i=0;i<MAX_SPELL_EFFECTS;++i)
- if (spellInfo->EffectApplyAuraName[i] == SPELL_AURA_MOD_STEALTH ||
- spellInfo->Effect[i] == SPELL_EFFECT_APPLY_AREA_AURA_OWNER ||
- spellInfo->Effect[i] == SPELL_EFFECT_APPLY_AREA_AURA_PET )
+ bool isCaster = itr->second->GetCasterGUID() == GetGUID();
+ if (!isCaster)
+ if (itr->second->IsSingleTarget()
+ || itr->second->IsAreaAura())
continue;
+
uint32 amounts[MAX_SPELL_EFFECTS];
for (uint8 i=0;i<MAX_SPELL_EFFECTS;++i)
{
diff --git a/src/game/Pet.h b/src/game/Pet.h
index 5879208a6b8..de998c20aac 100644
--- a/src/game/Pet.h
+++ b/src/game/Pet.h
@@ -35,13 +35,16 @@ enum PetType
extern char const* petTypeSuffix[MAX_PET_TYPE];
+#define MAX_PET_STABLES 4
+
+// stored in character_pet.slot
enum PetSaveMode
{
- PET_SAVE_AS_DELETED =-1,
- PET_SAVE_AS_CURRENT = 0,
- PET_SAVE_IN_STABLE_SLOT_1 = 1,
- PET_SAVE_IN_STABLE_SLOT_2 = 2,
- PET_SAVE_NOT_IN_SLOT = 3
+ PET_SAVE_AS_DELETED = -1, // not saved in fact
+ PET_SAVE_AS_CURRENT = 0, // in current slot (with player)
+ PET_SAVE_FIRST_STABLE_SLOT = 1,
+ PET_SAVE_LAST_STABLE_SLOT = MAX_PET_STABLES, // last in DB stable slot index (including), all higher have same meaning as PET_SAVE_NOT_IN_SLOT
+ PET_SAVE_NOT_IN_SLOT = 100 // for avoid conflict with stable size grow will use 100
};
enum HappinessState
diff --git a/src/game/PetitionsHandler.cpp b/src/game/PetitionsHandler.cpp
index 0ec0eee3d9e..61485c3eb04 100644
--- a/src/game/PetitionsHandler.cpp
+++ b/src/game/PetitionsHandler.cpp
@@ -254,7 +254,7 @@ void WorldSession::HandlePetitionShowSignOpcode(WorldPacket & recv_data)
QueryResult *result = CharacterDatabase.PQuery("SELECT type FROM petition WHERE petitionguid = '%u'", petitionguid_low);
if(!result)
{
- sLog.outError("any petition on server...");
+ sLog.outError("Petition %u is not found for player %u %s", GUID_LOPART(petitionguid), GetPlayer()->GetGUIDLow(), GetPlayer()->GetName());
return;
}
Field *fields = result->Fetch();
@@ -462,7 +462,7 @@ void WorldSession::HandlePetitionSignOpcode(WorldPacket & recv_data)
if(!result)
{
- sLog.outError("any petition on server...");
+ sLog.outError("Petition %u is not found for player %u %s", GUID_LOPART(petitionguid), GetPlayer()->GetGUIDLow(), GetPlayer()->GetName());
return;
}
diff --git a/src/game/Player.cpp b/src/game/Player.cpp
index 2eeb5d3548c..ae14d5ebc30 100644
--- a/src/game/Player.cpp
+++ b/src/game/Player.cpp
@@ -340,7 +340,8 @@ Player::Player (WorldSession *session): Unit(), m_achievementMgr(this), m_reputa
m_atLoginFlags = AT_LOGIN_NONE;
- m_dontMove = false;
+ mSemaphoreTeleport_Near = false;
+ mSemaphoreTeleport_Far = false;
pTrader = 0;
ClearTrade();
@@ -467,8 +468,6 @@ Player::Player (WorldSession *session): Unit(), m_achievementMgr(this), m_reputa
m_isActive = true;
- m_farsightVision = false;
-
m_runes = NULL;
m_lastFallTime = 0;
@@ -1645,9 +1644,7 @@ bool Player::TeleportTo(uint32 mapid, float x, float y, float z, float orientati
m_movementInfo.t_time = 0;
}
- SetSemaphoreTeleport(true);
-
- // The player was ported to another map and looses the duel immediatly.
+ // The player was ported to another map and looses the duel immediately.
// We have to perform this check before the teleport, otherwise the
// ObjectAccessor won't find the flag.
if (duel && GetMapId()!=mapid)
@@ -1662,72 +1659,29 @@ bool Player::TeleportTo(uint32 mapid, float x, float y, float z, float orientati
if ((GetMapId() == mapid) && (!m_transport))
{
- // prepare zone change detect
- uint32 old_zone = GetZoneId();
-
- // near teleport
- if(!GetSession()->PlayerLogout())
- {
- WorldPacket data;
- BuildTeleportAckMsg(&data, x, y, z, orientation);
- GetSession()->SendPacket(&data);
- SetPosition( x, y, z, orientation, true);
- }
- else
- // this will be used instead of the current location in SaveToDB
- m_teleport_dest = WorldLocation(mapid, x, y, z, orientation);
-
- SetFallInformation(0, z);
-
- //BuildHeartBeatMsg(&data);
- //SendMessageToSet(&data, true);
if (!(options & TELE_TO_NOT_UNSUMMON_PET))
{
- //same map, only remove pet if out of range
- if(pet && !IsWithinDistInMap(pet, OWNER_MAX_DISTANCE))
- {
- if(pet->isControlled() && !pet->isTemporarySummoned() )
- m_temporaryUnsummonedPetNumber = pet->GetCharmInfo()->GetPetNumber();
- else
- m_temporaryUnsummonedPetNumber = 0;
-
- RemovePet(pet, PET_SAVE_NOT_IN_SLOT);
- }
+ //same map, only remove pet if out of range for new position
+ if(pet && pet->GetDistance(x,y,z) >= OWNER_MAX_DISTANCE)
+ UnsummonPetTemporaryIfAny();
}
if(!(options & TELE_TO_NOT_LEAVE_COMBAT))
CombatStop();
- if (!(options & TELE_TO_NOT_UNSUMMON_PET))
- {
- // resummon pet
- if(pet && m_temporaryUnsummonedPetNumber)
- {
- Pet* NewPet = new Pet(this);
- if(!NewPet->LoadPetFromDB(this, 0, m_temporaryUnsummonedPetNumber, true))
- delete NewPet;
-
- m_temporaryUnsummonedPetNumber = 0;
- }
- }
-
- uint32 newzone, newarea;
- GetZoneAndAreaId(newzone,newarea);
+ // this will be used instead of the current location in SaveToDB
+ m_teleport_dest = WorldLocation(mapid, x, y, z, orientation);
+ SetFallInformation(0, z);
+ // code for finish transfer called in WorldSession::HandleMovementOpcodes()
+ // at client packet MSG_MOVE_TELEPORT_ACK
+ SetSemaphoreTeleportNear(true);
+ // near teleport, triggering send MSG_MOVE_TELEPORT_ACK from client at landing
if(!GetSession()->PlayerLogout())
{
- // don't reset teleport semaphore while logging out, otherwise m_teleport_dest won't be used in Player::SaveToDB
- SetSemaphoreTeleport(false);
-
- UpdateZone(newzone,newarea);
- }
-
- // new zone
- if(old_zone != newzone)
- {
- // honorless target
- if(pvpInfo.inHostileArea)
- CastSpell(this, 2479, true);
+ WorldPacket data;
+ BuildTeleportAckMsg(&data, x, y, z, orientation);
+ GetSession()->SendPacket(&data);
}
}
else
@@ -1739,10 +1693,7 @@ bool Player::TeleportTo(uint32 mapid, float x, float y, float z, float orientati
// Check enter rights before map getting to avoid creating instance copy for player
// this check not dependent from map instance copy and same for all instance copies of selected map
if (!MapManager::Instance().CanPlayerEnter(mapid, this))
- {
- SetSemaphoreTeleport(false);
return false;
- }
// If the map is not created, assume it is possible to enter it.
// It will be created in the WorldPortAck.
@@ -1767,15 +1718,7 @@ bool Player::TeleportTo(uint32 mapid, float x, float y, float z, float orientati
// remove pet on map change
if (pet)
- {
- //leaving map -> delete pet right away (doing this later will cause problems)
- if(pet->isControlled() && !pet->isTemporarySummoned())
- m_temporaryUnsummonedPetNumber = pet->GetCharmInfo()->GetPetNumber();
- else
- m_temporaryUnsummonedPetNumber = 0;
-
- RemovePet(pet, PET_SAVE_NOT_IN_SLOT);
- }
+ UnsummonPetTemporaryIfAny();
// remove all dyn objects
RemoveAllDynObjects();
@@ -1835,10 +1778,8 @@ bool Player::TeleportTo(uint32 mapid, float x, float y, float z, float orientati
RemoveAurasWithInterruptFlags(AURA_INTERRUPT_FLAG_CHANGE_MAP | AURA_INTERRUPT_FLAG_MOVE | AURA_INTERRUPT_FLAG_TURNING);
// move packet sent by client always after far teleport
- // SetPosition(final_x, final_y, final_z, final_o, true);
- SetDontMove(true);
-
// code for finish transfer to new map called in WorldSession::HandleMoveWorldportAckOpcode at client packet
+ SetSemaphoreTeleportFar(true);
}
else
return false;
@@ -2474,7 +2415,7 @@ void Player::InitStatsForLevel(bool reapplyMods)
SetUInt32Value(PLAYER_FIELD_MOD_TARGET_PHYSICAL_RESISTANCE,0);
for(int i = 0; i < MAX_SPELL_SCHOOL; ++i)
{
- SetFloatValue(UNIT_FIELD_POWER_COST_MODIFIER+i,0.0f);
+ SetUInt32Value(UNIT_FIELD_POWER_COST_MODIFIER+i,0);
SetFloatValue(UNIT_FIELD_POWER_COST_MULTIPLIER+i,0.0f);
}
// Reset no reagent cost field
@@ -3299,7 +3240,6 @@ void Player::_LoadSpellCooldowns(QueryResult *result)
// some cooldowns can be already set at aura loading...
//QueryResult *result = CharacterDatabase.PQuery("SELECT spell,item,time FROM character_spell_cooldown WHERE guid = '%u'",GetGUIDLow());
-
if(result)
{
time_t curTime = time(NULL);
@@ -4688,24 +4628,24 @@ float Player::GetRatingBonusValue(CombatRating cr) const
uint32 Player::GetMeleeCritDamageReduction(uint32 damage) const
{
- float melee = GetRatingBonusValue(CR_CRIT_TAKEN_MELEE)*2.0f;
- if (melee>25.0f) melee = 25.0f;
+ float melee = GetRatingBonusValue(CR_CRIT_TAKEN_MELEE)*2.2f;
+ if (melee>33.0f) melee = 33.0f;
return uint32 (melee * damage /100.0f);
}
uint32 Player::GetRangedCritDamageReduction(uint32 damage) const
{
- float ranged = GetRatingBonusValue(CR_CRIT_TAKEN_RANGED)*2.0f;
- if (ranged>25.0f) ranged=25.0f;
+ float ranged = GetRatingBonusValue(CR_CRIT_TAKEN_RANGED)*2.2f;
+ if (ranged>33.0f) ranged=33.0f;
return uint32 (ranged * damage /100.0f);
}
uint32 Player::GetSpellCritDamageReduction(uint32 damage) const
{
- float spell = GetRatingBonusValue(CR_CRIT_TAKEN_SPELL)*2.0f;
- // In wow script resilience limited to 25%
- if (spell>25.0f)
- spell = 25.0f;
+ float spell = GetRatingBonusValue(CR_CRIT_TAKEN_SPELL)*2.2f;
+ // In wow script resilience limited to 33%
+ if (spell>33.0f)
+ spell = 33.0f;
return uint32 (spell * damage / 100.0f);
}
@@ -5489,11 +5429,6 @@ void Player::removeActionButton(uint8 button)
sLog.outDetail( "Action Button '%u' Removed from Player '%u'", button, GetGUIDLow() );
}
-void Player::SetDontMove(bool dontMove)
-{
- m_dontMove = dontMove;
-}
-
bool Player::SetPosition(float x, float y, float z, float orientation, bool teleport)
{
// prevent crash when a bad coord is sent by the client
@@ -5722,6 +5657,9 @@ void Player::RewardReputation(Unit *pVictim, float rate)
if(!pVictim || pVictim->GetTypeId() == TYPEID_PLAYER)
return;
+ if(((Creature*)pVictim)->IsReputationGainDisabled())
+ return;
+
ReputationOnKillEntry const* Rep = objmgr.GetReputationOnKilEntry(((Creature*)pVictim)->GetCreatureInfo()->Entry);
if(!Rep)
@@ -6273,7 +6211,7 @@ void Player::DuelComplete(DuelCompleteType type)
if(!duel)
return;
- sLog.outDebug("Dual Complete %s %s", GetName(), duel->opponent->GetName());
+ sLog.outDebug("Duel Complete %s %s", GetName(), duel->opponent->GetName());
WorldPacket data(SMSG_DUEL_COMPLETE, (1));
data << (uint8)((type != DUEL_INTERUPTED) ? 1 : 0);
@@ -10256,7 +10194,7 @@ Item* Player::StoreItem( ItemPosCountVec const& dest, Item* pItem, bool update )
return NULL;
Item* lastItem = pItem;
-
+ uint32 entry = pItem->GetEntry();
for(ItemPosCountVec::const_iterator itr = dest.begin(); itr != dest.end(); )
{
uint16 pos = itr->pos;
@@ -10272,7 +10210,7 @@ Item* Player::StoreItem( ItemPosCountVec const& dest, Item* pItem, bool update )
lastItem = _StoreItem(pos,pItem,count,true,update);
}
-
+ GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_OWN_ITEM, entry);
return lastItem;
}
@@ -12744,6 +12682,8 @@ void Player::RewardQuest( Quest const *pQuest, uint32 reward, Object* questGiver
SendQuestReward( pQuest, XP, questGiver );
if (q_status.uState != QUEST_NEW) q_status.uState = QUEST_CHANGED;
+ if (pQuest->GetZoneOrSort() > 0)
+ GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_QUESTS_IN_ZONE, pQuest->GetZoneOrSort());
GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_QUEST_COUNT);
GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_QUEST);
@@ -13398,7 +13338,6 @@ void Player::ItemAddedQuestCheck( uint32 entry, uint32 count )
}
}
UpdateForQuestsGO();
- GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_OWN_ITEM, entry);
}
void Player::ItemRemovedQuestCheck( uint32 entry, uint32 count )
@@ -14414,10 +14353,10 @@ bool Player::LoadFromDB( uint32 guid, SqlQueryHolder *holder )
uint32 extraflags = fields[25].GetUInt32();
m_stableSlots = fields[26].GetUInt32();
- if(m_stableSlots > 4)
+ if(m_stableSlots > MAX_PET_STABLES)
{
- sLog.outError("Player can have not more 4 stable slots, but have in DB %u",uint32(m_stableSlots));
- m_stableSlots = 4;
+ sLog.outError("Player can have not more %u stable slots, but have in DB %u",MAX_PET_STABLES,uint32(m_stableSlots));
+ m_stableSlots = MAX_PET_STABLES;
}
m_atLoginFlags = fields[27].GetUInt32();
@@ -15841,17 +15780,20 @@ void Player::_SaveAuras()
AuraMap const& auras = GetAuras();
for(AuraMap::const_iterator itr = auras.begin(); itr !=auras.end() ; ++itr)
{
- // skip all auras from spell that apply at cast SPELL_AURA_MOD_SHAPESHIFT or pet area auras.
- // do not save single target auras (unless they were cast by the player)
+ // skip:
+ // area auras or single cast auras casted by other unit
+ // passive auras and stances
if (itr->second->IsPassive()
- || (itr->second->GetCasterGUID() != GetGUID() && itr->second->IsSingleTarget())
+ || itr->second->IsAuraType(SPELL_AURA_MOD_SHAPESHIFT)
+ || itr->second->IsAuraType(SPELL_AURA_MOD_STEALTH)
|| itr->second->IsRemovedOnShapeLost())
continue;
- SpellEntry const *spellInfo = itr->second->GetSpellProto();
- for (uint8 i=0;i<MAX_SPELL_EFFECTS;++i)
- if (spellInfo->Effect[i] == SPELL_AURA_MOD_SHAPESHIFT ||
- spellInfo->Effect[i] == SPELL_AURA_MOD_STEALTH )
+ bool isCaster = itr->second->GetCasterGUID() == GetGUID();
+ if (!isCaster)
+ if (itr->second->IsSingleTarget()
+ || itr->second->IsAreaAura())
continue;
+
int32 amounts[MAX_SPELL_EFFECTS];
for (uint8 i=0;i<MAX_SPELL_EFFECTS;++i)
{
@@ -16953,7 +16895,7 @@ void Player::RemoveSpellMods(Spell const* spell)
if (mod && mod->charges == -1 && (mod->lastAffected == spell || mod->lastAffected==NULL))
{
- RemoveAurasDueToSpell(mod->spellId);
+ RemoveAurasDueToSpell(mod->spellId, 0, AURA_REMOVE_BY_EXPIRE);
if (m_spellMods[i].empty())
break;
else
@@ -18697,7 +18639,7 @@ void Player::SendAurasForTarget(Unit *target)
// level
data << aura->m_auraLevel;
// charges
- data << uint8(aura->GetStackAmount() ? aura->GetStackAmount() : aura->GetAuraCharges());
+ data << uint8(aura->GetStackAmount()>1 ? aura->GetStackAmount() : aura->GetAuraCharges());
if(!(aura->m_auraFlags & AFLAG_CASTER))
{
@@ -19534,7 +19476,7 @@ void Player::UpdateUnderwaterState( Map* m, float x, float y, float z )
}
// Allow travel in dark water on taxi or transport
- if (liquid_status.type & MAP_LIQUID_TYPE_DARK_WATER && !isInFlight() && !(GetUnitMovementFlags()&MOVEMENTFLAG_ONTRANSPORT))
+ if ((liquid_status.type & MAP_LIQUID_TYPE_DARK_WATER) && !isInFlight() && !GetTransport())
m_MirrorTimerFlags |= UNDERWARER_INDARKWATER;
else
m_MirrorTimerFlags &= ~UNDERWARER_INDARKWATER;
@@ -19645,14 +19587,17 @@ WorldObject* Player::GetViewpoint() const
bool Player::CanUseBattleGroundObject()
{
+ // TODO : some spells gives player ForceReaction to one faction (ReputationMgr::ApplyForceReaction)
+ // maybe gameobject code should handle that ForceReaction usage
+ // BUG: sometimes when player clicks on flag in AB - client won't send gameobject_use, only gameobject_report_use packet
return ( //InBattleGround() && // in battleground - not need, check in other cases
//!IsMounted() && - not correct, player is dismounted when he clicks on flag
- //i'm not sure if these two are correct, because invisible players should get visible when they click on flag
+ //player cannot use object when he is invulnerable (immune)
!isTotalImmune() && // not totally immune
+ //i'm not sure if these two are correct, because invisible players should get visible when they click on flag
!HasStealthAura() && // not stealthed
!HasInvisibilityAura() && // not invisible
!HasAura(SPELL_RECENTLY_DROPPED_FLAG) && // can't pickup
- //TODO player cannot use object when he is invulnerable (immune) - (ice block, divine shield, divine protection, divine intervention ...)
isAlive() // live player
);
}
@@ -19744,37 +19689,31 @@ void Player::EnterVehicle(Vehicle *vehicle)
StopCastingCharm();
StopCastingBindSight();
+
SetCharm(vehicle, true);
SetViewpoint(vehicle, true);
SetMover(vehicle);
-
SetClientControl(vehicle, 1); // redirect controls to vehicle
+ addUnitState(UNIT_STAT_ONVEHICLE);
+ Relocate(vehicle->GetPositionX(), vehicle->GetPositionY(), vehicle->GetPositionZ(), vehicle->GetOrientation());
+ AddUnitMovementFlag(MOVEMENTFLAG_ONTRANSPORT);
+ m_movementInfo.t_x = veSeat->m_attachmentOffsetX;
+ m_movementInfo.t_y = veSeat->m_attachmentOffsetY;
+ m_movementInfo.t_z = veSeat->m_attachmentOffsetZ;
+ m_movementInfo.t_o = 0;
+ m_movementInfo.t_time = getMSTime();
+ m_movementInfo.t_seat = 0;
+
WorldPacket data(SMSG_ON_CANCEL_EXPECTED_RIDE_VEHICLE_AURA, 0);
GetSession()->SendPacket(&data);
- data.Initialize(MSG_MOVE_TELEPORT_ACK, 30);
- data.append(GetPackGUID());
- data << uint32(0); // counter?
- data << uint32(MOVEMENTFLAG_ONTRANSPORT); // transport
- data << uint16(0); // special flags
- data << uint32(getMSTime()); // time
- data << vehicle->GetPositionX(); // x
- data << vehicle->GetPositionY(); // y
- data << vehicle->GetPositionZ(); // z
- data << vehicle->GetOrientation(); // o
- // transport part, TODO: load/calculate seat offsets
- data << uint64(vehicle->GetGUID()); // transport guid
- data << float(veSeat->m_attachmentOffsetX); // transport offsetX
- data << float(veSeat->m_attachmentOffsetY); // transport offsetY
- data << float(veSeat->m_attachmentOffsetZ); // transport offsetZ
- data << float(0); // transport orientation
- data << uint32(getMSTime()); // transport time
- data << uint8(0); // seat
- // end of transport part
- data << uint32(0); // fall time
+ BuildTeleportAckMsg(&data, GetPositionX(), GetPositionY(), GetPositionZ(), GetOrientation());
GetSession()->SendPacket(&data);
+ BuildHeartBeatMsg(&data);
+ SendMessageToSet(&data, false);
+
VehicleSpellInitialize();
}
@@ -19787,29 +19726,36 @@ void Player::ExitVehicle(Vehicle *vehicle)
SetCharm(vehicle, false);
SetViewpoint(vehicle, false);
SetMover(this);
-
SetClientControl(vehicle, 0);
- WorldPacket data(MSG_MOVE_TELEPORT_ACK, 30);
- data.append(GetPackGUID());
- data << uint32(0); // counter?
- data << uint32(MOVEMENTFLAG_FLY_UNK1); // fly unk
- data << uint16(0x40); // special flags
- data << uint32(getMSTime()); // time
- data << vehicle->GetPositionX(); // x
- data << vehicle->GetPositionY(); // y
- data << vehicle->GetPositionZ(); // z
- data << vehicle->GetOrientation(); // o
- data << uint32(0); // fall time
+ clearUnitState(UNIT_STAT_ONVEHICLE);
+ Relocate(vehicle->GetPositionX(), vehicle->GetPositionY(), vehicle->GetPositionZ(), vehicle->GetOrientation());
+ RemoveUnitMovementFlag(MOVEMENTFLAG_ONTRANSPORT);
+ m_movementInfo.t_x = 0;
+ m_movementInfo.t_y = 0;
+ m_movementInfo.t_z = 0;
+ m_movementInfo.t_o = 0;
+ m_movementInfo.t_time = 0;
+ m_movementInfo.t_seat = 0;
+
+ WorldPacket data;
+ BuildTeleportAckMsg(&data, GetPositionX(), GetPositionY(), GetPositionZ(), GetOrientation());
GetSession()->SendPacket(&data);
+ BuildHeartBeatMsg(&data);
+ SendMessageToSet(&data, false);
+
data.Initialize(SMSG_PET_SPELLS, 8+4);
data << uint64(0);
data << uint32(0);
GetSession()->SendPacket(&data);
// only for flyable vehicles?
- CastSpell(this, 45472, true); // Parachute
+ //CastSpell(this, 45472, true); // Parachute
+
+ //if(!vehicle->GetDBTableGUIDLow())
+ if(vehicle->GetOwnerGUID() == GetGUID())
+ vehicle->Dismiss();
}
bool Player::isTotalImmune()
@@ -20162,7 +20108,7 @@ void Player::HandleFall(MovementInfo const& movementInfo)
{
// calculate total z distance of the fall
float z_diff = m_lastFallZ - movementInfo.z;
- sLog.outDebug("zDiff = %f", z_diff);
+ //sLog.outDebug("zDiff = %f", z_diff);
//Players with low fall distance, Feather Fall or physical immunity (charges used) are ignored
// 14.57 can be calculated by resolving damageperc formular below to 0
@@ -20475,3 +20421,37 @@ void Player::UpdateFallInformationIfNeed( MovementInfo const& minfo,uint16 opcod
if (m_lastFallTime >= minfo.fallTime || m_lastFallZ <=minfo.z || opcode == MSG_MOVE_FALL_LAND)
SetFallInformation(minfo.fallTime, minfo.z);
}
+
+void Player::UnsummonPetTemporaryIfAny()
+{
+ Pet* pet = GetPet();
+ if(!pet)
+ return;
+
+ if(!m_temporaryUnsummonedPetNumber && pet->isControlled() && !pet->isTemporarySummoned() )
+ {
+ m_temporaryUnsummonedPetNumber = pet->GetCharmInfo()->GetPetNumber();
+ m_oldpetspell = pet->GetUInt32Value(UNIT_CREATED_BY_SPELL);
+ }
+
+ RemovePet(pet, PET_SAVE_AS_CURRENT);
+}
+
+void Player::ResummonPetTemporaryUnSummonedIfAny()
+{
+ if(!m_temporaryUnsummonedPetNumber)
+ return;
+
+ // not resummon in not appropriate state
+ if(IsPetNeedBeTemporaryUnsummoned())
+ return;
+
+ if(GetPetGUID())
+ return;
+
+ Pet* NewPet = new Pet(this);
+ if(!NewPet->LoadPetFromDB(this, 0, m_temporaryUnsummonedPetNumber, true))
+ delete NewPet;
+
+ m_temporaryUnsummonedPetNumber = 0;
+}
diff --git a/src/game/Player.h b/src/game/Player.h
index 4738ce603a0..60b2c7a0a1d 100644
--- a/src/game/Player.h
+++ b/src/game/Player.h
@@ -1663,8 +1663,12 @@ class TRINITY_DLL_SPEC Player : public Unit
bool HasSkill(uint32 skill) const;
void learnSkillRewardedSpells(uint32 id, uint32 value);
- void SetDontMove(bool dontMove);
- bool GetDontMove() const { return m_dontMove; }
+ WorldLocation& GetTeleportDest() { return m_teleport_dest; }
+ bool IsBeingTeleported() const { return mSemaphoreTeleport_Near || mSemaphoreTeleport_Far; }
+ bool IsBeingTeleportedNear() const { return mSemaphoreTeleport_Near; }
+ bool IsBeingTeleportedFar() const { return mSemaphoreTeleport_Far; }
+ void SetSemaphoreTeleportNear(bool semphsetting) { mSemaphoreTeleport_Near = semphsetting; }
+ void SetSemaphoreTeleportFar(bool semphsetting) { mSemaphoreTeleport_Far = semphsetting; }
void CheckExploreSystem(void);
@@ -1998,8 +2002,9 @@ class TRINITY_DLL_SPEC Player : public Unit
// Temporarily removed pet cache
uint32 GetTemporaryUnsummonedPetNumber() const { return m_temporaryUnsummonedPetNumber; }
void SetTemporaryUnsummonedPetNumber(uint32 petnumber) { m_temporaryUnsummonedPetNumber = petnumber; }
- uint32 GetOldPetSpell() const { return m_oldpetspell; }
- void SetOldPetSpell(uint32 petspell) { m_oldpetspell = petspell; }
+ void UnsummonPetTemporaryIfAny();
+ void ResummonPetTemporaryUnSummonedIfAny();
+ bool IsPetNeedBeTemporaryUnsummoned() const { return !IsInWorld() || !isAlive() || IsMounted() /*+in flight*/; }
void SendCinematicStart(uint32 CinematicSequenceId);
void SendMovieStart(uint32 MovieId);
@@ -2056,8 +2061,6 @@ class TRINITY_DLL_SPEC Player : public Unit
bool isAllowedToLoot(Creature* creature);
- WorldLocation& GetTeleportDest() { return m_teleport_dest; }
-
DeclinedName const* GetDeclinedNames() const { return m_declinedname; }
uint8 GetRunesState() const { return m_runes->runeState; }
uint8 GetBaseRune(uint8 index) const { return m_runes->runes[index].BaseRune; }
@@ -2224,8 +2227,6 @@ class TRINITY_DLL_SPEC Player : public Unit
typedef std::list<Channel*> JoinedChannelsList;
JoinedChannelsList m_channels;
- bool m_dontMove;
-
int m_cinematic;
Player *pTrader;
@@ -2290,10 +2291,6 @@ class TRINITY_DLL_SPEC Player : public Unit
uint32 m_groupUpdateMask;
uint64 m_auraRaidUpdateMask;
- // Temporarily removed pet cache
- uint32 m_temporaryUnsummonedPetNumber;
- uint32 m_oldpetspell;
-
// Player summoning
time_t m_summon_expire;
uint32 m_summon_mapid;
@@ -2301,11 +2298,6 @@ class TRINITY_DLL_SPEC Player : public Unit
float m_summon_y;
float m_summon_z;
- // Far Teleport
- WorldLocation m_teleport_dest;
-
- bool m_farsightVision;
-
DeclinedName *m_declinedname;
Runes *m_runes;
private:
@@ -2333,6 +2325,15 @@ class TRINITY_DLL_SPEC Player : public Unit
uint8 m_MirrorTimerFlagsLast;
bool m_isInWater;
+ // Current teleport data
+ WorldLocation m_teleport_dest;
+ bool mSemaphoreTeleport_Near;
+ bool mSemaphoreTeleport_Far;
+
+ // Temporary removed pet cache
+ uint32 m_temporaryUnsummonedPetNumber;
+ uint32 m_oldpetspell;
+
AchievementMgr m_achievementMgr;
ReputationMgr m_reputationMgr;
};
diff --git a/src/game/Spell.cpp b/src/game/Spell.cpp
index 16cfe5b0e60..f14cc6b5ed3 100644
--- a/src/game/Spell.cpp
+++ b/src/game/Spell.cpp
@@ -307,6 +307,7 @@ Spell::Spell( Unit* Caster, SpellEntry const *info, bool triggered, uint64 origi
m_triggeringContainer = triggeringContainer;
m_referencedFromCurrentSpell = false;
m_executedCurrently = false;
+ m_needComboPoints = NeedsComboPoints(m_spellInfo);
m_delayStart = 0;
m_delayAtDamageCount = 0;
@@ -945,6 +946,10 @@ void Spell::DoAllEffectOnTarget(TargetInfo *target)
if (target->reflectResult == SPELL_MISS_NONE) // If reflected spell hit caster -> do all effect on him
DoSpellHitOnUnit(m_caster, mask);
}
+ // Do not take combo points on dodge
+ if (m_needComboPoints && m_targets.getUnitTargetGUID() == target->targetGUID)
+ if( missInfo != SPELL_MISS_NONE && missInfo != SPELL_MISS_MISS)
+ m_needComboPoints = false;
/*else //TODO: This is a hack. need fix
{
uint32 tempMask = 0;
@@ -1022,14 +1027,6 @@ void Spell::DoAllEffectOnTarget(TargetInfo *target)
caster->ProcDamageAndSpell(unit, procAttacker, procVictim, procEx, 0, m_attackType, m_spellInfo);
}
- // Take combo points after effects handling (combo points are used in effect handling)
- if(!m_IsTriggeredSpell && !m_CastItem
- && NeedsComboPoints(m_spellInfo)
- && m_caster->GetTypeId()==TYPEID_PLAYER
- && target->targetGUID == m_targets.getUnitTargetGUID()
- && (missInfo == SPELL_MISS_NONE || missInfo == SPELL_MISS_MISS))
- ((Player*)m_caster)->ClearComboPoints();
-
// Call scripted function for AI if this spell is casted upon a creature (except pets)
if(IS_CREATURE_GUID(target->targetGUID))
{
@@ -1103,8 +1100,8 @@ void Spell::DoSpellHitOnUnit(Unit *unit, const uint32 effectMask)
}
unit->RemoveAurasWithInterruptFlags(AURA_INTERRUPT_FLAG_HITBYSPELL);
- if(m_customAttr & SPELL_ATTR_CU_AURA_CC)
- unit->RemoveAurasWithInterruptFlags(AURA_INTERRUPT_FLAG_CC);
+ //if(m_customAttr & SPELL_ATTR_CU_AURA_CC)
+ //unit->RemoveAurasWithInterruptFlags(AURA_INTERRUPT_FLAG_CC);
}
else
{
@@ -2192,6 +2189,10 @@ void Spell::prepare(SpellCastTargets const* targets, AuraEffect* triggeredByAura
// Prepare data for triggers
prepareDataForTriggerSystem();
+ // Set combo point requirement
+ if (m_IsTriggeredSpell || m_CastItem || m_caster->GetTypeId()!=TYPEID_PLAYER)
+ m_needComboPoints = false;
+
// calculate cast time (calculated after first CheckCast check to prevent charge counting for first CheckCast fail)
m_casttime = GetSpellCastTime(m_spellInfo, this);
@@ -2208,6 +2209,9 @@ void Spell::prepare(SpellCastTargets const* targets, AuraEffect* triggeredByAura
if(isSpellBreakStealth(m_spellInfo) )
m_caster->RemoveAurasWithInterruptFlags(AURA_INTERRUPT_FLAG_CAST);
+ if(!m_IsTriggeredSpell)
+ m_caster->RemoveAurasWithInterruptFlags(AURA_INTERRUPT_FLAG_ANY_CAST);
+
m_caster->SetCurrentCastedSpell( this );
m_selfContainer = &(m_caster->m_currentSpells[GetCurrentContainer()]);
SendSpellStart();
@@ -2224,6 +2228,10 @@ void Spell::cancel()
if(m_spellState == SPELL_STATE_FINISHED)
return;
+ SetReferencedFromCurrent(false);
+ if(m_selfContainer && *m_selfContainer == this)
+ *m_selfContainer = NULL;
+
uint32 oldState = m_spellState;
m_spellState = SPELL_STATE_FINISHED;
@@ -2541,6 +2549,10 @@ void Spell::_handle_immediate_phase()
void Spell::_handle_finish_phase()
{
+ // Take for real after all targets are processed
+ if (m_needComboPoints)
+ ((Player*)m_caster)->ClearComboPoints();
+
// spell log
if(m_needSpellLog)
SendLogExecute();
@@ -3693,7 +3705,7 @@ SpellCastResult Spell::CheckCast(bool strict)
return SPELL_FAILED_TARGET_AURASTATE;
// Not allow casting on flying player
- if (target->isInFlight())
+ if (target->hasUnitState(UNIT_STAT_UNATTACKABLE))
return SPELL_FAILED_BAD_TARGETS;
if(!m_IsTriggeredSpell && VMAP::VMapFactory::checkSpellForLoS(m_spellInfo->Id) && !m_caster->IsWithinLOSInMap(target))
@@ -3997,8 +4009,18 @@ SpellCastResult Spell::CheckCast(bool strict)
{
if(m_spellInfo->SpellIconID == 1648) // Execute
{
- if(!m_targets.getUnitTarget() || m_targets.getUnitTarget()->GetHealth() > m_targets.getUnitTarget()->GetMaxHealth()*0.2)
+ if(!m_targets.getUnitTarget())
return SPELL_FAILED_BAD_TARGETS;
+ if (m_targets.getUnitTarget()->GetHealth() > m_targets.getUnitTarget()->GetMaxHealth()*0.2)
+ {
+ bool found = false;
+ Unit::AuraEffectList const& stateAuras = m_caster->GetAurasByType(SPELL_AURA_ABILITY_IGNORE_AURASTATE);
+ for(Unit::AuraEffectList::const_iterator j = stateAuras.begin();j != stateAuras.end(); ++j)
+ if((*j)->isAffectedOnSpell(m_spellInfo))
+ found=true;
+ if (!found)
+ return SPELL_FAILED_BAD_TARGETS;
+ }
}
else if (m_spellInfo->Id == 51582) // Rocket Boots Engaged
{
@@ -4527,7 +4549,7 @@ SpellCastResult Spell::CheckCasterAuras() const
dispel_immune |= GetDispellMask(DispelType(m_spellInfo->EffectMiscValue[i]));
}
//immune movement impairment and loss of control
- if(m_spellInfo->Id==(uint32)42292)
+ if(m_spellInfo->Id==42292 || m_spellInfo->Id==59752)
mechanic_immune = IMMUNE_TO_MOVEMENT_IMPAIRMENT_AND_LOSS_CONTROL_MASK;
}
@@ -4559,7 +4581,7 @@ SpellCastResult Spell::CheckCasterAuras() const
{
if( GetAllSpellMechanicMask(itr->second->GetSpellProto()) & mechanic_immune )
continue;
- if( GetAllSpellMechanicMask(itr->second->GetSpellProto()) & school_immune )
+ if( GetSpellSchoolMask(itr->second->GetSpellProto()) & school_immune )
continue;
if( (1<<(itr->second->GetSpellProto()->Dispel)) & dispel_immune)
continue;
@@ -4620,8 +4642,9 @@ bool Spell::CanAutoCast(Unit* target)
}
else
{
- if( (target->GetAuraEffect(m_spellInfo->Id, j))->GetParentAura()->GetStackAmount() >= m_spellInfo->StackAmount)
- return false;
+ if( AuraEffect * aureff = target->GetAuraEffect(m_spellInfo->Id, j))
+ if (aureff->GetParentAura()->GetStackAmount() >= m_spellInfo->StackAmount)
+ return false;
}
}
else if ( IsAreaAuraEffect( m_spellInfo->Effect[j] ))
diff --git a/src/game/Spell.h b/src/game/Spell.h
index 7c52a4e8bb3..45a3a123bae 100644
--- a/src/game/Spell.h
+++ b/src/game/Spell.h
@@ -278,6 +278,7 @@ class Spell
void EffectSummonWild(uint32 i);
void EffectHealMechanical(uint32 i);
void EffectJump(uint32 i);
+ void EffectJump2(uint32 i);
void EffectTeleUnitsFaceCaster(uint32 i);
void EffectLearnSkill(uint32 i);
void EffectAddHonor(uint32 i);
@@ -507,6 +508,7 @@ class Spell
bool m_referencedFromCurrentSpell; // mark as references to prevent deleted and access by dead pointers
bool m_executedCurrently; // mark as executed to prevent deleted and access by dead pointers
bool m_needSpellLog; // need to send spell log?
+ bool m_needComboPoints;
uint8 m_applyMultiplierMask; // by effect: damage multiplier needed?
float m_damageMultipliers[3]; // by effect: damage multiplier
diff --git a/src/game/SpellAuras.cpp b/src/game/SpellAuras.cpp
index 89d5a5578d5..008ba1278a5 100644
--- a/src/game/SpellAuras.cpp
+++ b/src/game/SpellAuras.cpp
@@ -198,7 +198,7 @@ pAuraHandler AuraHandler[TOTAL_AURAS]=
&AuraEffect::HandleNoImmediateEffect, //144 SPELL_AURA_SAFE_FALL implemented in WorldSession::HandleMovementOpcodes
&AuraEffect::HandleAuraModPetTalentsPoints, //145 SPELL_AURA_MOD_PET_TALENT_POINTS
&AuraEffect::HandleNoImmediateEffect, //146 SPELL_AURA_ALLOW_TAME_PET_TYPE
- &AuraEffect::HandleModMechanicImmunity, //147 SPELL_AURA_MECHANIC_IMMUNITY_MASK
+ &AuraEffect::HandleModStateImmunityMask, //147 SPELL_AURA_MECHANIC_IMMUNITY_MASK
&AuraEffect::HandleAuraRetainComboPoints, //148 SPELL_AURA_RETAIN_COMBO_POINTS
&AuraEffect::HandleNoImmediateEffect, //149 SPELL_AURA_REDUCE_PUSHBACK
&AuraEffect::HandleShieldBlockValue, //150 SPELL_AURA_MOD_SHIELD_BLOCKVALUE_PCT
@@ -344,8 +344,8 @@ pAuraHandler AuraHandler[TOTAL_AURAS]=
Aura::Aura(SpellEntry const* spellproto, uint32 effMask, int32 *currentBasePoints, Unit *target, Unit *caster, Item* castItem) :
m_caster_guid(0), m_castItemGuid(castItem?castItem->GetGUID():0), m_target(target),
-m_timeCla(1000), m_removeMode(AURA_NO_REMOVE_MODE), m_AuraDRGroup(DIMINISHING_NONE),
-m_auraSlot(MAX_AURAS), m_auraLevel(1), m_procCharges(0), m_stackAmount(1),m_auraStateMask(0), m_updated(false), m_in_use(false)
+m_timeCla(1000), m_removeMode(AURA_REMOVE_BY_DEFAULT), m_AuraDRGroup(DIMINISHING_NONE),
+m_auraSlot(MAX_AURAS), m_auraLevel(1), m_procCharges(0), m_stackAmount(1),m_auraStateMask(0), m_updated(false), m_isRemoved(false)
{
assert(target);
@@ -415,7 +415,7 @@ m_auraSlot(MAX_AURAS), m_auraLevel(1), m_procCharges(0), m_stackAmount(1),m_aura
m_partAuras[i]=CreateAuraEffect(this, i, NULL , caster);
// correct flags if aura couldn't be created
if (!m_partAuras[i])
- m_auraFlags &= uint8(~(uint8(1) << i));
+ m_auraFlags &= uint8(~(1<< i));
}
else
{
@@ -462,19 +462,6 @@ m_target(parentAura->GetTarget())
m_effIndex = effIndex;
m_auraName = AuraType(m_spellProto->EffectApplyAuraName[m_effIndex]);
- /*if(currentBasePoints)
- {
- m_amount = *currentBasePoints;
- m_currentBasePoints = m_amount - 1;
- }
- else
- {
- m_currentBasePoints = m_spellProto->EffectBasePoints[m_effIndex];
- if(caster)
- m_amount = caster->CalculateSpellDamage(m_spellProto, m_effIndex, m_currentBasePoints, m_target);
- else
- m_amount = m_currentBasePoints + 1;
- }*/
if(currentBasePoints)
m_currentBasePoints = *currentBasePoints;
else
@@ -637,12 +624,12 @@ void Aura::Update(uint32 diff)
if (caster->GetHealth()>manaPerSecond)
caster->ModifyHealth(-manaPerSecond);
else
- RemoveAura();
+ m_target->RemoveAura(this);
}
else if (caster->GetPower(powertype)>=manaPerSecond)
caster->ModifyPower(powertype,-manaPerSecond);
else
- RemoveAura();
+ m_target->RemoveAura(this);
}
}
}
@@ -654,7 +641,7 @@ void Aura::Update(uint32 diff)
Unit* caster = GetCaster();
if(!caster)
{
- RemoveAura();
+ m_target->RemoveAura(this);
return;
}
// Get spell range
@@ -680,7 +667,7 @@ void Aura::Update(uint32 diff)
if(!caster->IsWithinDistInMap(m_target,radius))
{
- RemoveAura();
+ m_target->RemoveAura(this);
return;
}
}
@@ -777,37 +764,41 @@ void AreaAuraEffect::Update(uint32 diff)
}
else // aura at non-caster
{
- Unit * tmp_target = m_target;
+ // WARNING: the aura may get deleted during the update
+ // DO NOT access its members after update!
+ AuraEffect::Update(diff);
+
+ // Speedup - no need to do more checks
+ if (GetParentAura()->IsRemoved())
+ return;
+
+ // Caster may be deleted due to update
Unit* caster = GetCaster();
uint32 tmp_spellId = GetId();
uint32 tmp_effIndex = GetEffIndex();
uint64 tmp_guid = GetCasterGUID();
- // WARNING: the aura may get deleted during the update
- // DO NOT access its members after update!
- AuraEffect::Update(diff);
-
// remove aura if out-of-range from caster (after teleport for example)
// or caster is isolated or caster no longer has the aura
// or caster is (no longer) friendly
bool needFriendly = (m_areaAuraType == AREA_AURA_ENEMY ? false : true);
if( !caster || caster->hasUnitState(UNIT_STAT_ISOLATED) ||
!caster->HasAuraEffect(tmp_spellId, tmp_effIndex) ||
- caster->IsFriendlyTo(tmp_target) != needFriendly
+ caster->IsFriendlyTo(m_target) != needFriendly
)
{
- GetParentAura()->RemoveAura();
+ m_target->RemoveAura(GetParentAura());
}
- else if (!caster->IsWithinDistInMap(tmp_target, m_radius))
+ else if (!caster->IsWithinDistInMap(m_target, m_radius))
{
if (needFriendly)
{
m_removeTime -= diff;
if (m_removeTime < 0)
- GetParentAura()->RemoveAura();
+ m_target->RemoveAura(GetParentAura());
}
else
- GetParentAura()->RemoveAura();
+ m_target->RemoveAura(GetParentAura());
}
else
{
@@ -815,18 +806,18 @@ void AreaAuraEffect::Update(uint32 diff)
m_removeTime = FRIENDLY_AA_REMOVE_TIME;
if( m_areaAuraType == AREA_AURA_PARTY) // check if in same sub group
{
- if(!tmp_target->IsInPartyWith(caster))
- GetParentAura()->RemoveAura();
+ if(!m_target->IsInPartyWith(caster))
+ m_target->RemoveAura(GetParentAura());
}
else if( m_areaAuraType == AREA_AURA_RAID)
{
- if(!tmp_target->IsInRaidWith(caster))
- GetParentAura()->RemoveAura();
+ if(!m_target->IsInRaidWith(caster))
+ m_target->RemoveAura(GetParentAura());
}
else if( m_areaAuraType == AREA_AURA_PET || m_areaAuraType == AREA_AURA_OWNER )
{
- if( tmp_target->GetGUID() != caster->GetCharmerOrOwnerGUID() )
- GetParentAura()->RemoveAura();
+ if( m_target->GetGUID() != caster->GetCharmerOrOwnerGUID() )
+ m_target->RemoveAura(GetParentAura());
}
}
}
@@ -854,22 +845,21 @@ void PersistentAreaAuraEffect::Update(uint32 diff)
remove = true;
if(remove)
- GetParentAura()->RemoveAura();
+ {
+ m_target->RemoveAura(GetParentAura());
+ return;
+ }
AuraEffect::Update(diff);
}
void AuraEffect::ApplyModifier(bool apply, bool Real)
{
- AuraType aura = m_auraName;
+ if (GetParentAura()->IsRemoved())
+ return;
- bool inuse = GetParentAura()->IsInUse();
- if (!inuse)
- GetParentAura()->SetInUse(true);
- if(aura<TOTAL_AURAS)
- (*this.*AuraHandler [aura])(apply,Real);
- if (!inuse)
- GetParentAura()->SetInUse(false);
+ if(m_auraName<TOTAL_AURAS)
+ (*this.*AuraHandler [m_auraName])(apply,Real);
}
void AuraEffect::CleanupTriggeredSpells()
@@ -921,7 +911,7 @@ void Aura::SendAuraUpdate()
data << uint32(GetId());
data << uint8(m_auraFlags);
data << uint8(m_auraLevel);
- data << uint8(m_stackAmount ? m_stackAmount : m_procCharges);
+ data << uint8(m_stackAmount>1 ? m_stackAmount : m_procCharges);
if(!(m_auraFlags & AFLAG_CASTER))
{
@@ -952,7 +942,8 @@ void Aura::_AddAura()
// set infinity cooldown state for spells
if(caster && caster->GetTypeId() == TYPEID_PLAYER)
{
- if (m_spellProto->Attributes & SPELL_ATTR_DISABLED_WHILE_ACTIVE)
+ // Do not apply cooldown for caster passive spells (needed by Reincarnation)
+ if (!(caster->HasSpell(GetId()) && IsPassive()) && m_spellProto->Attributes & SPELL_ATTR_DISABLED_WHILE_ACTIVE)
{
Item* castItem = m_castItemGuid ? ((Player*)caster)->GetItemByGuid(m_castItemGuid) : NULL;
((Player*)caster)->AddSpellAndCategoryCooldowns(m_spellProto,castItem ? castItem->GetEntry() : 0, NULL,true);
@@ -961,12 +952,15 @@ void Aura::_AddAura()
// passive auras (except totem auras) do not get placed in the slots
// area auras with SPELL_AURA_NONE are not shown on target
- if((m_spellProto->Attributes & 0x80 && GetTalentSpellPos(GetId())) || !m_isPassive || (caster && caster->GetTypeId() == TYPEID_UNIT && ((Creature*)caster)->isTotem())
- && (!IsAreaAura()
- || m_target!=caster ||
- (m_spellProto->Effect[0]!=SPELL_EFFECT_APPLY_AREA_AURA_ENEMY
- && m_spellProto->Effect[1]!=SPELL_EFFECT_APPLY_AREA_AURA_ENEMY
- && m_spellProto->Effect[2]!=SPELL_EFFECT_APPLY_AREA_AURA_ENEMY)))
+ if((m_spellProto->Attributes & 0x80 && GetTalentSpellPos(GetId()))
+ || !m_isPassive
+ || (caster && caster->GetTypeId() == TYPEID_UNIT && ((Creature*)caster)->isTotem())
+ || (IsAuraType(SPELL_AURA_ABILITY_IGNORE_AURASTATE))
+ && (!IsAreaAura()
+ || m_target!=caster ||
+ (m_spellProto->Effect[0]!=SPELL_EFFECT_APPLY_AREA_AURA_ENEMY
+ && m_spellProto->Effect[1]!=SPELL_EFFECT_APPLY_AREA_AURA_ENEMY
+ && m_spellProto->Effect[2]!=SPELL_EFFECT_APPLY_AREA_AURA_ENEMY)))
{
// Try find slot for aura
uint8 slot = MAX_AURAS;
@@ -1022,10 +1016,12 @@ void Aura::_AddAura()
{
if(const std::vector<int32> *spell_triggered = spellmgr.GetSpellLinked(id + SPELL_LINK_AURA))
for(std::vector<int32>::const_iterator itr = spell_triggered->begin(); itr != spell_triggered->end(); ++itr)
+ {
if(*itr < 0)
m_target->ApplySpellImmune(id, IMMUNITY_ID, -(*itr), m_target);
else if(Unit* caster = GetCaster())
m_target->AddAura(*itr, m_target);
+ }
}
//*****************************************************
@@ -1078,6 +1074,8 @@ void Aura::_AddAura()
bool Aura::SetPartAura(AuraEffect* aurEff, uint8 effIndex)
{
+ if (IsRemoved())
+ return false;
if (m_auraFlags & (1<<effIndex))
return false;
m_auraFlags |= 1<<effIndex;
@@ -1138,6 +1136,11 @@ void Aura::_RemoveAura()
m_target->ApplyModFlag(UNIT_FIELD_AURASTATE, foundMask, false);
}
+ // since now aura cannot apply/remove it's modifiers
+ m_isRemoved = true;
+ // disable client server communication for removed aura
+ SetAuraSlot(MAX_AURAS);
+
// reset cooldown state for spells
if(caster && caster->GetTypeId() == TYPEID_PLAYER)
{
@@ -1145,29 +1148,32 @@ void Aura::_RemoveAura()
// note: item based cooldowns and cooldown spell mods with charges ignored (unknown existed cases)
((Player*)caster)->SendCooldownEvent(GetSpellProto());
}
- if (m_removeMode==AURA_REMOVE_BY_EXPIRE)
+ uint32 id = GetId();
+ // Remove Linked Auras
+ if(spellmgr.GetSpellCustomAttr(id) & SPELL_ATTR_CU_LINK_REMOVE)
{
- // Remove Linked Auras (on last aura remove)
- uint32 id = GetId();
- if(spellmgr.GetSpellCustomAttr(id) & SPELL_ATTR_CU_LINK_REMOVE)
- {
- if(const std::vector<int32> *spell_triggered = spellmgr.GetSpellLinked(-(int32)id))
- for(std::vector<int32>::const_iterator itr = spell_triggered->begin(); itr != spell_triggered->end(); ++itr)
- if(*itr < 0)
- m_target->RemoveAurasDueToSpell(-(*itr));
- else if(Unit* caster = GetCaster())
+ if(const std::vector<int32> *spell_triggered = spellmgr.GetSpellLinked(-(int32)id))
+ for(std::vector<int32>::const_iterator itr = spell_triggered->begin(); itr != spell_triggered->end(); ++itr)
+ {
+ if(*itr < 0)
+ m_target->RemoveAurasDueToSpell(-(*itr));
+ else if(Unit* caster = GetCaster())
+ if (m_removeMode==AURA_REMOVE_BY_EXPIRE)
m_target->CastSpell(m_target, *itr, true, 0, 0, caster->GetGUID());
- }
- if(spellmgr.GetSpellCustomAttr(id) & SPELL_ATTR_CU_LINK_AURA)
- {
- if(const std::vector<int32> *spell_triggered = spellmgr.GetSpellLinked(id + SPELL_LINK_AURA))
- for(std::vector<int32>::const_iterator itr = spell_triggered->begin(); itr != spell_triggered->end(); ++itr)
- if(*itr < 0)
- m_target->ApplySpellImmune(id, IMMUNITY_ID, -(*itr), false);
- else
- m_target->RemoveAurasDueToSpell(*itr);
- }
+ }
+ }
+ if(spellmgr.GetSpellCustomAttr(id) & SPELL_ATTR_CU_LINK_AURA)
+ {
+ if(const std::vector<int32> *spell_triggered = spellmgr.GetSpellLinked(id + SPELL_LINK_AURA))
+ for(std::vector<int32>::const_iterator itr = spell_triggered->begin(); itr != spell_triggered->end(); ++itr)
+ {
+ if(*itr < 0)
+ m_target->ApplySpellImmune(id, IMMUNITY_ID, -(*itr), false);
+ else
+ m_target->RemoveAurasDueToSpell(*itr);
+ }
}
+
// Proc on aura remove (only spell flags for now)
if (caster)
{
@@ -1199,22 +1205,23 @@ void Aura::SetStackAmount(uint8 stackAmount)
{
Unit *target = GetTarget();
Unit *caster = GetCaster();
- if (!target || !caster)
- return;
- m_stackAmount = stackAmount;
- for (uint8 i=0;i<MAX_SPELL_EFFECTS;++i)
+ if (target && caster)
{
- if (AuraEffect * part = GetPartAura(i))
+ m_stackAmount = stackAmount;
+ for (uint8 i=0;i<MAX_SPELL_EFFECTS;++i)
{
- int32 amount = m_stackAmount * caster->CalculateSpellDamage(m_spellProto, part->GetEffIndex(), part->GetBasePoints(), target);
- // Reapply if amount change
- if (amount!=part->GetAmount())
+ if (AuraEffect * part = GetPartAura(i))
{
- bool Real = bool (part->m_spellmod);
- // Auras which are applying spellmod should have removed spellmods for real
- part->ApplyModifier(false,Real);
- part->SetAmount(amount);
- part->ApplyModifier(true, Real);
+ int32 amount = m_stackAmount * caster->CalculateSpellDamage(m_spellProto, part->GetEffIndex(), part->GetBasePoints(), target);
+ // Reapply if amount change
+ if (amount!=part->GetAmount())
+ {
+ bool Real = bool (part->m_spellmod);
+ // Auras which are applying spellmod should have removed spellmods for real
+ part->ApplyModifier(false,Real);
+ part->SetAmount(amount);
+ part->ApplyModifier(true, Real);
+ }
}
}
}
@@ -1486,23 +1493,6 @@ void AuraEffect::HandleAddModifier(bool apply, bool Real)
if (apply)
{
- // Add custom charges for some mod aura
- switch (m_spellProto->Id)
- {
- case 17941: // Shadow Trance
- case 22008: // Netherwind Focus
- case 31834: // Light's Grace
- case 34754: // Clearcasting
- case 34936: // Backlash
- case 48108: // Hot Streak
- case 51124: // Killing Machine
- case 54741: // Firestarter
- case 57761: // Fireball!
- case 39805: // Lightning Overload
- GetParentAura()->SetAuraCharges(1);
- break;
-
- }
SpellModifier *mod = new SpellModifier;
mod->op = SpellModOp(GetMiscValue());
@@ -2456,14 +2446,6 @@ void AuraEffect::HandleAuraDummy(bool apply, bool Real)
caster->CastSpell(m_target, GetAmount(), true);
return;
}
- // Focused Magic
- if(m_spellProto->Id == 54646)
- {
- // only on remove by crit
- if(caster && GetParentAura()->GetRemoveMode() == AURA_REMOVE_BY_EXPIRE)
- caster->CastSpell(caster,54648, true);
- return;
- }
break;
}
}
@@ -3848,8 +3830,6 @@ void AuraEffect::HandleAuraModSilence(bool apply, bool Real)
if ( state == SPELL_STATE_PREPARING || state == SPELL_STATE_CASTING )
{
currentSpell->cancel();
- currentSpell->SetReferencedFromCurrent(false);
- m_target->m_currentSpells[i] = NULL;
}
}
}
@@ -4013,7 +3993,7 @@ void AuraEffect::HandleAuraModIncreaseFlightSpeed(bool apply, bool Real)
//Players on flying mounts must be immune to polymorph
if (m_target->GetTypeId()==TYPEID_PLAYER)
- m_target->ApplySpellImmune(GetId(),IMMUNITY_MECHANIC,1<<MECHANIC_POLYMORPH,apply);
+ m_target->ApplySpellImmune(GetId(),IMMUNITY_MECHANIC,MECHANIC_POLYMORPH,apply);
// Dragonmaw Illusion (overwrite mount model, mounted aura already applied)
if( apply && m_target->HasAuraEffect(42016,0) && m_target->GetMountID())
@@ -4058,16 +4038,57 @@ void AuraEffect::HandleAuraModUseNormalSpeed(bool /*apply*/, bool Real)
/*** IMMUNITY ***/
/*********************************************************/
+void AuraEffect::HandleModStateImmunityMask(bool apply, bool Real)
+{
+ std::list <AuraType> immunity_list;
+ if (GetMiscValue() & (1<<10))
+ immunity_list.push_back(SPELL_AURA_MOD_STUN);
+ if (GetMiscValue() & (1<<7))
+ immunity_list.push_back(SPELL_AURA_MOD_DISARM);
+ if (GetMiscValue() & (1<<1))
+ immunity_list.push_back(SPELL_AURA_MOD_TAUNT);
+
+ // These flag can be recognized wrong:
+ if (GetMiscValue() & (1<<6))
+ immunity_list.push_back(SPELL_AURA_MOD_DECREASE_SPEED);
+ if (GetMiscValue() & (1<<0))
+ immunity_list.push_back(SPELL_AURA_MOD_ROOT);
+ if (GetMiscValue() & (1<<3))
+ immunity_list.push_back(SPELL_AURA_MOD_CONFUSE);
+ if (GetMiscValue() & (1<<9))
+ immunity_list.push_back(SPELL_AURA_MOD_FEAR);
+
+ // Patch 3.0.3 Bladestorm now breaks all snares and roots on the warrior when activated.
+ // however not all mechanic specified in immunity
+ if (apply && GetId()==46924)
+ {
+ m_target->RemoveAurasByType(SPELL_AURA_MOD_ROOT);
+ m_target->RemoveAurasByType(SPELL_AURA_MOD_DECREASE_SPEED);
+ }
+
+ if(apply && GetSpellProto()->AttributesEx & SPELL_ATTR_EX_DISPEL_AURAS_ON_IMMUNITY)
+ {
+ for (std::list <AuraType>::iterator iter = immunity_list.begin(); iter != immunity_list.end();++iter)
+ {
+ m_target->RemoveAurasByType(*iter);
+ }
+ }
+ for (std::list <AuraType>::iterator iter = immunity_list.begin(); iter != immunity_list.end();++iter)
+ {
+ m_target->ApplySpellImmune(GetId(),IMMUNITY_STATE,*iter,apply);
+ }
+}
+
void AuraEffect::HandleModMechanicImmunity(bool apply, bool Real)
{
uint32 mechanic;
- if (GetSpellProto()->EffectApplyAuraName[GetEffIndex()]==SPELL_AURA_MECHANIC_IMMUNITY)
- mechanic = 1 << GetMiscValue();
- else //SPELL_AURA_MECHANIC_IMMUNITY_MASK
- mechanic = GetMiscValue();
+ mechanic = 1 << GetMiscValue();
+
//immune movement impairment and loss of control
if(GetId()==42292 || GetId()==59752)
mechanic=IMMUNE_TO_MOVEMENT_IMPAIRMENT_AND_LOSS_CONTROL_MASK;
+ if (!mechanic)
+ return;
if(apply && GetSpellProto()->AttributesEx & SPELL_ATTR_EX_DISPEL_AURAS_ON_IMMUNITY)
{
@@ -4091,7 +4112,7 @@ void AuraEffect::HandleModMechanicImmunity(bool apply, bool Real)
}
}
- m_target->ApplySpellImmune(GetId(),IMMUNITY_MECHANIC,mechanic,apply);
+ m_target->ApplySpellImmune(GetId(),IMMUNITY_MECHANIC,GetMiscValue(),apply);
// Bestial Wrath
if ( GetSpellProto()->SpellFamilyName == SPELLFAMILY_HUNTER && GetSpellProto()->Id == 19574)
@@ -4238,18 +4259,6 @@ void AuraEffect::HandleAuraProcTriggerSpell(bool apply, bool Real)
{
if(!Real)
return;
-
- if(apply)
- {
- // some spell have charges by functionality not have its in spell data
- switch (GetId())
- {
- case 28200: // Ascendance (Talisman of Ascendance trinket)
- GetParentAura()->SetAuraCharges(6);
- break;
- default: break;
- }
- }
}
void AuraEffect::HandleAuraModStalked(bool apply, bool Real)
@@ -4270,7 +4279,7 @@ void AuraEffect::HandlePeriodicTriggerSpell(bool apply, bool Real)
m_isPeriodic = apply;
if (m_spellProto->Id == 66 && !apply)
{
- if (GetParentAura()->GetRemoveMode() && GetParentAura()->GetAuraDuration()<=0)
+ if (GetParentAura()->GetRemoveMode() == AURA_REMOVE_BY_EXPIRE)
m_target->CastSpell(m_target, 32612, true, NULL, this);
}
}
@@ -5650,7 +5659,7 @@ void AuraEffect::PeriodicTick()
100;
if(m_target->GetHealth()*100 >= m_target->GetMaxHealth()*percent )
{
- GetParentAura()->RemoveAura();
+ m_target->RemoveAurasDueToSpell(GetId());
return;
}
break;
diff --git a/src/game/SpellAuras.h b/src/game/SpellAuras.h
index 3632c7b2121..fb8120a01e6 100644
--- a/src/game/SpellAuras.h
+++ b/src/game/SpellAuras.h
@@ -92,17 +92,14 @@ class TRINITY_DLL_SPEC Aura
void SetNegative() { m_positive = false; }
void SetPositive() { m_positive = true; }
bool IsPermanent() const { return m_permanent; }
- void RemoveAura(AuraRemoveMode mode = AURA_REMOVE_BY_DEFAULT) { m_permanent = false; m_duration=0; m_removeMode = mode; }
bool IsPassive() const { return m_isPassive; }
bool IsDeathPersistent() const { return m_isDeathPersist; }
bool IsRemovedOnShapeLost() const { return m_isRemovedOnShapeLost; }
bool IsUpdated() const { return m_updated; }
+ bool IsRemoved() const { return m_isRemoved; }
void SetUpdated(bool val) { m_updated = val; }
- bool IsInUse() const { return m_in_use; }
- void SetInUse(bool val) { m_in_use = val; }
-
bool IsPersistent() const;
bool IsAreaAura() const;
bool IsAuraType(AuraType type) const;
@@ -158,8 +155,8 @@ class TRINITY_DLL_SPEC Aura
bool m_isPassive:1;
bool m_positive:1;
bool m_permanent:1;
+ bool m_isRemoved:1;
bool m_updated:1; // Prevent remove aura by stack if set
- bool m_in_use:1;
bool m_isSingleTargetAura:1; // true if it's a single target spell and registered at caster - can change at spell steal for example
};
class TRINITY_DLL_SPEC AuraEffect
@@ -270,6 +267,7 @@ class TRINITY_DLL_SPEC AuraEffect
void HandleFarSight(bool Apply, bool Real);
void HandleModPossessPet(bool Apply, bool Real);
void HandleModMechanicImmunity(bool Apply, bool Real);
+ void HandleModStateImmunityMask(bool apply, bool Real);
void HandleAuraModSkill(bool Apply, bool Real);
void HandleModDamagePercentDone(bool Apply, bool Real);
void HandleModPercentStat(bool Apply, bool Real);
@@ -334,6 +332,7 @@ class TRINITY_DLL_SPEC AuraEffect
uint32 GetId() const { return m_spellProto->Id; }
uint32 GetEffIndex() const { return m_effIndex; }
int32 GetBasePoints() const { return m_currentBasePoints; }
+ int32 GetAuraAmplitude(){return m_amplitude;}
void Update(uint32 diff);
bool IsAreaAura() const { return m_isAreaAura; }
diff --git a/src/game/SpellEffects.cpp b/src/game/SpellEffects.cpp
index 5dac4ca1a7e..d01e992ed90 100644
--- a/src/game/SpellEffects.cpp
+++ b/src/game/SpellEffects.cpp
@@ -105,7 +105,7 @@ pEffect SpellEffects[TOTAL_SPELL_EFFECTS]=
&Spell::EffectDispel, // 38 SPELL_EFFECT_DISPEL
&Spell::EffectUnused, // 39 SPELL_EFFECT_LANGUAGE
&Spell::EffectDualWield, // 40 SPELL_EFFECT_DUAL_WIELD
- &Spell::EffectUnused, // 41 SPELL_EFFECT_JUMP
+ &Spell::EffectJump, // 41 SPELL_EFFECT_JUMP
&Spell::EffectJump, // 42 SPELL_EFFECT_JUMP2
&Spell::EffectTeleUnitsFaceCaster, // 43 SPELL_EFFECT_TELEPORT_UNITS_FACE_CASTER
&Spell::EffectLearnSkill, // 44 SPELL_EFFECT_SKILL_STEP
@@ -202,14 +202,14 @@ pEffect SpellEffects[TOTAL_SPELL_EFFECTS]=
&Spell::EffectNULL, //135 SPELL_EFFECT_CALL_PET
&Spell::EffectHealPct, //136 SPELL_EFFECT_HEAL_PCT
&Spell::EffectEnergisePct, //137 SPELL_EFFECT_ENERGIZE_PCT
- &Spell::EffectNULL, //138 SPELL_EFFECT_138 Leap
+ &Spell::EffectJump2, //138 SPELL_EFFECT_138 Leap
&Spell::EffectUnused, //139 SPELL_EFFECT_CLEAR_QUEST (misc - is quest ID)
&Spell::EffectForceCast, //140 SPELL_EFFECT_FORCE_CAST
&Spell::EffectNULL, //141 SPELL_EFFECT_141 damage and reduce speed?
&Spell::EffectTriggerSpellWithValue, //142 SPELL_EFFECT_TRIGGER_SPELL_WITH_VALUE
&Spell::EffectApplyAreaAura, //143 SPELL_EFFECT_APPLY_AREA_AURA_OWNER
&Spell::EffectKnockBack, //144 SPELL_EFFECT_KNOCK_BACK_2 Spectral Blast
- &Spell::EffectNULL, //145 SPELL_EFFECT_145 Black Hole Effect
+ &Spell::EffectPlayerPull, //145 SPELL_EFFECT_145 Black Hole Effect
&Spell::EffectActivateRune, //146 SPELL_EFFECT_ACTIVATE_RUNE
&Spell::EffectQuestFail, //147 SPELL_EFFECT_QUEST_FAIL quest fail
&Spell::EffectUnused, //148 SPELL_EFFECT_148 unused
@@ -402,7 +402,7 @@ void Spell::SpellDamageSchoolDmg(uint32 effect_idx)
damage = uint32(damage * (m_caster->GetTotalAttackPowerValue(BASE_ATTACK)) / 100);
}
// Shield Slam
- else if(m_spellInfo->SpellFamilyFlags[1] & 0x200)
+ else if(m_spellInfo->SpellFamilyFlags[1] & 0x200 && m_spellInfo->Category==1209)
damage += int32(m_caster->GetShieldBlockValue());
// Victory Rush
else if(m_spellInfo->SpellFamilyFlags[1] & 0x100)
@@ -430,6 +430,13 @@ void Spell::SpellDamageSchoolDmg(uint32 effect_idx)
damage += int32(m_caster->GetTotalAttackPowerValue(BASE_ATTACK) * 12 / 100);
break;
}
+ // Concussion Blow
+ else if(m_spellInfo->SpellFamilyFlags[0] & 0x4000000)
+ {
+ int32 pct = m_caster->CalculateSpellDamage(m_spellInfo, 2, m_spellInfo->EffectBasePoints[2], unitTarget);
+ damage += int32(m_caster->GetTotalAttackPowerValue(BASE_ATTACK) * pct / 100);
+ break;
+ }
break;
}
case SPELLFAMILY_WARLOCK:
@@ -1361,7 +1368,16 @@ void Spell::EffectDummy(uint32 i)
spell_id = 20647;
bp = damage+int32(rage * m_spellInfo->DmgMultiplier[i] +
m_caster->GetTotalAttackPowerValue(BASE_ATTACK)*0.2f);
- m_caster->SetPower(POWER_RAGE,0);
+ // Sudden death cost modifier
+ if (Aura * aur = m_caster->GetAura(52437))
+ {
+ m_caster->ModifyPower(POWER_RAGE,- m_powerCost);
+ if (m_caster->GetPower(POWER_RAGE)<100)
+ m_caster->SetPower(POWER_RAGE,100);
+ m_caster->RemoveAura(aur);
+ }
+ else
+ m_caster->SetPower(POWER_RAGE,0);
break;
}
// Slam
@@ -1648,29 +1664,31 @@ void Spell::EffectDummy(uint32 i)
return;
}
- case 561: // Judgement of command
+ }
+
+ switch(m_spellInfo->Id)
+ {
+ case 20425: // Judgement of command
{
if(!unitTarget)
return;
- uint32 spell_id = m_spellInfo->EffectBasePoints[i]+1;//m_currentBasePoints[i]+1;
- SpellEntry const* spell_proto = sSpellStore.LookupEntry(spell_id);
+ SpellEntry const* spell_proto = sSpellStore.LookupEntry(damage);
if(!spell_proto)
return;
- if( !unitTarget->hasUnitState(UNIT_STAT_STUNNED) && m_caster->GetTypeId()==TYPEID_PLAYER)
+ if(unitTarget->hasUnitState(UNIT_STAT_STUNNED) && m_caster->GetTypeId()==TYPEID_PLAYER)
{
- // decreased damage (/2) for non-stunned target.
+ // always critical for stunned target
SpellModifier *mod = new SpellModifier;
- mod->op = SPELLMOD_DAMAGE;
- mod->value = -50;
- mod->type = SPELLMOD_PCT;
+ mod->op = SPELLMOD_CRITICAL_CHANCE;
+ mod->value = 100;
+ mod->type = SPELLMOD_FLAT;
mod->spellId = m_spellInfo->Id;
mod->mask[1] = 0x00000200;
((Player*)m_caster)->AddSpellMod(mod, true);
m_caster->CastSpell(unitTarget,spell_proto,true,NULL);
- // mod deleted
((Player*)m_caster)->AddSpellMod(mod, false);
}
else
@@ -1678,10 +1696,6 @@ void Spell::EffectDummy(uint32 i)
return;
}
- }
-
- switch(m_spellInfo->Id)
- {
case 31789: // Righteous Defense (step 1)
{
// 31989 -> dummy effect (step 1) + dummy effect (step 2) -> 31709 (taunt like spell for each target)
@@ -1850,7 +1864,7 @@ void Spell::EffectDummy(uint32 i)
return;
}
// Death Coil
- if(m_spellInfo->SpellFamilyFlags[0] & 0x002000)
+ else if(m_spellInfo->SpellFamilyFlags[0] & 0x002000)
{
if(m_caster->IsFriendlyTo(unitTarget))
{
@@ -1867,6 +1881,12 @@ void Spell::EffectDummy(uint32 i)
}
return;
}
+ // Death Grip
+ else if(m_spellInfo->Id == 49560)
+ {
+ unitTarget->CastSpell(m_caster, damage, true);
+ return;
+ }
break;
}
@@ -1984,6 +2004,7 @@ void Spell::EffectTriggerSpell(uint32 i)
// get highest rank of the Stealth spell
uint32 spellId = 0;
+ SpellEntry const *spellInfo;
const PlayerSpellMap& sp_list = ((Player*)m_caster)->GetSpellMap();
for (PlayerSpellMap::const_iterator itr = sp_list.begin(); itr != sp_list.end(); ++itr)
{
@@ -1991,7 +2012,7 @@ void Spell::EffectTriggerSpell(uint32 i)
if(!itr->second->active || itr->second->disabled || itr->second->state == PLAYERSPELL_REMOVED)
continue;
- SpellEntry const *spellInfo = sSpellStore.LookupEntry(itr->first);
+ spellInfo = sSpellStore.LookupEntry(itr->first);
if (!spellInfo)
continue;
@@ -2010,7 +2031,8 @@ void Spell::EffectTriggerSpell(uint32 i)
if(((Player*)m_caster)->HasSpellCooldown(spellId))
((Player*)m_caster)->RemoveSpellCooldown(spellId);
- m_caster->CastSpell(m_caster, spellId, true);
+ // Push stealth to list because it must be handled after combat remove
+ m_TriggerSpells.push_back(spellInfo);
return;
}
// just skip
@@ -2202,7 +2224,16 @@ void Spell::EffectJump(uint32 i)
return;
}
- m_caster->NearTeleportTo(x,y,z,o,true);
+ //m_caster->NearTeleportTo(x,y,z,o,true);
+ float speedZ;
+ if(m_spellInfo->EffectMiscValue[i])
+ speedZ = float(m_spellInfo->EffectMiscValue[i])/10;
+ else if(m_spellInfo->EffectMiscValueB[i])
+ speedZ = float(m_spellInfo->EffectMiscValueB[i])/10;
+ else
+ speedZ = 10.0f;
+ float speedXY = m_caster->GetExactDistance2d(x, y) * 10.0f / speedZ;
+ m_caster->GetMotionMaster()->MoveJump(x, y, z, speedXY, speedZ);
}
void Spell::EffectTeleportUnits(uint32 i)
@@ -2527,12 +2558,23 @@ void Spell::SpellDamageHeal(uint32 /*i*/)
addhealth += tickheal * tickcount;
// Glyph of Swiftmend
- if(!caster->GetAura(54824))
+ if(!caster->GetDummyAura(54824))
unitTarget->RemoveAura(targetAura->GetId(), targetAura->GetCasterGUID());
//addhealth += tickheal * tickcount;
//addhealth = caster->SpellHealingBonus(m_spellInfo, addhealth,HEAL, unitTarget);
}
+ // Riptide - increase healing done by Chain Heal
+ else if (m_spellInfo->SpellFamilyName==SPELLFAMILY_SHAMAN && m_spellInfo->SpellFamilyFlags[0] & 0x100)
+ {
+ if (AuraEffect * aurEff = unitTarget->GetAura(SPELL_AURA_PERIODIC_HEAL, SPELLFAMILY_SHAMAN, 0, 0, 0x10, m_originalCasterGUID))
+ {
+ addhealth = caster->SpellHealingBonus(unitTarget, m_spellInfo, addhealth, HEAL);
+ addhealth *= 1.25f;
+ // consume aura
+ unitTarget->RemoveAura(aurEff->GetParentAura());
+ }
+ }
else
addhealth = caster->SpellHealingBonus(unitTarget, m_spellInfo, addhealth, HEAL);
@@ -2552,6 +2594,9 @@ void Spell::EffectHealPct( uint32 /*i*/ )
return;
uint32 addhealth = unitTarget->GetMaxHealth() * damage / 100;
+ if(Player* modOwner = m_caster->GetSpellModOwner())
+ modOwner->ApplySpellMod(m_spellInfo->Id, SPELLMOD_DAMAGE, addhealth, this);
+
caster->SendHealSpellLog(unitTarget, m_spellInfo->Id, addhealth, false);
int32 gain = unitTarget->ModifyHealth( int32(addhealth) );
@@ -4029,14 +4074,14 @@ void Spell::SpellDamageWeaponDmg(uint32 i)
{
if (m_caster->GetTypeId()!=TYPEID_PLAYER)
return;
+ SpellEntry const *spellInfo = NULL;
uint32 stack = 0;
- int32 maxStack = 0;
+
if (AuraEffect * aur = unitTarget->GetAura(SPELL_AURA_MOD_RESISTANCE,SPELLFAMILY_WARRIOR,SPELLFAMILYFLAG_WARRIOR_SUNDERARMOR, 0, 0, m_caster->GetGUID()))
{
aur->GetParentAura()->RefreshAura();
+ spellInfo = aur->GetSpellProto();
stack = aur->GetParentAura()->GetStackAmount();
- maxStack = aur->GetSpellProto()->StackAmount;
- break;
}
for(int j = 0; j < 3; j++)
@@ -4048,7 +4093,7 @@ void Spell::SpellDamageWeaponDmg(uint32 i)
}
}
- if(stack < maxStack)
+ if(!spellInfo)
{
// get highest rank of the Sunder Armor spell
const PlayerSpellMap& sp_list = ((Player*)m_caster)->GetSpellMap();
@@ -4058,19 +4103,22 @@ void Spell::SpellDamageWeaponDmg(uint32 i)
if(!itr->second->active || itr->second->disabled || itr->second->state == PLAYERSPELL_REMOVED)
continue;
- SpellEntry const *spellInfo = sSpellStore.LookupEntry(itr->first);
- if (!spellInfo)
+ SpellEntry const *spellProto = sSpellStore.LookupEntry(itr->first);
+ if (!spellProto)
continue;
- if (spellInfo->SpellFamilyFlags.IsEqual(SPELLFAMILYFLAG_WARRIOR_SUNDERARMOR)
- && spellInfo->Id != m_spellInfo->Id
- && spellInfo->SpellFamilyName == SPELLFAMILY_WARRIOR)
+ if (spellProto->SpellFamilyFlags[0] & SPELLFAMILYFLAG_WARRIOR_SUNDERARMOR
+ && spellProto->Id != m_spellInfo->Id
+ && spellProto->SpellFamilyName == SPELLFAMILY_WARRIOR)
{
- m_caster->CastSpell(unitTarget, spellInfo, true);
+ spellInfo = spellProto;
break;
}
}
}
+ if (!spellInfo)
+ break;
+ m_caster->CastSpell(unitTarget, spellInfo, true);
if (stack)
spell_bonus += stack * CalculateDamage(2, unitTarget);
}
@@ -4118,6 +4166,13 @@ void Spell::SpellDamageWeaponDmg(uint32 i)
spell_bonus += int32(0.23f*m_caster->SpellBaseDamageBonus(GetSpellSchoolMask(m_spellInfo)));
spell_bonus += int32(0.29f*m_caster->SpellBaseDamageBonusForVictim(GetSpellSchoolMask(m_spellInfo), unitTarget));
}
+
+ // Seal of Command Unleashed
+ else if(m_spellInfo->Id==20467)
+ {
+ spell_bonus += int32(0.16f*m_caster->GetTotalAttackPowerValue(BASE_ATTACK));
+ spell_bonus += int32(0.25f*m_caster->SpellBaseDamageBonus(GetSpellSchoolMask(m_spellInfo)));
+ }
break;
}
case SPELLFAMILY_SHAMAN:
@@ -4871,8 +4926,14 @@ void Spell::EffectScriptEffect(uint32 effIndex)
// Viper Sting - Instantly restores mana to you equal to 60% of the total amount drained by your Viper Sting.
if (familyFlag[1] & 0x00000080)
{
+ int32 tickCount = (aura->GetAuraMaxDuration() - aura->GetAuraDuration()) / aura->GetPartAura(0)->GetAuraAmplitude();
spellId = 53358; // 53358 Chimera Shot - Viper
- basePoint = aura->GetPartAura(0)->GetAmount() * 4 * 60 / 100;
+ // Amount of one aura tick
+ basePoint = aura->GetPartAura(0)->GetAmount() * aura->GetTarget()->GetMaxPower(POWER_MANA) / 100 ;
+ int32 casterBasePoint = aura->GetPartAura(0)->GetAmount() * unitTarget->GetMaxPower(POWER_MANA) / 50 ;
+ if (basePoint > casterBasePoint)
+ basePoint = casterBasePoint;
+ basePoint = basePoint * tickCount * 60 / 100;
}
// Scorpid Sting - Attempts to Disarm the target for 10 sec. This effect cannot occur more than once per 1 minute.
if (familyFlag[0] & 0x00008000)
@@ -4915,18 +4976,33 @@ void Spell::EffectScriptEffect(uint32 effIndex)
return;
}
// all seals have aura dummy in 2 effect
- Unit::AuraEffectList const& m_dummyAuras = m_caster->GetAurasByType(SPELL_AURA_DUMMY);
- for(Unit::AuraEffectList::const_iterator itr = m_dummyAuras.begin(); itr != m_dummyAuras.end(); ++itr)
- {
- SpellEntry const *spellInfo = (*itr)->GetSpellProto();
- // search seal (all seals have judgement's aura dummy spell id in 2 effect
- if ((*itr)->GetEffIndex() != 2 || !spellInfo || !IsSealSpell(spellInfo))
- continue;
- spellId2 = (*itr)->GetAmount();
- SpellEntry const *judge = sSpellStore.LookupEntry(spellId2);
- if (!judge)
- continue;
- break;
+ Unit::AuraMap & sealAuras = m_caster->GetAuras();
+ for(Unit::AuraMap::iterator iter = sealAuras.begin(); iter != sealAuras.end();)
+ {
+ if (IsSealSpell(iter->second->GetSpellProto()))
+ {
+ if (AuraEffect * aureff = iter->second->GetPartAura(2))
+ if (aureff->GetAuraName()==SPELL_AURA_DUMMY)
+ {
+ if (sSpellStore.LookupEntry(aureff->GetAmount()))
+ spellId2 = aureff->GetAmount();
+ break;
+ }
+ if (!spellId2)
+ {
+ switch (iter->first)
+ {
+ // Seal of light, wisdom, justice
+ case 20165:
+ case 20166:
+ case 20164:
+ spellId2 = 54158;
+ }
+ }
+ break;
+ }
+ else
+ ++iter;
}
if (spellId1)
m_caster->CastSpell(unitTarget, spellId1, true);
@@ -5668,6 +5744,8 @@ void Spell::EffectSummonCritter(uint32 i)
critter->SetReactState(REACT_PASSIVE);
critter->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE);
+ critter->GetMotionMaster()->MoveTargetedHome();
+
std::string name = player->GetName();
name.append(petTypeSuffix[3]);
critter->SetName( name );
@@ -5691,26 +5769,28 @@ void Spell::EffectKnockBack(uint32 i)
}
float speedxy = float(m_spellInfo->EffectMiscValue[i])/10;
- float speedz = float(damage/-10);
+ float speedz = float(damage/10);
- if(unitTarget->GetTypeId() == TYPEID_UNIT)
- {
- unitTarget->GetMotionMaster()->MoveJumpFrom(x, y, speedxy, -speedz);
- return;
- }
-
- float vcos, vsin;
- unitTarget->GetSinCos(x, y, vsin, vcos);
+ unitTarget->KnockbackFrom(x, y, speedxy, speedz);
+}
- WorldPacket data(SMSG_MOVE_KNOCK_BACK, (8+4+4+4+4+4));
- data.append(unitTarget->GetPackGUID());
- data << uint32(0); // Sequence
- data << float(vcos); // x direction
- data << float(vsin); // y direction
- data << float(speedxy); // Horizontal speed
- data << float(speedz); // Z Movement speed (vertical)
+void Spell::EffectJump2(uint32 i)
+{
+ if(!unitTarget)
+ return;
- ((Player*)unitTarget)->GetSession()->SendPacket(&data);
+ float speedxy = float(m_spellInfo->EffectMiscValue[i])/10;
+ float speedz = float(damage/10);
+ if(!speedxy)
+ {
+ if(m_targets.getUnitTarget())
+ unitTarget->JumpTo(m_targets.getUnitTarget(), speedz);
+ }
+ else
+ {
+ //1891: Disengage
+ unitTarget->JumpTo(speedxy, speedz, m_spellInfo->SpellIconID != 1891);
+ }
}
void Spell::EffectSendTaxi(uint32 i)
@@ -5796,7 +5876,7 @@ void Spell::EffectDispelMechanic(uint32 i)
Unit::AuraMap& Auras = unitTarget->GetAuras();
for(Unit::AuraMap::iterator iter = Auras.begin(); iter != Auras.end(); iter++)
- if(GetAllSpellMechanicMask(iter->second->GetSpellProto()) & (1<<(mechanic-1)))
+ if(GetAllSpellMechanicMask(iter->second->GetSpellProto()) & (1<<(mechanic)))
dispel_list.push(iter->second);
for(;dispel_list.size();dispel_list.pop())
@@ -5844,10 +5924,14 @@ void Spell::EffectDestroyAllTotems(uint32 /*i*/)
uint32 spell_id = totem->GetUInt32Value(UNIT_CREATED_BY_SPELL);
SpellEntry const* spellInfo = sSpellStore.LookupEntry(spell_id);
if(spellInfo)
- mana += spellInfo->manaCost * damage / 100;
+ {
+ mana += spellInfo->manaCost;
+ mana += spellInfo->ManaCostPercentage * m_caster->GetCreateMana() / 100;
+ }
((Totem*)totem)->UnSummon();
}
}
+ mana = mana * damage / 100;
int32 gain = m_caster->ModifyPower(POWER_MANA,int32(mana));
m_caster->SendEnergizeSpellLog(m_caster, m_spellInfo->Id, gain, POWER_MANA);
@@ -6417,6 +6501,7 @@ void Spell::SummonVehicle(uint32 entry, SummonPropertiesEntry const *properties)
if(!vehicle)
return;
+ vehicle->SetOwnerGUID(m_caster->GetGUID());
vehicle->SetUInt32Value(UNIT_CREATED_BY_SPELL, m_spellInfo->Id);
if(damage)
diff --git a/src/game/SpellHandler.cpp b/src/game/SpellHandler.cpp
index daa1b2d9add..0efc4cb0ee4 100644
--- a/src/game/SpellHandler.cpp
+++ b/src/game/SpellHandler.cpp
@@ -387,8 +387,6 @@ void WorldSession::HandleCancelAuraOpcode( WorldPacket& recvPacket)
if(spell->m_spellInfo->Id==spellId)
{
spell->cancel();
- spell->SetReferencedFromCurrent(false);
- _player->m_currentSpells[CURRENT_CHANNELED_SPELL] = NULL;
}
}
return;
diff --git a/src/game/SpellMgr.cpp b/src/game/SpellMgr.cpp
index 57b68ae55d9..f3f8907cfc4 100644
--- a/src/game/SpellMgr.cpp
+++ b/src/game/SpellMgr.cpp
@@ -39,18 +39,10 @@ SpellMgr::SpellMgr()
case SPELL_EFFECT_PERSISTENT_AREA_AURA: //27
case SPELL_EFFECT_SUMMON: //28
case SPELL_EFFECT_TRIGGER_MISSILE: //32
- //case SPELL_EFFECT_SUMMON_WILD: //41 not 303
- //case SPELL_EFFECT_SUMMON_GUARDIAN: //42 not 303
case SPELL_EFFECT_TRANS_DOOR: //50 summon object
case SPELL_EFFECT_SUMMON_PET: //56
case SPELL_EFFECT_ADD_FARSIGHT: //72
- //case SPELL_EFFECT_SUMMON_POSSESSED: //73
- //case SPELL_EFFECT_SUMMON_TOTEM: //74
case SPELL_EFFECT_SUMMON_OBJECT_WILD: //76
- //case SPELL_EFFECT_SUMMON_TOTEM_SLOT1: //87
- //case SPELL_EFFECT_SUMMON_TOTEM_SLOT2: //88
- //case SPELL_EFFECT_SUMMON_TOTEM_SLOT3: //89
- //case SPELL_EFFECT_SUMMON_TOTEM_SLOT4: //90
//case SPELL_EFFECT_SUMMON_CRITTER: //97 not 303
case SPELL_EFFECT_SUMMON_OBJECT_SLOT1: //104
case SPELL_EFFECT_SUMMON_OBJECT_SLOT2: //105
@@ -75,6 +67,7 @@ SpellMgr::SpellMgr()
case SPELL_EFFECT_FEED_PET:
case SPELL_EFFECT_PROSPECTING:
case SPELL_EFFECT_MILLING:
+ case SPELL_EFFECT_ENCHANT_ITEM_PRISMATIC:
EffectTargetType[i] = SPELL_REQUIRE_ITEM;
break;
//caster must be pushed otherwise no sound
@@ -83,6 +76,7 @@ SpellMgr::SpellMgr()
case SPELL_EFFECT_APPLY_AREA_AURA_ENEMY:
case SPELL_EFFECT_APPLY_AREA_AURA_PET:
case SPELL_EFFECT_APPLY_AREA_AURA_OWNER:
+ case SPELL_EFFECT_JUMP2: //42
EffectTargetType[i] = SPELL_REQUIRE_CASTER;
break;
default:
@@ -533,6 +527,8 @@ bool IsPositiveEffect(uint32 spellId, uint32 effIndex, bool deep)
case 34700: // Allergic Reaction
case 31719: // Suspension
return false;
+ case 12042: // Arcane Power
+ return true;
}
switch(spellproto->Mechanic)
@@ -597,6 +593,8 @@ bool IsPositiveEffect(uint32 spellId, uint32 effIndex, bool deep)
// non-positive targets of main spell return early
for(int i = 0; i < 3; ++i)
{
+ if (!spellTriggeredProto->Effect[i])
+ continue;
// if non-positive trigger cast targeted to positive target this main cast is non-positive
// this will place this spell auras as debuffs
if(IsPositiveTarget(spellTriggeredProto->EffectImplicitTargetA[effIndex],spellTriggeredProto->EffectImplicitTargetB[effIndex]) && !IsPositiveEffect(spellTriggeredId,i, true))
@@ -604,7 +602,6 @@ bool IsPositiveEffect(uint32 spellId, uint32 effIndex, bool deep)
}
}
}
- break;
case SPELL_AURA_PROC_TRIGGER_SPELL:
// many positive auras have negative triggered spells at damage for example and this not make it negative (it can be canceled for example)
break;
@@ -715,7 +712,7 @@ bool IsPositiveEffect(uint32 spellId, uint32 effIndex, bool deep)
return false;
if (!deep && spellproto->EffectTriggerSpell[effIndex]
- && !spellproto->procFlags
+ && !spellproto->EffectApplyAuraName[effIndex]
&& IsPositiveTarget(spellproto->EffectImplicitTargetA[effIndex],spellproto->EffectImplicitTargetB[effIndex])
&& !IsPositiveSpell(spellproto->EffectTriggerSpell[effIndex], true))
return false;
@@ -1198,7 +1195,7 @@ bool SpellMgr::IsSpellProcEventCanTriggeredBy(SpellProcEventEntry const * spellP
// spellFamilyName is Ok need check for spellFamilyMask if present
if(spellProcEvent->spellFamilyMask)
{
- if ((spellProcEvent->spellFamilyMask & procSpell->SpellFamilyFlags ) == 0)
+ if ((spellProcEvent->spellFamilyMask & procSpell->SpellFamilyFlags ) == 0)
return false;
active = true; // Spell added manualy -> so its active spell
}
@@ -2368,6 +2365,25 @@ void SpellMgr::LoadSpellCustomAttr()
case 18662: // Curse of Doom
spellInfo->EffectBasePoints[0] = 0; //prevent summon too many of them
break;
+ case 17941: // Shadow Trance
+ case 22008: // Netherwind Focus
+ case 31834: // Light's Grace
+ case 34754: // Clearcasting
+ case 34936: // Backlash
+ case 48108: // Hot Streak
+ case 51124: // Killing Machine
+ case 54741: // Firestarter
+ case 57761: // Fireball!
+ case 39805: // Lightning Overload
+ case 52437: // Sudden Death
+ spellInfo->procCharges=1;
+ break;
+ case 44544: // Fingers of Frost
+ spellInfo->procCharges=2;
+ break;
+ case 28200: // Ascendance (Talisman of Ascendance trinket)
+ spellInfo->procCharges=6;
+ break;
default:
break;
}
diff --git a/src/game/TemporarySummon.cpp b/src/game/TemporarySummon.cpp
index acf0dbc78ba..c87ad91ff90 100644
--- a/src/game/TemporarySummon.cpp
+++ b/src/game/TemporarySummon.cpp
@@ -176,10 +176,22 @@ void TempSummon::InitSummon(uint32 duration)
if(m_type == TEMPSUMMON_MANUAL_DESPAWN)
m_type = (duration == 0) ? TEMPSUMMON_DEAD_DESPAWN : TEMPSUMMON_TIMED_DESPAWN;
+ Unit* owner = GetSummoner();
+ if(owner)
+ {
+ if(owner->GetTypeId()==TYPEID_UNIT && ((Creature*)owner)->IsAIEnabled)
+ ((Creature*)owner)->AI()->JustSummoned(this);
+
+ if(GetCreatureInfo()->flags_extra & CREATURE_FLAG_EXTRA_TRIGGER && m_spells[0])
+ {
+ setFaction(owner->getFaction());
+ CastSpell(this, m_spells[0], false, 0, 0, m_summonerGUID);
+ }
+ }
+
if(!m_Properties)
return;
- Unit* owner = GetSummoner();
if(uint32 slot = m_Properties->Slot)
{
if(owner)
@@ -194,18 +206,6 @@ void TempSummon::InitSummon(uint32 duration)
}
}
- if(owner)
- {
- if(owner->GetTypeId()==TYPEID_UNIT && ((Creature*)owner)->IsAIEnabled)
- ((Creature*)owner)->AI()->JustSummoned(this);
-
- if(GetCreatureInfo()->flags_extra & CREATURE_FLAG_EXTRA_TRIGGER && m_spells[0])
- {
- setFaction(owner->getFaction());
- CastSpell(this, m_spells[0], false, 0, 0, m_summonerGUID);
- }
- }
-
if(m_Properties->Faction)
setFaction(m_Properties->Faction);
}
diff --git a/src/game/Unit.cpp b/src/game/Unit.cpp
index e08d4c2d43e..f41637b6c75 100644
--- a/src/game/Unit.cpp
+++ b/src/game/Unit.cpp
@@ -159,7 +159,6 @@ Unit::Unit()
for (int i = 0; i < MAX_MOVE_TYPE; ++i)
m_speed_rate[i] = 1.0f;
- m_removedAuras = 0;
m_charmInfo = NULL;
m_unit_movement_flags = 0;
m_reducedThreatPercent = 0;
@@ -344,38 +343,32 @@ void Unit::SendMonsterMove(float NewPosX, float NewPosY, float NewPosZ, uint32 M
WorldPacket data( SMSG_MONSTER_MOVE, (41 + GetPackGUID().size()) );
data.append(GetPackGUID());
- // Point A, starting location
data << GetPositionX() << GetPositionY() << GetPositionZ();
- // unknown field - unrelated to orientation
- // seems to increment about 1000 for every 1.7 seconds
- // for now, we'll just use mstime
- data << getMSTime();
+ data << uint32(getMSTime());
data << uint8(type); // unknown
switch(type)
{
case 0: // normal packet
break;
- case 1: // stop packet
+ case 1: // stop packet (raw pos?)
SendMessageToSet( &data, true );
return;
- case 2: // not used currently
- data << float(0); // orientation
+ case 2: // facing spot, not used currently
+ data << float(0);
data << float(0);
data << float(0);
break;
case 3: // not used currently
- data << uint64(0); // probably target guid
+ data << uint64(0); // probably target guid (facing target?)
break;
case 4: // not used currently
- data << float(0); // probably orientation
+ data << float(0); // facing angle
break;
}
- //Movement Flags (0x0 = walk, 0x100 = run, 0x200 = fly/swim)
- data << uint32((MovementFlags & MOVEMENTFLAG_LEVITATING) ? MOVEFLAG_FLY : MOVEFLAG_WALK);
-
- data << Time; // Time in between points
+ data << uint32(MovementFlags);
+ data << uint32(Time); // Time in between points
data << uint32(1); // 1 single waypoint
data << NewPosX << NewPosY << NewPosZ; // the single waypoint Point B
@@ -396,16 +389,12 @@ void Unit::SendMonsterMoveByPath(Path const& path, uint32 start, uint32 end)
data << GetPositionX();
data << GetPositionY();
data << GetPositionZ();
-
data << getMSTime();
-
data << uint8( 0 );
data << uint32(((GetUnitMovementFlags() & MOVEMENTFLAG_LEVITATING) || isInFlight())? (MOVEFLAG_FLY|MOVEFLAG_WALK) : MOVEFLAG_WALK);
data << uint32( traveltime );
data << uint32( pathSize );
data.append( (char*)path.GetNodes(start), pathSize * 4 * 3 );
-
- //WPAssert( data.size() == 37 + pathnodes.Size( ) * 4 * 3 );
SendMessageToSet(&data, true);
}
@@ -472,7 +461,10 @@ void Unit::RemoveAurasWithInterruptFlags(uint32 flag, uint32 except)
++iter;
if ((aur->GetSpellProto()->AuraInterruptFlags & flag) && (!except || aur->GetId() != except))
{
+ uint32 removedAuras = m_removedAuras.size();
RemoveAura(aur);
+ if (removedAuras+1<m_removedAuras.size())
+ iter=m_interruptableAuras.begin();
}
}
@@ -513,14 +505,17 @@ void Unit::RemoveSpellbyDamageTaken(uint32 damage, uint32 spell)
++iter;
if ((!spell || aur->GetId() != spell) && roll_chance_f(chance))
{
+ uint32 removedAuras = m_removedAuras.size();
RemoveAura(aur);
+ if (removedAuras+1<m_removedAuras.size())
+ iter=m_ccAuras.begin();
}
}
}
uint32 Unit::DealDamage(Unit *pVictim, uint32 damage, CleanDamage const* cleanDamage, DamageEffectType damagetype, SpellSchoolMask damageSchoolMask, SpellEntry const *spellProto, bool durabilityLoss)
{
- if (!pVictim->isAlive() || pVictim->isInFlight() || pVictim->GetTypeId() == TYPEID_UNIT && ((Creature*)pVictim)->IsInEvadeMode())
+ if (!pVictim->isAlive() || pVictim->hasUnitState(UNIT_STAT_UNATTACKABLE) || pVictim->GetTypeId() == TYPEID_UNIT && ((Creature*)pVictim)->IsInEvadeMode())
return 0;
//You don't lose health from damage taken from another player while in a sanctuary
@@ -1323,7 +1318,7 @@ void Unit::DealSpellDamage(SpellNonMeleeDamage *damageInfo, bool durabilityLoss)
if(!this || !pVictim)
return;
- if (!pVictim->isAlive() || pVictim->isInFlight() || pVictim->GetTypeId() == TYPEID_UNIT && ((Creature*)pVictim)->IsInEvadeMode())
+ if (!pVictim->isAlive() || pVictim->hasUnitState(UNIT_STAT_UNATTACKABLE) || pVictim->GetTypeId() == TYPEID_UNIT && ((Creature*)pVictim)->IsInEvadeMode())
return;
SpellEntry const *spellProto = sSpellStore.LookupEntry(damageInfo->SpellID);
@@ -1566,7 +1561,7 @@ void Unit::DealMeleeDamage(CalcDamageInfo *damageInfo, bool durabilityLoss)
if(!this || !pVictim)
return;
- if (!pVictim->isAlive() || pVictim->isInFlight() || pVictim->GetTypeId() == TYPEID_UNIT && ((Creature*)pVictim)->IsInEvadeMode())
+ if (!pVictim->isAlive() || pVictim->hasUnitState(UNIT_STAT_UNATTACKABLE) || pVictim->GetTypeId() == TYPEID_UNIT && ((Creature*)pVictim)->IsInEvadeMode())
return;
//You don't lose health from damage taken from another player while in a sanctuary
@@ -1626,7 +1621,8 @@ void Unit::DealMeleeDamage(CalcDamageInfo *damageInfo, bool durabilityLoss)
// If this is a creature and it attacks from behind it has a probability to daze it's victim
if( (damageInfo->hitOutCome==MELEE_HIT_CRIT || damageInfo->hitOutCome==MELEE_HIT_CRUSHING || damageInfo->hitOutCome==MELEE_HIT_NORMAL || damageInfo->hitOutCome==MELEE_HIT_GLANCING) &&
- GetTypeId() != TYPEID_PLAYER && !((Creature*)this)->GetCharmerOrOwnerGUID() && !pVictim->HasInArc(M_PI, this) )
+ GetTypeId() != TYPEID_PLAYER && !((Creature*)this)->GetCharmerOrOwnerGUID() && !pVictim->HasInArc(M_PI, this)
+ && (pVictim->GetTypeId() == TYPEID_PLAYER || !((Creature*)pVictim)->isWorldBoss()))
{
// -probability is between 0% and 40%
// 20% base chance
@@ -1659,7 +1655,7 @@ void Unit::DealMeleeDamage(CalcDamageInfo *damageInfo, bool durabilityLoss)
// victim's damage shield
std::set<AuraEffect*> alreadyDone;
- uint32 removedAuras = pVictim->m_removedAuras;
+ uint32 removedAuras = pVictim->m_removedAuras.size();
AuraEffectList const& vDamageShields = pVictim->GetAurasByType(SPELL_AURA_DAMAGE_SHIELD);
for(AuraEffectList::const_iterator i = vDamageShields.begin(), next = vDamageShields.begin(); i != vDamageShields.end(); i = next)
{
@@ -1688,9 +1684,9 @@ void Unit::DealMeleeDamage(CalcDamageInfo *damageInfo, bool durabilityLoss)
pVictim->DealDamage(this, damage, 0, SPELL_DIRECT_DAMAGE, GetSpellSchoolMask(spellProto), spellProto, true);
- if (pVictim->m_removedAuras > removedAuras)
+ if (pVictim->m_removedAuras.size() > removedAuras)
{
- removedAuras = pVictim->m_removedAuras;
+ removedAuras = pVictim->m_removedAuras.size();
next = vDamageShields.begin();
}
}
@@ -2083,7 +2079,10 @@ void Unit::CalcAbsorbResist(Unit *pVictim,SpellSchoolMask schoolMask, DamageEffe
++i;
if (auraeff->GetAmount()<=0)
{
- pVictim->RemoveAura(aura);
+ uint32 removedAuras = pVictim->m_removedAuras.size();
+ pVictim->RemoveAura(aura, AURA_REMOVE_BY_ENEMY_SPELL);
+ if (removedAuras+1<pVictim->m_removedAuras.size())
+ i=vSchoolAbsorb.begin();
}
}
}
@@ -2118,7 +2117,7 @@ void Unit::CalcAbsorbResist(Unit *pVictim,SpellSchoolMask schoolMask, DamageEffe
(*i)->SetAmount((*i)->GetAmount()-currentAbsorb);
if((*i)->GetAmount() <= 0)
{
- pVictim->RemoveAurasDueToSpell((*i)->GetId());
+ pVictim->RemoveAura((*i)->GetParentAura(), AURA_REMOVE_BY_ENEMY_SPELL);
next = vManaShield.begin();
}
@@ -2426,7 +2425,10 @@ MeleeHitOutcome Unit::RollMeleeOutcomeAgainst (const Unit *pVictim, WeaponAttack
if (tmp > 0 && roll < (sum += tmp))
{
DEBUG_LOG ("RollMeleeOutcomeAgainst: CRIT <%d, %d)", sum-tmp, sum);
- return MELEE_HIT_CRIT;
+ if(GetTypeId() == TYPEID_UNIT && (((Creature*)this)->GetCreatureInfo()->flags_extra & CREATURE_FLAG_EXTRA_NO_CRIT))
+ DEBUG_LOG ("RollMeleeOutcomeAgainst: CRIT DISABLED)");
+ else
+ return MELEE_HIT_CRIT;
}
// Max 40% chance to score a glancing blow against mobs that are higher level (can do only players and pets and not with ranged weapon)
@@ -2832,7 +2834,7 @@ SpellMissInfo Unit::MagicSpellHitResult(Unit *pVictim, SpellEntry const *spell)
HitChance -= int32(((Player*)pVictim)->GetRatingBonusValue(CR_HIT_TAKEN_SPELL)*100.0f);
if (HitChance < 100) HitChance = 100;
- if (HitChance > 9900) HitChance = 9900;
+ if (HitChance > 10000) HitChance = 10000;
int32 tmp = 10000 - HitChance;
@@ -3183,6 +3185,67 @@ uint32 Unit::GetWeaponSkillValue (WeaponAttackType attType, Unit const* target)
return value;
}
+void Unit::_DeleteAuras()
+{
+ for (AuraList::iterator i = m_removedAuras.begin(); i != m_removedAuras.end();i = m_removedAuras.begin())
+ {
+ Aura * Aur = *i;
+ SpellEntry const* AurSpellInfo = Aur->GetSpellProto();
+ // Statue unsummoned at aura delete
+ Totem* statue = NULL;
+ if(Aur->GetAuraDuration() && !Aur->IsPersistent() && IsChanneledSpell(Aur->GetSpellProto()))
+ {
+ Unit* caster = Aur->GetCaster();
+ if(caster && caster->isAlive())
+ {
+ // stop caster chanelling state
+ if(caster->m_currentSpells[CURRENT_CHANNELED_SPELL])
+ {
+ // same spell
+ if (AurSpellInfo == caster->m_currentSpells[CURRENT_CHANNELED_SPELL]->m_spellInfo
+ //prevent recurential call
+ && caster->m_currentSpells[CURRENT_CHANNELED_SPELL]->getState() != SPELL_STATE_FINISHED)
+ {
+ if (caster==this || !IsAreaOfEffectSpell(AurSpellInfo))
+ {
+ // remove auras only for non-aoe spells or when chanelled aura is removed
+ // because aoe spells don't require aura on target to continue
+ caster->m_currentSpells[CURRENT_CHANNELED_SPELL]->cancel();
+ }
+
+ if(caster->GetTypeId()==TYPEID_UNIT && ((Creature*)caster)->isTotem() && ((Totem*)caster)->GetTotemType()==TOTEM_STATUE)
+ statue = ((Totem*)caster);
+ }
+ }
+
+ // Unsummon summon as possessed creatures on spell cancel
+ if(caster->GetTypeId() == TYPEID_PLAYER)
+ {
+ for(int i = 0; i < 3; ++i)
+ {
+ if(AurSpellInfo->Effect[i] == SPELL_EFFECT_SUMMON)
+ if(SummonPropertiesEntry const *SummonProperties = sSummonPropertiesStore.LookupEntry(AurSpellInfo->EffectMiscValueB[i]))
+ if(SummonProperties->Category == SUMMON_CATEGORY_POSSESSED)
+ {
+ ((Player*)caster)->StopCastingCharm();
+ break;
+ }
+ }
+ }
+ }
+ }
+ if(statue)
+ {
+ sLog.outDebug("Statue %d is unsummoned by aura %d delete from unit %d", statue->GetGUIDLow(), Aur->GetId(),GetGUIDLow());
+ statue->UnSummon();
+ }
+
+ sLog.outDebug("Aura %d is deleted from unit %d", Aur->GetId(), GetGUIDLow());
+ m_removedAuras.pop_front();
+ delete (Aur);
+ }
+}
+
void Unit::_UpdateSpells( uint32 time )
{
if(m_currentSpells[CURRENT_AUTOREPEAT_SPELL])
@@ -3199,7 +3262,6 @@ void Unit::_UpdateSpells( uint32 time )
}
// TODO: Find a better way to prevent crash when multiple auras are removed.
- m_removedAuras = 0;
for (AuraMap::iterator i = m_Auras.begin(); i != m_Auras.end(); ++i)
i->second->SetUpdated(false);
@@ -3208,20 +3270,20 @@ void Unit::_UpdateSpells( uint32 time )
Aura *aur = i->second;
// prevent double update
- if (aur->IsUpdated())
+ if(aur->IsUpdated())
+ {
+ ++i;
continue;
+ }
+
aur->SetUpdated(true);
- aur->SetInUse(true);
+ uint32 removedAuras = m_removedAuras.size();
aur->Update( time );
- aur->SetInUse(false);
// several auras can be deleted due to update
- if(m_removedAuras)
- {
- m_removedAuras = 0;
+ if(removedAuras < m_removedAuras.size())
i = m_Auras.begin();
- }
else
++i;
}
@@ -3234,6 +3296,8 @@ void Unit::_UpdateSpells( uint32 time )
++i;
}
+ _DeleteAuras();
+
if(!m_gameObj.empty())
{
std::list<GameObject*>::iterator ite1, dnext1;
@@ -3696,6 +3760,8 @@ bool Unit::AddAura(Aura *Aur)
{
if(foundAura->GetStackAmount() < aurSpellInfo->StackAmount)
foundAura->SetStackAmount(foundAura->GetStackAmount()+1);
+ else
+ foundAura->RefreshAura();
delete Aur;
return true;
}
@@ -3751,7 +3817,7 @@ bool Unit::AddAura(Aura *Aur)
}
if((Aur->GetSpellProto()->Attributes & SPELL_ATTR_BREAKABLE_BY_DAMAGE
&& !Aur->IsAuraType(SPELL_AURA_MOD_POSSESS)) //only dummy aura is breakable
- || (Aur->GetSpellProto()->Mechanic==MECHANIC_KNOCKOUT && Aur->IsAuraType(SPELL_AURA_MOD_STUN)))
+ || ((GetAllSpellMechanicMask(Aur->GetSpellProto()) & 1<<MECHANIC_KNOCKOUT) && Aur->IsAuraType(SPELL_AURA_MOD_STUN)))
{
m_ccAuras.push_back(Aur);
}
@@ -3787,7 +3853,6 @@ bool Unit::RemoveNoStackAurasDueToAura(Aura *Aur)
{
next = i;
++next;
- if ((*i).second->IsInUse()) continue;
SpellEntry const* i_spellProto = (*i).second->GetSpellProto();
@@ -3863,12 +3928,9 @@ void Unit::RemoveAura(uint32 spellId, uint64 caster ,AuraRemoveMode removeMode)
void Unit::RemoveAura(Aura * aur ,AuraRemoveMode mode)
{
- if (aur->IsInUse())
- {
- if (!aur->GetRemoveMode())
- aur->RemoveAura(mode);
+ // no need to remove
+ if (!aur || aur->IsRemoved())
return;
- }
for(AuraMap::iterator iter = m_Auras.lower_bound(aur->GetId()); iter != m_Auras.upper_bound(aur->GetId());)
{
if (aur == iter->second)
@@ -3885,7 +3947,7 @@ void Unit::RemoveAurasDueToSpell(uint32 spellId, uint64 caster ,AuraRemoveMode r
{
for(AuraMap::iterator iter = m_Auras.lower_bound(spellId); iter != m_Auras.upper_bound(spellId);)
{
- if ((!caster || iter->second->GetCasterGUID()==caster) && (!iter->second->IsInUse() || !iter->second->GetRemoveMode()))
+ if (!caster || iter->second->GetCasterGUID()==caster)
{
RemoveAura(iter, removeMode);
iter = m_Auras.lower_bound(spellId);
@@ -3958,15 +4020,15 @@ void Unit::RemoveAurasDueToSpellBySteal(uint32 spellId, uint64 casterGUID, Unit
else
damage[i]=NULL;
}
- int32 dur = 2*MINUTE*IN_MILISECONDS > aur->GetAuraDuration() ? 2*MINUTE*IN_MILISECONDS : aur->GetAuraDuration();
+ int32 dur = 2*MINUTE*IN_MILISECONDS < aur->GetAuraDuration() ? 2*MINUTE*IN_MILISECONDS : aur->GetAuraDuration();
Aura * new_aur = new Aura(aur->GetSpellProto(),aur->GetEffectMask(), NULL, stealer, stealer, NULL);
new_aur->SetLoadedState(aur->GetCasterGUID(), dur, dur, aur->GetAuraCharges(), aur->GetStackAmount(), &damage[0]);
// Unregister _before_ adding to stealer
aur->UnregisterSingleCastAura();
-
// strange but intended behaviour: Stolen single target auras won't be treated as single targeted
new_aur->SetIsSingleTarget(false);
+ stealer->AddAura(new_aur);
RemoveAuraFromStack(iter, AURA_REMOVE_BY_ENEMY_SPELL);
return;
}
@@ -3979,7 +4041,7 @@ void Unit::RemoveAurasDueToItemSpell(Item* castItem,uint32 spellId)
{
for (AuraMap::iterator iter = m_Auras.lower_bound(spellId); iter != m_Auras.upper_bound(spellId);)
{
- if ((!castItem || iter->second->GetCastItemGUID()==castItem->GetGUID()) && (!iter->second->IsInUse() || !iter->second->GetRemoveMode()))
+ if (!castItem || iter->second->GetCastItemGUID()==castItem->GetGUID())
{
RemoveAura(iter);
iter = m_Auras.upper_bound(spellId); // overwrite by more appropriate
@@ -3998,7 +4060,10 @@ void Unit::RemoveAurasByType(AuraType auraType, uint64 casterGUID, Aura * except
++iter;
if (aur != except && (!casterGUID || aur->GetCasterGUID()==casterGUID))
{
+ uint32 removedAuras = m_removedAuras.size();
RemoveAura(aur);
+ if (removedAuras+1<m_removedAuras.size())
+ iter=m_modAuras[auraType].begin();
}
}
}
@@ -4012,7 +4077,10 @@ void Unit::RemoveAurasByTypeWithDispel(AuraType auraType, Spell * spell)
++iter;
if (GetDispelChance(spell, aur->GetCaster(), aur->GetId()))
{
+ uint32 removedAuras = m_removedAuras.size();
RemoveAura(aur, AURA_REMOVE_BY_ENEMY_SPELL);
+ if (removedAuras+1<m_removedAuras.size())
+ iter=m_modAuras[auraType].begin();
}
}
}
@@ -4032,35 +4100,25 @@ void Unit::RemoveNotOwnSingleTargetAuras()
AuraList& scAuras = GetSingleCastAuras();
for (AuraList::iterator iter = scAuras.begin(); iter != scAuras.end();)
{
- if ((*iter)->GetTarget()!=this)
+ Aura * aur=*iter;
+ ++iter;
+ if (aur->GetTarget()!=this)
{
- Aura * aur=*iter;
- ++iter;
+ uint32 removedAuras = m_removedAuras.size();
aur->GetTarget()->RemoveAura(aur->GetId(),aur->GetCasterGUID());
+ if (removedAuras+1<m_removedAuras.size())
+ iter=scAuras.begin();
}
- else
- ++iter;
}
}
void Unit::RemoveAura(AuraMap::iterator &i, AuraRemoveMode mode)
{
Aura* Aur = i->second;
- //aura can be during update when removing, set it to remove at next update
- if (Aur->IsInUse())
- {
- if (!Aur->GetRemoveMode())
- Aur->RemoveAura(mode);
- i++;
- return;
- }
-
- SpellEntry const* AurSpellInfo = Aur->GetSpellProto();
// some ShapeshiftBoosts at remove trigger removing other auras including parent Shapeshift aura
// remove aura from list before to prevent deleting it before
m_Auras.erase(i);
- ++m_removedAuras; // internal count used by unit update
Aur->UnregisterSingleCastAura();
@@ -4072,71 +4130,20 @@ void Unit::RemoveAura(AuraMap::iterator &i, AuraRemoveMode mode)
if((Aur->GetSpellProto()->Attributes & SPELL_ATTR_BREAKABLE_BY_DAMAGE
&& !Aur->IsAuraType(SPELL_AURA_MOD_POSSESS)) //only dummy aura is breakable
- || (Aur->GetSpellProto()->Mechanic==MECHANIC_KNOCKOUT && Aur->IsAuraType(SPELL_AURA_MOD_STUN)))
+ || ((GetAllSpellMechanicMask(Aur->GetSpellProto()) & 1<<MECHANIC_KNOCKOUT) && Aur->IsAuraType(SPELL_AURA_MOD_STUN)))
{
m_ccAuras.remove(Aur);
}
- // Set remove mode if mode already not set
- if (!Aur->GetRemoveMode())
- Aur->SetRemoveMode(mode);
-
- // Statue unsummoned at aura remove
- Totem* statue = NULL;
- bool channeled = false;
- if(Aur->GetAuraDuration() && !Aur->IsPersistent() && IsChanneledSpell(AurSpellInfo))
- {
- Unit* caster = Aur->GetCaster();
- if(caster && caster->isAlive())
- {
- // stop caster chanelling state
- if(caster->m_currentSpells[CURRENT_CHANNELED_SPELL])
- {
- // same spell
- if (AurSpellInfo == caster->m_currentSpells[CURRENT_CHANNELED_SPELL]->m_spellInfo
- //prevent recurential call
- && caster->m_currentSpells[CURRENT_CHANNELED_SPELL]->getState() != SPELL_STATE_FINISHED)
- {
- if (caster==this || !IsAreaOfEffectSpell(AurSpellInfo))
- {
- // remove auras only for non-aoe spells or when chanelled aura is removed
- // because aoe spells don't require aura on target to continue
- {
- caster->m_currentSpells[CURRENT_CHANNELED_SPELL]->cancel();
- caster->m_currentSpells[CURRENT_CHANNELED_SPELL]=NULL;
- }
- }
-
- if(caster->GetTypeId()==TYPEID_UNIT && ((Creature*)caster)->isTotem() && ((Totem*)caster)->GetTotemType()==TOTEM_STATUE)
- statue = ((Totem*)caster);
- }
- }
-
- // Unsummon summon as possessed creatures on spell cancel
- if(caster->GetTypeId() == TYPEID_PLAYER)
- {
- for(int i = 0; i < 3; ++i)
- {
- if(AurSpellInfo->Effect[i] == SPELL_EFFECT_SUMMON)
- if(SummonPropertiesEntry const *SummonProperties = sSummonPropertiesStore.LookupEntry(AurSpellInfo->EffectMiscValueB[i]))
- if(SummonProperties->Category == SUMMON_CATEGORY_POSSESSED)
- {
- ((Player*)caster)->StopCastingCharm();
- break;
- }
- }
- }
- }
- }
+ Aur->SetRemoveMode(mode);
sLog.outDebug("Aura %u now is remove mode %d", Aur->GetId(), mode);
Aur->HandleEffects(false);
- Aur->_RemoveAura();
- delete Aur;
+ // set aura to be removed during unit::_updatespells
+ m_removedAuras.push_back(Aur);
- if(statue)
- statue->UnSummon();
+ Aur->_RemoveAura();
// only way correctly remove all auras from list
i = m_Auras.begin();
@@ -4233,6 +4240,21 @@ bool Unit::HasAura(uint32 spellId, uint64 caster) const
return false;
}
+bool Unit::HasAura(Aura * aur) const
+{
+ // no need to find aura
+ if (!aur || aur->IsRemoved())
+ return false;
+ for(AuraMap::const_iterator iter = m_Auras.lower_bound(aur->GetId()); iter != m_Auras.upper_bound(aur->GetId());)
+ {
+ if (aur == iter->second)
+ return true;
+ else
+ ++iter;
+ }
+ return false;
+}
+
bool Unit::HasAuraEffect(uint32 spellId, uint8 effIndex, uint64 caster) const
{
if (Aura * aur = GetAura(spellId, caster))
@@ -4745,10 +4767,6 @@ bool Unit::HandleDummyAuraProc(Unit *pVictim, uint32 damage, AuraEffect* trigger
case 9799:
case 25988:
{
- // prevent damage back from weapon special attacks
- if (!procSpell || procSpell->DmgClass != SPELL_DAMAGE_CLASS_MAGIC )
- return false;
-
// return damage % to attacker but < 50% own total health
basepoints0 = triggerAmount*int32(damage)/100;
if(basepoints0 > GetMaxHealth()/2)
@@ -5124,7 +5142,7 @@ bool Unit::HandleDummyAuraProc(Unit *pVictim, uint32 damage, AuraEffect* trigger
for(AuraMap::iterator iter = Auras.begin(); iter != Auras.end();)
{
SpellEntry const *spell = iter->second->GetSpellProto();
- if( GetAllSpellMechanicMask(spell) & 1<<(MECHANIC_STUN-1))
+ if( GetAllSpellMechanicMask(spell) & 1<<(MECHANIC_STUN))
{
pVictim->RemoveAura(iter);
}
@@ -5388,7 +5406,7 @@ bool Unit::HandleDummyAuraProc(Unit *pVictim, uint32 damage, AuraEffect* trigger
if (!target)
return false;
triggered_spell_id = 54181;
- basepoints0 = damage * triggerAmount / 100;
+ basepoints0 = damage * 15 / 100;
break;
}
switch(dummySpell->Id)
@@ -5599,14 +5617,14 @@ bool Unit::HandleDummyAuraProc(Unit *pVictim, uint32 damage, AuraEffect* trigger
// Leader of the Pack
case 24932:
{
- if (triggerAmount <= 0)
+ if (triggerAmount <= 0)
return false;
basepoints0 = triggerAmount * GetMaxHealth() / 100;
target = this;
triggered_spell_id = 34299;
if (triggeredByAura->GetCaster() != this)
break;
- int32 basepoints1 = triggerAmount * 2 *GetMaxPower(POWER_MANA)/100;
+ int32 basepoints1 = triggerAmount * 2;
CastCustomSpell(this,60889,&basepoints1,0,0,true,0,triggeredByAura);
break;
}
@@ -5818,6 +5836,34 @@ bool Unit::HandleDummyAuraProc(Unit *pVictim, uint32 damage, AuraEffect* trigger
basepoints0 = GetAttackTime(BASE_ATTACK) * int32(ap*0.022f + 0.044f * holy) / 1000;
break;
}
+ // Light's Beacon - Beacon of Light
+ if ( dummySpell->Id == 53651 )
+ {
+ if (Unit * caster = triggeredByAura->GetCaster())
+ {
+ // do not proc when target of beacon of light is healed
+ if (caster == pVictim)
+ return false;
+ if (Aura * aur = caster->GetAura(53563))
+ {
+ if (Unit * paladin = aur->GetCaster())
+ {
+ if (paladin != this)
+ return false;
+ basepoints0 = damage;
+ triggered_spell_id = 53654;
+ target = caster;
+ break;
+ }
+ else
+ {
+ pVictim->RemoveAura(triggeredByAura->GetParentAura());
+ return false;
+ }
+ }
+ }
+ else return false;
+ }
// Judgements of the Wise
if (dummySpell->SpellIconID == 3017)
{
@@ -6595,7 +6641,7 @@ bool Unit::HandleProcTriggerSpell(Unit *pVictim, uint32 damage, AuraEffect* trig
Item* castItem = triggeredByAura->GetParentAura()->GetCastItemGUID() && GetTypeId()==TYPEID_PLAYER
? ((Player*)this)->GetItemByGuid(triggeredByAura->GetParentAura()->GetCastItemGUID()) : NULL;
- // Try handle uncnown trigger spells
+ // Try handle unknown trigger spells
if (sSpellStore.LookupEntry(trigger_spell_id)==NULL)
{
switch (auraSpellInfo->SpellFamilyName)
@@ -8000,7 +8046,7 @@ void Unit::SetGuardian(Guardian* guardian, bool apply)
if(AddUInt64Value(UNIT_FIELD_SUMMON, guardian->GetGUID()))
{
- if(GetTypeId() == TYPEID_PLAYER)
+ if(GetTypeId() == TYPEID_PLAYER && !GetCharmGUID())
{
if(guardian->isPet())
((Player*)this)->PetSpellInitialize();
@@ -8035,12 +8081,17 @@ void Unit::SetGuardian(Guardian* guardian, bool apply)
//Check if there is another guardian
for(ControlList::iterator itr = m_Controlled.begin(); itr != m_Controlled.end(); ++itr)
{
+ if(GetCharmGUID() == (*itr)->GetGUID())
+ continue;
+
assert((*itr)->GetOwnerGUID() == GetGUID());
+ assert((*itr)->GetTypeId() == TYPEID_UNIT);
if(AddUInt64Value(UNIT_FIELD_SUMMON, (*itr)->GetGUID()))
{
- if(GetTypeId() == TYPEID_PLAYER)
+ //show another pet bar if there is no charm bar
+ if(GetTypeId() == TYPEID_PLAYER && !GetCharmGUID())
{
- if(guardian->isPet())
+ if(((Creature*)(*itr))->isPet())
((Player*)this)->PetSpellInitialize();
else
((Player*)this)->CharmSpellInitialize();
@@ -8665,18 +8716,28 @@ bool Unit::isSpellCrit(Unit *pVictim, SpellEntry const *spellProto, SpellSchoolM
if (pVictim->GetTypeId() == TYPEID_PLAYER)
crit_chance -= ((Player*)pVictim)->GetRatingBonusValue(CR_CRIT_TAKEN_SPELL);
}
-
// scripted (increase crit chance ... against ... target by x%
AuraEffectList const& mOverrideClassScript = GetAurasByType(SPELL_AURA_OVERRIDE_CLASS_SCRIPTS);
for(AuraEffectList::const_iterator i = mOverrideClassScript.begin(); i != mOverrideClassScript.end(); ++i)
{
if (!((*i)->isAffectedOnSpell(spellProto)))
continue;
+ int32 modChance=0;
switch((*i)->GetMiscValue())
{
- case 849: if (pVictim->HasAuraState(AURA_STATE_FROZEN, spellProto, this)) crit_chance+= 17.0f; break; //Shatter Rank 1
- case 910: if (pVictim->HasAuraState(AURA_STATE_FROZEN, spellProto, this)) crit_chance+= 34.0f; break; //Shatter Rank 2
- case 911: if (pVictim->HasAuraState(AURA_STATE_FROZEN, spellProto, this)) crit_chance+= 50.0f; break; //Shatter Rank 3
+ // Shatter
+ case 911: modChance+= 16.0f;
+ case 910: modChance+= 17.0f;
+ case 849: modChance+= 17.0f;
+ if (!pVictim->HasAuraState(AURA_STATE_FROZEN, spellProto, this))
+ break;
+ crit_chance+=modChance;
+ // Fingers of Frost
+ // TODO: Change this code to less hacky
+ if (Aura * aur = GetAura(44544))
+ if (aur->DropAuraCharge())
+ RemoveAura(aur);
+ break;
case 7917: // Glyph of Shadowburn
if (pVictim->HasAuraState(AURA_STATE_HEALTHLESS_35_PERCENT, spellProto, this))
crit_chance+=(*i)->GetAmount();
@@ -8906,6 +8967,7 @@ uint32 Unit::SpellHealingBonus(Unit *pVictim, SpellEntry const *spellProto, uint
// Check for table values
SpellBonusEntry const* bonus = spellmgr.GetSpellBonusData(spellProto->Id);
float coeff;
+ bool scripted = false;
if (bonus)
{
if (damagetype == DOT)
@@ -8915,57 +8977,74 @@ uint32 Unit::SpellHealingBonus(Unit *pVictim, SpellEntry const *spellProto, uint
if (bonus->ap_bonus)
DoneTotal+=bonus->ap_bonus * GetTotalAttackPowerValue(BASE_ATTACK) * stack;
}
+ else // scripted bonus
+ {
+ // Gift of the Naaru
+ if (spellProto->Id==59547)
+ {
+ scripted = true;
+ uint32 apBonus = GetTotalAttackPowerValue(BASE_ATTACK);
+ if (apBonus > DoneAdvertisedBenefit)
+ {
+ DoneTotal+=apBonus * stack;
+ coeff = 0.0f;
+ }
+ else
+ coeff = 1.0f;
+ }
+ }
+
// Default calculation
if (DoneAdvertisedBenefit || TakenAdvertisedBenefit)
{
- if(!bonus)
- {
- // Damage Done from spell damage bonus
- int32 CastingTime = !IsChanneledSpell(spellProto) ? GetSpellCastTime(spellProto) : GetSpellDuration(spellProto);
- // Damage over Time spells bonus calculation
- float DotFactor = 1.0f;
- if(damagetype == DOT)
+ if(!bonus && !scripted)
{
- int32 DotDuration = GetSpellDuration(spellProto);
- // 200% limit
- if(DotDuration > 0)
+ // Damage Done from spell damage bonus
+ int32 CastingTime = !IsChanneledSpell(spellProto) ? GetSpellCastTime(spellProto) : GetSpellDuration(spellProto);
+ // Damage over Time spells bonus calculation
+ float DotFactor = 1.0f;
+ if(damagetype == DOT)
{
- if(DotDuration > 30000) DotDuration = 30000;
- if(!IsChanneledSpell(spellProto)) DotFactor = DotDuration / 15000.0f;
- int x = 0;
- for(int j = 0; j < 3; j++)
+ int32 DotDuration = GetSpellDuration(spellProto);
+ // 200% limit
+ if(DotDuration > 0)
{
- if( spellProto->Effect[j] == SPELL_EFFECT_APPLY_AURA && (
- spellProto->EffectApplyAuraName[j] == SPELL_AURA_PERIODIC_DAMAGE ||
- spellProto->EffectApplyAuraName[j] == SPELL_AURA_PERIODIC_LEECH) )
+ if(DotDuration > 30000) DotDuration = 30000;
+ if(!IsChanneledSpell(spellProto)) DotFactor = DotDuration / 15000.0f;
+ int x = 0;
+ for(int j = 0; j < 3; j++)
{
- x = j;
- break;
+ if( spellProto->Effect[j] == SPELL_EFFECT_APPLY_AURA && (
+ spellProto->EffectApplyAuraName[j] == SPELL_AURA_PERIODIC_DAMAGE ||
+ spellProto->EffectApplyAuraName[j] == SPELL_AURA_PERIODIC_LEECH) )
+ {
+ x = j;
+ break;
+ }
+ }
+ int32 DotTicks = 6;
+ if(spellProto->EffectAmplitude[x] != 0)
+ DotTicks = DotDuration / spellProto->EffectAmplitude[x];
+ if(DotTicks)
+ {
+ DoneAdvertisedBenefit = DoneAdvertisedBenefit * int32(stack) / DotTicks;
+ TakenAdvertisedBenefit = TakenAdvertisedBenefit * int32(stack) / DotTicks;
}
- }
- int32 DotTicks = 6;
- if(spellProto->EffectAmplitude[x] != 0)
- DotTicks = DotDuration / spellProto->EffectAmplitude[x];
- if(DotTicks)
- {
- DoneAdvertisedBenefit = DoneAdvertisedBenefit * int32(stack) / DotTicks;
- TakenAdvertisedBenefit = TakenAdvertisedBenefit * int32(stack) / DotTicks;
}
}
- }
- // Distribute Damage over multiple effects, reduce by AoE
- CastingTime = GetCastingTimeForBonus( spellProto, damagetype, CastingTime );
- // 50% for damage and healing spells for leech spells from damage bonus and 0% from healing
- for(int j = 0; j < 3; ++j)
- {
- if( spellProto->Effect[j] == SPELL_EFFECT_HEALTH_LEECH ||
- spellProto->Effect[j] == SPELL_EFFECT_APPLY_AURA && spellProto->EffectApplyAuraName[j] == SPELL_AURA_PERIODIC_LEECH )
+ // Distribute Damage over multiple effects, reduce by AoE
+ CastingTime = GetCastingTimeForBonus( spellProto, damagetype, CastingTime );
+ // 50% for damage and healing spells for leech spells from damage bonus and 0% from healing
+ for(int j = 0; j < 3; ++j)
{
- CastingTime /= 2;
- break;
+ if( spellProto->Effect[j] == SPELL_EFFECT_HEALTH_LEECH ||
+ spellProto->Effect[j] == SPELL_EFFECT_APPLY_AURA && spellProto->EffectApplyAuraName[j] == SPELL_AURA_PERIODIC_LEECH )
+ {
+ CastingTime /= 2;
+ break;
+ }
}
- }
- coeff = (CastingTime / 3500.0f) * DotFactor;
+ coeff = (CastingTime / 3500.0f) * DotFactor;
}
float coeff2 = CalculateLevelPenalty(spellProto) * 1.88f * stack;
@@ -9117,12 +9196,15 @@ bool Unit::IsImmunedToSpell(SpellEntry const* spellInfo)
return true;
}
- SpellImmuneList const& mechanicList = m_spellImmune[IMMUNITY_MECHANIC];
- for(SpellImmuneList::const_iterator itr = mechanicList.begin(); itr != mechanicList.end(); ++itr)
+ if (spellInfo->Mechanic)
{
- if(itr->type & (1<<spellInfo->Mechanic))
+ SpellImmuneList const& mechanicList = m_spellImmune[IMMUNITY_MECHANIC];
+ for(SpellImmuneList::const_iterator itr = mechanicList.begin(); itr != mechanicList.end(); ++itr)
{
- return true;
+ if(itr->type == spellInfo->Mechanic)
+ {
+ return true;
+ }
}
}
@@ -9153,7 +9235,7 @@ bool Unit::IsImmunedToSpellEffect(SpellEntry const* spellInfo, uint32 index) con
{
SpellImmuneList const& mechanicList = m_spellImmune[IMMUNITY_MECHANIC];
for (SpellImmuneList::const_iterator itr = mechanicList.begin(); itr != mechanicList.end(); ++itr)
- if(itr->type & 1<<(spellInfo->EffectMechanic[index]))
+ if(itr->type == spellInfo->EffectMechanic[index])
return true;
}
@@ -9457,21 +9539,7 @@ void Unit::Mount(uint32 mount)
// unsummon pet
if(GetTypeId() == TYPEID_PLAYER)
- {
- Pet* pet = ((Player*)this)->GetPet();
- if(pet)
- {
- if(pet->isControlled())
- {
- ((Player*)this)->SetTemporaryUnsummonedPetNumber(pet->GetCharmInfo()->GetPetNumber());
- ((Player*)this)->SetOldPetSpell(pet->GetUInt32Value(UNIT_CREATED_BY_SPELL));
- }
-
- ((Player*)this)->RemovePet(NULL,PET_SAVE_NOT_IN_SLOT);
- }
- else
- ((Player*)this)->SetTemporaryUnsummonedPetNumber(0);
- }
+ ((Player*)this)->UnsummonPetTemporaryIfAny();
}
void Unit::Unmount()
@@ -9487,14 +9555,8 @@ void Unit::Unmount()
// only resummon old pet if the player is already added to a map
// this prevents adding a pet to a not created map which would otherwise cause a crash
// (it could probably happen when logging in after a previous crash)
- if(GetTypeId() == TYPEID_PLAYER && IsInWorld() && ((Player*)this)->GetTemporaryUnsummonedPetNumber() && isAlive())
- {
- Pet* NewPet = new Pet((Player*)this);
- if(!NewPet->LoadPetFromDB((Player*)this, 0, ((Player*)this)->GetTemporaryUnsummonedPetNumber(), true))
- delete NewPet;
-
- ((Player*)this)->SetTemporaryUnsummonedPetNumber(0);
- }
+ if(GetTypeId() == TYPEID_PLAYER)
+ ((Player*)this)->ResummonPetTemporaryUnSummonedIfAny();
}
void Unit::SetInCombatWith(Unit* enemy)
@@ -9648,7 +9710,7 @@ bool Unit::isAttackableByAOE() const
if(GetTypeId()==TYPEID_PLAYER && ((Player *)this)->isGameMaster())
return false;
- return !isInFlight();
+ return !hasUnitState(UNIT_STAT_UNATTACKABLE);
}
int32 Unit::ModifyHealth(int32 dVal)
@@ -10429,7 +10491,7 @@ void Unit::ModSpellCastTime(SpellEntry const* spellProto, int32 & castTime, Spel
if(Player* modOwner = GetSpellModOwner())
modOwner->ApplySpellMod(spellProto->Id, SPELLMOD_CASTING_TIME, castTime, spell);
- if( !(spellProto->Attributes & (SPELL_ATTR_UNK4|SPELL_ATTR_UNK5)) )
+ if( !(spellProto->Attributes & (SPELL_ATTR_UNK4|SPELL_ATTR_UNK5)) && spellProto->DmgClass == SPELL_DAMAGE_CLASS_MAGIC && spellProto->SpellFamilyName)
castTime = int32( float(castTime) * GetFloatValue(UNIT_MOD_CAST_SPEED));
else
{
@@ -10575,6 +10637,16 @@ Unit* Unit::GetUnit(WorldObject& object, uint64 guid)
return ObjectAccessor::GetUnit(object,guid);
}
+Player* Unit::GetPlayer(uint64 guid)
+{
+ return ObjectAccessor::FindPlayer(guid);
+}
+
+Creature* Unit::GetCreature(WorldObject& object, uint64 guid)
+{
+ return ObjectAccessor::GetCreature(object, guid);
+}
+
bool Unit::isVisibleForInState( Player const* u, bool inVisibleList ) const
{
return u->canSeeOrDetect(this, false, inVisibleList, false);
@@ -10995,9 +11067,22 @@ uint32 Unit::GetCreatePowers( Powers power ) const
return 0;
}
+void Unit::AddToWorld()
+{
+ if(!IsInWorld())
+ {
+ WorldObject::AddToWorld();
+ m_Notified = false;
+ m_IsInNotifyList = false;
+ SetToNotify();
+ }
+}
+
void Unit::RemoveFromWorld()
{
// cleanup
+ assert(GetGUID());
+
if(IsInWorld())
{
UnsummonAllTotems();
@@ -11015,11 +11100,12 @@ void Unit::RemoveFromWorld()
void Unit::CleanupsBeforeDelete()
{
- assert(m_uint32Values);
+ assert(GetGUID());
//A unit may be in removelist and not in world, but it is still in grid
//and may have some references during delete
RemoveAllAuras();
+ _DeleteAuras();
InterruptNonMeleeSpells(true);
m_Events.KillAllEvents(false); // non-delatable (currently casted spells) will not deleted now but it will deleted at call in Map::RemoveAllObjectsInRemoveList
CombatStop();
@@ -11254,34 +11340,18 @@ bool Unit::isFrozen() const
struct ProcTriggeredData
{
- ProcTriggeredData(SpellProcEventEntry const * _spellProcEvent, AuraEffect* _triggeredByAura)
- : spellProcEvent(_spellProcEvent), triggeredByAura(_triggeredByAura)
- {}
- SpellProcEventEntry const *spellProcEvent;
- AuraEffect* triggeredByAura;
-};
-struct ProcTriggerringAura
-{
- ProcTriggerringAura(uint32 _spellId, uint64 _casterGUID) : spellId(_spellId), casterGUID(_casterGUID)
+ ProcTriggeredData(Aura* _aura)
+ : aura(_aura)
{
- triggeringAura[0]=NULL;
- triggeringAura[1]=NULL;
- triggeringAura[2]=NULL;
- }
- ProcTriggeredData * triggeringAura[3];
- uint32 spellId;
- uint64 casterGUID;
- ~ProcTriggerringAura()
- {
- for (uint8 i = 0;i<3;++i)
- if (triggeringAura[i])
- delete triggeringAura[i];
+ effMask = 0;
+ spellProcEvent = NULL;
}
+ SpellProcEventEntry const *spellProcEvent;
+ Aura * aura;
+ uint32 effMask;
};
-//typedef std::list< ProcTriggeredData > ProcTriggeredList;
-typedef std::list< ProcTriggerringAura > ProcTriggeredList;
-typedef std::list< uint32> RemoveSpellList;
+typedef std::list< ProcTriggeredData > ProcTriggeredList;
// List of auras that CAN be trigger but may not exist in spell_proc_event
// in most case need for drop charges
@@ -11324,6 +11394,7 @@ bool InitTriggerAuraData()
isTriggerAura[SPELL_AURA_RAID_PROC_FROM_CHARGE_WITH_VALUE] = true;
isTriggerAura[SPELL_AURA_PROC_TRIGGER_SPELL_WITH_VALUE] = true;
isTriggerAura[SPELL_AURA_MOD_DAMAGE_FROM_CASTER] = true;
+ isTriggerAura[SPELL_AURA_ABILITY_IGNORE_AURASTATE] = true;
isNonTriggerAura[SPELL_AURA_MOD_POWER_REGEN]=true;
isNonTriggerAura[SPELL_AURA_REDUCE_PUSHBACK]=true;
@@ -11437,69 +11508,60 @@ void Unit::ProcDamageAndSpellFor( bool isVictim, Unit * pTarget, uint32 procFlag
}
}
- RemoveSpellList removedSpells;
ProcTriggeredList procTriggered;
// Fill procTriggered list
for(AuraMap::const_iterator itr = GetAuras().begin(); itr!= GetAuras().end(); ++itr)
{
- bool first = true;
- ProcTriggeredList::iterator aurItr;
+ ProcTriggeredData triggerData(itr->second);
+
+ if(!IsTriggeredAtSpellProcEvent(pTarget, triggerData.aura, procSpell, procFlag, procExtra, attType, isVictim, (damage > 0), triggerData.spellProcEvent))
+ continue;
+
for (uint8 i=0; i<MAX_SPELL_EFFECTS;++i)
{
if (AuraEffect * aurEff = itr->second->GetPartAura(i))
{
- SpellProcEventEntry const* spellProcEvent = NULL;
- if(!IsTriggeredAtSpellProcEvent(pTarget, aurEff, procSpell, procFlag, procExtra, attType, isVictim, (damage > 0), spellProcEvent))
+ // Skip this auras
+ if (isNonTriggerAura[aurEff->GetAuraName()])
continue;
- if (first)
- {
- first = false;
- ProcTriggerringAura procAur(itr->second->GetId(), itr->second->GetCasterGUID());
- procTriggered.push_front(procAur);
- aurItr = procTriggered.begin();
- }
- aurItr->triggeringAura[i] = new ProcTriggeredData(spellProcEvent, aurEff);
+ // If not trigger by default and spellProcEvent==NULL - skip
+ if (!isTriggerAura[aurEff->GetAuraName()] && triggerData.spellProcEvent==NULL)
+ continue;
+
+ triggerData.effMask |= 1<<i;
}
}
+ if (triggerData.effMask)
+ procTriggered.push_front(triggerData);
}
// Nothing found
if (procTriggered.empty())
return;
- Aura * parentAura = NULL;
// Handle effects proceed this time
for(ProcTriggeredList::iterator i = procTriggered.begin(); i != procTriggered.end(); ++i)
{
- // look for parent aura in auras list, it may be removed while proc even processing
- parentAura = GetAura(i->spellId, i->casterGUID);
- if (!parentAura)
+ // look for aura in auras list, it may be removed while proc event processing
+ if (!HasAura(i->aura))
continue;
- bool inuse = parentAura->IsInUse();
- if (!inuse)
- parentAura->SetInUse(true);
-
- bool useCharges= parentAura->GetAuraCharges()>0;
+ bool useCharges= i->aura->GetAuraCharges()>0;
bool takeCharges = false;
+ SpellEntry const *spellInfo = i->aura->GetSpellProto();
+ uint32 Id=i->aura->GetId();
- for (uint8 j = 0; j<MAX_SPELL_EFFECTS;++j)
- {
- if (!i->triggeringAura[j])
- continue;
+ // For players set spell cooldown if need
+ uint32 cooldown = 0;
+ if (GetTypeId() == TYPEID_PLAYER && i->spellProcEvent && i->spellProcEvent->cooldown)
+ cooldown = i->spellProcEvent->cooldown;
- // possible for stacked auras from same caster, skip then
- if (parentAura->GetPartAura(j)!=i->triggeringAura[j]->triggeredByAura)
+ for (uint8 effIndex = 0; effIndex<MAX_SPELL_EFFECTS;++effIndex)
+ {
+ if (!(i->effMask & (1<<effIndex)))
continue;
- SpellProcEventEntry const *spellProcEvent = i->triggeringAura[j]->spellProcEvent;
- AuraEffect *triggeredByAura =triggeredByAura = i->triggeringAura[j]->triggeredByAura;
-
- SpellEntry const *spellInfo = triggeredByAura->GetSpellProto();
- uint32 effIndex = triggeredByAura->GetEffIndex();
- // For players set spell cooldown if need
- uint32 cooldown = 0;
- if (GetTypeId() == TYPEID_PLAYER && spellProcEvent && spellProcEvent->cooldown)
- cooldown = spellProcEvent->cooldown;
+ AuraEffect *triggeredByAura = i->aura->GetPartAura(effIndex);
+ assert(triggeredByAura);
switch(triggeredByAura->GetAuraName())
{
@@ -11611,19 +11673,11 @@ void Unit::ProcDamageAndSpellFor( bool isVictim, Unit * pTarget, uint32 procFlag
}
takeCharges=true;
}
- if (!inuse)
- parentAura->SetInUse(false);
-
- if ( !parentAura->GetAuraDuration() && !(parentAura->IsPermanent() || (parentAura->IsPassive())) )
- RemoveAura(parentAura);
- else
+ // Remove charge (aura can be removed by triggers)
+ if(useCharges && takeCharges)
{
- // Remove charge (aura can be removed by triggers)
- if(useCharges && takeCharges)
- {
- if (parentAura->DropAuraCharge())
- RemoveAura(parentAura->GetId(),parentAura->GetCasterGUID());
- }
+ if (i->aura->DropAuraCharge())
+ RemoveAura(i->aura);
}
}
}
@@ -12243,20 +12297,13 @@ Pet* Unit::CreateTamedPetFrom(Creature* creatureTarget,uint32 spell_id)
return pet;
}
-bool Unit::IsTriggeredAtSpellProcEvent(Unit *pVictim, AuraEffect * aura, SpellEntry const* procSpell, uint32 procFlag, uint32 procExtra, WeaponAttackType attType, bool isVictim, bool active, SpellProcEventEntry const*& spellProcEvent )
+bool Unit::IsTriggeredAtSpellProcEvent(Unit *pVictim, Aura * aura, SpellEntry const* procSpell, uint32 procFlag, uint32 procExtra, WeaponAttackType attType, bool isVictim, bool active, SpellProcEventEntry const*& spellProcEvent )
{
SpellEntry const* spellProto = aura->GetSpellProto ();
// Get proc Event Entry
spellProcEvent = spellmgr.GetSpellProcEvent(spellProto->Id);
- // Skip this auras
- if (isNonTriggerAura[aura->GetAuraName()])
- return false;
- // If not trigger by default and spellProcEvent==NULL - skip
- if (!isTriggerAura[aura->GetAuraName()] && spellProcEvent==NULL)
- return false;
-
// Get EventProcFlag
uint32 EventProcFlag;
if (spellProcEvent && spellProcEvent->procFlags) // if exist get custom spellProcEvent->procFlags
@@ -12362,8 +12409,6 @@ bool Unit::HandleAuraRaidProcFromChargeWithValue( AuraEffect* triggeredByAura )
else
radius = GetSpellMaxRangeForTarget(triggeredByAura->GetCaster() ,sSpellRangeStore.LookupEntry(spellProto->rangeIndex));
- //Get max possible jumps for aura to get proper charges amount for target
-
if(Player* caster = ((Player*)triggeredByAura->GetCaster()))
{
caster->ApplySpellMod(spellProto->Id, SPELLMOD_RADIUS, radius,NULL);
@@ -12371,7 +12416,7 @@ bool Unit::HandleAuraRaidProcFromChargeWithValue( AuraEffect* triggeredByAura )
if (Unit* target= GetNextRandomRaidMemberOrPet(radius))
{
CastCustomSpell(target,spellProto->Id,&heal,NULL,NULL,true,NULL,triggeredByAura,caster->GetGUID());
- if (Aura * aur = GetAura(spellProto->Id, caster->GetGUID()))
+ if (Aura * aur = target->GetAura(spellProto->Id, caster->GetGUID()))
aur->SetAuraCharges(jumps);
//bonus must be applied after aura cast on target
@@ -12425,19 +12470,14 @@ bool Unit::HandleAuraRaidProcFromCharge( AuraEffect* triggeredByAura )
else
radius = GetSpellMaxRangeForTarget(triggeredByAura->GetCaster() ,sSpellRangeStore.LookupEntry(spellProto->rangeIndex));
- //Get max possible jumps for aura to get proper charges amount for target
- int32 maxJumps = spellProto->procCharges;
-
if(Player* caster = ((Player*)triggeredByAura->GetCaster()))
{
caster->ApplySpellMod(spellProto->Id, SPELLMOD_RADIUS, radius,NULL);
- caster->ApplySpellMod(spellProto->Id, SPELLMOD_CHARGES, maxJumps, NULL);
-
if (Unit* target= GetNextRandomRaidMemberOrPet(radius))
{
- CastSpell(this, spellProto, true,NULL,triggeredByAura,caster_guid);
- if (Aura * aur = GetAura(spellProto->Id, caster->GetGUID()))
+ CastSpell(target, spellProto, true,NULL,triggeredByAura,caster_guid);
+ if (Aura * aur = target->GetAura(spellProto->Id, caster->GetGUID()))
aur->SetAuraCharges(jumps);
}
}
@@ -12796,7 +12836,7 @@ void Unit::SetCharmedOrPossessedBy(Unit* charmer, bool possess)
if(this == charmer)
return;
- if(isInFlight())
+ if(hasUnitState(UNIT_STAT_UNATTACKABLE))
return;
if(GetTypeId() == TYPEID_PLAYER && ((Player*)this)->GetTransport())
@@ -13107,6 +13147,8 @@ void Unit::GetPartyMember(std::list<Unit*> &TagUnitMap, float radius)
void Unit::HandleAuraEffect(AuraEffect * aureff, bool apply)
{
+ if (aureff->GetParentAura()->IsRemoved())
+ return;
if (apply)
{
m_modAuras[aureff->GetAuraName()].push_back(aureff);
@@ -13145,7 +13187,7 @@ void Unit::AddAura(uint32 spellId, Unit* target)
for(uint32 i = 0; i < 3; ++i)
{
- if(spellInfo->Effect[i] == SPELL_EFFECT_APPLY_AURA)
+ if(spellInfo->Effect[i] == SPELL_EFFECT_APPLY_AURA || IsAreaAuraEffect(spellInfo->Effect[i]))
{
if(target->IsImmunedToSpellEffect(spellInfo, i))
continue;
@@ -13174,6 +13216,8 @@ Aura * Unit::AddAuraEffect(uint32 spellId, uint8 effIndex, Unit* caster)
if (aur)
{
AuraEffect *aurEffect = CreateAuraEffect(aur, effIndex, NULL, caster);
+ if (!aurEffect)
+ return aur;
if (!aur->SetPartAura(aurEffect, effIndex))
delete aurEffect;
}
@@ -13259,6 +13303,61 @@ void Unit::SetPhaseMask(uint32 newPhaseMask, bool update)
summon->SetPhaseMask(newPhaseMask,true);
}
+void Unit::KnockbackFrom(float x, float y, float speedXY, float speedZ)
+{
+ if(GetTypeId() == TYPEID_UNIT)
+ {
+ GetMotionMaster()->MoveKnockbackFrom(x, y, speedXY, speedZ);
+ }
+ else
+ {
+ float vcos, vsin;
+ GetSinCos(x, y, vsin, vcos);
+
+ WorldPacket data(SMSG_MOVE_KNOCK_BACK, (8+4+4+4+4+4));
+ data.append(GetPackGUID());
+ data << uint32(0); // Sequence
+ data << float(vcos); // x direction
+ data << float(vsin); // y direction
+ data << float(speedXY); // Horizontal speed
+ data << float(-speedZ); // Z Movement speed (vertical)
+
+ ((Player*)this)->GetSession()->SendPacket(&data);
+ }
+}
+
+void Unit::JumpTo(float speedXY, float speedZ, bool forward)
+{
+ float angle = forward ? 0 : M_PI;
+ if(GetTypeId() == TYPEID_UNIT)
+ {
+ GetMotionMaster()->MoveJumpTo(angle, speedXY, speedZ);
+ }
+ else
+ {
+ float vcos = cos(angle+GetOrientation());
+ float vsin = sin(angle+GetOrientation());
+
+ WorldPacket data(SMSG_MOVE_KNOCK_BACK, (8+4+4+4+4+4));
+ data.append(GetPackGUID());
+ data << uint32(0); // Sequence
+ data << float(vcos); // x direction
+ data << float(vsin); // y direction
+ data << float(speedXY); // Horizontal speed
+ data << float(-speedZ); // Z Movement speed (vertical)
+
+ ((Player*)this)->GetSession()->SendPacket(&data);
+ }
+}
+
+void Unit::JumpTo(WorldObject *obj, float speedZ)
+{
+ float x, y, z;
+ obj->GetContactPoint(this, x, y, z);
+ float speedXY = GetExactDistance2d(x, y) * 10.0f / speedZ;
+ GetMotionMaster()->MoveJump(x, y, z, speedXY, speedZ);
+}
+
void Unit::NearTeleportTo( float x, float y, float z, float orientation, bool casting /*= false*/ )
{
if(GetTypeId() == TYPEID_PLAYER)
diff --git a/src/game/Unit.h b/src/game/Unit.h
index 2ab00f23407..17e5abb10a0 100644
--- a/src/game/Unit.h
+++ b/src/game/Unit.h
@@ -59,9 +59,9 @@ enum SpellChannelInterruptFlags
enum SpellAuraInterruptFlags
{
- AURA_INTERRUPT_FLAG_HITBYSPELL = 0x00000001, // 0 removed when getting hit by a negative spell?
+ AURA_INTERRUPT_FLAG_ANY_CAST = 0x00000001, // 0 removed by any cast
AURA_INTERRUPT_FLAG_DAMAGE = 0x00000002, // 1 removed by any damage
- AURA_INTERRUPT_FLAG_CC = 0x00000004, // 2 crowd control
+ AURA_INTERRUPT_FLAG_HITBYSPELL = 0x00000004, // 2 removed when getting hit by a negative spell? aoe damage?
AURA_INTERRUPT_FLAG_MOVE = 0x00000008, // 3 removed by any movement
AURA_INTERRUPT_FLAG_TURNING = 0x00000010, // 4 removed by any turning
AURA_INTERRUPT_FLAG_JUMP = 0x00000020, // 5 removed by entering combat
@@ -71,8 +71,8 @@ enum SpellAuraInterruptFlags
AURA_INTERRUPT_FLAG_NOT_SHEATHED = 0x00000200, // 9 removed by unsheathing
AURA_INTERRUPT_FLAG_TALK = 0x00000400, // 10 talk to npc / loot? action on creature
AURA_INTERRUPT_FLAG_USE = 0x00000800, // 11 mine/use/open action on gameobject
- AURA_INTERRUPT_FLAG_ATTACK = 0x00001000, // 12 removed by attacking
- AURA_INTERRUPT_FLAG_CAST = 0x00002000, // 13 ???
+ AURA_INTERRUPT_FLAG_ATTACK = 0x00001000, // 12 removed by attacking (negative spell cast?)
+ AURA_INTERRUPT_FLAG_CAST = 0x00002000, // 13 cast stealth breaking spell
AURA_INTERRUPT_FLAG_UNK14 = 0x00004000, // 14
AURA_INTERRUPT_FLAG_TRANSFORM = 0x00008000, // 15 removed by transform?
AURA_INTERRUPT_FLAG_UNK16 = 0x00010000, // 16
@@ -295,6 +295,7 @@ class Pet;
class Path;
class PetAura;
class Guardian;
+class UnitAI;
struct SpellImmune
{
@@ -328,7 +329,6 @@ enum DamageTypeToSchool
enum AuraRemoveMode
{
- AURA_NO_REMOVE_MODE = 0,
AURA_REMOVE_BY_DEFAULT,
AURA_REMOVE_BY_STACK, // change stack, single aura remove,
AURA_REMOVE_BY_CANCEL,
@@ -422,6 +422,8 @@ enum UnitState
UNIT_STAT_POSSESSED = 0x00010000,
UNIT_STAT_CHARGING = 0x00020000,
UNIT_STAT_JUMPING = 0x00040000,
+ UNIT_STAT_ONVEHICLE = 0x00080000,
+ UNIT_STAT_UNATTACKABLE = (UNIT_STAT_IN_FLIGHT | UNIT_STAT_ONVEHICLE),
UNIT_STAT_MOVING = (UNIT_STAT_ROAMING | UNIT_STAT_CHASE),
UNIT_STAT_CONTROLLED = (UNIT_STAT_CONFUSED | UNIT_STAT_STUNNED | UNIT_STAT_FLEEING),
UNIT_STAT_LOST_CONTROL = (UNIT_STAT_CONTROLLED | UNIT_STAT_JUMPING | UNIT_STAT_CHARGING),
@@ -857,6 +859,7 @@ class TRINITY_DLL_SPEC Unit : public WorldObject
virtual ~Unit ( );
+ void AddToWorld();
void RemoveFromWorld();
void CleanupsBeforeDelete(); // used in ~Creature/~Player (or before mass creature delete to remove cross-references to already deleted units)
@@ -1142,6 +1145,10 @@ class TRINITY_DLL_SPEC Unit : public WorldObject
void NearTeleportTo(float x, float y, float z, float orientation, bool casting = false);
+ void KnockbackFrom(float x, float y, float speedXY, float speedZ);
+ void JumpTo(float speedXY, float speedZ, bool forward = true);
+ void JumpTo(WorldObject *obj, float speedZ);
+
void SendMonsterStop();
void SendMonsterMove(float NewPosX, float NewPosY, float NewPosZ, uint32 Time, Player* player = NULL);
void SendMonsterMove(float NewPosX, float NewPosY, float NewPosZ, uint32 MoveFlags, uint32 time, float speedZ, Player *player = NULL);
@@ -1150,8 +1157,6 @@ class TRINITY_DLL_SPEC Unit : public WorldObject
void SendMonsterMoveWithSpeed(float x, float y, float z, uint32 transitTime = 0, Player* player = NULL);
void SendMonsterMoveWithSpeedToCurrentDestination(Player* player = NULL);
- virtual void MoveOutOfRange(Player &) { };
-
bool isAlive() const { return (m_deathState == ALIVE); };
bool isDead() const { return ( m_deathState == DEAD || m_deathState == CORPSE ); };
DeathState getDeathState() { return m_deathState; };
@@ -1395,6 +1400,7 @@ class TRINITY_DLL_SPEC Unit : public WorldObject
AuraEffect* GetAura(AuraType type, uint32 family, uint32 familyFlag1 , uint32 familyFlag2=0, uint32 familyFlag3=0, uint64 casterGUID=0);
bool HasAuraEffect(uint32 spellId, uint8 effIndex, uint64 caster = 0) const;
bool HasAura(uint32 spellId, uint64 caster = 0) const;
+ bool HasAura(Aura * aur) const;
bool HasAuraType(AuraType auraType) const;
bool HasAuraTypeWithMiscvalue(AuraType auratype, uint32 miscvalue) const;
@@ -1491,6 +1497,8 @@ class TRINITY_DLL_SPEC Unit : public WorldObject
void addFollower(FollowerReference* pRef) { m_FollowingRefManager.insertFirst(pRef); }
void removeFollower(FollowerReference* /*pRef*/ ) { /* nothing to do yet */ }
static Unit* GetUnit(WorldObject& object, uint64 guid);
+ static Player* GetPlayer(uint64 guid);
+ static Creature* GetCreature(WorldObject& object, uint64 guid);
MotionMaster* GetMotionMaster() { return &i_motionMaster; }
@@ -1555,6 +1563,7 @@ class TRINITY_DLL_SPEC Unit : public WorldObject
UnitAI *i_AI, *i_disabledAI;
void _UpdateSpells(uint32 time);
+ void _DeleteAuras();
void _UpdateAutoRepeatSpell();
bool m_AutoRepeatFirstCast;
@@ -1576,12 +1585,12 @@ class TRINITY_DLL_SPEC Unit : public WorldObject
std::list<GameObject*> m_gameObj;
bool m_isSorted;
uint32 m_transform;
- uint32 m_removedAuras;
AuraEffectList m_modAuras[TOTAL_AURAS];
AuraList m_scAuras; // casted singlecast auras
AuraList m_interruptableAuras;
AuraList m_ccAuras;
+ AuraList m_removedAuras;
uint32 m_interruptMask;
float m_auraModifiersGroup[UNIT_MOD_END][MODIFIER_TYPE_END];
@@ -1609,7 +1618,7 @@ class TRINITY_DLL_SPEC Unit : public WorldObject
void SendAttackStop(Unit* victim); // only from AttackStop(Unit*)
//void SendAttackStart(Unit* pVictim); // only from Unit::AttackStart(Unit*)
- bool IsTriggeredAtSpellProcEvent(Unit *pVictim, AuraEffect* aura, SpellEntry const* procSpell, uint32 procFlag, uint32 procExtra, WeaponAttackType attType, bool isVictim, bool active, SpellProcEventEntry const*& spellProcEvent );
+ bool IsTriggeredAtSpellProcEvent(Unit *pVictim, Aura* aura, SpellEntry const* procSpell, uint32 procFlag, uint32 procExtra, WeaponAttackType attType, bool isVictim, bool active, SpellProcEventEntry const*& spellProcEvent );
bool HandleDummyAuraProc( Unit *pVictim, uint32 damage, AuraEffect* triggeredByAura, SpellEntry const *procSpell, uint32 procFlag, uint32 procEx, uint32 cooldown);
bool HandleObsModEnergyAuraProc( Unit *pVictim, uint32 damage, AuraEffect* triggeredByAura, SpellEntry const *procSpell, uint32 procFlag, uint32 procEx, uint32 cooldown);
bool HandleHasteAuraProc( Unit *pVictim, uint32 damage, AuraEffect* triggeredByAura, SpellEntry const *procSpell, uint32 procFlag, uint32 procEx, uint32 cooldown);
@@ -1642,5 +1651,20 @@ class TRINITY_DLL_SPEC Unit : public WorldObject
uint32 m_reducedThreatPercent;
uint64 m_misdirectionTargetGUID;
};
+
+namespace Trinity
+{
+ template<class T>
+ void RandomResizeList(std::list<T> &_list, uint32 _size)
+ {
+ while(_list.size() > _size)
+ {
+ typename std::list<T>::iterator itr = _list.begin();
+ advance(itr, urand(0, _list.size() - 1));
+ _list.erase(itr);
+ }
+ }
+}
+
#endif
diff --git a/src/game/World.cpp b/src/game/World.cpp
index 9105e6a8eb8..d9a22a4a4a2 100644
--- a/src/game/World.cpp
+++ b/src/game/World.cpp
@@ -40,6 +40,7 @@
#include "AchievementMgr.h"
#include "AuctionHouseMgr.h"
#include "ObjectMgr.h"
+#include "CreatureEventAIMgr.h"
#include "SpellMgr.h"
#include "Chat.h"
#include "DBCStores.h"
@@ -736,7 +737,7 @@ void World::LoadConfigSettings(bool reload)
{
sLog.outError("StartHonorPoints (%i) must be in range 0..MaxHonorPoints(%u). Set to %u.",
m_configs[CONFIG_START_HONOR_POINTS],m_configs[CONFIG_MAX_HONOR_POINTS],0);
- m_configs[CONFIG_MAX_HONOR_POINTS] = 0;
+ m_configs[CONFIG_START_HONOR_POINTS] = 0;
}
else if(m_configs[CONFIG_START_HONOR_POINTS] > m_configs[CONFIG_MAX_HONOR_POINTS])
{
@@ -1371,6 +1372,7 @@ void World::SetInitialWorldSettings()
sLog.outString();
achievementmgr.LoadAchievementReferenceList();
achievementmgr.LoadAchievementCriteriaList();
+ achievementmgr.LoadAchievementCriteriaData();
achievementmgr.LoadRewards();
achievementmgr.LoadRewardLocales();
achievementmgr.LoadCompletedAchievements();
@@ -1447,6 +1449,15 @@ void World::SetInitialWorldSettings()
sLog.outString( "Loading Scripts text locales..." ); // must be after Load*Scripts calls
objmgr.LoadDbScriptStrings();
+ sLog.outString( "Loading CreatureEventAI Texts...");
+ CreatureEAI_Mgr.LoadCreatureEventAI_Texts();
+
+ sLog.outString( "Loading CreatureEventAI Summons...");
+ CreatureEAI_Mgr.LoadCreatureEventAI_Summons();
+
+ sLog.outString( "Loading CreatureEventAI Scripts...");
+ CreatureEAI_Mgr.LoadCreatureEventAI_Scripts();
+
sLog.outString( "Initializing Scripts..." );
if(!LoadScriptingModule())
exit(1);
@@ -3190,14 +3201,20 @@ void World::UpdateMaxSessionCounters()
void World::LoadDBVersion()
{
QueryResult* result = WorldDatabase.Query("SELECT db_version FROM version LIMIT 1");
+ //QueryResult* result = WorldDatabase.Query("SELECT version, creature_ai_version FROM db_version LIMIT 1");
if(result)
{
Field* fields = result->Fetch();
- m_DBVersion = fields[0].GetString();
+ m_DBVersion = fields[0].GetCppString();
+ //m_CreatureEventAIVersion = fields[1].GetCppString();
delete result;
}
- else
- m_DBVersion = "unknown world database";
+
+ if(m_DBVersion.empty())
+ m_DBVersion = "Unknown world database.";
+
+ if(m_CreatureEventAIVersion.empty())
+ m_CreatureEventAIVersion = "Unknown creature EventAI.";
}
diff --git a/src/game/World.h b/src/game/World.h
index 2f261467a6c..27075885368 100644
--- a/src/game/World.h
+++ b/src/game/World.h
@@ -560,6 +560,7 @@ class World
//used World DB version
void LoadDBVersion();
char const* GetDBVersion() { return m_DBVersion.c_str(); }
+ char const* GetCreatureEventAIVersion() { return m_CreatureEventAIVersion.c_str(); }
//used Script version
void SetScriptsVersion(char const* version) { m_ScriptsVersion = version ? version : "unknown scripting library"; }
@@ -640,6 +641,7 @@ class World
//used versions
std::string m_DBVersion;
+ std::string m_CreatureEventAIVersion;
std::string m_ScriptsVersion;
};
diff --git a/src/game/WorldSession.cpp b/src/game/WorldSession.cpp
index 01bda647fa4..da6837b1662 100644
--- a/src/game/WorldSession.cpp
+++ b/src/game/WorldSession.cpp
@@ -240,7 +240,7 @@ bool WorldSession::Update(uint32 /*diff*/)
void WorldSession::LogoutPlayer(bool Save)
{
// finish pending transfers before starting the logout
- while(_player && _player->IsBeingTeleported())
+ while(_player && _player->IsBeingTeleportedFar())
HandleMoveWorldportAckOpcode();
m_playerLogout = true;